3 * A Nautilus extension which offers configurable context menu actions.
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
9 * This Program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This Program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this Library; see the file COPYING. If not,
21 * write to the Free Software Foundation, Inc., 59 Temple Place,
22 * Suite 330, Boston, MA 02111-1307, USA.
25 * Frederic Ruaudel <grumz@grumz.net>
26 * Rodrigo Moya <rodrigo@gnome-db.org>
27 * Pierre Wieser <pwieser@trychlos.org>
28 * ... and many others (see AUTHORS)
36 #include <glib/gi18n.h>
41 #include <api/na-core-utils.h>
42 #include <api/na-object-api.h>
43 #include <api/na-dbus.h>
45 #include <core/na-gconf-migration.h>
46 #include <core/na-pivot.h>
47 #include <core/na-selected-info.h>
48 #include <core/na-tokens.h>
50 #include "console-utils.h"
51 #include "nautilus-actions-run-bindings.h"
53 static gchar
*id
= "";
54 static gchar
**targets_array
= NULL
;
55 static gboolean version
= FALSE
;
57 static GOptionEntry entries
[] = {
59 { "id" , 'i', 0, G_OPTION_ARG_STRING
, &id
,
60 N_( "The internal identifier of the action to be launched" ), N_( "<STRING>" ) },
61 { "target" , 't', 0, G_OPTION_ARG_FILENAME_ARRAY
, &targets_array
,
62 N_( "A target, file or folder, for the action. More than one options may be specified" ), N_( "<URI>" ) },
66 static GOptionEntry misc_entries
[] = {
68 { "version" , 'v', 0, G_OPTION_ARG_NONE
, &version
,
69 N_( "Output the version number" ), NULL
},
73 static GOptionContext
*init_options( void );
74 static NAObjectAction
*get_action( const gchar
*id
);
75 static GList
*targets_from_selection( void );
76 static GList
*targets_from_commandline( void );
77 static GList
*get_selection_from_strv( const gchar
**strv
, gboolean has_mimetype
);
78 static NAObjectProfile
*get_profile_for_targets( NAObjectAction
*action
, GList
*targets
);
79 static void execute_action( NAObjectAction
*action
, NAObjectProfile
*profile
, GList
*targets
);
80 static void dump_targets( GList
*targets
);
81 static void exit_with_usage( void );
84 main( int argc
, char** argv
)
86 static const gchar
*thisfn
= "nautilus_actions_run_main";
87 int status
= EXIT_SUCCESS
;
88 GOptionContext
*context
;
92 NAObjectAction
*action
;
93 NAObjectProfile
*profile
;
97 setlocale( LC_ALL
, "" );
98 console_init_log_handler();
101 * run GConf migration tools before doing anything else
102 * above all before allocating a new NAPivot
104 na_gconf_migration_run();
106 context
= init_options();
109 g_set_prgname( argv
[0] );
110 help
= g_option_context_get_help( context
, FALSE
, NULL
);
111 g_print( "\n%s", help
);
116 if( !g_option_context_parse( context
, &argc
, &argv
, &error
)){
117 g_printerr( _( "Syntax error: %s\n" ), error
->message
);
118 g_error_free (error
);
122 g_option_context_free( context
);
125 na_core_utils_print_version();
131 if( !id
|| !strlen( id
)){
132 g_printerr( _( "Error: action id is mandatory.\n" ));
136 action
= get_action( id
);
140 g_debug( "%s: action %s have been found, and is enabled and valid", thisfn
, id
);
148 targets
= targets_from_commandline();
151 targets
= targets_from_selection();
154 dump_targets( targets
);
156 if( g_list_length( targets
) == 0 ){
157 g_print( _( "No current selection. Nothing to do. Exiting.\n" ));
161 if( !na_icontext_is_candidate( NA_ICONTEXT( action
), ITEM_TARGET_ANY
, targets
)){
162 g_printerr( _( "Action %s is not a valid candidate. Exiting.\n" ), id
);
166 profile
= get_profile_for_targets( action
, targets
);
168 g_print( _( "No valid profile is candidate to execution. Exiting.\n" ));
171 g_debug( "%s: profile %p found", thisfn
, ( void * ) profile
);
173 execute_action( action
, profile
, targets
);
175 na_selected_info_free_list( targets
);
180 * init options context
182 static GOptionContext
*
185 GOptionContext
*context
;
187 GOptionGroup
*misc_group
;
189 context
= g_option_context_new( _( "Execute an action on the specified target." ));
190 g_option_context_set_translation_domain( context
, GETTEXT_PACKAGE
);
193 bindtextdomain( GETTEXT_PACKAGE
, GNOMELOCALEDIR
);
194 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
195 bind_textdomain_codeset( GETTEXT_PACKAGE
, "UTF-8" );
197 textdomain( GETTEXT_PACKAGE
);
198 g_option_context_add_main_entries( context
, entries
, GETTEXT_PACKAGE
);
200 g_option_context_add_main_entries( context
, entries
, NULL
);
203 description
= console_cmdline_get_description();
204 g_option_context_set_description( context
, description
);
205 g_free( description
);
207 misc_group
= g_option_group_new(
208 "misc", _( "Miscellaneous options" ), _( "Miscellaneous options" ), NULL
, NULL
);
209 g_option_group_add_entries( misc_group
, misc_entries
);
210 g_option_group_set_translation_domain( misc_group
, GETTEXT_PACKAGE
);
211 g_option_context_add_group( context
, misc_group
);
217 * search for the action in the repository
219 static NAObjectAction
*
220 get_action( const gchar
*id
)
223 NAObjectAction
*action
;
227 pivot
= na_pivot_new();
228 na_pivot_set_loadable( pivot
, !PIVOT_LOAD_DISABLED
& !PIVOT_LOAD_INVALID
);
229 na_pivot_load_items( pivot
);
231 action
= ( NAObjectAction
* ) na_pivot_get_item( pivot
, id
);
234 g_printerr( _( "Error: action '%s' doesn't exist.\n" ), id
);
237 if( !na_object_is_enabled( action
)){
238 g_printerr( _( "Error: action '%s' is disabled.\n" ), id
);
239 g_object_unref( action
);
242 if( !na_object_is_valid( action
)){
243 g_printerr( _( "Error: action '%s' is not valid.\n" ), id
);
244 g_object_unref( action
);
253 * the DBus.Tracker.Status interface returns a list of strings
254 * where each selected item brings up both its URI and its Nautilus
257 * We return to the caller a GList of NASelectedInfo objects
260 targets_from_selection( void )
262 static const gchar
*thisfn
= "nautilus_actions_run_targets_from_selection";
264 DBusGConnection
*connection
;
273 connection
= dbus_g_bus_get( DBUS_BUS_SESSION
, &error
);
277 g_printerr( _( "Error: unable to get a connection to session DBus: %s" ), error
->message
);
278 g_error_free( error
);
282 g_debug( "%s: connection is ok", thisfn
);
284 proxy
= dbus_g_proxy_new_for_name( connection
,
285 NAUTILUS_ACTIONS_DBUS_SERVICE
,
286 NAUTILUS_ACTIONS_DBUS_TRACKER_PATH
,
287 NAUTILUS_ACTIONS_DBUS_TRACKER_INTERFACE
);
290 g_printerr( _( "Error: unable to get a proxy on %s service" ), NAUTILUS_ACTIONS_DBUS_SERVICE
);
291 dbus_g_connection_unref( connection
);
294 g_debug( "%s: proxy is ok", thisfn
);
296 if( !dbus_g_proxy_call( proxy
, "GetSelectedPaths", &error
,
298 G_TYPE_STRV
, &paths
, G_TYPE_INVALID
)){
300 g_printerr( _( "Error on GetSelectedPaths call: %s" ), error
->message
);
301 g_error_free( error
);
302 /* TODO: unref proxy */
303 dbus_g_connection_unref( connection
);
306 g_debug( "%s: function call is ok", thisfn
);
308 selection
= get_selection_from_strv(( const gchar
** ) paths
, TRUE
);
312 /* TODO: unref proxy */
313 dbus_g_connection_unref( connection
);
319 * get targets from command-line
321 * We return to the caller a GList of NASelectedInfo objects.
324 targets_from_commandline( void )
326 static const gchar
*thisfn
= "nautilus_actions_run_targets_from_commandline";
329 g_debug( "%s", thisfn
);
331 targets
= get_selection_from_strv(( const gchar
** ) targets_array
, FALSE
);
337 get_selection_from_strv( const gchar
**strv
, gboolean has_mimetype
)
344 iter
= ( gchar
** ) strv
;
347 const gchar
*uri
= ( const gchar
* ) *iter
;
348 const gchar
*mimetype
= NULL
;
351 mimetype
= ( const gchar
* ) *iter
;
355 NASelectedInfo
*nsi
= na_selected_info_create_for_uri( uri
, mimetype
, &errmsg
);
358 g_printerr( "%s\n", errmsg
);
363 list
= g_list_prepend( list
, nsi
);
368 return( g_list_reverse( list
));
372 * find a profile candidate to be executed for the given uris
374 static NAObjectProfile
*
375 get_profile_for_targets( NAObjectAction
*action
, GList
*targets
)
377 /*static const gchar *thisfn = "nautilus_actions_run_get_profile_for_targets";*/
378 GList
*profiles
, *ip
;
379 NAObjectProfile
*candidate
;
382 profiles
= na_object_get_items( action
);
384 for( ip
= profiles
; ip
&& !candidate
; ip
= ip
->next
){
385 if( na_icontext_is_candidate( NA_ICONTEXT( ip
->data
), ITEM_TARGET_ANY
, targets
)){
386 candidate
= NA_OBJECT_PROFILE( ip
->data
);
394 execute_action( NAObjectAction
*action
, NAObjectProfile
*profile
, GList
*targets
)
396 /*static const gchar *thisfn = "nautilus_action_run_execute_action";*/
399 tokens
= na_tokens_new_from_selection( targets
);
400 na_tokens_execute_action( tokens
, profile
);
407 dump_targets( GList
*targets
)
410 gchar
*uri
, *mimetype
;
412 for( it
= targets
; it
; it
= it
->next
){
413 NASelectedInfo
*nsi
= NA_SELECTED_INFO( it
->data
);
414 uri
= na_selected_info_get_uri( nsi
);
415 mimetype
= na_selected_info_get_mime_type( nsi
);
416 g_print( "%s\t[%s]\n", uri
, mimetype
);
423 * print a help message and exit with failure
426 exit_with_usage( void )
428 g_printerr( _( "Try %s --help for usage.\n" ), g_get_prgname());
429 exit( EXIT_FAILURE
);