[nautilus-actions] Run an action outside of Nautilus



commit d559d5005ee0a82923b2c3a23a8cde55c53be79d
Author: Pierre Wieser <pwieser trychlos org>
Date:   Sat Dec 12 10:39:54 2009 +0100

    Run an action outside of Nautilus
    
    The tracker plugin tracks Nautilus selection, and publish it via a DBus service.
    nautilus-actions-run is a DBus client which gets the current selection and
    applies an action on it.

 ChangeLog                                          |   40 +++
 TODO                                               |    7 +
 nautilus-actions/api/Makefile.am                   |    1 +
 nautilus-actions/api/na-dbus.h                     |   46 ++++
 nautilus-actions/nact/nact-clipboard.c             |    2 +-
 nautilus-actions/private/na-gnome-vfs-uri.c        |   19 +-
 nautilus-actions/private/na-gnome-vfs-uri.h        |    2 +-
 nautilus-actions/private/na-object-profile-class.h |    9 +
 nautilus-actions/private/na-object-profile-fn.h    |    2 +
 nautilus-actions/private/na-object-profile.c       |  260 ++++++++++++++++----
 nautilus-actions/test/test-parse-uris.c            |    3 +-
 nautilus-actions/tracker/.gitignore                |    1 +
 nautilus-actions/tracker/Makefile.am               |    8 +
 nautilus-actions/tracker/na-tracker-dbus.c         |   58 ++---
 nautilus-actions/tracker/na-tracker.c              |    2 +
 nautilus-actions/tracker/na-tracker.h              |    2 -
 nautilus-actions/utils/Makefile.am                 |    4 +
 nautilus-actions/utils/nautilus-actions-run.c      |  148 +++++++++---
 18 files changed, 486 insertions(+), 128 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 73a428e..6103342 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2009-12-12 Pierre Wieser <pwieser trychlos org>
+
+	* nautilus-actions/api/na-dbus.h: New file.
+
+	* nautilus-actions/api/Makefile.am: Updated accordingly.
+
+	* nautilus-actions/nact/nact-clipboard.c (nact_clipboard_dump):
+	Fix debug parameters to have pointer of correct size.
+
+	* nautilus-actions/private/na-gnome-vfs-uri.c:
+	* nautilus-actions/private/na-gnome-vfs-uri.h:
+	Rename uri field to path.
+
+	* nautilus-actions/private/na-object-profile-class.h:
+	Define NATrackedItem structure.
+
+	* nautilus-actions/private/na-object-profile-fn.h:
+	* nautilus-actions/private/na-object-profile.c
+	(na_object_profile_is_candidate_for_tracked,
+	na_object_profile_parse_parameters_for_tracked): New functions.
+
+	* nautilus-actions/test/test-parse-uris.c:
+	Add a new test case.
+
+	* nautilus-actions/tracker/Makefile.am:
+	* nautilus-actions/utils/Makefile.am:
+	Fix make distcheck.
+	Install XML service definition and cleanup built files.
+
+	* nautilus-actions/tracker/na-tracker-dbus.c:
+	Take a reference on NautilusFileInfo provided list.
+
+	* nautilus-actions/tracker/na-tracker.c:
+	* nautilus-actions/tracker/na-tracker.h:
+	Move DBus service name to api/na-dbus.h header.
+
+	* nautilus-actions/utils/nautilus-actions-run.c:
+	Remove '--parameters' and '--current' useless options.
+	Execute action on candidate profile.
+
 2009-12-10 Pierre Wieser <pwieser trychlos org>
 
 	* nautilus-actions/runtime/na-pivot.c:
diff --git a/TODO b/TODO
index 0de4d78..35a7f9c 100644
--- a/TODO
+++ b/TODO
@@ -102,3 +102,10 @@
 - lockdown: cut should be disabled
   inline edition should be disabled
   all entry fields should be readonly
+
+- naobjectprofile: object_are_equal, object_is_valid should be static
+
+- dbus send: do we should free the strings after their emission ?
+
+- when looking to see if an action is candidate, we only look at valid action, yes ?
+  but when searching for a profile, we also should check that the profile is valid
diff --git a/nautilus-actions/api/Makefile.am b/nautilus-actions/api/Makefile.am
index 90a0f85..4de385f 100644
--- a/nautilus-actions/api/Makefile.am
+++ b/nautilus-actions/api/Makefile.am
@@ -38,6 +38,7 @@ libna_api_includedir = $(pkgincludedir)/api
 
 libna_api_include_HEADERS = \
 	na-api.h											\
+	na-dbus.h											\
 	na-gconf-keys.h										\
 	na-gconf-monitor.h									\
 	na-iio-provider.h									\
diff --git a/nautilus-actions/api/na-dbus.h b/nautilus-actions/api/na-dbus.h
new file mode 100644
index 0000000..598ad65
--- /dev/null
+++ b/nautilus-actions/api/na-dbus.h
@@ -0,0 +1,46 @@
+/*
+ * 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 __NAUTILUS_ACTIONS_NA_DBUS_H__
+#define __NAUTILUS_ACTIONS_NA_DBUS_H__
+
+/**
+ * SECTION: na_dbus
+ * @short_description: Nautilus-Actions DBus description.
+ * @include: nautilus-actions/api/na-dbus.h
+ */
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_ACTIONS_DBUS_SERVICE	"org.nautilus-actions.DBus"
+
+G_END_DECLS
+
+#endif /* __NAUTILUS_ACTIONS_NA_DBUS_H__ */
diff --git a/nautilus-actions/nact/nact-clipboard.c b/nautilus-actions/nact/nact-clipboard.c
index dd16087..6669423 100644
--- a/nautilus-actions/nact/nact-clipboard.c
+++ b/nautilus-actions/nact/nact-clipboard.c
@@ -801,7 +801,7 @@ nact_clipboard_dump( NactClipboard *clipboard )
 			}
 		}
 
-		g_debug( "%s:  primary_got=%s", thisfn, ( void * ) clipboard->private->primary_got ? "True":"False" );
+		g_debug( "%s:  primary_got=%s", thisfn, clipboard->private->primary_got ? "True":"False" );
 	}
 }
 
diff --git a/nautilus-actions/private/na-gnome-vfs-uri.c b/nautilus-actions/private/na-gnome-vfs-uri.c
index ed2830a..183dcad 100644
--- a/nautilus-actions/private/na-gnome-vfs-uri.c
+++ b/nautilus-actions/private/na-gnome-vfs-uri.c
@@ -85,7 +85,7 @@ na_gnome_vfs_uri_parse( NAGnomeVFSURI *vfs, const gchar *text_uri )
 	const gchar *method_scanner;
 	gchar *extension_scanner;
 
-	vfs->uri = NULL;
+	vfs->path = NULL;
 	vfs->scheme = NULL;
 	vfs->host_name = NULL;
 	vfs->host_port = 0;
@@ -120,6 +120,7 @@ na_gnome_vfs_uri_parse( NAGnomeVFSURI *vfs, const gchar *text_uri )
 void
 na_gnome_vfs_uri_free( NAGnomeVFSURI *vfs )
 {
+	g_free( vfs->path );
 	g_free( vfs->scheme );
 	g_free( vfs->host_name );
 	g_free( vfs->user_name );
@@ -577,18 +578,18 @@ set_uri_element (NAGnomeVFSURI *vfs,
 	char *escaped_text;
 
 	if (text == NULL || len == 0) {
-		vfs->uri = g_strdup ("/");
+		vfs->path = g_strdup ("/");
 		return;
 	}
 
 	if ( text[0] == '/' && text[1] == '/') {
-		vfs->uri = split_toplevel_uri (text + 2, len - 2,
+		vfs->path = split_toplevel_uri (text + 2, len - 2,
 						&vfs->host_name,
 						&vfs->user_name,
 						&vfs->host_port,
 						&vfs->password);
 	} else {
-		vfs->uri = g_strndup (text, len);
+		vfs->path = g_strndup (text, len);
 	}
 
 	/* FIXME: this should be handled/supported by the specific method.
@@ -608,13 +609,13 @@ set_uri_element (NAGnomeVFSURI *vfs,
 	        || strcmp (vfs->scheme, "help") == 0
 		)) {
 
-		escaped_text = gnome_vfs_escape_set (vfs->uri, ";?&=+$,");
-		g_free (vfs->uri);
-		vfs->uri = escaped_text;
+		escaped_text = gnome_vfs_escape_set (vfs->path, ";?&=+$,");
+		g_free (vfs->path);
+		vfs->path = escaped_text;
 	}
 
-	gnome_vfs_remove_optional_escapes (vfs->uri);
-	gnome_vfs_canonicalize_pathname (vfs->uri);
+	gnome_vfs_remove_optional_escapes (vfs->path);
+	gnome_vfs_canonicalize_pathname (vfs->path);
 }
 
 /*
diff --git a/nautilus-actions/private/na-gnome-vfs-uri.h b/nautilus-actions/private/na-gnome-vfs-uri.h
index 864d640..a0b6210 100644
--- a/nautilus-actions/private/na-gnome-vfs-uri.h
+++ b/nautilus-actions/private/na-gnome-vfs-uri.h
@@ -62,7 +62,7 @@
 G_BEGIN_DECLS
 
 typedef struct {
-	gchar *uri;
+	gchar *path;
 	gchar *scheme;
 	gchar *host_name;
 	guint  host_port;
diff --git a/nautilus-actions/private/na-object-profile-class.h b/nautilus-actions/private/na-object-profile-class.h
index 4ead284..ebe38b8 100644
--- a/nautilus-actions/private/na-object-profile-class.h
+++ b/nautilus-actions/private/na-object-profile-class.h
@@ -72,6 +72,15 @@ typedef struct {
 
 GType na_object_profile_get_type( void );
 
+/* a structure used by the org.nautilus_actions.DBus service,
+ * in its Tracker.Status interface
+ */
+typedef struct {
+	gchar *uri;
+	gchar *mimetype;
+}
+	NATrackedItem;
+
 G_END_DECLS
 
 #endif /* __NAUTILUS_ACTIONS_NA_PRIVATE_OBJECT_PROFILE_CLASS_H__ */
diff --git a/nautilus-actions/private/na-object-profile-fn.h b/nautilus-actions/private/na-object-profile-fn.h
index ce32d51..c089a04 100644
--- a/nautilus-actions/private/na-object-profile-fn.h
+++ b/nautilus-actions/private/na-object-profile-fn.h
@@ -82,7 +82,9 @@ void             na_object_profile_set_folders( NAObjectProfile *profile, GSList
 void             na_object_profile_replace_folder_uri( NAObjectProfile *profile, const gchar *old, const gchar *new );
 
 gboolean         na_object_profile_is_candidate( const NAObjectProfile *profile, gint target, GList *files );
+gboolean         na_object_profile_is_candidate_for_tracked( const NAObjectProfile *profile, GList *tracked );
 gchar           *na_object_profile_parse_parameters( const NAObjectProfile *profile, gint target, GList *files );
+gchar           *na_object_profile_parse_parameters_for_tracked( const NAObjectProfile *profile, GList *tracked );
 
 G_END_DECLS
 
diff --git a/nautilus-actions/private/na-object-profile.c b/nautilus-actions/private/na-object-profile.c
index 38aec45..358f96e 100644
--- a/nautilus-actions/private/na-object-profile.c
+++ b/nautilus-actions/private/na-object-profile.c
@@ -89,8 +89,15 @@ static void      instance_finalize( GObject *object );
 static gboolean  is_target_background_candidate( const NAObjectProfile *profile, NautilusFileInfo *current_folder );
 static gboolean  is_target_toolbar_candidate( const NAObjectProfile *profile, NautilusFileInfo *current_folder );
 static gboolean  is_current_folder_inside( const NAObjectProfile *profile, NautilusFileInfo *current_folder );
-static gboolean  is_target_selection_candidate( const NAObjectProfile *profile, GList *files );
-static int       validate_schemes( GSList *schemes2test, NautilusFileInfo *file );
+static gboolean  is_target_selection_candidate( const NAObjectProfile *profile, GList *files, gboolean from_nautilus );
+static gboolean  tracked_is_directory( void *iter, gboolean from_nautilus );
+static gchar    *tracked_to_basename( void *iter, gboolean from_nautilus );
+static GFile    *tracked_to_location( void *iter, gboolean from_nautilus );
+static gchar    *tracked_to_scheme( void *iter, gboolean from_nautilus );
+static gchar    *tracked_to_mimetype( void *iter, gboolean from_nautilus );
+static gchar    *tracked_to_uri( void *iter, gboolean from_nautilus );
+static int       validate_schemes( GSList *schemes2test, void *iter, gboolean from_nautilus );
+static gchar    *parse_parameters( const NAObjectProfile *profile, gint target, GList* files, gboolean from_nautilus );
 
 static void      object_dump( const NAObject *profile );
 static void      object_dump_list( const gchar *thisfn, const gchar *label, GSList *list );
@@ -1035,7 +1042,7 @@ na_object_profile_is_candidate( const NAObjectProfile *profile, gint target, GLi
 
 		case ITEM_TARGET_SELECTION:
 		default:
-			is_candidate = is_target_selection_candidate( profile, files );
+			is_candidate = is_target_selection_candidate( profile, files, TRUE );
 	}
 
 	return( is_candidate );
@@ -1089,8 +1096,35 @@ is_current_folder_inside( const NAObjectProfile *profile, NautilusFileInfo *curr
 	return( is_inside );
 }
 
+/**
+ * na_object_profile_is_candidate_for_tracked:
+ * @profile: the #NAObjectProfile to be checked.
+ * @files: the currently selected items, as a list of uris.
+ *
+ * Determines if the given profile is candidate to be displayed in the
+ * Nautilus context menu, regarding the list of currently selected
+ * items.
+ *
+ * Returns: %TRUE if this profile succeeds to all tests and is so a
+ * valid candidate to be displayed in Nautilus context menu, %FALSE
+ * else.
+ *
+ * The case where we only have URIs for target files is when we have
+ * got this list through the org.nautilus_actions.DBus service (or
+ * another equivalent) - typically for use in a command-line tool.
+ */
+gboolean
+na_object_profile_is_candidate_for_tracked( const NAObjectProfile *profile, GList *tracked_items )
+{
+	gboolean is_candidate;
+
+	is_candidate = is_target_selection_candidate( profile, tracked_items, FALSE );
+
+	return( is_candidate );
+}
+
 static gboolean
-is_target_selection_candidate( const NAObjectProfile *profile, GList *files )
+is_target_selection_candidate( const NAObjectProfile *profile, GList *files, gboolean from_nautilus )
 {
 	gboolean retv = FALSE;
 	gboolean test_multiple_file = FALSE;
@@ -1167,13 +1201,13 @@ is_target_selection_candidate( const NAObjectProfile *profile, GList *files )
 		}
 	}
 
-	for (iter1 = files; iter1; iter1 = iter1->next)
-	{
-		tmp_filename = nautilus_file_info_get_name ((NautilusFileInfo *)iter1->data);
+	for( iter1 = files; iter1; iter1 = iter1->next ){
+
+		tmp_filename = tracked_to_basename( iter1->data, from_nautilus );
 
 		if (tmp_filename)
 		{
-			tmp_mimetype = nautilus_file_info_get_mime_type ((NautilusFileInfo *)iter1->data);
+			tmp_mimetype = tracked_to_mimetype( iter1->data, from_nautilus );
 
 			if (!profile->private->match_case)
 			{
@@ -1191,16 +1225,13 @@ is_target_selection_candidate( const NAObjectProfile *profile, GList *files )
 			g_free (tmp_mimetype);
 			tmp_mimetype = tmp_mimetype2;
 
-			if (nautilus_file_info_is_directory ((NautilusFileInfo *)iter1->data))
-			{
+			if( tracked_is_directory( iter1->data, from_nautilus )){
 				dir_count++;
-			}
-			else
-			{
+			} else {
 				file_count++;
 			}
 
-			scheme_ok_count += validate_schemes (profile->private->schemes, (NautilusFileInfo*)iter1->data);
+			scheme_ok_count += validate_schemes( profile->private->schemes, iter1->data, from_nautilus );
 
 			if (!test_basename) /* if it is already ok, skip the test to improve performance */
 			{
@@ -1242,7 +1273,6 @@ is_target_selection_candidate( const NAObjectProfile *profile, GList *files )
 
 			g_free (tmp_mimetype);
 			g_free (tmp_filename);
-
 		}
 
 		total_count++;
@@ -1314,6 +1344,146 @@ is_target_selection_candidate( const NAObjectProfile *profile, GList *files )
 	return retv;
 }
 
+static gboolean
+tracked_is_directory( void *iter, gboolean from_nautilus )
+{
+	gboolean is_dir;
+	GFile *file;
+	GFileType type;
+
+	if( from_nautilus ){
+		is_dir = nautilus_file_info_is_directory(( NautilusFileInfo * ) iter );
+
+	} else {
+		file = g_file_new_for_uri((( NATrackedItem * ) iter )->uri );
+		type = g_file_query_file_type( file, G_FILE_QUERY_INFO_NONE, NULL );
+		is_dir = ( type == G_FILE_TYPE_DIRECTORY );
+		g_object_unref( file );
+	}
+
+	return( is_dir );
+}
+
+static gchar *
+tracked_to_basename( void *iter, gboolean from_nautilus )
+{
+	gchar *bname;
+	GFile *file;
+
+	if( from_nautilus ){
+		bname = nautilus_file_info_get_name(( NautilusFileInfo * ) iter );
+	} else {
+		file = g_file_new_for_uri((( NATrackedItem * ) iter )->uri );
+		bname = g_file_get_basename( file );
+		g_object_unref( file );
+	}
+
+	return( bname );
+}
+
+static GFile *
+tracked_to_location( void *iter, gboolean from_nautilus )
+{
+	GFile *file;
+
+	if( from_nautilus ){
+		file = nautilus_file_info_get_location(( NautilusFileInfo * ) iter );
+	} else {
+		file = g_file_new_for_uri((( NATrackedItem * ) iter )->uri );
+	}
+
+	return( file );
+}
+
+static gchar *
+tracked_to_mimetype( void *iter, gboolean from_nautilus )
+{
+	gchar *type;
+	NATrackedItem *tracked;
+	GFile *file;
+	GFileInfo *info;
+
+	type = NULL;
+	if( from_nautilus ){
+		type = nautilus_file_info_get_mime_type(( NautilusFileInfo * ) iter );
+
+	} else {
+		tracked = ( NATrackedItem * ) iter;
+		if( tracked->mimetype ){
+			type = g_strdup( tracked->mimetype );
+
+		} else {
+			file = g_file_new_for_uri((( NATrackedItem * ) iter )->uri );
+			info = g_file_query_info( file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL );
+			if( info ){
+				type = g_strdup( g_file_info_get_content_type( info ));
+				g_object_unref( info );
+			}
+			g_object_unref( file );
+		}
+	}
+
+	return( type );
+}
+
+static gchar *
+tracked_to_scheme( void *iter, gboolean from_nautilus )
+{
+	gchar *scheme;
+	NAGnomeVFSURI *vfs;
+
+	if( from_nautilus ){
+		scheme = nautilus_file_info_get_uri_scheme(( NautilusFileInfo * ) iter );
+
+	} else {
+		vfs = g_new0( NAGnomeVFSURI, 1 );
+		na_gnome_vfs_uri_parse( vfs, (( NATrackedItem * ) iter )->uri );
+		scheme = g_strdup( vfs->scheme );
+		na_gnome_vfs_uri_free( vfs );
+	}
+
+	return( scheme );
+}
+
+static gchar *
+tracked_to_uri( void *iter, gboolean from_nautilus )
+{
+	gchar *uri;
+
+	if( from_nautilus ){
+		uri = nautilus_file_info_get_uri(( NautilusFileInfo * ) iter );
+	} else {
+		uri = g_strdup((( NATrackedItem * ) iter )->uri );
+	}
+
+	return( uri );
+}
+
+static int
+validate_schemes( GSList* schemes2test, void* tracked_iter, gboolean from_nautilus )
+{
+	int retv = 0;
+	GSList* iter;
+	gboolean found = FALSE;
+	gchar *scheme;
+
+	iter = schemes2test;
+	while( iter && !found ){
+
+		scheme = tracked_to_scheme( tracked_iter, from_nautilus );
+
+		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;
+}
+
 /**
  * Expands the parameters path, in function of the found tokens.
  *
@@ -1336,14 +1506,34 @@ is_target_selection_candidate( const NAObjectProfile *profile, GList *files )
  * %% : a percent sign
  *
  * Adding a parameter requires updating of :
- * - src/common/na/na-action-profile.c:na_object_profile_parse_parameters()
- * - src/common/na/na-xml-names.h
- * - src/nact/nact-icommand-tab.c:parse_parameters()
- * - src/nact/nautilus-actions-config-tool.ui:LegendDialog
+ * - nautilus-actions/private/na-action-profile.c:na_object_profile_parse_parameters()
+ * - nautilus-actions/runtime/na-xml-names.h
+ * - nautilus-actions/nact/nact-icommand-tab.c:parse_parameters()
+ * - nautilus-actions/nact/nautilus-actions-config-tool.ui:LegendDialog
  */
 gchar *
 na_object_profile_parse_parameters( const NAObjectProfile *profile, gint target, GList* files )
 {
+	return( parse_parameters( profile, target, files, TRUE ));
+}
+
+/**
+ * na_object_profile_parse_parameters_for_tracked:
+ * @profile: the selected profile.
+ * @tracked_items: current selection.
+ */
+gchar *
+na_object_profile_parse_parameters_for_tracked( const NAObjectProfile *profile, GList *tracked_items )
+{
+	return( parse_parameters( profile, ITEM_TARGET_SELECTION, tracked_items, FALSE ));
+}
+
+/*
+ * Expands the parameters path, in function of the found tokens.
+ */
+static gchar *
+parse_parameters( const NAObjectProfile *profile, gint target, GList* files, gboolean from_nautilus )
+{
 	gchar *parsed = NULL;
 	GString *string;
 	GList *ifi;
@@ -1375,8 +1565,8 @@ na_object_profile_parse_parameters( const NAObjectProfile *profile, gint target,
 
 	for( ifi = files ; ifi ; ifi = ifi->next ){
 
-		iuri = nautilus_file_info_get_uri(( NautilusFileInfo * ) ifi->data );
-		iloc = nautilus_file_info_get_location(( NautilusFileInfo * ) ifi->data );
+		iuri = tracked_to_uri( ifi->data, from_nautilus );
+		iloc = tracked_to_location( ifi->data, from_nautilus );
 		ipath = g_file_get_path( iloc );
 		ibname = g_file_get_basename( iloc );
 
@@ -1387,7 +1577,7 @@ na_object_profile_parse_parameters( const NAObjectProfile *profile, gint target,
 
 			uri = g_strdup( iuri );
 			dirname = g_path_get_dirname( ipath );
-			scheme = nautilus_file_info_get_uri_scheme(( NautilusFileInfo * ) ifi->data );
+			scheme = g_strdup( vfs->scheme );
 			filename = g_strdup( ibname );
 			hostname = g_strdup( vfs->host_name );
 			username = g_strdup( vfs->user_name );
@@ -1516,32 +1706,6 @@ na_object_profile_parse_parameters( const NAObjectProfile *profile, gint target,
 	return( parsed );
 }
 
-static int
-validate_schemes( GSList* schemes2test, NautilusFileInfo* file )
-{
-	int retv = 0;
-	GSList* iter;
-	gboolean found = FALSE;
-	gchar *scheme;
-
-	iter = schemes2test;
-	while (iter && !found)
-	{
-		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;
-}
-
 static void
 object_dump( const NAObject *object )
 {
diff --git a/nautilus-actions/test/test-parse-uris.c b/nautilus-actions/test/test-parse-uris.c
index b619ef7..ead7100 100644
--- a/nautilus-actions/test/test-parse-uris.c
+++ b/nautilus-actions/test/test-parse-uris.c
@@ -44,6 +44,7 @@ static const gchar *uris[] = {
 		"ssh://pwi.dyndns.biz:2207",
 		"sftp://kde.org:1234/pub/kde";,
 		"/usr/bin/nautilus-actions-config-tool",
+		"file:///home/pierre/data/eclipse/nautilus-actions/AUTHORS",
 		NULL
 };
 
@@ -59,7 +60,7 @@ main( int argc, char** argv )
 		NAGnomeVFSURI *vfs = g_new0( NAGnomeVFSURI, 1 );
 		na_gnome_vfs_uri_parse( vfs, uris[i] );
 		g_printf( "original  uri=%s\n", uris[i] );
-		g_printf( "vfs       uri=%s\n", vfs->uri );
+		g_printf( "vfs      path=%s\n", vfs->path );
 		g_printf( "vfs    scheme=%s\n", vfs->scheme );
 		g_printf( "vfs host_name=%s\n", vfs->host_name );
 		g_printf( "vfs host_port=%d\n", vfs->host_port );
diff --git a/nautilus-actions/tracker/.gitignore b/nautilus-actions/tracker/.gitignore
new file mode 100644
index 0000000..27e3d04
--- /dev/null
+++ b/nautilus-actions/tracker/.gitignore
@@ -0,0 +1 @@
+na-tracker-dbus-glue.h
diff --git a/nautilus-actions/tracker/Makefile.am b/nautilus-actions/tracker/Makefile.am
index 1f6b63b..2e8a32d 100644
--- a/nautilus-actions/tracker/Makefile.am
+++ b/nautilus-actions/tracker/Makefile.am
@@ -59,3 +59,11 @@ libnautilus_actions_tracker_la_LIBADD = \
 	-L$(top_builddir)/nautilus-actions/runtime	-lna-runtime	\
 	$(NAUTILUS_ACTIONS_LIBS)									\
 	$(NULL)
+
+EXTRA_DIST = \
+	na-tracker-dbus.xml											\
+	$(NULL)
+
+CLEANFILES = \
+	$(BUILT_SOURCES)											\
+	$(NULL)
diff --git a/nautilus-actions/tracker/na-tracker-dbus.c b/nautilus-actions/tracker/na-tracker-dbus.c
index 636f180..9c8518d 100644
--- a/nautilus-actions/tracker/na-tracker-dbus.c
+++ b/nautilus-actions/tracker/na-tracker-dbus.c
@@ -41,6 +41,8 @@
 
 #include <dbus/dbus-glib.h>
 
+#include <api/na-dbus.h>
+
 #include "na-tracker-dbus.h"
 #include "na-tracker-dbus-glue.h"
 
@@ -54,7 +56,7 @@ struct NATrackerDBusClassPrivate {
  */
 struct NATrackerDBusPrivate {
 	gboolean  dispose_has_run;
-	GList    *uris;
+	GList    *selected;
 };
 
 static GObjectClass *st_parent_class = NULL;
@@ -65,7 +67,7 @@ static void   instance_init( GTypeInstance *instance, gpointer klass );
 static void   instance_dispose( GObject *object );
 static void   instance_finalize( GObject *object );
 
-static GList *free_uris( GList *uris );
+static GList *free_selected( GList *selected );
 
 GType
 na_tracker_dbus_get_type( void )
@@ -143,7 +145,7 @@ instance_init( GTypeInstance *instance, gpointer klass )
 
 	self->private = g_new0( NATrackerDBusPrivate, 1 );
 	self->private->dispose_has_run = FALSE;
-	self->private->uris = NULL;
+	self->private->selected = NULL;
 }
 
 static void
@@ -177,7 +179,7 @@ instance_finalize( GObject *object )
 	g_return_if_fail( NA_IS_TRACKER_DBUS( object ));
 	self = NA_TRACKER_DBUS( object );
 
-	self->private->uris = free_uris( self->private->uris );
+	self->private->selected = free_selected( self->private->selected );
 
 	g_free( self->private );
 
@@ -197,29 +199,28 @@ instance_finalize( GObject *object )
 void
 na_tracker_dbus_set_uris( NATrackerDBus *tracker, GList *files )
 {
-	GList *it;
-	gchar *uri;
-
 	if( !tracker->private->dispose_has_run ){
 
-		tracker->private->uris = free_uris( tracker->private->uris );
-
-		for( it = files ; it ; it = it->next ){
-			uri = nautilus_file_info_get_uri(( NautilusFileInfo * ) it->data );
-			tracker->private->uris = g_list_prepend( tracker->private->uris, uri );
-		}
-
-		tracker->private->uris = g_list_reverse( tracker->private->uris );
+		tracker->private->selected = free_selected( tracker->private->selected );
+		tracker->private->selected = nautilus_file_info_list_copy( files );
 	}
 }
 
 /**
  * na_tracker_dbus_get_selected_paths:
- * @tracker:
- * @paths:
- * @error:
+ * @tracker: this #NATrackerDBus object.
+ * @paths: the location in which copy the strings to be sent.
+ * @error: the location of a GError.
+ *
+ * Send on session DBus the list of currently selected items, as two
+ * strings for each item :
+ * - its uri
+ * - its mimetype.
  *
- * Exported as GetSelectedPaths method.
+ * Note that this _must_ correspond to the content of the NATrackedItem
+ * structure, as described in private/na-object-profile-class.h
+ *
+ * Exported as GetSelectedPaths method on Tracker.Status interface.
  */
 gboolean
 na_tracker_dbus_get_selected_paths( NATrackerDBus *tracker, char ***paths, GError **error )
@@ -237,12 +238,15 @@ na_tracker_dbus_get_selected_paths( NATrackerDBus *tracker, char ***paths, GErro
 
 	if( !tracker->private->dispose_has_run ){
 
-		count = g_list_length( tracker->private->uris );
+		count = 2 * g_list_length( tracker->private->selected );
 		*paths = ( char ** ) g_new0( gchar *, 1+count );
 		iter = *paths;
 
-		for( it = tracker->private->uris ; it ; it = it->next ){
-			*iter = g_strdup(( gchar * ) it->data );
+		for( it = tracker->private->selected ; it ; it = it->next ){
+
+			*iter = nautilus_file_info_get_uri(( NautilusFileInfo * ) it->data );
+			iter++;
+			*iter = nautilus_file_info_get_mime_type(( NautilusFileInfo * ) it->data );
 			iter++;
 		}
 	}
@@ -251,15 +255,9 @@ na_tracker_dbus_get_selected_paths( NATrackerDBus *tracker, char ***paths, GErro
 }
 
 static GList *
-free_uris( GList *uris )
+free_selected( GList *selected )
 {
-	GList *it;
-
-	for( it = uris ; it ; it = it->next ){
-		g_free(( gchar * ) it->data );
-	}
-
-	g_list_free( uris );
+	nautilus_file_info_list_free( selected );
 
 	return( NULL );
 }
diff --git a/nautilus-actions/tracker/na-tracker.c b/nautilus-actions/tracker/na-tracker.c
index 0861cf2..e282cba 100644
--- a/nautilus-actions/tracker/na-tracker.c
+++ b/nautilus-actions/tracker/na-tracker.c
@@ -36,6 +36,8 @@
 #include <libnautilus-extension/nautilus-file-info.h>
 #include <libnautilus-extension/nautilus-menu-provider.h>
 
+#include <api/na-dbus.h>
+
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-bindings.h>
 
diff --git a/nautilus-actions/tracker/na-tracker.h b/nautilus-actions/tracker/na-tracker.h
index 8aa009a..f79cf40 100644
--- a/nautilus-actions/tracker/na-tracker.h
+++ b/nautilus-actions/tracker/na-tracker.h
@@ -76,8 +76,6 @@ typedef struct
 GType na_tracker_get_type( void );
 void  na_tracker_register_type( GTypeModule *module );
 
-#define NAUTILUS_ACTIONS_DBUS_SERVICE	"org.nautilus-actions.DBus"
-
 G_END_DECLS
 
 #endif /* __NA_TRACKER_H__ */
diff --git a/nautilus-actions/utils/Makefile.am b/nautilus-actions/utils/Makefile.am
index 8fd940e..f34716e 100644
--- a/nautilus-actions/utils/Makefile.am
+++ b/nautilus-actions/utils/Makefile.am
@@ -85,3 +85,7 @@ nautilus_actions_schemas_LDADD = \
 	-L$(top_builddir)/nautilus-actions/runtime	-lna-runtime	\
 	$(NAUTILUS_ACTIONS_LIBS)									\
 	$(NULL)
+
+CLEANFILES = \
+	$(BUILT_SOURCES)											\
+	$(NULL)
diff --git a/nautilus-actions/utils/nautilus-actions-run.c b/nautilus-actions/utils/nautilus-actions-run.c
index de7e1cd..8f0a89e 100644
--- a/nautilus-actions/utils/nautilus-actions-run.c
+++ b/nautilus-actions/utils/nautilus-actions-run.c
@@ -37,6 +37,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <api/na-dbus.h>
 #include <api/na-object-api.h>
 
 #include <runtime/na-pivot.h>
@@ -49,21 +50,15 @@
 #include "nautilus-actions-run-bindings.h"
 
 static gchar     *id               = "";
-static gchar     *parms            = "";
 static gchar    **targets_array    = NULL;
-static gboolean   current          = FALSE;
 static gboolean   version          = FALSE;
 
 static GOptionEntry entries[] = {
 
-	{ "id"                   , 'i', 0, G_OPTION_ARG_STRING      , &id,
+	{ "id"                   , 'i', 0, G_OPTION_ARG_STRING        , &id,
 			N_( "The internal identifiant of the action to be launched" ), N_( "<STRING>" ) },
-	{ "parameters"           , 'p', 0, G_OPTION_ARG_STRING      , &parms,
-			N_( "The parameters to be applied to the action" ), N_( "<STRING>" ) },
-	{ "target"               , 't', 0, G_OPTION_ARG_STRING      , &targets_array,
-			N_( "A target of the action. More than one options may be specified. Incompatible with '--current' option" ), N_( "<STRING>" ) },
-	{ "current"              , 'c', 0, G_OPTION_ARG_NONE        , &current,
-			N_( "Whether the action should be executed on current Nautilus selection [default]. Incompatible with '--target' option" ), NULL },
+	{ "target"               , 't', 0, G_OPTION_ARG_FILENAME_ARRAY, &targets_array,
+			N_( "A target, file or folder, for the action. More than one options may be specified" ), N_( "<URI>" ) },
 	{ NULL }
 };
 
@@ -74,13 +69,15 @@ static GOptionEntry misc_entries[] = {
 	{ NULL }
 };
 
-static GOptionContext *init_options( void );
-static NAObjectAction *get_action( const gchar *id );
-static GList          *get_current_selection( void );
-static GList          *targets_from_commandline( void );
-static void            dump_targets( GList *targets );
-static void            free_targets( GList *targets );
-static void            exit_with_usage( void );
+static GOptionContext  *init_options( void );
+static NAObjectAction  *get_action( const gchar *id );
+static GList           *targets_from_selection( void );
+static GList           *targets_from_commandline( void );
+static NAObjectProfile *get_profile_for_targets( NAObjectAction *action, GList *targets );
+static void             execute_action( NAObjectAction *action, NAObjectProfile *profile, GList *targets );
+static void             dump_targets( GList *targets );
+static void             free_targets( GList *targets );
+static void             exit_with_usage( void );
 
 int
 main( int argc, char** argv )
@@ -92,6 +89,7 @@ main( int argc, char** argv )
 	gchar *help;
 	gint errors;
 	NAObjectAction *action;
+	NAObjectProfile *profile;
 	GList *targets;
 
 	g_type_init();
@@ -127,34 +125,41 @@ main( int argc, char** argv )
 		errors += 1;
 	}
 
-	if( current && targets_array ){
-		g_printerr( _( "Error: '--target' and '--current' options cannot both be specified.\n" ));
-		errors += 1;
-	}
-
-	if( !current && !targets_array ){
-		current = TRUE;
-	}
-
 	action = get_action( id );
 	if( !action ){
 		errors += 1;
+	} else {
+		g_debug( "%s: action %s have been found, and is enabled and valid", thisfn, id );
 	}
-	g_debug( "%s: action %s have been found, and is enabled and valid", thisfn, id );
 
 	if( errors ){
 		exit_with_usage();
 	}
 
-	if( current ){
-		targets = get_current_selection();
-	} else {
+	if( targets_array ){
 		targets = targets_from_commandline();
+
+	} else {
+		targets = targets_from_selection();
 	}
 
 	dump_targets( targets );
-	free_targets( targets );
 
+	if( g_list_length( targets ) == 0 ){
+		g_print( "No current selection. Nothing to do. Exiting...\n" );
+		exit( status );
+	}
+
+	profile = get_profile_for_targets( action, targets );
+	if( !profile ){
+		g_print( "No valid profile is candidate to execution. Exiting...\n" );
+		exit( status );
+	}
+	g_debug( "%s: profile %p found", thisfn, ( void * ) profile );
+
+	execute_action( action, profile, targets );
+
+	free_targets( targets );
 	exit( status );
 }
 
@@ -235,11 +240,18 @@ get_action( const gchar *id )
 	return( action );
 }
 
+/*
+ * the DBus.Tracker.Status interface returns a list of strings
+ * each item has two slots in this list:
+ * - uri
+ * - mimetype
+ */
 static GList *
-get_current_selection( void )
+targets_from_selection( void )
 {
-	static const gchar *thisfn = "nautilus_actions_run_get_current_selection";
+	static const gchar *thisfn = "nautilus_actions_run_targets_from_selection";
 	GList *selection;
+	NATrackedItem *tracked;
 	DBusGConnection *connection;
 	DBusGProxy *proxy;
 	GError *error;
@@ -285,8 +297,12 @@ get_current_selection( void )
 
 	iter = paths;
 	while( *iter ){
-		selection = g_list_prepend( selection, g_strdup( *iter ));
+		tracked = g_new0( NATrackedItem, 1 );
+		tracked->uri = g_strdup( *iter );
 		iter++;
+		tracked->mimetype = g_strdup( *iter );
+		iter++;
+		selection = g_list_prepend( selection, tracked );
 	}
 	g_strfreev( paths );
 	selection = g_list_reverse( selection );
@@ -303,14 +319,21 @@ get_current_selection( void )
 static GList *
 targets_from_commandline( void )
 {
+	static const gchar *thisfn = "nautilus_actions_run_targets_from_commandline";
 	GList *targets;
+	NATrackedItem *tracked;
 	gchar **iter;
 
+	g_debug( "%s", thisfn );
+
 	targets = NULL;
 	iter = targets_array;
+
 	while( *iter ){
-		targets = g_list_prepend( targets, g_strdup( *iter ));
+		tracked = g_new0( NATrackedItem, 1 );
+		tracked->uri = g_strdup( *iter );
 		iter++;
+		targets = g_list_prepend( targets, tracked );
 	}
 
 	targets = g_list_reverse( targets );
@@ -319,15 +342,64 @@ targets_from_commandline( void )
 }
 
 /*
+ * find a profile candidate to be executed for the given uris
+ */
+static NAObjectProfile *
+get_profile_for_targets( NAObjectAction *action, GList *targets )
+{
+	/*static const gchar *thisfn = "nautilus_actions_run_get_profile_for_targets";*/
+	NAObjectProfile *candidate;
+	GList *profiles, *ip;
+
+	candidate = NULL;
+	profiles = na_object_get_items_list( action );
+	for( ip = profiles ; ip && !candidate ; ip = ip->next ){
+
+		NAObjectProfile *profile = NA_OBJECT_PROFILE( ip->data );
+		if( na_object_profile_is_candidate_for_tracked( profile, targets )){
+			candidate = profile;
+		}
+	}
+
+	return( candidate );
+}
+
+static void
+execute_action( NAObjectAction *action, NAObjectProfile *profile, GList *targets )
+{
+	static const gchar *thisfn = "nautilus_action_run_execute_action";
+	GString *cmd;
+	gchar *param, *path;
+
+	path = na_object_profile_get_path( profile );
+	cmd = g_string_new( path );
+
+	param = na_object_profile_parse_parameters_for_tracked( profile, targets );
+
+	if( param != NULL ){
+		g_string_append_printf( cmd, " %s", param );
+		g_free( param );
+	}
+
+	g_debug( "%s: executing '%s'", thisfn, cmd->str );
+	g_spawn_command_line_async( cmd->str, NULL );
+
+	g_string_free (cmd, TRUE);
+	g_free( path );
+}
+
+/*
  *
  */
 static void
 dump_targets( GList *targets )
 {
+	NATrackedItem *tracked;
 	GList *it;
 
 	for( it = targets ; it ; it = it->next ){
-		g_print( "%s\n", ( gchar * ) it->data );
+		tracked = ( NATrackedItem * ) it->data;
+		g_print( "%s\t[%s]\n", tracked->uri, tracked->mimetype );
 	}
 }
 
@@ -337,10 +409,14 @@ dump_targets( GList *targets )
 static void
 free_targets( GList *targets )
 {
+	NATrackedItem *tracked;
 	GList *it;
 
 	for( it = targets ; it ; it = it->next ){
-		g_free(( gchar * ) it->data );
+		tracked = ( NATrackedItem * ) it->data;
+		g_free( tracked->uri );
+		g_free( tracked->mimetype );
+		g_free( tracked );
 	}
 
 	g_list_free( targets );



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