[nautilus-actions] Read .desktop files



commit 1a4a623e1e75e7eaea041af94e87bac0b6af1b3d
Author: Pierre Wieser <pwieser trychlos org>
Date:   Sun Jan 31 18:39:48 2010 +0100

    Read .desktop files

 ChangeLog                                          |    8 +
 TODO                                               |   34 ++-
 .../io-provider-desktop/nadp-desktop-file.c        |  523 +++++++++++++++++++-
 .../io-provider-desktop/nadp-desktop-file.h        |   29 +-
 nautilus-actions/io-provider-desktop/nadp-read.c   |  239 ++++++++-
 nautilus-actions/io-provider-desktop/nadp-utils.c  |   61 ++-
 nautilus-actions/io-provider-desktop/nadp-utils.h  |    3 +
 nautilus-actions/io-provider-gconf/nagp-read.c     |    3 +-
 8 files changed, 844 insertions(+), 56 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0ac2d76..d0758c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2009-01-31 Pierre Wieser <pwieser trychlos org>
 
+	* nautilus-actions/io-provider-desktop/nadp-desktop-file.c:
+	* nautilus-actions/io-provider-desktop/nadp-desktop-file.h:
+	* nautilus-actions/io-provider-desktop/nadp-read.c:
+	* nautilus-actions/io-provider-desktop/nadp-utils.c:
+	* nautilus-actions/io-provider-desktop/nadp-utils.h:
+	* nautilus-actions/io-provider-gconf/nagp-read.c:
+	Implements reading of .desktop files.
+
 	* nautilus-actions/io-provider-gconf/nagp-write.c (write_item_action):
 	Always writes the 'OBJECT_ITEM_TOOLBAR_LABEL_ENTRY' key.
 
diff --git a/TODO b/TODO
index e279fe4..1813420 100644
--- a/TODO
+++ b/TODO
@@ -92,8 +92,10 @@
 
 - DBus service: import/export an action or a menu
 
-- reunion of TargetSelection and TargetFolder
+- replace na_object_action_set/get_target_selection/background by target_context
+  reunion of TargetSelection and TargetFolder
   as TargetFolder is just a special case of TargetSelection
+  !! This suppose that we implement the SelectionCount condition
   > add special case 'x-nautilus-desktop:///' as a special folder
   > remove GConf entry
   > remove importing
@@ -125,3 +127,33 @@
   the 'editable' cell property should be set only once, instead of at each redraw
   and more because we also compute this on selection change
   what we should do: compute once, and monitor to only change when needed
+
+- Implement:
+	Description
+	SuggestedShortcut
+	GetItemsList
+	Path
+	ExecutionMode
+	StartupNotify
+	StartupWMClass
+	ExecuteAs
+	ForEach
+	OnlyShowIn
+	NotShowIn
+	Hidden
+	TryExec
+	ShowIfRegistered
+	ShowIfTrue
+	ShowIfRunning
+	SelectionCount
+	Capabilities
+
+- Review:
+	Mimetypes
+	Basenames
+	Schemes
+
+- when appending a profile found but not listed, it should be marked as invalid
+  to be editable in NACT, but not used in runtime plugin
+
+- profile path and parameters should be set together as only one variable
diff --git a/nautilus-actions/io-provider-desktop/nadp-desktop-file.c b/nautilus-actions/io-provider-desktop/nadp-desktop-file.c
index 25bbdef..22ff6ad 100644
--- a/nautilus-actions/io-provider-desktop/nadp-desktop-file.c
+++ b/nautilus-actions/io-provider-desktop/nadp-desktop-file.c
@@ -53,6 +53,18 @@ struct NadpDesktopFilePrivate {
 	GKeyFile  *key_file;
 };
 
+#define NADP_KEY_TOOLTIP				"Tooltip"
+#define NADP_KEY_ITEMS_LIST				"ItemsList"
+#define NADP_KEY_TARGET_CONTEXT			"TargetContext"
+#define NADP_KEY_TARGET_TOOLBAR			"TargetToolbar"
+#define NADP_KEY_TOOLBAR_LABEL			"ToolbarLabel"
+#define NADP_KEY_PROFILES				"Profiles"
+#define NADP_KEY_PROFILE_GROUP			"X-Action-Profile"
+#define NADP_KEY_BASENAMES				"Basenames"
+#define NADP_KEY_MIMETYPES				"Mimetypes"
+#define NADP_KEY_SCHEMES				"Schemes"
+#define NADP_KEY_FOLDERS				"Folders"
+
 static GObjectClass *st_parent_class = NULL;
 
 static GType            register_type( void );
@@ -63,6 +75,13 @@ static void             instance_finalize( GObject *object );
 
 static NadpDesktopFile *ndf_new( const gchar *path );
 static gboolean         check_key_file( NadpDesktopFile *ndf );
+#if 0
+static gboolean         ndf_has_entry( const NadpDesktopFile *ndf, const gchar *group, const gchar *entry );
+#endif
+static gboolean         ndf_read_bool( const NadpDesktopFile *ndf, const gchar *group, const gchar *entry, gboolean default_value );
+static gchar           *ndf_read_profile_string( const NadpDesktopFile *ndf, const gchar *profile_id, const gchar *entry );
+static GSList          *ndf_read_profile_string_list( const NadpDesktopFile *ndf, const gchar *profile_id, const gchar *entry );
+static gchar           *group_name_to_profile_id( const gchar *group_name );
 
 GType
 nadp_desktop_file_get_type( void )
@@ -328,6 +347,32 @@ nadp_desktop_file_get_key_file_path( const NadpDesktopFile *ndf )
 }
 
 /**
+ * nadp_desktop_file_get_file_type:
+ * @ndf: the #NadpDesktopFile instance.
+ *
+ * Returns: the value for the Type entry.
+ */
+gchar *
+nadp_desktop_file_get_file_type( const NadpDesktopFile *ndf )
+{
+	gchar *type;
+
+	type = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), type );
+
+	if( !ndf->private->dispose_has_run ){
+		type = g_key_file_get_locale_string(
+				ndf->private->key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_TYPE, NULL, NULL );
+
+		if( !type ){
+			type = g_strdup( "Action" );
+		}
+	}
+
+	return( type );
+}
+
+/**
  * nadp_desktop_file_get_id:
  * @ndf: the #NadpDesktopFile instance.
  *
@@ -350,14 +395,14 @@ nadp_desktop_file_get_id( const NadpDesktopFile *ndf )
 }
 
 /**
- * nadp_desktop_file_get_label:
+ * nadp_desktop_file_get_name:
  * @ndf: the #NadpDesktopFile instance.
  *
  * Returns: the label of the action, as a newly allocated string which
  * should be g_free() by the caller.
  */
 gchar *
-nadp_desktop_file_get_label( const NadpDesktopFile *ndf )
+nadp_desktop_file_get_name( const NadpDesktopFile *ndf )
 {
 	gchar *label;
 
@@ -393,7 +438,7 @@ nadp_desktop_file_get_tooltip( const NadpDesktopFile *ndf )
 
 	if( !ndf->private->dispose_has_run ){
 		tooltip = g_key_file_get_locale_string(
-				ndf->private->key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, NULL, NULL );
+				ndf->private->key_file, G_KEY_FILE_DESKTOP_GROUP, NADP_KEY_TOOLTIP, NULL, NULL );
 
 		if( !tooltip ){
 			tooltip = g_strdup( "" );
@@ -448,15 +493,475 @@ nadp_desktop_file_get_enabled( const NadpDesktopFile *ndf )
 
 	if( !ndf->private->dispose_has_run ){
 
-		if( g_key_file_has_key(
-				ndf->private->key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, NULL )){
+		enabled = !ndf_read_bool( ndf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, FALSE );
+	}
+
+	return( enabled );
+}
 
-			enabled = !g_key_file_get_boolean(
-				ndf->private->key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, NULL );
+/**
+ * nadp_desktop_file_get_items_list:
+ * @ndf: the #NadpDesktopFile instance.
+ *
+ * Returns: The string list value associated to the ItemsList entry.
+ * Returns: %NULL if the entry is not found or empty.
+ */
+GSList *
+nadp_desktop_file_get_items_list( const NadpDesktopFile *ndf )
+{
+	GSList *list;
+	gchar **string_list;
+	gsize count;
+
+	list = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), NULL );
+
+	if( !ndf->private->dispose_has_run ){
+
+		string_list = g_key_file_get_string_list(
+				ndf->private->key_file, G_KEY_FILE_DESKTOP_GROUP, NADP_KEY_ITEMS_LIST, &count, NULL );
+
+		if( string_list ){
+			list = nadp_utils_to_slist(( const gchar ** ) string_list );
+			g_strfreev( string_list );
 		}
 	}
 
-	return( enabled );
+	return( list );
+}
+
+/**
+ * nadp_desktop_file_get_target_context:
+ * @ndf: the #NadpDesktopFile instance.
+ *
+ * Returns: %TRUE if the action targets the context menu, %FALSE else.
+ *
+ * Defaults to TRUE if the key is not specified.
+ */
+gboolean
+nadp_desktop_file_get_target_context( const NadpDesktopFile *ndf )
+{
+	gboolean target_context;
+
+	target_context = TRUE;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), target_context );
+
+	if( !ndf->private->dispose_has_run ){
+
+		target_context = ndf_read_bool( ndf, G_KEY_FILE_DESKTOP_GROUP, NADP_KEY_TARGET_CONTEXT, TRUE );
+	}
+
+	return( target_context );
+}
+
+/**
+ * nadp_desktop_file_get_target_toolbar:
+ * @ndf: the #NadpDesktopFile instance.
+ *
+ * Returns: %TRUE if the action is target_toolbar, %FALSE else.
+ *
+ * Defaults to TRUE if the key is not specified.
+ */
+gboolean
+nadp_desktop_file_get_target_toolbar( const NadpDesktopFile *ndf )
+{
+	gboolean target_toolbar;
+
+	target_toolbar = TRUE;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), target_toolbar );
+
+	if( !ndf->private->dispose_has_run ){
+
+		target_toolbar = ndf_read_bool( ndf, G_KEY_FILE_DESKTOP_GROUP, NADP_KEY_TARGET_TOOLBAR, FALSE );
+	}
+
+	return( target_toolbar );
+}
+
+/**
+ * nadp_desktop_file_get_toolbar_label:
+ * @ndf: the #NadpDesktopFile instance.
+ *
+ * Returns: the label of the action in the toolbar, as a newly allocated
+ * string which should be g_free() by the caller.
+ */
+gchar *
+nadp_desktop_file_get_toolbar_label( const NadpDesktopFile *ndf )
+{
+	gchar *label;
+
+	label = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), label );
+
+	if( !ndf->private->dispose_has_run ){
+
+		label = g_key_file_get_locale_string(
+				ndf->private->key_file, G_KEY_FILE_DESKTOP_GROUP, NADP_KEY_TOOLBAR_LABEL, NULL, NULL );
+	}
+
+	return( label );
+}
+
+/**
+ * nadp_desktop_file_get_profiles_list:
+ * @ndf: the #NadpDesktopFile instance.
+ *
+ * Returns: The string list value associated to the Profiles entry.
+ * Returns: %NULL if the entry is not found or empty.
+ */
+GSList *
+nadp_desktop_file_get_profiles_list( const NadpDesktopFile *ndf )
+{
+	GSList *list;
+	gchar **string_list;
+	gsize count;
+
+	list = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), NULL );
+
+	if( !ndf->private->dispose_has_run ){
+
+		string_list = g_key_file_get_string_list(
+				ndf->private->key_file, G_KEY_FILE_DESKTOP_GROUP, NADP_KEY_PROFILES, &count, NULL );
+
+		if( string_list ){
+			list = nadp_utils_to_slist(( const gchar ** ) string_list );
+			g_strfreev( string_list );
+		}
+	}
+
+	return( list );
+}
+
+/**
+ * nadp_desktop_file_get_profile_group_list:
+ * @ndf: the #NadpDesktopFile instance.
+ *
+ * Returns: The list of profile names extracted from the list of groups.
+ * A profile group is identified by its name beggining with X-Action-Profile.
+ */
+GSList *
+nadp_desktop_file_get_profile_group_list( const NadpDesktopFile *ndf )
+{
+	GSList *groups, *strlist, *is;
+	gchar **string_list;
+	gchar *profile_id;
+
+	groups = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), NULL );
+
+	if( !ndf->private->dispose_has_run ){
+
+		string_list = g_key_file_get_groups( ndf->private->key_file, NULL );
+		if( string_list ){
+
+			strlist = nadp_utils_to_slist(( const gchar ** ) string_list );
+			g_strfreev( string_list );
+
+			for( is = strlist ; is ; is = is->next ){
+
+				profile_id = group_name_to_profile_id(( const gchar * ) is->data );
+				if( profile_id && strlen( profile_id )){
+
+					groups = g_slist_prepend( groups, g_strdup( profile_id ));
+				}
+
+				g_free( profile_id );
+			}
+
+			groups = g_slist_reverse( groups );
+			nadp_utils_gslist_free( strlist );
+		}
+	}
+
+	return( groups );
+}
+
+/**
+ * nadp_desktop_file_get_profile_name:
+ * @ndf: the #NadpDesktopFile instance.
+ * @profile_id: the id of the profile to be read.
+ *
+ * Returns: The name of the profile, as a newly allocated string which
+ * should be g_free() by the caller.
+ */
+gchar *
+nadp_desktop_file_get_profile_name( const NadpDesktopFile *ndf, const gchar *profile_id )
+{
+	gchar *name;
+
+	name = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), NULL );
+
+	if( !ndf->private->dispose_has_run ){
+
+		name = ndf_read_profile_string( ndf, profile_id, G_KEY_FILE_DESKTOP_KEY_NAME );
+		if( !name ){
+			name = g_strdup( "" );
+		}
+	}
+
+	return( name );
+}
+
+/**
+ * nadp_desktop_file_get_profile_exec:
+ * @ndf: the #NadpDesktopFile instance.
+ * @profile_id: the id of the profile to be read.
+ *
+ * Returns: The command to be executed, as a newly allocated string which
+ * should be g_free() by the caller.
+ */
+gchar *
+nadp_desktop_file_get_profile_exec( const NadpDesktopFile *ndf, const gchar *profile_id )
+{
+	gchar *command;
+
+	command = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), NULL );
+
+	if( !ndf->private->dispose_has_run ){
+
+		command = ndf_read_profile_string( ndf, profile_id, G_KEY_FILE_DESKTOP_KEY_EXEC );
+		if( !command ){
+
+			command = g_strdup( "" );
+		}
+	}
+
+	return( command );
+}
+
+/**
+ * nadp_desktop_file_get_basenames:
+ * @ndf: the #NadpDesktopFile instance.
+ * @profile_id: the id of the profile to be read.
+ *
+ * Returns: The list of basenames.
+ */
+GSList *
+nadp_desktop_file_get_basenames( const NadpDesktopFile *ndf, const gchar *profile_id )
+{
+	GSList *strlist;
+
+	strlist = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), NULL );
+
+	if( !ndf->private->dispose_has_run ){
+
+		strlist = ndf_read_profile_string_list( ndf, profile_id, NADP_KEY_BASENAMES );
+		if( !strlist ){
+			strlist = g_slist_append( NULL, g_strdup( "*" ));
+		}
+	}
+
+	return( strlist );
+}
+
+/**
+ * nadp_desktop_file_get_matchcase:
+ * @ndf: the #NadpDesktopFile instance.
+ *
+ * Returns: %TRUE if the basenames are case sensitive, %FALSE else.
+ *
+ * Defaults to TRUE if the key is not specified.
+ */
+gboolean
+nadp_desktop_file_get_matchcase( const NadpDesktopFile *ndf, const gchar *profile_id )
+{
+	gboolean matchcase;
+
+	matchcase = TRUE;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), matchcase );
+
+	if( !ndf->private->dispose_has_run ){
+
+		matchcase = ndf_read_bool( ndf, G_KEY_FILE_DESKTOP_GROUP, NADP_KEY_TARGET_TOOLBAR, TRUE );
+	}
+
+	return( matchcase );
+}
+
+/**
+ * nadp_desktop_file_get_mimetypes:
+ * @ndf: the #NadpDesktopFile instance.
+ * @profile_id: the id of the profile to be read.
+ *
+ * Returns: The list of mimetypes.
+ */
+GSList *
+nadp_desktop_file_get_mimetypes( const NadpDesktopFile *ndf, const gchar *profile_id )
+{
+	GSList *strlist;
+
+	strlist = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), NULL );
+
+	if( !ndf->private->dispose_has_run ){
+
+		strlist = ndf_read_profile_string_list( ndf, profile_id, NADP_KEY_MIMETYPES );
+		if( !strlist ){
+			strlist = g_slist_append( NULL, g_strdup( "*" ));
+		}
+	}
+
+	return( strlist );
+}
+
+/**
+ * nadp_desktop_file_get_schemes:
+ * @ndf: the #NadpDesktopFile instance.
+ * @profile_id: the id of the profile to be read.
+ *
+ * Returns: The list of schemes.
+ */
+GSList *
+nadp_desktop_file_get_schemes( const NadpDesktopFile *ndf, const gchar *profile_id )
+{
+	GSList *strlist;
+
+	strlist = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), NULL );
+
+	if( !ndf->private->dispose_has_run ){
+
+		strlist = ndf_read_profile_string_list( ndf, profile_id, NADP_KEY_SCHEMES );
+		if( !strlist ){
+			strlist = g_slist_append( NULL, g_strdup( "*" ));
+		}
+	}
+
+	return( strlist );
+}
+
+/**
+ * nadp_desktop_file_get_folders:
+ * @ndf: the #NadpDesktopFile instance.
+ * @profile_id: the id of the profile to be read.
+ *
+ * Returns: The list of folders.
+ */
+GSList *
+nadp_desktop_file_get_folders( const NadpDesktopFile *ndf, const gchar *profile_id )
+{
+	GSList *strlist;
+
+	strlist = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), NULL );
+
+	if( !ndf->private->dispose_has_run ){
+
+		strlist = ndf_read_profile_string_list( ndf, profile_id, NADP_KEY_FOLDERS );
+		if( !strlist ){
+			strlist = g_slist_append( NULL, g_strdup( "/" ));
+		}
+	}
+
+	return( strlist );
+}
+
+#if 0
+static gboolean
+ndf_has_entry( const NadpDesktopFile *ndf, const gchar *group, const gchar *entry )
+{
+	gboolean has_entry;
+
+	has_entry = FALSE;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), FALSE );
+
+	if( !ndf->private->dispose_has_run ){
+
+		has_entry = g_key_file_has_key( ndf->private->key_file, group, entry, NULL );
+	}
+
+	return( has_entry );
+}
+#endif
+
+static gboolean
+ndf_read_bool( const NadpDesktopFile *ndf, const gchar *group, const gchar *entry, gboolean default_value )
+{
+	gboolean value;
+	gboolean has_entry;
+
+	value = default_value;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), value );
+
+	if( !ndf->private->dispose_has_run ){
+
+		has_entry = g_key_file_has_key( ndf->private->key_file, group, entry, NULL );
+		if( has_entry ){
+			value = g_key_file_get_boolean(
+				ndf->private->key_file, group, entry, NULL );
+		}
+	}
+
+	return( value );
+}
+
+static gchar *
+ndf_read_profile_string( const NadpDesktopFile *ndf, const gchar *profile_id, const gchar *entry )
+{
+	gchar *string;
+	gchar *group_name;
+
+	group_name = g_strdup_printf( "%s %s", NADP_KEY_PROFILE_GROUP, profile_id );
+
+	string = g_key_file_get_locale_string( ndf->private->key_file, group_name, entry, NULL, NULL );
+
+	g_free( group_name );
+
+	return( string );
+}
+
+static GSList *
+ndf_read_profile_string_list( const NadpDesktopFile *ndf, const gchar *profile_id, const gchar *entry )
+{
+	GSList *strlist;
+	gchar **string_list;
+	gchar *group_name;
+
+	strlist = NULL;
+	group_name = g_strdup_printf( "%s %s", NADP_KEY_PROFILE_GROUP, profile_id );
+
+	string_list = g_key_file_get_string_list( ndf->private->key_file, group_name, entry, NULL, NULL );
+	if( string_list ){
+		strlist = nadp_utils_to_slist(( const gchar ** ) string_list );
+		g_strfreev( string_list );
+	}
+
+	g_free( group_name );
+
+	return( strlist );
+}
+
+static gchar *
+group_name_to_profile_id( const gchar *group_name )
+{
+	gchar *profile_id;
+
+	profile_id = NULL;
+
+	if( g_str_has_prefix( group_name, NADP_KEY_PROFILE_GROUP )){
+
+		gchar **tokens, **iter;
+		gchar *tmp;
+		gchar *source = g_strdup( group_name );
+
+		tmp = g_strstrip( source );
+		if( tmp && g_utf8_strlen( tmp, -1 )){
+
+			tokens = g_strsplit_set( tmp, " ", -1 );
+			iter = tokens;
+			++iter;
+			profile_id = g_strdup( g_strstrip( *iter ));
+			g_strfreev( tokens );
+		}
+
+		g_free( source );
+	}
+
+	return( profile_id );
 }
 
 /**
@@ -499,7 +1004,7 @@ nadp_desktop_file_set_tooltip( NadpDesktopFile *ndf, const gchar *tooltip )
 
 		locales = ( char ** ) g_get_language_names();
 		g_key_file_set_locale_string(
-				ndf->private->key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, locales[0], tooltip );
+				ndf->private->key_file, G_KEY_FILE_DESKTOP_GROUP, NADP_KEY_TOOLTIP, locales[0], tooltip );
 	}
 }
 
diff --git a/nautilus-actions/io-provider-desktop/nadp-desktop-file.h b/nautilus-actions/io-provider-desktop/nadp-desktop-file.h
index ec1d36b..07d6b83 100644
--- a/nautilus-actions/io-provider-desktop/nadp-desktop-file.h
+++ b/nautilus-actions/io-provider-desktop/nadp-desktop-file.h
@@ -74,13 +74,28 @@ GType            nadp_desktop_file_get_type( void );
 NadpDesktopFile *nadp_desktop_file_new_for_write( const gchar *path );
 NadpDesktopFile *nadp_desktop_file_new_from_path( const gchar *path );
 
-gchar           *nadp_desktop_file_get_key_file_path( const NadpDesktopFile *ndf );
-
-gchar           *nadp_desktop_file_get_id( const NadpDesktopFile *ndf );
-gchar           *nadp_desktop_file_get_label( const NadpDesktopFile *ndf );
-gchar           *nadp_desktop_file_get_tooltip( const NadpDesktopFile *ndf );
-gchar           *nadp_desktop_file_get_icon( const NadpDesktopFile *ndf );
-gboolean         nadp_desktop_file_get_enabled( const NadpDesktopFile *ndf );
+gchar           *nadp_desktop_file_get_key_file_path     ( const NadpDesktopFile *ndf );
+
+gchar           *nadp_desktop_file_get_file_type         ( const NadpDesktopFile *ndf );
+gchar           *nadp_desktop_file_get_id                ( const NadpDesktopFile *ndf );
+gchar           *nadp_desktop_file_get_name              ( const NadpDesktopFile *ndf );
+gchar           *nadp_desktop_file_get_tooltip           ( const NadpDesktopFile *ndf );
+gchar           *nadp_desktop_file_get_icon              ( const NadpDesktopFile *ndf );
+gboolean         nadp_desktop_file_get_enabled           ( const NadpDesktopFile *ndf );
+GSList          *nadp_desktop_file_get_items_list        ( const NadpDesktopFile *ndf );
+gboolean         nadp_desktop_file_get_target_context    ( const NadpDesktopFile *ndf );
+gboolean         nadp_desktop_file_get_target_toolbar    ( const NadpDesktopFile *ndf );
+gchar           *nadp_desktop_file_get_toolbar_label     ( const NadpDesktopFile *ndf );
+GSList          *nadp_desktop_file_get_profiles_list     ( const NadpDesktopFile *ndf );
+GSList          *nadp_desktop_file_get_profile_group_list( const NadpDesktopFile *ndf );
+
+gchar           *nadp_desktop_file_get_profile_name      ( const NadpDesktopFile *ndf, const gchar *profile_id );
+gchar           *nadp_desktop_file_get_profile_exec      ( const NadpDesktopFile *ndf, const gchar *profile_id );
+GSList          *nadp_desktop_file_get_basenames         ( const NadpDesktopFile *ndf, const gchar *profile_id );
+gboolean         nadp_desktop_file_get_matchcase         ( const NadpDesktopFile *ndf, const gchar *profile_id );
+GSList          *nadp_desktop_file_get_mimetypes         ( const NadpDesktopFile *ndf, const gchar *profile_id );
+GSList          *nadp_desktop_file_get_schemes           ( const NadpDesktopFile *ndf, const gchar *profile_id );
+GSList          *nadp_desktop_file_get_folders           ( const NadpDesktopFile *ndf, const gchar *profile_id );
 
 void             nadp_desktop_file_set_label( NadpDesktopFile *ndf, const gchar *label );
 void             nadp_desktop_file_set_tooltip( NadpDesktopFile *ndf, const gchar *tooltip );
diff --git a/nautilus-actions/io-provider-desktop/nadp-read.c b/nautilus-actions/io-provider-desktop/nadp-read.c
index 984e44c..c12bb91 100644
--- a/nautilus-actions/io-provider-desktop/nadp-read.c
+++ b/nautilus-actions/io-provider-desktop/nadp-read.c
@@ -32,6 +32,8 @@
 #include <config.h>
 #endif
 
+#include <string.h>
+
 #include <nautilus-actions/api/na-object-api.h>
 
 #include "nadp-desktop-file.h"
@@ -51,9 +53,12 @@ static GList          *get_list_of_desktop_paths( const NadpDesktopProvider *pro
 static void            get_list_of_desktop_files( const NadpDesktopProvider *provider, GList **files, const gchar *dir, GSList **messages );
 static gboolean        is_already_loaded( const NadpDesktopProvider *provider, GList *files, const gchar *desktop_id );
 static GList          *desktop_path_from_id( const NadpDesktopProvider *provider, GList *files, const gchar *dir, const gchar *id );
-static NAObjectAction *action_from_desktop_path( const NadpDesktopProvider *provider, DesktopPath *dps, GSList **messages );
-static void            read_action_properties( const NadpDesktopProvider *provider, NAObjectAction *action, NadpDesktopFile *ndf, GSList **messages );
-static void            read_item_properties( const NadpDesktopProvider *provider, NAObjectItem *item, NadpDesktopFile *ndf, GSList **messages );
+static NAObjectItem   *item_from_desktop_path( const NadpDesktopProvider *provider, DesktopPath *dps, GSList **messages );
+static void            read_menu_from_desktop_file( const NadpDesktopProvider *provider, NAObjectMenu *menu, NadpDesktopFile *ndf, GSList **messages );
+static void            read_action_from_desktop_file( const NadpDesktopProvider *provider, NAObjectAction *action, NadpDesktopFile *ndf, GSList **messages );
+static void            read_item_properties_from_ndf( const NadpDesktopProvider *provider, NAObjectItem *item, NadpDesktopFile *ndf, GSList **messages );
+static void            append_profile( NAObjectAction *action, NadpDesktopFile *ndf, const gchar *profile_id, GSList **messages );
+static void            exec_to_path_parameters( const gchar *command, gchar **path, gchar **parameters );
 static void            free_desktop_paths( GList *paths );
 
 /*
@@ -66,7 +71,7 @@ nadp_iio_provider_read_items( const NAIIOProvider *provider, GSList **messages )
 	GList *items;
 	GList *paths, *ip;
 	DesktopPath *dps;
-	NAObjectAction *action;
+	NAObjectItem *item;
 
 	g_debug( "%s: provider=%p, messages=%p", thisfn, ( void * ) provider, ( void * ) messages );
 
@@ -75,9 +80,9 @@ nadp_iio_provider_read_items( const NAIIOProvider *provider, GSList **messages )
 	paths = get_list_of_desktop_paths( NADP_DESKTOP_PROVIDER( provider ), messages );
 	for( ip = paths ; ip ; ip = ip->next ){
 		dps = ( DesktopPath * ) ip->data;
-		action = action_from_desktop_path( NADP_DESKTOP_PROVIDER( provider ), dps, messages );
-		if( action ){
-			items = g_list_prepend( items, action );
+		item = item_from_desktop_path( NADP_DESKTOP_PROVIDER( provider ), dps, messages );
+		if( item ){
+			items = g_list_prepend( items, item );
 		}
 	}
 
@@ -203,46 +208,119 @@ desktop_path_from_id( const NadpDesktopProvider *provider, GList *files, const g
 }
 
 /*
- * returns a newly allocated NAObjectAction object, initialized
- * from the .desktop file pointed to by DesktopPath struct
+ * Returns a newly allocated NAObjectItem object, initialized from the
+ * .desktop file pointed to by DesktopPath struct
+ * A menu is identified by the Type=Menu.
+ * If not found, we presume that the .desktop describes an action.
  */
-static NAObjectAction *
-action_from_desktop_path( const NadpDesktopProvider *provider, DesktopPath *dps, GSList **messages )
+static NAObjectItem *
+item_from_desktop_path( const NadpDesktopProvider *provider, DesktopPath *dps, GSList **messages )
 {
 	NadpDesktopFile *ndf;
-	NAObjectAction *action;
-	NAObjectProfile *profile;
+	NAObjectItem *item;
+	gchar *type;
 
 	ndf = nadp_desktop_file_new_from_path( dps->path );
 	if( !ndf ){
 		return( NULL );
 	}
 
-	action = na_object_action_new();
-	na_object_set_provider_data( action, ndf );
-	g_object_weak_ref( G_OBJECT( action ), ( GWeakNotify ) g_object_unref, ndf );
+	type = nadp_desktop_file_get_file_type( ndf );
+	if( !strcmp( type, "Menu" )){
+		item = NA_OBJECT_ITEM( na_object_menu_new());
+		read_menu_from_desktop_file( provider, NA_OBJECT_MENU( item ), ndf, messages );
 
-	read_action_properties( provider, action, ndf, messages );
-
-	/* have at least one profile */
-	if( !na_object_get_items_count( action )){
-		profile = na_object_profile_new();
-		na_object_action_attach_profile( action, profile );
+	} else if( !type || !strlen( type ) || !strcmp( type, "Action" )){
+		item = NA_OBJECT_ITEM( na_object_action_new());
+		read_action_from_desktop_file( provider, NA_OBJECT_ACTION( item ), ndf, messages );
 	}
 
-	return( action );
+	return( item );
+}
+
+static void
+read_menu_from_desktop_file( const NadpDesktopProvider *provider, NAObjectMenu *menu, NadpDesktopFile *ndf, GSList **messages )
+{
+	GSList *items_list;
+
+	read_item_properties_from_ndf( provider, NA_OBJECT_ITEM( menu ), ndf, messages );
+
+	items_list = nadp_desktop_file_get_items_list( ndf );
+	na_object_item_set_items_string_list( NA_OBJECT_ITEM( menu ), items_list );
+	nadp_utils_gslist_free( items_list );
 }
 
 static void
-read_action_properties( const NadpDesktopProvider *provider, NAObjectAction *action, NadpDesktopFile *ndf, GSList **messages )
+read_action_from_desktop_file( const NadpDesktopProvider *provider, NAObjectAction *action, NadpDesktopFile *ndf, GSList **messages )
 {
-	read_item_properties( provider, NA_OBJECT_ITEM( action ), ndf, messages );
+	gboolean target_context;
+	gboolean target_toolbar;
+	gchar *action_label;
+	gchar *toolbar_label;
+	gboolean same_label;
+	GSList *profiles_list, *ip;
+	GSList *group_list;
+	NAObjectProfile *profile;
+
+	read_item_properties_from_ndf( provider, NA_OBJECT_ITEM( action ), ndf, messages );
+
+	target_context = nadp_desktop_file_get_target_context( ndf );
+	na_object_action_set_target_selection( action, target_context );
+
+	target_toolbar = nadp_desktop_file_get_target_toolbar( ndf );
+	na_object_action_set_target_toolbar( action, target_toolbar );
+
+	action_label = na_object_get_label( action );
+	toolbar_label = nadp_desktop_file_get_toolbar_label( ndf );
+	same_label = FALSE;
+	if( !toolbar_label || !g_utf8_strlen( toolbar_label, -1 ) || !g_utf8_collate( toolbar_label, action_label )){
+		same_label = TRUE;
+		g_free( toolbar_label );
+		toolbar_label = g_strdup( action_label );
+	}
+	na_object_action_toolbar_set_label( action, toolbar_label );
+	na_object_action_toolbar_set_same_label( action, same_label );
+	g_free( toolbar_label );
+	g_free( action_label );
+
+	profiles_list = nadp_desktop_file_get_profiles_list( ndf );
+	na_object_item_set_items_string_list( NA_OBJECT_ITEM( action ), profiles_list );
+
+	/* trying to load all profiles found in .desktop files
+	 * starting with those correctly recorded in profiles_list
+	 * appending those not listed in the 'Profiles' entry
+	 */
+	group_list = nadp_desktop_file_get_profile_group_list( ndf );
+	if( group_list && g_slist_length( group_list )){
+
+		/* read profiles in the specified order
+		 */
+		for( ip = profiles_list ; ip ; ip = ip->next ){
+			append_profile( action, ndf, ( const gchar * ) ip->data, messages );
+			group_list = nadp_utils_gslist_remove_from( group_list, ( const gchar * ) ip->data );
+		}
+
+		/* append other profiles
+		 * but this may be an inconvenient for the runtime plugin ?
+		 */
+		for( ip = group_list ; ip ; ip = ip->next ){
+			append_profile( action, ndf, ( const gchar * ) ip->data, messages );
+		}
+	}
+	nadp_utils_gslist_free( group_list );
+	nadp_utils_gslist_free( profiles_list );
+
+	/* have at least one profile */
+	if( !na_object_get_items_count( action )){
+		profile = na_object_profile_new();
+		na_object_action_attach_profile( action, profile );
+	}
 }
 
 static void
-read_item_properties( const NadpDesktopProvider *provider, NAObjectItem *item, NadpDesktopFile *ndf, GSList **messages )
+read_item_properties_from_ndf( const NadpDesktopProvider *provider, NAObjectItem *item, NadpDesktopFile *ndf, GSList **messages )
 {
-	static const gchar *thisfn = "nadp_read_read_item_properties";
+	static const gchar *thisfn = "nadp_read_read_item_properties_from_ndf";
 	gchar *id;
 	gchar *label;
 	gchar *tooltip;
@@ -250,10 +328,13 @@ read_item_properties( const NadpDesktopProvider *provider, NAObjectItem *item, N
 	gboolean enabled;
 	gboolean writable;
 
+	na_object_set_provider_data( item, ndf );
+	g_object_weak_ref( G_OBJECT( item ), ( GWeakNotify ) g_object_unref, ndf );
+
 	id = nadp_desktop_file_get_id( ndf );
 	na_object_set_id( item, id );
 
-	label = nadp_desktop_file_get_label( ndf );
+	label = nadp_desktop_file_get_name( ndf );
 	if( !label || !g_utf8_strlen( label, -1 )){
 		g_warning( "%s: id=%s, label not found or empty", thisfn, id );
 		g_free( label );
@@ -270,6 +351,14 @@ read_item_properties( const NadpDesktopProvider *provider, NAObjectItem *item, N
 	na_object_set_icon( item, icon );
 	g_free( icon );
 
+	/*description = nadp_desktop_file_get_description( ndf );
+	na_object_set_description( item, description );
+	g_free( description );*/
+
+	/*shortcut = nadp_desktop_file_get_shortcut( ndf );
+	na_object_set_shortcut( item, shortcut );
+	g_free( shortcut );*/
+
 	enabled = nadp_desktop_file_get_enabled( ndf );
 	na_object_set_enabled( item, enabled );
 
@@ -280,6 +369,100 @@ read_item_properties( const NadpDesktopProvider *provider, NAObjectItem *item, N
 }
 
 static void
+append_profile( NAObjectAction *action, NadpDesktopFile *ndf, const gchar *profile_id, GSList **messages )
+{
+	NAObjectProfile *profile;
+	gchar *name;
+	gchar *exec, *path, *parameters;
+	GSList *basenames, *mimetypes, *schemes, *folders;
+	gboolean matchcase;
+	gboolean isfile, isdir;
+	gboolean multiple;
+
+	profile = na_object_profile_new();
+	na_object_set_id( profile, profile_id );
+
+	name = nadp_desktop_file_get_profile_name( ndf, profile_id );
+	na_object_set_label( profile, name );
+	g_free( name );
+
+	exec = nadp_desktop_file_get_profile_exec( ndf, profile_id );
+	exec_to_path_parameters( exec, &path, &parameters );
+	na_object_profile_set_path( profile, path );
+	na_object_profile_set_parameters( profile, parameters );
+	g_free( parameters );
+	g_free( path );
+	g_free( exec );
+
+	basenames = nadp_desktop_file_get_basenames( ndf, profile_id );
+	na_object_profile_set_basenames( profile, basenames );
+	nadp_utils_gslist_free( basenames );
+
+	matchcase = nadp_desktop_file_get_matchcase( ndf, profile_id );
+	na_object_profile_set_matchcase( profile, matchcase );
+
+	mimetypes = nadp_desktop_file_get_mimetypes( ndf, profile_id );
+	na_object_profile_set_mimetypes( profile, mimetypes );
+	nadp_utils_gslist_free( mimetypes );
+
+	schemes = nadp_desktop_file_get_schemes( ndf, profile_id );
+	na_object_profile_set_schemes( profile, schemes );
+	nadp_utils_gslist_free( schemes );
+
+	folders = nadp_desktop_file_get_folders( ndf, profile_id );
+	na_object_profile_set_folders( profile, folders );
+	nadp_utils_gslist_free( folders );
+
+	isfile = TRUE;
+	isdir = TRUE;
+	na_object_profile_set_isfiledir( profile, isfile, isdir );
+
+	multiple = TRUE;
+	na_object_profile_set_multiple( profile, multiple );
+
+	na_object_action_attach_profile( action, profile );
+}
+
+/*
+ * suppose here that command is only one word,
+ * also 'normalize' space characters (bad, but temporary!)
+ */
+static void
+exec_to_path_parameters( const gchar *command, gchar **path, gchar **parameters )
+{
+	gchar **tokens, **iter;
+	gchar *tmp;
+	gchar *source = g_strdup( command );
+	GString *string;
+
+	tmp = g_strstrip( source );
+	if( tmp && g_utf8_strlen( tmp, -1 )){
+
+		tokens = g_strsplit_set( tmp, " ", -1 );
+		*path = g_strdup( *tokens );
+
+		iter = tokens;
+		iter++;
+		string = g_string_new( "" );
+		while( *iter ){
+			if( !string->len ){
+				string = g_string_append( string, " " );
+			}
+			string = g_string_append( string, g_strstrip( *iter ));
+			iter++;
+		}
+		*parameters = g_string_free( string, FALSE );
+		g_strfreev( tokens );
+
+	} else {
+		*path = g_strdup( "" );
+		*parameters = g_strdup( "" );
+	}
+
+	g_free( source );
+}
+
+static void
 free_desktop_paths( GList *paths )
 {
 	GList *ip;
diff --git a/nautilus-actions/io-provider-desktop/nadp-utils.c b/nautilus-actions/io-provider-desktop/nadp-utils.c
index 96a2575..307978b 100644
--- a/nautilus-actions/io-provider-desktop/nadp-utils.c
+++ b/nautilus-actions/io-provider-desktop/nadp-utils.c
@@ -63,7 +63,7 @@ static GSList *
 text_to_string_list( const gchar *text, const gchar *separator, const gchar *default_value )
 {
 	GSList *strlist = NULL;
-	gchar **tokens, **iter;
+	gchar **tokens;
 	gchar *tmp;
 	gchar *source = g_strdup( text );
 
@@ -72,15 +72,8 @@ text_to_string_list( const gchar *text, const gchar *separator, const gchar *def
 		strlist = g_slist_append( strlist, g_strdup( default_value ));
 
 	} else {
-		tokens = g_strsplit( source, separator, -1 );
-		iter = tokens;
-
-		while( *iter ){
-			tmp = g_strstrip( *iter );
-			strlist = g_slist_append( strlist, g_strdup( tmp ));
-			iter++;
-		}
-
+		tokens = g_strsplit( tmp, separator, -1 );
+		strlist = nadp_utils_to_slist(( const gchar ** ) tokens );
 		g_strfreev( tokens );
 	}
 
@@ -89,6 +82,30 @@ text_to_string_list( const gchar *text, const gchar *separator, const gchar *def
 }
 
 /**
+ * nadp_utils_to_slist:
+ * @list: a gchar ** list of strings.
+ *
+ * Returns: a #GSList.
+ */
+GSList *
+nadp_utils_to_slist( const gchar **list )
+{
+	GSList *strlist = NULL;
+	gchar **iter;
+	gchar *tmp;
+
+	iter = ( gchar ** ) list;
+
+	while( *iter ){
+		tmp = g_strstrip( *iter );
+		strlist = g_slist_append( strlist, g_strdup( tmp ));
+		iter++;
+	}
+
+	return( strlist );
+}
+
+/**
  * nadp_utils_gslist_free:
  * @list: the GSList to be freed.
  *
@@ -102,6 +119,30 @@ nadp_utils_gslist_free( GSList *list )
 }
 
 /**
+ * nadp_utils_gslist_remove_from:
+ * @list: the #GSList from which remove the @string.
+ * @string: the string to be removed.
+ *
+ * Removes a @string from a string list, then frees the removed @string.
+ */
+GSList *
+nadp_utils_gslist_remove_from( GSList *list, const gchar *string )
+{
+	GSList *is;
+
+	for( is = list ; is ; is = is->next ){
+		const gchar *istr = ( const gchar * ) is->data;
+		if( !g_utf8_collate( string, istr )){
+			g_free( is->data );
+			list = g_slist_delete_link( list, is );
+			break;
+		}
+	}
+
+	return( list );
+}
+
+/**
  * nadp_utils_remove_suffix:
  * @string: source string.
  * @suffix: suffix to be removed from @string.
diff --git a/nautilus-actions/io-provider-desktop/nadp-utils.h b/nautilus-actions/io-provider-desktop/nadp-utils.h
index 8f87469..9cf8e11 100644
--- a/nautilus-actions/io-provider-desktop/nadp-utils.h
+++ b/nautilus-actions/io-provider-desktop/nadp-utils.h
@@ -35,7 +35,10 @@ G_BEGIN_DECLS
 
 GSList  *nadp_utils_split_path_list( const gchar *path_list );
 
+GSList  *nadp_utils_to_slist( const gchar **list );
+
 void     nadp_utils_gslist_free( GSList *list );
+GSList  *nadp_utils_gslist_remove_from( GSList *list, const gchar *string );
 
 gchar   *nadp_utils_remove_suffix( const gchar *string, const gchar *suffix );
 
diff --git a/nautilus-actions/io-provider-gconf/nagp-read.c b/nautilus-actions/io-provider-gconf/nagp-read.c
index 8496d91..0b683bc 100644
--- a/nautilus-actions/io-provider-gconf/nagp-read.c
+++ b/nautilus-actions/io-provider-gconf/nagp-read.c
@@ -194,7 +194,8 @@ read_item_action( NagpGConfProvider *provider, const gchar *path, NAObjectAction
 			g_free( profile_path );
 		}
 
-		/* read other profiles
+		/* append other profiles
+		 * but this may be an inconvenient for the runtime plugin ?
 		 */
 		for( ip = list_profiles ; ip ; ip = ip->next ){
 			profile_path = g_strdup(( gchar * ) ip->data );



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