[nautilus-actions] Load old versions, write current, test for writable i/o subsystem
- From: Pierre Wieser <pwieser src gnome org>
- To: svn-commits-list gnome org
- Subject: [nautilus-actions] Load old versions, write current, test for writable i/o subsystem
- Date: Tue, 14 Jul 2009 18:47:04 +0000 (UTC)
commit ecdf6afda6876164b7ade8a282e7fdb90d47d354
Author: Pierre Wieser <pwieser trychlos org>
Date: Sat Jun 20 23:57:06 2009 +0200
Load old versions, write current, test for writable i/o subsystem
ChangeLog | 17 ++
src/common/na-action-profile.c | 317 +++++++++++++++++--------
src/common/na-action-profile.h | 24 ++
src/common/na-action.c | 152 ++++++++----
src/common/na-action.h | 12 +
src/common/na-gconf-keys.h | 20 ++-
src/common/na-gconf.c | 515 +++++++++++++++++++++++++++++++++++++---
src/common/na-iio-provider.c | 40 +++-
src/common/na-iio-provider.h | 17 +-
src/plugin/nautilus-actions.c | 2 +-
10 files changed, 918 insertions(+), 198 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 816321c..fa95337 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
2009-06-20 Pierre Wieser <pwieser trychlos org>
+ * src/common/na-gconf.c:
+ Implement loading of old versions.
+ Implement writing an action.
+
+ * src/common/na-action.c:
+ * src/common/na-action.h:
+ * src/common/na-gconf.c:
+ Add read-only attribute set when GConf key is not writable.
+
+ * src/common/na-action.c:
+ * src/common/na-action.h:
+ * src/common/na-action-profile.c:
+ * src/common/na-action-profile.h:
+ Object properties are renamed, and moved to include file.
+ Objects are created with suitable default values.
+ Finalize helper functions.
+
* src/common/na-iio-provider.c:
Record the provider in each NAAction object.
diff --git a/src/common/na-action-profile.c b/src/common/na-action-profile.c
index ccdbb8f..e207744 100644
--- a/src/common/na-action-profile.c
+++ b/src/common/na-action-profile.c
@@ -33,6 +33,7 @@
#endif
#include <string.h>
+#include <glib/gi18n.h>
#include <libnautilus-extension/nautilus-file-info.h>
@@ -69,38 +70,25 @@ struct NAActionProfilePrivate {
GSList *schemes;
};
-/* private instance properties
+/* instance properties
* please note that property names must have the same spelling as the
* NactIIOProvider parameters
*/
enum {
- PROP_ACTION = 1,
+ PROP_PROFILE_ACTION = 1,
PROP_PROFILE_NAME,
- PROP_LABEL,
- PROP_PATH,
- PROP_PARAMETERS,
- PROP_ACCEPT_MULTIPLE,
- PROP_BASENAMES,
- PROP_ISDIR,
- PROP_ISFILE,
- PROP_MATCHCASE,
- PROP_MIMETYPES,
- PROP_SCHEMES
+ 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
};
-#define PROP_ACTION_STR "action"
-#define PROP_PROFILE_NAME_STR "name"
-#define PROP_LABEL_STR "desc-name"
-#define PROP_PATH_STR "path"
-#define PROP_PARAMETERS_STR "parameters"
-#define PROP_ACCEPT_MULTIPLE_STR "accept-multiple-files"
-#define PROP_BASENAMES_STR "basenames"
-#define PROP_ISDIR_STR "isdir"
-#define PROP_ISFILE_STR "isfile"
-#define PROP_MATCHCASE_STR "matchcase"
-#define PROP_MIMETYPES_STR "mimetypes"
-#define PROP_SCHEMES_STR "schemes"
-
static NAObjectClass *st_parent_class = NULL;
static GType register_type( void );
@@ -163,11 +151,11 @@ class_init( NAActionProfileClass *klass )
GParamSpec *spec;
spec = g_param_spec_pointer(
- PROP_ACTION_STR,
- PROP_ACTION_STR,
+ 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_ACTION, spec );
+ g_object_class_install_property( object_class, PROP_PROFILE_ACTION, spec );
/* the id of the object is marked as G_PARAM_CONSTRUCT_ONLY */
spec = g_param_spec_string(
@@ -178,74 +166,74 @@ class_init( NAActionProfileClass *klass )
g_object_class_install_property( object_class, PROP_PROFILE_NAME, spec );
spec = g_param_spec_string(
- PROP_LABEL_STR,
- PROP_LABEL_STR,
+ PROP_PROFILE_LABEL_STR,
+ PROP_PROFILE_LABEL_STR,
"Displayable profile's name", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_LABEL, spec );
+ g_object_class_install_property( object_class, PROP_PROFILE_LABEL, spec );
spec = g_param_spec_string(
- PROP_PATH_STR,
- PROP_PATH_STR,
+ PROP_PROFILE_PATH_STR,
+ PROP_PROFILE_PATH_STR,
"Command path", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PATH, spec );
+ g_object_class_install_property( object_class, PROP_PROFILE_PATH, spec );
spec = g_param_spec_string(
- PROP_PARAMETERS_STR,
- PROP_PARAMETERS_STR,
+ PROP_PROFILE_PARAMETERS_STR,
+ PROP_PROFILE_PARAMETERS_STR,
"Command parameters", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PARAMETERS, spec );
+ g_object_class_install_property( object_class, PROP_PROFILE_PARAMETERS, spec );
spec = g_param_spec_boolean(
- PROP_ACCEPT_MULTIPLE_STR,
- PROP_ACCEPT_MULTIPLE_STR,
+ 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_ACCEPT_MULTIPLE, spec );
+ g_object_class_install_property( object_class, PROP_PROFILE_ACCEPT_MULTIPLE, spec );
spec = g_param_spec_pointer(
- PROP_BASENAMES_STR,
- PROP_BASENAMES_STR,
+ PROP_PROFILE_BASENAMES_STR,
+ PROP_PROFILE_BASENAMES_STR,
"Filenames mask",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_BASENAMES, spec );
+ g_object_class_install_property( object_class, PROP_PROFILE_BASENAMES, spec );
spec = g_param_spec_boolean(
- PROP_ISDIR_STR,
- PROP_ISDIR_STR,
+ PROP_PROFILE_ISDIR_STR,
+ PROP_PROFILE_ISDIR_STR,
"Whether apply when a dir is selected", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_ISDIR, spec );
+ g_object_class_install_property( object_class, PROP_PROFILE_ISDIR, spec );
spec = g_param_spec_boolean(
- PROP_ISFILE_STR,
- PROP_ISFILE_STR,
+ PROP_PROFILE_ISFILE_STR,
+ PROP_PROFILE_ISFILE_STR,
"Whether apply when a file is selected", TRUE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_ISFILE, spec );
+ g_object_class_install_property( object_class, PROP_PROFILE_ISFILE, spec );
spec = g_param_spec_boolean(
- PROP_MATCHCASE_STR,
- PROP_MATCHCASE_STR,
+ PROP_PROFILE_MATCHCASE_STR,
+ PROP_PROFILE_MATCHCASE_STR,
"Whether the filenames are case sensitive", TRUE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_MATCHCASE, spec );
+ g_object_class_install_property( object_class, PROP_PROFILE_MATCHCASE, spec );
spec = g_param_spec_pointer(
- PROP_MIMETYPES_STR,
- PROP_MIMETYPES_STR,
+ PROP_PROFILE_MIMETYPES_STR,
+ PROP_PROFILE_MIMETYPES_STR,
"List of selectable mimetypes",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_MIMETYPES, spec );
+ g_object_class_install_property( object_class, PROP_PROFILE_MIMETYPES, spec );
spec = g_param_spec_pointer(
- PROP_SCHEMES_STR,
- PROP_SCHEMES_STR,
+ PROP_PROFILE_SCHEMES_STR,
+ PROP_PROFILE_SCHEMES_STR,
"list of selectable schemes",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_SCHEMES, spec );
+ g_object_class_install_property( object_class, PROP_PROFILE_SCHEMES, spec );
klass->private = g_new0( NAActionProfileClassPrivate, 1 );
@@ -264,7 +252,25 @@ instance_init( GTypeInstance *instance, gpointer klass )
NAActionProfile* self = NA_ACTION_PROFILE( instance );
self->private = g_new0( NAActionProfilePrivate, 1 );
+
self->private->dispose_has_run = FALSE;
+
+ /* 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->schemes = NULL;
+ self->private->schemes = g_slist_append( self->private->schemes, g_strdup( "file" ));
}
static void
@@ -276,7 +282,7 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
GSList *list;
switch( property_id ){
- case PROP_ACTION:
+ case PROP_PROFILE_ACTION:
g_value_set_pointer( value, self->private->action );
break;
@@ -284,45 +290,45 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
g_value_set_string( value, self->private->name );
break;
- case PROP_LABEL:
+ case PROP_PROFILE_LABEL:
g_value_set_string( value, self->private->label );
break;
- case PROP_PATH:
+ case PROP_PROFILE_PATH:
g_value_set_string( value, self->private->path );
break;
- case PROP_PARAMETERS:
+ case PROP_PROFILE_PARAMETERS:
g_value_set_string( value, self->private->parameters );
break;
- case PROP_ACCEPT_MULTIPLE:
+ case PROP_PROFILE_ACCEPT_MULTIPLE:
g_value_set_boolean( value, self->private->accept_multiple_files );
break;
- case PROP_BASENAMES:
+ case PROP_PROFILE_BASENAMES:
list = na_utils_duplicate_string_list( self->private->basenames );
g_value_set_pointer( value, list );
break;
- case PROP_ISDIR:
+ case PROP_PROFILE_ISDIR:
g_value_set_boolean( value, self->private->is_dir );
break;
- case PROP_ISFILE:
+ case PROP_PROFILE_ISFILE:
g_value_set_boolean( value, self->private->is_file );
break;
- case PROP_MATCHCASE:
+ case PROP_PROFILE_MATCHCASE:
g_value_set_boolean( value, self->private->match_case );
break;
- case PROP_MIMETYPES:
+ case PROP_PROFILE_MIMETYPES:
list = na_utils_duplicate_string_list( self->private->mimetypes );
g_value_set_pointer( value, list );
break;
- case PROP_SCHEMES:
+ case PROP_PROFILE_SCHEMES:
list = na_utils_duplicate_string_list( self->private->schemes );
g_value_set_pointer( value, list );
break;
@@ -340,7 +346,7 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
NAActionProfile *self = NA_ACTION_PROFILE( object );
switch( property_id ){
- case PROP_ACTION:
+ case PROP_PROFILE_ACTION:
self->private->action = g_value_get_pointer( value );
break;
@@ -349,48 +355,48 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
self->private->name = g_value_dup_string( value );
break;
- case PROP_LABEL:
+ case PROP_PROFILE_LABEL:
g_free( self->private->label );
self->private->label = g_value_dup_string( value );
break;
- case PROP_PATH:
+ case PROP_PROFILE_PATH:
g_free( self->private->path );
self->private->path = g_value_dup_string( value );
break;
- case PROP_PARAMETERS:
+ case PROP_PROFILE_PARAMETERS:
g_free( self->private->parameters );
self->private->parameters = g_value_dup_string( value );
break;
- case PROP_ACCEPT_MULTIPLE:
+ case PROP_PROFILE_ACCEPT_MULTIPLE:
self->private->accept_multiple_files = g_value_get_boolean( value );
break;
- case PROP_BASENAMES:
+ case PROP_PROFILE_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_ISDIR:
+ case PROP_PROFILE_ISDIR:
self->private->is_dir = g_value_get_boolean( value );
break;
- case PROP_ISFILE:
+ case PROP_PROFILE_ISFILE:
self->private->is_file = g_value_get_boolean( value );
break;
- case PROP_MATCHCASE:
+ case PROP_PROFILE_MATCHCASE:
self->private->match_case = g_value_get_boolean( value );
break;
- case PROP_MIMETYPES:
+ 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 ));
break;
- case PROP_SCHEMES:
+ case PROP_PROFILE_SCHEMES:
na_utils_free_string_list( self->private->schemes );
self->private->schemes = na_utils_duplicate_string_list( g_value_get_pointer( value ));
break;
@@ -460,7 +466,7 @@ na_action_profile_new( const NAObject *action, const gchar *name )
NAActionProfile *profile =
g_object_new(
NA_ACTION_PROFILE_TYPE,
- PROP_ACTION_STR, action, PROP_PROFILE_NAME_STR, name, NULL );
+ PROP_PROFILE_ACTION_STR, action, PROP_PROFILE_NAME_STR, name, NULL );
return( profile );
}
@@ -484,16 +490,16 @@ na_action_profile_copy( const NAActionProfile *profile )
na_action_profile_new( profile->private->action, profile->private->name );
g_object_set( G_OBJECT( new ),
- PROP_LABEL_STR, profile->private->label,
- PROP_PATH_STR, profile->private->path,
- PROP_PARAMETERS_STR, profile->private->parameters,
- PROP_ACCEPT_MULTIPLE_STR, profile->private->accept_multiple_files,
- PROP_BASENAMES_STR, profile->private->basenames,
- PROP_ISDIR_STR, profile->private->is_dir,
- PROP_ISFILE_STR, profile->private->is_file,
- PROP_MATCHCASE_STR, profile->private->match_case,
- PROP_MIMETYPES_STR, profile->private->mimetypes,
- PROP_SCHEMES_STR, profile->private->schemes,
+ 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 );
return( new );
@@ -584,7 +590,7 @@ do_get_label( const NAObject *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
gchar *label;
- g_object_get( G_OBJECT( profile ), PROP_LABEL_STR, &label, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_PROFILE_LABEL_STR, &label, NULL );
return( label );
}
@@ -618,7 +624,7 @@ na_action_profile_get_action( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
gpointer action;
- g_object_get( G_OBJECT( profile ), PROP_ACTION_STR, &action, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_PROFILE_ACTION_STR, &action, NULL );
return( NA_OBJECT( action ));
}
@@ -637,7 +643,7 @@ na_action_profile_get_path( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
gchar *path;
- g_object_get( G_OBJECT( profile ), PROP_PATH_STR, &path, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_PROFILE_PATH_STR, &path, NULL );
return( path );
}
@@ -656,11 +662,132 @@ na_action_profile_get_parameters( const NAActionProfile *profile )
g_assert( NA_IS_ACTION_PROFILE( profile ));
gchar *parameters;
- g_object_get( G_OBJECT( profile ), PROP_PARAMETERS_STR, ¶meters, NULL );
+ g_object_get( G_OBJECT( profile ), PROP_PROFILE_PARAMETERS_STR, ¶meters, NULL );
return( parameters );
}
+/**
+ * Returns the list of basenames this profile applies to.
+ *
+ * @profile: this NAActionProfile object.
+ *
+ * The returned GSList should be freed by the caller by calling
+ * na_utils_free_string_list.
+ */
+GSList *
+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 );
+
+ return( basenames );
+}
+
+/**
+ * Are specified basenames case sensitive ?
+ *
+ * @profile: this NAActionProfile object.
+ */
+gboolean
+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 );
+
+ return( matchcase );
+}
+
+/**
+ * Returns the list of mimetypes this profile applies to.
+ *
+ * @profile: this NAActionProfile object.
+ *
+ * The returned GSList should be freed by the caller by calling
+ * na_utils_free_string_list.
+ */
+GSList *
+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 );
+
+ return( mimetypes );
+}
+
+/**
+ * Does this profile apply to files ?
+ *
+ * @profile: this NAActionProfile object.
+ */
+gboolean
+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 );
+
+ return( isfile );
+}
+
+/**
+ * Does this profile apply to directories ?
+ *
+ * @profile: this NAActionProfile object.
+ */
+gboolean
+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 );
+
+ return( isdir );
+}
+
+/**
+ * Does this profile apply on a multiple selection ?
+ *
+ * @profile: this NAActionProfile object.
+ */
+gboolean
+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 );
+
+ return( multiple );
+}
+
+/**
+ * Returns the list of schemes this profile applies to.
+ *
+ * @profile: this NAActionProfile object.
+ *
+ * The returned GSList should be freed by the caller by calling
+ * na_utils_free_string_list.
+ */
+GSList *
+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 );
+
+ return( schemes );
+}
+
static int
validate_schemes( GSList* schemes2test, NautilusFileInfo* file )
{
diff --git a/src/common/na-action-profile.h b/src/common/na-action-profile.h
index e21c2a1..53ce8a2 100644
--- a/src/common/na-action-profile.h
+++ b/src/common/na-action-profile.h
@@ -68,6 +68,23 @@ typedef struct {
}
NAActionProfileClass;
+/* instance properties
+ * please note that property names must have the same spelling as the
+ * NactIIOProvider parameters
+ */
+#define PROP_PROFILE_ACTION_STR "action"
+#define PROP_PROFILE_NAME_STR "name"
+#define PROP_PROFILE_LABEL_STR "desc-name"
+#define PROP_PROFILE_PATH_STR "path"
+#define PROP_PROFILE_PARAMETERS_STR "parameters"
+#define PROP_PROFILE_ACCEPT_MULTIPLE_STR "accept-multiple-files"
+#define PROP_PROFILE_BASENAMES_STR "basenames"
+#define PROP_PROFILE_ISDIR_STR "isdir"
+#define PROP_PROFILE_ISFILE_STR "isfile"
+#define PROP_PROFILE_MATCHCASE_STR "matchcase"
+#define PROP_PROFILE_MIMETYPES_STR "mimetypes"
+#define PROP_PROFILE_SCHEMES_STR "schemes"
+
GType na_action_profile_get_type( void );
NAActionProfile *na_action_profile_new( const NAObject *action, const gchar *name );
@@ -79,6 +96,13 @@ 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 );
gchar *na_action_profile_get_parameters( const NAActionProfile *profile );
+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_multiple( const NAActionProfile *profile );
+GSList *na_action_profile_get_schemes( const NAActionProfile *profile );
gboolean na_action_profile_is_candidate( const NAActionProfile *profile, GList *files );
gchar *na_action_profile_parse_parameters( const NAActionProfile *profile, GList *files );
diff --git a/src/common/na-action.c b/src/common/na-action.c
index 02b72d4..df97fa4 100644
--- a/src/common/na-action.c
+++ b/src/common/na-action.c
@@ -61,25 +61,35 @@ struct NAActionPrivate {
* (thanks, Frederic ;-))
*/
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;
};
-/* private instance properties
+/* instance properties
* please note that property names must have the same spelling as the
* NactIIOProvider parameters
*/
enum {
- PROP_UUID = 1,
- PROP_VERSION,
- PROP_LABEL,
- PROP_TOOLTIP,
- PROP_ICON
+ PROP_ACTION_UUID = 1,
+ PROP_ACTION_VERSION,
+ PROP_ACTION_LABEL,
+ PROP_ACTION_TOOLTIP,
+ PROP_ACTION_ICON,
+ PROP_ACTION_READONLY
};
-#define PROP_UUID_STR "uuid"
-#define PROP_VERSION_STR "version"
-#define PROP_LABEL_STR "label"
-#define PROP_TOOLTIP_STR "tooltip"
-#define PROP_ICON_STR "icon"
+#define PROP_ACTION_UUID_STR "uuid"
+#define PROP_ACTION_VERSION_STR "version"
+#define PROP_ACTION_LABEL_STR "label"
+#define PROP_ACTION_TOOLTIP_STR "tooltip"
+#define PROP_ACTION_ICON_STR "icon"
+#define PROP_ACTION_READONLY_STR "read-only"
+
+#define NA_ACTION_LATEST_VERSION "2.0"
static NAObjectClass *st_parent_class = NULL;
@@ -145,39 +155,46 @@ class_init( NAActionClass *klass )
/* the id of the object is marked as G_PARAM_CONSTRUCT_ONLY */
spec = g_param_spec_string(
- PROP_UUID_STR,
- PROP_UUID_STR,
+ PROP_ACTION_UUID_STR,
+ PROP_ACTION_UUID_STR,
"Globally unique identifier (UUID) of the action", "",
G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_UUID, spec );
+ g_object_class_install_property( object_class, PROP_ACTION_UUID, spec );
spec = g_param_spec_string(
- PROP_VERSION_STR,
- PROP_VERSION_STR,
+ PROP_ACTION_VERSION_STR,
+ PROP_ACTION_VERSION_STR,
"Version of the schema", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_VERSION, spec );
+ g_object_class_install_property( object_class, PROP_ACTION_VERSION, spec );
spec = g_param_spec_string(
- PROP_LABEL_STR,
- PROP_LABEL_STR,
+ PROP_ACTION_LABEL_STR,
+ PROP_ACTION_LABEL_STR,
"Context menu displayable label", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_LABEL, spec );
+ g_object_class_install_property( object_class, PROP_ACTION_LABEL, spec );
spec = g_param_spec_string(
- PROP_TOOLTIP_STR,
- PROP_TOOLTIP_STR,
+ PROP_ACTION_TOOLTIP_STR,
+ PROP_ACTION_TOOLTIP_STR,
"Context menu tooltip", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_TOOLTIP, spec );
+ g_object_class_install_property( object_class, PROP_ACTION_TOOLTIP, spec );
spec = g_param_spec_string(
- PROP_ICON_STR,
- PROP_ICON_STR,
+ PROP_ACTION_ICON_STR,
+ PROP_ACTION_ICON_STR,
"Context menu displayable icon", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_ICON, spec );
+ g_object_class_install_property( object_class, PROP_ACTION_ICON, spec );
+
+ spec = g_param_spec_boolean(
+ PROP_ACTION_READONLY_STR,
+ PROP_ACTION_READONLY_STR,
+ "Is this action only readable", FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, PROP_ACTION_READONLY, spec );
klass->private = g_new0( NAActionClassPrivate, 1 );
@@ -196,7 +213,17 @@ instance_init( GTypeInstance *instance, gpointer klass )
NAAction* self = NA_ACTION( instance );
self->private = g_new0( NAActionPrivate, 1 );
+
self->private->dispose_has_run = FALSE;
+
+ /* initialize suitable default values, but for label which is
+ * mandatory
+ */
+ self->private->version = g_strdup( NA_ACTION_LATEST_VERSION );
+ self->private->label = NULL;
+ self->private->tooltip = NULL;
+ self->private->icon = NULL;
+ self->private->read_only = FALSE;
}
static void
@@ -206,26 +233,30 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
NAAction *self = NA_ACTION( object );
switch( property_id ){
- case PROP_UUID:
+ case PROP_ACTION_UUID:
g_value_set_string( value, self->private->uuid );
break;
- case PROP_VERSION:
+ case PROP_ACTION_VERSION:
g_value_set_string( value, self->private->version );
break;
- case PROP_LABEL:
+ case PROP_ACTION_LABEL:
g_value_set_string( value, self->private->label );
break;
- case PROP_TOOLTIP:
+ case PROP_ACTION_TOOLTIP:
g_value_set_string( value, self->private->tooltip );
break;
- case PROP_ICON:
+ case PROP_ACTION_ICON:
g_value_set_string( value, self->private->icon );
break;
+ case PROP_ACTION_READONLY:
+ g_value_set_boolean( value, self->private->read_only );
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
break;
@@ -239,31 +270,35 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
NAAction *self = NA_ACTION( object );
switch( property_id ){
- case PROP_UUID:
+ case PROP_ACTION_UUID:
g_free( self->private->uuid );
self->private->uuid = g_value_dup_string( value );
break;
- case PROP_VERSION:
+ case PROP_ACTION_VERSION:
g_free( self->private->version );
self->private->version = g_value_dup_string( value );
break;
- case PROP_LABEL:
+ case PROP_ACTION_LABEL:
g_free( self->private->label );
self->private->label = g_value_dup_string( value );
break;
- case PROP_TOOLTIP:
+ case PROP_ACTION_TOOLTIP:
g_free( self->private->tooltip );
self->private->tooltip = g_value_dup_string( value );
break;
- case PROP_ICON:
+ case PROP_ACTION_ICON:
g_free( self->private->icon );
self->private->icon = g_value_dup_string( value );
break;
+ case PROP_ACTION_READONLY:
+ self->private->read_only = g_value_get_boolean( value );
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
break;
@@ -322,7 +357,7 @@ instance_finalize( GObject *object )
NAAction *
na_action_new( const gchar *uuid )
{
- NAAction *action = g_object_new( NA_ACTION_TYPE, PROP_UUID_STR, uuid, NULL );
+ NAAction *action = g_object_new( NA_ACTION_TYPE, PROP_ACTION_UUID_STR, uuid, NULL );
return( action );
}
@@ -343,17 +378,18 @@ 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_UUID_STR, uuid, NULL );
+ 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;
GSList *ip;
for( ip = action->private->profiles ; ip ; ip = ip->next ){
-
+ /* TODO: duplicate profile */
}
return( duplicate );
@@ -371,11 +407,12 @@ do_dump( const NAObject *action )
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: 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" );
/* dump profiles */
g_debug( "%s: %d profile(s) at %p", thisfn, na_action_get_profiles_count( self ), self->private->profiles );
@@ -391,7 +428,7 @@ do_get_id( const NAObject *action )
g_assert( NA_IS_ACTION( action ));
gchar *uuid;
- g_object_get( G_OBJECT( action ), PROP_UUID_STR, &uuid, NULL );
+ g_object_get( G_OBJECT( action ), PROP_ACTION_UUID_STR, &uuid, NULL );
return( uuid );
}
@@ -427,7 +464,7 @@ na_action_get_version( const NAAction *action )
g_assert( NA_IS_ACTION( action ));
gchar *version;
- g_object_get( G_OBJECT( action ), PROP_VERSION_STR, &version, NULL );
+ g_object_get( G_OBJECT( action ), PROP_ACTION_VERSION_STR, &version, NULL );
return( version );
}
@@ -438,7 +475,7 @@ do_get_label( const NAObject *action )
g_assert( NA_IS_ACTION( action ));
gchar *label;
- g_object_get( G_OBJECT( action ), PROP_LABEL_STR, &label, NULL );
+ g_object_get( G_OBJECT( action ), PROP_ACTION_LABEL_STR, &label, NULL );
return( label );
}
@@ -471,7 +508,7 @@ na_action_get_tooltip( const NAAction *action )
g_assert( NA_IS_ACTION( action ));
gchar *tooltip;
- g_object_get( G_OBJECT( action ), PROP_TOOLTIP_STR, &tooltip, NULL );
+ g_object_get( G_OBJECT( action ), PROP_ACTION_TOOLTIP_STR, &tooltip, NULL );
return( tooltip );
}
@@ -490,7 +527,7 @@ na_action_get_icon( const NAAction *action )
g_assert( NA_IS_ACTION( action ));
gchar *icon;
- g_object_get( G_OBJECT( action ), PROP_ICON_STR, &icon, NULL );
+ g_object_get( G_OBJECT( action ), PROP_ACTION_ICON_STR, &icon, NULL );
return( icon );
}
@@ -509,7 +546,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_ICON_STR, &icon_name, NULL );
+ g_object_get( G_OBJECT( action ), PROP_ACTION_ICON_STR, &icon_name, NULL );
if( icon_name[0] == '/' ){
if( !g_file_test( icon_name, G_FILE_TEST_IS_REGULAR )){
@@ -525,6 +562,19 @@ na_action_get_verified_icon_name( const NAAction *action )
}
/**
+ * Is the specified action only readable ?
+ * Or, in other words, may this action be edited and then saved ?
+ *
+ * @action: an NAAction object.
+ */
+gboolean
+na_action_is_readonly( const NAAction *action )
+{
+ g_assert( NA_IS_ACTION( action ));
+ return( action->private->read_only );
+}
+
+/**
* Set a new UUID for the action.
*
* @action: action whose UUID is to be set.
@@ -539,7 +589,7 @@ na_action_set_new_uuid( NAAction *action )
uuid_generate( uuid );
uuid_unparse_lower( uuid, uuid_str );
- g_object_set( G_OBJECT( action ), PROP_UUID_STR, uuid_str, NULL );
+ g_object_set( G_OBJECT( action ), PROP_ACTION_UUID_STR, uuid_str, NULL );
}
/**
diff --git a/src/common/na-action.h b/src/common/na-action.h
index 7a5bdaa..c8eb992 100644
--- a/src/common/na-action.h
+++ b/src/common/na-action.h
@@ -67,6 +67,17 @@ typedef struct {
}
NAActionClass;
+/* instance properties
+ * please note that property names must have the same spelling as the
+ * NactIIOProvider parameters
+ */
+#define PROP_ACTION_UUID_STR "uuid"
+#define PROP_ACTION_VERSION_STR "version"
+#define PROP_ACTION_LABEL_STR "label"
+#define PROP_ACTION_TOOLTIP_STR "tooltip"
+#define PROP_ACTION_ICON_STR "icon"
+#define PROP_ACTION_READONLY_STR "read-only"
+
GType na_action_get_type( void );
NAAction *na_action_new( const gchar *uuid );
@@ -78,6 +89,7 @@ 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 );
void na_action_set_new_uuid( NAAction *action );
diff --git a/src/common/na-gconf-keys.h b/src/common/na-gconf-keys.h
index 92703e5..b5d2d61 100644
--- a/src/common/na-gconf-keys.h
+++ b/src/common/na-gconf-keys.h
@@ -31,7 +31,25 @@
#ifndef __NA_GCONF_KEYS_H__
#define __NA_GCONF_KEYS_H__
-/* GConf general information */
+/* GConf general information
+ */
#define NA_GCONF_CONFIG_PATH NAUTILUS_ACTIONS_CONFIG_GCONF_BASEDIR "/configurations"
+/* GConf key names
+ */
+#define ACTION_VERSION_ENTRY "version"
+#define ACTION_LABEL_ENTRY "label"
+#define ACTION_TOOLTIP_ENTRY "tooltip"
+#define ACTION_ICON_ENTRY "icon"
+#define ACTION_PROFILE_LABEL_ENTRY "desc-name"
+#define ACTION_PATH_ENTRY "path"
+#define ACTION_PARAMETERS_ENTRY "parameters"
+#define ACTION_BASENAMES_ENTRY "basenames"
+#define ACTION_MATCHCASE_ENTRY "matchcase"
+#define ACTION_MIMETYPES_ENTRY "mimetypes"
+#define ACTION_ISFILE_ENTRY "isfile"
+#define ACTION_ISDIR_ENTRY "isdir"
+#define ACTION_MULTIPLE_ENTRY "accept-multiple-files"
+#define ACTION_SCHEMES_ENTRY "schemes"
+
#endif /* __NA_GCONF_KEYS_H__ */
diff --git a/src/common/na-gconf.c b/src/common/na-gconf.c
index d899650..53c3011 100644
--- a/src/common/na-gconf.c
+++ b/src/common/na-gconf.c
@@ -72,29 +72,50 @@ enum {
static GObjectClass *st_parent_class = NULL;
-static GType register_type( void );
-static void class_init( NAGConfClass *klass );
-static void iio_provider_iface_init( NAIIOProviderInterface *iface );
-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 GSList *do_read_actions( NAIIOProvider *provider );
-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 *keys );
-static gchar *path_to_key( const gchar *path );
-static void set_item_properties( NAObject *object, GSList *properties );
+static GType register_type( void );
+static void class_init( NAGConfClass *klass );
+static void iio_provider_iface_init( NAIIOProviderInterface *iface );
+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 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 *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 gboolean set_action_properties( NAGConf *gconf, NAAction *action, GSList *properties );
+static void load_v1_properties( NAAction *action, const gchar *version, GSList *properties );
+static gchar *search_for_str( GSList *properties, const gchar *profile, const gchar *key );
+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 guint install_gconf_watch( NAGConf *gconf );
-static void remove_gconf_watch( NAGConf *gconf );
-static void action_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data );
+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 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 );
+static gboolean write_str2( NAGConf *gconf, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, gchar **message );
+static gboolean write_key( NAGConf *gconf, const gchar *path, const gchar *value, gchar **message );
+static gboolean write_bool( NAGConf *gconf, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, gchar **message );
+static gboolean write_list( NAGConf *gconf, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, gchar **message );
+
+static guint install_gconf_watch( NAGConf *gconf );
+static void remove_gconf_watch( NAGConf *gconf );
+static void action_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data );
GType
na_gconf_get_type( void )
@@ -168,6 +189,9 @@ iio_provider_iface_init( NAIIOProviderInterface *iface )
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;
}
static void
@@ -271,6 +295,12 @@ na_gconf_new( const GObject *handler )
/*
* 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.
*/
static GSList *
do_read_actions( NAIIOProvider *provider )
@@ -285,7 +315,6 @@ do_read_actions( NAIIOProvider *provider )
GSList *items = NULL;
GSList *ip;
GSList *listpath = load_subdirs( self, NA_GCONF_CONFIG_PATH );
- GSList *profiles;
for( ip = listpath ; ip ; ip = ip->next ){
@@ -293,13 +322,12 @@ do_read_actions( NAIIOProvider *provider )
NAAction *action = na_action_new( key );
- load_action_properties( self, action );
-
- profiles = load_profiles( self, action );
- na_action_set_profiles( action, profiles );
- na_action_free_profiles( profiles );
+ if( load_action( self, action, key )){
+ items = g_slist_prepend( items, action );
- items = g_slist_prepend( items, action );
+ } else {
+ g_object_unref( action );
+ }
g_free( key );
}
@@ -311,12 +339,57 @@ do_read_actions( NAIIOProvider *provider )
/*
* load and set the properties of the specified action
+ * at least we must have a label, as all other entries can have
+ * suitable default values
+ *
+ * we have to deal with successive versions of action schema :
+ *
+ * - version = '1.0'
+ * action+= uuid+label+tooltip+icon
+ * action+= path+parameters+basenames+isdir+isfile+multiple+schemes
+ *
+ * - version > '1.0'
+ * action+= matchcase+mimetypes
+ *
+ * - version = '2.0' which introduces the 'profile' notion
+ * profile += name+label
*/
-static void
+static gboolean
+load_action( NAGConf *gconf, NAAction *action, const gchar *uuid )
+{
+ static const gchar *thisfn = "nacf_gconf_load_action";
+ g_debug( "%s: gconf=%p, action=%p, uuid=%s", thisfn, gconf, action, uuid );
+
+ g_assert( NA_IS_GCONF( gconf ));
+ g_assert( NA_IS_ACTION( action ));
+
+ gchar *path = g_strdup_printf( "%s/%s", NA_GCONF_CONFIG_PATH, uuid );
+
+ GSList *entries = load_keys_values( gconf, path );
+ GSList *properties = keys_to_notify( entries );
+ free_keys_values( entries );
+
+ gboolean ok = set_action_properties( gconf, action, properties );
+
+ if( !gconf_client_key_is_writable( gconf->private->gconf, path, NULL )){
+ g_debug( "%s: %s key is not writable", thisfn, path );
+ gboolean readonly = TRUE;
+ g_object_set( G_OBJECT( action ), PROP_ACTION_READONLY_STR, readonly, NULL );
+ }
+
+ free_list_notify( properties );
+ g_free( path );
+ return( ok );
+}
+
+/*
+ * load and set the properties of the specified action
+ */
+/*static void
load_action_properties( NAGConf *gconf, NAAction *action )
{
- /*static const gchar *thisfn = "nacf_gconf_load_action_properties";
- g_debug( "%s: gconf=%p, action=%p", thisfn, gconf, action );*/
+ static const gchar *thisfn = "nacf_gconf_load_action_properties";
+ g_debug( "%s: gconf=%p, action=%p", thisfn, gconf, action );
g_assert( NA_IS_GCONF( gconf ));
g_assert( NA_IS_ACTION( action ));
@@ -331,7 +404,7 @@ load_action_properties( NAGConf *gconf, NAAction *action )
free_keys_values( properties );
g_free( uuid );
g_free( path );
-}
+}*/
/*
* load the list of profiles for an action and returns them as a GSList
@@ -401,7 +474,7 @@ load_profile_properties( NAGConf *gconf, NAActionProfile *profile )
* load the keys which are the subdirs of the given path
* returns a list of keys as full path
*/
-GSList *
+static GSList *
load_subdirs( const NAGConf *gconf, const gchar *path )
{
static const gchar *thisfn = "na_gconf_load_subdirs";
@@ -418,10 +491,10 @@ load_subdirs( const NAGConf *gconf, const gchar *path )
}
/*
- * load all the key=value pairs of this key (specified as a full path)
+ * 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
+ * path. To free the returned list, call free_key_values.
*/
static GSList *
load_keys_values( const NAGConf *gconf, const gchar *path )
@@ -501,11 +574,188 @@ set_item_properties( NAObject *object, GSList *properties )
}
/*
+ * set the item properties into the action, dealing with successive
+ * versions
+ */
+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";
+
+ gchar *label = search_for_str( properties, NULL, ACTION_LABEL_ENTRY );
+ if( !label ){
+ return( FALSE );
+ }
+
+ gchar *version = search_for_str( properties, NULL, ACTION_VERSION_ENTRY );
+ gchar *tooltip = search_for_str( properties, NULL, ACTION_TOOLTIP_ENTRY );
+ 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,
+ NULL );
+
+ g_free( icon );
+ g_free( tooltip );
+ g_free( label );
+
+ if( g_ascii_strcasecmp( version, "2.0" ) < 0 ){
+
+ load_v1_properties( action, version, properties );
+
+ gchar *uuid = na_action_get_uuid( action );
+ gchar *path = g_strdup_printf( "%s/%s", NA_GCONF_CONFIG_PATH, uuid );
+ if( gconf_client_key_is_writable( gconf->private->gconf, path, NULL )){
+ remove_v1_keys( gconf, action, NULL );
+ }
+ g_free( path );
+ g_free( uuid );
+
+ } else {
+
+ GSList *profiles = load_profiles( gconf, action );
+ na_action_set_profiles( action, profiles );
+ na_action_free_profiles( profiles );
+ }
+
+ g_free( version );
+ return( TRUE );
+}
+
+/*
+ * only handle one profile, which is already loaded
+ * action+= path+parameters+basenames+isdir+isfile+multiple+schemes
+ */
+static void
+load_v1_properties( NAAction *action, const gchar *version, GSList *properties )
+{
+ GSList *profiles = NULL;
+ NAActionProfile *profile = na_action_profile_new( NA_OBJECT( action ), "default" );
+
+ gchar *path = search_for_str( properties, NULL, ACTION_PATH_ENTRY );
+ gchar *parameters = search_for_str( properties, NULL, ACTION_PARAMETERS_ENTRY );
+ GSList *basenames = search_for_list( properties, NULL, ACTION_BASENAMES_ENTRY );
+ gboolean isdir = search_for_bool( properties, NULL, ACTION_ISDIR_ENTRY );
+ gboolean isfile = search_for_bool( properties, NULL, ACTION_ISFILE_ENTRY );
+ gboolean multiple = search_for_bool( properties, NULL, ACTION_MULTIPLE_ENTRY );
+ 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,
+ NULL );
+
+ g_free( path );
+ g_free( parameters );
+ na_utils_free_string_list( basenames );
+ 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 );
+ 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,
+ NULL );
+
+ na_utils_free_string_list( mimetypes );
+ }
+
+ profiles = g_slist_prepend( profiles, profile );
+ na_action_set_profiles( action, profiles );
+ na_action_free_profiles( profiles );
+}
+
+static gchar *
+search_for_str( GSList *properties, const gchar *profile, const gchar *key )
+{
+ 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 )){
+ return( g_strdup(( gchar * ) npn->data ));
+ }
+ }
+ return(( gchar * ) NULL );
+}
+
+static gboolean
+search_for_bool( GSList *properties, const gchar *profile, const gchar *key )
+{
+ 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 )){
+ return(( gboolean ) npn->data );
+ }
+ }
+ return( FALSE );
+}
+
+static GSList *
+search_for_list( GSList *properties, const gchar *profile, const gchar *key )
+{
+ 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 )){
+ return( na_utils_duplicate_string_list(( GSList * ) npn->data ));
+ }
+ }
+ 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.
+ */
+static GSList *
+keys_to_notify( GSList *entries )
+{
+ GSList *item;
+ GSList *properties = NULL;
+
+ for( item = entries ; item ; item = item->next ){
+ GConfEntry *entry = ( GConfEntry * ) item->data;
+ NAPivotNotify *npn = entry_to_notify( entry );
+ properties = g_slist_prepend( properties, npn );
+ }
+
+ return( properties );
+}
+
+/*
* convert a GConfEntry to a structure suitable to notify NAPivot
*
* when created or modified, the entry can be of the forms :
* key/parm
* key/profile/parm with a not null value
+ *
* but when removing an entry, it will be of the form :
* key
* key/parm
@@ -576,6 +826,199 @@ entry_to_notify( const GConfEntry *entry )
return( npn );
}
+static void
+free_list_notify( GSList *list )
+{
+ GSList *il;
+ for( il = list ; il ; il = il->next ){
+ na_pivot_free_notify(( NAPivotNotify *) il->data );
+ }
+}
+
+static gboolean
+remove_v1_keys( NAGConf *gconf, const NAAction *action, gchar **message )
+{
+ gchar *uuid = na_action_get_uuid( action );
+
+ gboolean ret =
+ remove_key( gconf, uuid, ACTION_PATH_ENTRY, message ) &&
+ remove_key( gconf, uuid, ACTION_PARAMETERS_ENTRY, message ) &&
+ remove_key( gconf, uuid, ACTION_BASENAMES_ENTRY, message ) &&
+ remove_key( gconf, uuid, ACTION_MATCHCASE_ENTRY, message ) &&
+ remove_key( gconf, uuid, ACTION_MIMETYPES_ENTRY, message ) &&
+ remove_key( gconf, uuid, ACTION_ISFILE_ENTRY, message ) &&
+ remove_key( gconf, uuid, ACTION_ISDIR_ENTRY, message ) &&
+ remove_key( gconf, uuid, ACTION_MULTIPLE_ENTRY, message ) &&
+ remove_key( gconf, uuid, ACTION_SCHEMES_ENTRY, message );
+
+ g_free( uuid );
+ return( ret );
+}
+
+static gboolean
+remove_key( NAGConf *gconf, const gchar *uuid, const gchar *key, gchar **message )
+{
+ gboolean ret = TRUE;
+ GError *error = NULL;
+
+ gchar *path = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, key );
+
+ if( !gconf_client_unset( gconf->private->gconf, path, &error )){
+ if( message ){
+ *message = g_strdup( error->message );
+ }
+ g_error_free( error );
+ ret = FALSE;
+ }
+
+ 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 );
+ }
+
+ return( NA_IIO_PROVIDER_WRITE_OK );
+}
+
+static gboolean
+write_v2_keys( NAGConf *gconf, const NAAction *action, gchar **message )
+{
+ gchar *uuid = na_action_get_uuid( action );
+
+ gboolean ret =
+ write_str( gconf, uuid, ACTION_VERSION_ENTRY, na_action_get_version( action ), message ) &&
+ write_str( gconf, uuid, ACTION_LABEL_ENTRY, na_action_get_label( action ), message ) &&
+ write_str( gconf, uuid, ACTION_TOOLTIP_ENTRY, na_action_get_tooltip( action ), message ) &&
+ write_str( gconf, uuid, ACTION_ICON_ENTRY, na_action_get_icon( action ), message );
+
+ GSList *ip;
+ GSList *profiles = na_action_get_profiles( action );
+
+ for( ip = profiles ; ip && ret ; ip = ip->next ){
+
+ NAActionProfile *profile = NA_ACTION_PROFILE( ip->data );
+ gchar *name = na_action_profile_get_name( profile );
+
+ ret =
+ write_str2( gconf, uuid, name, ACTION_PROFILE_LABEL_ENTRY, na_action_profile_get_label( profile ), message ) &&
+ write_str2( gconf, uuid, name, ACTION_PATH_ENTRY, na_action_profile_get_path( profile ), message ) &&
+ write_str2( gconf, uuid, name, ACTION_PARAMETERS_ENTRY, na_action_profile_get_parameters( profile ), message ) &&
+ write_list( gconf, uuid, name, ACTION_BASENAMES_ENTRY, na_action_profile_get_basenames( profile ), message ) &&
+ write_bool( gconf, uuid, name, ACTION_MATCHCASE_ENTRY, na_action_profile_get_matchcase( profile ), message ) &&
+ write_list( gconf, uuid, name, ACTION_MIMETYPES_ENTRY, na_action_profile_get_mimetypes( profile ), message ) &&
+ write_bool( gconf, uuid, name, ACTION_ISFILE_ENTRY, na_action_profile_get_is_file( profile ), message ) &&
+ write_bool( gconf, uuid, name, ACTION_ISDIR_ENTRY, na_action_profile_get_is_dir( profile ), message ) &&
+ write_bool( gconf, uuid, name, ACTION_MULTIPLE_ENTRY, na_action_profile_get_multiple( profile ), message ) &&
+ write_list( gconf, uuid, name, ACTION_SCHEMES_ENTRY, na_action_profile_get_schemes( profile ), message );
+
+ g_free( name );
+ }
+
+ g_free( uuid );
+ return( ret );
+}
+
+static gboolean
+write_str( NAGConf *gconf, const gchar *uuid, const gchar *key, gchar *value, gchar **message )
+{
+ gchar *path = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, key );
+ gboolean ret = write_key( gconf, path, value, message );
+ g_free( value );
+ g_free( path );
+ return( ret );
+}
+
+static gboolean
+write_str2( NAGConf *gconf, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, gchar **message )
+{
+ gchar *path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
+ gboolean ret = write_key( gconf, path, value, message );
+ g_free( value );
+ g_free( path );
+ return( ret );
+}
+
+static gboolean
+write_key( NAGConf *gconf, const gchar *path, const gchar *value, gchar **message )
+{
+ gboolean ret = TRUE;
+ GError *error = NULL;
+
+ if( !gconf_client_set_string( gconf->private->gconf, path, value, &error )){
+ *message = g_strdup( error->message );
+ g_error_free( error );
+ ret = FALSE;
+ }
+
+ return( ret );
+}
+
+static gboolean
+write_bool( NAGConf *gconf, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, gchar **message )
+{
+ gboolean ret = TRUE;
+ GError *error = NULL;
+
+ gchar *path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
+
+ if( !gconf_client_set_bool( gconf->private->gconf, path, value, &error )){
+ *message = g_strdup( error->message );
+ g_error_free( error );
+ ret = FALSE;
+ }
+
+ g_free( path );
+ return( ret );
+}
+
+static gboolean
+write_list( NAGConf *gconf, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, gchar **message )
+{
+ gboolean ret = TRUE;
+ GError *error = NULL;
+
+ gchar *path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
+
+ if( !gconf_client_set_list( gconf->private->gconf, path, GCONF_VALUE_STRING, value, &error )){
+ *message = g_strdup( error->message );
+ g_error_free( error );
+ ret = FALSE;
+ }
+
+ na_utils_free_string_list( value );
+ g_free( path );
+ return( ret );
+}
+
/*
* note that we need the NAPivot object in action_changed_cb handler
* but it is initialized as a construction property, and this watch is
diff --git a/src/common/na-iio-provider.c b/src/common/na-iio-provider.c
index 19e53ff..05664a0 100644
--- a/src/common/na-iio-provider.c
+++ b/src/common/na-iio-provider.c
@@ -44,9 +44,12 @@
struct NAIIOProviderInterfacePrivate {
};
-static GType register_type( void );
-static void interface_base_init( NAIIOProviderInterface *klass );
-static void interface_base_finalize( NAIIOProviderInterface *klass );
+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 );
/**
* Registers the GType of this interface.
@@ -100,6 +103,9 @@ 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->write_action = NULL;
initialized = TRUE;
}
@@ -147,7 +153,6 @@ na_iio_provider_read_actions( const GObject *object )
for( ip = providers ; ip ; ip = ip->next ){
instance = NA_IIO_PROVIDER( ip->data );
-
if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->read_actions ){
list = NA_IIO_PROVIDER_GET_INTERFACE( instance )->read_actions( instance );
@@ -182,7 +187,7 @@ na_iio_provider_read_actions( const GObject *object )
*
* Returns TRUE if the write is successfull, FALSE else.
*/
-gboolean
+guint
na_iio_provider_write_action( const GObject *obj_pivot, const GObject *obj_action, gchar **message )
{
static const gchar *thisfn = "na_iio_provider_write_action";
@@ -193,7 +198,7 @@ na_iio_provider_write_action( const GObject *obj_pivot, const GObject *obj_actio
g_assert( NA_IS_ACTION( obj_action ));
- gboolean ret = TRUE;
+ guint ret = NA_IIO_PROVIDER_NOT_WRITABLE;
GSList *ip;
NAIIOProvider *instance;
@@ -202,13 +207,26 @@ na_iio_provider_write_action( const GObject *obj_pivot, const GObject *obj_actio
for( ip = providers ; ip ; ip = ip->next ){
instance = NA_IIO_PROVIDER( ip->data );
-
- /* TODO: write the action
if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->write_action ){
- list = NA_IIO_PROVIDER_GET_INTERFACE( instance )->load_actions( instance );
- actions = g_slist_concat( actions, list );
- }*/
+
+ 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;
+ }
+ }
}
return( ret );
}
+
+static gboolean
+do_is_writable( NAIIOProvider *instance )
+{
+ return( FALSE );
+}
+
+static gboolean
+do_is_willing_to_write( NAIIOProvider *instance, const GObject *action )
+{
+ return( FALSE );
+}
diff --git a/src/common/na-iio-provider.h b/src/common/na-iio-provider.h
index 86c6175..fd9bcd1 100644
--- a/src/common/na-iio-provider.h
+++ b/src/common/na-iio-provider.h
@@ -60,8 +60,10 @@ typedef struct {
NAIIOProviderInterfacePrivate *private;
/* i/o api */
- GSList * ( *read_actions )( NAIIOProvider *instance );
- gboolean ( *write_action )( NAIIOProvider *instance, const GObject *action, gchar **message );
+ 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 );
}
NAIIOProviderInterface;
@@ -69,7 +71,16 @@ GType na_iio_provider_get_type( void );
GSList *na_iio_provider_read_actions( const GObject *pivot );
-gboolean na_iio_provider_write_action( const GObject *pivot, const GObject *action, gchar **message );
+guint na_iio_provider_write_action( const GObject *pivot, const GObject *action, gchar **message );
+
+/* return code of write_action function
+ */
+enum {
+ NA_IIO_PROVIDER_WRITE_OK = 0,
+ NA_IIO_PROVIDER_NOT_WRITABLE,
+ NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE,
+ NA_IIO_PROVIDER_WRITE_ERROR
+};
G_END_DECLS
diff --git a/src/plugin/nautilus-actions.c b/src/plugin/nautilus-actions.c
index f26f639..9bca418 100644
--- a/src/plugin/nautilus-actions.c
+++ b/src/plugin/nautilus-actions.c
@@ -278,7 +278,7 @@ static GList *
get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files )
{
static const gchar *thisfn = "nautilus_actions_get_file_items";
- g_debug( "%s provider=%p, window=%p, files=%p, count=%d", thisfn, provider, window, files, g_list_length( files ));
+ g_debug( "%s: provider=%p, window=%p, files=%p, count=%d", thisfn, provider, window, files, g_list_length( files ));
GList *items = NULL;
GSList* profiles;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]