1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3 /* nautilus-program-choosing.c - functions for selecting and activating
4 programs for opening/viewing particular files.
6 Copyright (C) 2000 Eazel, Inc.
8 The Gnome Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
13 The Gnome Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Library General Public
19 License along with the Gnome Library; see the file COPYING.LIB. If not,
20 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.
23 Author: John Sullivan <sullivan@eazel.com>
27 #include "nautilus-program-choosing.h"
29 #include "nautilus-mime-actions.h"
30 #include "nautilus-global-preferences.h"
31 #include "nautilus-icon-info.h"
32 #include "nautilus-recent.h"
33 #include "nautilus-desktop-icon-file.h"
34 #include <eel/eel-glib-extensions.h>
35 #include <eel/eel-gnome-extensions.h>
36 #include <eel/eel-stock-dialogs.h>
37 #include <eel/eel-preferences.h>
38 #include <eel/eel-string.h>
39 #include <eel/eel-app-launch-context.h>
41 #include <glib/gi18n.h>
43 #include <gio/gdesktopappinfo.h>
50 * application_cannot_open_location
52 * Handle the case where an application has been selected to be launched,
53 * and it cannot handle the current uri scheme. This can happen
54 * because the default application for a file type may not be able
55 * to handle some kinds of locations. We want to tell users that their
56 * default application doesn't work here, rather than switching off to
57 * a different one without them noticing.
59 * @application: The application that was to be launched.
60 * @file: The file whose location was passed as a parameter to the application
61 * @parent_window: A window to use as the parent for any error dialogs.
64 application_cannot_open_location (GAppInfo
*application
,
66 const char *uri_scheme
,
67 GtkWindow
*parent_window
)
69 #ifdef NEW_MIME_COMPLETE
70 GtkDialog
*message_dialog
;
71 LaunchParameters
*launch_parameters
;
77 file_name
= nautilus_file_get_display_name (file
);
79 if (nautilus_mime_has_any_applications_for_file (file
)) {
80 if (application
!= NULL
) {
81 prompt
= _("Open Failed, would you like to choose another application?");
82 message
= g_strdup_printf (_("\"%s\" cannot open \"%s\" because \"%s\" cannot access files at \"%s\" "
84 g_app_info_get_name (application
), file_name
,
85 g_app_info_get_name (application
), uri_scheme
);
87 prompt
= _("Open Failed, would you like to choose another action?");
88 message
= g_strdup_printf (_("The default action cannot open \"%s\" because it cannot access files at \"%s\" "
90 file_name
, uri_scheme
);
93 message_dialog
= eel_show_yes_no_dialog (prompt
,
98 response
= gtk_dialog_run (message_dialog
);
99 gtk_object_destroy (GTK_OBJECT (message_dialog
));
101 if (response
== GTK_RESPONSE_YES
) {
102 launch_parameters
= launch_parameters_new (file
, parent_window
);
103 nautilus_choose_application_for_file
106 launch_application_callback
,
112 if (application
!= NULL
) {
113 prompt
= g_strdup_printf (_("\"%s\" cannot open \"%s\" because \"%s\" cannot access files at \"%s\" "
114 "locations."), g_app_info_get_name (application
), file_name
,
115 g_app_info_get_name (application
), uri_scheme
);
116 message
= _("No other applications are available to view this file. "
117 "If you copy this file onto your computer, you may be able to open "
120 prompt
= g_strdup_printf (_("The default action cannot open \"%s\" because it cannot access files at \"%s\" "
121 "locations."), file_name
, uri_scheme
);
122 message
= _("No other actions are available to view this file. "
123 "If you copy this file onto your computer, you may be able to open "
127 eel_show_info_dialog (prompt
, message
, parent_window
);
136 * nautilus_launch_application:
138 * Fork off a process to launch an application with a given file as a
139 * parameter. Provide a parent window for error dialogs.
141 * @application: The application to be launched.
142 * @files: The files whose locations should be passed as a parameter to the application.
143 * @parent_window: A window to use as the parent for any error dialogs.
146 nautilus_launch_application (GAppInfo
*application
,
148 GtkWindow
*parent_window
)
151 GList
*locations
, *l
;
156 EelAppLaunchContext
*launch_context
;
157 NautilusIconInfo
*icon
;
159 g_assert (files
!= NULL
);
162 for (l
= files
; l
!= NULL
; l
= l
->next
) {
163 file
= NAUTILUS_FILE (l
->data
);
165 location
= nautilus_file_get_activation_location (file
);
167 locations
= g_list_prepend (locations
, location
);
169 locations
= g_list_reverse (locations
);
171 launch_context
= eel_app_launch_context_new ();
173 eel_app_launch_context_set_screen (launch_context
,
174 gtk_window_get_screen (parent_window
));
176 file
= NAUTILUS_FILE (files
->data
);
177 icon
= nautilus_file_get_icon (file
, 48, 0);
179 eel_app_launch_context_set_icon_name (launch_context
,
180 nautilus_icon_info_get_used_name (icon
));
181 g_object_unref (icon
);
185 result
= g_app_info_launch (application
,
187 G_APP_LAUNCH_CONTEXT (launch_context
),
190 g_object_unref (launch_context
);
193 if (error
->domain
== G_IO_ERROR
&&
194 error
->code
== G_IO_ERROR_NOT_SUPPORTED
) {
195 uri_scheme
= nautilus_file_get_uri_scheme (NAUTILUS_FILE (files
->data
));
196 application_cannot_open_location (application
,
202 #ifdef NEW_MIME_COMPLETE
203 nautilus_program_chooser_show_invalid_message
204 (GNOME_VFS_MIME_ACTION_TYPE_APPLICATION
, file
, parent_window
);
206 g_warning ("Cannot open app: %s\n", error
->message
);
210 for (l
= files
; l
!= NULL
; l
= l
->next
) {
211 file
= NAUTILUS_FILE (l
->data
);
213 nautilus_recent_add_file (file
, application
);
217 eel_g_object_list_free (locations
);
221 * nautilus_launch_application_from_command:
223 * Fork off a process to launch an application with a given uri as
226 * @command_string: The application to be launched, with any desired
227 * command-line options.
228 * @parameter: Passed as a parameter to the application as is.
231 nautilus_launch_application_from_command (GdkScreen
*screen
,
233 const char *command_string
,
234 const char *parameter
,
235 gboolean use_terminal
)
238 char *quoted_parameter
;
240 if (parameter
!= NULL
) {
241 quoted_parameter
= g_shell_quote (parameter
);
242 full_command
= g_strconcat (command_string
, " ", quoted_parameter
, NULL
);
243 g_free (quoted_parameter
);
245 full_command
= g_strdup (command_string
);
249 eel_gnome_open_terminal_on_screen (full_command
, screen
);
251 gdk_spawn_command_line_on_screen (screen
, full_command
, NULL
);
254 g_free (full_command
);
258 nautilus_launch_desktop_file (GdkScreen
*screen
,
259 const char *desktop_file_uri
,
260 const GList
*parameter_uris
,
261 GtkWindow
*parent_window
)
264 char *message
, *desktop_file_path
;
268 GFile
*file
, *desktop_file
;
269 GDesktopAppInfo
*app_info
;
270 EelAppLaunchContext
*context
;
272 /* Don't allow command execution from remote locations
273 * to partially mitigate the security
274 * risk of executing arbitrary commands.
276 desktop_file
= g_file_new_for_uri (desktop_file_uri
);
277 desktop_file_path
= g_file_get_path (desktop_file
);
278 if (!g_file_is_native (desktop_file
)) {
279 g_free (desktop_file_path
);
280 g_object_unref (desktop_file
);
281 eel_show_error_dialog
282 (_("Sorry, but you cannot execute commands from "
284 _("This is disabled due to security considerations."),
289 g_object_unref (desktop_file
);
291 app_info
= g_desktop_app_info_new_from_filename (desktop_file_path
);
292 g_free (desktop_file_path
);
293 if (app_info
== NULL
) {
294 eel_show_error_dialog
295 (_("There was an error launching the application."),
301 /* count the number of uris with local paths */
303 total
= g_list_length ((GList
*) parameter_uris
);
305 for (p
= parameter_uris
; p
!= NULL
; p
= p
->next
) {
306 file
= g_file_new_for_uri ((const char *) p
->data
);
307 if (g_file_is_native (file
)) {
310 files
= g_list_prepend (files
, file
);
313 /* check if this app only supports local files */
314 if (g_app_info_supports_files (G_APP_INFO (app_info
)) &&
315 !g_app_info_supports_uris (G_APP_INFO (app_info
)) &&
316 parameter_uris
!= NULL
) {
318 /* all files are non-local */
319 eel_show_error_dialog
320 (_("This drop target only supports local files."),
321 _("To open non-local files copy them to a local folder and then"
322 " drop them again."),
325 eel_g_object_list_free (files
);
326 g_object_unref (app_info
);
328 } else if (count
!= total
) {
329 /* some files are non-local */
330 eel_show_warning_dialog
331 (_("This drop target only supports local files."),
332 _("To open non-local files copy them to a local folder and then"
333 " drop them again. The local files you dropped have already been opened."),
339 context
= eel_app_launch_context_new ();
340 /* TODO: Ideally we should accept a timestamp here instead of using GDK_CURRENT_TIME */
341 eel_app_launch_context_set_timestamp (context
, GDK_CURRENT_TIME
);
342 eel_app_launch_context_set_screen (context
,
343 gtk_window_get_screen (parent_window
));
344 if (count
== total
) {
345 /* All files are local, so we can use g_app_info_launch () with
346 * the file list we constructed before.
348 g_app_info_launch (G_APP_INFO (app_info
),
350 G_APP_LAUNCH_CONTEXT (context
),
353 /* Some files are non local, better use g_app_info_launch_uris ().
355 g_app_info_launch_uris (G_APP_INFO (app_info
),
356 (GList
*) parameter_uris
,
357 G_APP_LAUNCH_CONTEXT (context
),
361 message
= g_strconcat (_("Details: "), error
->message
, NULL
);
362 eel_show_error_dialog
363 (_("There was an error launching the application."),
367 g_error_free (error
);
371 eel_g_object_list_free (files
);
372 g_object_unref (context
);
373 g_object_unref (app_info
);