Set Nautilus-Actions as being the actual official product name
[nautilus-actions.git] / src / utils / nautilus-actions-run.c
blob14d6ed19602b7043e552251cbc9526cc3a71d8be
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 <stdlib.h>
38 #include <string.h>
40 #include <api/na-core-utils.h>
41 #include <api/na-object-api.h>
42 #include <api/na-dbus.h>
44 #include <core/na-pivot.h>
45 #include <core/na-selected-info.h>
46 #include <core/na-tokens.h>
48 #include "console-utils.h"
49 #include "nautilus-actions-run-bindings.h"
51 static gchar *id = "";
52 static gchar **targets_array = NULL;
53 static gboolean version = FALSE;
55 static GOptionEntry entries[] = {
57 { "id" , 'i', 0, G_OPTION_ARG_STRING , &id,
58 N_( "The internal identifiant of the action to be launched" ), N_( "<STRING>" ) },
59 { "target" , 't', 0, G_OPTION_ARG_FILENAME_ARRAY, &targets_array,
60 N_( "A target, file or folder, for the action. More than one options may be specified" ), N_( "<URI>" ) },
61 { NULL }
64 static GOptionEntry misc_entries[] = {
66 { "version" , 'v', 0, G_OPTION_ARG_NONE , &version,
67 N_( "Output the version number" ), NULL },
68 { NULL }
71 static GOptionContext *init_options( void );
72 static NAObjectAction *get_action( const gchar *id );
73 static GList *targets_from_selection( void );
74 static GList *targets_from_commandline( void );
75 static GList *get_selection_from_strv( const gchar **strv, gboolean has_mimetype );
76 static NAObjectProfile *get_profile_for_targets( NAObjectAction *action, GList *targets );
77 static void execute_action( NAObjectAction *action, NAObjectProfile *profile, GList *targets );
78 static void dump_targets( GList *targets );
79 static void exit_with_usage( void );
81 int
82 main( int argc, char** argv )
84 static const gchar *thisfn = "nautilus_actions_run_main";
85 int status = EXIT_SUCCESS;
86 GOptionContext *context;
87 GError *error = NULL;
88 gchar *help;
89 gint errors;
90 NAObjectAction *action;
91 NAObjectProfile *profile;
92 GList *targets;
94 g_type_init();
95 console_init_log_handler();
97 context = init_options();
99 if( argc == 1 ){
100 g_set_prgname( argv[0] );
101 help = g_option_context_get_help( context, FALSE, NULL );
102 g_print( "\n%s", help );
103 g_free( help );
104 exit( status );
107 if( !g_option_context_parse( context, &argc, &argv, &error )){
108 g_printerr( _( "Syntax error: %s\n" ), error->message );
109 g_error_free (error);
110 exit_with_usage();
113 g_option_context_free( context );
115 if( version ){
116 na_core_utils_print_version();
117 exit( status );
120 errors = 0;
122 if( !id || !strlen( id )){
123 g_printerr( _( "Error: action id is mandatory.\n" ));
124 errors += 1;
127 action = get_action( id );
128 if( !action ){
129 errors += 1;
130 } else {
131 g_debug( "%s: action %s have been found, and is enabled and valid", thisfn, id );
134 if( errors ){
135 exit_with_usage();
138 if( targets_array ){
139 targets = targets_from_commandline();
141 } else {
142 targets = targets_from_selection();
145 dump_targets( targets );
147 if( g_list_length( targets ) == 0 ){
148 g_print( _( "No current selection. Nothing to do. Exiting.\n" ));
149 exit( status );
152 if( !na_icontext_is_candidate( NA_ICONTEXT( action ), ITEM_TARGET_ANY, targets )){
153 g_printerr( _( "Action %s is not a valid candidate. Exiting.\n" ), id );
154 exit( status );
157 profile = get_profile_for_targets( action, targets );
158 if( !profile ){
159 g_print( _( "No valid profile is candidate to execution. Exiting.\n" ));
160 exit( status );
162 g_debug( "%s: profile %p found", thisfn, ( void * ) profile );
164 execute_action( action, profile, targets );
166 na_selected_info_free_list( targets );
167 exit( status );
171 * init options context
173 static GOptionContext *
174 init_options( void )
176 GOptionContext *context;
177 gchar* description;
178 GOptionGroup *misc_group;
180 context = g_option_context_new( _( "Execute an action on the specified target." ));
182 #ifdef ENABLE_NLS
183 bindtextdomain( GETTEXT_PACKAGE, GNOMELOCALEDIR );
184 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
185 bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" );
186 # endif
187 textdomain( GETTEXT_PACKAGE );
188 g_option_context_add_main_entries( context, entries, GETTEXT_PACKAGE );
189 #else
190 g_option_context_add_main_entries( context, entries, NULL );
191 #endif
193 description = console_cmdline_get_description();
194 g_option_context_set_description( context, description );
195 g_free( description );
197 misc_group = g_option_group_new(
198 "misc", _( "Miscellaneous options" ), _( "Miscellaneous options" ), NULL, NULL );
199 g_option_group_add_entries( misc_group, misc_entries );
200 g_option_context_add_group( context, misc_group );
202 return( context );
206 * search for the action in the repository
208 static NAObjectAction *
209 get_action( const gchar *id )
211 NAObjectAction *action;
212 NAPivot *pivot;
214 action = NULL;
216 pivot = na_pivot_new();
217 na_pivot_set_loadable( pivot, !PIVOT_LOAD_DISABLED & !PIVOT_LOAD_INVALID );
218 na_pivot_load_items( pivot );
220 action = ( NAObjectAction * ) na_pivot_get_item( pivot, id );
222 if( !action ){
223 g_printerr( _( "Error: action '%s' doesn't exist.\n" ), id );
225 } else {
226 if( !na_object_is_enabled( action )){
227 g_printerr( _( "Error: action '%s' is disabled.\n" ), id );
228 g_object_unref( action );
229 action = NULL;
231 if( !na_object_is_valid( action )){
232 g_printerr( _( "Error: action '%s' is not valid.\n" ), id );
233 g_object_unref( action );
234 action = NULL;
238 return( action );
242 * the DBus.Tracker.Status interface returns a list of strings
243 * where each selected item brings up both its URI and its Nautilus
244 * mime type.
246 * We return to the caller a GList of NASelectedInfo objects
248 static GList *
249 targets_from_selection( void )
251 static const gchar *thisfn = "nautilus_actions_run_targets_from_selection";
252 GList *selection;
253 DBusGConnection *connection;
254 DBusGProxy *proxy;
255 GError *error;
256 gchar **paths;
258 error = NULL;
259 proxy = NULL;
260 paths = NULL;
262 connection = dbus_g_bus_get( DBUS_BUS_SESSION, &error );
264 if( !connection ){
265 if( error ){
266 g_printerr( _( "Error: unable to get a connection to session DBus: %s" ), error->message );
267 g_error_free( error );
269 return( NULL );
271 g_debug( "%s: connection is ok", thisfn );
273 proxy = dbus_g_proxy_new_for_name( connection,
274 NAUTILUS_ACTIONS_DBUS_SERVICE,
275 NAUTILUS_ACTIONS_DBUS_TRACKER_PATH,
276 NAUTILUS_ACTIONS_DBUS_TRACKER_INTERFACE );
278 if( !proxy ){
279 g_printerr( _( "Error: unable to get a proxy on %s service" ), NAUTILUS_ACTIONS_DBUS_SERVICE );
280 dbus_g_connection_unref( connection );
281 return( NULL );
283 g_debug( "%s: proxy is ok", thisfn );
285 if( !dbus_g_proxy_call( proxy, "GetSelectedPaths", &error,
286 G_TYPE_INVALID,
287 G_TYPE_STRV, &paths, G_TYPE_INVALID )){
289 g_printerr( _( "Error on GetSelectedPaths call: %s" ), error->message );
290 g_error_free( error );
291 /* TODO: unref proxy */
292 dbus_g_connection_unref( connection );
293 return( NULL );
295 g_debug( "%s: function call is ok", thisfn );
297 selection = get_selection_from_strv(( const gchar ** ) paths, TRUE );
299 g_strfreev( paths );
301 /* TODO: unref proxy */
302 dbus_g_connection_unref( connection );
304 return( selection );
308 * get targets from command-line
310 * We return to the caller a GList of NASelectedInfo objects.
312 static GList *
313 targets_from_commandline( void )
315 static const gchar *thisfn = "nautilus_actions_run_targets_from_commandline";
316 GList *targets;
318 g_debug( "%s", thisfn );
320 targets = get_selection_from_strv(( const gchar ** ) targets_array, FALSE );
322 return( targets );
325 static GList *
326 get_selection_from_strv( const gchar **strv, gboolean has_mimetype )
328 GList *list;
329 gchar **iter;
330 gchar *errmsg;
332 list = NULL;
333 iter = ( gchar ** ) strv;
335 while( *iter ){
336 const gchar *uri = ( const gchar * ) *iter;
337 const gchar *mimetype = NULL;
338 if( has_mimetype ){
339 iter++;
340 mimetype = ( const gchar * ) *iter;
343 errmsg = NULL;
344 NASelectedInfo *nsi = na_selected_info_create_for_uri( uri, mimetype, &errmsg );
346 if( errmsg ){
347 g_printerr( "%s\n", errmsg );
348 g_free( errmsg );
351 if( nsi ){
352 list = g_list_prepend( list, nsi );
354 iter++;
357 return( g_list_reverse( list ));
361 * find a profile candidate to be executed for the given uris
363 static NAObjectProfile *
364 get_profile_for_targets( NAObjectAction *action, GList *targets )
366 /*static const gchar *thisfn = "nautilus_actions_run_get_profile_for_targets";*/
367 GList *profiles, *ip;
368 NAObjectProfile *candidate;
370 candidate = NULL;
371 profiles = na_object_get_items( action );
373 for( ip = profiles ; ip && !candidate ; ip = ip->next ){
374 if( na_icontext_is_candidate( NA_ICONTEXT( ip->data ), ITEM_TARGET_ANY, targets )){
375 candidate = NA_OBJECT_PROFILE( ip->data );
379 return( candidate );
382 static void
383 execute_action( NAObjectAction *action, NAObjectProfile *profile, GList *targets )
385 /*static const gchar *thisfn = "nautilus_action_run_execute_action";*/
386 NATokens *tokens;
388 tokens = na_tokens_new_from_selection( targets );
389 na_tokens_execute_action( tokens, profile );
395 static void
396 dump_targets( GList *targets )
398 GList *it;
399 gchar *uri, *mimetype;
401 for( it = targets ; it ; it = it->next ){
402 NASelectedInfo *nsi = NA_SELECTED_INFO( it->data );
403 uri = na_selected_info_get_uri( nsi );
404 mimetype = na_selected_info_get_mime_type( nsi );
405 g_print( "%s\t[%s]\n", uri, mimetype );
406 g_free( mimetype );
407 g_free( uri );
412 * print a help message and exit with failure
414 static void
415 exit_with_usage( void )
417 g_printerr( _( "Try %s --help for usage.\n" ), g_get_prgname());
418 exit( EXIT_FAILURE );