[nautilus-actions: 17/45] New NAIDuplicable and NactIMenubar interfaces for the new UI
- From: Pierre Wieser <pwieser src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [nautilus-actions: 17/45] New NAIDuplicable and NactIMenubar interfaces for the new UI
- Date: Wed, 29 Jul 2009 21:19:12 +0000 (UTC)
commit f6d0a9dde0d24306b965441f65f91983846c3bec
Author: Pierre Wieser <pwieser trychlos org>
Date: Sat Jul 25 21:36:52 2009 +0200
New NAIDuplicable and NactIMenubar interfaces for the new UI
ChangeLog | 18 +
src/Makefile.am | 2 +-
src/common/Makefile.am | 8 +-
.../{na-ipivot-container.h => na-action-class.h} | 49 +-
...pivot-container.h => na-action-profile-class.h} | 49 +-
src/common/na-action-profile.c | 1011 ++++++++++++--------
src/common/na-action-profile.h | 69 +-
src/common/na-action.c | 849 ++++++++++-------
src/common/na-action.h | 111 +--
src/common/na-gconf.c | 918 +++++++++++++-----
src/common/na-gconf.h | 9 +-
src/common/na-iduplicable.c | 422 ++++++++
src/common/na-iduplicable.h | 129 +++
src/common/na-iio-provider.c | 166 ++--
src/common/na-iio-provider.h | 94 ++-
...{na-ipivot-container.c => na-ipivot-consumer.c} | 46 +-
src/common/na-ipivot-consumer.h | 82 ++
src/common/na-object.c | 490 +++++++++-
src/common/na-object.h | 124 +++-
src/common/na-pivot.c | 346 +++++--
src/common/na-pivot.h | 69 ++-
src/common/na-utils.c | 2 +-
src/nact/Makefile.am | 2 +
src/nact/nact-application.c | 10 +-
src/nact/nact-application.h | 4 +-
src/nact/nact-assist-import.c | 2 +-
src/nact/nact-gconf-reader.c | 8 +-
src/nact/nact-iaction-tab.c | 115 +++-
src/nact/nact-iaction-tab.h | 8 +-
src/nact/nact-iactions-list.c | 443 ++++++++--
src/nact/nact-iactions-list.h | 16 +-
src/nact/nact-icommand-tab.c | 83 ++-
src/nact/nact-icommand-tab.h | 1 +
src/nact/nact-iconditions-tab.h | 2 +-
src/nact/nact-imenubar.c | 936 ++++++++++++++++++
src/nact/nact-imenubar.h | 85 ++
src/nact/nact-main-window.c | 624 ++++++-------
src/nact/nact-window.c | 41 +-
src/nact/nact-window.h | 6 +-
src/plugin/nautilus-actions.c | 36 +-
40 files changed, 5577 insertions(+), 1908 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 7148198..099d1dd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2009-07-25 Pierre Wieser <pwieser trychlos org>
+
+ * src/common/na-action-class.h:
+ * src/common/na-action-profile-class.h:
+ New files to properly handle forward declarations.
+
+ * src/common/na-ipivot-container.c:
+ * src/common/na-ipivot-container.h:
+ Renamed as na-ipivot-consumer.{c,h}.
+
+ * src/common/na-iduplicable.c:
+ * src/common/na-iduplicable.h:
+ New NAIDuplicable interface implemented by NAObject class.
+
+ * src/nact/nact-imenubar.c:
+ * src/nact/nact-imenubar.h:
+ New NactIMenubar interface implemented by NactMainWindow class.
+
2009-07-19 Pierre Wieser <pwieser trychlos org>
* src/nact/nact-action-conditions-editor.c:
diff --git a/src/Makefile.am b/src/Makefile.am
index f86e2a2..75ebe69 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,6 +29,6 @@
SUBDIRS = \
common \
nact \
- $(OPTIONAL_SUBDIR) \
plugin \
+ $(OPTIONAL_SUBDIR) \
$(NULL)
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index b07e308..868da5d 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -37,15 +37,19 @@ AM_CPPFLAGS += \
libnact_la_SOURCES = \
na-action.c \
na-action.h \
+ na-action-class.h \
na-action-profile.c \
na-action-profile.h \
+ na-action-profile-class.h \
na-gconf.c \
na-gconf.h \
na-gconf-keys.h \
+ na-iduplicable.c \
+ na-iduplicable.h \
na-iio-provider.c \
na-iio-provider.h \
- na-ipivot-container.c \
- na-ipivot-container.h \
+ na-ipivot-consumer.c \
+ na-ipivot-consumer.h \
na-object.c \
na-object.h \
na-pivot.c \
diff --git a/src/common/na-ipivot-container.h b/src/common/na-action-class.h
similarity index 50%
copy from src/common/na-ipivot-container.h
copy to src/common/na-action-class.h
index 308efe9..a734f5b 100644
--- a/src/common/na-ipivot-container.h
+++ b/src/common/na-action-class.h
@@ -28,43 +28,42 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_IPIVOT_CONTAINER_H__
-#define __NA_IPIVOT_CONTAINER_H__
+#ifndef __NA_ACTION_CLASS_H__
+#define __NA_ACTION_CLASS_H__
-/*
- * NAIPivotContainer interface definition.
- *
- * This interface should be implemented by all classes which embed a
- * NAPivot object, in order to receive modification notification
- * messages.
+/**
+ * SECTION: na_action
*/
-#include <glib-object.h>
+#include "na-object.h"
G_BEGIN_DECLS
-#define NA_IPIVOT_CONTAINER_TYPE ( na_ipivot_container_get_type())
-#define NA_IPIVOT_CONTAINER( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_IPIVOT_CONTAINER_TYPE, NAIPivotContainer ))
-#define NA_IS_IPIVOT_CONTAINER( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_IPIVOT_CONTAINER_TYPE ))
-#define NA_IPIVOT_CONTAINER_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NA_IPIVOT_CONTAINER_TYPE, NAIPivotContainerInterface ))
+#define NA_ACTION_TYPE ( na_action_get_type())
+#define NA_ACTION( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_ACTION_TYPE, NAAction ))
+#define NA_ACTION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_ACTION_TYPE, NAActionClass ))
+#define NA_IS_ACTION( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_ACTION_TYPE ))
+#define NA_IS_ACTION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_ACTION_TYPE ))
+#define NA_ACTION_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_ACTION_TYPE, NAActionClass ))
-typedef struct NAIPivotContainer NAIPivotContainer;
-
-typedef struct NAIPivotContainerInterfacePrivate NAIPivotContainerInterfacePrivate;
+typedef struct NAActionPrivate NAActionPrivate;
typedef struct {
- GTypeInterface parent;
- NAIPivotContainerInterfacePrivate *private;
-
- /* api */
- void ( *on_actions_changed )( NAIPivotContainer *instance, gpointer user_data );
+ NAObject parent;
+ NAActionPrivate *private;
}
- NAIPivotContainerInterface;
+ NAAction;
-GType na_ipivot_container_get_type( void );
+typedef struct NAActionClassPrivate NAActionClassPrivate;
+
+typedef struct {
+ NAObjectClass parent;
+ NAActionClassPrivate *private;
+}
+ NAActionClass;
-void na_ipivot_container_notify( NAIPivotContainer *instance );
+GType na_action_get_type( void );
G_END_DECLS
-#endif /* __NA_IPIVOT_CONTAINER_H__ */
+#endif /* __NA_ACTION_CLASS_H__ */
diff --git a/src/common/na-ipivot-container.h b/src/common/na-action-profile-class.h
similarity index 50%
rename from src/common/na-ipivot-container.h
rename to src/common/na-action-profile-class.h
index 308efe9..5f8eaa7 100644
--- a/src/common/na-ipivot-container.h
+++ b/src/common/na-action-profile-class.h
@@ -28,43 +28,42 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_IPIVOT_CONTAINER_H__
-#define __NA_IPIVOT_CONTAINER_H__
+#ifndef __NA_ACTION_PROFILE_CLASS_H__
+#define __NA_ACTION_PROFILE_CLASS_H__
-/*
- * NAIPivotContainer interface definition.
- *
- * This interface should be implemented by all classes which embed a
- * NAPivot object, in order to receive modification notification
- * messages.
+/**
+ * SECTION: na_action_profile
*/
-#include <glib-object.h>
+#include "na-object.h"
G_BEGIN_DECLS
-#define NA_IPIVOT_CONTAINER_TYPE ( na_ipivot_container_get_type())
-#define NA_IPIVOT_CONTAINER( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_IPIVOT_CONTAINER_TYPE, NAIPivotContainer ))
-#define NA_IS_IPIVOT_CONTAINER( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_IPIVOT_CONTAINER_TYPE ))
-#define NA_IPIVOT_CONTAINER_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NA_IPIVOT_CONTAINER_TYPE, NAIPivotContainerInterface ))
+#define NA_ACTION_PROFILE_TYPE ( na_action_profile_get_type())
+#define NA_ACTION_PROFILE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_ACTION_PROFILE_TYPE, NAActionProfile ))
+#define NA_ACTION_PROFILE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_ACTION_PROFILE_TYPE, NAActionProfileClass ))
+#define NA_IS_ACTION_PROFILE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_ACTION_PROFILE_TYPE ))
+#define NA_IS_ACTION_PROFILE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_ACTION_PROFILE_TYPE ))
+#define NA_ACTION_PROFILE_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_ACTION_PROFILE_TYPE, NAActionProfileClass ))
-typedef struct NAIPivotContainer NAIPivotContainer;
-
-typedef struct NAIPivotContainerInterfacePrivate NAIPivotContainerInterfacePrivate;
+typedef struct NAActionProfilePrivate NAActionProfilePrivate;
typedef struct {
- GTypeInterface parent;
- NAIPivotContainerInterfacePrivate *private;
-
- /* api */
- void ( *on_actions_changed )( NAIPivotContainer *instance, gpointer user_data );
+ NAObject parent;
+ NAActionProfilePrivate *private;
}
- NAIPivotContainerInterface;
+ NAActionProfile;
-GType na_ipivot_container_get_type( void );
+typedef struct NAActionProfileClassPrivate NAActionProfileClassPrivate;
+
+typedef struct {
+ NAObjectClass parent;
+ NAActionProfileClassPrivate *private;
+}
+ NAActionProfileClass;
-void na_ipivot_container_notify( NAIPivotContainer *instance );
+GType na_action_profile_get_type( void );
G_END_DECLS
-#endif /* __NA_IPIVOT_CONTAINER_H__ */
+#endif /* __NA_ACTION_PROFILE_CLASS_H__ */
diff --git a/src/common/na-action-profile.c b/src/common/na-action-profile.c
index a931a9d..ffa233c 100644
--- a/src/common/na-action-profile.c
+++ b/src/common/na-action-profile.c
@@ -53,57 +53,69 @@ struct NAActionProfilePrivate {
/* the NAAction object
*/
- gpointer action;
+ NAAction *action;
/* profile properties
*/
- gchar *name;
- gchar *label;
gchar *path;
gchar *parameters;
GSList *basenames;
gboolean match_case;
- gboolean is_dir;
- gboolean is_file;
- gboolean accept_multiple_files;
GSList *mimetypes;
+ gboolean is_file;
+ gboolean is_dir;
+ gboolean accept_multiple;
GSList *schemes;
};
-/* instance properties
- * please note that property names must have the same spelling as the
- * NactIIOProvider parameters
+/* profile properties
*/
enum {
- PROP_PROFILE_ACTION = 1,
- PROP_PROFILE_NAME,
- PROP_PROFILE_LABEL,
- PROP_PROFILE_PATH,
- PROP_PROFILE_PARAMETERS,
- PROP_PROFILE_ACCEPT_MULTIPLE,
- PROP_PROFILE_BASENAMES,
- PROP_PROFILE_ISDIR,
- PROP_PROFILE_ISFILE,
- PROP_PROFILE_MATCHCASE,
- PROP_PROFILE_MIMETYPES,
- PROP_PROFILE_SCHEMES
+ PROP_NAPROFILE_ACTION = 1,
+ PROP_NAPROFILE_NAME,
+ PROP_NAPROFILE_LABEL,
+ PROP_NAPROFILE_PATH,
+ PROP_NAPROFILE_PARAMETERS,
+ PROP_NAPROFILE_BASENAMES,
+ PROP_NAPROFILE_MATCHCASE,
+ PROP_NAPROFILE_MIMETYPES,
+ PROP_NAPROFILE_ISFILE,
+ PROP_NAPROFILE_ISDIR,
+ PROP_NAPROFILE_ACCEPT_MULTIPLE,
+ PROP_NAPROFILE_SCHEMES
};
+#define PROP_NAPROFILE_ACTION_STR "na-profile-action"
+#define PROP_NAPROFILE_NAME_STR "na-profile-name"
+#define PROP_NAPROFILE_LABEL_STR "na-profile-desc-name"
+#define PROP_NAPROFILE_PATH_STR "na-profile-path"
+#define PROP_NAPROFILE_PARAMETERS_STR "na-profile-parameters"
+#define PROP_NAPROFILE_BASENAMES_STR "na-profile-basenames"
+#define PROP_NAPROFILE_MATCHCASE_STR "na-profile-matchcase"
+#define PROP_NAPROFILE_MIMETYPES_STR "na-profile-mimetypes"
+#define PROP_NAPROFILE_ISFILE_STR "na-profile-isfile"
+#define PROP_NAPROFILE_ISDIR_STR "na-profile-isdir"
+#define PROP_NAPROFILE_ACCEPT_MULTIPLE_STR "na-profile-accept-multiple"
+#define PROP_NAPROFILE_SCHEMES_STR "na-profile-schemes"
+
static NAObjectClass *st_parent_class = NULL;
-static GType register_type( void );
-static void class_init( NAActionProfileClass *klass );
-static void instance_init( GTypeInstance *instance, gpointer klass );
-static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
-static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
-static void instance_dispose( GObject *object );
-static void instance_finalize( GObject *object );
+static GType register_type( void );
+static void class_init( NAActionProfileClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
-static void do_dump( const NAObject *profile );
-static void do_dump_list( const gchar *thisfn, const gchar *label, GSList *list );
-static gchar *do_get_id( const NAObject *object );
-static gchar *do_get_label( const NAObject *object );
-static int validate_schemes( GSList* schemes2test, NautilusFileInfo* file );
+static void object_dump( const NAObject *action );
+static void object_dump_list( const gchar *thisfn, const gchar *label, GSList *list );
+static NAObject *object_duplicate( const NAObject *action );
+static void object_copy( NAObject *target, const NAObject *source );
+static gboolean object_are_equal( const NAObject *a, const NAObject *b );
+static gboolean object_is_valid( const NAObject *action );
+
+static int validate_schemes( GSList* schemes2test, NautilusFileInfo* file );
GType
na_action_profile_get_type( void )
@@ -120,6 +132,9 @@ na_action_profile_get_type( void )
static GType
register_type( void )
{
+ static const gchar *thisfn = "na_action_profile_register_type";
+ g_debug( "%s", thisfn );
+
static GTypeInfo info = {
sizeof( NAActionProfileClass ),
( GBaseInitFunc ) NULL,
@@ -151,102 +166,103 @@ class_init( NAActionProfileClass *klass )
GParamSpec *spec;
spec = g_param_spec_pointer(
- PROP_PROFILE_ACTION_STR,
- PROP_PROFILE_ACTION_STR,
- "The NAAction object",
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_ACTION, spec );
+ PROP_NAPROFILE_ACTION_STR,
+ "NAAction attachment",
+ "The NAAction action to which this profile belongs",
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_ACTION, spec );
- /* the id of the object is marked as G_PARAM_CONSTRUCT_ONLY */
spec = g_param_spec_string(
- PROP_PROFILE_NAME_STR,
- PROP_PROFILE_NAME_STR,
- "Internal profile's name", "",
+ PROP_NAPROFILE_NAME_STR,
+ "Profile name",
+ "Internal profile identifiant (ASCII, case insensitive)", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_NAME, spec );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_NAME, spec );
spec = g_param_spec_string(
- PROP_PROFILE_LABEL_STR,
- PROP_PROFILE_LABEL_STR,
- "Displayable profile's name", "",
+ PROP_NAPROFILE_LABEL_STR,
+ "Profile label",
+ "Displayable profile's label (UTF-8, localizable)", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_LABEL, spec );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_LABEL, spec );
spec = g_param_spec_string(
- PROP_PROFILE_PATH_STR,
- PROP_PROFILE_PATH_STR,
+ PROP_NAPROFILE_PATH_STR,
+ "Command path",
"Command path", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_PATH, spec );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_PATH, spec );
spec = g_param_spec_string(
- PROP_PROFILE_PARAMETERS_STR,
- PROP_PROFILE_PARAMETERS_STR,
+ PROP_NAPROFILE_PARAMETERS_STR,
+ "Command parameters",
"Command parameters", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_PARAMETERS, spec );
-
- spec = g_param_spec_boolean(
- PROP_PROFILE_ACCEPT_MULTIPLE_STR,
- PROP_PROFILE_ACCEPT_MULTIPLE_STR,
- "Whether apply when multiple files may be selected", TRUE,
- G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_ACCEPT_MULTIPLE, spec );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_PARAMETERS, spec );
spec = g_param_spec_pointer(
- PROP_PROFILE_BASENAMES_STR,
- PROP_PROFILE_BASENAMES_STR,
+ PROP_NAPROFILE_BASENAMES_STR,
+ "Filenames mask",
"Filenames mask",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_BASENAMES, spec );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_BASENAMES, spec );
spec = g_param_spec_boolean(
- PROP_PROFILE_ISDIR_STR,
- PROP_PROFILE_ISDIR_STR,
- "Whether apply when a dir is selected", FALSE,
+ PROP_NAPROFILE_MATCHCASE_STR,
+ "Match case",
+ "Whether the filenames are case sensitive", TRUE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_MATCHCASE, spec );
+
+ spec = g_param_spec_pointer(
+ PROP_NAPROFILE_MIMETYPES_STR,
+ "Mimetypes",
+ "List of selectable mimetypes",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_ISDIR, spec );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_MIMETYPES, spec );
spec = g_param_spec_boolean(
- PROP_PROFILE_ISFILE_STR,
- PROP_PROFILE_ISFILE_STR,
- "Whether apply when a file is selected", TRUE,
+ PROP_NAPROFILE_ISFILE_STR,
+ "Only files",
+ "Whether apply when only files are selected", TRUE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_ISFILE, spec );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_ISFILE, spec );
spec = g_param_spec_boolean(
- PROP_PROFILE_MATCHCASE_STR,
- PROP_PROFILE_MATCHCASE_STR,
- "Whether the filenames are case sensitive", TRUE,
+ PROP_NAPROFILE_ISDIR_STR,
+ "Only dirs",
+ "Whether apply when only dirs are selected", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_MATCHCASE, spec );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_ISDIR, spec );
- spec = g_param_spec_pointer(
- PROP_PROFILE_MIMETYPES_STR,
- PROP_PROFILE_MIMETYPES_STR,
- "List of selectable mimetypes",
+ spec = g_param_spec_boolean(
+ PROP_NAPROFILE_ACCEPT_MULTIPLE_STR,
+ "Accept multiple selection",
+ "Whether apply when multiple files or folders are selected", TRUE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_MIMETYPES, spec );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_ACCEPT_MULTIPLE, spec );
spec = g_param_spec_pointer(
- PROP_PROFILE_SCHEMES_STR,
- PROP_PROFILE_SCHEMES_STR,
+ PROP_NAPROFILE_SCHEMES_STR,
+ "Schemes",
"list of selectable schemes",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PROFILE_SCHEMES, spec );
+ g_object_class_install_property( object_class, PROP_NAPROFILE_SCHEMES, spec );
klass->private = g_new0( NAActionProfileClassPrivate, 1 );
- NA_OBJECT_CLASS( klass )->dump = do_dump;
- NA_OBJECT_CLASS( klass )->get_id = do_get_id;
- NA_OBJECT_CLASS( klass )->get_label = do_get_label;
+ NA_OBJECT_CLASS( klass )->dump = object_dump;
+ NA_OBJECT_CLASS( klass )->duplicate = object_duplicate;
+ NA_OBJECT_CLASS( klass )->copy = object_copy;
+ NA_OBJECT_CLASS( klass )->are_equal = object_are_equal;
+ NA_OBJECT_CLASS( klass )->is_valid = object_is_valid;
}
static void
instance_init( GTypeInstance *instance, gpointer klass )
{
- static const gchar *thisfn = "na_action_profile_instance_init";
- g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
+ /*static const gchar *thisfn = "na_action_profile_instance_init";
+ g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );*/
g_assert( NA_IS_ACTION_PROFILE( instance ));
NAActionProfile* self = NA_ACTION_PROFILE( instance );
@@ -257,18 +273,16 @@ instance_init( GTypeInstance *instance, gpointer klass )
/* initialize suitable default values
*/
- /* i18n: default label for the default profile */
- self->private->label = g_strdup( _( "Default profile" ));
self->private->path = g_strdup( "" );
self->private->parameters = g_strdup( "" );
- self->private->accept_multiple_files = FALSE;
self->private->basenames = NULL;
self->private->basenames = g_slist_append( self->private->basenames, g_strdup( "*" ));
- self->private->is_dir = FALSE;
- self->private->is_file = TRUE;
self->private->match_case = TRUE;
self->private->mimetypes = NULL;
self->private->mimetypes = g_slist_append( self->private->mimetypes, g_strdup( "*/*" ));
+ self->private->is_file = TRUE;
+ self->private->is_dir = FALSE;
+ self->private->accept_multiple = FALSE;
self->private->schemes = NULL;
self->private->schemes = g_slist_append( self->private->schemes, g_strdup( "file" ));
}
@@ -282,53 +296,53 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
GSList *list;
switch( property_id ){
- case PROP_PROFILE_ACTION:
+ case PROP_NAPROFILE_ACTION:
g_value_set_pointer( value, self->private->action );
break;
- case PROP_PROFILE_NAME:
- g_value_set_string( value, self->private->name );
+ case PROP_NAPROFILE_NAME:
+ G_OBJECT_CLASS( st_parent_class )->get_property( object, PROP_NAOBJECT_ID, value, spec );
break;
- case PROP_PROFILE_LABEL:
- g_value_set_string( value, self->private->label );
+ case PROP_NAPROFILE_LABEL:
+ G_OBJECT_CLASS( st_parent_class )->get_property( object, PROP_NAOBJECT_LABEL, value, spec );
break;
- case PROP_PROFILE_PATH:
+ case PROP_NAPROFILE_PATH:
g_value_set_string( value, self->private->path );
break;
- case PROP_PROFILE_PARAMETERS:
+ case PROP_NAPROFILE_PARAMETERS:
g_value_set_string( value, self->private->parameters );
break;
- case PROP_PROFILE_ACCEPT_MULTIPLE:
- g_value_set_boolean( value, self->private->accept_multiple_files );
- break;
-
- case PROP_PROFILE_BASENAMES:
+ case PROP_NAPROFILE_BASENAMES:
list = na_utils_duplicate_string_list( self->private->basenames );
g_value_set_pointer( value, list );
break;
- case PROP_PROFILE_ISDIR:
- g_value_set_boolean( value, self->private->is_dir );
+ case PROP_NAPROFILE_MATCHCASE:
+ g_value_set_boolean( value, self->private->match_case );
+ break;
+
+ case PROP_NAPROFILE_MIMETYPES:
+ list = na_utils_duplicate_string_list( self->private->mimetypes );
+ g_value_set_pointer( value, list );
break;
- case PROP_PROFILE_ISFILE:
+ case PROP_NAPROFILE_ISFILE:
g_value_set_boolean( value, self->private->is_file );
break;
- case PROP_PROFILE_MATCHCASE:
- g_value_set_boolean( value, self->private->match_case );
+ case PROP_NAPROFILE_ISDIR:
+ g_value_set_boolean( value, self->private->is_dir );
break;
- case PROP_PROFILE_MIMETYPES:
- list = na_utils_duplicate_string_list( self->private->mimetypes );
- g_value_set_pointer( value, list );
+ case PROP_NAPROFILE_ACCEPT_MULTIPLE:
+ g_value_set_boolean( value, self->private->accept_multiple );
break;
- case PROP_PROFILE_SCHEMES:
+ case PROP_NAPROFILE_SCHEMES:
list = na_utils_duplicate_string_list( self->private->schemes );
g_value_set_pointer( value, list );
break;
@@ -346,57 +360,55 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
NAActionProfile *self = NA_ACTION_PROFILE( object );
switch( property_id ){
- case PROP_PROFILE_ACTION:
+ case PROP_NAPROFILE_ACTION:
self->private->action = g_value_get_pointer( value );
break;
- case PROP_PROFILE_NAME:
- g_free( self->private->name );
- self->private->name = g_value_dup_string( value );
+ case PROP_NAPROFILE_NAME:
+ G_OBJECT_CLASS( st_parent_class )->set_property( object, PROP_NAOBJECT_ID, value, spec );
break;
- case PROP_PROFILE_LABEL:
- g_free( self->private->label );
- self->private->label = g_value_dup_string( value );
+ case PROP_NAPROFILE_LABEL:
+ G_OBJECT_CLASS( st_parent_class )->set_property( object, PROP_NAOBJECT_LABEL, value, spec );
break;
- case PROP_PROFILE_PATH:
+ case PROP_NAPROFILE_PATH:
g_free( self->private->path );
self->private->path = g_value_dup_string( value );
break;
- case PROP_PROFILE_PARAMETERS:
+ case PROP_NAPROFILE_PARAMETERS:
g_free( self->private->parameters );
self->private->parameters = g_value_dup_string( value );
break;
- case PROP_PROFILE_ACCEPT_MULTIPLE:
- self->private->accept_multiple_files = g_value_get_boolean( value );
- break;
-
- case PROP_PROFILE_BASENAMES:
+ case PROP_NAPROFILE_BASENAMES:
na_utils_free_string_list( self->private->basenames );
self->private->basenames = na_utils_duplicate_string_list( g_value_get_pointer( value ));
break;
- case PROP_PROFILE_ISDIR:
- self->private->is_dir = g_value_get_boolean( value );
+ case PROP_NAPROFILE_MATCHCASE:
+ self->private->match_case = g_value_get_boolean( value );
+ break;
+
+ case PROP_NAPROFILE_MIMETYPES:
+ na_utils_free_string_list( self->private->mimetypes );
+ self->private->mimetypes = na_utils_duplicate_string_list( g_value_get_pointer( value ));
break;
- case PROP_PROFILE_ISFILE:
+ case PROP_NAPROFILE_ISFILE:
self->private->is_file = g_value_get_boolean( value );
break;
- case PROP_PROFILE_MATCHCASE:
- self->private->match_case = g_value_get_boolean( value );
+ case PROP_NAPROFILE_ISDIR:
+ self->private->is_dir = g_value_get_boolean( value );
break;
- case PROP_PROFILE_MIMETYPES:
- na_utils_free_string_list( self->private->mimetypes );
- self->private->mimetypes = na_utils_duplicate_string_list( g_value_get_pointer( value ));
+ case PROP_NAPROFILE_ACCEPT_MULTIPLE:
+ self->private->accept_multiple = g_value_get_boolean( value );
break;
- case PROP_PROFILE_SCHEMES:
+ case PROP_NAPROFILE_SCHEMES:
na_utils_free_string_list( self->private->schemes );
self->private->schemes = na_utils_duplicate_string_list( g_value_get_pointer( value ));
break;
@@ -434,8 +446,6 @@ instance_finalize( GObject *object )
g_assert( NA_IS_ACTION_PROFILE( object ));
NAActionProfile *self = ( NAActionProfile * ) object;
- g_free( self->private->name );
- g_free( self->private->label );
g_free( self->private->path );
g_free( self->private->parameters );
na_utils_free_string_list( self->private->basenames );
@@ -451,196 +461,98 @@ instance_finalize( GObject *object )
}
/**
- * Allocates a new profile for an action.
- *
- * @action: the action to which the profile must be attached.
+ * na_action_profile_new:
*
- * @name: the internal name (identifier) of the profile.
+ * Allocates a new profile of the given name.
*
- * Returns the newly allocated NAActionProfile object.
+ * Returns: the newly allocated #NAActionProfile profile.
*/
NAActionProfile *
-na_action_profile_new( const NAObject *action, const gchar *name )
+na_action_profile_new( void )
{
- g_assert( NA_IS_ACTION( action ));
- g_assert( name && strlen( name ));
+ NAActionProfile *profile = g_object_new( NA_ACTION_PROFILE_TYPE, NULL );
- NAActionProfile *profile =
- g_object_new(
- NA_ACTION_PROFILE_TYPE,
- PROP_PROFILE_ACTION_STR, action,
- PROP_PROFILE_NAME_STR, name,
- NULL );
+ na_action_profile_set_name( profile, ACTION_PROFILE_PREFIX "zero" );
+
+ /* i18n: default label for a new profile */
+ na_action_profile_set_label( profile, _( "Default profile" ));
return( profile );
}
/**
- * Duplicates a profile.
+ * na_action_profile_get_action:
+ * @profile: the #NAActionProfile to be requested.
*
- * @profile: the profile to be duplicated.
+ * Returns a pointer to the action to which this profile is attached,
+ * or NULL if the profile has never been attached.
*
- * Returns the newly allocated NAActionProfile object.
+ * Returns: a #NAAction pointer.
*
- * Note the duplicated profile has the same internal name (identifier)
- * as the initial one, and thus cannot be attached to the same action.
+ * Note that the returned #NAAction pointer is owned by the profile.
+ * The caller should not try to g_free() nor g_object_unref() it.
*/
-NAActionProfile *
-na_action_profile_duplicate( const NAAction *action, const NAActionProfile *profile )
+NAAction *
+na_action_profile_get_action( const NAActionProfile *profile )
{
g_assert( NA_IS_ACTION_PROFILE( profile ));
- NAActionProfile *new =
- na_action_profile_new( NA_OBJECT( action ), profile->private->name );
-
- g_object_set( G_OBJECT( new ),
- PROP_PROFILE_LABEL_STR, profile->private->label,
- PROP_PROFILE_PATH_STR, profile->private->path,
- PROP_PROFILE_PARAMETERS_STR, profile->private->parameters,
- PROP_PROFILE_ACCEPT_MULTIPLE_STR, profile->private->accept_multiple_files,
- PROP_PROFILE_BASENAMES_STR, profile->private->basenames,
- PROP_PROFILE_ISDIR_STR, profile->private->is_dir,
- PROP_PROFILE_ISFILE_STR, profile->private->is_file,
- PROP_PROFILE_MATCHCASE_STR, profile->private->match_case,
- PROP_PROFILE_MIMETYPES_STR, profile->private->mimetypes,
- PROP_PROFILE_SCHEMES_STR, profile->private->schemes,
- NULL );
+ NAAction *action;
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_ACTION_STR, &action, NULL );
- return( new );
+ return( action );
}
/**
- * Frees a profile.
+ * na_action_profile_get_name:
+ * @profile: the #NAActionProfile to be requested.
*
- * @profile: the NAActionProfile object to be freed.
- */
-void
-na_action_profile_free( NAActionProfile *profile )
-{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
- g_object_unref( profile );
-}
-
-static void
-do_dump( const NAObject *object )
-{
- static const gchar *thisfn = "na_action_profile_do_dump";
-
- g_assert( NA_IS_ACTION_PROFILE( object ));
- NAActionProfile *self = NA_ACTION_PROFILE( object );
-
- if( st_parent_class->dump ){
- st_parent_class->dump( object );
- }
-
- g_debug( "%s: action=%p", thisfn, self->private->action );
- g_debug( "%s: profile_name='%s'", thisfn, self->private->name );
- g_debug( "%s: label='%s'", thisfn, self->private->label );
- g_debug( "%s: path='%s'", thisfn, self->private->path );
- g_debug( "%s: parameters='%s'", thisfn, self->private->parameters );
- g_debug( "%s: accept_multiple_file='%s'", thisfn, self->private->accept_multiple_files ? "True" : "False" );
- g_debug( "%s: is_dir='%s'", thisfn, self->private->is_dir ? "True" : "False" );
- g_debug( "%s: is_file='%s'", thisfn, self->private->is_file ? "True" : "False" );
- g_debug( "%s: match_case='%s'", thisfn, self->private->match_case ? "True" : "False" );
- do_dump_list( thisfn, "basenames", self->private->basenames );
- do_dump_list( thisfn, "mimetypes", self->private->mimetypes );
- do_dump_list( thisfn, " schemes", self->private->schemes );
-}
-
-static void
-do_dump_list( const gchar *thisfn, const gchar *label, GSList *list )
-{
- GString *str;
- str = g_string_new( "[" );
- GSList *item;
- for( item = list ; item != NULL ; item = item->next ){
- if( item != list ){
- g_string_append_printf( str, "," );
- }
- g_string_append_printf( str, "'%s'", ( gchar * ) item->data );
- }
- g_string_append_printf( str, "]" );
- g_debug( "%s: %s=%s", thisfn, label, str->str );
- g_string_free( str, TRUE );
-}
-
-static gchar *
-do_get_id( const NAObject *profile )
-{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
-
- gchar *name;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_NAME_STR, &name, NULL );
-
- return( name );
-}
-
-/**
* Returns the internal name (identifier) of the profile.
*
- * @action: an NAActionProfile object.
+ * Returns: the name of the profile as a newly allocated string.
+ * The returned string must be g_free() by the caller.
*
- * The returned string must be g_freed by the caller.
+ * See na_action_profile_set_name() for some rationales about name.
*/
gchar *
na_action_profile_get_name( const NAActionProfile *profile )
{
g_assert( NA_IS_ACTION_PROFILE( profile ));
- return( na_object_get_id( NA_OBJECT( profile )));
-}
-
-static gchar *
-do_get_label( const NAObject *profile )
-{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
- gchar *label;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_LABEL_STR, &label, NULL );
-
- return( label );
+ gchar *id;
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_NAME_STR, &id, NULL );
+ return( id );
}
/**
+ * na_action_profile_get_label:
+ * @profile: the #NAActionProfile to be requested.
+ *
* Returns the descriptive name (label) of the profile.
*
- * @action: an NAAction object.
+ * Returns: the label of the profile as a newly allocated string.
+ * The returned string must be g_free() by the caller.
*
- * The returned string must be g_freed by the caller.
+ * See na_action_profile_set_label() for some rationale about label.
*/
gchar *
na_action_profile_get_label( const NAActionProfile *profile )
{
g_assert( NA_IS_ACTION_PROFILE( profile ));
- return( na_object_get_label( NA_OBJECT( profile )));
-}
-
-/**
- * Returns a pointer to the action for this profile.
- *
- * @profile: the NAActionProfile object whose parent action is to be
- * retrieved.
- *
- * Note that the returned NactNaction is owned by the profile. The
- * caller should not try to free or unref it.
- */
-NAObject *
-na_action_profile_get_action( const NAActionProfile *profile )
-{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
- gpointer action;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_ACTION_STR, &action, NULL );
-
- return( NA_OBJECT( action ));
+ gchar *label;
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_LABEL_STR, &label, NULL );
+ return( label );
}
/**
- * Returns the path of the command in the profile.
+ * na_action_profile_get_path:
+ * @profile: the #NAActionProfile to be requested.
*
- * @profile: the NAActionProfile object whose command path is to be
- * retrieved.
+ * Returns the path of the command attached to the profile.
*
- * The returned string should be g_freed by the caller.
+ * Returns: the command path as a newly allocated string. The returned
+ * string must be g_free() by the caller.
*/
gchar *
na_action_profile_get_path( const NAActionProfile *profile )
@@ -648,18 +560,19 @@ na_action_profile_get_path( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
gchar *path;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_PATH_STR, &path, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_PATH_STR, &path, NULL );
return( path );
}
/**
- * Returns the parameters of the command in the profile.
+ * na_action_profile_get_parameters:
+ * @profile: the #NAActionProfile to be requested.
*
- * @profile: the NAActionProfile object whose command parameters are
- * to be retrieved.
+ * Returns the parameters of the command attached to the profile.
*
- * The returned string should be g_freed by the caller.
+ * Returns: the command parameters as a newly allocated string. The
+ * returned string must be g_free() by the caller.
*/
gchar *
na_action_profile_get_parameters( const NAActionProfile *profile )
@@ -667,18 +580,22 @@ na_action_profile_get_parameters( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
gchar *parameters;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_PARAMETERS_STR, ¶meters, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_PARAMETERS_STR, ¶meters, NULL );
return( parameters );
}
/**
- * Returns the list of basenames this profile applies to.
+ * na_action_profile_get_basenames:
+ * @profile: the #NAActionProfile to be requested.
+ *
+ * Returns the basenames of the files to which the profile applies.
*
- * @profile: this NAActionProfile object.
+ * Returns: a GSList of newly allocated strings. The list must be
+ * na_utils_free_string_list() by the caller.
*
- * The returned GSList should be freed by the caller by calling
- * na_utils_free_string_list.
+ * See na_action_profile_set_basenames() for some rationale about
+ * basenames.
*/
GSList *
na_action_profile_get_basenames( const NAActionProfile *profile )
@@ -686,15 +603,22 @@ na_action_profile_get_basenames( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
GSList *basenames;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_BASENAMES_STR, &basenames, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_BASENAMES_STR, &basenames, NULL );
return( basenames );
}
/**
+ * na_action_profile_get_matchcase:
+ * @profile: the #NAActionProfile to be requested.
+ *
* Are specified basenames case sensitive ?
*
- * @profile: this NAActionProfile object.
+ * Returns: %TRUE if the provided filenames are case sensitive, %FALSE
+ * else.
+ *
+ * See na_action_profile_set_matchcase() for some rationale about case
+ * sensitivity.
*/
gboolean
na_action_profile_get_matchcase( const NAActionProfile *profile )
@@ -702,18 +626,22 @@ na_action_profile_get_matchcase( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
gboolean matchcase;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_MATCHCASE_STR, &matchcase, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_MATCHCASE_STR, &matchcase, NULL );
return( matchcase );
}
/**
+ * na_action_profile_get_mimetypes:
+ * @profile: the #NAActionProfile to be requested.
+ *
* Returns the list of mimetypes this profile applies to.
*
- * @profile: this NAActionProfile object.
+ * Returns: a GSList of newly allocated strings. The list must be
+ * na_utils_free_string_list() by the caller.
*
- * The returned GSList should be freed by the caller by calling
- * na_utils_free_string_list.
+ * See na_action_profile_set_mimetypes() for some rationale about
+ * mimetypes.
*/
GSList *
na_action_profile_get_mimetypes( const NAActionProfile *profile )
@@ -721,15 +649,21 @@ na_action_profile_get_mimetypes( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
GSList *mimetypes;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_MIMETYPES_STR, &mimetypes, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_MIMETYPES_STR, &mimetypes, NULL );
return( mimetypes );
}
/**
- * Does this profile apply to files ?
+ * na_action_profile_get_is_file:
+ * @profile: the #NAActionProfile to be requested.
*
- * @profile: this NAActionProfile object.
+ * Does this profile apply if the selection contains files ?
+ *
+ * Returns: %TRUE if it applies, %FALSE else.
+ *
+ * See na_action_profile_set_isfiledir() for some rationale about file
+ * selection.
*/
gboolean
na_action_profile_get_is_file( const NAActionProfile *profile )
@@ -737,15 +671,21 @@ na_action_profile_get_is_file( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
gboolean isfile;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_ISFILE_STR, &isfile, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_ISFILE_STR, &isfile, NULL );
return( isfile );
}
/**
- * Does this profile apply to directories ?
+ * na_action_profile_get_is_dir:
+ * @profile: the #NAActionProfile to be requested.
+ *
+ * Does this profile apply if the selection contains folders ?
*
- * @profile: this NAActionProfile object.
+ * Returns: %TRUE if it applies, %FALSE else.
+ *
+ * See na_action_profile_set_isfiledir() for some rationale about file
+ * selection.
*/
gboolean
na_action_profile_get_is_dir( const NAActionProfile *profile )
@@ -753,15 +693,22 @@ na_action_profile_get_is_dir( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
gboolean isdir;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_ISDIR_STR, &isdir, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_ISDIR_STR, &isdir, NULL );
return( isdir );
}
/**
- * Does this profile apply on a multiple selection ?
+ * na_action_profile_get_multiple:
+ * @profile: the #NAActionProfile to be requested.
+ *
+ * Does this profile apply if selection contains multiple files or
+ * folders ?
*
- * @profile: this NAActionProfile object.
+ * Returns: %TRUE if it applies, %FALSE else.
+ *
+ * See na_action_profile_set_multiple() for some rationale about
+ * multiple selection.
*/
gboolean
na_action_profile_get_multiple( const NAActionProfile *profile )
@@ -769,18 +716,22 @@ na_action_profile_get_multiple( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
gboolean multiple;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_ACCEPT_MULTIPLE_STR, &multiple, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_ACCEPT_MULTIPLE_STR, &multiple, NULL );
return( multiple );
}
/**
+ * na_action_profile_get_schemes:
+ * @profile: the #NAActionProfile to be requested.
+ *
* Returns the list of schemes this profile applies to.
*
- * @profile: this NAActionProfile object.
+ * Returns: a GSList of newly allocated strings. The list must be
+ * na_utils_free_string_list() by the caller.
*
- * The returned GSList should be freed by the caller by calling
- * na_utils_free_string_list.
+ * See na_action_profile_set_schemes() for some rationale about
+ * schemes.
*/
GSList *
na_action_profile_get_schemes( const NAActionProfile *profile )
@@ -788,219 +739,254 @@ na_action_profile_get_schemes( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
GSList *schemes;
- g_object_get( G_OBJECT( profile ), PROP_PROFILE_SCHEMES_STR, &schemes, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_SCHEMES_STR, &schemes, NULL );
return( schemes );
}
/**
- * Returns TRUE if the profile are the same, excluding action pointer.
- *
- * @first: a NAActionProfile.
+ * na_action_profile_set_action:
+ * @profile: the #NAActionProfile to be updated.
+ * @action: the #NAAction action to which this profile is attached.
*
- * @second: another NAActionProfile, to be compared with @first.
+ * Sets the action to which this profile is attached.
*/
-gboolean
-na_action_profile_are_equal( NAActionProfile *first, NAActionProfile *second )
+void
+na_action_profile_set_action( NAActionProfile *profile, const NAAction *action )
{
- gboolean equal =
- ( g_utf8_collate( first->private->name, second->private->name ) == 0 ) &&
- ( g_utf8_collate( first->private->label, second->private->label ) == 0 ) &&
- ( g_utf8_collate( first->private->path, second->private->path ) == 0 ) &&
- ( g_utf8_collate( first->private->parameters, second->private->parameters ) == 0 );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
- if( equal ){
- equal = (( first->private->accept_multiple_files && second->private->accept_multiple_files ) ||
- ( !first->private->accept_multiple_files && !second->private->accept_multiple_files ));
- }
- if( equal ){
- equal = (( first->private->is_dir && second->private->is_dir ) ||
- ( !first->private->is_dir && !second->private->is_dir ));
- }
- if( equal ){
- equal = (( first->private->is_file && second->private->is_file ) ||
- ( !first->private->is_file && !second->private->is_file ));
- }
- if( equal ){
- equal = na_utils_string_lists_are_equal( first->private->basenames, second->private->basenames ) &&
- na_utils_string_lists_are_equal( first->private->mimetypes, second->private->mimetypes ) &&
- na_utils_string_lists_are_equal( first->private->schemes, second->private->schemes );
- }
- return( equal );
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_ACTION_STR, action, NULL );
}
-static int
-validate_schemes( GSList* schemes2test, NautilusFileInfo* file )
+/**
+ * na_action_profile_set_name:
+ * @profile: the #NAActionProfile to be updated.
+ * @name: the name to be set.
+ *
+ * Sets the name for this profile.
+ *
+ * #NAActionProfile takes a copy of the provided name. This later may
+ * so be g_free() by the caller after this function returns.
+ *
+ * The profile name is an ASCII, case insensitive, string which
+ * uniquely identifies the profile inside of the action.
+ *
+ * This function doesn't check for the unicity of the name. And this
+ * unicity will never be checked until we try to write the action to
+ * GConf.
+ */
+void
+na_action_profile_set_name( NAActionProfile *profile, const gchar *name )
{
- int retv = 0;
- GSList* iter;
- gboolean found = FALSE;
-
- iter = schemes2test;
- while (iter && !found)
- {
- gchar* scheme = nautilus_file_info_get_uri_scheme (file);
-
- if (g_ascii_strncasecmp (scheme, (gchar*)iter->data, strlen ((gchar*)iter->data)) == 0)
- {
- found = TRUE;
- retv = 1;
- }
-
- g_free (scheme);
- iter = iter->next;
- }
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
- return retv;
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_NAME_STR, name, NULL );
}
/**
- * Set the label for this profile.
+ * na_action_profile_set_label:
+ * @profile: the #NAActionProfile to be updated.
+ * @label: the label to be set.
*
- * @profile: this NAActionProfile object.
+ * Sets the label for this profile.
*
- * @label: label to be set.
+ * #NAActionProfile takes a copy of the provided label. This later may
+ * so be g_free() by the caller after this function returns.
+ *
+ * The label of the #NAActionProfile is an UTF-8 string.
*/
void
na_action_profile_set_label( NAActionProfile *profile, const gchar *label )
{
- g_object_set( G_OBJECT( profile ), PROP_PROFILE_LABEL_STR, label, NULL );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_LABEL_STR, label, NULL );
}
/**
- * Set the path of the command for this profile.
+ * na_action_profile_set_path:
+ * @profile: the #NAActionProfile to be updated.
+ * @path: the command path to be set.
*
- * @profile: this NAActionProfile object.
+ * Sets the path of the command for this profile.
*
- * @path: path to be set.
+ * #NAActionProfile takes a copy of the provided path. This later may
+ * so be g_free() by the caller after this function returns.
*/
void
na_action_profile_set_path( NAActionProfile *profile, const gchar *path )
{
- g_object_set( G_OBJECT( profile ), PROP_PROFILE_PATH_STR, path, NULL );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_PATH_STR, path, NULL );
}
/**
- * Set the parameters of the command for this profile.
+ * na_action_profile_set_parameters:
+ * @profile: the #NAActionProfile to be updated.
+ * @parameters : the command parameters to be set.
*
- * @profile: this NAActionProfile object.
+ * Sets the parameters of the command for this profile.
*
- * @parameters: parameters to be set.
+ * #NAActionProfile takes a copy of the provided parameters. This later
+ * may so be g_free() by the caller after this function returns.
*/
void
na_action_profile_set_parameters( NAActionProfile *profile, const gchar *parameters )
{
- g_object_set( G_OBJECT( profile ), PROP_PROFILE_PARAMETERS_STR, parameters, NULL );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_PARAMETERS_STR, parameters, NULL );
}
/**
- * Set the basenames on which this profile applies.
+ * na_action_profile_set_basenames:
+ * @profile: the #NAActionProfile to be updated.
+ * @basenames : the basenames to be set.
+ *
+ * Sets the basenames of the elements on which this profile applies.
*
- * @profile: this NAActionProfile object.
+ * #NAActionProfile takes a copy of the provided basenames. This later
+ * may so be na_utils_free_string_list() by the caller after this
+ * function returns.
*
- * @basenames: list of basenames to be matched.
+ * The basenames list defaults to the single element "*", which means
+ * that the profile will apply to all basenames.
*/
void
na_action_profile_set_basenames( NAActionProfile *profile, GSList *basenames )
{
- g_object_set( G_OBJECT( profile ), PROP_PROFILE_BASENAMES_STR, basenames, NULL );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_BASENAMES_STR, basenames, NULL );
}
/**
- * Set the 'match_case' flag, indicating if specified basename patterns
- * are, or not, case sensitive.
+ * na_action_profile_set_matchcase:
+ * @profile: the #NAActionProfile to be updated.
+ * @matchcase : whether the basenames are case sensitive or not.
*
- * @profile: this NAActionProfile object.
+ * Sets the 'match_case' flag, indicating if specified basename
+ * patterns are, or not, case sensitive.
*
- * @matchcase: TRUE if basename patterns are case sensitive.
+ * This value defaults to %TRUE, which means that basename patterns
+ * default to be case sensitive.
*/
void
na_action_profile_set_matchcase( NAActionProfile *profile, gboolean matchcase )
{
- g_object_set( G_OBJECT( profile ), PROP_PROFILE_MATCHCASE_STR, matchcase, NULL );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_MATCHCASE_STR, matchcase, NULL );
}
/**
- * Set the mimetypes on which this profile applies.
+ * na_action_profile_set_mimetypes:
+ * @profile: the #NAActionProfile to be updated.
+ * @mimetypes: list of mimetypes to be matched.
*
- * @profile: this NAActionProfile object.
+ * Sets the mimetypes on which this profile applies.
*
- * @mimetypes: list of mimetypes to be matched.
+ * #NAActionProfile takes a copy of the provided mimetypes. This later
+ * may so be na_utils_free_string_list() by the caller after this
+ * function returns.
+ *
+ * The mimetypes list defaults to the single element "* / *", which
+ * means that the profile will apply to all types of files.
*/
void
na_action_profile_set_mimetypes( NAActionProfile *profile, GSList *mimetypes )
{
- g_object_set( G_OBJECT( profile ), PROP_PROFILE_MIMETYPES_STR, mimetypes, NULL );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_MIMETYPES_STR, mimetypes, NULL );
}
/**
- * Set the 'isfile' flag on which this profile applies.
- *
- * @profile: this NAActionProfile object.
+ * na_action_profile_set_isfile:
+ * @profile: the #NAActionProfile to be updated.
+ * @isfile: whether the profile applies only to files.
*
- * @isfile: the profile applies only to files.
+ * Sets the 'isfile' flag on which this profile applies.
*/
void
na_action_profile_set_isfile( NAActionProfile *profile, gboolean isfile )
{
- g_object_set( G_OBJECT( profile ), PROP_PROFILE_ISFILE_STR, isfile, NULL );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_ISFILE_STR, isfile, NULL );
}
/**
- * Set the 'isdir' flag on which this profile applies.
- *
- * @profile: this NAActionProfile object.
- *
+ * na_action_profile_set_isdir:
+ * @profile: the #NAActionProfile to be updated.
* @isdir: the profile applies only to folders.
+ *
+ * Sets the 'isdir' flag on which this profile applies.
*/
void
na_action_profile_set_isdir( NAActionProfile *profile, gboolean isdir )
{
- g_object_set( G_OBJECT( profile ), PROP_PROFILE_ISDIR_STR, isdir, NULL );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_ISDIR_STR, isdir, NULL );
}
/**
- * Set the 'isfile' and 'isdir' flags on which this profile applies.
+ * na_action_profile_set_isfiledir:
+ * @profile: the #NAActionProfile to be updated.
+ * @isfile: whether the profile applies only to files.
+ * @isdir: the profile applies only to folders.
*
- * @profile: this NAActionProfile object.
+ * Sets the 'isfile' and 'isdir' flags on which this profile applies.
*
- * @isfile: the profile applies only to files.
+ * File selection defaults to %TRUE.
*
- * @isdir: the profile applies only to folders.
+ * Folder selection defaults to %FALSE, which means that this profile will
+ * not apply if the selection contains folders.
*/
void
na_action_profile_set_isfiledir( NAActionProfile *profile, gboolean isfile, gboolean isdir )
{
- g_object_set( G_OBJECT( profile ), PROP_PROFILE_ISFILE_STR, isfile, PROP_PROFILE_ISDIR_STR, isdir, NULL );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_ISFILE_STR, isfile, PROP_NAPROFILE_ISDIR_STR, isdir, NULL );
}
/**
- * Does this profile accept multiple selection ?
+ * na_action_profile_set_multiple:
+ * @profile: the #NAActionProfile to be updated.
+ * @multiple: TRUE if it does.
*
- * @profile: this NAActionProfile object.
+ * Sets if this profile accept multiple selection ?
*
- * @multiple: TRUE if it does.
+ * This value defaults to %FALSE, which means that this profile will
+ * not apply if the selection contains more than one element.
*/
void
na_action_profile_set_multiple( NAActionProfile *profile, gboolean multiple )
{
- g_object_set( G_OBJECT( profile ), PROP_PROFILE_ACCEPT_MULTIPLE_STR, multiple, NULL );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_ACCEPT_MULTIPLE_STR, multiple, NULL );
}
/**
- * Set the status of a scheme relative to this profile.
- *
- * @profile: this NAActionProfile object.
- *
- * @scheme: nae of the scheme.
- *
+ * na_action_profile_set_scheme:
+ * @profile: the #NAActionProfile to be updated.
+ * @scheme: name of the scheme.
* @selected: whether this scheme is candidate to this profile.
+ *
+ * Sets the status of a scheme relative to this profile.
*/
void
na_action_profile_set_scheme( NAActionProfile *profile, const gchar *scheme, gboolean selected )
{
/*static const gchar *thisfn = "na_action_profile_set_scheme";*/
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
gboolean exist = na_utils_find_in_list( profile->private->schemes, scheme );
/*g_debug( "%s: scheme=%s exist=%s", thisfn, scheme, exist ? "True":"False" );*/
@@ -1013,30 +999,45 @@ na_action_profile_set_scheme( NAActionProfile *profile, const gchar *scheme, gbo
}
/**
- * Set the schemes on which this profile applies.
+ * na_action_profile_set_schemes:
+ * @profile: the #NAActionProfile to be updated.
+ * @schemes: list of schemes which apply.
*
- * @profile: this NAActionProfile object.
+ * Sets the schemes on which this profile applies.
*
- * @schemes: list of schemes which apply.
+ * #NAActionProfile takes a copy of the provided mimetypes. This later
+ * may so be na_utils_free_string_list() by the caller after this
+ * function returns.
+ *
+ * The schemes list defaults to the single element "file", which means
+ * that the profile will only apply to local files.
*/
void
na_action_profile_set_schemes( NAActionProfile *profile, GSList *schemes )
{
- g_object_set( G_OBJECT( profile ), PROP_PROFILE_SCHEMES_STR, schemes, NULL );
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_SCHEMES_STR, schemes, NULL );
}
/**
+ * na_action_profile_is_candidate:
+ * @profile: the #NAActionProfile to be checked.
+ * @files: the currently selected items, as provided by Nautilus.
+ *
* Determines if the given profile is candidate to be displayed in the
* Nautilus context menu, regarding the list of currently selected
* items.
*
- * @profile: the profile to be examined.
- *
- * @files: the list currently selected items, as provided by Nautilus.
+ * Returns: %TRUE if this profile succeeds to all tests and is so a
+ * valid candidate to be displayed in Nautilus context menu, %FALSE
+ * else.
*/
gboolean
na_action_profile_is_candidate( const NAActionProfile *profile, GList* files )
{
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
gboolean retv = FALSE;
gboolean test_multiple_file = FALSE;
gboolean test_file_type = FALSE;
@@ -1186,11 +1187,11 @@ na_action_profile_is_candidate( const NAActionProfile *profile, GList* files )
total_count++;
}
- if ((files != NULL) && (files->next == NULL) && (!profile->private->accept_multiple_files))
+ if ((files != NULL) && (files->next == NULL) && (!profile->private->accept_multiple))
{
test_multiple_file = TRUE;
}
- else if (profile->private->accept_multiple_files)
+ else if (profile->private->accept_multiple)
{
test_multiple_file = TRUE;
}
@@ -1419,3 +1420,175 @@ na_action_profile_parse_parameters( const NAActionProfile *profile, GList* files
parsed = g_string_free( string, FALSE );
return( parsed );
}
+
+static void
+object_dump( const NAObject *object )
+{
+ static const gchar *thisfn = "na_action_profile_object_dump";
+
+ g_assert( NA_IS_ACTION_PROFILE( object ));
+ NAActionProfile *self = NA_ACTION_PROFILE( object );
+
+ if( st_parent_class->dump ){
+ st_parent_class->dump( object );
+ }
+
+ g_debug( "%s: action=%p", thisfn, self->private->action );
+ g_debug( "%s: path='%s'", thisfn, self->private->path );
+ g_debug( "%s: parameters='%s'", thisfn, self->private->parameters );
+ g_debug( "%s: accept_multiple='%s'", thisfn, self->private->accept_multiple ? "True" : "False" );
+ g_debug( "%s: is_dir='%s'", thisfn, self->private->is_dir ? "True" : "False" );
+ g_debug( "%s: is_file='%s'", thisfn, self->private->is_file ? "True" : "False" );
+ g_debug( "%s: match_case='%s'", thisfn, self->private->match_case ? "True" : "False" );
+ object_dump_list( thisfn, "basenames", self->private->basenames );
+ object_dump_list( thisfn, "mimetypes", self->private->mimetypes );
+ object_dump_list( thisfn, " schemes", self->private->schemes );
+}
+
+static void
+object_dump_list( const gchar *thisfn, const gchar *label, GSList *list )
+{
+ gchar *string = na_utils_gslist_to_schema( list );
+ g_debug( "%s: %s=%s", thisfn, label, string );
+ g_free( string );
+}
+
+static NAObject *
+object_duplicate( const NAObject *profile )
+{
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ NAObject *duplicate = NA_OBJECT( na_action_profile_new());
+
+ na_object_copy( duplicate, profile );
+
+ return( duplicate );
+}
+
+static void
+object_copy( NAObject *target, const NAObject *source )
+{
+ g_assert( NA_IS_ACTION_PROFILE( target ));
+ g_assert( NA_IS_ACTION_PROFILE( source ));
+
+ gchar *path, *parameters;
+ gboolean matchcase, isfile, isdir, multiple;
+ GSList *basenames, *mimetypes, *schemes;
+
+ g_object_get( G_OBJECT( source ),
+ PROP_NAPROFILE_PATH_STR, &path,
+ PROP_NAPROFILE_PARAMETERS_STR, ¶meters,
+ PROP_NAPROFILE_BASENAMES_STR, &basenames,
+ PROP_NAPROFILE_MATCHCASE_STR, &matchcase,
+ PROP_NAPROFILE_MIMETYPES_STR, &mimetypes,
+ PROP_NAPROFILE_ISFILE_STR, &isfile,
+ PROP_NAPROFILE_ISDIR_STR, &isdir,
+ PROP_NAPROFILE_ACCEPT_MULTIPLE_STR, &multiple,
+ PROP_NAPROFILE_SCHEMES_STR, &schemes,
+ NULL );
+
+ g_object_set( G_OBJECT( target ),
+ PROP_NAPROFILE_PATH_STR, path,
+ PROP_NAPROFILE_PARAMETERS_STR, parameters,
+ PROP_NAPROFILE_BASENAMES_STR, basenames,
+ PROP_NAPROFILE_MATCHCASE_STR, matchcase,
+ PROP_NAPROFILE_MIMETYPES_STR, mimetypes,
+ PROP_NAPROFILE_ISFILE_STR, isfile,
+ PROP_NAPROFILE_ISDIR_STR, isdir,
+ PROP_NAPROFILE_ACCEPT_MULTIPLE_STR, multiple,
+ PROP_NAPROFILE_SCHEMES_STR, schemes,
+ NULL );
+
+ g_free( path );
+ g_free( parameters );
+ na_utils_free_string_list( basenames );
+ na_utils_free_string_list( mimetypes );
+ na_utils_free_string_list( schemes );
+
+ if( st_parent_class->copy ){
+ st_parent_class->copy( target, source );
+ }
+}
+
+gboolean
+object_are_equal( const NAObject *a, const NAObject *b )
+{
+ g_assert( NA_IS_ACTION_PROFILE( a ));
+ g_assert( NA_IS_ACTION_PROFILE( b ));
+
+ NAActionProfile *first = NA_ACTION_PROFILE( a );
+ NAActionProfile *second = NA_ACTION_PROFILE( b );
+
+ gboolean equal =
+ ( g_utf8_collate( first->private->path, second->private->path ) == 0 ) &&
+ ( g_utf8_collate( first->private->parameters, second->private->parameters ) == 0 );
+
+ if( equal ){
+ equal = (( first->private->accept_multiple && second->private->accept_multiple ) ||
+ ( !first->private->accept_multiple && !second->private->accept_multiple ));
+ }
+ if( equal ){
+ equal = (( first->private->is_dir && second->private->is_dir ) ||
+ ( !first->private->is_dir && !second->private->is_dir ));
+ }
+ if( equal ){
+ equal = (( first->private->is_file && second->private->is_file ) ||
+ ( !first->private->is_file && !second->private->is_file ));
+ }
+ if( equal ){
+ equal = na_utils_string_lists_are_equal( first->private->basenames, second->private->basenames ) &&
+ na_utils_string_lists_are_equal( first->private->mimetypes, second->private->mimetypes ) &&
+ na_utils_string_lists_are_equal( first->private->schemes, second->private->schemes );
+ }
+ if( equal ){
+ if( st_parent_class->are_equal ){
+ equal = st_parent_class->are_equal( a, b );
+ }
+ }
+
+ return( equal );
+}
+
+gboolean
+object_is_valid( const NAObject *profile )
+{
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ gchar *label;
+ g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_LABEL_STR, &label, NULL );
+ gboolean is_valid = ( label && g_utf8_strlen( label, -1 ) > 0 );
+ g_free( label );
+
+ if( is_valid ){
+ if( st_parent_class->is_valid ){
+ is_valid = st_parent_class->is_valid( profile );
+ }
+ }
+
+ return( is_valid );
+}
+
+static int
+validate_schemes( GSList* schemes2test, NautilusFileInfo* file )
+{
+ int retv = 0;
+ GSList* iter;
+ gboolean found = FALSE;
+
+ iter = schemes2test;
+ while (iter && !found)
+ {
+ gchar* scheme = nautilus_file_info_get_uri_scheme (file);
+
+ if (g_ascii_strncasecmp (scheme, (gchar*)iter->data, strlen ((gchar*)iter->data)) == 0)
+ {
+ found = TRUE;
+ retv = 1;
+ }
+
+ g_free (scheme);
+ iter = iter->next;
+ }
+
+ return retv;
+}
diff --git a/src/common/na-action-profile.h b/src/common/na-action-profile.h
index 407ee2c..fcad4c0 100644
--- a/src/common/na-action-profile.h
+++ b/src/common/na-action-profile.h
@@ -31,71 +31,32 @@
#ifndef __NA_ACTION_PROFILE_H__
#define __NA_ACTION_PROFILE_H__
-/*
- * NactActionProfile class definition.
+/**
+ * SECTION: na_action_profile
+ * @short_description: #NAActionProfile class definition.
+ * @include: common/na-action-profile.h
*
- * This is a companion class of NactAction. It embeds the profile
+ * This is a companion class of NAAction. It embeds the profile
* definition of an action.
*
- * As NactAction itself, NactActionProfile class is derived from
- * NAObject which takes care of i/o.
+ * As NAAction itself, NAActionProfile class is derived from
+ * NAObject class, which takes care of IDuplicable interface management.
*/
-#include "na-object.h"
+#include "na-action-class.h"
+#include "na-action-profile-class.h"
G_BEGIN_DECLS
-#define NA_ACTION_PROFILE_TYPE ( na_action_profile_get_type())
-#define NA_ACTION_PROFILE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_ACTION_PROFILE_TYPE, NAActionProfile ))
-#define NA_ACTION_PROFILE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_ACTION_PROFILE_TYPE, NAActionProfileClass ))
-#define NA_IS_ACTION_PROFILE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_ACTION_PROFILE_TYPE ))
-#define NA_IS_ACTION_PROFILE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_ACTION_PROFILE_TYPE ))
-#define NA_ACTION_PROFILE_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_ACTION_PROFILE_TYPE, NAActionProfileClass ))
-
-typedef struct NAActionProfilePrivate NAActionProfilePrivate;
-
-typedef struct {
- NAObject parent;
- NAActionProfilePrivate *private;
-}
- NAActionProfile;
-
-typedef struct NAActionProfileClassPrivate NAActionProfileClassPrivate;
-
-typedef struct {
- NAObjectClass parent;
- NAActionProfileClassPrivate *private;
-}
- NAActionProfileClass;
-
-/* instance properties
- */
-#define PROP_PROFILE_ACTION_STR "profile-action"
-#define PROP_PROFILE_NAME_STR "profile-name"
-#define PROP_PROFILE_LABEL_STR "profile-desc-name"
-#define PROP_PROFILE_PATH_STR "profile-path"
-#define PROP_PROFILE_PARAMETERS_STR "profile-parameters"
-#define PROP_PROFILE_BASENAMES_STR "profile-basenames"
-#define PROP_PROFILE_MATCHCASE_STR "profile-matchcase"
-#define PROP_PROFILE_ISDIR_STR "profile-isdir"
-#define PROP_PROFILE_ISFILE_STR "profile-isfile"
-#define PROP_PROFILE_ACCEPT_MULTIPLE_STR "profile-accept-multiple-files"
-#define PROP_PROFILE_MIMETYPES_STR "profile-mimetypes"
-#define PROP_PROFILE_SCHEMES_STR "profile-schemes"
-
/* internal identifier of profiles must begin with the following prefix
* this let us identify a profile key versus an action key
* corollarily, no action entry must begin with this same prefix
*/
-#define ACTION_PROFILE_PREFIX "profile-"
-
-GType na_action_profile_get_type( void );
+#define ACTION_PROFILE_PREFIX "profile-"
-NAActionProfile *na_action_profile_new( const NAObject *action, const gchar *name );
-NAActionProfile *na_action_profile_duplicate( const NAAction *action, const NAActionProfile *profile );
-void na_action_profile_free( NAActionProfile *profile );
+NAActionProfile *na_action_profile_new( void );
-NAObject *na_action_profile_get_action( const NAActionProfile *profile );
+NAAction *na_action_profile_get_action( const NAActionProfile *profile );
gchar *na_action_profile_get_name( const NAActionProfile *profile );
gchar *na_action_profile_get_label( const NAActionProfile *profile );
gchar *na_action_profile_get_path( const NAActionProfile *profile );
@@ -103,13 +64,13 @@ gchar *na_action_profile_get_parameters( const NAActionProfile *profil
GSList *na_action_profile_get_basenames( const NAActionProfile *profile );
gboolean na_action_profile_get_matchcase( const NAActionProfile *profile );
GSList *na_action_profile_get_mimetypes( const NAActionProfile *profile );
-gboolean na_action_profile_get_is_dir( const NAActionProfile *profile );
gboolean na_action_profile_get_is_file( const NAActionProfile *profile );
+gboolean na_action_profile_get_is_dir( const NAActionProfile *profile );
gboolean na_action_profile_get_multiple( const NAActionProfile *profile );
GSList *na_action_profile_get_schemes( const NAActionProfile *profile );
-gboolean na_action_profile_are_equal( NAActionProfile *first, NAActionProfile *second );
-
+void na_action_profile_set_action( NAActionProfile *profile, const NAAction *action );
+void na_action_profile_set_name( NAActionProfile *profile, const gchar *name );
void na_action_profile_set_label( NAActionProfile *profile, const gchar *label );
void na_action_profile_set_path( NAActionProfile *profile, const gchar *path );
void na_action_profile_set_parameters( NAActionProfile *profile, const gchar *parameters );
diff --git a/src/common/na-action.c b/src/common/na-action.c
index ff8df22..7be1555 100644
--- a/src/common/na-action.c
+++ b/src/common/na-action.c
@@ -32,6 +32,7 @@
#include <config.h>
#endif
+#include <glib/gi18n.h>
#include <string.h>
#include <uuid/uuid.h>
@@ -47,64 +48,70 @@ struct NAActionClassPrivate {
/* private instance data
*/
struct NAActionPrivate {
- gboolean dispose_has_run;
+ gboolean dispose_has_run;
/* action properties
*/
- gchar *uuid;
- gchar *version;
- gchar *label;
- gchar *tooltip;
- gchar *icon;
+ gchar *version;
+ gchar *tooltip;
+ gchar *icon;
/* list of action's profiles as NAActionProfile objects
* (thanks, Frederic ;-))
*/
- GSList *profiles;
+ GSList *profiles;
/* dynamically set when reading the actions from the I/O storage
* subsystem
* defaults to FALSE unless a write has already returned an error
*/
- gboolean read_only;
+ gboolean read_only;
/* the original provider
* required to be able to edit/delete the action
*/
- gpointer provider;
+ NAIIOProvider *provider;
};
-/* instance properties
- * please note that property names must have the same spelling as the
- * NactIIOProvider parameters
+/* action properties
*/
enum {
- PROP_ACTION_UUID = 1,
- PROP_ACTION_VERSION,
- PROP_ACTION_LABEL,
- PROP_ACTION_TOOLTIP,
- PROP_ACTION_ICON,
- PROP_ACTION_READONLY,
- PROP_ACTION_PROVIDER
+ PROP_NAACTION_UUID = 1,
+ PROP_NAACTION_LABEL,
+ PROP_NAACTION_VERSION,
+ PROP_NAACTION_TOOLTIP,
+ PROP_NAACTION_ICON,
+ PROP_NAACTION_READONLY,
+ PROP_NAACTION_PROVIDER
};
-#define NA_ACTION_LATEST_VERSION "2.0"
+#define PROP_NAACTION_UUID_STR "na-action-uuid"
+#define PROP_NAACTION_LABEL_STR "na-action-label"
+#define PROP_NAACTION_VERSION_STR "na-action-version"
+#define PROP_NAACTION_TOOLTIP_STR "na-action-tooltip"
+#define PROP_NAACTION_ICON_STR "na-action-icon"
+#define PROP_NAACTION_READONLY_STR "na-action-read-only"
+#define PROP_NAACTION_PROVIDER_STR "na-action-provider"
+
+#define NA_ACTION_LATEST_VERSION "2.0"
static NAObjectClass *st_parent_class = NULL;
-static GType register_type( void );
-static void class_init( NAActionClass *klass );
-static void instance_init( GTypeInstance *instance, gpointer klass );
-static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
-static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
-static void instance_dispose( GObject *object );
-static void instance_finalize( GObject *object );
+static GType register_type( void );
+static void class_init( NAActionClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
-static void do_dump( const NAObject *action );
-static gchar *do_get_id( const NAObject *action );
-static gchar *do_get_label( const NAObject *action );
+static void object_dump( const NAObject *action );
+static NAObject *object_duplicate( const NAObject *action );
+static void object_copy( NAObject *target, const NAObject *source );
+static gboolean object_are_equal( const NAObject *a, const NAObject *b );
+static gboolean object_is_valid( const NAObject *action );
-static void free_profiles( NAAction *action );
+static void free_profiles( NAAction *action );
GType
na_action_get_type( void )
@@ -121,6 +128,9 @@ na_action_get_type( void )
static GType
register_type( void )
{
+ static const gchar *thisfn = "na_action_register_type";
+ g_debug( "%s", thisfn );
+
static GTypeInfo info = {
sizeof( NAActionClass ),
( GBaseInitFunc ) NULL,
@@ -151,69 +161,69 @@ class_init( NAActionClass *klass )
object_class->get_property = instance_get_property;
GParamSpec *spec;
-
- /* the id of the object is marked as G_PARAM_CONSTRUCT_ONLY */
spec = g_param_spec_string(
- PROP_ACTION_UUID_STR,
- PROP_ACTION_UUID_STR,
+ PROP_NAACTION_UUID_STR,
+ "Action UUID",
"Globally unique identifier (UUID) of the action", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_ACTION_UUID, spec );
+ g_object_class_install_property( object_class, PROP_NAACTION_UUID, spec );
spec = g_param_spec_string(
- PROP_ACTION_VERSION_STR,
- PROP_ACTION_VERSION_STR,
- "Version of the schema", "",
+ PROP_NAACTION_LABEL_STR,
+ "Action label",
+ "Context menu displayable label", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_ACTION_VERSION, spec );
+ g_object_class_install_property( object_class, PROP_NAACTION_LABEL, spec );
spec = g_param_spec_string(
- PROP_ACTION_LABEL_STR,
- PROP_ACTION_LABEL_STR,
- "Context menu displayable label", "",
+ PROP_NAACTION_VERSION_STR,
+ "Version",
+ "Version of the schema", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_ACTION_LABEL, spec );
+ g_object_class_install_property( object_class, PROP_NAACTION_VERSION, spec );
spec = g_param_spec_string(
- PROP_ACTION_TOOLTIP_STR,
- PROP_ACTION_TOOLTIP_STR,
+ PROP_NAACTION_TOOLTIP_STR,
+ "Action tooltip",
"Context menu tooltip", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_ACTION_TOOLTIP, spec );
+ g_object_class_install_property( object_class, PROP_NAACTION_TOOLTIP, spec );
spec = g_param_spec_string(
- PROP_ACTION_ICON_STR,
- PROP_ACTION_ICON_STR,
+ PROP_NAACTION_ICON_STR,
+ "Icon name",
"Context menu displayable icon", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_ACTION_ICON, spec );
+ g_object_class_install_property( object_class, PROP_NAACTION_ICON, spec );
spec = g_param_spec_boolean(
- PROP_ACTION_READONLY_STR,
- PROP_ACTION_READONLY_STR,
+ PROP_NAACTION_READONLY_STR,
+ "Read-only flag",
"Is this action only readable", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_ACTION_READONLY, spec );
+ g_object_class_install_property( object_class, PROP_NAACTION_READONLY, spec );
spec = g_param_spec_pointer(
- PROP_ACTION_PROVIDER_STR,
- PROP_ACTION_PROVIDER_STR,
+ PROP_NAACTION_PROVIDER_STR,
+ "Original provider",
"Original provider",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_ACTION_PROVIDER, spec );
+ g_object_class_install_property( object_class, PROP_NAACTION_PROVIDER, spec );
klass->private = g_new0( NAActionClassPrivate, 1 );
- NA_OBJECT_CLASS( klass )->dump = do_dump;
- NA_OBJECT_CLASS( klass )->get_id = do_get_id;
- NA_OBJECT_CLASS( klass )->get_label = do_get_label;
+ NA_OBJECT_CLASS( klass )->dump = object_dump;
+ NA_OBJECT_CLASS( klass )->duplicate = object_duplicate;
+ NA_OBJECT_CLASS( klass )->copy = object_copy;
+ NA_OBJECT_CLASS( klass )->are_equal = object_are_equal;
+ NA_OBJECT_CLASS( klass )->is_valid = object_is_valid;
}
static void
instance_init( GTypeInstance *instance, gpointer klass )
{
- static const gchar *thisfn = "na_action_instance_init";
- g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
+ /*static const gchar *thisfn = "na_action_instance_init";
+ g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );*/
g_assert( NA_IS_ACTION( instance ));
NAAction* self = NA_ACTION( instance );
@@ -225,7 +235,6 @@ instance_init( GTypeInstance *instance, gpointer klass )
/* initialize suitable default values
*/
self->private->version = g_strdup( NA_ACTION_LATEST_VERSION );
- self->private->label = g_strdup( "" );
self->private->tooltip = g_strdup( "" );
self->private->icon = g_strdup( "" );
self->private->read_only = FALSE;
@@ -239,31 +248,31 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
NAAction *self = NA_ACTION( object );
switch( property_id ){
- case PROP_ACTION_UUID:
- g_value_set_string( value, self->private->uuid );
+ case PROP_NAACTION_UUID:
+ G_OBJECT_CLASS( st_parent_class )->get_property( object, PROP_NAOBJECT_ID, value, spec );
break;
- case PROP_ACTION_VERSION:
- g_value_set_string( value, self->private->version );
+ case PROP_NAACTION_LABEL:
+ G_OBJECT_CLASS( st_parent_class )->get_property( object, PROP_NAOBJECT_LABEL, value, spec );
break;
- case PROP_ACTION_LABEL:
- g_value_set_string( value, self->private->label );
+ case PROP_NAACTION_VERSION:
+ g_value_set_string( value, self->private->version );
break;
- case PROP_ACTION_TOOLTIP:
+ case PROP_NAACTION_TOOLTIP:
g_value_set_string( value, self->private->tooltip );
break;
- case PROP_ACTION_ICON:
+ case PROP_NAACTION_ICON:
g_value_set_string( value, self->private->icon );
break;
- case PROP_ACTION_READONLY:
+ case PROP_NAACTION_READONLY:
g_value_set_boolean( value, self->private->read_only );
break;
- case PROP_ACTION_PROVIDER:
+ case PROP_NAACTION_PROVIDER:
g_value_set_pointer( value, self->private->provider );
break;
@@ -280,36 +289,34 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
NAAction *self = NA_ACTION( object );
switch( property_id ){
- case PROP_ACTION_UUID:
- g_free( self->private->uuid );
- self->private->uuid = g_value_dup_string( value );
+ case PROP_NAACTION_UUID:
+ G_OBJECT_CLASS( st_parent_class )->set_property( object, PROP_NAOBJECT_ID, value, spec );
break;
- case PROP_ACTION_VERSION:
- g_free( self->private->version );
- self->private->version = g_value_dup_string( value );
+ case PROP_NAACTION_LABEL:
+ G_OBJECT_CLASS( st_parent_class )->set_property( object, PROP_NAOBJECT_LABEL, value, spec );
break;
- case PROP_ACTION_LABEL:
- g_free( self->private->label );
- self->private->label = g_value_dup_string( value );
+ case PROP_NAACTION_VERSION:
+ g_free( self->private->version );
+ self->private->version = g_value_dup_string( value );
break;
- case PROP_ACTION_TOOLTIP:
+ case PROP_NAACTION_TOOLTIP:
g_free( self->private->tooltip );
self->private->tooltip = g_value_dup_string( value );
break;
- case PROP_ACTION_ICON:
+ case PROP_NAACTION_ICON:
g_free( self->private->icon );
self->private->icon = g_value_dup_string( value );
break;
- case PROP_ACTION_READONLY:
+ case PROP_NAACTION_READONLY:
self->private->read_only = g_value_get_boolean( value );
break;
- case PROP_ACTION_PROVIDER:
+ case PROP_NAACTION_PROVIDER:
self->private->provider = g_value_get_pointer( value );
break;
@@ -349,9 +356,7 @@ instance_finalize( GObject *object )
g_assert( NA_IS_ACTION( object ));
NAAction *self = ( NAAction * ) object;
- g_free( self->private->uuid );
g_free( self->private->version );
- g_free( self->private->label );
g_free( self->private->tooltip );
g_free( self->private->icon );
@@ -364,187 +369,123 @@ instance_finalize( GObject *object )
}
/**
- * Allocates a new NAAction object.
+ * na_action_new:
*
- * @uuid: the globally unique identifier (UUID) of the action.
- * If NULL, a new UUID is allocated for this action.
+ * Allocates a new #NAAction object.
*
- * Return a newly allocated NAAction object.
- */
-NAAction *
-na_action_new( const gchar *uuid )
-{
- NAAction *action = g_object_new( NA_ACTION_TYPE, PROP_ACTION_UUID_STR, uuid, NULL );
-
- if( !uuid || !strlen( uuid )){
- na_action_set_new_uuid( action );
- }
-
- return( action );
-}
-
-/**
- * Allocates a new NAAction object along with a default profile.
+ * The new #NAAction object is initialized with suitable default values,
+ * but without any profile.
*
- * Return a newly allocated NAAction object.
+ * Returns: the newly allocated #NAAction object.
*/
NAAction *
-na_action_new_with_profile( void )
+na_action_new( void )
{
- NAAction *action = na_action_new( NULL );
+ NAAction *action = g_object_new( NA_ACTION_TYPE, NULL );
- NAActionProfile *profile = na_action_profile_new( NA_OBJECT( action ), ACTION_PROFILE_PREFIX "zero" );
+ na_action_set_new_uuid( action );
- action->private->profiles = g_slist_prepend( action->private->profiles, profile );
+ /* i18n: default label for a new action */
+ na_action_set_label( action, _( "New Nautilus action" ));
return( action );
}
/**
- * Allocates a new NAAction object, and initializes it as an exact
- * copy of the specified action.
- *
- * @action: the action to be duplicated.
+ * na_action_new_with_profile:
*
- * Return a newly allocated NAAction object.
+ * Allocates a new #NAAction object along with a default profile.
*
- * Please note than "an exact copy" here means that the newly allocated
- * returned object has the _same_ UUID than the original one.
+ * Return: the newly allocated #NAAction action.
*/
NAAction *
-na_action_duplicate( const NAAction *action )
-{
- g_assert( NA_IS_ACTION( action ));
-
- gchar *uuid = do_get_id( NA_OBJECT( action ));
- NAAction *duplicate = g_object_new( NA_ACTION_TYPE, PROP_ACTION_UUID_STR, uuid, NULL );
- g_free( uuid );
-
- duplicate->private->version = g_strdup( action->private->version );
- duplicate->private->label = g_strdup( action->private->label );
- duplicate->private->tooltip = g_strdup( action->private->tooltip );
- duplicate->private->icon = g_strdup( action->private->icon );
- duplicate->private->read_only = action->private->read_only;
- duplicate->private->provider = action->private->provider;
-
- GSList *ip;
- for( ip = action->private->profiles ; ip ; ip = ip->next ){
- duplicate->private->profiles =
- g_slist_prepend(
- duplicate->private->profiles,
- na_action_profile_duplicate( duplicate, NA_ACTION_PROFILE( ip->data )));
- }
-
- return( duplicate );
-}
-
-static void
-do_dump( const NAObject *action )
+na_action_new_with_profile( void )
{
- static const gchar *thisfn = "na_action_do_dump";
-
- g_assert( NA_IS_ACTION( action ));
- NAAction *self = NA_ACTION( action );
-
- if( st_parent_class->dump ){
- st_parent_class->dump( action );
- }
-
- g_debug( "%s: uuid='%s'", thisfn, self->private->uuid );
- g_debug( "%s: version='%s'", thisfn, self->private->version );
- g_debug( "%s: label='%s'", thisfn, self->private->label );
- g_debug( "%s: tooltip='%s'", thisfn, self->private->tooltip );
- g_debug( "%s: icon='%s'", thisfn, self->private->icon );
- g_debug( "%s: read-only='%s'", thisfn, self->private->read_only ? "True" : "False" );
- g_debug( "%s: provider=%p", thisfn, self->private->provider );
-
- /* dump profiles */
- g_debug( "%s: %d profile(s) at %p", thisfn, na_action_get_profiles_count( self ), self->private->profiles );
- GSList *item;
- for( item = self->private->profiles ; item != NULL ; item = item->next ){
- na_object_dump(( const NAObject * ) item->data );
- }
-}
+ NAAction *action = na_action_new();
-static gchar *
-do_get_id( const NAObject *action )
-{
- g_assert( NA_IS_ACTION( action ));
+ NAActionProfile *profile = na_action_profile_new();
- gchar *uuid;
- g_object_get( G_OBJECT( action ), PROP_ACTION_UUID_STR, &uuid, NULL );
+ na_action_attach_profile( action, profile );
- return( uuid );
+ return( action );
}
/**
+ * na_action_get_uuid:
+ * @action: the #NAAction object to be requested.
+ *
* Returns the globally unique identifier (UUID) of the action.
*
- * @action: an NAAction object.
+ * Returns: the uuid of the action as a newly allocated string. This
+ * returned string must be g_free() by the caller.
*
- * The returned string must be g_freed by the caller.
+ * See na_action_set_uuid() for some rationale about uuid.
*/
gchar *
na_action_get_uuid( const NAAction *action )
{
g_assert( NA_IS_ACTION( action ));
- return( na_object_get_id( NA_OBJECT( action )));
+
+ gchar *id;
+ g_object_get( G_OBJECT( action ), PROP_NAACTION_UUID_STR, &id, NULL );
+
+ return( id );
}
/**
- * Returns the version attached to the action.
+ * na_action_get_label:
+ * @action: the #NAAction object to be requested.
*
- * @action: an NAAction object.
+ * Returns the label of the action.
*
- * The returned string must be g_freed by the caller.
+ * Returns: the label of the action as a newly allocated string. This
+ * returned string must be g_free() by the caller.
*
- * The version is always upgraded to the latest when the action is
- * readen from the I/O provider. So we could assert here that the
- * returned version is also the latest.
+ * See na_action_set_label() for some rationale about label.
*/
gchar *
-na_action_get_version( const NAAction *action )
-{
- g_assert( NA_IS_ACTION( action ));
-
- gchar *version;
- g_object_get( G_OBJECT( action ), PROP_ACTION_VERSION_STR, &version, NULL );
-
- return( version );
-}
-
-static gchar *
-do_get_label( const NAObject *action )
+na_action_get_label( const NAAction *action )
{
g_assert( NA_IS_ACTION( action ));
gchar *label;
- g_object_get( G_OBJECT( action ), PROP_ACTION_LABEL_STR, &label, NULL );
+ g_object_get( G_OBJECT( action ), PROP_NAACTION_LABEL_STR, &label, NULL );
return( label );
}
/**
- * Returns the label of the action.
+ * na_action_get_version:
+ * @action: the #NAAction object to be requested.
*
- * @action: an NAAction object.
+ * Returns the version of the description of the action, as found when
+ * reading it from the I/O storage subsystem.
*
- * The returned string must be g_freed by the caller.
+ * Returns: the version of the action as a newly allocated string. This
+ * returned string must be g_free() by the caller.
+ *
+ * See na_action_set_version() for some rationale about version.
*/
gchar *
-na_action_get_label( const NAAction *action )
+na_action_get_version( const NAAction *action )
{
g_assert( NA_IS_ACTION( action ));
- return( na_object_get_label( NA_OBJECT( action )));
+
+ gchar *version;
+ g_object_get( G_OBJECT( action ), PROP_NAACTION_VERSION_STR, &version, NULL );
+
+ return( version );
}
/**
- * Returns the tooltip attached to the context menu item for the
- * action.
+ * na_action_get_tooltip:
+ * @action: the #NAAction object to be requested.
*
- * @action: an NAAction object.
+ * Returns the tooltip which will be display in the Nautilus context
+ * menu item for this action.
*
- * The returned string must be g_freed by the caller.
+ * Returns: the tooltip of the action as a newly allocated string. This
+ * returned string must be g_free() by the caller.
*/
gchar *
na_action_get_tooltip( const NAAction *action )
@@ -552,18 +493,20 @@ na_action_get_tooltip( const NAAction *action )
g_assert( NA_IS_ACTION( action ));
gchar *tooltip;
- g_object_get( G_OBJECT( action ), PROP_ACTION_TOOLTIP_STR, &tooltip, NULL );
+ g_object_get( G_OBJECT( action ), PROP_NAACTION_TOOLTIP_STR, &tooltip, NULL );
return( tooltip );
}
/**
- * Returns the name of the icon attached to the context menu item for
- * the action.
+ * na_action_get_icon:
+ * @action: the #NAAction object to be requested.
*
- * @action: an NAAction object.
+ * Returns the name of the icon attached to the Nautilus context menu
+ * item for this action.
*
- * The returned string must be g_freed by the caller.
+ * Returns: the icon name as a newly allocated string. This returned
+ * string must be g_free() by the caller.
*/
gchar *
na_action_get_icon( const NAAction *action )
@@ -571,18 +514,13 @@ na_action_get_icon( const NAAction *action )
g_assert( NA_IS_ACTION( action ));
gchar *icon;
- g_object_get( G_OBJECT( action ), PROP_ACTION_ICON_STR, &icon, NULL );
+ g_object_get( G_OBJECT( action ), PROP_NAACTION_ICON_STR, &icon, NULL );
return( icon );
}
-/**
- * Returns the icon name attached to the context menu item for the
- * action.
- *
- * @action: an NAAction object.
- *
- * When not NULL, the returned string must be g_free by the caller.
+/*
+ * TODO: remove this function
*/
gchar *
na_action_get_verified_icon_name( const NAAction *action )
@@ -590,7 +528,7 @@ na_action_get_verified_icon_name( const NAAction *action )
g_assert( NA_IS_ACTION( action ));
gchar *icon_name;
- g_object_get( G_OBJECT( action ), PROP_ACTION_ICON_STR, &icon_name, NULL );
+ g_object_get( G_OBJECT( action ), PROP_NAACTION_ICON_STR, &icon_name, NULL );
if( icon_name[0] == '/' ){
if( !g_file_test( icon_name, G_FILE_TEST_IS_REGULAR )){
@@ -606,35 +544,55 @@ na_action_get_verified_icon_name( const NAAction *action )
}
/**
+ * na_action_is_readonly:
+ * @action: the #NAAction object to be requested.
+ *
* Is the specified action only readable ?
- * Or, in other words, may this action be edited and then saved ?
+ * Or, in other words, may this action be edited and then saved to the
+ * original I/O storage subsystem ?
*
- * @action: an NAAction object.
+ * Returns: %TRUE if the action is editable, %FALSE else.
*/
gboolean
na_action_is_readonly( const NAAction *action )
{
g_assert( NA_IS_ACTION( action ));
- return( action->private->read_only );
+
+ gboolean readonly;
+ g_object_get( G_OBJECT( action ), PROP_NAACTION_READONLY_STR, &readonly, NULL );
+
+ return( readonly );
}
/**
+ * na_action_get_provider:
+ * @action: the #NAAction object to be requested.
+ *
* Returns the initial provider of the action (or the last which has
- * accepted a write).
+ * accepted a write operation). At the time of this request, this is
+ * the most probable provider willing to accept a next writing
+ * operation.
*
- * @action: an NAAction object.
+ * Returns: a #NAIIOProvider object. The reference is
+ * owned by #NAPivot pivot and should be g_object_unref() by the
+ * caller.
*/
-gpointer
+NAIIOProvider *
na_action_get_provider( const NAAction *action )
{
g_assert( NA_IS_ACTION( action ));
- return( action->private->provider );
+
+ NAIIOProvider *provider;
+ g_object_get( G_OBJECT( action ), PROP_NAACTION_PROVIDER_STR, &provider, NULL );
+
+ return( provider );
}
/**
- * Set a new UUID for the action.
+ * na_action_set_new_uuid:
+ * @action: the #NAAction object to be updated.
*
- * @action: action whose UUID is to be set.
+ * Set a new UUID for the action.
*/
void
na_action_set_new_uuid( NAAction *action )
@@ -646,134 +604,167 @@ na_action_set_new_uuid( NAAction *action )
uuid_generate( uuid );
uuid_unparse_lower( uuid, uuid_str );
- g_object_set( G_OBJECT( action ), PROP_ACTION_UUID_STR, uuid_str, NULL );
+ g_object_set( G_OBJECT( action ), PROP_NAACTION_UUID_STR, uuid_str, NULL );
}
/**
- * Set a new uuid for the action.
+ * na_action_set_uuid:
+ * @action: the #NAAction object to be updated.
+ * @uuid: the uuid to be set.
+ *
+ * Sets a new uuid for the action.
+ *
+ * #NAAction takes a copy of the provided UUID. This later may so be
+ * g_free() by the caller after this function returns.
+ *
+ * This uuid is only required when writing the action to GConf in order
+ * easily have unique subdirectories.
*
- * @action: action whose uuid is to be set.
+ * This is an ASCII, case insensitive, string.
*
- * @uuid: new uuid.
+ * UUID is transfered through import/export operations.
+ *
+ * Note that a user may import an action, translate it and then
+ * reexport it : we so may have two different actions with the same
+ * uuid.
*/
void
na_action_set_uuid( NAAction *action, const gchar *uuid )
{
g_assert( NA_IS_ACTION( action ));
- g_object_set( G_OBJECT( action ), PROP_ACTION_UUID_STR, uuid, NULL );
+
+ g_object_set( G_OBJECT( action ), PROP_NAACTION_UUID_STR, uuid, NULL );
}
/**
- * Set a new version for the action.
+ * na_action_set_label:
+ * @action: the #NAAction object to be updated.
+ * @label: the label to be set.
+ *
+ * Sets a new label for the action.
*
- * @action: action whose version is to be set.
+ * #NAAction takes a copy of the provided label. This later may so be
+ * g_free() by the caller after this function returns.
*
- * @version: new version.
+ * The user knows its actions through their labels, as this is the main
+ * visible part (with the icon) in Nautilus context menu and in the
+ * NACT ui.
*/
void
-na_action_set_version( NAAction *action, const gchar *version )
+na_action_set_label( NAAction *action, const gchar *label )
{
g_assert( NA_IS_ACTION( action ));
- g_object_set( G_OBJECT( action ), PROP_ACTION_VERSION_STR, version, NULL );
+
+ g_object_set( G_OBJECT( action ), PROP_NAACTION_LABEL_STR, label, NULL );
}
/**
- * Set a new label for the action.
+ * na_action_set_version:
+ * @action: the #NAAction object to be updated.
+ * @label: the label to be set.
+ *
+ * Sets a new version for the action.
*
- * @action: action whose label is to be set.
+ * #NAAction takes a copy of the provided version. This later may so be
+ * g_free() by the caller after this function returns.
*
- * @label: new label.
+ * The version describes the schema of the informations in the I/O
+ * storage subsystem.
+ *
+ * Version is stored in the #NAAction object as readen from the I/O
+ * storage subsystem, even if the #NAAction object itself only reflects
+ * the lastest known version. Conversion is made at load time (cf.
+ * na_gconf_load_action()).
*/
void
-na_action_set_label( NAAction *action, const gchar *label )
+na_action_set_version( NAAction *action, const gchar *version )
{
g_assert( NA_IS_ACTION( action ));
- g_object_set( G_OBJECT( action ), PROP_ACTION_LABEL_STR, label, NULL );
+
+ g_object_set( G_OBJECT( action ), PROP_NAACTION_VERSION_STR, version, NULL );
}
/**
- * Set a new tooltip for the action.
+ * na_action_set_tooltip:
+ * @action: the #NAAction object to be updated.
+ * @tooltip: the tooltip to be set.
*
- * @action: action whose tooltip is to be set.
+ * Sets a new tooltip for the action. Tooltip will be displayed by
+ * Nautilus when the user move its mouse over the Nautilus context menu
+ * item.
*
- * @tooltip: new tooltip.
+ * #NAAction takes a copy of the provided tooltip. This later may so be
+ * g_free() by the caller after this function returns.
*/
void
na_action_set_tooltip( NAAction *action, const gchar *tooltip )
{
g_assert( NA_IS_ACTION( action ));
- g_object_set( G_OBJECT( action ), PROP_ACTION_TOOLTIP_STR, tooltip, NULL );
+
+ g_object_set( G_OBJECT( action ), PROP_NAACTION_TOOLTIP_STR, tooltip, NULL );
}
/**
- * Set a new icon for the action.
+ * na_action_set_icon:
+ * @action: the #NAAction object to be updated.
+ * @icon: the icon name to be set.
*
- * @action: action whose icon name is to be set.
+ * Sets a new icon name for the action.
*
- * @icon: new icon name.
+ * #NAAction takes a copy of the provided icon name. This later may so
+ * be g_free() by the caller after this function returns.
*/
void
na_action_set_icon( NAAction *action, const gchar *icon )
{
g_assert( NA_IS_ACTION( action ));
- g_object_set( G_OBJECT( action ), PROP_ACTION_ICON_STR, icon, NULL );
+
+ g_object_set( G_OBJECT( action ), PROP_NAACTION_ICON_STR, icon, NULL );
}
/**
- * Are the two actions the sames (excluding UUID) ?
+ * na_action_set_readonly:
+ * @action: the #NAAction object to be updated.
+ * @readonly: the indicator to be set.
*
- * @first: first action to check.
+ * Sets whether the action is readonly.
+ */
+void
+na_action_set_readonly( NAAction *action, gboolean readonly )
+{
+ g_assert( NA_IS_ACTION( action ));
+
+ g_object_set( G_OBJECT( action ), PROP_NAACTION_READONLY_STR, readonly, NULL );
+}
+
+/**
+ * na_action_set_provider:
+ * @action: the #NAAction object to be updated.
+ * @provider: the #NAIIOProvider to be set.
*
- * @second: second action to be compared to @first.
+ * Sets the I/O provider for this #NAAction.
*/
-gboolean
-na_action_are_equal( const NAAction *first, const NAAction *second )
+void
+na_action_set_provider( NAAction *action, const NAIIOProvider *provider )
{
- gboolean equal =
- ( g_utf8_collate( first->private->label, second->private->label ) == 0 ) &&
- ( g_utf8_collate( first->private->tooltip, second->private->tooltip ) == 0 ) &&
- ( g_utf8_collate( first->private->icon, second->private->icon ) == 0 );
+ g_assert( NA_IS_ACTION( action ));
- if( equal ){
- equal = ( g_slist_length( first->private->profiles ) == g_slist_length( second->private->profiles ));
- }
- if( equal ){
- GSList *ip;
- for( ip = first->private->profiles ; ip && equal ; ip = ip->next ){
- NAActionProfile *first_profile = NA_ACTION_PROFILE( ip->data );
- gchar *first_name = na_action_profile_get_name( first_profile );
- NAActionProfile *second_profile = NA_ACTION_PROFILE( na_action_get_profile( second, first_name ));
- if( second_profile ){
- equal = na_action_profile_are_equal( first_profile, second_profile );
- } else {
- equal = FALSE;
- }
- g_free( first_name );
- }
- }
- if( equal ){
- GSList *ip;
- for( ip = second->private->profiles ; ip && equal ; ip = ip->next ){
- NAActionProfile *second_profile = NA_ACTION_PROFILE( ip->data );
- gchar *second_name = na_action_profile_get_name( second_profile );
- NAActionProfile *first_profile = NA_ACTION_PROFILE( na_action_get_profile( first, second_name ));
- if( first_profile ){
- equal = na_action_profile_are_equal( first_profile, second_profile );
- } else {
- equal = FALSE;
- }
- g_free( second_name );
- }
- }
- return( equal );
+ g_object_set( G_OBJECT( action ), PROP_NAACTION_PROVIDER_STR, provider, NULL );
}
/**
+ * na_action_get_new_profile_name:
+ * @action: the #NAAction object which will receive a new profile.
+ *
* Returns a name suitable as a new profile name.
*
- * @action: the action for which we are searching a new profile name.
+ * The search is made by iterating over the standard profile name
+ * prefix : basically, we increment a counter until finding a unique
+ * name. The provided name is so only suitable for the specified
+ * @action.
*
- * Basically, we increment a counter until finding a unique name.
+ * Returns: a newly allocated profile name, which should be g_free() by
+ * the caller.
*/
gchar *
na_action_get_new_profile_name( const NAAction *action )
@@ -798,27 +789,30 @@ na_action_get_new_profile_name( const NAAction *action )
}
/**
- * Returns the profile with the required name.
+ * na_action_get_profile:
+ * @action: the #NAAction object which is to be requested.
+ * @name: the name of the searched profile.
*
- * @action: the action whose profiles has to be retrieved.
+ * Returns the required profile.
*
- * @name: name of the required profile.
+ * Returns: a pointer to the #NAActionProfile profile with the required
+ * name.
*
- * The returned pointer is owned by the @action object ; the caller
- * should not try to free or unref it.
+ * The returned #NAActionProfile is owned by the @action object ; the
+ * caller should not try to g_free() nor g_object_unref() it.
*/
-NAObject *
+NAActionProfile *
na_action_get_profile( const NAAction *action, const gchar *name )
{
g_assert( NA_IS_ACTION( action ));
- NAObject *found = NULL;
+ NAActionProfile *found = NULL;
GSList *ip;
for( ip = action->private->profiles ; ip && !found ; ip = ip->next ){
NAActionProfile *iprofile = NA_ACTION_PROFILE( ip->data );
gchar *iname = na_action_profile_get_name( iprofile );
if( !strcmp( name, iname )){
- found = NA_OBJECT( iprofile );
+ found = iprofile;
}
g_free( iname );
}
@@ -827,29 +821,48 @@ na_action_get_profile( const NAAction *action, const gchar *name )
}
/**
- * Add a profile at the end of the list of profiles.
+ * na_action_attach_profile:
+ * @action: the #NAAction action to which the profile will be attached.
+ * @profile: the #NAActionProfile profile to be attached to @action.
*
- * @action: the action.
+ * Adds a profile at the end of the list of profiles.
+ */
+void
+na_action_attach_profile( NAAction *action, NAActionProfile *profile )
+{
+ g_assert( NA_IS_ACTION( action ));
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ action->private->profiles = g_slist_append( action->private->profiles, ( gpointer ) profile );
+
+ na_action_profile_set_action( profile, action );
+}
+
+/**
+ * na_action_remove_profile:
+ * @action: the #NAAction action from which the profile will be removed.
+ * @profile: the #NAActionProfile profile to be removed from @action.
*
- * @profile: the added profile.
+ * Removes a profile from the list of profiles.
*/
void
-na_action_add_profile( NAAction *action, NAObject *profile )
+na_action_remove_profile( NAAction *action, NAActionProfile *profile )
{
g_assert( NA_IS_ACTION( action ));
g_assert( NA_IS_ACTION_PROFILE( profile ));
- action->private->profiles = g_slist_append( action->private->profiles, profile );
+ action->private->profiles = g_slist_remove( action->private->profiles, ( gconstpointer ) profile );
}
/**
- * Returns the list of profiles of the actions as a GSList of
- * NAActionProfile GObjects.
+ * na_action_get_profiles:
+ * @action: the #NAAction action whose profiles has to be retrieved.
*
- * @action: the action whose profiles has to be retrieved.
+ * Returns the list of profiles of the action.
*
- * The returned pointer is owned by the @action object ; the caller
- * should not try to free or unref it.
+ * Returns: a #GSList of #NAActionProfile objects. The returned pointer
+ * is owned by the @action object ; the caller should not try to
+ * g_free() nor g_object_unref() it.
*/
GSList *
na_action_get_profiles( const NAAction *action )
@@ -860,15 +873,16 @@ na_action_get_profiles( const NAAction *action )
}
/**
- * Set the list of the profiles for the action.
+ * na_action_set_profiles:
+ * @action: the #NAAction action whose profiles has to be set.
+ * @list: a #GSList list of #NAActionProfile objects to be installed in
+ * the @action.
*
- * @action: the action whose profiles has to be retrieved.
+ * Sets the list of the profiles for the action.
*
- * @list: a list of NAActionProfile objects to be installed in the
- * action.
- *
- * The provided list is copied to the action, and thus can then be
- * safely freed (see na_action_free_profiles) by the caller.
+ * The provided list removes and replaces the previous profiles list.
+ * This list is then copied to the action, and thus can then be safely
+ * na_action_free_profiles() by the caller.
*/
void
na_action_set_profiles( NAAction *action, GSList *list )
@@ -876,19 +890,37 @@ na_action_set_profiles( NAAction *action, GSList *list )
g_assert( NA_IS_ACTION( action ));
free_profiles( action );
+
+ GSList *ip;
+ for( ip = list ; ip ; ip = ip->next ){
+ NAObject *new_profile = na_object_duplicate( NA_OBJECT( ip->data ));
+ na_action_attach_profile( action, NA_ACTION_PROFILE( new_profile ));
+ }
+}
+
+/**
+ * na_action_free_profiles:
+ * @list: a #GSList list of #NAActionProfile objects.
+ *
+ * Frees a profiles list.
+ */
+void
+na_action_free_profiles( GSList *list )
+{
GSList *ip;
for( ip = list ; ip ; ip = ip->next ){
- action->private->profiles = g_slist_prepend(
- action->private->profiles,
- na_action_profile_duplicate( action, NA_ACTION_PROFILE( ip->data ))
- );
+ g_object_unref( NA_ACTION_PROFILE( ip->data ));
}
+ g_slist_free( list );
}
/**
+ * na_action_get_profiles_count:
+ * @action: the #NAAction action whose profiles has to be counted.
+ *
* Returns the number of profiles which are defined for the action.
*
- * @action: the action whose profiles has to be retrieved.
+ * Returns: the number of profiles defined for @action.
*/
guint
na_action_get_profiles_count( const NAAction *action )
@@ -899,26 +931,165 @@ na_action_get_profiles_count( const NAAction *action )
}
static void
-free_profiles( NAAction *action )
+object_dump( const NAObject *action )
{
+ static const gchar *thisfn = "na_action_object_dump";
+
g_assert( NA_IS_ACTION( action ));
+ NAAction *self = NA_ACTION( action );
- na_action_free_profiles( action->private->profiles );
+ if( st_parent_class->dump ){
+ st_parent_class->dump( action );
+ }
- action->private->profiles = NULL;
+ g_debug( "%s: version='%s'", thisfn, self->private->version );
+ g_debug( "%s: tooltip='%s'", thisfn, self->private->tooltip );
+ g_debug( "%s: icon='%s'", thisfn, self->private->icon );
+ g_debug( "%s: read-only='%s'", thisfn, self->private->read_only ? "True" : "False" );
+ g_debug( "%s: provider=%p", thisfn, self->private->provider );
+
+ /* dump profiles */
+ g_debug( "%s: %d profile(s) at %p", thisfn, na_action_get_profiles_count( self ), self->private->profiles );
+ GSList *item;
+ for( item = self->private->profiles ; item != NULL ; item = item->next ){
+ na_object_dump(( const NAObject * ) item->data );
+ }
+}
+
+static NAObject *
+object_duplicate( const NAObject *action )
+{
+ g_assert( NA_IS_ACTION( action ));
+
+ NAObject *duplicate = NA_OBJECT( na_action_new());
+
+ na_object_copy( duplicate, action );
+
+ return( duplicate );
}
-/**
- * Frees a profiles list.
- *
- * @list: a list of NAActionProfile objects.
- */
void
-na_action_free_profiles( GSList *list )
+object_copy( NAObject *target, const NAObject *source )
{
+ g_assert( NA_IS_ACTION( source ));
+ g_assert( NA_IS_ACTION( target ));
+
+ gchar *version, *tooltip, *icon;
+ gboolean readonly;
+ gpointer provider;
+
+ g_object_get( G_OBJECT( source ),
+ PROP_NAACTION_VERSION_STR, &version,
+ PROP_NAACTION_TOOLTIP_STR, &tooltip,
+ PROP_NAACTION_ICON_STR, &icon,
+ PROP_NAACTION_READONLY_STR, &readonly,
+ PROP_NAACTION_PROVIDER_STR, &provider,
+ NULL );
+
+ g_object_set( G_OBJECT( target ),
+ PROP_NAACTION_VERSION_STR, version,
+ PROP_NAACTION_TOOLTIP_STR, tooltip,
+ PROP_NAACTION_ICON_STR, icon,
+ PROP_NAACTION_READONLY_STR, readonly,
+ PROP_NAACTION_PROVIDER_STR, provider,
+ NULL );
+
+ g_free( tooltip );
+ g_free( version );
+
GSList *ip;
- for( ip = list ; ip ; ip = ip->next ){
- g_object_unref( NA_ACTION_PROFILE( ip->data ));
+ for( ip = NA_ACTION( source )->private->profiles ; ip ; ip = ip->next ){
+ NAActionProfile *profile = NA_ACTION_PROFILE( na_object_duplicate( NA_OBJECT( ip->data )));
+ na_action_attach_profile( NA_ACTION( target ), profile );
}
- g_slist_free( list );
+
+ if( st_parent_class->copy ){
+ st_parent_class->copy( target, source );
+ }
+}
+
+static gboolean
+object_are_equal( const NAObject *a, const NAObject *b )
+{
+ g_assert( NA_IS_ACTION( a ));
+ g_assert( NA_IS_ACTION( b ));
+
+ NAAction *first = NA_ACTION( a );
+ NAAction *second = NA_ACTION( b );
+
+ gboolean equal =
+ ( g_utf8_collate( first->private->version, second->private->version ) == 0 ) &&
+ ( g_utf8_collate( first->private->tooltip, second->private->tooltip ) == 0 ) &&
+ ( g_utf8_collate( first->private->icon, second->private->icon ) == 0 );
+
+ if( equal ){
+ equal = ( g_slist_length( first->private->profiles ) == g_slist_length( second->private->profiles ));
+ }
+ if( equal ){
+ GSList *ip;
+ for( ip = first->private->profiles ; ip && equal ; ip = ip->next ){
+ NAActionProfile *first_profile = NA_ACTION_PROFILE( ip->data );
+ gchar *first_name = na_action_profile_get_name( first_profile );
+ NAActionProfile *second_profile = NA_ACTION_PROFILE( na_action_get_profile( second, first_name ));
+ if( second_profile ){
+ equal = na_object_are_equal( NA_OBJECT( first_profile ), NA_OBJECT( second_profile ));
+ } else {
+ equal = FALSE;
+ }
+ g_free( first_name );
+ }
+ }
+ if( equal ){
+ GSList *ip;
+ for( ip = second->private->profiles ; ip && equal ; ip = ip->next ){
+ NAActionProfile *second_profile = NA_ACTION_PROFILE( ip->data );
+ gchar *second_name = na_action_profile_get_name( second_profile );
+ NAActionProfile *first_profile = NA_ACTION_PROFILE( na_action_get_profile( first, second_name ));
+ if( first_profile ){
+ equal = na_object_are_equal( NA_OBJECT( first_profile ), NA_OBJECT( second_profile ));
+ } else {
+ equal = FALSE;
+ }
+ g_free( second_name );
+ }
+ }
+ if( equal ){
+ if( st_parent_class->are_equal ){
+ equal = st_parent_class->are_equal( a, b );
+ }
+ }
+
+ return( equal );
+}
+
+gboolean
+object_is_valid( const NAObject *action )
+{
+ g_assert( NA_IS_ACTION( action ));
+
+ gchar *label;
+ g_object_get( G_OBJECT( action ), PROP_NAACTION_LABEL_STR, &label, NULL );
+ gboolean is_valid = ( label && g_utf8_strlen( label, -1 ) > 0 );
+ g_free( label );
+
+ GSList *ip;
+ for( ip = NA_ACTION( action )->private->profiles ; ip && is_valid ; ip = ip->next ){
+ is_valid = na_object_is_valid( NA_OBJECT( ip->data ));
+ }
+
+ if( is_valid ){
+ if( st_parent_class->is_valid ){
+ is_valid = st_parent_class->is_valid( action );
+ }
+ }
+
+ return( is_valid );
+}
+
+static void
+free_profiles( NAAction *action )
+{
+ na_action_free_profiles( action->private->profiles );
+
+ action->private->profiles = NULL;
}
diff --git a/src/common/na-action.h b/src/common/na-action.h
index 3a6a6fd..0996d48 100644
--- a/src/common/na-action.h
+++ b/src/common/na-action.h
@@ -31,52 +31,22 @@
#ifndef __NA_ACTION_H__
#define __NA_ACTION_H__
-/*
- * NAAction class definition.
- *
- * This is the class which maintains an action.
+/**
+ * SECTION: na_action
+ * @short_description: #NAAction class definition.
+ * @include: common/na-action.h
*
- * NAAction class is derived from NAObject.
+ * This is the class which maintains data and properties of an Nautilus
+ * action.
*/
-#include "na-object.h"
-#include "na-pivot.h"
+#include "na-action-class.h"
+#include "na-action-profile-class.h"
+#include "na-iio-provider.h"
G_BEGIN_DECLS
-#define NA_ACTION_TYPE ( na_action_get_type())
-#define NA_ACTION( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_ACTION_TYPE, NAAction ))
-#define NA_ACTION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_ACTION_TYPE, NAActionClass ))
-#define NA_IS_ACTION( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_ACTION_TYPE ))
-#define NA_IS_ACTION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_ACTION_TYPE ))
-#define NA_ACTION_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_ACTION_TYPE, NAActionClass ))
-
-typedef struct NAActionPrivate NAActionPrivate;
-
-typedef struct {
- NAObject parent;
- NAActionPrivate *private;
-}
- NAAction;
-
-typedef struct NAActionClassPrivate NAActionClassPrivate;
-
-typedef struct {
- NAObjectClass parent;
- NAActionClassPrivate *private;
-}
- NAActionClass;
-
-/* instance properties
- */
-#define PROP_ACTION_UUID_STR "action-uuid"
-#define PROP_ACTION_VERSION_STR "action-version"
-#define PROP_ACTION_LABEL_STR "action-label"
-#define PROP_ACTION_TOOLTIP_STR "action-tooltip"
-#define PROP_ACTION_ICON_STR "action-icon"
-#define PROP_ACTION_READONLY_STR "action-read-only"
-#define PROP_ACTION_PROVIDER_STR "action-provider"
-
+/* TODO: move this declaration elsewhere */
/* export formats
* used to be only GConf schemas ('gconfschemafile' XML document)
*/
@@ -84,38 +54,35 @@ enum {
EXPORT_FORMAT_GCONFSCHEMAFILE = 1
};
-GType na_action_get_type( void );
-
-NAAction *na_action_new( const gchar *uuid );
-NAAction *na_action_new_with_profile( void );
-NAAction *na_action_duplicate( const NAAction *action );
-
-gchar *na_action_get_uuid( const NAAction *action );
-gchar *na_action_get_version( const NAAction *action );
-gchar *na_action_get_label( const NAAction *action );
-gchar *na_action_get_tooltip( const NAAction *action );
-gchar *na_action_get_icon( const NAAction *action );
-gchar *na_action_get_verified_icon_name( const NAAction *action );
-gboolean na_action_is_readonly( const NAAction *action );
-gpointer na_action_get_provider( const NAAction *action );
-
-void na_action_set_new_uuid( NAAction *action );
-void na_action_set_uuid( NAAction *action, const gchar *uuid );
-void na_action_set_version( NAAction *action, const gchar *version );
-void na_action_set_label( NAAction *action, const gchar *label );
-void na_action_set_tooltip( NAAction *action, const gchar *tooltip );
-void na_action_set_icon( NAAction *action, const gchar *icon_name );
-
-gboolean na_action_are_equal( const NAAction *first, const NAAction *second );
-
-gchar *na_action_get_new_profile_name( const NAAction *action );
-NAObject *na_action_get_profile( const NAAction *action, const gchar *name );
-GSList *na_action_get_profiles( const NAAction *action );
-void na_action_add_profile( NAAction *action, NAObject *profile );
-void na_action_set_profiles( NAAction *action, GSList *list );
-void na_action_free_profiles( GSList *list );
-
-guint na_action_get_profiles_count( const NAAction *action );
+NAAction *na_action_new( void );
+NAAction *na_action_new_with_profile( void );
+
+gchar *na_action_get_uuid( const NAAction *action );
+gchar *na_action_get_label( const NAAction *action );
+gchar *na_action_get_version( const NAAction *action );
+gchar *na_action_get_tooltip( const NAAction *action );
+gchar *na_action_get_icon( const NAAction *action );
+gchar *na_action_get_verified_icon_name( const NAAction *action );
+gboolean na_action_is_readonly( const NAAction *action );
+NAIIOProvider *na_action_get_provider( const NAAction *action );
+
+void na_action_set_new_uuid( NAAction *action );
+void na_action_set_uuid( NAAction *action, const gchar *uuid );
+void na_action_set_label( NAAction *action, const gchar *label );
+void na_action_set_version( NAAction *action, const gchar *version );
+void na_action_set_tooltip( NAAction *action, const gchar *tooltip );
+void na_action_set_icon( NAAction *action, const gchar *icon_name );
+void na_action_set_readonly( NAAction *action, gboolean readonly );
+void na_action_set_provider( NAAction *action, const NAIIOProvider *provider );
+
+gchar *na_action_get_new_profile_name( const NAAction *action );
+NAActionProfile *na_action_get_profile( const NAAction *action, const gchar *name );
+GSList *na_action_get_profiles( const NAAction *action );
+void na_action_attach_profile( NAAction *action, NAActionProfile *profile );
+void na_action_remove_profile( NAAction *action, NAActionProfile *profile );
+void na_action_set_profiles( NAAction *action, GSList *list );
+void na_action_free_profiles( GSList *list );
+guint na_action_get_profiles_count( const NAAction *action );
G_END_DECLS
diff --git a/src/common/na-gconf.c b/src/common/na-gconf.c
index 7029d2a..ef8b283 100644
--- a/src/common/na-gconf.c
+++ b/src/common/na-gconf.c
@@ -32,10 +32,10 @@
#include <config.h>
#endif
-#include <string.h>
-
#include <gconf/gconf.h>
#include <gconf/gconf-client.h>
+#include <glib/gi18n.h>
+#include <string.h>
#include "na-action.h"
#include "na-action-profile.h"
@@ -53,45 +53,49 @@ struct NAGConfClassPrivate {
*/
struct NAGConfPrivate {
gboolean dispose_has_run;
-
GConfClient *gconf;
-
- /* instance to be notified of an action modification
- */
gpointer notified;
- guint notify_id;
+ guint watch_id;
};
/* private instance properties
*/
enum {
- PROP_NOTIFIED = 1
+ PROP_NAGCONF_GCONF = 1,
+ PROP_NAGCONF_NOTIFIED,
+ PROP_NAGCONF_WATCH_ID
};
-#define PROP_NOTIFIED_STR "to-be-notified"
+#define PROP_NAGCONF_GCONF_STR "na-gconf-client"
+#define PROP_NAGCONF_NOTIFIED_STR "na-gconf-to-be-notified"
+#define PROP_NAGCONF_WATCH_ID_STR "na-gconf-watch-id"
/* correspondance table for association of GConf entry keys to action
* and profile properties
*/
-typedef struct {
+/*typedef struct {
gchar *gconfkey;
gchar *property;
}
KeyToPropertyStruct;
static KeyToPropertyStruct st_key_property[] = {
- { ACTION_PROFILE_LABEL_ENTRY, PROP_PROFILE_LABEL_STR },
- { ACTION_PATH_ENTRY , PROP_PROFILE_PATH_STR },
- { ACTION_PARAMETERS_ENTRY , PROP_PROFILE_PARAMETERS_STR },
- { ACTION_BASENAMES_ENTRY , PROP_PROFILE_BASENAMES_STR },
- { ACTION_MATCHCASE_ENTRY , PROP_PROFILE_MATCHCASE_STR },
- { ACTION_MIMETYPES_ENTRY , PROP_PROFILE_MIMETYPES_STR },
- { ACTION_ISFILE_ENTRY , PROP_PROFILE_ISFILE_STR },
- { ACTION_ISDIR_ENTRY , PROP_PROFILE_ISDIR_STR },
- { ACTION_MULTIPLE_ENTRY , PROP_PROFILE_ACCEPT_MULTIPLE_STR },
- { ACTION_SCHEMES_ENTRY , PROP_PROFILE_SCHEMES_STR },
+ { ACTION_VERSION_ENTRY , PROP_NAACTION_VERSION_STR },
+ { ACTION_LABEL_ENTRY , PROP_NAACTION_LABEL_STR },
+ { ACTION_TOOLTIP_ENTRY , PROP_NAACTION_TOOLTIP_STR },
+ { ACTION_ICON_ENTRY , PROP_NAACTION_ICON_STR },
+ { ACTION_PROFILE_LABEL_ENTRY, PROP_NAPROFILE_LABEL_STR },
+ { ACTION_PATH_ENTRY , PROP_NAPROFILE_PATH_STR },
+ { ACTION_PARAMETERS_ENTRY , PROP_NAPROFILE_PARAMETERS_STR },
+ { ACTION_BASENAMES_ENTRY , PROP_NAPROFILE_BASENAMES_STR },
+ { ACTION_MATCHCASE_ENTRY , PROP_NAPROFILE_MATCHCASE_STR },
+ { ACTION_MIMETYPES_ENTRY , PROP_NAPROFILE_MIMETYPES_STR },
+ { ACTION_ISFILE_ENTRY , PROP_NAPROFILE_ISFILE_STR },
+ { ACTION_ISDIR_ENTRY , PROP_NAPROFILE_ISDIR_STR },
+ { ACTION_MULTIPLE_ENTRY , PROP_NAPROFILE_ACCEPT_MULTIPLE_STR },
+ { ACTION_SCHEMES_ENTRY , PROP_NAPROFILE_SCHEMES_STR },
{ NULL, NULL }
-};
+};*/
static GObjectClass *st_parent_class = NULL;
@@ -104,15 +108,35 @@ static void instance_set_property( GObject *object, guint property_id,
static void instance_dispose( GObject *object );
static void instance_finalize( GObject *object );
-static GSList *do_read_actions( NAIIOProvider *provider );
-static gboolean load_action( NAGConf *gconf, NAAction *action, const gchar *uuid );
-/*static void load_action_properties( NAGConf *gconf, NAAction *action );*/
+static GSList *iio_provider_read_actions( const NAIIOProvider *provider );
+static gboolean iio_provider_is_willing_to_write( const NAIIOProvider *provider );
+static gboolean iio_provider_is_writable( const NAIIOProvider *provider, const NAAction *action );
+static guint iio_provider_write_action( const NAIIOProvider *provider, NAAction *action, gchar **message );
+static guint iio_provider_delete_action( const NAIIOProvider *provider, const NAAction *action, gchar **message );
+
+static gboolean read_action( NAGConf *gconf, NAAction *action, const gchar *path );
+static gboolean read_profile( NAGConf *gconf, NAActionProfile *profile, const gchar *path );
+static gboolean fill_action_core_properties( NAGConf *gconf, NAAction *action, GSList *notifies );
+static void fill_action_v1_properties( NAGConf *gconf, NAAction *action, GSList *notifies );
+static void fill_profile_properties( NAGConf *gconf, NAActionProfile *profile, GSList *notifies );
+
+static GSList *get_path_subdirs( const NAGConf *gconf, const gchar *path );
+static GSList *get_list_entries( const NAGConf *gconf, const gchar *path );
+static void free_list_entries( GSList *entries );
+static gchar *path_to_key( const gchar *path );
+static NAPivotNotify *entry_to_notify( const GConfEntry *entry );
+static GSList *entries_to_notifies( GSList *entries );
+static void free_list_notifies( GSList *notifies );
+static gboolean search_for_str( GSList *notifies, const gchar *profile, const gchar *key, gchar **value );
+static gboolean search_for_bool( GSList *notifies, const gchar *profile, const gchar *key, gboolean *value );
+static gboolean search_for_list( GSList *notifies, const gchar *profile, const gchar *key, GSList **value );
+
+/*static gboolean load_action( NAGConf *gconf, NAAction *action, const gchar *path );
+static void load_action_properties( NAGConf *gconf, NAAction *action );
static GSList *load_profiles( NAGConf *gconf, NAAction *action );
static void load_profile_properties( NAGConf *gconf, NAActionProfile *profile );
-static GSList *load_subdirs( const NAGConf *gconf, const gchar *path );
static GSList *load_keys_values( const NAGConf *gconf, const gchar *path );
static void free_keys_values( GSList *entries );
-static gchar *path_to_key( const gchar *path );
static void set_item_properties( NAObject *object, GSList *properties );
static const gchar *key_to_property( const gchar *key );
static gboolean set_action_properties( NAGConf *gconf, NAAction *action, GSList *properties );
@@ -121,16 +145,10 @@ static gchar *search_for_str( GSList *properties, const gchar *profile,
static gboolean search_for_bool( GSList *properties, const gchar *profile, const gchar *key );
static GSList *search_for_list( GSList *properties, const gchar *profile, const gchar *key );
static GSList *keys_to_notify( GSList *entries );
-static NAPivotNotify *entry_to_notify( const GConfEntry *entry );
static void free_list_notify( GSList *list );
static gboolean remove_v1_keys( NAGConf *gconf, const NAAction *action, gchar **message );
-static gboolean remove_key( NAGConf *gconf, const gchar *uuid, const gchar *key, gchar **message );
+static gboolean remove_key( NAGConf *gconf, const gchar *uuid, const gchar *key, gchar **message );*/
-static gboolean do_is_writable( NAIIOProvider *provider );
-static gboolean do_is_willing_to_write( NAIIOProvider *provider, const GObject *action );
-
-static guint do_write_action( NAIIOProvider *provider, const GObject *action, gchar **message );
-static guint do_delete_action( NAIIOProvider *provider, const GObject *action, gchar **message );
static gboolean key_is_writable( NAGConf *gconf, const gchar *path );
static gboolean write_v2_keys( NAGConf *gconf, const NAAction *action, gchar **message );
static gboolean write_str( NAGConf *gconf, const gchar *uuid, const gchar *key, gchar *value, gchar **message );
@@ -160,6 +178,9 @@ na_gconf_get_type( void )
static GType
register_type( void )
{
+ static const gchar *thisfn = "na_gconf_register_type";
+ g_debug( "%s", thisfn );
+
static GTypeInfo info = {
sizeof( NAGConfClass ),
NULL,
@@ -174,6 +195,8 @@ register_type( void )
GType type = g_type_register_static( G_TYPE_OBJECT, "NAGConf", &info, 0 );
+ /* implements IIOProvider interface
+ */
static const GInterfaceInfo iio_provider_iface_info = {
( GInterfaceInitFunc ) iio_provider_iface_init,
NULL,
@@ -201,11 +224,25 @@ class_init( NAGConfClass *klass )
GParamSpec *spec;
spec = g_param_spec_pointer(
- PROP_NOTIFIED_STR,
- PROP_NOTIFIED_STR,
+ PROP_NAGCONF_GCONF_STR,
+ "GConfClient object",
+ "A pointer to the GConfClient object",
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, PROP_NAGCONF_GCONF, spec );
+
+ spec = g_param_spec_pointer(
+ PROP_NAGCONF_NOTIFIED_STR,
+ "Object to be notified",
"A pointer to a GObject which will receive action_changed notifications",
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NOTIFIED, spec );
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, PROP_NAGCONF_NOTIFIED, spec );
+
+ spec = g_param_spec_uint(
+ PROP_NAGCONF_WATCH_ID_STR,
+ "Watch ID",
+ "The unique ID got when installing the watch monitor on GConf", 0, 0, 0,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, PROP_NAGCONF_WATCH_ID, spec );
klass->private = g_new0( NAGConfClassPrivate, 1 );
}
@@ -216,11 +253,11 @@ iio_provider_iface_init( NAIIOProviderInterface *iface )
static const gchar *thisfn = "na_gconf_iio_provider_iface_init";
g_debug( "%s: iface=%p", thisfn, iface );
- iface->read_actions = do_read_actions;
- iface->is_writable = do_is_writable;
- iface->is_willing_to_write = do_is_willing_to_write;
- iface->write_action = do_write_action;
- iface->delete_action = do_delete_action;
+ iface->read_actions = iio_provider_read_actions;
+ iface->is_willing_to_write = iio_provider_is_willing_to_write;
+ iface->is_writable = iio_provider_is_writable;
+ iface->write_action = iio_provider_write_action;
+ iface->delete_action = iio_provider_delete_action;
}
static void
@@ -236,7 +273,7 @@ instance_init( GTypeInstance *instance, gpointer klass )
self->private->dispose_has_run = FALSE;
self->private->gconf = gconf_client_get_default();
- self->private->notify_id = install_gconf_watch( self );
+ self->private->watch_id = install_gconf_watch( self );
}
static void
@@ -246,10 +283,18 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
NAGConf *self = NA_GCONF( object );
switch( property_id ){
- case PROP_NOTIFIED:
+ case PROP_NAGCONF_GCONF:
+ g_value_set_pointer( value, self->private->gconf );
+ break;
+
+ case PROP_NAGCONF_NOTIFIED:
g_value_set_pointer( value, self->private->notified );
break;
+ case PROP_NAGCONF_WATCH_ID:
+ g_value_set_uint( value, self->private->watch_id );
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
break;
@@ -263,10 +308,18 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
NAGConf *self = NA_GCONF( object );
switch( property_id ){
- case PROP_NOTIFIED:
+ case PROP_NAGCONF_GCONF:
+ self->private->gconf = g_value_get_pointer( value );
+ break;
+
+ case PROP_NAGCONF_NOTIFIED:
self->private->notified = g_value_get_pointer( value );
break;
+ case PROP_NAGCONF_WATCH_ID:
+ self->private->watch_id = g_value_get_uint( value );
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
break;
@@ -307,36 +360,32 @@ instance_finalize( GObject *object )
}
/**
- * Allocate a new GConf object.
+ * na_gconf_new:
+ * @handler: a #GObject-derived object which is to be notified when an
+ * action is added, modified or removed in underlying GConf system.
*
- * @handler: the GObject which is to be notified when an action is
- * added, modified or removed in underlying GConf system.
+ * Allocates a new #NAGConf object.
*
- * The object to be notified will receive a
- * "notify_pivot_of_action_changed" message for each detected
- * modification, with a pointer to a newly allocated NAPivotNotify
+ * Is specified, the #GObject-derived object to be notified will
+ * receive a "notify_pivot_of_action_changed" message for each detected
+ * modification, with a pointer to a newly allocated #NAPivotNotify
* structure describing the change.
*/
NAGConf *
na_gconf_new( const GObject *handler )
{
- return( g_object_new( NA_GCONF_TYPE, PROP_NOTIFIED_STR, handler, NULL ));
+ return( g_object_new( NA_GCONF_TYPE, PROP_NAGCONF_NOTIFIED_STR, handler, NULL ));
}
/*
- * NAIIOProviderInterface implementation
- * load the list of actions and returns them as a GSList
- *
- * @provider: this NAGconf object, seen here as a I/O provider.
- *
- * Note that whatever be the version of the readen action, we convert
- * it now to the latest available, possibly updating the GConf storage
- * subsystem.
+ * Note that whatever be the version of the readen action, it will be
+ * stored as a #NAAction and its set of #NAActionProfile of the same,
+ * latest, version of these classes.
*/
static GSList *
-do_read_actions( NAIIOProvider *provider )
+iio_provider_read_actions( const NAIIOProvider *provider )
{
- static const gchar *thisfn = "nacf_gconf_do_read_actions";
+ static const gchar *thisfn = "nacf_gconf_iio_provider_read_actions";
g_debug( "%s: provider=%p", thisfn, provider );
g_assert( NA_IS_IIO_PROVIDER( provider ));
@@ -345,22 +394,33 @@ do_read_actions( NAIIOProvider *provider )
GSList *items = NULL;
GSList *ip;
- GSList *listpath = load_subdirs( self, NA_GCONF_CONFIG_PATH );
+ GSList *listpath = get_path_subdirs( self, NA_GCONF_CONFIG_PATH );
for( ip = listpath ; ip ; ip = ip->next ){
- gchar *key = path_to_key(( const gchar * ) ip->data );
+ const gchar *path = ( const gchar * ) ip->data;
- NAAction *action = na_action_new( key );
+ NAAction *action = na_action_new();
- if( load_action( self, action, key )){
+ if( read_action( self, action, path )){
items = g_slist_prepend( items, action );
} else {
g_object_unref( action );
}
- g_free( key );
+ /*gchar *uuid = path_to_key( path );
+
+ NAAction *action = na_action_new( uuid );
+
+ if( load_action( self, action, path )){
+ items = g_slist_prepend( items, action );
+
+ } else {
+ g_object_unref( action );
+ }
+
+ g_free( uuid );*/
}
na_utils_free_string_list( listpath );
@@ -368,6 +428,81 @@ do_read_actions( NAIIOProvider *provider )
return( items );
}
+static gboolean
+iio_provider_is_willing_to_write( const NAIIOProvider *provider )
+{
+ /* TODO: na_gconf_iio_provider_is_willing_to_write */
+ return( TRUE );
+}
+
+static gboolean
+iio_provider_is_writable( const NAIIOProvider *provider, const NAAction *action )
+{
+ /* TODO: na_gconf_iio_provider_is_writable */
+ return( TRUE );
+}
+
+static guint
+iio_provider_write_action( const NAIIOProvider *provider, NAAction *action, gchar **message )
+{
+ static const gchar *thisfn = "na_gconf_iio_provider_write_action";
+ g_debug( "%s: provider=%p, action=%p, message=%p", thisfn, provider, action, message );
+
+ g_assert( NA_IS_IIO_PROVIDER( provider ));
+ g_assert( NA_IS_GCONF( provider ));
+ NAGConf *self = NA_GCONF( provider );
+
+ message = NULL;
+
+ g_assert( NA_IS_ACTION( action ));
+
+ if( !write_v2_keys( self, action, message )){
+ return( NA_IIO_PROVIDER_WRITE_ERROR );
+
+ } else {
+ gconf_client_suggest_sync( self->private->gconf, NULL );
+ }
+
+ na_action_set_provider( action, provider );
+
+ return( NA_IIO_PROVIDER_WRITE_OK );
+}
+
+static guint
+iio_provider_delete_action( const NAIIOProvider *provider, const NAAction *action, gchar **message )
+{
+ static const gchar *thisfn = "na_gconf_iio_provider_delete_action";
+ g_debug( "%s: provider=%p, action=%p, message=%p", thisfn, provider, action, message );
+
+ g_assert( NA_IS_IIO_PROVIDER( provider ));
+ g_assert( NA_IS_GCONF( provider ));
+ NAGConf *self = NA_GCONF( provider );
+
+ message = NULL;
+ guint ret = NA_IIO_PROVIDER_WRITE_OK;
+
+ g_assert( NA_IS_ACTION( action ));
+
+ gchar *uuid = na_action_get_uuid( action );
+ gchar *path = g_strdup_printf( "%s/%s", NA_GCONF_CONFIG_PATH, uuid );
+ GError *error = NULL;
+
+ if( !gconf_client_recursive_unset( self->private->gconf, path, 0, &error )){
+ g_debug( "%s: error=%s", thisfn, error->message );
+ *message = g_strdup( error->message );
+ g_error_free( error );
+ ret = NA_IIO_PROVIDER_WRITE_ERROR;
+
+ } else {
+ gconf_client_suggest_sync( self->private->gconf, NULL );
+ g_debug( "%s: ok for %s", thisfn, path );
+ }
+
+ g_free( path );
+ g_free( uuid );
+ return( ret );
+}
+
/*
* load and set the properties of the specified action
* at least we must have a label, as all other entries can have
@@ -385,8 +520,8 @@ do_read_actions( NAIIOProvider *provider )
* - version = '2.0' which introduces the 'profile' notion
* profile += name+label
*/
-static gboolean
-load_action( NAGConf *gconf, NAAction *action, const gchar *uuid )
+/*static gboolean
+load_action( NAGConf *gconf, NAAction *action, const gchar *path )
{
static const gchar *thisfn = "nacf_gconf_load_action";
g_debug( "%s: gconf=%p, action=%p, uuid=%s", thisfn, gconf, action, uuid );
@@ -403,12 +538,445 @@ load_action( NAGConf *gconf, NAAction *action, const gchar *uuid )
gboolean ok = set_action_properties( gconf, action, properties );
if( !key_is_writable( gconf, path )){
- g_object_set( G_OBJECT( action ), PROP_ACTION_READONLY_STR, TRUE, NULL );
+ g_object_set( G_OBJECT( action ), PROP_NAGCONF_ACTION_READONLY_STR, TRUE, NULL );
}
free_list_notify( properties );
g_free( path );
return( ok );
+}*/
+static gboolean
+read_action( NAGConf *gconf, NAAction *action, const gchar *path )
+{
+ static const gchar *thisfn = "nacf_gconf_read_action";
+ g_debug( "%s: gconf=%p, action=%p, path=%s", thisfn, gconf, action, path );
+
+ g_assert( NA_IS_GCONF( gconf ));
+ g_assert( NA_IS_ACTION( action ));
+
+ gchar *uuid = path_to_key( path );
+ na_action_set_uuid( action, uuid );
+ g_free( uuid );
+
+ GSList *entries = get_list_entries( gconf, path );
+ GSList *notifies = entries_to_notifies( entries );
+ free_list_entries( entries );
+
+ gboolean ok = fill_action_core_properties( gconf, action, notifies );
+
+ GSList *ip;
+ GSList *list_profiles = get_path_subdirs( gconf, path );
+ if( list_profiles ){
+ for( ip = list_profiles ; ip ; ip = ip->next ){
+
+ const gchar *profile_path = ( const gchar * ) ip->data;
+ NAActionProfile *profile = na_action_profile_new();
+
+ if( read_profile( gconf, profile, profile_path )){
+ na_action_attach_profile( action, profile );
+
+ } else {
+ g_object_unref( profile );
+ }
+ }
+
+ } else {
+ fill_action_v1_properties( gconf, action, notifies );
+ }
+
+ free_list_notifies( notifies );
+
+ na_action_set_readonly( action, !key_is_writable( gconf, path ));
+
+ return( ok );
+}
+
+static gboolean
+read_profile( NAGConf *gconf, NAActionProfile *profile, const gchar *path )
+{
+ static const gchar *thisfn = "nacf_gconf_read_profile";
+ g_debug( "%s: gconf=%p, profile=%p, path=%s", thisfn, gconf, profile, path );
+
+ g_assert( NA_IS_GCONF( gconf ));
+ g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+ gchar *name = path_to_key( path );
+ na_action_profile_set_name( profile, name );
+ g_free( name );
+
+ GSList *entries = get_list_entries( gconf, path );
+ GSList *notifies = entries_to_notifies( entries );
+ free_list_entries( entries );
+
+ fill_profile_properties( gconf, profile, notifies );
+
+ free_list_notifies( notifies );
+
+ return( TRUE );
+}
+
+/*
+ * set the item properties into the action, dealing with successive
+ * versions
+ */
+static gboolean
+fill_action_core_properties( NAGConf *gconf, NAAction *action, GSList *notifies )
+{
+ static const gchar *thisfn = "na_gconf_fill_action_properties";
+
+ gchar *label;
+ if( !search_for_str( notifies, NULL, ACTION_LABEL_ENTRY, &label )){
+ gchar *uuid = na_action_get_uuid( action );
+ g_warning( "%s: no label found for action '%s'", thisfn, uuid );
+ g_free( uuid );
+ return( FALSE );
+ }
+ na_action_set_label( action, label );
+ g_free( label );
+
+ gchar *version;
+ if( search_for_str( notifies, NULL, ACTION_VERSION_ENTRY, &version )){
+ na_action_set_version( action, version );
+ g_free( version );
+ }
+
+ gchar *tooltip;
+ if( search_for_str( notifies, NULL, ACTION_TOOLTIP_ENTRY, &tooltip )){
+ na_action_set_tooltip( action, tooltip );
+ g_free( tooltip );
+ }
+
+ gchar *icon;
+ if( search_for_str( notifies, NULL, ACTION_ICON_ENTRY, &icon )){
+ na_action_set_icon( action, icon );
+ g_free( icon );
+ }
+
+ return( TRUE );
+}
+
+/*
+ * version is marked as less than "2.0"
+ * we handle so only one profile, which is already loaded
+ * action+= path+parameters+basenames+isdir+isfile+multiple+schemes
+ * if version greater than "1.0", we have also matchcase+mimetypes
+ */
+static void
+fill_action_v1_properties( NAGConf *gconf, NAAction *action, GSList *notifies )
+{
+ NAActionProfile *profile = na_action_profile_new();
+
+ na_action_attach_profile( action, profile );
+
+ fill_profile_properties( gconf, profile, notifies );
+}
+
+static void
+fill_profile_properties( NAGConf *gconf, NAActionProfile *profile, GSList *notifies )
+{
+ gchar *label;
+ if( !search_for_str( notifies, NULL, ACTION_PROFILE_LABEL_ENTRY, &label )){
+ /* i18n: default profile label */
+ label = g_strdup( _( "Default profile" ));
+ }
+ na_action_profile_set_label( profile, label );
+ g_free( label );
+
+ gchar *path;
+ if( search_for_str( notifies, NULL, ACTION_PATH_ENTRY, &path )){
+ na_action_profile_set_path( profile, path );
+ g_free( path );
+ }
+
+ gchar *parameters;
+ if( search_for_str( notifies, NULL, ACTION_PARAMETERS_ENTRY, ¶meters )){
+ na_action_profile_set_parameters( profile, parameters );
+ g_free( parameters );
+ }
+
+ GSList *basenames;
+ if( search_for_list( notifies, NULL, ACTION_BASENAMES_ENTRY, &basenames )){
+ na_action_profile_set_basenames( profile, basenames );
+ na_utils_free_string_list( basenames );
+ }
+
+ gboolean isfile;
+ if( search_for_bool( notifies, NULL, ACTION_ISFILE_ENTRY, &isfile )){
+ na_action_profile_set_isfile( profile, isfile );
+ }
+
+ gboolean isdir;
+ if( search_for_bool( notifies, NULL, ACTION_ISDIR_ENTRY, &isdir )){
+ na_action_profile_set_isdir( profile, isdir );
+ }
+
+ gboolean multiple;
+ if( search_for_bool( notifies, NULL, ACTION_MULTIPLE_ENTRY, &multiple )){
+ na_action_profile_set_multiple( profile, multiple );
+ }
+
+ GSList *schemes;
+ if( search_for_list( notifies, NULL, ACTION_SCHEMES_ENTRY, &schemes )){
+ na_action_profile_set_schemes( profile, schemes );
+ na_utils_free_string_list( schemes );
+ }
+
+ /* handle matchcase+mimetypes
+ * note that default values for 1.0 version have been set
+ * in na_action_profile_instance_init
+ */
+ gboolean matchcase;
+ if( search_for_bool( notifies, NULL, ACTION_MATCHCASE_ENTRY, &matchcase )){
+ na_action_profile_set_matchcase( profile, matchcase );
+ }
+
+ GSList *mimetypes;
+ if( search_for_list( notifies, NULL, ACTION_MIMETYPES_ENTRY, &mimetypes )){
+ na_action_profile_set_mimetypes( profile, mimetypes );
+ na_utils_free_string_list( mimetypes );
+ }
+}
+
+/*
+ * load the keys which are the subdirs of the given path
+ * returns a list of keys as full path
+ */
+/*static GSList *
+load_subdirs( const NAGConf *gconf, const gchar *path )
+{
+ static const gchar *thisfn = "na_gconf_load_subdirs";
+
+ GError *error = NULL;
+ GSList *list = gconf_client_all_dirs( gconf->private->gconf, path, &error );
+ if( error ){
+ g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+ g_error_free( error );
+ return(( GSList * ) NULL );
+ }
+
+ return( list );
+}*/
+static GSList *
+get_path_subdirs( const NAGConf *gconf, const gchar *path )
+{
+ static const gchar *thisfn = "na_gconf_get_path_subdirs";
+
+ GError *error = NULL;
+ GSList *list = gconf_client_all_dirs( gconf->private->gconf, path, &error );
+ if( error ){
+ g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+ g_error_free( error );
+ return(( GSList * ) NULL );
+ }
+
+ return( list );
+}
+
+/*
+ * load all the key=value pairs of this key (specified as a full path),
+ * returning them as a list of GConfEntry.
+ *
+ * The list is not recursive, it contains only the immediate children of
+ * path. To free the returned list, call free_list_entries().
+ */
+static GSList *
+get_list_entries( const NAGConf *gconf, const gchar *path )
+{
+ static const gchar *thisfn = "na_gconf_get_list_values";
+
+ GError *error = NULL;
+ GSList *list_path = gconf_client_all_entries( gconf->private->gconf, path, &error );
+ if( error ){
+ g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+ g_error_free( error );
+ return(( GSList * ) NULL );
+ }
+
+ return( list_path );
+}
+
+static void
+free_list_entries( GSList *list )
+{
+ GSList *item;
+ for( item = list ; item != NULL ; item = item->next ){
+ GConfEntry *entry = ( GConfEntry * ) item->data;
+ gconf_entry_unref( entry );
+ }
+ g_slist_free( list );
+}
+
+/*
+ * extract the key part (the last part) of a full path
+ * returns a newly allocated string which must be g_free() by the caller
+ */
+static gchar *
+path_to_key( const gchar *path )
+{
+ gchar **split = g_strsplit( path, "/", -1 );
+ guint count = g_strv_length( split );
+ gchar *key = g_strdup( split[count-1] );
+ g_strfreev( split );
+ return( key );
+}
+
+/*
+ * convert a GConfEntry to a structure suitable to notify NAPivot
+ *
+ * when created or modified, the entry can be of the forms :
+ * key=path/uuid/parm
+ * key=path/uuid/profile/parm with a not null value
+ *
+ * but when removing an entry, it will be of the form :
+ * key=path/uuid
+ * key=path/uuid/parm
+ * key=path/uuid/profile
+ * key=path/uuid/profile/parm with a null value
+ *
+ * I don't know any way to choose between key/parm and key/profile (*)
+ * as the entry no more exists in GConf and thus cannot be tested
+ * -> we will set this as key/parm, letting pivot try to interpret it
+ *
+ * (*) other than assuming that a profile name begins with 'profile-'
+ * (see action-profile.h)
+ */
+static NAPivotNotify *
+entry_to_notify( const GConfEntry *entry )
+{
+ /*static const gchar *thisfn = "na_gconf_entry_to_notify";*/
+ GSList *listvalues, *iv, *strings;
+
+ g_assert( entry );
+
+ const gchar *path = gconf_entry_get_key( entry );
+ g_assert( path );
+
+ NAPivotNotify *npn = g_new0( NAPivotNotify, 1 );
+
+ const gchar *subpath = path + strlen( NA_GCONF_CONFIG_PATH ) + 1;
+ gchar **split = g_strsplit( subpath, "/", -1 );
+ /*g_debug( "%s: [0]=%s, [1]=%s", thisfn, split[0], split[1] );*/
+ npn->uuid = g_strdup( split[0] );
+ if( g_strv_length( split ) == 2 ){
+ npn->parm = g_strdup( split[1] );
+ } else if( g_strv_length( split ) == 3 ){
+ npn->profile = g_strdup( split[1] );
+ npn->parm = g_strdup( split[2] );
+ }
+ g_strfreev( split );
+
+ const GConfValue *value = gconf_entry_get_value( entry );
+ if( value ){
+ switch( value->type ){
+
+ case GCONF_VALUE_STRING:
+ npn->type = NA_PIVOT_STR;
+ npn->data = ( gpointer ) g_strdup( gconf_value_get_string( value ));
+ break;
+
+ case GCONF_VALUE_BOOL:
+ npn->type = NA_PIVOT_BOOL;
+ npn->data = ( gpointer ) gconf_value_get_bool( value );
+ break;
+
+ case GCONF_VALUE_LIST:
+ listvalues = gconf_value_get_list( value );
+ strings = NULL;
+ for( iv = listvalues ; iv != NULL ; iv = iv->next ){
+ strings = g_slist_prepend( strings,
+ ( gpointer ) gconf_value_get_string(( GConfValue * ) iv->data ));
+ }
+
+ npn->type = NA_PIVOT_STRLIST;
+ npn->data = ( gpointer ) na_utils_duplicate_string_list( strings );
+ /*na_utils_free_string_list( strings );*/
+ break;
+
+ default:
+ g_assert_not_reached();
+ break;
+ }
+ }
+ return( npn );
+}
+
+/*
+ * convert a list of GConfEntry to a list of NAPivotNotify.
+ */
+static GSList *
+entries_to_notifies( GSList *entries )
+{
+ GSList *item;
+ GSList *notifies = NULL;
+
+ for( item = entries ; item ; item = item->next ){
+
+ const GConfEntry *entry = ( const GConfEntry * ) item->data;
+ NAPivotNotify *npn = entry_to_notify( entry );
+ notifies = g_slist_prepend( notifies, npn );
+ }
+
+ return( notifies );
+}
+
+static void
+free_list_notifies( GSList *list )
+{
+ GSList *il;
+ for( il = list ; il ; il = il->next ){
+ na_pivot_free_notify(( NAPivotNotify *) il->data );
+ }
+}
+
+static gboolean
+search_for_str( GSList *properties, const gchar *profile, const gchar *key, gchar **value )
+{
+ *value = NULL;
+ GSList *ip;
+ for( ip = properties ; ip ; ip = ip->next ){
+ NAPivotNotify *npn = ( NAPivotNotify * ) ip->data;
+ if( npn->type == NA_PIVOT_STR &&
+ ( !profile || !g_ascii_strcasecmp( profile, npn->profile )) &&
+ !g_ascii_strcasecmp( key, npn->parm )){
+ *value = g_strdup(( gchar * ) npn->data );
+ return( TRUE );
+ }
+ }
+ return( FALSE );
+}
+
+static gboolean
+search_for_bool( GSList *properties, const gchar *profile, const gchar *key, gboolean *value )
+{
+ *value = FALSE;
+ GSList *ip;
+ for( ip = properties ; ip ; ip = ip->next ){
+ NAPivotNotify *npn = ( NAPivotNotify * ) ip->data;
+ if( npn->type == NA_PIVOT_BOOL &&
+ ( !profile || !g_ascii_strcasecmp( profile, npn->profile )) &&
+ !g_ascii_strcasecmp( key, npn->parm )){
+ *value = ( gboolean ) npn->data;
+ return( TRUE );
+ }
+ }
+ return( FALSE );
+}
+
+static gboolean
+search_for_list( GSList *properties, const gchar *profile, const gchar *key, GSList **value )
+{
+ *value = NULL;
+ GSList *ip;
+ for( ip = properties ; ip ; ip = ip->next ){
+ NAPivotNotify *npn = ( NAPivotNotify * ) ip->data;
+ if( npn->type == NA_PIVOT_STRLIST &&
+ ( !profile || !g_ascii_strcasecmp( profile, npn->profile )) &&
+ !g_ascii_strcasecmp( key, npn->parm )){
+ *value = na_utils_duplicate_string_list(( GSList * ) npn->data );
+ return( TRUE );
+ }
+ }
+ return( FALSE );
}
/*
@@ -438,13 +1006,13 @@ load_action_properties( NAGConf *gconf, NAAction *action )
/*
* load the list of profiles for an action and returns them as a GSList
*/
-static GSList *
+/*static GSList *
load_profiles( NAGConf *gconf, NAAction *action )
-{
+{*/
/*static const gchar *thisfn = "nacf_gconf_load_profiles";
g_debug( "%s: gconf=%p, action=%p", thisfn, gconf, action );*/
- g_assert( NA_IS_GCONF( gconf ));
+ /*g_assert( NA_IS_GCONF( gconf ));
g_assert( NA_IS_ACTION( action ));
gchar *uuid = na_action_get_uuid( action );
@@ -468,18 +1036,18 @@ load_profiles( NAGConf *gconf, NAAction *action )
g_free( uuid );
return( items );
-}
+}*/
/*
* load and set the properties of the specified profile
*/
-static void
+/*static void
load_profile_properties( NAGConf *gconf, NAActionProfile *profile )
{
- /*static const gchar *thisfn = "nacf_gconf_load_profile_properties";
+ *//*static const gchar *thisfn = "nacf_gconf_load_profile_properties";
g_debug( "%s: gconf=%p, profile=%p", thisfn, gconf, profile );*/
- g_assert( NA_IS_GCONF( gconf ));
+/* g_assert( NA_IS_GCONF( gconf ));
g_assert( NA_IS_ACTION_PROFILE( profile ));
NAAction *action =
@@ -497,27 +1065,7 @@ load_profile_properties( NAGConf *gconf, NAActionProfile *profile )
free_keys_values( properties );
g_free( path );
g_free( uuid );
-}
-
-/*
- * load the keys which are the subdirs of the given path
- * returns a list of keys as full path
- */
-static GSList *
-load_subdirs( const NAGConf *gconf, const gchar *path )
-{
- static const gchar *thisfn = "na_gconf_load_subdirs";
-
- GError *error = NULL;
- GSList *list = gconf_client_all_dirs( gconf->private->gconf, path, &error );
- if( error ){
- g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
- g_error_free( error );
- return(( GSList * ) NULL );
- }
-
- return( list );
-}
+}*/
/*
* load all the key=value pairs of this key (specified as a full path),
@@ -525,7 +1073,7 @@ load_subdirs( const NAGConf *gconf, const gchar *path )
* The list is not recursive, it contains only the immediate children of
* path. To free the returned list, call free_key_values.
*/
-static GSList *
+/*static GSList *
load_keys_values( const NAGConf *gconf, const gchar *path )
{
static const gchar *thisfn = "na_gconf_load_keys_values";
@@ -550,27 +1098,13 @@ free_keys_values( GSList *list )
gconf_entry_unref( entry );
}
g_slist_free( list );
-}
-
-/*
- * extract the key part (the last part) of a full path
- * returns a newly allocated string which must be g_freed by the caller
- */
-static gchar *
-path_to_key( const gchar *path )
-{
- gchar **split = g_strsplit( path, "/", -1 );
- guint count = g_strv_length( split );
- gchar *key = g_strdup( split[count-1] );
- g_strfreev( split );
- return( key );
-}
+}*/
/*
* set the item properties into the object
* properties is a list of path to entry
*/
-static void
+/*static void
set_item_properties( NAObject *object, GSList *properties )
{
static const gchar *thisfn = "na_gconf_set_item_properties";
@@ -605,9 +1139,9 @@ set_item_properties( NAObject *object, GSList *properties )
na_pivot_free_notify( npn );
}
-}
+}*/
-static const gchar *
+/*static const gchar *
key_to_property( const gchar *key )
{
int i;
@@ -621,19 +1155,16 @@ key_to_property( const gchar *key )
}
return( property );
-}
+}*/
/*
* set the item properties into the action, dealing with successive
* versions
*/
-static gboolean
+/*static gboolean
set_action_properties( NAGConf *gconf, NAAction *action, GSList *properties )
{
- /*static const gchar *thisfn = "na_gconf_set_action_properties";*/
-
- /* the last action version we handle here */
- static const gchar *last_version = "2.0";
+ *//*static const gchar *thisfn = "na_gconf_set_action_properties";*//*
gchar *label = search_for_str( properties, NULL, ACTION_LABEL_ENTRY );
if( !label ){
@@ -645,11 +1176,11 @@ set_action_properties( NAGConf *gconf, NAAction *action, GSList *properties )
gchar *icon = search_for_str( properties, NULL, ACTION_ICON_ENTRY );
g_object_set( G_OBJECT( action ),
- PROP_ACTION_VERSION_STR, last_version,
- PROP_ACTION_LABEL_STR, label,
- PROP_ACTION_TOOLTIP_STR, tooltip,
- PROP_ACTION_ICON_STR, icon,
- PROP_ACTION_PROVIDER_STR, gconf,
+ PROP_NAACTION_VERSION_STR, version,
+ PROP_NAACTION_LABEL_STR, label,
+ PROP_NAACTION_TOOLTIP_STR, tooltip,
+ PROP_NAACTION_ICON_STR, icon,
+ PROP_NAACTION_PROVIDER_STR, gconf,
NULL );
g_free( icon );
@@ -677,13 +1208,13 @@ set_action_properties( NAGConf *gconf, NAAction *action, GSList *properties )
g_free( version );
return( TRUE );
-}
+}*/
/*
* only handle one profile, which is already loaded
* action+= path+parameters+basenames+isdir+isfile+multiple+schemes
*/
-static void
+/*static void
load_v1_properties( NAAction *action, const gchar *version, GSList *properties )
{
GSList *profiles = NULL;
@@ -698,13 +1229,13 @@ load_v1_properties( NAAction *action, const gchar *version, GSList *properties )
GSList *schemes = search_for_list( properties, NULL, ACTION_SCHEMES_ENTRY );
g_object_set( G_OBJECT( profile ),
- PROP_PROFILE_PATH_STR, path,
- PROP_PROFILE_PARAMETERS_STR, parameters,
- PROP_PROFILE_BASENAMES_STR, basenames,
- PROP_PROFILE_ISDIR_STR, isdir,
- PROP_PROFILE_ISFILE_STR, isfile,
- PROP_PROFILE_ACCEPT_MULTIPLE_STR, multiple,
- PROP_PROFILE_SCHEMES_STR, schemes,
+ PROP_NAPROFILE_PATH_STR, path,
+ PROP_NAPROFILE_PARAMETERS_STR, parameters,
+ PROP_NAPROFILE_BASENAMES_STR, basenames,
+ PROP_NAPROFILE_ISDIR_STR, isdir,
+ PROP_NAPROFILE_ISFILE_STR, isfile,
+ PROP_NAPROFILE_ACCEPT_MULTIPLE_STR, multiple,
+ PROP_NAPROFILE_SCHEMES_STR, schemes,
NULL );
g_free( path );
@@ -713,17 +1244,17 @@ load_v1_properties( NAAction *action, const gchar *version, GSList *properties )
na_utils_free_string_list( schemes );
if( g_ascii_strcasecmp( version, "1.0" ) > 0 ){
-
+*/
/* handle matchcase+mimetypes
* note that default values for 1.0 version have been set
* in na_action_profile_instance_init
*/
- gboolean matchcase = search_for_bool( properties, "", ACTION_MATCHCASE_ENTRY );
+ /*gboolean matchcase = search_for_bool( properties, "", ACTION_MATCHCASE_ENTRY );
GSList *mimetypes = search_for_list( properties, "", ACTION_MIMETYPES_ENTRY );
g_object_set( G_OBJECT( profile ),
- PROP_PROFILE_MATCHCASE_STR, matchcase,
- PROP_PROFILE_MIMETYPES_STR, mimetypes,
+ PROP_NAGCONF_PROFILE_MATCHCASE_STR, matchcase,
+ PROP_NAGCONF_PROFILE_MIMETYPES_STR, mimetypes,
NULL );
na_utils_free_string_list( mimetypes );
@@ -732,9 +1263,9 @@ load_v1_properties( NAAction *action, const gchar *version, GSList *properties )
profiles = g_slist_prepend( profiles, profile );
na_action_set_profiles( action, profiles );
na_action_free_profiles( profiles );
-}
+}*/
-static gchar *
+/*static gchar *
search_for_str( GSList *properties, const gchar *profile, const gchar *key )
{
GSList *ip;
@@ -777,15 +1308,12 @@ search_for_list( GSList *properties, const gchar *profile, const gchar *key )
}
}
return(( GSList * ) NULL );
-}
+}*/
/*
- * load all the key=value pairs of this key (specified as a full path),
- * returning them as a list of GConfEntry.
- * The list is not recursive, it contains only the immediate children of
- * path. To free the returned list, call free_key_values.
+ * convet a list of GConfEntry to a list of NAPivotNotify.
*/
-static GSList *
+/*static GSList *
keys_to_notify( GSList *entries )
{
GSList *item;
@@ -798,7 +1326,7 @@ keys_to_notify( GSList *entries )
}
return( properties );
-}
+}*/
/*
* convert a GConfEntry to a structure suitable to notify NAPivot
@@ -817,10 +1345,10 @@ keys_to_notify( GSList *entries )
* as the entry no more exists in GConf and thus cannot be tested
* -> we will set this as key/parm, letting pivot try to interpret it
*/
-static NAPivotNotify *
+/*static NAPivotNotify *
entry_to_notify( const GConfEntry *entry )
{
- /*static const gchar *thisfn = "na_gconf_entry_to_notify";*/
+ *//*static const gchar *thisfn = "na_gconf_entry_to_notify";*//*
GSList *listvalues, *iv, *strings;
g_assert( entry );
@@ -832,7 +1360,7 @@ entry_to_notify( const GConfEntry *entry )
const gchar *subpath = path + strlen( NA_GCONF_CONFIG_PATH ) + 1;
gchar **split = g_strsplit( subpath, "/", -1 );
- /*g_debug( "%s: [0]=%s, [1]=%s", thisfn, split[0], split[1] );*/
+ *//*g_debug( "%s: [0]=%s, [1]=%s", thisfn, split[0], split[1] );*//*
npn->uuid = g_strdup( split[0] );
if( g_strv_length( split ) == 2 ){
npn->parm = g_strdup( split[1] );
@@ -866,7 +1394,7 @@ entry_to_notify( const GConfEntry *entry )
npn->type = NA_PIVOT_STRLIST;
npn->data = ( gpointer ) na_utils_duplicate_string_list( strings );
- /*na_utils_free_string_list( strings );*/
+ *//*na_utils_free_string_list( strings );*//*
break;
default:
@@ -884,9 +1412,9 @@ free_list_notify( GSList *list )
for( il = list ; il ; il = il->next ){
na_pivot_free_notify(( NAPivotNotify *) il->data );
}
-}
+}*/
-static gboolean
+/*static gboolean
remove_v1_keys( NAGConf *gconf, const NAAction *action, gchar **message )
{
gchar *uuid = na_action_get_uuid( action );
@@ -904,9 +1432,9 @@ remove_v1_keys( NAGConf *gconf, const NAAction *action, gchar **message )
g_free( uuid );
return( ret );
-}
+}*/
-static gboolean
+/*static gboolean
remove_key( NAGConf *gconf, const gchar *uuid, const gchar *key, gchar **message )
{
gboolean ret = TRUE;
@@ -924,74 +1452,7 @@ remove_key( NAGConf *gconf, const gchar *uuid, const gchar *key, gchar **message
g_free( path );
return( ret );
-}
-
-static gboolean
-do_is_writable( NAIIOProvider *provider )
-{
- return( TRUE );
-}
-
-static gboolean
-do_is_willing_to_write( NAIIOProvider *provider, const GObject *action )
-{
- return( TRUE );
-}
-
-static guint
-do_write_action( NAIIOProvider *provider, const GObject *obj_action, gchar **message )
-{
- static const gchar *thisfn = "nacf_gconf_do_write_action";
- g_debug( "%s: provider=%p, action=%p, message=%p", thisfn, provider, obj_action, message );
-
- g_assert( NA_IS_IIO_PROVIDER( provider ));
- g_assert( NA_IS_GCONF( provider ));
- NAGConf *self = NA_GCONF( provider );
-
- message = NULL;
-
- g_assert( NA_IS_ACTION( obj_action ));
- NAAction *action = NA_ACTION( obj_action );
-
- if( !write_v2_keys( self, action, message )){
- return( NA_IIO_PROVIDER_WRITE_ERROR );
- }
-
- g_object_set( G_OBJECT( action ), PROP_ACTION_PROVIDER_STR, provider, NULL );
-
- return( NA_IIO_PROVIDER_WRITE_OK );
-}
-
-static guint
-do_delete_action( NAIIOProvider *provider, const GObject *obj_action, gchar **message )
-{
- static const gchar *thisfn = "nacf_gconf_do_delete_action";
- g_debug( "%s: provider=%p, action=%p, message=%p", thisfn, provider, obj_action, message );
-
- g_assert( NA_IS_IIO_PROVIDER( provider ));
- g_assert( NA_IS_GCONF( provider ));
- NAGConf *self = NA_GCONF( provider );
-
- message = NULL;
- guint ret = NA_IIO_PROVIDER_WRITE_OK;
-
- g_assert( NA_IS_ACTION( obj_action ));
- NAAction *action = NA_ACTION( obj_action );
-
- gchar *uuid = na_action_get_uuid( action );
- gchar *path = g_strdup_printf( "%s/%s", NA_GCONF_CONFIG_PATH, uuid );
- GError *error = NULL;
-
- if( !gconf_client_recursive_unset( self->private->gconf, path, 0, &error )){
- *message = g_strdup( error->message );
- g_error_free( error );
- ret = NA_IIO_PROVIDER_WRITE_ERROR;
- }
-
- g_free( path );
- g_free( uuid );
- return( ret );
-}
+}*/
/*
* gconf_client_key_is_writable doesn't work as I expect: it returns
@@ -1207,8 +1668,8 @@ install_gconf_watched_dir( NAGConf *gconf )
static void
remove_gconf_watch( NAGConf *gconf )
{
- if( gconf->private->notify_id ){
- gconf_client_notify_remove( gconf->private->gconf, gconf->private->notify_id );
+ if( gconf->private->watch_id ){
+ gconf_client_notify_remove( gconf->private->gconf, gconf->private->watch_id );
}
remove_gconf_watched_dir( gconf );
@@ -1255,6 +1716,7 @@ action_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, gpoint
g_assert( NA_IS_GCONF( user_data ));
NAGConf *gconf = NA_GCONF( user_data );
+ g_assert( NA_IS_IIO_PROVIDER( gconf ));
NAPivotNotify *npn = entry_to_notify( entry );
g_signal_emit_by_name( gconf->private->notified, NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED, npn );
diff --git a/src/common/na-gconf.h b/src/common/na-gconf.h
index 23049ba..0a96487 100644
--- a/src/common/na-gconf.h
+++ b/src/common/na-gconf.h
@@ -31,10 +31,13 @@
#ifndef __NA_GCONF_H__
#define __NA_GCONF_H__
-/*
- * NAGConf class definition.
+/**
+ * SECTION: na_gconf
+ * @short_description: #NAGConf class definition.
+ * @include: common/na-gconf.h
*
- * Implements the NactIIOProvider (I/O storage subsystem) interface.
+ * This class manages the GConf I/O storage subsystem.
+ * It should only be used through the NAIIOProvider interface.
*/
#include <glib-object.h>
diff --git a/src/common/na-iduplicable.c b/src/common/na-iduplicable.c
new file mode 100644
index 0000000..33907e5
--- /dev/null
+++ b/src/common/na-iduplicable.c
@@ -0,0 +1,422 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * This Program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "na-iduplicable.h"
+
+/* private interface data
+ */
+struct NAIDuplicableInterfacePrivate {
+};
+
+/* data set against GObject
+ */
+#define PROP_IDUPLICABLE_ORIGIN "na-iduplicable-origin"
+#define PROP_IDUPLICABLE_ISMODIFIED "na-iduplicable-is-modified"
+#define PROP_IDUPLICABLE_ISVALID "na-iduplicable-is-valid"
+
+static GType register_type( void );
+static void interface_base_init( NAIDuplicableInterface *klass );
+static void interface_base_finalize( NAIDuplicableInterface *klass );
+
+static NAObject *v_duplicate( const NAObject *object );
+static gboolean v_are_equal( const NAObject *a, const NAObject *b );
+static gboolean v_is_valid( const NAObject *object );
+
+static NAObject *get_origin( const NAObject *object );
+static void set_origin( const NAObject *object, const NAObject *origin );
+static gboolean get_modified( const NAObject *object );
+static void set_modified( const NAObject *object, gboolean is_modified );
+static gboolean get_valid( const NAObject *object );
+static void set_valid( const NAObject *object, gboolean is_valid );
+
+GType
+na_iduplicable_get_type( void )
+{
+ static GType iface_type = 0;
+
+ if( !iface_type ){
+ iface_type = register_type();
+ }
+
+ return( iface_type );
+}
+
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "na_iduplicable_register_type";
+ g_debug( "%s", thisfn );
+
+ static const GTypeInfo info = {
+ sizeof( NAIDuplicableInterface ),
+ ( GBaseInitFunc ) interface_base_init,
+ ( GBaseFinalizeFunc ) interface_base_finalize,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL
+ };
+
+ GType type = g_type_register_static( G_TYPE_INTERFACE, "NAIDuplicable", &info, 0 );
+
+ g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
+
+ return( type );
+}
+
+static void
+interface_base_init( NAIDuplicableInterface *klass )
+{
+ static const gchar *thisfn = "na_iduplicable_interface_base_init";
+ static gboolean initialized = FALSE;
+
+ if( !initialized ){
+ g_debug( "%s: klass=%p", thisfn, klass );
+
+ klass->private = g_new0( NAIDuplicableInterfacePrivate, 1 );
+
+ initialized = TRUE;
+ }
+}
+
+static void
+interface_base_finalize( NAIDuplicableInterface *klass )
+{
+ static const gchar *thisfn = "na_iduplicable_interface_base_finalize";
+ static gboolean finalized = FALSE ;
+
+ if( !finalized ){
+ g_debug( "%s: klass=%p", thisfn, klass );
+
+ g_free( klass->private );
+
+ finalized = TRUE;
+ }
+}
+
+/**
+ * na_iduplicable_init:
+ * @object: the #NAObject object to be initialized.
+ *
+ * Initializes the properties of a IDuplicable object.
+ *
+ * This function should be called when creating the object, e.g. from
+ * instance_init().
+ */
+void
+na_iduplicable_init( NAObject *object )
+{
+ g_assert( NA_IS_OBJECT( object ));
+ g_assert( NA_IS_IDUPLICABLE( object ));
+
+ set_origin( object, NULL );
+ set_modified( object, FALSE );
+ set_valid( object, TRUE );
+}
+
+/**
+ * na_iduplicable_dump:
+ * @object: the #NAObject object to be duplicated.
+ *
+ * Dumps via g_debug the properties of the object.
+ */
+void
+na_iduplicable_dump( const NAObject *object )
+{
+ static const gchar *thisfn = "na_iduplicable_dump";
+
+ NAObject *origin = NULL;
+ gboolean modified = FALSE;
+ gboolean valid = TRUE;
+
+ if( object ){
+ g_assert( NA_IS_OBJECT( object ));
+ g_assert( NA_IS_IDUPLICABLE( object ));
+
+ origin = get_origin( object );
+ modified = get_modified( object );
+ valid = get_valid( object );
+ }
+
+ g_debug( "%s: origin=%p", thisfn, origin );
+ g_debug( "%s: modified=%s", thisfn, modified ? "True" : "False" );
+ g_debug( "%s: valid=%s", thisfn, valid ? "True" : "False" );
+}
+
+/**
+ * na_iduplicable_duplicate:
+ * @object: the #NAObject object to be duplicated.
+ *
+ * Exactly duplicates a #NAObject-derived object.
+ * Properties %PROP_IDUPLICABLE_ORIGIN, %PROP_IDUPLICABLE_ISMODIFIED
+ * and %PROP_IDUPLICABLE_ISVALID are initialized to their default
+ * values.
+ *
+ * As %PROP_IDUPLICABLE_ISVALID property is set to %TRUE without any
+ * further check, this suppose that only valid objects are duplicated.
+ *
+ * Returns: a new #NAObject.
+ */
+NAObject *
+na_iduplicable_duplicate( const NAObject *object )
+{
+ static const gchar *thisfn = "na_iduplicable_duplicate";
+ g_debug( "%s: object=%p", thisfn, object );
+
+ NAObject *dup = NULL;
+
+ if( object ){
+ g_assert( NA_IS_OBJECT( object ));
+ g_assert( NA_IS_IDUPLICABLE( object ));
+
+ dup = v_duplicate( object );
+
+ set_origin( dup, object );
+ set_modified( dup, FALSE );
+ set_valid( dup, TRUE );
+ }
+
+ return( dup );
+}
+
+/**
+ * na_iduplicable_check_edited_status:
+ * @object: the #NAObject object to be checked.
+ *
+ * Checks the edition status of the #NAObject object, and set up the
+ * corresponding %PROP_IDUPLICABLE_ISMODIFIED and
+ * %PROP_IDUPLICABLE_ISVALID properties.
+ *
+ * This function is supposed to be called each time the object may have
+ * been modified in order to set these properties. Helper functions
+ * na_iduplicable_is_modified() and na_iduplicable_is_valid() will
+ * then only return the current value of the properties.
+ */
+void
+na_iduplicable_check_edited_status( const NAObject *object )
+{
+ /*static const gchar *thisfn = "na_iduplicable_check_edited_status";
+ g_debug( "%s: object=%p", thisfn, object );*/
+
+ if( object ){
+ g_assert( NA_IS_OBJECT( object ));
+ g_assert( NA_IS_IDUPLICABLE( object ));
+
+ gboolean modified = TRUE;
+ NAObject *origin = get_origin( object );
+ if( origin ){
+ modified = !v_are_equal( object, origin );
+ }
+ set_modified( object, modified );
+
+ gboolean valid = v_is_valid( object );
+ set_valid( object, valid );
+ }
+}
+
+/**
+ * na_iduplicable_is_modified:
+ * @object: the #NAObject object whose status is to be returned.
+ *
+ * Returns the current value of the %PROP_IDUPLICABLE_ISMODIFIED
+ * property without rechecking the edition status itself.
+ *
+ * Returns: %TRUE is the provided object has been modified regarding of
+ * the original one.
+ */
+gboolean
+na_iduplicable_is_modified( const NAObject *object )
+{
+ /*static const gchar *thisfn = "na_iduplicable_is_modified";
+ g_debug( "%s: object=%p", thisfn, object );*/
+
+ gboolean is_modified = FALSE;
+
+ if( object ){
+ g_assert( NA_IS_OBJECT( object ));
+ g_assert( NA_IS_IDUPLICABLE( object ));
+
+ is_modified = get_modified( object );
+ }
+
+ return( is_modified );
+}
+
+/**
+ * na_iduplicable_is_valid:
+ * @object: the #NAObject object whose status is to be returned.
+ *
+ * Returns the current value of the %PROP_IDUPLICABLE_ISVALID property
+ * without rechecking the edition status itself.
+ *
+ * Returns: %TRUE is the provided object is valid.
+ */
+gboolean
+na_iduplicable_is_valid( const NAObject *object )
+{
+ /*static const gchar *thisfn = "na_iduplicable_is_valid";
+ g_debug( "%s: object=%p", thisfn, object );*/
+
+ gboolean is_valid = FALSE;
+
+ if( object ){
+ g_assert( NA_IS_OBJECT( object ));
+ g_assert( NA_IS_IDUPLICABLE( object ));
+
+ is_valid = get_valid( object );
+ }
+
+ return( is_valid );
+}
+
+/**
+ * na_iduplicable_get_origin:
+ * @object: the #NAObject object whose origin is to be returned.
+ *
+ * Returns the origin of a duplicated #NAObject.
+ *
+ * Returns: the original #NAObject, or NULL.
+ */
+NAObject *
+na_iduplicable_get_origin( const NAObject *object )
+{
+ /*static const gchar *thisfn = "na_iduplicable_is_valid";
+ g_debug( "%s: object=%p", thisfn, object );*/
+
+ NAObject *origin = NULL;
+
+ if( object ){
+ g_assert( NA_IS_OBJECT( object ));
+ g_assert( NA_IS_IDUPLICABLE( object ));
+
+ origin = get_origin( object );
+ }
+
+ return( origin );
+}
+
+/**
+ * na_iduplicable_set_origin:
+ * @object: the #NAObject object whose origin is to be returned.
+ * @origin: the new original #NAObject.
+ *
+ * Sets the new origin of a duplicated #NAObject.
+ */
+void
+na_iduplicable_set_origin( NAObject *object, const NAObject *origin )
+{
+ /*static const gchar *thisfn = "na_iduplicable_is_valid";
+ g_debug( "%s: object=%p", thisfn, object );*/
+
+ if( object ){
+ g_assert( NA_IS_OBJECT( object ));
+ g_assert( NA_IS_IDUPLICABLE( object ));
+
+ set_origin( object, origin );
+ }
+}
+
+static NAObject *
+v_duplicate( const NAObject *object )
+{
+ NAIDuplicable *instance = NA_IDUPLICABLE( object );
+
+ if( NA_IDUPLICABLE_GET_INTERFACE( instance )->duplicate ){
+ return( NA_IDUPLICABLE_GET_INTERFACE( instance )->duplicate( object ));
+ }
+
+ return( NULL );
+}
+
+static gboolean
+v_are_equal( const NAObject *a, const NAObject *b )
+{
+ NAIDuplicable *instance = NA_IDUPLICABLE( a );
+
+ if( NA_IDUPLICABLE_GET_INTERFACE( instance )->are_equal ){
+ return( NA_IDUPLICABLE_GET_INTERFACE( instance )->are_equal( a, b ));
+ }
+
+ return( TRUE );
+}
+
+static gboolean
+v_is_valid( const NAObject *object )
+{
+ NAIDuplicable *instance = NA_IDUPLICABLE( object );
+
+ if( NA_IDUPLICABLE_GET_INTERFACE( instance )->is_valid ){
+ return( NA_IDUPLICABLE_GET_INTERFACE( instance )->is_valid( object ));
+ }
+
+ return( TRUE );
+}
+
+static NAObject *
+get_origin( const NAObject *object )
+{
+ return( NA_OBJECT( g_object_get_data( G_OBJECT( object ), PROP_IDUPLICABLE_ORIGIN )));
+}
+
+static void
+set_origin( const NAObject *object, const NAObject *origin )
+{
+ g_object_set_data( G_OBJECT( object ), PROP_IDUPLICABLE_ORIGIN, ( gpointer ) origin );
+}
+
+static gboolean
+get_modified( const NAObject *object )
+{
+ return(( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( object ), PROP_IDUPLICABLE_ISMODIFIED )));
+}
+
+static void
+set_modified( const NAObject *object, gboolean is_modified )
+{
+ g_object_set_data( G_OBJECT( object ), PROP_IDUPLICABLE_ISMODIFIED, GUINT_TO_POINTER( is_modified ));
+}
+
+static gboolean
+get_valid( const NAObject *object )
+{
+ return(( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( object ), PROP_IDUPLICABLE_ISVALID )));
+}
+
+static void
+set_valid( const NAObject *object, gboolean is_valid )
+{
+ g_object_set_data( G_OBJECT( object ), PROP_IDUPLICABLE_ISVALID, GUINT_TO_POINTER( is_valid ));
+}
diff --git a/src/common/na-iduplicable.h b/src/common/na-iduplicable.h
new file mode 100644
index 0000000..0536b46
--- /dev/null
+++ b/src/common/na-iduplicable.h
@@ -0,0 +1,129 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * This Program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifndef __NACT_IDUPLICABLE_H__
+#define __NACT_IDUPLICABLE_H__
+
+/**
+ * SECTION: na_iduplicable
+ * @short_description: #NAObject IDuplicable interface.
+ * @include: common/na-iduplicable.h
+ *
+ * This interface is implemented by #NAObject in order to let
+ * #NAObject-derived instance duplication be easily tracked. This works
+ * by keeping a pointer on the original object at duplication time, and
+ * then only checking status when explictely required.
+ *
+ * As the reference count of the original object is not incremented
+ * here, the caller has to garantee himself that the original object
+ * will stay in life at least as long as the duplicated one.
+ */
+
+#include "na-object.h"
+
+G_BEGIN_DECLS
+
+#define NA_IDUPLICABLE_TYPE ( na_iduplicable_get_type())
+#define NA_IDUPLICABLE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_IDUPLICABLE_TYPE, NAIDuplicable ))
+#define NA_IS_IDUPLICABLE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_IDUPLICABLE_TYPE ))
+#define NA_IDUPLICABLE_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NA_IDUPLICABLE_TYPE, NAIDuplicableInterface ))
+
+typedef struct NAIDuplicable NAIDuplicable;
+
+typedef struct NAIDuplicableInterfacePrivate NAIDuplicableInterfacePrivate;
+
+typedef struct {
+ GTypeInterface parent;
+ NAIDuplicableInterfacePrivate *private;
+
+ /**
+ * duplicate:
+ * @object: the #NAObject object to be duplicated.
+ *
+ * Allocates an exact copy of the specified #NAObject object.
+ *
+ * The implementor should define a duplicate()-equivalent virtual
+ * function in order the new #NAObject-derived object be allocated
+ * with the right most-derived class.
+ *
+ * The implementor should also define a copy()-equivalent virtual
+ * function so that each class in the derivation hierarchy be able
+ * to copy its own data and properties to the target instance.
+ *
+ * Returns: a newly allocated #NAObject object, which is an exact
+ * copy of @object.
+ */
+ NAObject * ( *duplicate )( const NAObject *object );
+
+ /**
+ * are_equal:
+ * @a: a first #NAObject object.
+ * @b: a second #NAObject object to be compared to the first one.
+ *
+ * Compares the two objects.
+ *
+ * The implementor should define a are_equal()-equivalent virtual
+ * function so that each #NAObject-derived class be able to check
+ * for identity.
+ *
+ * Returns: %TRUE if @a and @b are identical, %FALSE else.
+ */
+ gboolean ( *are_equal )( const NAObject *a, const NAObject *b );
+
+ /**
+ * is_valid:
+ * @object: the #NAObject object to be checked.
+ *
+ * Checks @object for validity.
+ *
+ * The implementor should define a is_valid()-equivalent virtual
+ * function so that each #NAObject-derived class be able to check
+ * for validity.
+ *
+ * Returns: %TRUE if @object is valid, %FALSE else.
+ */
+ gboolean ( *is_valid ) ( const NAObject *object );
+}
+ NAIDuplicableInterface;
+
+GType na_iduplicable_get_type( void );
+
+void na_iduplicable_init( NAObject *object );
+void na_iduplicable_dump( const NAObject *object );
+NAObject *na_iduplicable_duplicate( const NAObject *object );
+void na_iduplicable_check_edited_status( const NAObject *object );
+gboolean na_iduplicable_is_modified( const NAObject *object );
+gboolean na_iduplicable_is_valid( const NAObject *object );
+NAObject *na_iduplicable_get_origin( const NAObject *object );
+void na_iduplicable_set_origin( NAObject *object, const NAObject *origin );
+
+G_END_DECLS
+
+#endif /* __NA_IDUPLICABLE_H__ */
diff --git a/src/common/na-iio-provider.c b/src/common/na-iio-provider.c
index f27b911..6cf10f9 100644
--- a/src/common/na-iio-provider.c
+++ b/src/common/na-iio-provider.c
@@ -33,11 +33,10 @@
#endif
#include <glib.h>
+#include <glib/gi18n.h>
#include "na-action.h"
-#include "na-action-profile.h"
#include "na-iio-provider.h"
-#include "na-pivot.h"
/* private interface data
*/
@@ -48,8 +47,9 @@ static GType register_type( void );
static void interface_base_init( NAIIOProviderInterface *klass );
static void interface_base_finalize( NAIIOProviderInterface *klass );
-static gboolean do_is_writable( NAIIOProvider *instance );
-static gboolean do_is_willing_to_write( NAIIOProvider *instance, const GObject *action );
+static gboolean do_is_willing_to_write( const NAIIOProvider *instance );
+static gboolean do_is_writable( const NAIIOProvider *instance, const NAAction *action );
+static guint write_action( const NAIIOProvider *instance, NAAction *action, gchar **message );
/**
* Registers the GType of this interface.
@@ -103,9 +103,10 @@ interface_base_init( NAIIOProviderInterface *klass )
klass->private = g_new0( NAIIOProviderInterfacePrivate, 1 );
klass->read_actions = NULL;
- klass->is_writable = do_is_writable;
klass->is_willing_to_write = do_is_willing_to_write;
+ klass->is_writable = do_is_writable;
klass->write_action = NULL;
+ klass->delete_action = NULL;
initialized = TRUE;
}
@@ -127,24 +128,28 @@ interface_base_finalize( NAIIOProviderInterface *klass )
}
/**
- * Loads the actions defined in the system.
+ * na_iio_provider_read_actions:
+ * @pivot: the #NAPivot object which owns the list of registered I/O
+ * storage providers.
+ *
+ * Loads the actions from storage subsystems.
*
- * @object: the pivot object which owns the list of registered
- * interface providers.
+ * Returns: a #GSList of newly allocated #NAAction objects.
*
- * Returns a GSList of newly allocated NAAction objects.
+ * na_iio_provider_read_actions() loads the list of #NAAction from each
+ * registered I/O storage provider, and takes care of concatenating
+ * them into the returned global list.
*/
GSList *
-na_iio_provider_read_actions( const GObject *object )
+na_iio_provider_read_actions( const NAPivot *pivot )
{
static const gchar *thisfn = "na_iio_provider_read_actions";
- g_debug( "%s", thisfn );
+ g_debug( "%s: pivot=%p", thisfn, pivot );
- g_assert( NA_IS_PIVOT( object ));
- NAPivot *pivot = NA_PIVOT( object );
+ g_assert( NA_IS_PIVOT( pivot ));
GSList *actions = NULL;
- GSList *ip, *il;
+ GSList *ip;
GSList *list;
NAIIOProvider *instance;
@@ -157,59 +162,54 @@ na_iio_provider_read_actions( const GObject *object )
list = NA_IIO_PROVIDER_GET_INTERFACE( instance )->read_actions( instance );
- for( il = list ; il ; il = il->next ){
- g_object_set_data( G_OBJECT( il->data ), "provider", instance );
+ GSList *ia;
+ for( ia = list ; ia ; ia = ia->next ){
+
+ na_action_set_provider( NA_ACTION( ia->data ), instance );
+
+ na_object_dump( NA_OBJECT( ia->data ));
}
actions = g_slist_concat( actions, list );
}
}
-#ifdef NACT_MAINTAINER_MODE
- for( ip = actions ; ip ; ip = ip->next ){
- na_object_dump( NA_OBJECT( ip->data ));
- }
-#endif
-
return( actions );
}
/**
- * Writes an action to a willing-to storage subsystem.
- *
- * @obj_pivot: the pivot object which owns the list of registered
- * interface providers.
- *
- * @obj_action: the action to be written.
- *
+ * na_iio_provider_write_action:
+ * @pivot: the #NAPivot object which owns the list of registered I/O
+ * storage providers.
+ * @action: the #NAAction action to be written.
* @message: the I/O provider can allocate and store here an error
* message.
*
- * Returns the IIOProvider return code.
+ * Writes an action to a willing-to storage subsystem.
+ *
+ * Returns: the NAIIOProvider return code.
*/
guint
-na_iio_provider_write_action( const GObject *obj_pivot, const GObject *obj_action, gchar **message )
+na_iio_provider_write_action( const NAPivot *pivot, NAAction *action, gchar **message )
{
static const gchar *thisfn = "na_iio_provider_write_action";
- g_debug( "%s", thisfn );
-
- g_assert( NA_IS_PIVOT( obj_pivot ));
- NAPivot *pivot = NA_PIVOT( obj_pivot );
+ g_debug( "%s: pivot=%p, action=%p, message=%p", thisfn, pivot, action, message );
- g_assert( NA_IS_ACTION( obj_action ));
+ g_assert( NA_IS_PIVOT( pivot ));
+ g_assert( NA_IS_ACTION( action ));
guint ret = NA_IIO_PROVIDER_NOT_WRITABLE;
- NAIIOProvider *instance = NA_IIO_PROVIDER( na_action_get_provider( NA_ACTION( obj_action )));
/* try to write to the original provider of the action
*/
+ NAIIOProvider *instance = NA_IIO_PROVIDER( na_action_get_provider( action ));
+
if( instance ){
- g_assert( NA_IS_IIO_PROVIDER( instance ));
- if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->write_action ){
- ret = NA_IIO_PROVIDER_GET_INTERFACE( instance )->write_action( instance, obj_action, message );
- } else {
- instance = NULL;
- }
+ ret = write_action( instance, action, message );
+ }
+
+ if( ret == NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE || ret == NA_IIO_PROVIDER_NOT_WRITABLE ){
+ instance = NULL;
}
/* else, search for a provider which is willing to write the action
@@ -217,15 +217,12 @@ na_iio_provider_write_action( const GObject *obj_pivot, const GObject *obj_actio
if( !instance ){
GSList *providers = na_pivot_get_providers( pivot, NA_IIO_PROVIDER_TYPE );
GSList *ip;
-
for( ip = providers ; ip ; ip = ip->next ){
- instance = NA_IIO_PROVIDER( ip->data );
- if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->write_action ){
- ret = NA_IIO_PROVIDER_GET_INTERFACE( instance )->write_action( instance, obj_action, message );
- if( ret == NA_IIO_PROVIDER_WRITE_OK || ret == NA_IIO_PROVIDER_WRITE_ERROR ){
- break;
- }
+ instance = NA_IIO_PROVIDER( ip->data );
+ ret = write_action( instance, action, message );
+ if( ret == NA_IIO_PROVIDER_WRITE_OK || ret == NA_IIO_PROVIDER_WRITE_ERROR ){
+ break;
}
}
}
@@ -234,49 +231,84 @@ na_iio_provider_write_action( const GObject *obj_pivot, const GObject *obj_actio
}
/**
- * Deletes an action from the storage subsystem.
- *
- * @obj_pivot: the pivot object which owns the list of registered
- * interface providers.
- *
- * @obj_action: the action to be deleted.
- *
+ * na_iio_provider_delete_action:
+ * @pivot: the #NAPivot object which owns the list of registered I/O
+ * storage providers.
+ * @action: the #NAAction action to be written.
* @message: the I/O provider can allocate and store here an error
* message.
*
- * Returns the IIOProvider return code.
+ * Deletes an action from the storage subsystem.
+ *
+ * Returns: the NAIIOProvider return code.
+ *
+ * Note that a new action, not already written to an I/O subsystem,
+ * doesn't have any attached provider. We so do nothing...
*/
guint
-na_iio_provider_delete_action( const GObject *obj_pivot, const GObject *obj_action, gchar **message )
+na_iio_provider_delete_action( const NAPivot *pivot, const NAAction *action, gchar **message )
{
static const gchar *thisfn = "na_iio_provider_delete_action";
- g_debug( "%s: pivot=%p, action=%p, message=%p", thisfn, obj_pivot, obj_action, message );
+ g_debug( "%s: pivot=%p, action=%p, message=%p", thisfn, pivot, action, message );
+
+ g_assert( NA_IS_PIVOT( pivot ));
+ g_assert( NA_IS_ACTION( action ));
- g_assert( NA_IS_ACTION( obj_action ));
guint ret = NA_IIO_PROVIDER_NOT_WRITABLE;
+ NAIIOProvider *instance = NA_IIO_PROVIDER( na_action_get_provider( action ));
- NAIIOProvider *instance = NA_IIO_PROVIDER( na_action_get_provider( NA_ACTION( obj_action )));
if( instance ){
g_assert( NA_IS_IIO_PROVIDER( instance ));
if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->delete_action ){
- ret = NA_IIO_PROVIDER_GET_INTERFACE( instance )->delete_action( instance, obj_action, message );
+ ret = NA_IIO_PROVIDER_GET_INTERFACE( instance )->delete_action( instance, action, message );
}
- } else {
- g_assert_not_reached();
+ /*} else {
+ *message = g_strdup( _( "Unable to delete the action: no I/O provider." ));
+ ret = NA_IIO_PROVIDER_NO_PROVIDER;*/
}
return( ret );
}
static gboolean
-do_is_writable( NAIIOProvider *instance )
+do_is_willing_to_write( const NAIIOProvider *instance )
{
return( FALSE );
}
static gboolean
-do_is_willing_to_write( NAIIOProvider *instance, const GObject *action )
+do_is_writable( const NAIIOProvider *instance, const NAAction *action )
{
return( FALSE );
}
+
+static guint
+write_action( const NAIIOProvider *provider, NAAction *action, gchar **message )
+{
+ static const gchar *thisfn = "na_iio_provider_write_action";
+ g_debug( "%s: provider=%p, action=%p, message=%p", thisfn, provider, action, message );
+
+ if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->is_willing_to_write( provider )){
+ return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
+ }
+
+ if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->is_writable( provider, action )){
+ return( NA_IIO_PROVIDER_NOT_WRITABLE );
+ }
+
+ if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->delete_action ){
+ return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
+ }
+
+ guint ret = NA_IIO_PROVIDER_GET_INTERFACE( provider )->delete_action( provider, action, message );
+ if( ret != NA_IIO_PROVIDER_WRITE_OK ){
+ return( ret );
+ }
+
+ if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->write_action ){
+ return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
+ }
+
+ return( NA_IIO_PROVIDER_GET_INTERFACE( provider )->write_action( provider, action, message ));
+}
diff --git a/src/common/na-iio-provider.h b/src/common/na-iio-provider.h
index 4c691cc..728031b 100644
--- a/src/common/na-iio-provider.h
+++ b/src/common/na-iio-provider.h
@@ -31,11 +31,13 @@
#ifndef __NA_IIO_PROVIDER_H__
#define __NA_IIO_PROVIDER_H__
-/*
- * NAIIOProvider interface definition.
+/**
+ * SECTION: na_iio_provider
+ * @short_description: #NAIIOProvider interface definition.
+ * @include: common/na-iio-provider.h
*
* This is the API all storage subsystems should implement in order to
- * provide i/o resources to NautilusActions.
+ * provide I/O resources to NautilusActions.
*
* In a near or far future, provider subsystems may be extended by
* creating extension libraries, this class loading the modules at
@@ -44,6 +46,8 @@
#include <glib-object.h>
+#include "na-pivot.h"
+
G_BEGIN_DECLS
#define NA_IIO_PROVIDER_TYPE ( na_iio_provider_get_type())
@@ -51,7 +55,7 @@ G_BEGIN_DECLS
#define NA_IS_IIO_PROVIDER( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_IIO_PROVIDER_TYPE ))
#define NA_IIO_PROVIDER_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NA_IIO_PROVIDER_TYPE, NAIIOProviderInterface ))
-typedef struct NAIIOProvider NAIIOProvider;
+typedef struct NAIIOProvider NAIIOProvider;
typedef struct NAIIOProviderInterfacePrivate NAIIOProviderInterfacePrivate;
@@ -59,33 +63,89 @@ typedef struct {
GTypeInterface parent;
NAIIOProviderInterfacePrivate *private;
- /* i/o api */
- GSList * ( *read_actions ) ( NAIIOProvider *instance );
- gboolean ( *is_writable ) ( NAIIOProvider *instance );
- gboolean ( *is_willing_to_write )( NAIIOProvider *instance, const GObject *action );
- guint ( *write_action ) ( NAIIOProvider *instance, const GObject *action, gchar **message );
- guint ( *delete_action ) ( NAIIOProvider *instance, const GObject *action, gchar **message );
+ /**
+ * read_actions:
+ * @instance: the #NAIIOProvider provider.
+ *
+ * Reads actions from the specified I/O provider.
+ *
+ * Returns: a #GSList of #NAAction actions.
+ */
+ GSList * ( *read_actions ) ( const NAIIOProvider *instance );
+
+ /**
+ * is_willing_to_write:
+ * @instance: the #NAIIOProvider provider.
+ *
+ * Checks for global writability of the I/O provider.
+ *
+ * Returns: %TRUE if we are able to update/write/delete a #NAAction
+ * into this I/O provider, %FALSE else.
+ *
+ * Note that the I/O provider may return a positive writability
+ * flag when considering the whole I/O storage subsystem, while not
+ * being able to update/write/delete a particular #NAAction.
+ */
+ gboolean ( *is_willing_to_write )( const NAIIOProvider *instance );
+
+ /**
+ * is_writable:
+ * @instance: the #NAIIOProvider provider.
+ * @action: a #NAAction action.
+ *
+ * Checks for writability of this particular #NAAction.
+ *
+ * Returns: %TRUE if we are able to update/write/delete the
+ * #NAAction, %FALSE else.
+ */
+ gboolean ( *is_writable ) ( const NAIIOProvider *instance, const NAAction *action );
+
+ /**
+ * write_action:
+ * @instance: the #NAIIOProvider provider.
+ * @action: a #NAAction action.
+ * @message: warning/error messages detected in the operation.
+ *
+ * Updates an existing #NAAction or write a new #NAAction.
+ *
+ * Returns: %NA_IIO_PROVIDER_WRITE_OK if the update/write operation
+ * was successfull, or another code depending of the detected error.
+ */
+ guint ( *write_action ) ( const NAIIOProvider *instance, NAAction *action, gchar **message );
+
+ /**
+ * delete_action:
+ * @instance: the #NAIIOProvider provider.
+ * @action: a #NAAction action.
+ * @message: warning/error messages detected in the operation.
+ *
+ * Deletes an existing #NAAction from the I/O subsystem.
+ *
+ * Returns: %NA_IIO_PROVIDER_WRITE_OK if the delete operation was
+ * successfull, or another code depending of the detected error.
+ */
+ guint ( *delete_action ) ( const NAIIOProvider *instance, const NAAction *action, gchar **message );
}
NAIIOProviderInterface;
-GType na_iio_provider_get_type( void );
-
-GSList *na_iio_provider_read_actions( const GObject *pivot );
+GType na_iio_provider_get_type( void );
-guint na_iio_provider_write_action( const GObject *pivot, const GObject *action, gchar **message );
-guint na_iio_provider_delete_action( const GObject *pivot, const GObject *action, gchar **message );
+GSList *na_iio_provider_read_actions( const NAPivot *pivot );
+guint na_iio_provider_write_action( const NAPivot *pivot, NAAction *action, gchar **message );
+guint na_iio_provider_delete_action( const NAPivot *pivot, const NAAction *action, gchar **message );
/* modification notification message to NAPivot
*/
#define NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED "notify_pivot_of_action_changed"
-/* return code of write_action function
+/* return code of update/write/delete operations
*/
enum {
NA_IIO_PROVIDER_WRITE_OK = 0,
NA_IIO_PROVIDER_NOT_WRITABLE,
NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE,
- NA_IIO_PROVIDER_WRITE_ERROR
+ NA_IIO_PROVIDER_WRITE_ERROR,
+ NA_IIO_PROVIDER_NO_PROVIDER,
};
G_END_DECLS
diff --git a/src/common/na-ipivot-container.c b/src/common/na-ipivot-consumer.c
similarity index 63%
rename from src/common/na-ipivot-container.c
rename to src/common/na-ipivot-consumer.c
index 8b323ca..e0e2ec2 100644
--- a/src/common/na-ipivot-container.c
+++ b/src/common/na-ipivot-consumer.c
@@ -34,24 +34,24 @@
#include <glib.h>
-#include "na-ipivot-container.h"
+#include "na-ipivot-consumer.h"
/* private interface data
*/
-struct NAIPivotContainerInterfacePrivate {
+struct NAIPivotConsumerInterfacePrivate {
};
static GType register_type( void );
-static void interface_base_init( NAIPivotContainerInterface *klass );
-static void interface_base_finalize( NAIPivotContainerInterface *klass );
+static void interface_base_init( NAIPivotConsumerInterface *klass );
+static void interface_base_finalize( NAIPivotConsumerInterface *klass );
-/*static void do_actions_changed( NAIPivotContainer *instance, gpointer user_data );*/
+/*static void do_actions_changed( NAIPivotConsumer *instance, gpointer user_data );*/
/**
* Registers the GType of this interface.
*/
GType
-na_ipivot_container_get_type( void )
+na_ipivot_consumer_get_type( void )
{
static GType object_type = 0;
@@ -65,11 +65,11 @@ na_ipivot_container_get_type( void )
static GType
register_type( void )
{
- static const gchar *thisfn = "na_ipivot_container_register_type";
+ static const gchar *thisfn = "na_ipivot_consumer_register_type";
g_debug( "%s", thisfn );
static const GTypeInfo info = {
- sizeof( NAIPivotContainerInterface ),
+ sizeof( NAIPivotConsumerInterface ),
( GBaseInitFunc ) interface_base_init,
( GBaseFinalizeFunc ) interface_base_finalize,
NULL,
@@ -80,7 +80,7 @@ register_type( void )
NULL
};
- GType type = g_type_register_static( G_TYPE_INTERFACE, "NAIPivotContainer", &info, 0 );
+ GType type = g_type_register_static( G_TYPE_INTERFACE, "NAIPivotConsumer", &info, 0 );
g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
@@ -88,15 +88,15 @@ register_type( void )
}
static void
-interface_base_init( NAIPivotContainerInterface *klass )
+interface_base_init( NAIPivotConsumerInterface *klass )
{
- static const gchar *thisfn = "na_ipivot_container_interface_base_init";
+ static const gchar *thisfn = "na_ipivot_consumer_interface_base_init";
static gboolean initialized = FALSE;
if( !initialized ){
g_debug( "%s: klass=%p", thisfn, klass );
- klass->private = g_new0( NAIPivotContainerInterfacePrivate, 1 );
+ klass->private = g_new0( NAIPivotConsumerInterfacePrivate, 1 );
klass->on_actions_changed = NULL /*do_actions_changed*/;
@@ -105,9 +105,9 @@ interface_base_init( NAIPivotContainerInterface *klass )
}
static void
-interface_base_finalize( NAIPivotContainerInterface *klass )
+interface_base_finalize( NAIPivotConsumerInterface *klass )
{
- static const gchar *thisfn = "na_ipivot_container_interface_base_finalize";
+ static const gchar *thisfn = "na_ipivot_consumer_interface_base_finalize";
static gboolean finalized = FALSE ;
if( !finalized ){
@@ -120,21 +120,25 @@ interface_base_finalize( NAIPivotContainerInterface *klass )
}
/**
- * Notify the container that the actions have been modified.
+ * na_ipivot_consumer_notify:
+ * @instance: the #NAIPivotConsumer instance to be notified of the end
+ * of the modifications.
+ *
+ * Notifies the consumers that the actions have been modified.
*/
-void na_ipivot_container_notify( NAIPivotContainer *instance )
+void na_ipivot_consumer_notify( NAIPivotConsumer *instance )
{
- static const gchar *thisfn = "na_ipivot_container_notify";
+ static const gchar *thisfn = "na_ipivot_consumer_notify";
g_debug( "%s: instance=%p", thisfn, instance );
- if( NA_IPIVOT_CONTAINER_GET_INTERFACE( instance )->on_actions_changed ){
- NA_IPIVOT_CONTAINER_GET_INTERFACE( instance )->on_actions_changed( instance, NULL );
+ if( NA_IPIVOT_CONSUMER_GET_INTERFACE( instance )->on_actions_changed ){
+ NA_IPIVOT_CONSUMER_GET_INTERFACE( instance )->on_actions_changed( instance, NULL );
}
}
/*static void
-do_actions_changed( NAIPivotContainer *instance, gpointer user_data )
+do_actions_changed( NAIPivotConsumer *instance, gpointer user_data )
{
- static const gchar *thisfn = "na_ipivot_container_do_actions_changed";
+ static const gchar *thisfn = "na_ipivot_consumer_do_actions_changed";
g_debug( "%s: instance=%p, user_data=%p", thisfn, instance, user_data );
}*/
diff --git a/src/common/na-ipivot-consumer.h b/src/common/na-ipivot-consumer.h
new file mode 100644
index 0000000..da84f4d
--- /dev/null
+++ b/src/common/na-ipivot-consumer.h
@@ -0,0 +1,82 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * This Program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifndef __NA_IPIVOT_CONSUMER_H__
+#define __NA_IPIVOT_CONSUMER_H__
+
+/**
+ * SECTION: na_ipivot_consumer
+ * @short_description: #NAIPivotConsumer interface definition.
+ * @include: common/na-ipivot-consumer.h
+ *
+ * This interface should be implemented by all classes which embed a
+ * #NAPivot object, in order to receive modification notification
+ * messages.
+ */
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define NA_IPIVOT_CONSUMER_TYPE ( na_ipivot_consumer_get_type())
+#define NA_IPIVOT_CONSUMER( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_IPIVOT_CONSUMER_TYPE, NAIPivotConsumer ))
+#define NA_IS_IPIVOT_CONSUMER( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_IPIVOT_CONSUMER_TYPE ))
+#define NA_IPIVOT_CONSUMER_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NA_IPIVOT_CONSUMER_TYPE, NAIPivotConsumerInterface ))
+
+typedef struct NAIPivotConsumer NAIPivotConsumer;
+
+typedef struct NAIPivotConsumerInterfacePrivate NAIPivotConsumerInterfacePrivate;
+
+typedef struct {
+ GTypeInterface parent;
+ NAIPivotConsumerInterfacePrivate *private;
+
+ /**
+ * on_actions_changed:
+ * @instance: the #NAIPivotConsumer instance which implements this
+ * interface.
+ * user_data: user data set when emitting the message. Currently,
+ * not used.
+ *
+ * This function is triggered once when #NAPivot detects the end of
+ * a bunch of modifications. At this time, the embedded list of
+ * #NAAction has been updated to be up to date.
+ */
+ void ( *on_actions_changed )( NAIPivotConsumer *instance, gpointer user_data );
+}
+ NAIPivotConsumerInterface;
+
+GType na_ipivot_consumer_get_type( void );
+
+void na_ipivot_consumer_notify( NAIPivotConsumer *instance );
+
+G_END_DECLS
+
+#endif /* __NA_IPIVOT_CONSUMER_H__ */
diff --git a/src/common/na-object.c b/src/common/na-object.c
index ac6b8be..48426e5 100644
--- a/src/common/na-object.c
+++ b/src/common/na-object.c
@@ -32,7 +32,10 @@
#include <config.h>
#endif
+#include <string.h>
+
#include "na-object.h"
+#include "na-iduplicable.h"
/* private class data
*/
@@ -42,20 +45,41 @@ struct NAObjectClassPrivate {
/* private instance data
*/
struct NAObjectPrivate {
- gboolean dispose_has_run;
+ gboolean dispose_has_run;
+ gchar *id;
+ gchar *label;
};
-static GObjectClass *st_parent_class = NULL;
+/* instance properties
+ */
+#define PROP_NAOBJECT_ID_STR "na-object-id"
+#define PROP_NAOBJECT_LABEL_STR "na-object-label"
-static GType register_type( void );
-static void class_init( NAObjectClass *klass );
-static void instance_init( GTypeInstance *instance, gpointer klass );
-static void instance_dispose( GObject *object );
-static void instance_finalize( GObject *object );
+static GObjectClass *st_parent_class = NULL;
-static void do_dump( const NAObject *object );
-static gchar *do_get_id( const NAObject *object );
-static gchar *do_get_label( const NAObject *object );
+static GType register_type( void );
+static void class_init( NAObjectClass *klass );
+static void iduplicable_iface_init( NAIDuplicableInterface *iface );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_constructed( GObject *object );
+static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
+
+static NAObject *v_duplicate( const NAObject *object );
+static void v_copy( NAObject *target, const NAObject *source );
+static gboolean v_are_equal( const NAObject *a, const NAObject *b );
+static gboolean v_is_valid( const NAObject *object );
+
+static void do_dump( const NAObject *object );
+static void do_copy( NAObject *target, const NAObject *source );
+static gboolean do_are_equal( const NAObject *a, const NAObject *b );
+static gboolean do_is_valid( const NAObject *object );
+
+static NAObject *iduplicable_duplicate( const NAObject *object );
+static gboolean iduplicable_are_equal( const NAObject *a, const NAObject *b );
+static gboolean iduplicable_is_valid( const NAObject *object );
GType
na_object_get_type( void )
@@ -72,6 +96,9 @@ na_object_get_type( void )
static GType
register_type( void )
{
+ static const gchar *thisfn = "na_object_register_type";
+ g_debug( "%s", thisfn );
+
static GTypeInfo info = {
sizeof( NAObjectClass ),
( GBaseInitFunc ) NULL,
@@ -84,7 +111,19 @@ register_type( void )
( GInstanceInitFunc ) instance_init
};
- return( g_type_register_static( G_TYPE_OBJECT, "NAObject", &info, 0 ));
+ GType type = g_type_register_static( G_TYPE_OBJECT, "NAObject", &info, 0 );
+
+ /* implements IDuplicable interface
+ */
+ static const GInterfaceInfo idupicable_iface_info = {
+ ( GInterfaceInitFunc ) iduplicable_iface_init,
+ NULL,
+ NULL
+ };
+
+ g_type_add_interface_static( type, NA_IDUPLICABLE_TYPE, &idupicable_iface_info );
+
+ return( type );
}
static void
@@ -96,14 +135,45 @@ class_init( NAObjectClass *klass )
st_parent_class = g_type_class_peek_parent( klass );
GObjectClass *object_class = G_OBJECT_CLASS( klass );
+ object_class->constructed = instance_constructed;
object_class->dispose = instance_dispose;
object_class->finalize = instance_finalize;
+ object_class->set_property = instance_set_property;
+ object_class->get_property = instance_get_property;
+
+ GParamSpec *spec;
+ spec = g_param_spec_string(
+ PROP_NAOBJECT_ID_STR,
+ "NAObject identifiant",
+ "Internal identifiant of the NAObject object (ASCII, case insensitive)", "",
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, PROP_NAOBJECT_ID, spec );
+
+ spec = g_param_spec_string(
+ PROP_NAOBJECT_LABEL_STR,
+ "NAObject libelle",
+ "Libelle of the NAObject object (UTF-8, localizable)", "",
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, PROP_NAOBJECT_LABEL, spec );
klass->private = g_new0( NAObjectClassPrivate, 1 );
klass->dump = do_dump;
- klass->get_id = do_get_id;
- klass->get_label = do_get_label;
+ klass->duplicate = NULL;
+ klass->copy = do_copy;
+ klass->are_equal = do_are_equal;
+ klass->is_valid = do_is_valid;
+}
+
+static void
+iduplicable_iface_init( NAIDuplicableInterface *iface )
+{
+ static const gchar *thisfn = "na_object_iduplicable_iface_init";
+ g_debug( "%s: iface=%p", thisfn, iface );
+
+ iface->duplicate = iduplicable_duplicate;
+ iface->are_equal = iduplicable_are_equal;
+ iface->is_valid = iduplicable_is_valid;
}
static void
@@ -121,6 +191,61 @@ instance_init( GTypeInstance *instance, gpointer klass )
}
static void
+instance_constructed( GObject *object )
+{
+ na_iduplicable_init( NA_OBJECT( object ));
+
+ /* chain call to parent class */
+ if( st_parent_class->constructed ){
+ G_OBJECT_CLASS( st_parent_class )->constructed( object );
+ }
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+ g_assert( NA_IS_OBJECT( object ));
+ NAObject *self = NA_OBJECT( object );
+
+ switch( property_id ){
+ case PROP_NAOBJECT_ID:
+ g_value_set_string( value, self->private->id );
+ break;
+
+ case PROP_NAOBJECT_LABEL:
+ g_value_set_string( value, self->private->label );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+ break;
+ }
+}
+
+static void
+instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+{
+ g_assert( NA_IS_OBJECT( object ));
+ NAObject *self = NA_OBJECT( object );
+
+ switch( property_id ){
+ case PROP_NAOBJECT_ID:
+ g_free( self->private->id );
+ self->private->id = g_value_dup_string( value );
+ break;
+
+ case PROP_NAOBJECT_LABEL:
+ g_free( self->private->label );
+ self->private->label = g_value_dup_string( value );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+ break;
+ }
+}
+
+static void
instance_dispose( GObject *object )
{
g_assert( NA_IS_OBJECT( object ));
@@ -141,6 +266,9 @@ instance_finalize( GObject *object )
g_assert( NA_IS_OBJECT( object ));
NAObject *self = ( NAObject * ) object;
+ g_free( self->private->id );
+ g_free( self->private->label );
+
g_free( self->private );
/* chain call to parent class */
@@ -149,75 +277,349 @@ instance_finalize( GObject *object )
}
}
-static void
-do_dump( const NAObject *object )
+/**
+ * na_object_dump:
+ * @object: the #NAObject object to be dumped.
+ *
+ * Dumps via g_debug the content of the object.
+ */
+void
+na_object_dump( const NAObject *object )
+{
+ if( object ){
+ g_assert( NA_IS_OBJECT( object ));
+
+ NA_OBJECT_GET_CLASS( object )->dump( object );
+ }
+}
+
+/**
+ * na_object_duplicate:
+ * @object: the #NAObject object to be dumped.
+ *
+ * Exactly duplicates a #NAObject-derived object.
+ *
+ * Returns: the new #NAObject.
+ */
+NAObject *
+na_object_duplicate( const NAObject *object )
{
- static const char *thisfn = "na_object_do_dump";
g_assert( NA_IS_OBJECT( object ));
- g_debug( "%s: object=%p", thisfn, object );
+
+ return( na_iduplicable_duplicate( object ));
+}
+
+/**
+ * na_object_copy:
+ * @target: the #NAObject-derived object which will receive data.
+ * @source: the #NAObject-derived object which will provide data.
+ *
+ * Copies data and properties from @source to @target.
+ */
+void
+na_object_copy( NAObject *target, const NAObject *source )
+{
+ g_assert( NA_IS_OBJECT( target ));
+ g_assert( NA_IS_OBJECT( source ));
+
+ v_copy( target, source );
}
/**
- * Dump the content of the object via g_debug output.
+ * na_object_check_edited_status:
+ * @object: the #NAObject object to be checked.
*
- * This is a virtual function which may be implemented by the derived
- * class ; the derived class may also call its parent class to get a
- * dump of parent object.
+ * Checks for the edition status of @object.
*
- * @object: object to be dumped.
+ * Internally set some properties which may be requested later. This
+ * two-steps check-request let us optimize some work in the UI.
*/
void
-na_object_dump( const NAObject *object )
+na_object_check_edited_status( const NAObject *object )
+{
+ g_assert( NA_IS_OBJECT( object ));
+
+ na_iduplicable_check_edited_status( object );
+}
+
+/**
+ * na_object_are_equal:
+ * @a: a first #NAObject object.
+ * @b: a second #NAObject object to be compared to the first one.
+ *
+ * Compares the two #NAObject objects.
+ *
+ * At least when it finds that @a and @b are equal, each derived
+ * class should call its parent class to give it an opportunity to
+ * detect a difference.
+ *
+ * Returns: %TRUE if @a and @b are identical, %FALSE else.
+ */
+gboolean
+na_object_are_equal( const NAObject *a, const NAObject *b )
+{
+ g_assert( NA_IS_OBJECT( a ));
+ g_assert( NA_IS_OBJECT( b ));
+
+ return( v_are_equal( a, b ));
+}
+
+/**
+ * na_object_get_is_valid:
+ * @object: the #NAObject object whose validity is to be checked.
+ *
+ * Checks for the validity of @object.
+ *
+ * Returns: %TRUE is @object is valid, %FALSE else.
+ */
+gboolean
+na_object_is_valid( const NAObject *object )
{
g_assert( NA_IS_OBJECT( object ));
- NA_OBJECT_GET_CLASS( object )->dump( object );
+ return( v_is_valid( object ));
}
-static gchar *
-do_get_id( const NAObject *object )
+/**
+ * na_object_get_origin:
+ * @object: the #NAObject object whose status is requested.
+ *
+ * Returns the original object which was at the origin of @object.
+ *
+ * Returns: a #NAObject, or NULL.
+ */
+NAObject *
+na_object_get_origin( const NAObject *object )
{
g_assert( NA_IS_OBJECT( object ));
- return(( gchar * ) NULL );
+
+ return( na_iduplicable_get_origin( object ));
}
/**
- * Returns the id of the object as new string.
+ * na_object_get_modified_status:
+ * @object: the #NAObject object whose status is requested.
+ *
+ * Returns the current modification status of @object.
*
- * This is a virtual function which should be implemented by the
- * derived class ; if not, this parent object returns NULL.
+ * This suppose that @object has been previously duplicated in order
+ * to get benefits provided by the IDuplicable interface.
*
- * @object: targeted NAObject object.
+ * This suppose also that the edition status of @object has previously
+ * been checked via na_object_check_edited_status().
*
- * The returned string should be g_freed by the caller.
+ * Returns: %TRUE is the provided object has been modified regarding to
+ * the original one, %FALSE else.
*/
-gchar *
-na_object_get_id( const NAObject *object )
+gboolean
+na_object_get_modified_status( const NAObject *object )
+{
+ g_assert( NA_IS_OBJECT( object ));
+
+ return( na_iduplicable_is_modified( object ));
+}
+
+/**
+ * na_object_get_valid_status:
+ * @object: the #NAObject object whose status is requested.
+ *
+ * Returns the current validity status of @object.
+ *
+ * This suppose that @object has been previously duplicated in order
+ * to get benefits provided by the IDuplicable interface.
+ *
+ * This suppose also that the edition status of @object has previously
+ * been checked via na_object_check_edited_status().
+ *
+ * Returns: %TRUE is the provided object is valid, %FALSE else.
+ */
+gboolean
+na_object_get_valid_status( const NAObject *object )
{
g_assert( NA_IS_OBJECT( object ));
- return( NA_OBJECT_GET_CLASS( object )->get_id( object ));
+
+ return( na_iduplicable_is_valid( object ));
}
-static gchar *
-do_get_label( const NAObject *object )
+/**
+ * na_object_set_origin:
+ * @object: the #NAObject object whose status is requested.
+ * @origin: a #NAObject which will be set as the new origin of @object.
+ *
+ * Sets the new origin of @object.
+ */
+void
+na_object_set_origin( NAObject *object, const NAObject *origin )
{
g_assert( NA_IS_OBJECT( object ));
- return(( gchar * ) NULL );
+
+ na_iduplicable_set_origin( object, origin );
}
/**
- * Returns the label of the object as new string.
+ * na_object_get_id:
+ * @object: the #NAObject object whose internal identifiant is
+ * requested.
*
- * This is a virtual function which should be implemented by the
- * derived class ; if not, this parent object returns NULL.
+ * Returns the internal identifiant of @object.
+ *
+ * Returns: the internal identifiant of @object as a new string. The
+ * returned string is an ASCII, case insensitive, string. It should be
+ * g_free() by the caller.
+ */
+gchar *
+na_object_get_id( const NAObject *object )
+{
+ g_assert( NA_IS_OBJECT( object ));
+ gchar *id;
+ g_object_get( G_OBJECT( object ), PROP_NAOBJECT_ID_STR, &id, NULL );
+ return( id );
+}
+
+/**
+ * na_object_get_label:
+ * @object: the #NAObject object whose label is requested.
*
- * @object: targeted NAObject object.
+ * Returns the label of @object.
*
- * The returned string should be g_freed by the caller.
+ * Returns: the label of @object as a new string. The returned string
+ * is an UTF_8 string. It should be g_free() by the caller.
*/
gchar *
na_object_get_label( const NAObject *object )
{
g_assert( NA_IS_OBJECT( object ));
- return( NA_OBJECT_GET_CLASS( object )->get_label( object ));
+ gchar *label;
+ g_object_get( G_OBJECT( object ), PROP_NAOBJECT_LABEL_STR, &label, NULL );
+ return( label );
+}
+
+/**
+ * na_object_set_id:
+ * @object: the #NAObject object whose internal identifiant is to be
+ * set.
+ * @id: internal identifiant to be set.
+ *
+ * Sets the internal identifiant of @object by taking a copy of the
+ * provided one.
+ */
+void
+na_object_set_id( NAObject *object, const gchar *id )
+{
+ g_assert( NA_IS_OBJECT( object ));
+ g_object_set( G_OBJECT( object ), PROP_NAOBJECT_ID_STR, id, NULL );
+}
+
+/**
+ * na_object_set_label:
+ * @object: the #NAObject object whose label is to be set.
+ * @label: label to be set.
+ *
+ * Sets the label of @object by taking a copy of the provided one.
+ */
+void
+na_object_set_label( NAObject *object, const gchar *label )
+{
+ g_assert( NA_IS_OBJECT( object ));
+ g_object_set( G_OBJECT( object ), PROP_NAOBJECT_LABEL_STR, label, NULL );
+}
+
+static NAObject *
+v_duplicate( const NAObject *object )
+{
+ if( NA_OBJECT_GET_CLASS( object )->duplicate ){
+ return( NA_OBJECT_GET_CLASS( object )->duplicate( object ));
+ }
+
+ return( NULL );
+}
+
+static void
+v_copy( NAObject *target, const NAObject *source )
+{
+ if( NA_OBJECT_GET_CLASS( target )->copy ){
+ NA_OBJECT_GET_CLASS( target )->copy( target, source );
+ }
+}
+
+static gboolean
+v_are_equal( const NAObject *a, const NAObject *b )
+{
+ if( NA_OBJECT_GET_CLASS( a )->are_equal ){
+ return( NA_OBJECT_GET_CLASS( a )->are_equal( a, b ));
+ }
+
+ return( FALSE );
+}
+
+static gboolean
+v_is_valid( const NAObject *object )
+{
+ if( NA_OBJECT_GET_CLASS( object )->is_valid ){
+ return( NA_OBJECT_GET_CLASS( object )->is_valid( object ));
+ }
+
+ return( TRUE );
+}
+
+static void
+do_dump( const NAObject *object )
+{
+ static const char *thisfn = "na_object_do_dump";
+
+ g_assert( NA_IS_OBJECT( object ));
+
+ g_debug( "%s: object=%p", thisfn, object );
+ g_debug( "%s: id=%s", thisfn, object->private->id );
+ g_debug( "%s: label=%s", thisfn, object->private->label );
+
+ na_iduplicable_dump( object );
+}
+
+static void
+do_copy( NAObject *target, const NAObject *source )
+{
+ gchar *id = na_object_get_id( source );
+ na_object_set_id( target, id );
+ g_free( id );
+
+ gchar *label = na_object_get_label( source );
+ na_object_set_label( target, label );
+ g_free( label );
+}
+
+static gboolean
+do_are_equal( const NAObject *a, const NAObject *b )
+{
+ if( g_ascii_strcasecmp( a->private->id, b->private->id )){
+ return( FALSE );
+ }
+ if( g_utf8_collate( a->private->label, b->private->label )){
+ return( FALSE );
+ }
+ return( TRUE );
+}
+
+static gboolean
+do_is_valid( const NAObject *object )
+{
+ return( object->private->id && strlen( object->private->id ));
+}
+
+static NAObject *
+iduplicable_duplicate( const NAObject *object )
+{
+ return( v_duplicate( object ));
+}
+
+static gboolean
+iduplicable_are_equal( const NAObject *a, const NAObject *b )
+{
+ return( v_are_equal( a, b ));
+}
+
+static gboolean
+iduplicable_is_valid( const NAObject *object )
+{
+ return( v_is_valid( object ));
}
diff --git a/src/common/na-object.h b/src/common/na-object.h
index 9d11de9..a863123 100644
--- a/src/common/na-object.h
+++ b/src/common/na-object.h
@@ -32,13 +32,20 @@
#define __NA_OBJECT_H__
/*
- * NAObject class definition.
+ * SECTION: na_object
+ * @short_description: #NAObject class definition.
+ * @include: common/na-object.h
*
- * This is the base class for NactAction and NactActionProfile.
+ * This is the base class for NAAction and NActionProfile.
*
- * It takes care of common things such as ids, i/o, etc.
- * It uses the NactIIOProviderInterface for all storage subsystems
- * management.
+ * It implements the NAIDuplicable interface in order to have easily
+ * duplicable derived objects.
+ *
+ * A #NAObject object is characterized by :
+ * - an internal identifiant (ASCII, case insensitive)
+ * - a libelle (UTF8, localizable).
+ *
+ * The #NAObject class is a pure virtual class.
*/
#include <glib-object.h>
@@ -66,18 +73,109 @@ typedef struct {
GObjectClass parent;
NAObjectClassPrivate *private;
- /* virtual public functions */
- void ( *dump ) ( const NAObject *object );
- gchar * ( *get_id ) ( const NAObject *object );
- gchar * ( *get_label )( const NAObject *object );
+ /**
+ * dump:
+ * @object: the #NAObject-derived object to be dumped.
+ *
+ * Dumps via g_debug the content of the object.
+ *
+ * In order to get a down-to-top display, the derived class
+ * implementation should call its parent class before actually
+ * dumping its own data and properties.
+ */
+ void ( *dump ) ( const NAObject *object );
+
+ /**
+ * duplicate:
+ * @object: the #NAObject-derived object to be dumped.
+ *
+ * Duplicates a #NAObject-derived object.
+ *
+ * As the most-derived class will actually allocate the new object
+ * with the right class, it shouldn't call its parent class.
+ *
+ * Copying data and properties should then be done via the
+ * na_object_copy() function.
+ *
+ * Returns: a newly allocated object, which is an exact copy of
+ * @object.
+ */
+ NAObject * ( *duplicate )( const NAObject *object );
+
+ /**
+ * copy:
+ * @target: the #NAObject-derived object which will receive data.
+ * @source: the #NAObject-derived object which will provide data.
+ *
+ * Copies data and properties from @source to @target.
+ *
+ * Each derived class should take care of calling its parent class
+ * to complete the copy.
+ */
+ void ( *copy ) ( NAObject *target, const NAObject *source );
+
+ /**
+ * are_equal:
+ * @a: a first #NAObject object.
+ * @b: a second #NAObject object to be compared to the first one.
+ *
+ * Compares the two objects.
+ *
+ * At least when it finds that @a and @b are equal, each derived
+ * class should call its parent class to give it an opportunity to
+ * detect a difference.
+ *
+ * Returns: %TRUE if @a and @b are identical, %FALSE else.
+ */
+ gboolean ( *are_equal )( const NAObject *a, const NAObject *b );
+
+ /**
+ * is_valid:
+ * @object: the #NAObject object to be checked.
+ *
+ * Checks @object for validity.
+ *
+ * At least when it finds that @object is valid, each derived class
+ * should call its parent class to give it an opportunity to detect
+ * an error.
+ *
+ * A #NAObject is valid if its internal identifiant is set.
+ *
+ * Returns: %TRUE if @object is valid, %FALSE else.
+ */
+ gboolean ( *is_valid ) ( const NAObject *object );
}
NAObjectClass;
-GType na_object_get_type( void );
+/* object properties
+ * used in derived classes to access to the properties
+ */
+enum {
+ PROP_NAOBJECT_ID = 1,
+ PROP_NAOBJECT_LABEL
+};
+
+GType na_object_get_type( void );
+
+void na_object_dump( const NAObject *object );
+NAObject *na_object_duplicate( const NAObject *object );
+void na_object_copy( NAObject *target, const NAObject *source );
+
+void na_object_check_edited_status( const NAObject *object );
+gboolean na_object_are_equal( const NAObject *a, const NAObject *b );
+gboolean na_object_is_valid( const NAObject *object );
+
+NAObject *na_object_get_origin( const NAObject *object );
+gboolean na_object_get_modified_status( const NAObject *object );
+gboolean na_object_get_valid_status( const NAObject *object );
+
+void na_object_set_origin( NAObject *object, const NAObject *origin );
+
+gchar *na_object_get_id( const NAObject *object );
+gchar *na_object_get_label( const NAObject *object );
-void na_object_dump( const NAObject *object );
-gchar *na_object_get_id( const NAObject *object );
-gchar *na_object_get_label( const NAObject *object );
+void na_object_set_id( NAObject *object, const gchar *id );
+void na_object_set_label( NAObject *object, const gchar *label );
G_END_DECLS
diff --git a/src/common/na-pivot.c b/src/common/na-pivot.c
index fbc5c57..593d1e7 100644
--- a/src/common/na-pivot.c
+++ b/src/common/na-pivot.c
@@ -39,7 +39,7 @@
#include "na-gconf.h"
#include "na-pivot.h"
#include "na-iio-provider.h"
-#include "na-ipivot-container.h"
+#include "na-ipivot-consumer.h"
#include "na-utils.h"
/* private class data
@@ -53,6 +53,7 @@ struct NAPivotPrivate {
gboolean dispose_has_run;
/* list of instances to be notified of an action modification
+ * these are called 'consumers' of NAPivot
*/
GSList *notified;
@@ -66,19 +67,9 @@ struct NAPivotPrivate {
/* list of actions
*/
GSList *actions;
+ gboolean reload;
};
-/* We have a double stage notification system :
- *
- * 1. When the storage subsystems detects a change on an action, it
- * must emit the "notify_pivot_of_action_changed" signal to notify
- * NAPivot of this change ; when this signal is received, NAPivot
- * then updates accordingly the list of actions it maintains.
- *
- * 2. When NAPivot has successfully updated its list of actions, it has
- * to notify its consumers (its 'containers') in order they update
- * themselves.
- */
enum {
ACTION_CHANGED,
LAST_SIGNAL
@@ -96,9 +87,9 @@ static void class_init( NAPivotClass *klass );
static void instance_init( GTypeInstance *instance, gpointer klass );
static GSList *register_interface_providers( const NAPivot *pivot );
static void instance_dispose( GObject *object );
-static void free_containers( GSList *list );
static void instance_finalize( GObject *object );
+static void free_consumers( GSList *list );
static void action_changed_handler( NAPivot *pivot, gpointer user_data );
static gboolean on_actions_changed_timeout( gpointer user_data );
static gulong time_val_diff( const GTimeVal *recent, const GTimeVal *old );
@@ -148,7 +139,7 @@ class_init( NAPivotClass *klass )
klass->private = g_new0( NAPivotClassPrivate, 1 );
/* register the signal and its default handler
- * this signal should be sent by the IIOProviders when an actions
+ * this signal should be sent by the IIOProvider when an actions
* has changed in the underlying storage subsystem
*/
st_signals[ ACTION_CHANGED ] = g_signal_new_class_handler(
@@ -175,9 +166,12 @@ instance_init( GTypeInstance *instance, gpointer klass )
NAPivot* self = NA_PIVOT( instance );
self->private = g_new0( NAPivotPrivate, 1 );
+
self->private->dispose_has_run = FALSE;
+ self->private->notified = NULL;
self->private->providers = register_interface_providers( self );
- self->private->actions = na_iio_provider_read_actions( G_OBJECT( self ));
+ self->private->actions = na_iio_provider_read_actions( self );
+ self->private->reload = TRUE;
}
static GSList *
@@ -207,7 +201,7 @@ instance_dispose( GObject *object )
self->private->dispose_has_run = TRUE;
/* release list of containers to be notified */
- free_containers( self->private->notified );
+ free_consumers( self->private->notified );
/* release list of actions */
na_pivot_free_actions( self->private->actions );
@@ -219,15 +213,6 @@ instance_dispose( GObject *object )
}
static void
-free_containers( GSList *containers )
-{
- GSList *ic;
- for( ic = containers ; ic ; ic = ic->next )
- ;
- g_slist_free( containers );
-}
-
-static void
instance_finalize( GObject *object )
{
static const gchar *thisfn = "na_pivot_instance_finalize";
@@ -253,11 +238,11 @@ instance_finalize( GObject *object )
}
/**
- * Allocates a new NAPivot object.
+ * na_pivot_new:
+ * @target: a GObject which wishes be notified of any modification of
+ * an action in any of the underlying I/O storage subsystems.
*
- * @target: the GObject which will handled Nautilus notification, and
- * should be notified when an actions is added, modified or removed in
- * one of the underlying storage subsystems.
+ * Allocates a new #NAPivot object.
*
* The target object will receive a "notify_nautilus_of_action_changed"
* message, without any parameter.
@@ -268,27 +253,52 @@ na_pivot_new( const GObject *target )
NAPivot *pivot = g_object_new( NA_PIVOT_TYPE, NULL );
if( target ){
- pivot->private->notified = g_slist_prepend( pivot->private->notified, ( gpointer ) target );
+ na_pivot_add_consumer( pivot, target );
}
return( pivot );
}
/**
+ * na_pivot_dump:
+ * @pivot: the #NAPivot object do be dumped.
+ *
+ * Dumps the content of a #NAPivot object.
+ */
+void
+na_pivot_dump( const NAPivot *pivot )
+{
+ static const gchar *thisfn = "na_pivot_dump";
+
+ GSList *it;
+ int i;
+ g_debug( "%s: notified=%p (%d elts)", thisfn, pivot->private->notified, g_slist_length( pivot->private->notified ));
+ g_debug( "%s: providers=%p (%d elts)", thisfn, pivot->private->providers, g_slist_length( pivot->private->providers ));
+ g_debug( "%s: actions=%p (%d elts)", thisfn, pivot->private->actions, g_slist_length( pivot->private->actions ));
+ for( it = pivot->private->actions, i = 0 ; it ; it = it->next ){
+ g_debug( "%s: [%d]: %p", thisfn, i++, it->data );
+ }
+}
+
+/**
+ * na_pivot_get_providers:
+ * @pivot: this #NAPivot instance.
+ * @type: the type of searched interface.
+ * For now, we only have NA_IIO_PROVIDER_TYPE interfaces.
+ *
* Returns the list of providers of the required interface.
*
* This function is called by interfaces API in order to find the
* list of providers registered for this given interface.
*
- * @pivot: this instance.
- *
- * @type: the type of searched interface.
+ * Returns: the list of providers of the required interface.
+ * This list should be na_pivot_free_providers().
*/
GSList *
na_pivot_get_providers( const NAPivot *pivot, GType type )
{
static const gchar *thisfn = "na_pivot_get_providers";
- g_debug( "%s", thisfn );
+ g_debug( "%s: pivot=%p", thisfn, pivot );
g_assert( NA_IS_PIVOT( pivot ));
@@ -304,24 +314,82 @@ na_pivot_get_providers( const NAPivot *pivot, GType type )
}
/**
- * Return the list of actions.
+ * na_pivot_free_providers:
+ * @providers: a list of providers.
+ *
+ * Frees a list of providers as returned from na_pivot_get_providers().
+ */
+void
+na_pivot_free_providers( GSList *providers )
+{
+ g_slist_free( providers );
+}
+
+/**
+ * na_pivot_get_actions:
+ * @pivot: this #NAPivot instance.
*
- * @pivot: this NAPivot object.
+ * Returns the list of actions.
*
- * The returned list is owned by this NAPivot object, and should not
- * be freed, nor unref by the caller.
+ * Returns: the list of #NAAction actions.
+ * The returned list is owned by this #NAPivot object, and should not
+ * be g_free(), nor g_object_unref() by the caller.
*/
GSList *
na_pivot_get_actions( const NAPivot *pivot )
{
g_assert( NA_IS_PIVOT( pivot ));
+
return( pivot->private->actions );
}
/**
- * Free a list of actions.
+ * na_pivot_reload_actions:
+ * @pivot: this #NAPivot instance.
+ *
+ * Reloads the list of actions from I/O providers.
+ */
+void
+na_pivot_reload_actions( NAPivot *pivot )
+{
+ g_assert( NA_IS_PIVOT( pivot ));
+
+ if( pivot->private->actions ){
+ na_pivot_free_actions( pivot->private->actions );
+ }
+
+ pivot->private->actions = na_iio_provider_read_actions( pivot );
+}
+
+/**
+ * na_pivot_get_duplicate_actions:
+ * @pivot: this #NAPivot instance.
*
- * @list: the GSList of NAActions to be freed.
+ * Returns an exact copy of the current list of actions.
+ *
+ * Returns: a #GSList of #NAAction actions.
+ * The caller should na_pivot_free_actions() after usage.
+ */
+GSList *
+na_pivot_get_duplicate_actions( const NAPivot *pivot )
+{
+ g_assert( NA_IS_PIVOT( pivot ));
+
+ GSList *list = NULL;
+ GSList *ia;
+
+ for( ia = pivot->private->actions ; ia ; ia = ia->next ){
+ list = g_slist_prepend( list, na_object_duplicate( NA_OBJECT( ia->data )));
+ }
+
+ return( list );
+}
+
+/**
+ * na_pivot_free_actions:
+ * @list: a #GSList of #NAActions to be freed.
+ *
+ * Frees a list of actions.
*/
void
na_pivot_free_actions( GSList *actions )
@@ -334,83 +402,183 @@ na_pivot_free_actions( GSList *actions )
}
/**
- * Return the specified action.
+ * na_pivot_add_action:
+ * @pivot: this #NAPivot instance.
+ * @action: the #NAAction to be added to the list.
+ *
+ * Adds a new #NAAction to the list of actions.
+ *
+ * We take the provided pointer. The provided #NAAction should so not
+ * be g_object_unref() by the caller.
+ */
+void
+na_pivot_add_action( NAPivot *pivot, const NAAction *action )
+{
+ g_assert( NA_IS_PIVOT( pivot ));
+
+ pivot->private->actions = g_slist_prepend( pivot->private->actions, ( gpointer ) action );
+}
+
+/**
+ * na_pivot_remove_action:
+ * @pivot: this #NAPivot instance.
+ * @action: the #NAAction to be removed to the list.
*
- * @pivot: this NAPivot object.
+ * Removes a #NAAction from the list of actions.
*
- * @uuid: required globally unique identifier (uuid).
+ * Note that #NAPivot also g_object_unref() the removed #NAAction.
+ */
+void
+na_pivot_remove_action( NAPivot *pivot, NAAction *action )
+{
+ g_assert( NA_IS_PIVOT( pivot ));
+
+ pivot->private->actions = g_slist_remove( pivot->private->actions, ( gconstpointer ) action );
+ g_object_unref( action );
+}
+
+/**
+ * na_pivot_get_action:
+ * @pivot: this #NAPivot instance.
+ * @uuid: the required globally unique identifier (uuid).
*
- * Returns the specified NAAction object, or NULL if not found.
+ * Returns the specified action.
*
- * The returned pointer is owned by NAPivot, and should not be freed
- * nor unref by the caller.
+ * Returns: the required #NAAction object, or NULL if not found.
+ * The returned pointer is owned by #NAPivot, and should not be
+ * g_free() nor g_object_unref() by the caller.
*/
-GObject *
-na_pivot_get_action( NAPivot *pivot, const gchar *uuid )
+NAAction *
+na_pivot_get_action( const NAPivot *pivot, const gchar *uuid )
{
- GSList *ia;
- NAAction *act;
- GObject *found = NULL;
- uuid_t uua, uub;
- gchar *uuid_act;
+ uuid_t uua, i_uub;
g_assert( NA_IS_PIVOT( pivot ));
+ if( !uuid || !strlen( uuid )){
+ return( NULL );
+ }
uuid_parse( uuid, uua );
+
+ GSList *ia;
for( ia = pivot->private->actions ; ia ; ia = ia->next ){
- act = NA_ACTION( ia->data );
- uuid_act = na_action_get_uuid( act );
- uuid_parse( uuid_act, uub );
- g_free( uuid_act );
- if( !uuid_compare( uua, uub )){
- found = G_OBJECT( act );
- break;
+
+ gchar *i_uuid = na_action_get_uuid( NA_ACTION( ia->data ));
+ uuid_parse( i_uuid, i_uub );
+ g_free( i_uuid );
+
+ if( !uuid_compare( uua, i_uub )){
+ return( NA_ACTION( ia->data ));
}
}
- return( found );
+ return( NULL );
}
/**
- * Write an action.
- *
- * @pivot: this NAPivot object.
- *
- * @action: action to be written by the storage subsystem.
- *
+ * na_pivot_write_action:
+ * @pivot: this #NAPivot instance.
+ * @action: a #NAAction action to be written by the storage subsystem.
* @message: the I/O provider can allocate and store here an error
* message.
*
- * Returns the IIOProvider return code.
+ * Writes an action.
+ *
+ * Returns: the #NAIIOProvider return code.
*/
guint
-na_pivot_write_action( NAPivot *pivot, const GObject *action, gchar **message )
+na_pivot_write_action( const NAPivot *pivot, NAAction *action, gchar **message )
{
g_assert( NA_IS_PIVOT( pivot ));
g_assert( NA_IS_ACTION( action ));
g_assert( message );
- return( na_iio_provider_write_action( G_OBJECT( pivot ), action, message ));
+ return( na_iio_provider_write_action( pivot, action, message ));
}
/**
- * Delete an action.
- *
- * @pivot: this NAPivot object.
- *
- * @action: action to be deleted from the storage subsystem.
- *
+ * na_pivot_delete_action:
+ * @pivot: this #NAPivot instance.
+ * @action: a #NAAction action to be deleted from the storage
+ * subsystem.
* @message: the I/O provider can allocate and store here an error
* message.
*
- * Returns the IIOProvider return code.
+ * Deletes an action from the I/O storage subsystem.
+ *
+ * Returns: the #NAIIOProvider return code.
*/
guint
-na_pivot_delete_action( NAPivot *pivot, const GObject *action, gchar **message )
+na_pivot_delete_action( const NAPivot *pivot, const NAAction *action, gchar **message )
{
g_assert( NA_IS_PIVOT( pivot ));
g_assert( NA_IS_ACTION( action ));
g_assert( message );
- return( na_iio_provider_delete_action( G_OBJECT( pivot ), action, message ));
+ return( na_iio_provider_delete_action( pivot, action, message ));
+}
+
+/**
+ * na_pivot_add_consumer:
+ * @pivot: this #NAPivot instance.
+ * @consumer: a #GObject which wishes be notified of any modification
+ * of an action in any of the underlying I/O storage subsystems.
+ *
+ * Registers a new consumer to be notified of an action modification.
+ */
+void
+na_pivot_add_consumer( NAPivot *pivot, const GObject *consumer )
+{
+ static const gchar *thisfn = "na_pivot_add_consumer";
+ g_debug( "%s: pivot=%p, consumer=%p", thisfn, pivot, consumer );
+
+ g_assert( NA_IS_PIVOT( pivot ));
+ g_assert( G_IS_OBJECT( consumer ));
+
+ pivot->private->notified = g_slist_prepend( pivot->private->notified, ( gpointer ) consumer );
+}
+
+/**
+ * na_pivot_get_automatic_reload:
+ * @pivot: this #NAPivot instance.
+ *
+ * Returns: the automatic reload flag.
+ */
+gboolean
+na_pivot_get_automatic_reload( const NAPivot *pivot )
+{
+ g_assert( NA_IS_PIVOT( pivot ));
+
+ return( pivot->private->reload );
+}
+
+/**
+ * na_pivot_set_automatic_reload:
+ * @pivot: this #NAPivot instance.
+ * @reload: whether this #NAPivot instance should automatically reload
+ * its list of actions when I/O providers advertize it of a
+ * modification.
+ *
+ * Sets the automatic reload flag.
+ *
+ * Note that even if the #NAPivot instance is not authorized to
+ * automatically reload its list of actions when it is advertized of
+ * a modification by one of the I/O providers, it always sends an
+ * ad-hoc notification to its consumers.
+ */
+void
+na_pivot_set_automatic_reload( NAPivot *pivot, gboolean reload )
+{
+ g_assert( NA_IS_PIVOT( pivot ));
+
+ pivot->private->reload = reload;
+}
+
+static void
+free_consumers( GSList *consumers )
+{
+ GSList *ic;
+ for( ic = consumers ; ic ; ic = ic->next )
+ ;
+ g_slist_free( consumers );
}
/*
@@ -457,7 +625,7 @@ on_actions_changed_timeout( gpointer user_data )
GTimeVal now;
g_assert( NA_IS_PIVOT( user_data ));
- NAPivot *pivot = NA_PIVOT( user_data );
+ const NAPivot *pivot = NA_PIVOT( user_data );
g_get_current_time( &now );
gulong diff = time_val_diff( &now, &st_last_event );
@@ -465,12 +633,14 @@ on_actions_changed_timeout( gpointer user_data )
return( TRUE );
}
- na_pivot_free_actions( pivot->private->actions );
- pivot->private->actions = na_iio_provider_read_actions( G_OBJECT( pivot ));
+ if( pivot->private->reload ){
+ na_pivot_free_actions( pivot->private->actions );
+ pivot->private->actions = na_iio_provider_read_actions( pivot );
+ }
GSList *ic;
for( ic = pivot->private->notified ; ic ; ic = ic->next ){
- na_ipivot_container_notify( NA_IPIVOT_CONTAINER( ic->data ));
+ na_ipivot_consumer_notify( NA_IPIVOT_CONSUMER( ic->data ));
}
st_event_source_id = 0;
@@ -522,13 +692,3 @@ na_pivot_free_notify( NAPivotNotify *npn )
g_free( npn );
}
}
-
-/**
- * Records a container which has to be notified of a modification of
- * the list of actions.
- */
-void
-na_pivot_add_notified( NAPivot *pivot, GObject *container )
-{
- pivot->private->notified = g_slist_prepend( pivot->private->notified, container );
-}
diff --git a/src/common/na-pivot.h b/src/common/na-pivot.h
index db57e58..b4d07a9 100644
--- a/src/common/na-pivot.h
+++ b/src/common/na-pivot.h
@@ -31,17 +31,53 @@
#ifndef __NA_PIVOT_H__
#define __NA_PIVOT_H__
-/*
- * NAPivot class definition.
+/**
+ * SECTION: na_pivot
+ * @short_description: #NAPivot class definition.
+ * @include: common/na-pivot.h
*
* A consuming program should allocate one new NAPivot object in its
* startup phase. The class takes care of declaring the I/O interface,
* while registering the known providers. The object will then load
* itself the existing list of actions.
+ *
+ * Notification system
+ *
+ * Each I/O storage provider should monitor modifications/deletions of
+ * actions, and advertize this #NAPivot, which itself will then
+ * advertize any registered consumers.
+ *
+ * This notification system is so a double-stage one :
+ *
+ * 1. When an I/O storage subsystem detects a change on an action, it
+ * should emit the "notify_pivot_of_action_changed" signal to notify
+ * #NAPivot of this change. The user data associated with the
+ * message should be a #gpointer to a #NAPivotNotify structure.
+ *
+ * When this signal is received, #NAPivot updates accordingly the
+ * list of actions it maintains.
+ *
+ * It is up to the I/O storage provider to decide if it sends a
+ * message for each and every one detected modification, or if it
+ * sends only one message for a whole, maybe coherent, set of
+ * updates.
+ *
+ * This first stage message is defined in na-iio-provider.h,
+ * as NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED.
+ *
+ * 2. When #NAPivot has successfully updated its list of actions, it
+ * notifies its consumers in order they update themselves.
+ *
+ * Note that #NAPivot tries to factorize notification messages, and
+ * to notify its consumers only once even if it has itself received
+ * many elementary notifications from the underlying I/O storage
+ * subsystem.
*/
#include <glib-object.h>
+#include "na-action-class.h"
+
G_BEGIN_DECLS
#define NA_PIVOT_TYPE ( na_pivot_get_type())
@@ -67,18 +103,29 @@ typedef struct {
}
NAPivotClass;
-GType na_pivot_get_type( void );
+GType na_pivot_get_type( void );
-NAPivot *na_pivot_new( const GObject *notified );
+NAPivot *na_pivot_new( const GObject *notified );
+void na_pivot_dump( const NAPivot *pivot );
-GSList *na_pivot_get_providers( const NAPivot *pivot, GType type );
+GSList *na_pivot_get_providers( const NAPivot *pivot, GType type );
+void na_pivot_free_providers( GSList *providers );
-GSList *na_pivot_get_actions( const NAPivot *pivot );
-void na_pivot_free_actions( GSList *actions );
+GSList *na_pivot_get_actions( const NAPivot *pivot );
+void na_pivot_reload_actions( NAPivot *pivot );
+GSList *na_pivot_get_duplicate_actions( const NAPivot *pivot );
+void na_pivot_free_actions( GSList *actions );
+void na_pivot_add_action( NAPivot *pivot, const NAAction *action );
+void na_pivot_remove_action( NAPivot *pivot, NAAction *action );
-GObject *na_pivot_get_action( NAPivot *pivot, const gchar *uuid );
-guint na_pivot_write_action( NAPivot *pivot, const GObject *action, gchar **message );
-guint na_pivot_delete_action( NAPivot *pivot, const GObject *action, gchar **message );
+NAAction *na_pivot_get_action( const NAPivot *pivot, const gchar *uuid );
+guint na_pivot_write_action( const NAPivot *pivot, NAAction *action, gchar **message );
+guint na_pivot_delete_action( const NAPivot *pivot, const NAAction *action, gchar **message );
+
+void na_pivot_add_consumer( NAPivot *pivot, const GObject *consumer );
+
+gboolean na_pivot_get_automatic_reload( const NAPivot *pivot );
+void na_pivot_set_automatic_reload( NAPivot *pivot, gboolean reload );
/* data passed from the storage subsystem when an action is changed
*/
@@ -99,8 +146,6 @@ typedef struct {
void na_pivot_free_notify( NAPivotNotify *data );
-void na_pivot_add_notified( NAPivot *pivot, GObject *container );
-
G_END_DECLS
#endif /* __NA_PIVOT_H__ */
diff --git a/src/common/na-utils.c b/src/common/na-utils.c
index 131f7f0..5dee803 100644
--- a/src/common/na-utils.c
+++ b/src/common/na-utils.c
@@ -218,7 +218,7 @@ na_utils_dump_string_list( GSList *list )
/**
* Converts a list of strings to a comma-separated list of strings,
- * enclosed by brackets (GConf export format).
+ * enclosed by brackets (dump format, GConf export format).
*/
gchar *
na_utils_gslist_to_schema( GSList *list )
diff --git a/src/nact/Makefile.am b/src/nact/Makefile.am
index ae442d6..cb3da93 100644
--- a/src/nact/Makefile.am
+++ b/src/nact/Makefile.am
@@ -67,6 +67,8 @@ nautilus_actions_config_SOURCES = \
nact-icommand-tab.h \
nact-iconditions-tab.c \
nact-iconditions-tab.h \
+ nact-imenubar.c \
+ nact-imenubar.h \
nact-iprefs.c \
nact-iprefs.h \
nact-main.c \
diff --git a/src/nact/nact-application.c b/src/nact/nact-application.c
index b7e8dd7..b99d269 100644
--- a/src/nact/nact-application.c
+++ b/src/nact/nact-application.c
@@ -35,8 +35,6 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-#include <common/na-pivot.h>
-
#include "nact-application.h"
#include "nact-main-window.h"
@@ -60,7 +58,7 @@ enum {
PROP_PIVOT = 1
};
-#define PROP_PIVOT_STR "pivot"
+#define PROP_PIVOT_STR "nact-application-pivot"
static GObjectClass *st_parent_class = NULL;
@@ -306,7 +304,7 @@ get_main_window( BaseApplication *application )
GObject *window = G_OBJECT( nact_main_window_new( G_OBJECT( application )));
- na_pivot_add_notified( NA_PIVOT( nact_application_get_pivot( NACT_APPLICATION( application ))), window );
+ na_pivot_add_consumer( NA_PIVOT( nact_application_get_pivot( NACT_APPLICATION( application ))), window );
return( window );
}
@@ -319,9 +317,9 @@ get_main_window( BaseApplication *application )
* The returned pointer is owned by the NactApplication object.
* It should not be freed not unref by the caller.
*/
-GObject *
+NAPivot *
nact_application_get_pivot( NactApplication *application )
{
g_assert( NACT_IS_APPLICATION( application ));
- return( G_OBJECT( application->private->pivot ));
+ return( NA_PIVOT( application->private->pivot ));
}
diff --git a/src/nact/nact-application.h b/src/nact/nact-application.h
index 0f26421..3232965 100644
--- a/src/nact/nact-application.h
+++ b/src/nact/nact-application.h
@@ -37,6 +37,8 @@
* This is the main class for UI programs.
*/
+#include <common/na-pivot.h>
+
#include "base-application.h"
G_BEGIN_DECLS
@@ -68,7 +70,7 @@ GType nact_application_get_type( void );
NactApplication *nact_application_new_with_args( int argc, char **argv );
-GObject *nact_application_get_pivot( NactApplication *application );
+NAPivot *nact_application_get_pivot( NactApplication *application );
G_END_DECLS
diff --git a/src/nact/nact-assist-import.c b/src/nact/nact-assist-import.c
index 13e7f73..d90a2d3 100644
--- a/src/nact/nact-assist-import.c
+++ b/src/nact/nact-assist-import.c
@@ -499,7 +499,7 @@ do_import( NactAssistImport *window, GtkAssistant *assistant )
msg = NULL;
NAAction *action = nact_gconf_reader_import( G_OBJECT( window ), ( const gchar * ) is->data, &msg );
- if( action && na_pivot_write_action( pivot, G_OBJECT( action ), &error ) != NA_IIO_PROVIDER_WRITE_OK ){
+ if( action && na_pivot_write_action( pivot, action, &error ) != NA_IIO_PROVIDER_WRITE_OK ){
g_object_unref( action );
action = NULL;
msg = g_slist_append( msg, error );
diff --git a/src/nact/nact-gconf-reader.c b/src/nact/nact-gconf-reader.c
index 2eab015..42d8b3b 100644
--- a/src/nact/nact-gconf-reader.c
+++ b/src/nact/nact-gconf-reader.c
@@ -334,7 +334,7 @@ gconf_reader_parse_schemalist( NactGConfReader *reader, xmlNode *schema )
xmlNode *iter;
- reader->private->action = na_action_new( NULL );
+ reader->private->action = na_action_new();
reader->private->uuid_set = FALSE;
for( iter = schema->children ; iter ; iter = iter->next ){
@@ -554,7 +554,7 @@ gconf_reader_parse_applyto( NactGConfReader *reader, xmlNode *node )
if( ret ){
if( !reader->private->uuid_set ){
- GObject *object = na_pivot_get_action( reader->private->pivot, uuid );
+ NAAction *object = na_pivot_get_action( reader->private->pivot, uuid );
if( object ){
add_message( reader, ERR_UUID_ALREADY_EXISTS, uuid );
ret = FALSE;
@@ -581,8 +581,8 @@ gconf_reader_parse_applyto( NactGConfReader *reader, xmlNode *node )
reader->private->profile = NA_ACTION_PROFILE( na_action_get_profile( reader->private->action, profile ));
if( !reader->private->profile ){
- reader->private->profile = na_action_profile_new( NA_OBJECT( reader->private->action ), profile );
- na_action_add_profile( reader->private->action, NA_OBJECT( reader->private->profile ));
+ reader->private->profile = na_action_profile_new();
+ na_action_attach_profile( reader->private->action, reader->private->profile );
}
}
diff --git a/src/nact/nact-iaction-tab.c b/src/nact/nact-iaction-tab.c
index 336b6c2..034ce9a 100644
--- a/src/nact/nact-iaction-tab.c
+++ b/src/nact/nact-iaction-tab.c
@@ -51,14 +51,21 @@ enum {
ICON_N_COLUMN
};
+/* IActionTab properties, set on the main window
+ */
+#define PROP_IACTION_TAB_STATUS_CONTEXT "nact-iaction-tab-status-context"
+
static GType register_type( void );
static void interface_base_init( NactIActionTabInterface *klass );
static void interface_base_finalize( NactIActionTabInterface *klass );
+static GtkWidget *v_get_status_bar( NactWindow *window );
+static NAObject *v_get_selected( NactWindow *window );
static NAAction *v_get_edited_action( NactWindow *window );
static void v_field_modified( NactWindow *window );
static void on_label_changed( GtkEntry *entry, gpointer user_data );
+static void check_for_label( NactWindow *window, GtkEntry *entry, const gchar *label );
static void on_tooltip_changed( GtkEntry *entry, gpointer user_data );
static void on_icon_changed( GtkEntry *entry, gpointer user_data );
static void on_icon_browse( GtkButton *button, gpointer user_data );
@@ -68,6 +75,11 @@ static gint sort_stock_ids( gconstpointer a, gconstpointer b );
static gchar *strip_underscore( const gchar *text );
static void display_icon( NactWindow *window, GtkWidget *image, gboolean display );
+static void display_status( NactWindow *window, const gchar *status );
+static void hide_status( NactWindow *window );
+static guint get_status_context( NactWindow *window );
+static void set_status_context( NactWindow *window, guint context );
+
GType
nact_iaction_tab_get_type( void )
{
@@ -147,6 +159,13 @@ nact_iaction_tab_initial_load( NactWindow *dialog )
GtkWidget *icon_widget = base_window_get_widget( BASE_WINDOW( dialog ), "ActionIconComboBoxEntry" );
gtk_combo_box_set_model( GTK_COMBO_BOX( icon_widget ), create_stock_icon_model());
icon_combo_list_fill( GTK_COMBO_BOX_ENTRY( icon_widget ));
+
+ GtkWidget *status_bar = v_get_status_bar( dialog );
+ if( status_bar ){
+ g_assert( GTK_IS_STATUSBAR( status_bar ));
+ guint context = gtk_statusbar_get_context_id( GTK_STATUSBAR( status_bar ), "nact-iaction-tab" );
+ set_status_context( dialog, context );
+ }
}
void
@@ -185,26 +204,45 @@ nact_iaction_tab_dispose( NactWindow *dialog )
g_debug( "%s: dialog=%p", thisfn, dialog );
}
+/*
+ * disable the tab if current row is a profile and the action has more
+ * than one profile
+ */
void
nact_iaction_tab_set_action( NactWindow *dialog, const NAAction *action )
{
/*static const gchar *thisfn = "nact_iaction_tab_set_action";
g_debug( "%s: dialog=%p, action=%p", thisfn, dialog, action );*/
+ NAObject *current = v_get_selected( dialog );
+ gboolean enabled = TRUE;
+ if( NA_IS_ACTION_PROFILE( current)){
+ if( na_action_get_profiles_count( action ) > 1 ){
+ enabled = FALSE;
+ }
+ }
+
GtkWidget *label_widget = base_window_get_widget( BASE_WINDOW( dialog ), "ActionLabelEntry" );
gchar *label = na_action_get_label( action );
gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
+ gtk_widget_set_sensitive( label_widget, enabled );
+ check_for_label( dialog, GTK_ENTRY( label_widget ), label );
g_free( label );
GtkWidget *tooltip_widget = base_window_get_widget( BASE_WINDOW( dialog ), "ActionTooltipEntry" );
gchar *tooltip = na_action_get_tooltip( action );
gtk_entry_set_text( GTK_ENTRY( tooltip_widget ), tooltip );
+ gtk_widget_set_sensitive( tooltip_widget, enabled );
g_free( tooltip );
GtkWidget *icon_widget = base_window_get_widget( BASE_WINDOW( dialog ), "ActionIconComboBoxEntry" );
gchar *icon = na_action_get_icon( action );
gtk_entry_set_text( GTK_ENTRY( GTK_BIN( icon_widget )->child ), icon );
+ gtk_widget_set_sensitive( icon_widget, enabled );
g_free( icon );
+
+ GtkWidget *button = base_window_get_widget( BASE_WINDOW( dialog ), "ActionIconBrowseButton" );
+ gtk_widget_set_sensitive( button, enabled );
}
/**
@@ -219,6 +257,28 @@ nact_iaction_tab_has_label( NactWindow *window )
return( g_utf8_strlen( label, -1 ) > 0 );
}
+static GtkWidget *
+v_get_status_bar( NactWindow *window )
+{
+ if( NACT_IACTION_TAB_GET_INTERFACE( window )->get_status_bar ){
+ return( NACT_IACTION_TAB_GET_INTERFACE( window )->get_status_bar( window ));
+ }
+
+ return( NULL );
+}
+
+static NAObject *
+v_get_selected( NactWindow *window )
+{
+ g_assert( NACT_IS_IACTION_TAB( window ));
+
+ if( NACT_IACTION_TAB_GET_INTERFACE( window )->get_selected ){
+ return( NACT_IACTION_TAB_GET_INTERFACE( window )->get_selected( window ));
+ }
+
+ return( NULL );
+}
+
static NAAction *
v_get_edited_action( NactWindow *window )
{
@@ -248,9 +308,34 @@ on_label_changed( GtkEntry *entry, gpointer user_data )
NactWindow *dialog = NACT_WINDOW( user_data );
NAAction *edited = v_get_edited_action( dialog );
- na_action_set_label( edited, gtk_entry_get_text( entry ));
+ const gchar *label = gtk_entry_get_text( entry );
+ na_action_set_label( edited, label );
+
+ /* 2009-07-20: about 900-1200 usec for ten loops */
+ /*int i;
+ GTimeVal begin, end;
+ g_get_current_time( &begin );
+ for( i=0 ; i<10 ; ++i ){
+ v_field_modified( dialog );
+ }
+ g_get_current_time( &end );
+ g_debug( "on_label_changed: %ld usec", ( 1000000 * ( end.tv_sec - begin.tv_sec )) + end.tv_usec - begin.tv_usec );*/
v_field_modified( dialog );
+ check_for_label( dialog, entry, label );
+}
+
+static void
+check_for_label( NactWindow *window, GtkEntry *entry, const gchar *label )
+{
+ hide_status( window );
+
+ NAAction *edited = v_get_edited_action( window );
+
+ if( edited && g_utf8_strlen( label, -1 ) == 0 ){
+ /* i18n: status bar message when the action label is empty */
+ display_status( window, _( "Caution: a label is mandatory for the action." ));
+ }
}
static void
@@ -467,3 +552,31 @@ display_icon( NactWindow *window, GtkWidget *image, gboolean show )
gtk_frame_set_shadow_type( frame, GTK_SHADOW_IN );
}
}
+
+static void
+display_status( NactWindow *window, const gchar *status )
+{
+ GtkWidget *bar = v_get_status_bar( window );
+ guint context = get_status_context( window );
+ gtk_statusbar_push( GTK_STATUSBAR( bar ), context, status );
+}
+
+static void
+hide_status( NactWindow *window )
+{
+ GtkWidget *bar = v_get_status_bar( window );
+ guint context = get_status_context( window );
+ gtk_statusbar_pop( GTK_STATUSBAR( bar ), context );
+}
+
+static guint
+get_status_context( NactWindow *window )
+{
+ return( GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( window ), PROP_IACTION_TAB_STATUS_CONTEXT )));
+}
+
+static void
+set_status_context( NactWindow *window, guint context )
+{
+ g_object_set_data( G_OBJECT( window ), PROP_IACTION_TAB_STATUS_CONTEXT, GUINT_TO_POINTER( context ));
+}
diff --git a/src/nact/nact-iaction-tab.h b/src/nact/nact-iaction-tab.h
index a304a31..4939879 100644
--- a/src/nact/nact-iaction-tab.h
+++ b/src/nact/nact-iaction-tab.h
@@ -51,12 +51,14 @@ typedef struct NactIActionTab NactIActionTab;
typedef struct NactIActionTabInterfacePrivate NactIActionTabInterfacePrivate;
typedef struct {
- GTypeInterface parent;
+ GTypeInterface parent;
NactIActionTabInterfacePrivate *private;
/* api */
- NAAction * ( *get_edited_action )( NactWindow *window );
- void ( *field_modified ) ( NactWindow *window );
+ GtkWidget * ( *get_status_bar ) ( NactWindow *window );
+ NAObject * ( *get_selected ) ( NactWindow *window );
+ NAAction * ( *get_edited_action )( NactWindow *window );
+ void ( *field_modified ) ( NactWindow *window );
}
NactIActionTabInterface;
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 73e251b..4ffbbf3 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -33,6 +33,7 @@
#endif
#include <gdk/gdkkeysyms.h>
+#include <string.h>
#include <common/na-action.h>
@@ -67,12 +68,20 @@ static GSList *v_get_actions( NactWindow *window );
static void v_on_selection_changed( GtkTreeSelection *selection, gpointer user_data );
static gboolean v_on_button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer data );
static gboolean v_on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, gpointer data );
+static gboolean v_is_modified_action( NactWindow *window, const NAAction *action );
+static gboolean v_is_valid_action( NactWindow *window, const NAAction *action );
+static gboolean v_is_modified_profile( NactWindow *window, const NAActionProfile *profile );
+static gboolean v_is_valid_profile( NactWindow *window, const NAActionProfile *profile );
+static void display_label( GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, NactWindow *window );
static void setup_action( GtkWidget *treeview, GtkTreeStore *model, GtkTreeIter *iter, NAAction *action );
static void setup_profile( GtkWidget *treeview, GtkTreeStore *model, GtkTreeIter *iter, NAActionProfile *profile );
static gint sort_actions_list( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, NactWindow *window );
static gboolean filter_visible( GtkTreeModel *model, GtkTreeIter *iter, gpointer data );
static GtkWidget *get_actions_list_widget( NactWindow *window );
+static GSList *get_expanded_rows( NactWindow *window );
+static void expand_rows( NactWindow *window, GSList *expanded );
+static void free_expanded_list( GSList *expanded );
GType
nact_iactions_list_get_type( void )
@@ -186,8 +195,15 @@ nact_iactions_list_initial_load( NactWindow *window )
"icon", gtk_cell_renderer_pixbuf_new(), "pixbuf", IACTIONS_LIST_ICON_COLUMN, NULL );
gtk_tree_view_append_column( GTK_TREE_VIEW( widget ), column );
- column = gtk_tree_view_column_new_with_attributes(
- "label", gtk_cell_renderer_text_new(), "text", IACTIONS_LIST_LABEL_COLUMN, NULL );
+ /*column = gtk_tree_view_column_new_with_attributes(
+ "label", gtk_cell_renderer_text_new(), "text", IACTIONS_LIST_LABEL_COLUMN, NULL );*/
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title( column, "label" );
+ gtk_tree_view_column_set_sort_column_id( column, IACTIONS_LIST_LABEL_COLUMN );
+ GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start( column, renderer, TRUE );
+ gtk_tree_view_column_set_cell_data_func(
+ column, renderer, ( GtkTreeCellDataFunc ) display_label, window, NULL );
gtk_tree_view_append_column( GTK_TREE_VIEW( widget ), column );
}
@@ -206,7 +222,7 @@ nact_iactions_list_runtime_init( NactWindow *window )
GtkWidget *widget = get_actions_list_widget( window );
g_assert( GTK_IS_WIDGET( widget ));
- nact_iactions_list_fill( window );
+ nact_iactions_list_fill( window, TRUE );
/* set up selection */
nact_window_signal_connect(
@@ -238,7 +254,7 @@ nact_iactions_list_runtime_init( NactWindow *window )
* Fill the listbox with current actions.
*/
void
-nact_iactions_list_fill( NactWindow *window )
+nact_iactions_list_fill( NactWindow *window, gboolean keep_expanded )
{
static const gchar *thisfn = "nact_iactions_list_fill";
g_debug( "%s: window=%p", thisfn, window );
@@ -247,6 +263,11 @@ nact_iactions_list_fill( NactWindow *window )
nact_iactions_list_set_is_filling_list( window, TRUE );
+ GSList *expanded = NULL;
+ if( keep_expanded ){
+ expanded = get_expanded_rows( window );
+ }
+
GtkWidget *widget = get_actions_list_widget( window );
GtkTreeModelFilter *tmf_model = GTK_TREE_MODEL_FILTER( gtk_tree_view_get_model( GTK_TREE_VIEW( widget )));
GtkTreeStore *ts_model = GTK_TREE_STORE( gtk_tree_model_filter_get_model( tmf_model ));
@@ -254,7 +275,7 @@ nact_iactions_list_fill( NactWindow *window )
GSList *actions = v_get_actions( window );
GSList *ia;
- /*g_debug( "%s: actions has %d elements", thisfn, g_slist_length( actions ));*/
+ g_debug( "%s: actions has %d elements", thisfn, g_slist_length( actions ));
for( ia = actions ; ia != NULL ; ia = ia->next ){
GtkTreeIter iter;
@@ -276,60 +297,164 @@ nact_iactions_list_fill( NactWindow *window )
}
/*g_debug( "%s: at end, actions has %d elements", thisfn, g_slist_length( actions ));*/
+ if( keep_expanded ){
+ expand_rows( window, expanded );
+ free_expanded_list( expanded );
+ }
+
nact_iactions_list_set_is_filling_list( window, FALSE );
}
/**
- * Set the selection to the named action.
- * If not found, we select the first following, else the previous one.
+ * Set the selection to the specified object.
+ *
+ * @type: select a profile or an action
+ * @uuid: uuid of the relevant action
+ * @label: label of the action, or of the profile
+ *
+ * if we want select an action:
+ * - set type = NA_ACTION_TYPE
+ * - set uuid = uuid of the action
+ * - set label = label of the action
+ *
+ * we are going to select:
+ * - an action
+ * - whose uuid is the requested uuid
+ * - or whose label is the most close of the required label (if uuid is not found)
+ *
+ * if we want select a profile
+ * - set type = NA_ACTION_PROFILE_TYPE
+ * - set uuid = uuid of the parent action
+ * - set label = label of the profile
+ *
+ * we are going to select:
+ * a) if the action is found
+ * a.1) if the action has more than one profile
+ * - a profile of the action
+ * - whose label is the most close of the required one
+ * a.2) if the action has only one profile
+ * - the action
+ * b) if the action is not found
+ * the last action of the list (this case should not appear)
*/
-/*void
-nact_iactions_list_set_selection( NactWindow *window, const gchar *uuid, const gchar *label )
+void
+nact_iactions_list_set_selection( NactWindow *window, GType type, const gchar *uuid, const gchar *label )
{
static const gchar *thisfn = "nact_iactions_list_set_selection";
- g_debug( "%s: window=%p, uuid=%s, label=%s", thisfn, window, uuid, label );
+ g_debug( "%s: window=%p, type=%s, uuid=%s, label=%s", thisfn, window, type == NA_ACTION_TYPE ? "action":"profile", uuid, label );
GtkWidget *list = get_actions_list_widget( window );
GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( list ));
+ /*GtkTreeModelFilter *tmf_model = GTK_TREE_MODEL_FILTER( gtk_tree_view_get_model( GTK_TREE_VIEW( list )));
+ GtkTreeStore *ts_model = GTK_TREE_STORE( gtk_tree_model_filter_get_model( tmf_model ));*/
GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW( list ));
- GtkTreeIter iter, previous;
- gtk_tree_selection_unselect_all( selection );
+ if( uuid && strlen( uuid )){
+ gboolean found = FALSE;
+ GtkTreeIter iter, previous;
+ /*gboolean iterok = gtk_tree_model_get_iter_first( GTK_TREE_MODEL( ts_model ), &iter );*/
+ gboolean iterok = gtk_tree_model_get_iter_first( model, &iter );
+ NAObject *iter_object;
+ gchar *iter_uuid, *iter_label;
+
+ while( iterok && !found ){
+ /*gtk_tree_model_get( GTK_TREE_MODEL( ts_model ), &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &iter_object, -1 );*/
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &iter_object, IACTIONS_LIST_LABEL_COLUMN, &iter_label, -1 );
+ g_debug( "%s: iter_object=%p", thisfn, iter_object );
+ g_assert( NA_IS_ACTION( iter_object ));
+
+ iter_uuid = na_action_get_uuid( NA_ACTION( iter_object ));
+ gint ret_uuid = g_ascii_strcasecmp( iter_uuid, uuid );
+ guint nb_profiles = na_action_get_profiles_count( NA_ACTION( iter_object ));
+
+ if( type == NA_ACTION_TYPE || ( ret_uuid == 0 && nb_profiles == 1 )){
+ gint ret_label = g_utf8_collate( iter_label, label );
+
+ if( ret_uuid == 0 || ret_label > 0 ){
+ gtk_tree_selection_select_iter( selection, &iter );
+ found = TRUE;
+ break;
+ }
- gboolean iterok = gtk_tree_model_get_iter_first( model, &iter );
- gboolean found = FALSE;
- NAAction *action;
- gchar *iter_uuid, *iter_label;
- gint count = 0;
-
- while( iterok && !found ){
- count += 1;
- gtk_tree_model_get(
- model,
- &iter,
- IACTIONS_LIST_NAOBJECT_COLUMN, &action, IACTIONS_LIST_LABEL_COLUMN, &iter_label,
- -1 );
-
- iter_uuid = na_action_get_uuid( action );
- gint ret_uuid = g_ascii_strcasecmp( iter_uuid, uuid );
- gint ret_label = g_utf8_collate( iter_label, label );
- if(( ret_uuid == 0 && ret_label == 0 ) || ret_label > 0 ){
- gtk_tree_selection_select_iter( selection, &iter );
- found = TRUE;
+ } else if( ret_uuid == 0 && gtk_tree_model_iter_has_child( model, &iter )){
+ GtkTreeIter iter_child, previous_child;
+ gboolean iter_child_ok = gtk_tree_model_iter_children( model, &iter_child, &iter );
+
+ while( iter_child_ok ){
+ gtk_tree_model_get( model, &iter_child, IACTIONS_LIST_NAOBJECT_COLUMN, &iter_object, IACTIONS_LIST_LABEL_COLUMN, &iter_label, -1 );
+ gint ret_label = g_utf8_collate( iter_label, label );
+
+ if( ret_label >= 0 ){
+ gtk_tree_selection_select_iter( selection, &iter_child );
+ found = TRUE;
+ break;
+ }
+ previous_child = iter_child;
+ iter_child_ok = gtk_tree_model_iter_next( model, &iter_child );
+ }
+ if( !found ){
+ gtk_tree_selection_select_iter( selection, &previous_child );
+ found = TRUE;
+ }
+ }
- } else {
previous = iter;
+ /*iterok = gtk_tree_model_iter_next( GTK_TREE_MODEL( ts_model ), &iter );*/
+ iterok = gtk_tree_model_iter_next( model, &iter );
+ }
+ if( !found ){
+ gtk_tree_selection_select_iter( selection, &previous );
}
- g_free( iter_uuid );
- g_free( iter_label );
- iterok = gtk_tree_model_iter_next( model, &iter );
+ } else {
+ gtk_tree_selection_unselect_all( selection );
}
+ /*
+ static const gchar *thisfn = "nact_iactions_list_set_selection";
+ g_debug( "%s: window=%p, uuid=%s, label=%s", thisfn, window, uuid, label );
+
+ GtkWidget *list = get_actions_list_widget( window );
+ GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( list ));
+ GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW( list ));
+ GtkTreeIter iter, previous;
+
+ gtk_tree_selection_unselect_all( selection );
+
+ gboolean iterok = gtk_tree_model_get_iter_first( model, &iter );
+ gboolean found = FALSE;
+ NAAction *action;
+ gchar *iter_uuid, *iter_label;
+ gint count = 0;
+
+ while( iterok && !found ){
+ count += 1;
+ gtk_tree_model_get(
+ model,
+ &iter,
+ IACTIONS_LIST_NAOBJECT_COLUMN, &action, IACTIONS_LIST_LABEL_COLUMN, &iter_label,
+ -1 );
+
+ iter_uuid = na_action_get_uuid( action );
+ gint ret_uuid = g_ascii_strcasecmp( iter_uuid, uuid );
+ gint ret_label = g_utf8_collate( iter_label, label );
+ if(( ret_uuid == 0 && ret_label == 0 ) || ret_label > 0 ){
+ gtk_tree_selection_select_iter( selection, &iter );
+ found = TRUE;
+
+ } else {
+ previous = iter;
+ }
- if( !found && count ){
- gtk_tree_selection_select_iter( selection, &previous );
- }
-}*/
+ g_free( iter_uuid );
+ g_free( iter_label );
+ iterok = gtk_tree_model_iter_next( model, &iter );
+ }
+
+ if( !found && count ){
+ gtk_tree_selection_select_iter( selection, &previous );
+ }
+ */
+}
/**
* Reset the focus on the ActionsList listbox.
@@ -345,16 +470,22 @@ nact_iactions_list_set_focus( NactWindow *window )
* Returns the currently selected action or profile.
*/
NAObject *
-nact_iactions_list_get_selected_action( NactWindow *window )
+nact_iactions_list_get_selected_object( NactWindow *window )
{
- GSList *list = nact_iactions_list_get_selected_actions( window );
+ NAObject *object = NULL;
- NAObject *object = NA_OBJECT( list->data );
+ GtkWidget *treeview = get_actions_list_widget( window );
+ GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( treeview ));
- g_assert( object );
- g_assert( NA_IS_OBJECT( object ));
+ GtkTreeModel *tm_model;
+ GtkTreeIter iter;
+ if( gtk_tree_selection_get_selected( selection, &tm_model, &iter )){
+
+ gtk_tree_model_get( tm_model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
- g_slist_free( list );
+ g_assert( object );
+ g_assert( NA_IS_OBJECT( object ));
+ }
return( object );
}
@@ -393,36 +524,76 @@ nact_iactions_list_get_selected_actions( NactWindow *window )
return( actions );
}
-
-void
+/*void
nact_iactions_list_set_modified( NactWindow *window, gboolean is_modified, gboolean can_save )
{
+}*/
+
+gboolean
+nact_iactions_list_is_expanded( NactWindow *window, const NAAction *action )
+{
+ GtkWidget *treeview = get_actions_list_widget( window );
+ GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ));
+
+ gboolean is_expanded = FALSE;
+ GtkTreeIter iter;
+ gboolean iterok = gtk_tree_model_get_iter_first( model, &iter );
+ NAObject *iter_object;
+
+ while( iterok ){
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &iter_object, -1 );
+
+ if( iter_object == NA_OBJECT( action )){
+ GtkTreePath *path = gtk_tree_model_get_path( model, &iter );
+ is_expanded = gtk_tree_view_row_expanded( GTK_TREE_VIEW( treeview ), path );
+ gtk_tree_path_free( path );
+ break;
+ }
+
+ iterok = gtk_tree_model_iter_next( model, &iter );
+ }
+
+ return( is_expanded );
}
/*
* Collapse / expand if actions has more than one profile
*/
void
-nact_iactions_list_toggle_collapse( NactWindow *window )
-{
- NAObject *object = nact_iactions_list_get_selected_action( window );
- if( NA_IS_ACTION( object )){
- NAAction *action = NA_ACTION( object );
- if( na_action_get_profiles_count( action ) > 1 ){
- GtkWidget *treeview = get_actions_list_widget( window );
- GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( treeview ));
- GtkTreeModel *model;
- GtkTreeIter iter;
- if( gtk_tree_selection_get_selected( selection, &model, &iter )){
+nact_iactions_list_toggle_collapse( NactWindow *window, const NAAction *action )
+{
+ static const gchar *thisfn = "nact_iactions_list_toggle_collapse";
+
+ GtkWidget *treeview = get_actions_list_widget( window );
+ GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ));
+
+ GtkTreeIter iter;
+ gboolean iterok = gtk_tree_model_get_iter_first( model, &iter );
+
+ while( iterok ){
+
+ NAObject *iter_object;
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &iter_object, -1 );
+ if( iter_object == NA_OBJECT( action )){
+
+ if( na_action_get_profiles_count( action ) > 1 ){
+
GtkTreePath *path = gtk_tree_model_get_path( model, &iter );
+
if( gtk_tree_view_row_expanded( GTK_TREE_VIEW( treeview ), path )){
gtk_tree_view_collapse_row( GTK_TREE_VIEW( treeview ), path );
+ g_debug( "%s: action=%p collapsed", thisfn, action );
+
} else {
gtk_tree_view_expand_row( GTK_TREE_VIEW( treeview ), path, TRUE );
+ g_debug( "%s: action=%p expanded", thisfn, action );
}
+
gtk_tree_path_free( path );
}
+ break;
}
+ iterok = gtk_tree_model_iter_next( model, &iter );
}
}
@@ -610,10 +781,98 @@ v_on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, gpointer user_dat
stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_enter_key_pressed( widget, event, user_data );
}
}
+ if( event->keyval == GDK_Delete || event->keyval == GDK_KP_Delete ){
+ if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_delete_key_pressed ){
+ stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_delete_key_pressed( widget, event, user_data );
+ }
+ }
}
return( stop );
}
+static gboolean
+v_is_modified_action( NactWindow *window, const NAAction *action )
+{
+ if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_modified_action ){
+ return( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_modified_action( window, action ));
+ }
+
+ return( FALSE );
+}
+
+static gboolean
+v_is_valid_action( NactWindow *window, const NAAction *action )
+{
+ if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_valid_action ){
+ return( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_valid_action( window, action ));
+ }
+
+ return( FALSE );
+}
+
+static gboolean
+v_is_modified_profile( NactWindow *window, const NAActionProfile *profile )
+{
+ if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_modified_profile ){
+ return( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_modified_profile( window, profile ));
+ }
+
+ return( FALSE );
+}
+
+static gboolean
+v_is_valid_profile( NactWindow *window, const NAActionProfile *profile )
+{
+ if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_valid_profile ){
+ return( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_valid_profile( window, profile ));
+ }
+
+ return( FALSE );
+}
+
+/*
+ * action modified: italic
+ * action not saveable: red
+ */
+static void
+display_label( GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, NactWindow *window )
+{
+ NAObject *object;
+ gtk_tree_model_get( model, iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+
+ if( object ){
+ g_assert( NA_IS_OBJECT( object ));
+ gchar *label = na_object_get_label( object );
+ gboolean modified = FALSE;
+ gboolean valid = TRUE;
+
+ if( NA_IS_ACTION( object )){
+ modified = v_is_modified_action( window, NA_ACTION( object ));
+ valid = v_is_valid_action( window, NA_ACTION( object ));
+
+ } else {
+ g_assert( NA_IS_ACTION_PROFILE( object ));
+ modified = v_is_modified_profile( window, NA_ACTION_PROFILE( object ));
+ valid = v_is_valid_profile( window, NA_ACTION_PROFILE( object ));
+ }
+
+ if( modified ){
+ g_object_set( cell, "style", PANGO_STYLE_ITALIC, "style-set", TRUE, NULL );
+ } else {
+ g_object_set( cell, "style-set", FALSE, NULL );
+ }
+ if( valid ){
+ g_object_set( cell, "foreground-set", FALSE, NULL );
+ } else {
+ g_object_set( cell, "foreground", "Red", "foreground-set", TRUE, NULL );
+ }
+
+ g_object_set( cell, "text", label, NULL );
+
+ g_free( label );
+ }
+}
+
static void
setup_action( GtkWidget *treeview, GtkTreeStore *model, GtkTreeIter *iter, NAAction *action )
{
@@ -685,6 +944,7 @@ filter_visible( GtkTreeModel *model, GtkTreeIter *iter, gpointer data )
{
NAObject *object;
gtk_tree_model_get( model, iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+ /*g_debug( "nact_main_window_filer_visible: model=%p, iter=%p, data=%p, object=%p", model, iter, data, object );*/
if( object ){
if( NA_IS_ACTION( object )){
@@ -692,7 +952,7 @@ filter_visible( GtkTreeModel *model, GtkTreeIter *iter, gpointer data )
}
g_assert( NA_IS_ACTION_PROFILE( object ));
- NAAction *action = NA_ACTION( na_action_profile_get_action( NA_ACTION_PROFILE( object )));
+ NAAction *action = na_action_profile_get_action( NA_ACTION_PROFILE( object ));
return( na_action_get_profiles_count( action ) > 1 );
}
@@ -704,3 +964,66 @@ get_actions_list_widget( NactWindow *window )
{
return( base_window_get_widget( BASE_WINDOW( window ), "ActionsList" ));
}
+
+static GSList *
+get_expanded_rows( NactWindow *window )
+{
+ GSList *expanded = NULL;
+ GtkWidget *treeview = get_actions_list_widget( window );
+ GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ));
+
+ GtkTreeIter iter;
+ gboolean iterok = gtk_tree_model_get_iter_first( model, &iter );
+ NAObject *object;
+
+ while( iterok ){
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+
+ GtkTreePath *path = gtk_tree_model_get_path( model, &iter );
+
+ if( gtk_tree_view_row_expanded( GTK_TREE_VIEW( treeview ), path )){
+ expanded = g_slist_prepend( expanded, object );
+ }
+
+ gtk_tree_path_free( path );
+
+ iterok = gtk_tree_model_iter_next( model, &iter );
+ }
+
+ return( expanded );
+}
+
+static void
+expand_rows( NactWindow *window, GSList *expanded )
+{
+ GtkWidget *treeview = get_actions_list_widget( window );
+ GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ));
+
+ GtkTreeIter iter;
+ gboolean iterok = gtk_tree_model_get_iter_first( model, &iter );
+ NAObject *object;
+
+ while( iterok ){
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+
+ GSList *is;
+ for( is = expanded ; is ; is = is->next ){
+ if( object == NA_OBJECT( is->data )){
+
+ GtkTreePath *path = gtk_tree_model_get_path( model, &iter );
+ gtk_tree_view_expand_row( GTK_TREE_VIEW( treeview ), path, TRUE );
+ gtk_tree_path_free( path );
+
+ break;
+ }
+ }
+
+ iterok = gtk_tree_model_iter_next( model, &iter );
+ }
+}
+
+static void
+free_expanded_list( GSList *expanded )
+{
+ g_slist_free( expanded );
+}
diff --git a/src/nact/nact-iactions-list.h b/src/nact/nact-iactions-list.h
index 37e9bd6..f0d2f31 100644
--- a/src/nact/nact-iactions-list.h
+++ b/src/nact/nact-iactions-list.h
@@ -64,7 +64,12 @@ typedef struct {
gboolean ( *on_button_press_event )( GtkWidget *widget, GdkEventButton *event, gpointer data );
gboolean ( *on_key_pressed_event ) ( GtkWidget *widget, GdkEventKey *event, gpointer data );
gboolean ( *on_double_click ) ( GtkWidget *widget, GdkEventButton *event, gpointer data );
+ gboolean ( *on_delete_key_pressed )( GtkWidget *widget, GdkEventKey *event, gpointer data );
gboolean ( *on_enter_key_pressed ) ( GtkWidget *widget, GdkEventKey *event, gpointer data );
+ gboolean ( *is_modified_action ) ( NactWindow *window, const NAAction *action );
+ gboolean ( *is_valid_action ) ( NactWindow *window, const NAAction *action );
+ gboolean ( *is_modified_profile ) ( NactWindow *window, const NAActionProfile *profile );
+ gboolean ( *is_valid_profile ) ( NactWindow *window, const NAActionProfile *profile );
}
NactIActionsListInterface;
@@ -72,13 +77,14 @@ GType nact_iactions_list_get_type( void );
void nact_iactions_list_initial_load( NactWindow *window );
void nact_iactions_list_runtime_init( NactWindow *window );
-void nact_iactions_list_fill( NactWindow *window );
-NAObject *nact_iactions_list_get_selected_action( NactWindow *window );
+void nact_iactions_list_fill( NactWindow *window, gboolean keep_expanded );
+NAObject *nact_iactions_list_get_selected_object( NactWindow *window );
GSList * nact_iactions_list_get_selected_actions( NactWindow *window );
-/*void nact_iactions_list_set_selection( NactWindow *window, const gchar *uuid, const gchar *label );*/
+void nact_iactions_list_set_selection( NactWindow *window, GType type, const gchar *uuid, const gchar *label );
/*void nact_iactions_list_set_focus( NactWindow *window );*/
-void nact_iactions_list_set_modified( NactWindow *window, gboolean is_modified, gboolean can_save );
-void nact_iactions_list_toggle_collapse( NactWindow *window );
+/*void nact_iactions_list_set_modified( NactWindow *window, gboolean is_modified, gboolean can_save );*/
+gboolean nact_iactions_list_is_expanded( NactWindow *window, const NAAction *action );
+void nact_iactions_list_toggle_collapse( NactWindow *window, const NAAction *action );
void nact_iactions_list_update_selected( NactWindow *window, NAAction *action );
void nact_iactions_list_set_multiple_selection( NactWindow *window, gboolean multiple );
diff --git a/src/nact/nact-icommand-tab.c b/src/nact/nact-icommand-tab.c
index c62317c..fde1b58 100644
--- a/src/nact/nact-icommand-tab.c
+++ b/src/nact/nact-icommand-tab.c
@@ -48,17 +48,22 @@ struct NactICommandTabInterfacePrivate {
/* the GConf key used to read/write size and position of auxiliary dialogs
*/
-#define IPREFS_LEGEND_DIALOG "iconditions-legend-dialog"
-#define IPREFS_COMMAND_CHOOSER "iconditions-command-chooser"
+#define IPREFS_LEGEND_DIALOG "iconditions-legend-dialog"
+#define IPREFS_COMMAND_CHOOSER "iconditions-command-chooser"
/* a data set in the LegendDialog GObject
*/
-#define LEGEND_DIALOG_IS_VISIBLE "iconditions-legend-dialog-visible"
+#define LEGEND_DIALOG_IS_VISIBLE "iconditions-legend-dialog-visible"
+
+/* ICommandTab properties, set on the main window
+ */
+#define PROP_ICOMMAND_TAB_STATUS_CONTEXT "iconditions-status-context"
static GType register_type( void );
static void interface_base_init( NactICommandTabInterface *klass );
static void interface_base_finalize( NactICommandTabInterface *klass );
+static GtkWidget *v_get_status_bar( NactWindow *window );
static NAActionProfile *v_get_edited_profile( NactWindow *window );
static void v_field_modified( NactWindow *window );
static void v_get_isfiledir( NactWindow *window, gboolean *isfile, gboolean *isdir );
@@ -66,6 +71,7 @@ static gboolean v_get_multiple( NactWindow *window );
static GSList *v_get_schemes( NactWindow *window );
static void on_label_changed( GtkEntry *entry, gpointer user_data );
+static void check_for_label( NactWindow *window, GtkEntry *entry, const gchar *label );
static GtkWidget *get_label_entry( NactWindow *window );
static void on_path_changed( GtkEntry *entry, gpointer user_data );
static void on_path_browse( GtkButton *button, gpointer user_data );
@@ -81,6 +87,11 @@ static void hide_legend_dialog( NactWindow *window );
static GtkButton *get_legend_button( NactWindow *window );
static GtkWindow *get_legend_dialog( NactWindow *window );
+static void display_status( NactWindow *window, const gchar *status );
+static void hide_status( NactWindow *window );
+static guint get_status_context( NactWindow *window );
+static void set_status_context( NactWindow *window, guint context );
+
GType
nact_icommand_tab_get_type( void )
{
@@ -156,6 +167,13 @@ nact_icommand_tab_initial_load( NactWindow *dialog )
{
static const gchar *thisfn = "nact_icommand_tab_initial_load";
g_debug( "%s: dialog=%p", thisfn, dialog );
+
+ GtkWidget *status_bar = v_get_status_bar( dialog );
+ if( status_bar ){
+ g_assert( GTK_IS_STATUSBAR( status_bar ));
+ guint context = gtk_statusbar_get_context_id( GTK_STATUSBAR( status_bar ), "nact-iaction-tab" );
+ set_status_context( dialog, context );
+ }
}
void
@@ -209,6 +227,7 @@ nact_icommand_tab_set_profile( NactWindow *dialog, const NAActionProfile *profil
gchar *label = profile ? na_action_profile_get_label( profile ) : g_strdup( "" );
gtk_entry_set_text( GTK_ENTRY( label_entry ), label );
gtk_widget_set_sensitive( label_entry, profile != NULL );
+ check_for_label( dialog, GTK_ENTRY( label_entry ), label );
g_free( label );
GtkWidget *path_entry = get_path_entry( dialog );
@@ -242,6 +261,16 @@ nact_icommand_tab_has_label( NactWindow *window )
return( g_utf8_strlen( label, -1 ) > 0 );
}
+static GtkWidget *
+v_get_status_bar( NactWindow *window )
+{
+ if( NACT_ICOMMAND_TAB_GET_INTERFACE( window )->get_status_bar ){
+ return( NACT_ICOMMAND_TAB_GET_INTERFACE( window )->get_status_bar( window ));
+ }
+
+ return( NULL );
+}
+
static NAActionProfile *
v_get_edited_profile( NactWindow *window )
{
@@ -308,10 +337,26 @@ on_label_changed( GtkEntry *entry, gpointer user_data )
g_assert( NACT_IS_WINDOW( user_data ));
NactWindow *dialog = NACT_WINDOW( user_data );
- NAActionProfile *edited = NA_ACTION_PROFILE( v_get_edited_profile( dialog ));
+ NAActionProfile *edited = v_get_edited_profile( dialog );
+
if( edited ){
- na_action_profile_set_label( edited, gtk_entry_get_text( entry ));
+ const gchar *label = gtk_entry_get_text( entry );
+ na_action_profile_set_label( edited, label );
v_field_modified( dialog );
+ check_for_label( dialog, entry, label );
+ }
+}
+
+static void
+check_for_label( NactWindow *window, GtkEntry *entry, const gchar *label )
+{
+ hide_status( window );
+
+ NAActionProfile *edited = v_get_edited_profile( window );
+
+ if( edited && g_utf8_strlen( label, -1 ) == 0 ){
+ /* i18n: status bar message when the profile label is empty */
+ display_status( window, _( "Caution: a label is mandatory for the profile." ));
}
}
@@ -660,3 +705,31 @@ get_legend_dialog( NactWindow *window )
{
return( base_window_get_dialog( BASE_WINDOW( window ), "LegendDialog" ));
}
+
+static void
+display_status( NactWindow *window, const gchar *status )
+{
+ GtkWidget *bar = v_get_status_bar( window );
+ guint context = get_status_context( window );
+ gtk_statusbar_push( GTK_STATUSBAR( bar ), context, status );
+}
+
+static void
+hide_status( NactWindow *window )
+{
+ GtkWidget *bar = v_get_status_bar( window );
+ guint context = get_status_context( window );
+ gtk_statusbar_pop( GTK_STATUSBAR( bar ), context );
+}
+
+static guint
+get_status_context( NactWindow *window )
+{
+ return( GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( window ), PROP_ICOMMAND_TAB_STATUS_CONTEXT )));
+}
+
+static void
+set_status_context( NactWindow *window, guint context )
+{
+ g_object_set_data( G_OBJECT( window ), PROP_ICOMMAND_TAB_STATUS_CONTEXT, GUINT_TO_POINTER( context ));
+}
diff --git a/src/nact/nact-icommand-tab.h b/src/nact/nact-icommand-tab.h
index 18895c3..4fa8ff1 100644
--- a/src/nact/nact-icommand-tab.h
+++ b/src/nact/nact-icommand-tab.h
@@ -55,6 +55,7 @@ typedef struct {
NactICommandTabInterfacePrivate *private;
/* api */
+ GtkWidget * ( *get_status_bar ) ( NactWindow *window );
NAActionProfile * ( *get_edited_profile )( NactWindow *window );
void ( *field_modified ) ( NactWindow *window );
void ( *get_isfiledir ) ( NactWindow *window, gboolean *is_file, gboolean *is_dir );
diff --git a/src/nact/nact-iconditions-tab.h b/src/nact/nact-iconditions-tab.h
index 91136cb..664d245 100644
--- a/src/nact/nact-iconditions-tab.h
+++ b/src/nact/nact-iconditions-tab.h
@@ -43,7 +43,7 @@
G_BEGIN_DECLS
#define NACT_ICONDITIONS_TAB_TYPE ( nact_iconditions_tab_get_type())
-#define NACT_ICONDITIONS_TAB( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_ICONDITIONS_TAB_TYPE, NactIConditions_Tab ))
+#define NACT_ICONDITIONS_TAB( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_ICONDITIONS_TAB_TYPE, NactIConditionsTab ))
#define NACT_IS_ICONDITIONS_TAB( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_ICONDITIONS_TAB_TYPE ))
#define NACT_ICONDITIONS_TAB_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NACT_ICONDITIONS_TAB_TYPE, NactIConditionsTabInterface ))
diff --git a/src/nact/nact-imenubar.c b/src/nact/nact-imenubar.c
new file mode 100644
index 0000000..7ec4623
--- /dev/null
+++ b/src/nact/nact-imenubar.c
@@ -0,0 +1,936 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * This Program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+
+#include "nact-application.h"
+#include "nact-assist-export.h"
+#include "nact-assist-import.h"
+#include "nact-imenubar.h"
+
+/* private interface data
+ */
+struct NactIMenubarInterfacePrivate {
+};
+
+/* menubar properties, set on the main window
+ */
+#define PROP_IMENUBAR_STATUS_CONTEXT "nact-imenubar-status-context"
+#define PROP_IMENUBAR_DELETED_ACTIONS "nact-imenubar-deleted-actions"
+#define PROP_IMENUBAR_NEW_PROFILE_ITEM "nact-imenubar-new-profile-item"
+#define PROP_IMENUBAR_SAVE_ITEM "nact-imenubar-save-item"
+#define PROP_IMENUBAR_DELETE_ITEM "nact-imenubar-delete-item"
+#define PROP_IMENUBAR_EXPORT_ITEM "nact-imenubar-export-item"
+
+static GType register_type( void );
+static void interface_base_init( NactIMenubarInterface *klass );
+static void interface_base_finalize( NactIMenubarInterface *klass );
+
+static void create_file_menu( NactMainWindow *window, GtkMenuBar *bar );
+static void create_edit_menu( NactMainWindow *window, GtkMenuBar *bar );
+static void create_tools_menu( NactMainWindow *window, GtkMenuBar *bar );
+static void create_help_menu( NactMainWindow *window, GtkMenuBar *bar );
+static void signal_connect( NactMainWindow *window, GtkWidget *item, GCallback on_activated, GCallback on_selected );
+
+static void on_file_selected( GtkMenuItem *item, NactWindow *window );
+static void on_new_action_activated( GtkMenuItem *item, NactWindow *window );
+static void on_new_action_selected( GtkItem *item, NactWindow *window );
+static void on_new_profile_activated( GtkMenuItem *item, NactWindow *window );
+static void on_new_profile_selected( GtkItem *item, NactWindow *window );
+static void on_save_activated( GtkMenuItem *item, NactWindow *window );
+static void on_save_selected( GtkMenuItem *item, NactWindow *window );
+static void on_quit_activated( GtkMenuItem *item, NactWindow *window );
+static void on_quit_selected( GtkMenuItem *item, NactWindow *window );
+
+static void on_edit_selected( GtkMenuItem *item, NactWindow *window );
+static void on_delete_activated( GtkMenuItem *item, NactWindow *window );
+static void on_delete_selected( GtkItem *item, NactWindow *window );
+
+static void on_tools_selected( GtkMenuItem *item, NactWindow *window );
+static void on_import_activated( GtkMenuItem *item, NactWindow *window );
+static void on_import_selected( GtkItem *item, NactWindow *window );
+static void on_export_activated( GtkMenuItem *item, NactWindow *window );
+static void on_export_selected( GtkItem *item, NactWindow *window );
+
+static void on_about_activated( GtkMenuItem *item, NactWindow *window );
+static void on_about_selected( GtkItem *item, NactWindow *window );
+
+static void on_menu_item_deselected( GtkItem *item, NactWindow *window );
+static void display_status( NactWindow *window, const gchar *status );
+static void hide_status( NactWindow *window );
+
+static void v_add_action( NactWindow *window, NAAction *action );
+static void v_add_profile( NactWindow *window, NAActionProfile *profile );
+static void v_remove_action( NactWindow *window, NAAction *action );
+static GSList *v_get_deleted_actions( NactWindow *window );
+static void v_free_deleted_actions( NactWindow *window );
+static void v_push_removed_action( NactWindow *window, NAAction *action );
+static GSList *v_get_actions( NactWindow *window );
+static NAObject *v_get_selected( NactWindow *window );
+static GtkWidget *v_get_status_bar( NactWindow *window );
+static void v_setup_dialog_title( NactWindow *window );
+static void v_update_actions_list( NactWindow *window );
+static void v_select_actions_list( NactWindow *window, GType type, const gchar *uuid, const gchar *label );
+static gint v_count_actions( NactWindow *window );
+static gint v_count_modified_actions( NactWindow *window );
+static void v_on_save( NactWindow *window );
+
+static guint get_status_context( NactMainWindow *window );
+static void set_status_context( NactMainWindow *window, guint context );
+static GtkWidget *get_new_profile_item( NactWindow *window );
+static void set_new_profile_item( NactWindow *window, GtkWidget *item );
+static GtkWidget *get_save_item( NactWindow *window );
+static void set_save_item( NactWindow *window, GtkWidget *item );
+static GtkWidget *get_delete_item( NactWindow *window );
+static void set_delete_item( NactWindow *window, GtkWidget *item );
+static GtkWidget *get_export_item( NactWindow *window );
+static void set_export_item( NactWindow *window, GtkWidget *item );
+
+GType
+nact_imenubar_get_type( void )
+{
+ static GType iface_type = 0;
+
+ if( !iface_type ){
+ iface_type = register_type();
+ }
+
+ return( iface_type );
+}
+
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "nact_imenubar_register_type";
+ g_debug( "%s", thisfn );
+
+ static const GTypeInfo info = {
+ sizeof( NactIMenubarInterface ),
+ ( GBaseInitFunc ) interface_base_init,
+ ( GBaseFinalizeFunc ) interface_base_finalize,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL
+ };
+
+ GType type = g_type_register_static( G_TYPE_INTERFACE, "NactIMenubar", &info, 0 );
+
+ g_type_interface_add_prerequisite( type, NACT_WINDOW_TYPE );
+
+ return( type );
+}
+
+static void
+interface_base_init( NactIMenubarInterface *klass )
+{
+ static const gchar *thisfn = "nact_imenubar_interface_base_init";
+ static gboolean initialized = FALSE;
+
+ if( !initialized ){
+ g_debug( "%s: klass=%p", thisfn, klass );
+
+ klass->private = g_new0( NactIMenubarInterfacePrivate, 1 );
+
+ initialized = TRUE;
+ }
+}
+
+static void
+interface_base_finalize( NactIMenubarInterface *klass )
+{
+ static const gchar *thisfn = "nact_imenubar_interface_base_finalize";
+ static gboolean finalized = FALSE ;
+
+ if( !finalized ){
+ g_debug( "%s: klass=%p", thisfn, klass );
+
+ g_free( klass->private );
+
+ finalized = TRUE;
+ }
+}
+
+/**
+ * nact_imenubar_init:
+ * @window: the #NactMainWindow to which the menubar is attached.
+ *
+ * Creates the menubar.
+ */
+void
+nact_imenubar_init( NactMainWindow *window )
+{
+ g_assert( NACT_IS_MAIN_WINDOW( window ));
+ g_assert( NACT_IS_IMENUBAR( window ));
+
+ GtkWidget *vbox = base_window_get_widget( BASE_WINDOW( window ), "MenuBarVBox" );
+ GtkWidget *menubar= gtk_menu_bar_new();
+ gtk_container_add( GTK_CONTAINER( vbox ), menubar );
+
+ create_file_menu( window, GTK_MENU_BAR( menubar ));
+ create_edit_menu( window, GTK_MENU_BAR( menubar ));
+ create_tools_menu( window, GTK_MENU_BAR( menubar ));
+ create_help_menu( window, GTK_MENU_BAR( menubar ));
+
+ GtkWidget *status_bar = v_get_status_bar( NACT_WINDOW( window ));
+ if( status_bar ){
+ g_assert( GTK_IS_STATUSBAR( status_bar ));
+ guint context = gtk_statusbar_get_context_id( GTK_STATUSBAR( status_bar ), "nact-imenubar" );
+ set_status_context( window, context );
+ }
+}
+
+/**
+ * nact_imenubar_on_delete_key_pressed:
+ * @window: the #NactMainWindow to which the menubar is attached.
+ *
+ * Deletes the currently selected item.
+ */
+void
+nact_imenubar_on_delete_key_pressed( NactWindow *window )
+{
+ static const gchar *thisfn = "nact_imenubar_on_delete_key_pressed";
+ g_debug( "%s: window=%p", thisfn, window );
+
+ g_assert( NACT_IS_MAIN_WINDOW( window ));
+ g_assert( NACT_IS_IMENUBAR( window ));
+
+ on_delete_activated( NULL, window );
+}
+
+/**
+ * nact_imenubar_on_delete_event:
+ * @window: the #NactMainWindow to which the menubar is attached.
+ *
+ * Closes the main window via the standard 'Quit' item of the menubar.
+ *
+ * This functions is triggered by the main window when it receives the
+ * 'delete-event' event.
+ */
+void
+nact_imenubar_on_delete_event( NactWindow *window )
+{
+ static const gchar *thisfn = "nact_imenubar_on_delete_event";
+ g_debug( "%s: window=%p", thisfn, window );
+
+ g_assert( NACT_IS_MAIN_WINDOW( window ));
+ g_assert( NACT_IS_IMENUBAR( window ));
+
+ on_quit_activated( NULL, window );
+}
+
+static void
+create_file_menu( NactMainWindow *window, GtkMenuBar *menubar )
+{
+ /* i18n: File menu */
+ GtkWidget *file = gtk_menu_item_new_with_label( _( "_File" ));
+ gtk_menu_item_set_use_underline( GTK_MENU_ITEM( file ), TRUE );
+ gtk_menu_shell_append( GTK_MENU_SHELL( menubar ), file );
+ GtkWidget *menu = gtk_menu_new();
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( file ), menu );
+ nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( file ), "select", G_CALLBACK( on_file_selected ));
+
+ GtkWidget *item = gtk_image_menu_item_new_from_stock( GTK_STOCK_NEW, NULL );
+ /* i18n: 'New action' item in 'File' menu - use same accelerator than GTK_STOCK_NEW item */
+ gtk_menu_item_set_label( GTK_MENU_ITEM( item ), _( "_New action" ));
+ gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
+ signal_connect( window, item, G_CALLBACK( on_new_action_activated ), G_CALLBACK( on_new_action_selected ));
+
+ /* i18n: 'New profile' item in 'File' menu */
+ item = gtk_image_menu_item_new_with_label( _( "New _profile" ));
+ gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
+ gtk_menu_item_set_use_underline( GTK_MENU_ITEM( item ), TRUE );
+ set_new_profile_item( NACT_WINDOW( window ), item );
+ signal_connect( window, item, G_CALLBACK( on_new_profile_activated ), G_CALLBACK( on_new_profile_selected ));
+
+ item = gtk_image_menu_item_new_from_stock( GTK_STOCK_SAVE, NULL );
+ gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
+ set_save_item( NACT_WINDOW( window ), item );
+ signal_connect( window, item, G_CALLBACK( on_save_activated ), G_CALLBACK( on_save_selected ));
+
+ item = gtk_separator_menu_item_new();
+ gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
+
+ item = gtk_image_menu_item_new_from_stock( GTK_STOCK_QUIT, NULL );
+ gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
+ signal_connect( window, item, G_CALLBACK( on_quit_activated ), G_CALLBACK( on_quit_selected ));
+}
+
+static void
+create_edit_menu( NactMainWindow *window, GtkMenuBar *menubar )
+{
+ /* i18n: Edit menu */
+ GtkWidget *edit = gtk_menu_item_new_with_label( _( "_Edit" ));
+ gtk_menu_item_set_use_underline( GTK_MENU_ITEM( edit ), TRUE );
+ gtk_menu_shell_append( GTK_MENU_SHELL( menubar ), edit );
+ GtkWidget *menu = gtk_menu_new();
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( edit ), menu );
+ nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( edit ), "select", G_CALLBACK( on_edit_selected ));
+
+ /* i18n: Delete item in Edit menu */
+ GtkWidget *item = gtk_image_menu_item_new_from_stock( GTK_STOCK_DELETE, NULL );
+ gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
+ set_delete_item( NACT_WINDOW( window ), item );
+ signal_connect( window, item, G_CALLBACK( on_delete_activated ), G_CALLBACK( on_delete_selected ));
+}
+
+static void
+create_tools_menu( NactMainWindow *window, GtkMenuBar *menubar )
+{
+ /* i18n: Tools menu */
+ GtkWidget *tools = gtk_menu_item_new_with_label( _( "_Tools" ));
+ gtk_menu_item_set_use_underline( GTK_MENU_ITEM( tools ), TRUE );
+ gtk_menu_shell_append( GTK_MENU_SHELL( menubar ), tools );
+ GtkWidget *menu = gtk_menu_new();
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( tools ), menu );
+ nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( tools ), "select", G_CALLBACK( on_tools_selected ));
+
+ /* i18n: Import item in Tools menu */
+ GtkWidget *item = gtk_image_menu_item_new_with_label( _( "_Import" ));
+ gtk_menu_item_set_use_underline( GTK_MENU_ITEM( item ), TRUE );
+ gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
+ signal_connect( window, item, G_CALLBACK( on_import_activated ), G_CALLBACK( on_import_selected ));
+
+ /* i18n: Export item in Tools menu */
+ item = gtk_image_menu_item_new_with_label( _( "_Export" ));
+ gtk_menu_item_set_use_underline( GTK_MENU_ITEM( item ), TRUE );
+ gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
+ set_export_item( NACT_WINDOW( window ), item );
+ signal_connect( window, item, G_CALLBACK( on_export_activated ), G_CALLBACK( on_export_selected ));
+}
+
+static void
+create_help_menu( NactMainWindow *window, GtkMenuBar *menubar )
+{
+ /* i18n: Help menu */
+ GtkWidget *help = gtk_menu_item_new_with_label( _( "_Help" ));
+ gtk_menu_item_set_use_underline( GTK_MENU_ITEM( help ), TRUE );
+ gtk_menu_shell_append( GTK_MENU_SHELL( menubar ), help );
+ GtkWidget *menu = gtk_menu_new();
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM( help ), menu );
+
+ GtkWidget *item = gtk_image_menu_item_new_from_stock( GTK_STOCK_ABOUT, NULL );
+ gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
+ signal_connect( window, item, G_CALLBACK( on_about_activated ), G_CALLBACK( on_about_selected ));
+}
+
+static void
+signal_connect( NactMainWindow *window, GtkWidget *item, GCallback on_activated, GCallback on_selected )
+{
+ if( on_activated ){
+ nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "activate", on_activated );
+ }
+
+ if( on_selected ){
+ nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "select", on_selected );
+ nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "deselect", G_CALLBACK( on_menu_item_deselected ));
+ }
+}
+
+static void
+on_file_selected( GtkMenuItem *item, NactWindow *window )
+{
+ NAObject *object = v_get_selected( window );
+ gboolean new_profile_enabled = NA_IS_ACTION( object ) || NA_IS_ACTION_PROFILE( object );
+ GtkWidget *new_profile_item = get_new_profile_item( window );
+ gtk_widget_set_sensitive( new_profile_item, new_profile_enabled );
+
+ gint modified = v_count_modified_actions( window );
+ gboolean save_enabled = ( modified > 0 );
+ GtkWidget *save_item = get_save_item( window );
+ gtk_widget_set_sensitive( save_item, save_enabled );
+}
+
+static void
+on_new_action_activated( GtkMenuItem *item, NactWindow *window )
+{
+ NAAction *action = na_action_new_with_profile();
+ na_object_check_edited_status( NA_OBJECT( action ));
+ v_add_action( window, action );
+
+ v_update_actions_list( window );
+ v_setup_dialog_title( window );
+
+ gchar *uuid = na_action_get_uuid( action );
+ gchar *label = na_action_get_label( action );
+ v_select_actions_list( window, NA_ACTION_TYPE, uuid, label );
+ g_free( label );
+ g_free( uuid );
+}
+
+static void
+on_new_action_selected( GtkItem *item, NactWindow *window )
+{
+ /* i18n: tooltip displayed in the status bar when selecting the 'New action' item */
+ display_status( window, _( "Define a new action." ));
+}
+
+static void
+on_new_profile_activated( GtkMenuItem *item, NactWindow *window )
+{
+ NAObject *object = v_get_selected( window );
+ g_assert( NA_IS_OBJECT( object ));
+
+ NAAction *action = NA_IS_ACTION( object ) ?
+ NA_ACTION( object ) : na_action_profile_get_action( NA_ACTION_PROFILE( object ));
+
+ NAActionProfile *new_profile = na_action_profile_new();
+ g_debug( "nact_imenubar_on_new_profile_activated: action=%p, profile=%p", action, new_profile );
+
+ na_action_attach_profile( action, new_profile );
+ na_object_check_edited_status( NA_OBJECT( new_profile ));
+
+ v_add_profile( window, new_profile );
+
+ v_setup_dialog_title( window );
+ v_update_actions_list( window );
+
+ gchar *uuid = na_action_get_uuid( action );
+ gchar *label = na_action_profile_get_label( new_profile );
+ v_select_actions_list( window, NA_ACTION_PROFILE_TYPE, uuid, label );
+ g_free( label );
+ g_free( uuid );
+}
+
+static void
+on_new_profile_selected( GtkItem *item, NactWindow *window )
+{
+ /* i18n: tooltip displayed in the status bar when selecting the 'New profile' item */
+ display_status( window, _( "Define a new profile attached to the current action." ));
+}
+
+static void
+on_save_activated( GtkMenuItem *item, NactWindow *window )
+{
+ NactApplication *application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
+ NAPivot *pivot = nact_application_get_pivot( application );
+ GSList *actions = v_get_actions( window );
+ GSList *ia;
+
+ /* keep the current selection
+ * to be able to restore it at the end of the operation
+ */
+ NAObject *current = v_get_selected( window );
+ GType type;
+ gchar *uuid, *label;
+ if( NA_IS_ACTION( current )){
+ uuid = na_action_get_uuid( NA_ACTION( current ));
+ label = na_action_get_label( NA_ACTION( current ));
+ type = NA_ACTION_TYPE;
+
+ } else {
+ g_assert( NA_IS_ACTION_PROFILE( current ));
+ NAAction *action = na_action_profile_get_action( NA_ACTION_PROFILE( current ));
+ uuid = na_action_get_uuid( action );
+ label = na_action_profile_get_label( NA_ACTION_PROFILE( current ));
+ type = NA_ACTION_PROFILE_TYPE;
+ }
+
+ /* save the modified actions
+ * - remove the origin of pivot if any
+ * - add a duplicate of this action to pivot
+ * - set the duplicate as the origin of this action
+ * - reset the status
+ */
+ for( ia = actions ; ia ; ia = ia->next ){
+ NAAction *current = NA_ACTION( ia->data );
+ if( na_object_get_modified_status( NA_OBJECT( current ))){
+ if( nact_window_save_action( window, current )){
+
+ NAAction *origin = NA_ACTION( na_object_get_origin( NA_OBJECT( current )));
+ if( origin ){
+ na_pivot_remove_action( pivot, origin );
+ }
+
+ NAAction *dup_pivot = NA_ACTION( na_object_duplicate( NA_OBJECT( current )));
+ na_pivot_add_action( pivot, dup_pivot );
+
+ v_remove_action( window, current );
+ g_object_unref( current );
+
+ NAAction *dup_window = NA_ACTION( na_object_duplicate( NA_OBJECT( dup_pivot )));
+ v_add_action( window, dup_window );
+ na_object_check_edited_status( NA_OBJECT( dup_window ));
+ }
+ }
+ }
+
+ /* delete the removed actions
+ * - remove the origin of pivot if any
+ */
+ GSList *deleted = v_get_deleted_actions( window );
+ for( ia = deleted ; ia ; ia = ia->next ){
+ NAAction *current = NA_ACTION( ia->data );
+ if( nact_window_delete_action( window, current )){
+
+ NAAction *origin = NA_ACTION( na_object_get_origin( NA_OBJECT( current )));
+ if( origin ){
+ na_pivot_remove_action( pivot, origin );
+ }
+ }
+ }
+ v_free_deleted_actions( window );
+ v_on_save( window );
+
+ v_setup_dialog_title( window );
+ v_update_actions_list( window );
+ v_select_actions_list( window, type, uuid, label );
+ g_free( label );
+ g_free( uuid );
+}
+
+static void
+on_save_selected( GtkMenuItem *item, NactWindow *window )
+{
+ /* i18n: tooltip displayed in the status bar when selecting 'Save' item */
+ display_status( window, _( "Record all the modified actions." ));
+}
+
+static void
+on_quit_activated( GtkMenuItem *item, NactWindow *window )
+{
+ static const gchar *thisfn = "nact_imenubar_on_quit_activated";
+ g_debug( "%s: item=%p, window=%p", thisfn, item, window );
+
+ gint count = v_count_modified_actions( NACT_WINDOW( window ));
+ if( !count || nact_window_warn_count_modified( NACT_WINDOW( window ), count )){
+ g_object_unref( window );
+ }
+}
+
+static void
+on_quit_selected( GtkMenuItem *item, NactWindow *window )
+{
+ /* i18n: tooltip displayed in the status bar when selecting 'Quit' item */
+ display_status( window, _( "Quit the application." ));
+}
+
+static void
+on_edit_selected( GtkMenuItem *item, NactWindow *window )
+{
+ NAObject *object = v_get_selected( window );
+ gboolean delete_enabled = FALSE;
+ if( object ){
+ if( NA_IS_ACTION( object )){
+ delete_enabled = TRUE;
+ } else {
+ g_assert( NA_IS_ACTION_PROFILE( object ));
+ NAAction *action = na_action_profile_get_action( NA_ACTION_PROFILE( object ));
+ delete_enabled = ( na_action_get_profiles_count( action ) > 1 );
+ }
+ }
+ GtkWidget *delete_item = get_delete_item( window );
+ gtk_widget_set_sensitive( delete_item, delete_enabled );
+}
+
+static void
+on_delete_activated( GtkMenuItem *item, NactWindow *window )
+{
+ static const gchar *thisfn = "nact_imenubar_on_delete_activated";
+ g_debug( "%s: item=%p, window=%p", thisfn, item, window );
+
+ NAObject *object = v_get_selected( window );
+ gchar *uuid, *label;
+ GType type;
+
+ if( NA_IS_ACTION( object )){
+ uuid = na_action_get_uuid( NA_ACTION( object ));
+ label = na_action_get_label( NA_ACTION( object ));
+ type = NA_ACTION_TYPE;
+ v_remove_action( window, NA_ACTION( object ));
+ v_push_removed_action( window, NA_ACTION( object ));
+
+ } else {
+ g_assert( NA_IS_ACTION_PROFILE( object ));
+ NAAction *action = na_action_profile_get_action( NA_ACTION_PROFILE( object ));
+ uuid = na_action_get_uuid( action );
+ label = na_action_profile_get_label( NA_ACTION_PROFILE( object ));
+ type = NA_ACTION_PROFILE_TYPE;
+ g_assert( na_action_get_profiles_count( action ) > 1 );
+ na_action_remove_profile( action, NA_ACTION_PROFILE( object ));
+ na_object_check_edited_status( NA_OBJECT( action ));
+ }
+
+ v_setup_dialog_title( window );
+ v_update_actions_list( window );
+
+ v_select_actions_list( window, type, uuid, label );
+ g_free( label );
+ g_free( uuid );
+}
+
+static void
+on_delete_selected( GtkItem *item, NactWindow *window )
+{
+ /* i18n: tooltip displayed in the status bar when selecting the Delete item */
+ display_status( window, _( "Remove the selected action or profile from your configuration." ));
+}
+
+static void
+on_tools_selected( GtkMenuItem *item, NactWindow *window )
+{
+ gboolean export_enabled = v_count_actions( window );
+ GtkWidget *export_item = get_export_item( window );
+ gtk_widget_set_sensitive( export_item, export_enabled );
+}
+
+static void
+on_import_activated( GtkMenuItem *item, NactWindow *window )
+{
+ static const gchar *thisfn = "nact_imenubar_on_import_activated";
+ g_debug( "%s: item=%p, window=%p", thisfn, item, window );
+
+ nact_assist_import_run( NACT_WINDOW( window ));
+
+ /*g_assert( NACT_IS_MAIN_WINDOW( user_data ));
+ NactWindow *wndmain = NACT_WINDOW( user_data );
+ nact_iactions_list_set_focus( wndmain );*/
+}
+
+static void
+on_import_selected( GtkItem *item, NactWindow *window )
+{
+ /* i18n: tooltip displayed in the status bar when selecting the Import item */
+ display_status( window, _( "Import one or more actions from external (XML) files into your configuration." ));
+}
+
+static void
+on_export_activated( GtkMenuItem *item, NactWindow *window )
+{
+ static const gchar *thisfn = "nact_imenubar_on_export_activated";
+ g_debug( "%s: item=%p, window=%p", thisfn, item, window );
+
+ nact_assist_export_run( NACT_WINDOW( window ));
+
+ /*g_assert( NACT_IS_MAIN_WINDOW( user_data ));
+ NactWindow *wndmain = NACT_WINDOW( user_data );
+ nact_iactions_list_set_focus( wndmain );*/
+}
+
+static void
+on_export_selected( GtkItem *item, NactWindow *window )
+{
+ /* i18n: tooltip displayed in the status bar when selecting the Export item */
+ display_status( window, _( "Export one or more actions from your configuration to external XML files." ));
+}
+
+/* TODO: make the website url and the mail addresses clickables
+ */
+static void
+on_about_activated( GtkMenuItem *item, NactWindow *window )
+{
+ static const gchar *thisfn = "nact_imenubar_on_about_activated";
+ g_debug( "%s: item=%p, window=%p", thisfn, item, window );
+
+ BaseApplication *appli;
+ g_object_get( G_OBJECT( window ), PROP_WINDOW_APPLICATION_STR, &appli, NULL );
+ gchar *icon_name = base_application_get_icon_name( appli );
+
+ static const gchar *artists[] = {
+ N_( "Ulisse Perusin <uli peru gmail com>" ),
+ NULL
+ };
+
+ static const gchar *authors[] = {
+ N_( "Frederic Ruaudel <grumz grumz net>" ),
+ N_( "Rodrigo Moya <rodrigo gnome-db org>" ),
+ N_( "Pierre Wieser <pwieser trychlos org>" ),
+ NULL
+ };
+
+ static const gchar *documenters[] = {
+ NULL
+ };
+
+ static gchar *license[] = {
+ N_( "Nautilus Actions Configuration Tool is free software; you can "
+ "redistribute it and/or modify it under the terms of the GNU General "
+ "Public License as published by the Free Software Foundation; either "
+ "version 2 of the License, or (at your option) any later version." ),
+ N_( "Nautilus Actions Configuration Tool is distributed in the hope that it "
+ "will be useful, but WITHOUT ANY WARRANTY; without even the implied "
+ "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See "
+ "the GNU General Public License for more details." ),
+ N_( "You should have received a copy of the GNU General Public License along "
+ "with Nautilus Actions Configuration Tool ; if not, write to the Free "
+ "Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, "
+ "MA 02110-1301, USA." ),
+ NULL
+ };
+ gchar *license_i18n = g_strjoinv( "\n\n", license );
+
+ GtkWindow *toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window ));
+
+ gtk_show_about_dialog( toplevel,
+ "artists", artists,
+ "authors", authors,
+ "comments", _( "A graphical interface to create and edit your Nautilus actions." ),
+ "copyright", _( "Copyright \xc2\xa9 2005-2007 Frederic Ruaudel <grumz grumz net>\nCopyright \xc2\xa9 2009 Pierre Wieser <pwieser trychlos org>" ),
+ "documenters", documenters,
+ "translator-credits", _( "The GNOME Translation Project <gnome-i18n gnome org>" ),
+ "license", license_i18n,
+ "wrap-license", TRUE,
+ "logo-icon-name", icon_name,
+ "version", PACKAGE_VERSION,
+ "website", "http://www.nautilus-actions.org",
+ NULL );
+
+ g_free( license_i18n );
+ g_free( icon_name );
+
+ /*nact_iactions_list_set_focus( NACT_WINDOW( wndmain ));*/
+}
+
+static void
+on_about_selected( GtkItem *item, NactWindow *window )
+{
+ /* i18n: tooltip displayed in the status bar when selecting the About item */
+ display_status( window, _( "Display informations about this program." ));
+}
+
+static void
+on_menu_item_deselected( GtkItem *item, NactWindow *window )
+{
+ hide_status( window );
+}
+
+static void
+display_status( NactWindow *window, const gchar *status )
+{
+ GtkWidget *bar = v_get_status_bar( window );
+ guint context = get_status_context( NACT_MAIN_WINDOW( window ));
+ gtk_statusbar_push( GTK_STATUSBAR( bar ), context, status );
+}
+
+static void
+hide_status( NactWindow *window )
+{
+ GtkWidget *bar = v_get_status_bar( window );
+ guint context = get_status_context( NACT_MAIN_WINDOW( window ));
+ gtk_statusbar_pop( GTK_STATUSBAR( bar ), context );
+}
+
+static void
+v_add_action( NactWindow *window, NAAction *action )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->add_action ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->add_action( window, action ));
+ }
+}
+
+static void
+v_add_profile( NactWindow *window, NAActionProfile *profile )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->add_profile ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->add_profile( window, profile ));
+ }
+}
+
+static void
+v_remove_action( NactWindow *window, NAAction *action )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->remove_action ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->remove_action( window, action ));
+ }
+}
+
+static GSList *
+v_get_deleted_actions( NactWindow *window )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->get_deleted_actions ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->get_deleted_actions( window ));
+ }
+
+ return( NULL );
+}
+
+static void
+v_free_deleted_actions( NactWindow *window )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->free_deleted_actions ){
+ NACT_IMENUBAR_GET_INTERFACE( window )->free_deleted_actions( window );
+ }
+}
+
+static void
+v_push_removed_action( NactWindow *window, NAAction *action )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->push_removed_action ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->push_removed_action( window, action ));
+ }
+}
+
+static GSList *
+v_get_actions( NactWindow *window )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->get_actions ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->get_actions( window ));
+ }
+
+ return( NULL );
+}
+
+static NAObject *
+v_get_selected( NactWindow *window )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->get_selected ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->get_selected( window ));
+ }
+
+ return( NULL );
+}
+
+static GtkWidget *
+v_get_status_bar( NactWindow *window )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->get_status_bar ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->get_status_bar( window ));
+ }
+
+ return( NULL );
+}
+
+static void
+v_setup_dialog_title( NactWindow *window )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->setup_dialog_title ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->setup_dialog_title( window ));
+ }
+}
+
+static void
+v_update_actions_list( NactWindow *window )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->update_actions_list ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->update_actions_list( window ));
+ }
+}
+
+static void
+v_select_actions_list( NactWindow *window, GType type, const gchar *uuid, const gchar *label )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->select_actions_list ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->select_actions_list( window, type, uuid, label ));
+ }
+}
+
+static gint
+v_count_actions( NactWindow *window )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->count_actions ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->count_actions( window ));
+ }
+
+ return( 0 );
+}
+
+static gint
+v_count_modified_actions( NactWindow *window )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->count_modified_actions ){
+ return( NACT_IMENUBAR_GET_INTERFACE( window )->count_modified_actions( window ));
+ }
+
+ return( 0 );
+}
+
+static void
+v_on_save( NactWindow *window )
+{
+ if( NACT_IMENUBAR_GET_INTERFACE( window )->on_save ){
+ NACT_IMENUBAR_GET_INTERFACE( window )->on_save( window );
+ }
+}
+
+static guint
+get_status_context( NactMainWindow *window )
+{
+ return( GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( window ), PROP_IMENUBAR_STATUS_CONTEXT )));
+}
+
+static void
+set_status_context( NactMainWindow *window, guint context )
+{
+ g_object_set_data( G_OBJECT( window ), PROP_IMENUBAR_STATUS_CONTEXT, GUINT_TO_POINTER( context ));
+}
+
+static GtkWidget *
+get_new_profile_item( NactWindow *window )
+{
+ return( GTK_WIDGET( g_object_get_data( G_OBJECT( window ), PROP_IMENUBAR_NEW_PROFILE_ITEM )));
+}
+
+static void
+set_new_profile_item( NactWindow *window, GtkWidget *item )
+{
+ g_object_set_data( G_OBJECT( window ), PROP_IMENUBAR_NEW_PROFILE_ITEM, item );
+}
+
+static GtkWidget *
+get_save_item( NactWindow *window )
+{
+ return( GTK_WIDGET( g_object_get_data( G_OBJECT( window ), PROP_IMENUBAR_SAVE_ITEM )));
+}
+
+static void
+set_save_item( NactWindow *window, GtkWidget *item )
+{
+ g_object_set_data( G_OBJECT( window ), PROP_IMENUBAR_SAVE_ITEM, item );
+}
+
+static GtkWidget *
+get_delete_item( NactWindow *window )
+{
+ return( GTK_WIDGET( g_object_get_data( G_OBJECT( window ), PROP_IMENUBAR_DELETE_ITEM )));
+}
+
+static void
+set_delete_item( NactWindow *window, GtkWidget *item )
+{
+ g_object_set_data( G_OBJECT( window ), PROP_IMENUBAR_DELETE_ITEM, item );
+}
+
+static GtkWidget *
+get_export_item( NactWindow *window )
+{
+ return( GTK_WIDGET( g_object_get_data( G_OBJECT( window ), PROP_IMENUBAR_EXPORT_ITEM )));
+}
+
+static void
+set_export_item( NactWindow *window, GtkWidget *item )
+{
+ g_object_set_data( G_OBJECT( window ), PROP_IMENUBAR_EXPORT_ITEM, item );
+}
diff --git a/src/nact/nact-imenubar.h b/src/nact/nact-imenubar.h
new file mode 100644
index 0000000..9bcbc31
--- /dev/null
+++ b/src/nact/nact-imenubar.h
@@ -0,0 +1,85 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * This Program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifndef __NACT_IMENUBAR_H__
+#define __NACT_IMENUBAR_H__
+
+/*
+ * NactIMenubar interface definition.
+ */
+
+#include <gtk/gtk.h>
+
+#include "nact-main-window.h"
+
+G_BEGIN_DECLS
+
+#define NACT_IMENUBAR_TYPE ( nact_imenubar_get_type())
+#define NACT_IMENUBAR( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_IMENUBAR_TYPE, NactIMenubar ))
+#define NACT_IS_IMENUBAR( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_IMENUBAR_TYPE ))
+#define NACT_IMENUBAR_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NACT_IMENUBAR_TYPE, NactIMenubarInterface ))
+
+typedef struct NactIMenubar NactIMenubar;
+
+typedef struct NactIMenubarInterfacePrivate NactIMenubarInterfacePrivate;
+
+typedef struct {
+ GTypeInterface parent;
+ NactIMenubarInterfacePrivate *private;
+
+ /* api */
+ void ( *add_action ) ( NactWindow *window, NAAction* action );
+ void ( *add_profile ) ( NactWindow *window, NAActionProfile *profile );
+ void ( *remove_action ) ( NactWindow *window, NAAction *action );
+ GSList * ( *get_deleted_actions ) ( NactWindow *window );
+ void ( *free_deleted_actions ) ( NactWindow *window );
+ void ( *push_removed_action ) ( NactWindow *window, NAAction *action );
+ GSList * ( *get_actions ) ( NactWindow *window );
+ NAObject * ( *get_selected ) ( NactWindow *window );
+ GtkWidget * ( *get_status_bar ) ( NactWindow *window );
+ void ( *setup_dialog_title ) ( NactWindow *window );
+ void ( *update_actions_list ) ( NactWindow *window );
+ void ( *select_actions_list ) ( NactWindow *window, GType type, const gchar *uuid, const gchar *label );
+ gint ( *count_actions ) ( NactWindow *window );
+ gint ( *count_modified_actions )( NactWindow *window );
+ void ( *on_save ) ( NactWindow *window );
+}
+ NactIMenubarInterface;
+
+GType nact_imenubar_get_type( void );
+
+void nact_imenubar_init( NactMainWindow *window );
+
+void nact_imenubar_on_delete_key_pressed( NactWindow *window );
+void nact_imenubar_on_delete_event( NactWindow *window );
+
+G_END_DECLS
+
+#endif /* __NACT_IMENUBAR_H__ */
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index 565b9f1..9140571 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -39,16 +39,15 @@
#include <common/na-pivot.h>
#include <common/na-iio-provider.h>
-#include <common/na-ipivot-container.h>
+#include <common/na-ipivot-consumer.h>
#include "nact-application.h"
-#include "nact-assist-export.h"
-#include "nact-assist-import.h"
#include "nact-iactions-list.h"
#include "nact-iaction-tab.h"
#include "nact-icommand-tab.h"
#include "nact-iconditions-tab.h"
#include "nact-iadvanced-tab.h"
+#include "nact-imenubar.h"
#include "nact-iprefs.h"
#include "nact-main-window.h"
@@ -63,11 +62,11 @@ struct NactMainWindowPrivate {
gboolean dispose_has_run;
GtkStatusbar *status_bar;
guint status_context;
- GtkWidget *new_profile_item;
- GtkWidget *save_item;
GSList *actions;
NAAction *edited_action;
NAActionProfile *edited_profile;
+ GSList *deleted;
+ GTimeVal last_saved;
};
/* the GConf key used to read/write size and position of auxiliary dialogs
@@ -83,7 +82,8 @@ static void iaction_tab_iface_init( NactIActionTabInterface *iface )
static void icommand_tab_iface_init( NactICommandTabInterface *iface );
static void iconditions_tab_iface_init( NactIConditionsTabInterface *iface );
static void iadvanced_tab_iface_init( NactIAdvancedTabInterface *iface );
-static void ipivot_container_iface_init( NAIPivotContainerInterface *iface );
+static void imenubar_iface_init( NactIMenubarInterface *iface );
+static void ipivot_consumer_iface_init( NAIPivotConsumerInterface *iface );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *application );
static void instance_finalize( GObject *application );
@@ -91,17 +91,16 @@ static void instance_finalize( GObject *application );
static gchar *get_iprefs_window_id( NactWindow *window );
static gchar *get_toplevel_name( BaseWindow *window );
static GSList *get_actions( NactWindow *window );
+static GtkWidget *get_status_bar( NactWindow *window );
static void on_initial_load_toplevel( BaseWindow *window );
-static void create_file_menu( BaseWindow *window, GtkMenuBar *menubar );
-static void create_tools_menu( BaseWindow *window, GtkMenuBar *menubar );
-static void create_help_menu( BaseWindow *window, GtkMenuBar *menubar );
static void on_runtime_init_toplevel( BaseWindow *window );
-static void setup_dialog_title( NactMainWindow *window );
-static void setup_dialog_menu( NactMainWindow *window );
+static void setup_dialog_title( NactWindow *window );
+/*static void setup_dialog_menu( NactMainWindow *window );*/
static void on_actions_list_selection_changed( GtkTreeSelection *selection, gpointer user_data );
static gboolean on_actions_list_double_click( GtkWidget *widget, GdkEventButton *event, gpointer data );
+static gboolean on_actions_list_delete_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer data );
static gboolean on_actions_list_enter_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer data );
static void set_current_action( NactMainWindow *window );
static void set_current_profile( NactMainWindow *window );
@@ -109,35 +108,34 @@ static NAAction *get_edited_action( NactWindow *window );
static NAActionProfile *get_edited_profile( NactWindow *window );
static void on_modified_field( NactWindow *window );
static void check_edited_status( NactWindow *window, const NAAction *action );
-static gboolean is_action_modified( const NAAction *action );
-static gboolean is_action_to_save( const NAAction *action );
+static gboolean is_modified_action( NactWindow *window, const NAAction *action );
+static gboolean is_valid_action( NactWindow *window, const NAAction *action );
+static gboolean is_modified_profile( NactWindow *window, const NAActionProfile *profile );
+static gboolean is_valid_profile( NactWindow *window, const NAActionProfile *profile );
static void get_isfiledir( NactWindow *window, gboolean *isfile, gboolean *isdir );
static gboolean get_multiple( NactWindow *window );
static GSList *get_schemes( NactWindow *window );
-static void on_new_action_activated( GtkMenuItem *item, gpointer user_data );
-static void on_new_action_selected( GtkItem *item, gpointer user_data );
-static void on_new_profile_activated( GtkMenuItem *item, gpointer user_data );
-static void on_new_profile_selected( GtkItem *item, gpointer user_data );
-
-static void on_import_activated( GtkMenuItem *item, gpointer user_data );
-static void on_import_selected( GtkItem *item, gpointer user_data );
-static void on_export_activated( GtkMenuItem *item, gpointer user_data );
-static void on_export_selected( GtkItem *item, gpointer user_data );
-static void on_about_activated( GtkMenuItem *item, gpointer user_data );
-static void on_about_selected( GtkItem *item, gpointer user_data );
-static void on_menu_item_deselected( GtkItem *item, gpointer user_data );
+static void add_action( NactWindow *window, NAAction *action );
+static void add_profile( NactWindow *window, NAActionProfile *profile );
+static void remove_action( NactWindow *window, NAAction *action );
+static GSList *get_deleted_actions( NactWindow *window );
+static void free_deleted_actions( NactWindow *window );
+static void push_removed_action( NactWindow *window, NAAction *action );
+
/*static void on_new_button_clicked( GtkButton *button, gpointer user_data );
static void on_edit_button_clicked( GtkButton *button, gpointer user_data );
static void on_duplicate_button_clicked( GtkButton *button, gpointer user_data );
static void on_delete_button_clicked( GtkButton *button, gpointer user_data );
static gboolean on_dialog_response( GtkDialog *dialog, gint response_id, BaseWindow *window );*/
-static void on_close( GtkMenuItem *item, gpointer user_data );
-static gboolean on_delete_event( BaseWindow *window, GtkWindow *toplevel, GdkEvent *event );
-static gint count_modified_actions( NactMainWindow *window );
-static void on_actions_changed( NAIPivotContainer *instance, gpointer user_data );
+static void update_actions_list( NactWindow *window );
+static gboolean on_delete_event( BaseWindow *window, GtkWindow *toplevel, GdkEvent *event );
+static gint count_actions( NactWindow *window );
+static gint count_modified_actions( NactWindow *window );
+static void on_save( NactWindow *window );
+static void on_actions_changed( NAIPivotConsumer *instance, gpointer user_data );
GType
nact_main_window_get_type( void )
@@ -215,14 +213,23 @@ register_type( void )
};
g_type_add_interface_static( type, NACT_IADVANCED_TAB_TYPE, &iadvanced_tab_iface_info );
- /* implement IPivotContainer interface
+ /* implement IMenubar interface
*/
- static const GInterfaceInfo pivot_container_iface_info = {
- ( GInterfaceInitFunc ) ipivot_container_iface_init,
+ static const GInterfaceInfo imenubar_iface_info = {
+ ( GInterfaceInitFunc ) imenubar_iface_init,
NULL,
NULL
};
- g_type_add_interface_static( type, NA_IPIVOT_CONTAINER_TYPE, &pivot_container_iface_info );
+ g_type_add_interface_static( type, NACT_IMENUBAR_TYPE, &imenubar_iface_info );
+
+ /* implement IPivotConsumer interface
+ */
+ static const GInterfaceInfo pivot_consumer_iface_info = {
+ ( GInterfaceInitFunc ) ipivot_consumer_iface_init,
+ NULL,
+ NULL
+ };
+ g_type_add_interface_static( type, NA_IPIVOT_CONSUMER_TYPE, &pivot_consumer_iface_info );
return( type );
}
@@ -260,7 +267,12 @@ iactions_list_iface_init( NactIActionsListInterface *iface )
iface->get_actions = get_actions;
iface->on_selection_changed = on_actions_list_selection_changed;
iface->on_double_click = on_actions_list_double_click;
+ iface->on_delete_key_pressed = on_actions_list_delete_key_pressed;
iface->on_enter_key_pressed = on_actions_list_enter_key_pressed;
+ iface->is_modified_action = is_modified_action;
+ iface->is_valid_action = is_valid_action;
+ iface->is_modified_profile = is_modified_profile;
+ iface->is_valid_profile = is_valid_profile;
}
static void
@@ -269,6 +281,8 @@ iaction_tab_iface_init( NactIActionTabInterface *iface )
static const gchar *thisfn = "nact_main_window_iaction_tab_iface_init";
g_debug( "%s: iface=%p", thisfn, iface );
+ iface->get_status_bar = get_status_bar;
+ iface->get_selected = nact_iactions_list_get_selected_object;
iface->get_edited_action = get_edited_action;
iface->field_modified = on_modified_field;
}
@@ -279,6 +293,7 @@ icommand_tab_iface_init( NactICommandTabInterface *iface )
static const gchar *thisfn = "nact_main_window_icommand_tab_iface_init";
g_debug( "%s: iface=%p", thisfn, iface );
+ iface->get_status_bar = get_status_bar;
iface->get_edited_profile = get_edited_profile;
iface->field_modified = on_modified_field;
iface->get_isfiledir = get_isfiledir;
@@ -307,9 +322,32 @@ iadvanced_tab_iface_init( NactIAdvancedTabInterface *iface )
}
static void
-ipivot_container_iface_init( NAIPivotContainerInterface *iface )
+imenubar_iface_init( NactIMenubarInterface *iface )
+{
+ static const gchar *thisfn = "nact_main_window_imenubar_iface_init";
+ g_debug( "%s: iface=%p", thisfn, iface );
+
+ iface->add_action = add_action;
+ iface->add_profile = add_profile;
+ iface->remove_action = remove_action;
+ iface->get_deleted_actions = get_deleted_actions;
+ iface->free_deleted_actions = free_deleted_actions;
+ iface->push_removed_action = push_removed_action;
+ iface->get_actions = get_actions;
+ iface->get_selected = nact_iactions_list_get_selected_object;
+ iface->get_status_bar = get_status_bar;
+ iface->setup_dialog_title = setup_dialog_title;
+ iface->update_actions_list = update_actions_list;
+ iface->select_actions_list = nact_iactions_list_set_selection;
+ iface->count_actions = count_actions;
+ iface->count_modified_actions = count_modified_actions;
+ iface->on_save = on_save;
+}
+
+static void
+ipivot_consumer_iface_init( NAIPivotConsumerInterface *iface )
{
- static const gchar *thisfn = "nact_main_window_ipivot_container_iface_init";
+ static const gchar *thisfn = "nact_main_window_ipivot_consumer_iface_init";
g_debug( "%s: iface=%p", thisfn, iface );
iface->on_actions_changed = on_actions_changed;
@@ -352,6 +390,8 @@ instance_dispose( GObject *window )
}
g_slist_free( self->private->actions );
+ free_deleted_actions( NACT_WINDOW( self ));
+
nact_iaction_tab_dispose( NACT_WINDOW( window ));
nact_icommand_tab_dispose( NACT_WINDOW( window ));
nact_iconditions_tab_dispose( NACT_WINDOW( window ));
@@ -412,6 +452,13 @@ get_actions( NactWindow *window )
return( NACT_MAIN_WINDOW( window )->private->actions );
}
+static GtkWidget *
+get_status_bar( NactWindow *window )
+{
+ g_assert( NACT_IS_MAIN_WINDOW( window ));
+ return( GTK_WIDGET( NACT_MAIN_WINDOW( window )->private->status_bar ));
+}
+
/*
* note that for this NactMainWindow, on_initial_load_toplevel and
* on_runtime_init_toplevel are equivalent, as there is only one
@@ -433,23 +480,16 @@ on_initial_load_toplevel( BaseWindow *window )
NactMainWindow *wnd = NACT_MAIN_WINDOW( window );
NactApplication *application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( wnd )));
- NAPivot *pivot = NA_PIVOT( nact_application_get_pivot( application ));
- GSList *origin = na_pivot_get_actions( pivot );
- GSList *ia;
- for( ia = origin ; ia ; ia = ia->next ){
- wnd->private->actions = g_slist_prepend( wnd->private->actions, na_action_duplicate( NA_ACTION( ia->data )));
- }
-
- GtkWidget *vbox = base_window_get_widget( window, "MenuBarVBox" );
- GtkWidget *menubar = gtk_menu_bar_new();
- gtk_container_add( GTK_CONTAINER( vbox ), menubar );
+ NAPivot *pivot = nact_application_get_pivot( application );
+ na_pivot_set_automatic_reload( pivot, FALSE );
+ wnd->private->actions = na_pivot_get_duplicate_actions( pivot );
- create_file_menu( window, GTK_MENU_BAR( menubar ));
- create_tools_menu( window, GTK_MENU_BAR( menubar ));
- create_help_menu( window, GTK_MENU_BAR( menubar ));
+ g_get_current_time( &wnd->private->last_saved );
wnd->private->status_bar = GTK_STATUSBAR( base_window_get_widget( window, "StatusBar" ));
- wnd->private->status_context = gtk_statusbar_get_context_id( wnd->private->status_bar, "NautilusActionsConfigurationTool" );
+ wnd->private->status_context = gtk_statusbar_get_context_id( wnd->private->status_bar, "nact-main-window" );
+
+ nact_imenubar_init( wnd );
g_assert( NACT_IS_IACTIONS_LIST( window ));
nact_iactions_list_initial_load( NACT_WINDOW( window ));
@@ -476,89 +516,6 @@ on_initial_load_toplevel( BaseWindow *window )
}
static void
-create_file_menu( BaseWindow *window, GtkMenuBar *menubar )
-{
- /* i18n: File menu */
- GtkWidget *file = gtk_menu_item_new_with_label( _( "_File" ));
- gtk_menu_item_set_use_underline( GTK_MENU_ITEM( file ), TRUE );
- gtk_menu_shell_append( GTK_MENU_SHELL( menubar ), file );
- GtkWidget *menu = gtk_menu_new();
- gtk_menu_item_set_submenu( GTK_MENU_ITEM( file ), menu );
-
- GtkWidget *item = gtk_image_menu_item_new_from_stock( GTK_STOCK_NEW, NULL );
- /* i18n: 'New action' item in 'File' menu - use same accelerator than GTK_STOCK_NEW item */
- gtk_menu_item_set_label( GTK_MENU_ITEM( item ), _( "_New action" ));
- gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "activate", G_CALLBACK( on_new_action_activated ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "select", G_CALLBACK( on_new_action_selected ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "deselect", G_CALLBACK( on_menu_item_deselected ));
-
- /* i18n: 'New profile' item in 'File' menu */
- item = gtk_image_menu_item_new_with_label( _( "New _profile" ));
- gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
- gtk_menu_item_set_use_underline( GTK_MENU_ITEM( item ), TRUE );
- NACT_MAIN_WINDOW( window )->private->new_profile_item = item;
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "activate", G_CALLBACK( on_new_profile_activated ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "select", G_CALLBACK( on_new_profile_selected ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "deselect", G_CALLBACK( on_menu_item_deselected ));
-
- item = gtk_image_menu_item_new_from_stock( GTK_STOCK_SAVE, NULL );
- gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
- NACT_MAIN_WINDOW( window )->private->save_item = item;
-
- item = gtk_separator_menu_item_new();
- gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
-
- item = gtk_image_menu_item_new_from_stock( GTK_STOCK_CLOSE, NULL );
- gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "activate", G_CALLBACK( on_close ));
-}
-
-static void
-create_tools_menu( BaseWindow *window, GtkMenuBar *menubar )
-{
- /* i18n: Tools menu */
- GtkWidget *tools = gtk_menu_item_new_with_label( _( "_Tools" ));
- gtk_menu_item_set_use_underline( GTK_MENU_ITEM( tools ), TRUE );
- gtk_menu_shell_append( GTK_MENU_SHELL( menubar ), tools );
- GtkWidget *menu = gtk_menu_new();
- gtk_menu_item_set_submenu( GTK_MENU_ITEM( tools ), menu );
-
- /* i18n: Import item in Tools menu */
- GtkWidget *item = gtk_image_menu_item_new_with_label( _( "_Import" ));
- gtk_menu_item_set_use_underline( GTK_MENU_ITEM( item ), TRUE );
- gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "activate", G_CALLBACK( on_import_activated ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "select", G_CALLBACK( on_import_selected ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "deselect", G_CALLBACK( on_menu_item_deselected ));
-
- /* i18n: Export item in Tools menu */
- item = gtk_image_menu_item_new_with_label( _( "_Export" ));
- gtk_menu_item_set_use_underline( GTK_MENU_ITEM( item ), TRUE );
- gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "activate", G_CALLBACK( on_export_activated ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "select", G_CALLBACK( on_export_selected ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "deselect", G_CALLBACK( on_menu_item_deselected ));
-}
-
-static void
-create_help_menu( BaseWindow *window, GtkMenuBar *menubar )
-{
- /* i18n: Help menu */
- GtkWidget *help = gtk_menu_item_new_with_label( _( "_Help" ));
- gtk_menu_item_set_use_underline( GTK_MENU_ITEM( help ), TRUE );
- gtk_menu_shell_append( GTK_MENU_SHELL( menubar ), help );
- GtkWidget *menu = gtk_menu_new();
- gtk_menu_item_set_submenu( GTK_MENU_ITEM( help ), menu );
-
- GtkWidget *item = gtk_image_menu_item_new_from_stock( GTK_STOCK_ABOUT, NULL );
- gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "activate", G_CALLBACK( on_about_activated ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "select", G_CALLBACK( on_about_selected ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( item ), "deselect", G_CALLBACK( on_menu_item_deselected ));
-}
-
-static void
on_runtime_init_toplevel( BaseWindow *window )
{
static const gchar *thisfn = "nact_main_window_on_runtime_init_toplevel";
@@ -589,23 +546,23 @@ on_runtime_init_toplevel( BaseWindow *window )
}
static void
-setup_dialog_title( NactMainWindow *window )
+setup_dialog_title( NactWindow *window )
{
BaseApplication *appli = BASE_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
gchar *title = base_application_get_name( appli );
- if( window->private->edited_action ){
- gchar *label = na_action_get_label( window->private->edited_action );
+ if( NACT_MAIN_WINDOW( window )->private->edited_action ){
+ gchar *label = na_action_get_label( NACT_MAIN_WINDOW( window )->private->edited_action );
gchar *tmp = g_strdup_printf( "%s - %s", title, label );
g_free( label );
g_free( title );
title = tmp;
- }
- if( count_modified_actions( window )){
- gchar *tmp = g_strdup_printf( "*%s", title );
- g_free( title );
- title = tmp;
+ if( is_modified_action( NACT_WINDOW( window ), NACT_MAIN_WINDOW( window )->private->edited_action )){
+ gchar *tmp = g_strdup_printf( "*%s", title );
+ g_free( title );
+ title = tmp;
+ }
}
GtkWindow *toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window ));
@@ -614,20 +571,20 @@ setup_dialog_title( NactMainWindow *window )
g_free( title );
}
-static void
+/*static void
setup_dialog_menu( NactMainWindow *window )
{
GSList *ia;
gboolean to_save = FALSE;
for( ia = window->private->actions ; ia && !to_save ; ia = ia->next ){
- gboolean elt_to_save = is_action_to_save( NA_ACTION( ia->data ));
+ gboolean elt_to_save = is_valid_action( NACT_WINDOW( window ), NA_ACTION( ia->data ));
to_save |= elt_to_save;
}
gtk_widget_set_sensitive( window->private->new_profile_item, window->private->edited_action != NULL );
gtk_widget_set_sensitive( window->private->save_item, to_save );
-}
+}*/
/*
* note that the IActionsList tree store may return an action or a profile
@@ -635,19 +592,25 @@ setup_dialog_menu( NactMainWindow *window )
static void
on_actions_list_selection_changed( GtkTreeSelection *selection, gpointer user_data )
{
+ static const gchar *thisfn = "nact_main_window_on_actions_list_selection_changed";
+ g_debug( "%s: selection=%p, user_data=%p", thisfn, selection, user_data );
+
g_assert( NACT_IS_MAIN_WINDOW( user_data ));
NactMainWindow *window = NACT_MAIN_WINDOW( user_data );
- NAObject *object = nact_iactions_list_get_selected_action( NACT_WINDOW( window ));
+ NAObject *object = nact_iactions_list_get_selected_object( NACT_WINDOW( window ));
+ g_debug( "%s: object=%p", thisfn, object );
- if( NA_IS_ACTION( object )){
- window->private->edited_action = NA_ACTION( object );
- set_current_action( window );
+ if( object ){
+ if( NA_IS_ACTION( object )){
+ window->private->edited_action = NA_ACTION( object );
+ set_current_action( window );
- } else {
- g_assert( NA_IS_ACTION_PROFILE( object ));
- window->private->edited_profile = NA_ACTION_PROFILE( object );
- set_current_profile( window );
+ } else {
+ g_assert( NA_IS_ACTION_PROFILE( object ));
+ window->private->edited_profile = NA_ACTION_PROFILE( object );
+ set_current_profile( window );
+ }
}
}
@@ -656,15 +619,28 @@ on_actions_list_double_click( GtkWidget *widget, GdkEventButton *event, gpointer
{
g_assert( event->type == GDK_2BUTTON_PRESS );
- nact_iactions_list_toggle_collapse( NACT_WINDOW( user_data ));
+ nact_iactions_list_toggle_collapse(
+ NACT_WINDOW( user_data ), NACT_MAIN_WINDOW( user_data )->private->edited_action );
return( TRUE );
}
static gboolean
+on_actions_list_delete_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
+{
+ if( NACT_MAIN_WINDOW( user_data )->private->edited_action ){
+ nact_imenubar_on_delete_key_pressed( NACT_WINDOW( user_data ));
+ return( TRUE );
+ }
+
+ return( FALSE );
+}
+
+static gboolean
on_actions_list_enter_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
{
- nact_iactions_list_toggle_collapse( NACT_WINDOW( user_data ));
+ nact_iactions_list_toggle_collapse(
+ NACT_WINDOW( user_data ), NACT_MAIN_WINDOW( user_data )->private->edited_action );
return( TRUE );
}
@@ -681,6 +657,7 @@ set_current_action( NactMainWindow *window )
nact_iaction_tab_set_action( NACT_WINDOW( window ), window->private->edited_action );
window->private->edited_profile = NULL;
+
if( na_action_get_profiles_count( window->private->edited_action ) == 1 ){
window->private->edited_profile = NA_ACTION_PROFILE( na_action_get_profiles( window->private->edited_action )->data );
}
@@ -693,10 +670,8 @@ set_current_profile( NactMainWindow *window )
{
if( window->private->edited_profile ){
NAAction *action = NA_ACTION( na_action_profile_get_action( window->private->edited_profile ));
- if( action != window->private->edited_action ){
- window->private->edited_action = action;
- nact_iaction_tab_set_action( NACT_WINDOW( window ), window->private->edited_action );
- }
+ window->private->edited_action = action;
+ nact_iaction_tab_set_action( NACT_WINDOW( window ), window->private->edited_action );
}
nact_icommand_tab_set_profile( NACT_WINDOW( window ), window->private->edited_profile );
@@ -724,8 +699,9 @@ get_edited_profile( NactWindow *window )
/*
* called as a virtual function by each interface tab when a field
- * has been modified : time to set the 'modified' flag in the
- * IActionsList box
+ * has been modified
+ * - if the label has been modified, the IActionsList must reflect this
+ * - setup dialog title
*/
static void
on_modified_field( NactWindow *window )
@@ -734,58 +710,76 @@ on_modified_field( NactWindow *window )
check_edited_status( window, NACT_MAIN_WINDOW( window )->private->edited_action );
- setup_dialog_title( NACT_MAIN_WINDOW( window ));
- setup_dialog_menu( NACT_MAIN_WINDOW( window ));
+ setup_dialog_title( window );
nact_iactions_list_update_selected( window, NACT_MAIN_WINDOW( window )->private->edited_action );
}
+/*
+ * is it modified ?
+ * and, if it has been modified, is it valid ?
+ */
static void
check_edited_status( NactWindow *window, const NAAction *edited )
{
g_assert( edited );
- NactApplication *application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
+ na_object_check_edited_status( NA_OBJECT( edited ));
+ /*NactApplication *application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
NAPivot *pivot = NA_PIVOT( nact_application_get_pivot( application ));
gchar *uuid = na_action_get_uuid( edited );
NAAction *original = NA_ACTION( na_pivot_get_action( pivot, uuid ));
g_free( uuid );
- gboolean is_modified = !na_action_are_equal( edited, original );
- g_object_set_data( G_OBJECT( edited ), "nact-main-window-action-modified", GINT_TO_POINTER( is_modified ));
+ gboolean is_modified = !na_object_are_equal( NA_OBJECT( edited ), NA_OBJECT( original ));
+ g_object_set_data( G_OBJECT( edited ), "nact-main-window-action-modified", GINT_TO_POINTER( is_modified ));*/
/*gboolean check = is_action_modified( edited );
g_debug( "check_edited_status: edited=%p, is_modified=%s, check=%s", edited, is_modified ? "True":"False", check ? "True":"False" );*/
- gboolean can_save = FALSE;
+ /*gboolean a_valid = TRUE;
if( is_modified ){
gchar *label = na_action_get_label( edited );
if( label && g_utf8_strlen( label, -1 )){
GSList *ip;
+ gboolean p_valid = FALSE;
GSList *profiles = na_action_get_profiles( edited );
for( ip = profiles ; ip ; ip = ip->next ){
NAActionProfile *prof = NA_ACTION_PROFILE( ip->data );
gchar *prof_label = na_action_profile_get_label( prof );
if( prof_label && g_utf8_strlen( prof_label, -1 )){
- can_save = TRUE;
+ p_valid = TRUE;
}
+ g_object_set_data( G_OBJECT( prof ), "nact-main-window-profile-is-valid", GINT_TO_POINTER( p_valid ));
g_free( prof_label );
}
g_free( label );
}
}
- g_object_set_data( G_OBJECT( edited ), "nact-main-window-action-can-save", GINT_TO_POINTER( can_save));
+ g_object_set_data( G_OBJECT( edited ), "nact-main-window-action-is-valid", GINT_TO_POINTER( a_valid ));*/
}
static gboolean
-is_action_modified( const NAAction *action )
+is_modified_action( NactWindow *window, const NAAction *action )
{
- return( GPOINTER_TO_INT( g_object_get_data( G_OBJECT( action ), "nact-main-window-action-modified" )));
+ return( na_object_get_modified_status( NA_OBJECT( action )));
}
static gboolean
-is_action_to_save( const NAAction *action )
+is_valid_action( NactWindow *window, const NAAction *action )
{
- return( GPOINTER_TO_INT( g_object_get_data( G_OBJECT( action ), "nact-main-window-action-can-save" )));
+ return( na_object_get_valid_status( NA_OBJECT( action )));
+}
+
+static gboolean
+is_modified_profile( NactWindow *window, const NAActionProfile *profile )
+{
+ return( na_object_get_modified_status( NA_OBJECT( profile )));
+}
+
+static gboolean
+is_valid_profile( NactWindow *window, const NAActionProfile *profile )
+{
+ return( na_object_get_valid_status( NA_OBJECT( profile )));
}
static void
@@ -807,183 +801,52 @@ get_schemes( NactWindow *window )
}
static void
-on_new_action_activated( GtkMenuItem *item, gpointer user_data )
+add_action( NactWindow *window, NAAction *action )
{
- g_assert( NACT_IS_MAIN_WINDOW( user_data ));
- NactMainWindow *window = NACT_MAIN_WINDOW( user_data );
-
- NAAction *action = na_action_new_with_profile();
- window->private->actions = g_slist_prepend( window->private->actions, action );
-}
-
-static void
-on_new_action_selected( GtkItem *item, gpointer user_data )
-{
- g_assert( NACT_IS_MAIN_WINDOW( user_data ));
- NactMainWindow *window = NACT_MAIN_WINDOW( user_data );
- gtk_statusbar_push(
- window->private->status_bar,
- window->private->status_context,
- /* i18n: tooltip displayed in the status bar when selecting the 'New action' item */
- _( "Define a new action." ));
-}
-
-static void
-on_new_profile_activated( GtkMenuItem *item, gpointer user_data )
-{
-
-}
-
-static void
-on_new_profile_selected( GtkItem *item, gpointer user_data )
-{
- g_assert( NACT_IS_MAIN_WINDOW( user_data ));
- NactMainWindow *window = NACT_MAIN_WINDOW( user_data );
- gtk_statusbar_push(
- window->private->status_bar,
- window->private->status_context,
- /* i18n: tooltip displayed in the status bar when selecting the 'New profile' item */
- _( "Define a new profile attached to the current action." ));
-}
-
-static void
-on_import_activated( GtkMenuItem *item, gpointer user_data )
-{
- static const gchar *thisfn = "nact_main_window_on_import_activated";
- g_debug( "%s: item=%p, user_data=%p", thisfn, item, user_data );
-
- nact_assist_import_run( NACT_WINDOW( user_data ));
-
- /*g_assert( NACT_IS_MAIN_WINDOW( user_data ));
- NactWindow *wndmain = NACT_WINDOW( user_data );
- nact_iactions_list_set_focus( wndmain );*/
-}
-
-static void
-on_import_selected( GtkItem *item, gpointer user_data )
-{
- g_assert( NACT_IS_MAIN_WINDOW( user_data ));
- NactMainWindow *window = NACT_MAIN_WINDOW( user_data );
- gtk_statusbar_push(
- window->private->status_bar,
- window->private->status_context,
- /* i18n: tooltip displayed in the status bar when selecting the Import item */
- _( "Import one or more actions from external (XML) files into your configuration." ));
+ NactMainWindow *wnd = NACT_MAIN_WINDOW( window );
+ wnd->private->actions = g_slist_prepend( wnd->private->actions, ( gpointer ) action );
}
static void
-on_export_activated( GtkMenuItem *item, gpointer user_data )
+add_profile( NactWindow *window, NAActionProfile *profile )
{
- static const gchar *thisfn = "nact_main_window_on_export_activated";
- g_debug( "%s: item=%p, user_data=%p", thisfn, item, user_data );
-
- nact_assist_export_run( NACT_WINDOW( user_data ));
+ NAAction *action = na_action_profile_get_action( profile );
- /*g_assert( NACT_IS_MAIN_WINDOW( user_data ));
- NactWindow *wndmain = NACT_WINDOW( user_data );
- nact_iactions_list_set_focus( wndmain );*/
+ if( !nact_iactions_list_is_expanded( window, action )){
+ nact_iactions_list_toggle_collapse( window, action );
+ }
}
static void
-on_export_selected( GtkItem *item, gpointer user_data )
+remove_action( NactWindow *window, NAAction *action )
{
- g_assert( NACT_IS_MAIN_WINDOW( user_data ));
- NactMainWindow *window = NACT_MAIN_WINDOW( user_data );
- gtk_statusbar_push(
- window->private->status_bar,
- window->private->status_context,
- /* i18n: tooltip displayed in the status bar when selecting the Export item */
- _( "Export one or more actions from your configuration to external XML files." ));
+ NactMainWindow *wnd = NACT_MAIN_WINDOW( window );
+ wnd->private->actions = g_slist_remove( wnd->private->actions, ( gconstpointer ) action );
}
-/* TODO: make the website url and the mail addresses clickables
- */
-static void
-on_about_activated( GtkMenuItem *item, gpointer user_data )
+static GSList *
+get_deleted_actions( NactWindow *window )
{
- static const gchar *thisfn = "nact_main_window_on_about_activated";
- g_debug( "%s: item=%p, user_data=%p", thisfn, item, user_data );
-
- g_assert( NACT_IS_MAIN_WINDOW( user_data ));
- NactMainWindow *window = NACT_MAIN_WINDOW( user_data );
-
- BaseApplication *appli;
- g_object_get( G_OBJECT( window ), PROP_WINDOW_APPLICATION_STR, &appli, NULL );
- gchar *icon_name = base_application_get_icon_name( appli );
-
- static const gchar *artists[] = {
- N_( "Ulisse Perusin <uli peru gmail com>" ),
- NULL
- };
-
- static const gchar *authors[] = {
- N_( "Frederic Ruaudel <grumz grumz net>" ),
- N_( "Rodrigo Moya <rodrigo gnome-db org>" ),
- N_( "Pierre Wieser <pwieser trychlos org>" ),
- NULL
- };
-
- static const gchar *documenters[] = {
- NULL
- };
-
- static gchar *license[] = {
- N_( "Nautilus Actions Configuration Tool is free software; you can "
- "redistribute it and/or modify it under the terms of the GNU General "
- "Public License as published by the Free Software Foundation; either "
- "version 2 of the License, or (at your option) any later version." ),
- N_( "Nautilus Actions Configuration Tool is distributed in the hope that it "
- "will be useful, but WITHOUT ANY WARRANTY; without even the implied "
- "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See "
- "the GNU General Public License for more details." ),
- N_( "You should have received a copy of the GNU General Public License along "
- "with Nautilus Actions Configuration Tool ; if not, write to the Free "
- "Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, "
- "MA 02110-1301, USA." ),
- NULL
- };
- gchar *license_i18n = g_strjoinv( "\n\n", license );
-
- GtkWindow *toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window ));
-
- gtk_show_about_dialog( toplevel,
- "artists", artists,
- "authors", authors,
- "comments", _( "A graphical tool to create and edit your Nautilus actions." ),
- "copyright", _( "Copyright \xc2\xa9 2005-2007 Frederic Ruaudel <grumz grumz net>\nCopyright \xc2\xa9 2009 Pierre Wieser <pwieser trychlos org>" ),
- "documenters", documenters,
- "translator-credits", _( "The GNOME Translation Project <gnome-i18n gnome org>" ),
- "license", license_i18n,
- "wrap-license", TRUE,
- "logo-icon-name", icon_name,
- "version", PACKAGE_VERSION,
- "website", "http://www.nautilus-actions.org",
- NULL );
-
- g_free( license_i18n );
- g_free( icon_name );
-
- /*nact_iactions_list_set_focus( NACT_WINDOW( wndmain ));*/
+ return( NACT_MAIN_WINDOW( window )->private->deleted );
}
static void
-on_about_selected( GtkItem *item, gpointer user_data )
+free_deleted_actions( NactWindow *window )
{
- g_assert( NACT_IS_MAIN_WINDOW( user_data ));
- NactMainWindow *window = NACT_MAIN_WINDOW( user_data );
- gtk_statusbar_push(
- window->private->status_bar,
- window->private->status_context,
- /* i18n: tooltip displayed in the status bar when selecting the About item */
- _( "Display informations about this program." ));
+ NactMainWindow *self = NACT_MAIN_WINDOW( window );
+ GSList *ia;
+ for( ia = self->private->deleted ; ia ; ia = ia->next ){
+ g_object_unref( NA_ACTION( ia->data ));
+ }
+ g_slist_free( self->private->deleted );
+ self->private->deleted = NULL;
}
static void
-on_menu_item_deselected( GtkItem *item, gpointer user_data )
+push_removed_action( NactWindow *window, NAAction *action )
{
- g_assert( NACT_IS_MAIN_WINDOW( user_data ));
- NactMainWindow *window = NACT_MAIN_WINDOW( user_data );
- gtk_statusbar_pop( window->private->status_bar, window->private->status_context );
+ NactMainWindow *wnd = NACT_MAIN_WINDOW( window );
+ wnd->private->deleted = g_slist_append( wnd->private->deleted, ( gpointer ) action );
}
/*
@@ -1143,18 +1006,9 @@ on_dialog_response( GtkDialog *dialog, gint response_id, BaseWindow *window )
}*/
static void
-on_close( GtkMenuItem *item, gpointer user_data )
+update_actions_list( NactWindow *window )
{
- static const gchar *thisfn = "nact_main_window_on_close";
- g_debug( "%s: item=%p, user_data=%p", thisfn, item, user_data );
-
- g_assert( NACT_IS_MAIN_WINDOW( user_data ));
- NactMainWindow *window = NACT_MAIN_WINDOW( user_data );
-
- gint count = count_modified_actions( window );
- if( !count || nact_window_warn_count_modified( NACT_WINDOW( window ), count )){
- g_object_unref( window );
- }
+ nact_iactions_list_fill( window, TRUE );
}
static gboolean
@@ -1164,36 +1018,66 @@ on_delete_event( BaseWindow *window, GtkWindow *toplevel, GdkEvent *event )
g_debug( "%s: window=%p, toplevel=%p, event=%p", thisfn, window, toplevel, event );
g_assert( NACT_IS_MAIN_WINDOW( window ));
-
- on_close( NULL, window );
+ nact_imenubar_on_delete_event( NACT_WINDOW( window ));
return( TRUE );
}
static gint
-count_modified_actions( NactMainWindow *window )
+count_actions( NactWindow *window )
{
- gint count = 0;
+ return( g_slist_length( NACT_MAIN_WINDOW( window )->private->actions ));
+}
+
+static gint
+count_modified_actions( NactWindow *window )
+{
+ gint count = g_slist_length( NACT_MAIN_WINDOW( window )->private->deleted );
+
GSList *ia;
- for( ia = window->private->actions ; ia ; ia = ia->next ){
- gboolean is_modified = is_action_modified( NA_ACTION( ia->data ));
- if( is_modified ){
+ for( ia = NACT_MAIN_WINDOW( window )->private->actions ; ia ; ia = ia->next ){
+ if( is_modified_action( window, NA_ACTION( ia->data ))){
count += 1;
}
- /*g_debug( "count_modified_actions: action=%p, is_modified=%s", ia->data, is_modified ? "True":"False" );*/
}
- /*g_debug( "count_modified_actions: length=%d, count=%d", g_slist_length( window->private->actions ), count );*/
+
return( count );
}
/*
- * called by NAPivot because this window implements the IIOContainer
+ * in initial_load_toplevel(), we have forbidden the automatic reload
+ * of the list of actions in NAPivot, as we take care of updating it of
+ * the modifications entered in the UI
+ *
+ * this doesn't prevent NAPivot to advertise us when it detects some
+ * modifications in an I/O provider ; so that we are able to ask the
+ * user for a reload
+ *
+ * but we don't want be advertized when this is our own save which
+ * triggers the NAPivot advertising - so we forbids such advertisings
+ * during one seconde after each save
+ *
+ * note that last_saved is initialized in initial_load_toplevel()
+ * there is so a race condition if NAPivot detects a modification
+ * in the seconde after this initialization - just ignore this case
+ */
+static void
+on_save( NactWindow *window )
+{
+ g_get_current_time( &NACT_MAIN_WINDOW( window )->private->last_saved );
+}
+
+/*
+ * called by NAPivot because this window implements the IIOConsumer
* interface, i.e. it wish to be advertised when the list of actions
* changes in the underlying I/O storage subsystem (typically, when we
* save the modifications)
+ *
+ * note that we only reload the full list of actions when asking for a
+ * reset - saving is handled on a per-action basis.
*/
static void
-on_actions_changed( NAIPivotContainer *instance, gpointer user_data )
+on_actions_changed( NAIPivotConsumer *instance, gpointer user_data )
{
static const gchar *thisfn = "nact_main_window_on_actions_changed";
g_debug( "%s: instance=%p, user_data=%p", thisfn, instance, user_data );
@@ -1201,10 +1085,44 @@ on_actions_changed( NAIPivotContainer *instance, gpointer user_data )
g_assert( NACT_IS_MAIN_WINDOW( instance ));
NactMainWindow *self = NACT_MAIN_WINDOW( instance );
- if( !self->private->dispose_has_run ){
- nact_iactions_list_fill( NACT_WINDOW( instance ));
+ GTimeVal now;
+ g_get_current_time( &now );
+ glong ecart = 1000000 * ( now.tv_sec - self->private->last_saved.tv_sec );
+ ecart += now.tv_usec - self->private->last_saved.tv_usec;
+ if( ecart < 1000000 ){
+ return;
}
- /*nact_iactions_list_set_selection(
- NACT_WINDOW( self ), self->private->current_uuid, self->private->current_label );*/
+ NactApplication *application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( instance )));
+ NAPivot *pivot = nact_application_get_pivot( application );
+
+ gchar *first = g_strdup(_( "One or more actions have been modified in the filesystem.\n"
+ "You could keep to work with your current list of actions, "
+ "or you may want to reload a fresh one." ));
+
+ if( count_modified_actions( NACT_WINDOW( instance )) > 0 ){
+ gchar *tmp = g_strdup_printf( "%s\n\n%s", first,
+ _( "Note that reloading a fresh list of actions requires "
+ "that you give up with your current modifications." ));
+ g_free( first );
+ first = tmp;
+ }
+
+ gchar *second = g_strdup( _( "Do you want to reload a fresh list of actions ?" ));
+
+ gboolean ok = base_window_yesno_dlg( BASE_WINDOW( instance ), GTK_MESSAGE_QUESTION, first, second );
+
+ g_free( second );
+ g_free( first );
+
+ if( ok ){
+
+ na_pivot_reload_actions( pivot );
+
+ na_pivot_free_actions( self->private->actions );
+
+ self->private->actions = na_pivot_get_duplicate_actions( pivot );
+
+ nact_iactions_list_fill( NACT_WINDOW( instance ), TRUE );
+ }
}
diff --git a/src/nact/nact-window.c b/src/nact/nact-window.c
index 9854d85..ee86e0d 100644
--- a/src/nact/nact-window.c
+++ b/src/nact/nact-window.c
@@ -35,7 +35,6 @@
#include <glib.h>
#include <glib/gi18n.h>
-#include <common/na-pivot.h>
#include <common/na-iio-provider.h>
#include "nact-application.h"
@@ -220,14 +219,14 @@ instance_finalize( GObject *window )
/**
* Returns a pointer to the list of actions.
*/
-GObject *
+NAPivot *
nact_window_get_pivot( NactWindow *window )
{
NactApplication *application;
g_object_get( G_OBJECT( window ), PROP_WINDOW_APPLICATION_STR, &application, NULL );
g_return_val_if_fail( NACT_IS_APPLICATION( application ), NULL );
- GObject *pivot = nact_application_get_pivot( application );
+ NAPivot *pivot = nact_application_get_pivot( application );
g_return_val_if_fail( NA_IS_PIVOT( pivot ), NULL );
return( pivot );
@@ -255,18 +254,18 @@ nact_window_set_current_action( NactWindow *window, const NAAction *action )
* @action: the modified action.
*/
gboolean
-nact_window_save_action( NactWindow *window, const NAAction *action )
+nact_window_save_action( NactWindow *window, NAAction *action )
{
static const gchar *thisfn = "nact_window_save_action";
g_debug( "%s: window=%p, action=%p", thisfn, window, action );
- NAPivot *pivot = NA_PIVOT( nact_window_get_pivot( window ));
+ NAPivot *pivot = nact_window_get_pivot( window );
g_assert( NA_IS_PIVOT( pivot ));
na_object_dump( NA_OBJECT( action ));
gchar *msg = NULL;
- guint ret = na_pivot_write_action( pivot, G_OBJECT( action ), &msg );
+ guint ret = na_pivot_write_action( pivot, action, &msg );
if( msg ){
base_window_error_dlg(
BASE_WINDOW( window ),
@@ -278,6 +277,36 @@ nact_window_save_action( NactWindow *window, const NAAction *action )
}
/**
+ * Deleted an action from the I/O storage subsystem.
+ *
+ * @window: this NactWindow object.
+ *
+ * @action: the action to delete.
+ */
+gboolean
+nact_window_delete_action( NactWindow *window, NAAction *action )
+{
+ static const gchar *thisfn = "nact_window_delete_action";
+ g_debug( "%s: window=%p, action=%p", thisfn, window, action );
+
+ NAPivot *pivot = nact_window_get_pivot( window );
+ g_assert( NA_IS_PIVOT( pivot ));
+
+ na_object_dump( NA_OBJECT( action ));
+
+ gchar *msg = NULL;
+ guint ret = na_pivot_delete_action( pivot, action, &msg );
+ if( msg ){
+ base_window_error_dlg(
+ BASE_WINDOW( window ),
+ GTK_MESSAGE_WARNING, _( "An error has occured when trying to delete the action" ), msg );
+ g_free( msg );
+ }
+
+ return( ret == NA_IIO_PROVIDER_WRITE_OK );
+}
+
+/**
* Emits a warning if the action has been modified.
*
* @window: this NactWindow object.
diff --git a/src/nact/nact-window.h b/src/nact/nact-window.h
index e75e0a5..aadca3f 100644
--- a/src/nact/nact-window.h
+++ b/src/nact/nact-window.h
@@ -40,6 +40,7 @@
#include <common/na-action.h>
#include <common/na-action-profile.h>
+#include <common/na-pivot.h>
#include "base-window.h"
@@ -74,11 +75,12 @@ typedef struct {
GType nact_window_get_type( void );
-GObject *nact_window_get_pivot( NactWindow *window );
+NAPivot *nact_window_get_pivot( NactWindow *window );
/* TODO: check these functions */
void nact_window_set_current_action( NactWindow *window, const NAAction *action );
-gboolean nact_window_save_action( NactWindow *window, const NAAction *action );
+gboolean nact_window_save_action( NactWindow *window, NAAction *action );
+gboolean nact_window_delete_action( NactWindow *window, NAAction *action );
/* TODO: move the function to nact-main-window */
gboolean nact_window_warn_count_modified( NactWindow *window, gint count );
diff --git a/src/plugin/nautilus-actions.c b/src/plugin/nautilus-actions.c
index fa4d2e0..18c6b54 100644
--- a/src/plugin/nautilus-actions.c
+++ b/src/plugin/nautilus-actions.c
@@ -41,7 +41,7 @@
#include <common/na-action.h>
#include <common/na-action-profile.h>
#include <common/na-pivot.h>
-#include <common/na-ipivot-container.h>
+#include <common/na-ipivot-consumer.h>
#include "nautilus-actions.h"
@@ -62,7 +62,7 @@ static GType st_actions_type = 0;
static void class_init( NautilusActionsClass *klass );
static void menu_provider_iface_init( NautilusMenuProviderIface *iface );
-static void pivot_container_iface_init( NAIPivotContainerInterface *iface );
+static void pivot_consumer_iface_init( NAIPivotConsumerInterface *iface );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *object );
static void instance_finalize( GObject *object );
@@ -71,7 +71,7 @@ static GList *get_background_items( NautilusMenuProvider *provider, G
static GList *get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files );
static NautilusMenuItem *create_menu_item( NAAction *action, NAActionProfile *profile, GList *files );
static void execute_action( NautilusMenuItem *item, NAActionProfile *profile );
-static void actions_changed_handler( NAIPivotContainer *instance, gpointer user_data );
+static void actions_changed_handler( NAIPivotConsumer *instance, gpointer user_data );
GType
nautilus_actions_get_type( void )
@@ -112,15 +112,15 @@ nautilus_actions_register_type( GTypeModule *module )
g_type_module_add_interface( module, st_actions_type, NAUTILUS_TYPE_MENU_PROVIDER, &menu_provider_iface_info );
- /* implement IPivotContainer interface
+ /* implement IPivotConsumer interface
*/
- static const GInterfaceInfo pivot_container_iface_info = {
- ( GInterfaceInitFunc ) pivot_container_iface_init,
+ static const GInterfaceInfo pivot_consumer_iface_info = {
+ ( GInterfaceInitFunc ) pivot_consumer_iface_init,
NULL,
NULL
};
- g_type_module_add_interface( module, st_actions_type, NA_IPIVOT_CONTAINER_TYPE, &pivot_container_iface_info );
+ g_type_module_add_interface( module, st_actions_type, NA_IPIVOT_CONSUMER_TYPE, &pivot_consumer_iface_info );
}
static void
@@ -149,9 +149,9 @@ menu_provider_iface_init( NautilusMenuProviderIface *iface )
}
static void
-pivot_container_iface_init( NAIPivotContainerInterface *iface )
+pivot_consumer_iface_init( NAIPivotConsumerInterface *iface )
{
- static const gchar *thisfn = "nautilus_actions_pivot_container_iface_init";
+ static const gchar *thisfn = "nautilus_actions_pivot_consumer_iface_init";
g_debug( "%s: iface=%p", thisfn, iface );
iface->on_actions_changed = actions_changed_handler;
@@ -171,18 +171,6 @@ instance_init( GTypeInstance *instance, gpointer klass )
/* from na-pivot */
self->private->pivot = na_pivot_new( G_OBJECT( self ));
-
- /* see nautilus_actions_class_init for why we had to connect an
- * handler to our signal instead of relying on default handler
- * see also nautilus_actions_class_init for why g_signal_connect is
- * no more needed
- */
- /*g_signal_connect(
- G_OBJECT( self ),
- SIGNAL_ACTION_CHANGED_NAME,
- ( GCallback ) action_changed_handler,
- NULL
- );*/
}
static void
@@ -328,7 +316,7 @@ create_menu_item( NAAction *action, NAActionProfile *profile, GList *files )
gchar *tooltip = na_action_get_tooltip( action );
gchar* icon_name = na_action_get_verified_icon_name( action );
- NAActionProfile *dup4menu = na_action_profile_duplicate( action, profile );
+ NAActionProfile *dup4menu = NA_ACTION_PROFILE( na_object_duplicate( NA_OBJECT( profile )));
item = nautilus_menu_item_new( name, label, tooltip, icon_name );
@@ -336,7 +324,7 @@ create_menu_item( NAAction *action, NAActionProfile *profile, GList *files )
"activate",
G_CALLBACK( execute_action ),
dup4menu,
- ( GClosureNotify ) na_action_profile_free,
+ ( GClosureNotify ) g_object_unref,
0
);
@@ -386,7 +374,7 @@ execute_action( NautilusMenuItem *item, NAActionProfile *profile )
}
static void
-actions_changed_handler( NAIPivotContainer *instance, gpointer user_data )
+actions_changed_handler( NAIPivotConsumer *instance, gpointer user_data )
{
static const gchar *thisfn = "nautilus_actions_actions_changed_handler";
g_debug( "%s: instance=%p, user_data=%p", thisfn, instance, user_data );
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]