Convert NASettings to a private singleton
[nautilus-actions.git] / src / utils / nautilus-actions-run.c
blob386f4424741e5c48057410b4e7c1a4a461f9b126
1 /*
2 * Nautilus-Actions
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.
24 * Authors:
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)
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
35 #include <glib.h>
36 #include <glib/gi18n.h>
37 #include <locale.h>
38 #include <stdlib.h>
39 #include <string.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>" ) },
63 { NULL }
66 static GOptionEntry misc_entries[] = {
68 { "version" , 'v', 0, G_OPTION_ARG_NONE , &version,
69 N_( "Output the version number" ), NULL },
70 { 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 );
83 int
84 main( int argc, char** argv )
86 static const gchar *thisfn = "nautilus_actions_run_main";
87 int status = EXIT_SUCCESS;
88 GOptionContext *context;
89 GError *error = NULL;
90 gchar *help;
91 gint errors;
92 NAObjectAction *action;
93 NAObjectProfile *profile;
94 GList *targets;
96 g_type_init();
97 setlocale( LC_ALL, "" );
98 console_init_log_handler();
100 /* pwi 2011-01-05
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();
108 if( argc == 1 ){
109 g_set_prgname( argv[0] );
110 help = g_option_context_get_help( context, FALSE, NULL );
111 g_print( "\n%s", help );
112 g_free( help );
113 exit( status );
116 if( !g_option_context_parse( context, &argc, &argv, &error )){
117 g_printerr( _( "Syntax error: %s\n" ), error->message );
118 g_error_free (error);
119 exit_with_usage();
122 g_option_context_free( context );
124 if( version ){
125 na_core_utils_print_version();
126 exit( status );
129 errors = 0;
131 if( !id || !strlen( id )){
132 g_printerr( _( "Error: action id is mandatory.\n" ));
133 errors += 1;
136 action = get_action( id );
137 if( !action ){
138 errors += 1;
139 } else {
140 g_debug( "%s: action %s have been found, and is enabled and valid", thisfn, id );
143 if( errors ){
144 exit_with_usage();
147 if( targets_array ){
148 targets = targets_from_commandline();
150 } else {
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" ));
158 exit( status );
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 );
163 exit( status );
166 profile = get_profile_for_targets( action, targets );
167 if( !profile ){
168 g_print( _( "No valid profile is candidate to execution. Exiting.\n" ));
169 exit( status );
171 g_debug( "%s: profile %p found", thisfn, ( void * ) profile );
173 execute_action( action, profile, targets );
175 na_selected_info_free_list( targets );
176 exit( status );
180 * init options context
182 static GOptionContext *
183 init_options( void )
185 GOptionContext *context;
186 gchar* description;
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 );
192 #ifdef ENABLE_NLS
193 bindtextdomain( GETTEXT_PACKAGE, GNOMELOCALEDIR );
194 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
195 bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" );
196 # endif
197 textdomain( GETTEXT_PACKAGE );
198 g_option_context_add_main_entries( context, entries, GETTEXT_PACKAGE );
199 #else
200 g_option_context_add_main_entries( context, entries, NULL );
201 #endif
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 );
213 return( context );
217 * search for the action in the repository
219 static NAObjectAction *
220 get_action( const gchar *id )
222 NAPivot *pivot;
223 NAObjectAction *action;
225 action = NULL;
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 );
233 if( !action ){
234 g_printerr( _( "Error: action '%s' doesn't exist.\n" ), id );
236 } else {
237 if( !na_object_is_enabled( action )){
238 g_printerr( _( "Error: action '%s' is disabled.\n" ), id );
239 g_object_unref( action );
240 action = NULL;
242 if( !na_object_is_valid( action )){
243 g_printerr( _( "Error: action '%s' is not valid.\n" ), id );
244 g_object_unref( action );
245 action = NULL;
249 return( 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
255 * mime type.
257 * We return to the caller a GList of NASelectedInfo objects
259 static GList *
260 targets_from_selection( void )
262 static const gchar *thisfn = "nautilus_actions_run_targets_from_selection";
263 GList *selection;
264 DBusGConnection *connection;
265 DBusGProxy *proxy;
266 GError *error;
267 gchar **paths;
269 error = NULL;
270 proxy = NULL;
271 paths = NULL;
273 connection = dbus_g_bus_get( DBUS_BUS_SESSION, &error );
275 if( !connection ){
276 if( error ){
277 g_printerr( _( "Error: unable to get a connection to session DBus: %s" ), error->message );
278 g_error_free( error );
280 return( NULL );
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 );
289 if( !proxy ){
290 g_printerr( _( "Error: unable to get a proxy on %s service" ), NAUTILUS_ACTIONS_DBUS_SERVICE );
291 dbus_g_connection_unref( connection );
292 return( NULL );
294 g_debug( "%s: proxy is ok", thisfn );
296 if( !dbus_g_proxy_call( proxy, "GetSelectedPaths", &error,
297 G_TYPE_INVALID,
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 );
304 return( NULL );
306 g_debug( "%s: function call is ok", thisfn );
308 selection = get_selection_from_strv(( const gchar ** ) paths, TRUE );
310 g_strfreev( paths );
312 /* TODO: unref proxy */
313 dbus_g_connection_unref( connection );
315 return( selection );
319 * get targets from command-line
321 * We return to the caller a GList of NASelectedInfo objects.
323 static GList *
324 targets_from_commandline( void )
326 static const gchar *thisfn = "nautilus_actions_run_targets_from_commandline";
327 GList *targets;
329 g_debug( "%s", thisfn );
331 targets = get_selection_from_strv(( const gchar ** ) targets_array, FALSE );
333 return( targets );
336 static GList *
337 get_selection_from_strv( const gchar **strv, gboolean has_mimetype )
339 GList *list;
340 gchar **iter;
341 gchar *errmsg;
343 list = NULL;
344 iter = ( gchar ** ) strv;
346 while( *iter ){
347 const gchar *uri = ( const gchar * ) *iter;
348 const gchar *mimetype = NULL;
349 if( has_mimetype ){
350 iter++;
351 mimetype = ( const gchar * ) *iter;
354 errmsg = NULL;
355 NASelectedInfo *nsi = na_selected_info_create_for_uri( uri, mimetype, &errmsg );
357 if( errmsg ){
358 g_printerr( "%s\n", errmsg );
359 g_free( errmsg );
362 if( nsi ){
363 list = g_list_prepend( list, nsi );
365 iter++;
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;
381 candidate = NULL;
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 );
390 return( candidate );
393 static void
394 execute_action( NAObjectAction *action, NAObjectProfile *profile, GList *targets )
396 /*static const gchar *thisfn = "nautilus_action_run_execute_action";*/
397 NATokens *tokens;
399 tokens = na_tokens_new_from_selection( targets );
400 na_tokens_execute_action( tokens, profile );
406 static void
407 dump_targets( GList *targets )
409 GList *it;
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 );
417 g_free( mimetype );
418 g_free( uri );
423 * print a help message and exit with failure
425 static void
426 exit_with_usage( void )
428 g_printerr( _( "Try %s --help for usage.\n" ), g_get_prgname());
429 exit( EXIT_FAILURE );