[nautilus-actions] Introduce NactAction and NactActionProfile classes



commit 2a9f1da6dfabb9d2cd4d11e20c89861ee2c958c2
Author: Pierre Wieser <pwieser trychlos org>
Date:   Mon Jun 1 15:25:48 2009 +0200

    Introduce NactAction and NactActionProfile classes
    
    These two new classes are NactStorage-based and take advantage of GObject properties.
---
 ChangeLog                        |    6 +-
 src/common/Makefile.am           |    4 +
 src/common/nact-action-profile.c |  750 ++++++++++++++++++++++++++++++++++++++
 src/common/nact-action-profile.h |   82 +++++
 src/common/nact-action.c         |  578 +++++++++++++++++++++++++++++
 src/common/nact-action.h         |   90 +++++
 src/common/nact-gconf.c          |   22 +-
 src/common/nact-storage.c        |    4 +-
 src/plugin/nautilus-actions.c    |    4 +-
 9 files changed, 1517 insertions(+), 23 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 83df80a..b5870cd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,12 +10,16 @@
 	Add forward declarations of, remove prefix from, static functions.
 	Do nothing on get_background_items callback.
 
+	* src/common/nact-action.c:
+	* src/common/nact-action.h:
+	* src/common/nact-action-profile.c:
+	* src/common/nact-action-profile.h:
 	* src/common/nact-gconf.c:
 	* src/common/nact-gconf.h:
 	* src/common/nact-gconf-keys.h:
 	* src/common/nact-storage.c:
 	* src/common/nact-storage.h:
-	New files, prepare for a new object hierarchy (with shorter names).
+	New files, preparing for a new object hierarchy (with shorter names).
 
 	* src/common/uti-lists.c:
 	* src/common/uti-lists.h:
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 9ec148d..a47375c 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -35,6 +35,10 @@ AM_CPPFLAGS += \
 	$(NULL)
 
 libnact_la_SOURCES = \
+	nact-action.c								\
+	nact-action.h								\
+	nact-action-profile.c						\
+	nact-action-profile.h						\
 	nact-gconf.c								\
 	nact-gconf.h								\
 	nact-gconf-keys.h							\
diff --git a/src/common/nact-action-profile.c b/src/common/nact-action-profile.c
new file mode 100644
index 0000000..2e906a3
--- /dev/null
+++ b/src/common/nact-action-profile.c
@@ -0,0 +1,750 @@
+/*
+ * 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 <libnautilus-extension/nautilus-file-info.h>
+#include <string.h>
+#include "nact-action-profile.h"
+
+static NactStorageClass *st_parent_class = NULL;
+
+static GType  register_type( void );
+static void   class_init( NactActionProfileClass *klass );
+static void   instance_init( GTypeInstance *instance, gpointer klass );
+static void   instance_dispose( 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_finalize( GObject *object );
+static gchar *get_id( const NactStorage *profile );
+static void   do_dump( const NactStorage *profile );
+static void   do_dump_list( const gchar *thisfn, const gchar *label, GSList *list );
+static void   free_string_list( GSList *list );
+static int    validate_schemes( GSList* schemes2test, NautilusFileInfo* file );
+
+enum {
+	PROP_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
+};
+
+struct NactActionProfilePrivate {
+	gboolean  dispose_has_run;
+
+	/* the NactAction object
+	 */
+	gpointer  action;
+
+	/* profile properties
+	 */
+	gchar    *name;
+	gchar    *label;
+	gchar    *path;
+	gchar    *parameters;
+	gboolean  accept_multiple_files;
+	GSList   *basenames;
+	gboolean  is_dir;
+	gboolean  is_file;
+	gboolean  match_case;
+	GSList   *mimetypes;
+	GSList   *schemes;
+};
+
+struct NactActionProfileClassPrivate {
+};
+
+GType
+nact_action_profile_get_type( void )
+{
+	static GType object_type = 0;
+
+	if( !object_type ){
+		object_type = register_type();
+	}
+
+	return( object_type );
+}
+
+static GType
+register_type( void )
+{
+	static GTypeInfo info = {
+		sizeof( NactActionProfileClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NactActionProfile ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	return( g_type_register_static( NACT_STORAGE_TYPE, "NactActionProfile", &info, 0 ));
+}
+
+static void
+class_init( NactActionProfileClass *klass )
+{
+	static const gchar *thisfn = "nact_action_profile_class_init";
+	g_debug( "%s: klass=%p", thisfn, klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	GObjectClass *object_class = G_OBJECT_CLASS( klass );
+	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_pointer(
+			"action",
+			"action",
+			"The NactAction object",
+			G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_ACTION, spec );
+
+	/* the id of the object is marked as G_PARAM_CONSTRUCT_ONLY */
+	spec = g_param_spec_string(
+			"name",
+			"name",
+			"Internal profile's name", "",
+			G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_PROFILE_NAME, spec );
+
+	spec = g_param_spec_string(
+			"desc-name",
+			"desc-name",
+			"Displayable profile's name", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_LABEL, spec );
+
+	spec = g_param_spec_string(
+			"path",
+			"path",
+			"Command path", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_PATH, spec );
+
+	spec = g_param_spec_string(
+			"parameters",
+			"parameters",
+			"Command parameters", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_PARAMETERS, spec );
+
+	spec = g_param_spec_boolean(
+			"accept-multiple-files",
+			"accept-multiple-files",
+			"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 );
+
+	spec = g_param_spec_pointer(
+			"basenames",
+			"basenames",
+			"Filenames mask",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_BASENAMES, spec );
+
+	spec = g_param_spec_boolean(
+			"isdir",
+			"isdir",
+			"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 );
+
+	spec = g_param_spec_boolean(
+			"isfile",
+			"isfile",
+			"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 );
+
+	spec = g_param_spec_boolean(
+			"matchcase",
+			"matchcase",
+			"Whether the filenames are case sensitive", TRUE,
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_MATCHCASE, spec );
+
+	spec = g_param_spec_pointer(
+			"mimetypes",
+			"mimetypes",
+			"List of selectable mimetypes",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_MIMETYPES, spec );
+
+	spec = g_param_spec_pointer(
+			"schemes",
+			"schemes",
+			"list of selectable schemes",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_SCHEMES, spec );
+
+	klass->private = g_new0( NactActionProfileClassPrivate, 1 );
+
+	NACT_STORAGE_CLASS( klass )->get_id = get_id;
+	NACT_STORAGE_CLASS( klass )->do_dump = do_dump;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "nact_action_profile_instance_init";
+	g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
+
+	g_assert( NACT_IS_ACTION_PROFILE( instance ));
+
+	NactActionProfile* self = NACT_ACTION_PROFILE( instance );
+
+	self->private = g_new0( NactActionProfilePrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+	g_assert( NACT_IS_ACTION_PROFILE( object ));
+
+	NactActionProfile *self = NACT_ACTION_PROFILE( object );
+
+	switch( property_id ){
+		case PROP_ACTION:
+			g_value_set_pointer( value, self->private->action );
+			break;
+
+		case PROP_PROFILE_NAME:
+			g_value_set_string( value, self->private->name );
+			break;
+
+		case PROP_LABEL:
+			g_value_set_string( value, self->private->label );
+			break;
+
+		case PROP_PATH:
+			g_value_set_string( value, self->private->path );
+			break;
+
+		case PROP_PARAMETERS:
+			g_value_set_string( value, self->private->parameters );
+			break;
+
+		case PROP_ACCEPT_MULTIPLE:
+			g_value_set_boolean( value, self->private->accept_multiple_files );
+			break;
+
+		case PROP_BASENAMES:
+			g_value_set_pointer( value, self->private->basenames );
+			break;
+
+		case PROP_ISDIR:
+			g_value_set_boolean( value, self->private->is_dir );
+			break;
+
+		case PROP_ISFILE:
+			g_value_set_boolean( value, self->private->is_file );
+			break;
+
+		case PROP_MATCHCASE:
+			g_value_set_boolean( value, self->private->match_case );
+			break;
+
+		case PROP_MIMETYPES:
+			g_value_set_pointer( value, self->private->mimetypes );
+			break;
+
+		case PROP_SCHEMES:
+			g_value_set_pointer( value, self->private->schemes );
+			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( NACT_IS_ACTION_PROFILE( object ));
+
+	NactActionProfile *self = NACT_ACTION_PROFILE( object );
+
+	switch( property_id ){
+		case PROP_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 );
+			break;
+
+		case PROP_LABEL:
+			g_free( self->private->label );
+			self->private->label = g_value_dup_string( value );
+			break;
+
+		case PROP_PATH:
+			g_free( self->private->path );
+			self->private->path = g_value_dup_string( value );
+			break;
+
+		case PROP_PARAMETERS:
+			g_free( self->private->parameters );
+			self->private->parameters = g_value_dup_string( value );
+			break;
+
+		case PROP_ACCEPT_MULTIPLE:
+			self->private->accept_multiple_files = g_value_get_boolean( value );
+			break;
+
+		case PROP_BASENAMES:
+			free_string_list( self->private->basenames );
+			self->private->basenames = g_value_get_pointer( value );
+			break;
+
+		case PROP_ISDIR:
+			self->private->is_dir = g_value_get_boolean( value );
+			break;
+
+		case PROP_ISFILE:
+			self->private->is_file = g_value_get_boolean( value );
+			break;
+
+		case PROP_MATCHCASE:
+			self->private->match_case = g_value_get_boolean( value );
+			break;
+
+		case PROP_MIMETYPES:
+			free_string_list( self->private->mimetypes );
+			self->private->mimetypes = g_value_get_pointer( value );
+			break;
+
+		case PROP_SCHEMES:
+			free_string_list( self->private->schemes );
+			self->private->schemes = g_value_get_pointer( value );
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+			break;
+	}
+}
+
+static void
+instance_dispose( GObject *object )
+{
+	static const gchar *thisfn = "nact_action_profile_instance_dispose";
+	g_debug( "%s: object=%p", thisfn, object );
+
+	g_assert( NACT_IS_ACTION_PROFILE( object ));
+
+	NactActionProfile *self = NACT_ACTION_PROFILE( object );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		/* chain up to the parent class */
+		G_OBJECT_CLASS( st_parent_class )->dispose( object );
+	}
+}
+
+static void
+instance_finalize( GObject *object )
+{
+	static const gchar *thisfn = "nact_action_profile_instance_finalize";
+	g_debug( "%s: object=%p", thisfn, object );
+
+	g_assert( NACT_IS_ACTION_PROFILE( object ));
+
+	NactActionProfile *self = ( NactActionProfile * ) object;
+
+	g_free( self->private->name );
+	g_free( self->private->label );
+	g_free( self->private->path );
+	g_free( self->private->parameters );
+
+	/* chain call to parent class */
+	if((( GObjectClass * ) st_parent_class )->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( object );
+	}
+}
+
+NactActionProfile *
+nact_action_profile_new( const NactStorage *action, const gchar *name )
+{
+	g_assert( NACT_IS_STORAGE( action ));
+	g_assert( name && strlen( name ));
+
+	NactActionProfile *profile =
+		g_object_new( NACT_ACTION_PROFILE_TYPE, "action", action, "name", name, NULL );
+	return( profile );
+}
+
+static gchar *
+get_id( const NactStorage *profile )
+{
+	g_assert( NACT_IS_ACTION_PROFILE( profile ));
+	gchar *id;
+	g_object_get( G_OBJECT( profile ), "name", &id, NULL );
+	return( id );
+}
+
+static void
+do_dump( const NactStorage *object )
+{
+	static const gchar *thisfn = "nact_action_profile_do_dump";
+
+	g_assert( NACT_IS_ACTION_PROFILE( object ));
+
+	if( st_parent_class->do_dump ){
+		st_parent_class->do_dump( object );
+	}
+
+	NactActionProfile *self = NACT_ACTION_PROFILE( object );
+
+	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 void
+free_string_list( GSList *list ){
+	GSList *item;
+	for( item = list ; item != NULL ; item = item->next ){
+		g_free(( gchar * ) item->data );
+	}
+	g_slist_free( list );
+}
+
+gchar *
+nact_action_profile_get_path( const NactActionProfile *profile )
+{
+	g_assert( NACT_IS_ACTION_PROFILE( profile ));
+
+	gchar *path;
+	g_object_get( G_OBJECT( profile ), "path", &path, NULL );
+
+	return( path );
+}
+
+gchar *
+nact_action_profile_get_parameters( const NactActionProfile *profile )
+{
+	g_assert( NACT_IS_ACTION_PROFILE( profile ));
+
+	gchar *parameters;
+	g_object_get( G_OBJECT( profile ), "parameters", &parameters, NULL );
+
+	return( parameters );
+}
+
+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;
+}
+
+gboolean
+nact_action_profile_validate( const NactActionProfile *profile, GList* files )
+{
+	gboolean retv = FALSE;
+	gboolean test_multiple_file = FALSE;
+	gboolean test_file_type = FALSE;
+	gboolean test_scheme = FALSE;
+	gboolean test_basename = FALSE;
+	gboolean test_mimetype = FALSE;
+	GList* glob_patterns = NULL;
+	GList* glob_mime_patterns = NULL;
+	GSList* iter;
+	GList* iter1;
+	GList* iter2;
+	guint dir_count = 0;
+	guint file_count = 0;
+	guint total_count = 0;
+	guint scheme_ok_count = 0;
+	guint glob_ok_count = 0;
+	guint mime_glob_ok_count = 0;
+	gboolean basename_match_ok = FALSE;
+	gboolean mimetype_match_ok = FALSE;
+
+	if (profile->private->basenames && profile->private->basenames->next != NULL &&
+			g_ascii_strcasecmp ((gchar*)(profile->private->basenames->data), "*") == 0)
+	{
+		/* if the only pattern is '*' then all files will match, so it
+		 * is not necessary to make the test for each of them
+		 */
+		test_basename = TRUE;
+	}
+	else
+	{
+		for (iter = profile->private->basenames; iter; iter = iter->next)
+		{
+			gchar* tmp_pattern = (gchar*)iter->data;
+			if (!profile->private->match_case)
+			{
+				/* --> if case-insensitive asked, lower all the string
+				 * since the pattern matching function don't manage it
+				 * itself.
+				 */
+				tmp_pattern = g_ascii_strdown ((gchar*)iter->data, strlen ((gchar*)iter->data));
+			}
+
+			glob_patterns = g_list_append (glob_patterns, g_pattern_spec_new (tmp_pattern));
+
+			if (!profile->private->match_case)
+			{
+				g_free (tmp_pattern);
+			}
+		}
+	}
+
+	if (profile->private->mimetypes && profile->private->mimetypes->next != NULL &&
+			(g_ascii_strcasecmp ((gchar*)(profile->private->mimetypes->data), "*") == 0 ||
+			 g_ascii_strcasecmp ((gchar*)(profile->private->mimetypes->data), "*/*") == 0))
+	{
+		/* if the only pattern is '*' or * / * then all mimetypes will
+		 * match, so it is not necessary to make the test for each of them
+		 */
+		test_mimetype = TRUE;
+	}
+	else
+	{
+		for (iter = profile->private->mimetypes; iter; iter = iter->next)
+		{
+			glob_mime_patterns = g_list_append (glob_mime_patterns, g_pattern_spec_new ((gchar*)iter->data));
+		}
+	}
+
+	for (iter1 = files; iter1; iter1 = iter1->next)
+	{
+		gchar* tmp_filename = nautilus_file_info_get_name ((NautilusFileInfo *)iter1->data);
+
+		if (tmp_filename)
+		{
+			gchar* tmp_mimetype = nautilus_file_info_get_mime_type ((NautilusFileInfo *)iter1->data);
+
+			if (!profile->private->match_case)
+			{
+				/* --> if case-insensitive asked, lower all the string
+				 * since the pattern matching function don't manage it
+				 * itself.
+				 */
+				gchar* tmp_filename2 = g_ascii_strdown (tmp_filename, strlen (tmp_filename));
+				g_free (tmp_filename);
+				tmp_filename = tmp_filename2;
+			}
+
+			/* --> for the moment we deal with all mimetypes case-insensitively */
+			gchar* tmp_mimetype2 = g_ascii_strdown (tmp_mimetype, strlen (tmp_mimetype));
+			g_free (tmp_mimetype);
+			tmp_mimetype = tmp_mimetype2;
+
+			if (nautilus_file_info_is_directory ((NautilusFileInfo *)iter1->data))
+			{
+				dir_count++;
+			}
+			else
+			{
+				file_count++;
+			}
+
+			scheme_ok_count += validate_schemes (profile->private->schemes, (NautilusFileInfo*)iter1->data);
+
+			if (!test_basename) /* if it is already ok, skip the test to improve performance */
+			{
+				basename_match_ok = FALSE;
+				iter2 = glob_patterns;
+				while (iter2 && !basename_match_ok)
+				{
+					if (g_pattern_match_string ((GPatternSpec*)iter2->data, tmp_filename))
+					{
+						basename_match_ok = TRUE;
+					}
+					iter2 = iter2->next;
+				}
+
+				if (basename_match_ok)
+				{
+					glob_ok_count++;
+				}
+			}
+
+			if (!test_mimetype) /* if it is already ok, skip the test to improve performance */
+			{
+				mimetype_match_ok = FALSE;
+				iter2 = glob_mime_patterns;
+				while (iter2 && !mimetype_match_ok)
+				{
+					if (g_pattern_match_string ((GPatternSpec*)iter2->data, tmp_mimetype))
+					{
+						mimetype_match_ok = TRUE;
+					}
+					iter2 = iter2->next;
+				}
+
+				if (mimetype_match_ok)
+				{
+					mime_glob_ok_count++;
+				}
+			}
+
+			g_free (tmp_mimetype);
+			g_free (tmp_filename);
+
+		}
+
+		total_count++;
+	}
+
+	if ((files != NULL) && (files->next == NULL) && (!profile->private->accept_multiple_files))
+	{
+		test_multiple_file = TRUE;
+	}
+	else if (profile->private->accept_multiple_files)
+	{
+		test_multiple_file = TRUE;
+	}
+
+	if (profile->private->is_dir && profile->private->is_file)
+	{
+		if (dir_count > 0 || file_count > 0)
+		{
+			test_file_type = TRUE;
+		}
+	}
+	else if (profile->private->is_dir && !profile->private->is_file)
+	{
+		if (file_count == 0)
+		{
+			test_file_type = TRUE;
+		}
+	}
+	else if (!profile->private->is_dir && profile->private->is_file)
+	{
+		if (dir_count == 0)
+		{
+			test_file_type = TRUE;
+		}
+	}
+
+	if (scheme_ok_count == total_count)
+	{
+		test_scheme = TRUE;
+	}
+
+
+	if (!test_basename) /* if not already tested */
+	{
+		if (glob_ok_count == total_count)
+		{
+			test_basename = TRUE;
+		}
+	}
+
+	if (!test_mimetype) /* if not already tested */
+	{
+		if (mime_glob_ok_count == total_count)
+		{
+			test_mimetype = TRUE;
+		}
+	}
+
+	if (test_basename && test_mimetype && test_file_type && test_scheme && test_multiple_file)
+	{
+		retv = TRUE;
+	}
+
+	g_list_foreach (glob_patterns, (GFunc) g_pattern_spec_free, NULL);
+	g_list_free (glob_patterns);
+	g_list_foreach (glob_mime_patterns, (GFunc) g_pattern_spec_free, NULL);
+	g_list_free (glob_mime_patterns);
+
+	return retv;
+}
diff --git a/src/common/nact-action-profile.h b/src/common/nact-action-profile.h
new file mode 100644
index 0000000..672866c
--- /dev/null
+++ b/src/common/nact-action-profile.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 __NACT_ACTION_PROFILE_H__
+#define __NACT_ACTION_PROFILE_H__
+
+/*
+ * NactActionProfile class definition.
+ *
+ * This is a companion class of NactAction. It embeds the profile
+ * definition of an action.
+ *
+ * As NactAction itself, NactActionProfile class is derived from
+ * NactStorage which takes care of i/o.
+ */
+
+#include "nact-storage.h"
+
+G_BEGIN_DECLS
+
+#define NACT_ACTION_PROFILE_TYPE				( nact_action_profile_get_type())
+#define NACT_ACTION_PROFILE( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_ACTION_PROFILE_TYPE, NactActionProfile ))
+#define NACT_ACTION_PROFILE_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_ACTION_PROFILE_TYPE, NactActionProfileClass ))
+#define NACT_IS_ACTION_PROFILE( object )		( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_ACTION_PROFILE_TYPE ))
+#define NACT_IS_ACTION_PROFILE_CLASS( klass )	( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_ACTION_PROFILE_TYPE ))
+#define NACT_ACTION_PROFILE_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_ACTION_PROFILE_TYPE, NactActionProfileClass ))
+
+typedef struct NactActionProfilePrivate NactActionProfilePrivate;
+
+typedef struct {
+	NactStorage               parent;
+	NactActionProfilePrivate *private;
+}
+	NactActionProfile;
+
+typedef struct NactActionProfileClassPrivate NactActionProfileClassPrivate;
+
+typedef struct {
+	NactStorageClass               parent;
+	NactActionProfileClassPrivate *private;
+}
+	NactActionProfileClass;
+
+GType              nact_action_profile_get_type( void );
+
+NactActionProfile *nact_action_profile_new( const NactStorage *action, const gchar *name );
+
+gchar             *nact_action_profile_get_path( const NactActionProfile *profile );
+gchar             *nact_action_profile_get_parameters( const NactActionProfile *profile );
+
+gboolean           nact_action_profile_validate( const NactActionProfile *profile, GList *files );
+
+G_END_DECLS
+
+#endif /* __NACT_ACTION_PROFILE_H__ */
diff --git a/src/common/nact-action.c b/src/common/nact-action.c
new file mode 100644
index 0000000..9e18f71
--- /dev/null
+++ b/src/common/nact-action.c
@@ -0,0 +1,578 @@
+/*
+ * 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 <string.h>
+#include "nact-action.h"
+#include "nact-action-profile.h"
+#include "uti-lists.h"
+
+static NactStorageClass *st_parent_class = NULL;
+
+static GType       register_type( void );
+static void        class_init( NactActionClass *klass );
+static void        instance_init( GTypeInstance *instance, gpointer klass );
+static void        instance_dispose( 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_finalize( GObject *object );
+static NactAction *new_action( const gchar *uuid );
+static gchar      *get_id( const NactStorage *action );
+static void        do_dump( const NactStorage *action );
+static NactAction *load_action( const gchar *uuid );
+
+enum {
+	PROP_UUID = 1,
+	PROP_VERSION,
+	PROP_LABEL,
+	PROP_TOOLTIP,
+	PROP_ICON
+};
+
+struct NactActionPrivate {
+	gboolean  dispose_has_run;
+
+	/* action properties
+	 */
+	gchar    *uuid;
+	gchar    *version;
+	gchar    *label;
+	gchar    *tooltip;
+	gchar    *icon;
+
+	/* list of action's profiles as NactActionProfile objects
+	 *  (thanks, Frederic ;-))
+	 */
+	GSList   *profiles;
+};
+
+struct NactActionClassPrivate {
+};
+
+GType
+nact_action_get_type( void )
+{
+	static GType action_type = 0;
+
+	if( !action_type ){
+		action_type = register_type();
+	}
+
+	return( action_type );
+}
+
+static GType
+register_type( void )
+{
+	static GTypeInfo info = {
+		sizeof( NactActionClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NactAction ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	return( g_type_register_static( NACT_STORAGE_TYPE, "NactAction", &info, 0 ));
+}
+
+static void
+class_init( NactActionClass *klass )
+{
+	static const gchar *thisfn = "nact_action_class_init";
+	g_debug( "%s: klass=%p", thisfn, klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	GObjectClass *object_class = G_OBJECT_CLASS( klass );
+	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;
+
+	/* the id of the object is marked as G_PARAM_CONSTRUCT_ONLY */
+	spec = g_param_spec_string(
+			"uuid",
+			"uuid",
+			"Globally unique identifier of the action", "",
+			G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_UUID, spec );
+
+	spec = g_param_spec_string(
+			"version",
+			"version",
+			"Version of the schema", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_VERSION, spec );
+
+	spec = g_param_spec_string(
+			"label",
+			"label",
+			"Context menu displayable label", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_LABEL, spec );
+
+	spec = g_param_spec_string(
+			"tooltip",
+			"tooltip",
+			"Context menu tooltip", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_TOOLTIP, spec );
+
+	spec = g_param_spec_string(
+			"icon",
+			"icon",
+			"Context menu displayable icon", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_ICON, spec );
+
+	klass->private = g_new0( NactActionClassPrivate, 1 );
+
+	NACT_STORAGE_CLASS( klass )->get_id = get_id;
+	NACT_STORAGE_CLASS( klass )->do_dump = do_dump;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "nact_action_instance_init";
+	g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
+
+	g_assert( NACT_IS_ACTION( instance ));
+
+	NactAction* self = NACT_ACTION( instance );
+
+	self->private = g_new0( NactActionPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+	g_assert( NACT_IS_ACTION( object ));
+
+	NactAction *self = NACT_ACTION( object );
+
+	switch( property_id ){
+		case PROP_UUID:
+			g_value_set_string( value, self->private->uuid );
+			break;
+
+		case PROP_VERSION:
+			g_value_set_string( value, self->private->version );
+			break;
+
+		case PROP_LABEL:
+			g_value_set_string( value, self->private->label );
+			break;
+
+		case PROP_TOOLTIP:
+			g_value_set_string( value, self->private->tooltip );
+			break;
+
+		case PROP_ICON:
+			g_value_set_string( value, self->private->icon );
+			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( NACT_IS_ACTION( object ));
+
+	NactAction *self = NACT_ACTION( object );
+
+	switch( property_id ){
+		case PROP_UUID:
+			g_free( self->private->uuid );
+			self->private->uuid = g_value_dup_string( value );
+			break;
+
+		case PROP_VERSION:
+			g_free( self->private->version );
+			self->private->version = g_value_dup_string( value );
+			break;
+
+		case PROP_LABEL:
+			g_free( self->private->label );
+			self->private->label = g_value_dup_string( value );
+			break;
+
+		case PROP_TOOLTIP:
+			g_free( self->private->tooltip );
+			self->private->tooltip = g_value_dup_string( value );
+			break;
+
+		case PROP_ICON:
+			g_free( self->private->icon );
+			self->private->icon = g_value_dup_string( value );
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+			break;
+	}
+}
+
+static void
+instance_dispose( GObject *object )
+{
+	static const gchar *thisfn = "nact_action_instance_dispose";
+	g_debug( "%s: object=%p", thisfn, object );
+
+	g_assert( NACT_IS_ACTION( object ));
+
+	NactAction *self = NACT_ACTION( object );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		GSList *item;
+		for( item = self->private->profiles ; item != NULL ; item = item->next ){
+			g_object_unref( NACT_ACTION_PROFILE( item->data ));
+		}
+
+		/* chain up to the parent class */
+		G_OBJECT_CLASS( st_parent_class )->dispose( object );
+	}
+}
+
+static void
+instance_finalize( GObject *object )
+{
+	static const gchar *thisfn = "nact_action_instance_finalize";
+	g_debug( "%s: object=%p", thisfn, object );
+
+	g_assert( NACT_IS_ACTION( object ));
+
+	NactAction *self = ( NactAction * ) 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 );
+
+	/* chain call to parent class */
+	if((( GObjectClass * ) st_parent_class )->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( object );
+	}
+}
+
+static NactAction *
+new_action( const gchar *uuid )
+{
+	NactAction *action = g_object_new( NACT_ACTION_TYPE, "uuid", uuid, NULL );
+	return( action );
+}
+
+static gchar *
+get_id( const NactStorage *action )
+{
+	g_assert( NACT_IS_ACTION( action ));
+	gchar *id;
+	g_object_get( G_OBJECT( action ), "uuid", &id, NULL );
+	return( id );
+}
+
+static void
+do_dump( const NactStorage *action )
+{
+	static const gchar *thisfn = "nact_action_do_dump";
+
+	g_assert( NACT_IS_ACTION( action ));
+
+	if( st_parent_class->do_dump ){
+		st_parent_class->do_dump( action );
+	}
+
+	NactAction *self = NACT_ACTION( 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 );
+
+	/* dump profiles */
+	g_debug( "%s: %d profile(s) at %p", thisfn, nact_action_get_profiles_count( self ), self->private->profiles );
+	GSList *item;
+	for( item = self->private->profiles ;	item != NULL ; item = item->next ){
+		nact_storage_dump(( const NactStorage * ) item->data );
+	}
+}
+
+/*
+ * load action
+ *
+ * +- load_action_properties
+ *
+ * +- load_profile_names
+ *
+ * +
+ */
+static NactAction *
+load_action( const gchar *uuid )
+{
+	g_assert( uuid && strlen( uuid ));
+
+	NactAction *action = new_action( uuid );
+
+	if( !nact_storage_load_action_properties( NACT_STORAGE( action ))){
+		g_object_unref( action );
+		return( NULL );
+	}
+
+	GSList *list = nact_storage_load_profile_ids( NACT_STORAGE( action ));
+	if( !list ){
+		g_object_unref( action );
+		return( NULL );
+	}
+
+	GSList *profile_id;
+	for( profile_id = list ; profile_id != NULL ; profile_id = profile_id->next ){
+
+		NactActionProfile *profile_obj =
+			nact_action_profile_new( NACT_STORAGE( action), ( const gchar * ) profile_id->data );
+
+		if( !nact_storage_load_profile_properties( NACT_STORAGE( profile_obj ))){
+			g_object_unref( profile_obj );
+			g_object_unref( action );
+			return( NULL );
+		}
+
+		action->private->profiles = g_slist_prepend( action->private->profiles, profile_obj );
+	}
+
+	return( action );
+}
+
+/*
+ * nautilus-actions_instance_init
+ * +- nautilus_actions_load_list_actions
+ *
+ *    +- nact_action_load_actions
+ *
+ *       +- nact_action_load_uuids
+ *       |  +- nact_storage_load_uuids
+ *       |     retrieve all storage subsystems (gconf only for now)
+ *       |     foreach subsystem, do
+ *       |     +- nact_<subsystem>_load_uuids
+ *       |
+ *       + foreach uuid, do
+ *         +- new NactAction
+ *         +- load_action
+ */
+GSList *
+nact_action_load_actions( void )
+{
+	static gchar *thisfn = "nact_action_load_actions";
+	g_debug( "%s", thisfn );
+
+	GSList *actions = NULL;
+
+	/* we read a first list which contains the list of action keys */
+	GSList *list = nact_storage_load_action_ids();
+
+	/* for each item (uuid) of the list, we allocate a new NactAction
+	 * object and prepend it to the returned list
+	 */
+	GSList *key;
+	for( key = list ; key != NULL ; key = key->next ){
+		NactAction *action_obj = load_action(( gchar *) key->data );
+		if( action_obj ){
+			nact_storage_dump( NACT_STORAGE( action_obj ));
+			actions = g_slist_prepend( actions, action_obj );
+		}
+	}
+
+	/* eventually, free the list of action keys */
+	nact_storage_free_action_ids( list );
+
+	return( actions );
+}
+
+/**
+ * Return the globally unique identifier (UUID) of the action.
+ *
+ * @action: an NactAction object.
+ *
+ * The returned string must be g_free by the caller.
+ */
+gchar *
+nact_action_get_uuid( const NactAction *action )
+{
+	g_assert( NACT_IS_ACTION( action ));
+
+	gchar *uuid;
+	g_object_get( G_OBJECT( action ), "uuid", &uuid, NULL );
+
+	return( uuid );
+}
+
+/**
+ * Return the label of the context menu item for the action.
+ *
+ * @action: an NactAction object.
+ *
+ * The returned string must be g_free by the caller.
+ */
+gchar *
+nact_action_get_label( const NactAction *action )
+{
+	g_assert( NACT_IS_ACTION( action ));
+
+	gchar *label;
+	g_object_get( G_OBJECT( action ), "label", &label, NULL );
+
+	return( label );
+}
+
+/**
+ * Return the tooltip attached to the context menu item for the action.
+ *
+ * @action: an NactAction object.
+ *
+ * The returned string must be g_free by the caller.
+ */
+gchar *
+nact_action_get_tooltip( const NactAction *action )
+{
+	g_assert( NACT_IS_ACTION( action ));
+
+	gchar *tooltip;
+	g_object_get( G_OBJECT( action ), "tooltip", &tooltip, NULL );
+
+	return( tooltip );
+}
+
+/**
+ * Return the icon name attached to the context menu item for the
+ * action.
+ *
+ * @action: an NactAction object.
+ *
+ * When not null, the returned string must be g_free by the caller.
+ */
+gchar *
+nact_action_get_verified_icon_name( const NactAction *action )
+{
+	g_assert( NACT_IS_ACTION( action ));
+
+	gchar *icon_name;
+	g_object_get( G_OBJECT( action ), "icon", &icon_name, NULL );
+
+	if( icon_name[0] == '/' ){
+		if( !g_file_test( icon_name, G_FILE_TEST_IS_REGULAR )){
+			g_free( icon_name );
+			return NULL;
+		}
+	} else if( strlen( icon_name ) == 0 ){
+		g_free( icon_name );
+		return NULL;
+	}
+
+	return( icon_name );
+}
+
+GSList *
+nact_action_get_profiles( const NactAction *action )
+{
+	g_assert( NACT_IS_ACTION( action ));
+	return( action->private->profiles );
+}
+
+guint
+nact_action_get_profiles_count( const NactAction *action )
+{
+	g_assert( NACT_IS_ACTION( action ));
+	return( g_slist_length( action->private->profiles ));
+}
+
+GSList *
+nact_action_get_profile_ids( const NactAction *action )
+{
+	GSList *item;
+	GSList *profile_names = NULL;
+	gchar *name;
+	NactActionProfile *profile;
+
+	g_assert( NACT_IS_ACTION( action ));
+
+	for( item = action->private->profiles ; item != NULL ; item = item->next ){
+		profile = ( NactActionProfile * ) item->data;
+		g_object_get( G_OBJECT( profile ), "name", &name, NULL );
+		profile_names = g_slist_prepend( profile_names, name );
+	}
+
+	return( profile_names );
+}
+
+void
+nact_action_free_profile_ids( GSList *list )
+{
+	nactuti_free_string_list( list );
+}
+
+NactActionProfile*
+nact_action_get_profile( const NactAction *action, const gchar *profile_name )
+{
+	g_assert( NACT_IS_ACTION( action ));
+	g_assert( profile_name && strlen( profile_name ));
+
+	GSList *item;
+	NactActionProfile *profile;
+	NactActionProfile *found = NULL;
+	gchar *name;
+
+	for( item = action->private->profiles ; item != NULL && found == NULL ; item = item->next ){
+		profile = NACT_ACTION_PROFILE( item->data );
+		g_object_get( G_OBJECT( profile ), "name", &name, NULL );
+		if( !g_strcmp0( name, profile_name )){
+			found = profile;
+		}
+		g_free( name );
+	}
+	return( found );
+}
diff --git a/src/common/nact-action.h b/src/common/nact-action.h
new file mode 100644
index 0000000..4e54bb9
--- /dev/null
+++ b/src/common/nact-action.h
@@ -0,0 +1,90 @@
+/*
+ * 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_ACTION_H__
+#define __NACT_ACTION_H__
+
+/*
+ * NactAction class definition.
+ *
+ * This is the class which maintains an action.
+ *
+ * Note that an action is globally identified by its uuid.
+ *
+ * NactAction class is derived from NactStorage which takes care of i/o.
+ */
+
+#include "nact-storage.h"
+#include "nact-action-profile.h"
+
+G_BEGIN_DECLS
+
+#define NACT_ACTION_TYPE				( nact_action_get_type())
+#define NACT_ACTION( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_ACTION_TYPE, NactAction ))
+#define NACT_ACTION_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_ACTION_TYPE, NactActionClass ))
+#define NACT_IS_ACTION( object )		( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_ACTION_TYPE ))
+#define NACT_IS_ACTION_CLASS( klass )	( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_ACTION_TYPE ))
+#define NACT_ACTION_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_ACTION_TYPE, NactActionClass ))
+
+typedef struct NactActionPrivate NactActionPrivate;
+
+typedef struct {
+	NactStorage        parent;
+	NactActionPrivate *private;
+}
+	NactAction;
+
+typedef struct NactActionClassPrivate NactActionClassPrivate;
+
+typedef struct {
+	NactStorageClass        parent;
+	NactActionClassPrivate *private;
+}
+	NactActionClass;
+
+GType   nact_action_get_type( void );
+
+GSList *nact_action_load_actions( void );
+
+gchar  *nact_action_get_uuid( const NactAction *action );
+gchar  *nact_action_get_label( const NactAction *action );
+gchar  *nact_action_get_tooltip( const NactAction *action );
+gchar  *nact_action_get_verified_icon_name( const NactAction *action );
+
+GSList *nact_action_get_profiles( const NactAction *action );
+guint   nact_action_get_profiles_count( const NactAction *action );
+GSList *nact_action_get_profile_ids( const NactAction *action );
+void    nact_action_free_profile_ids( GSList *list );
+
+NactActionProfile *nact_action_get_profile( const NactAction *action, const gchar *name );
+
+G_END_DECLS
+
+#endif /* __NACT_ACTION_H__ */
diff --git a/src/common/nact-gconf.c b/src/common/nact-gconf.c
index d56f469..5d4471e 100644
--- a/src/common/nact-gconf.c
+++ b/src/common/nact-gconf.c
@@ -36,6 +36,7 @@
 #include <string.h>
 #include "nact-gconf.h"
 #include "nact-gconf-keys.h"
+#include "uti-lists.h"
 
 static GConfClient *st_gconf = NULL;
 
@@ -43,7 +44,6 @@ static void     initialize( void );
 static gchar   *get_object_path( NactStorage *object );
 static gchar   *path_to_key( const gchar *path );
 static GSList  *load_subdirs( const gchar *path );
-static void     free_subdirs( GSList *list );
 static GSList  *load_keys_values( const gchar *path );
 static void     free_keys_values( GSList *list );
 static GSList  *duplicate_list( GSList *list );
@@ -116,7 +116,7 @@ load_subdirs( const gchar *path )
 		list_keys = g_slist_prepend( list_keys, key );
 	}
 
-	free_subdirs( list_path );
+	nactuti_free_string_list( list_path );
 
 	return( list_keys );
 }
@@ -136,20 +136,6 @@ nact_gconf_load_uuids( void )
 	return( load_subdirs( NACT_GCONF_CONFIG ));
 }
 
-static void
-free_subdirs( GSList *list )
-{
-	static const gchar *thisfn = "nact_gconf_free_subdirs";
-	g_debug( "%s: list=%p", thisfn, list );
-
-	GSList *key;
-	for( key = list ; key != NULL ; key = key->next ){
-		g_free(( gchar * ) key->data );
-	}
-
-	g_slist_free( list );
-}
-
 /**
  * Free a previously allocated list of UUIDs.
  *
@@ -160,8 +146,7 @@ nact_gconf_free_uuids( GSList *list )
 {
 	static const gchar *thisfn = "nact_gconf_free_uuids";
 	g_debug( "%s: list=%p", thisfn, list );
-
-	free_subdirs( list );
+	nactuti_free_string_list( list );
 }
 
 /*
@@ -340,4 +325,5 @@ nact_gconf_load_profile_properties( NactStorage *profile )
 void
 nact_gconf_free_profile_names( GSList *list )
 {
+	nactuti_free_string_list( list );
 }
diff --git a/src/common/nact-storage.c b/src/common/nact-storage.c
index 218bab8..b53d667 100644
--- a/src/common/nact-storage.c
+++ b/src/common/nact-storage.c
@@ -93,14 +93,14 @@ class_init( NactStorageClass *klass )
 	static const gchar *thisfn = "nact_storage_class_init";
 	g_debug( "%s: klass=%p", thisfn, klass );
 
+	st_parent_class = g_type_class_peek_parent( klass );
+
 	GObjectClass *object_class = G_OBJECT_CLASS( klass );
 	object_class->dispose = instance_dispose;
 	object_class->finalize = instance_finalize;
 	object_class->set_property = instance_set_property;
 	object_class->get_property = instance_get_property;
 
-	st_parent_class = g_type_class_peek_parent( klass );
-
 	GParamSpec *spec;
 	spec = g_param_spec_int(
 			"origin",
diff --git a/src/plugin/nautilus-actions.c b/src/plugin/nautilus-actions.c
index 9f383c2..991e305 100644
--- a/src/plugin/nautilus-actions.c
+++ b/src/plugin/nautilus-actions.c
@@ -114,12 +114,12 @@ class_init( NautilusActionsClass *klass )
 	static const gchar *thisfn = "nautilus_actions_class_init";
 	g_debug( "%s: klass=%p", thisfn, klass );
 
+	st_parent_class = g_type_class_peek_parent( klass );
+
 	GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
 	gobject_class->dispose = instance_dispose;
 	gobject_class->finalize = instance_finalize;
 
-	st_parent_class = g_type_class_peek_parent( klass );
-
 	klass->private = g_new0( NautilusActionsClassPrivate, 1 );
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]