1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3 /* nautilus-mime-actions.c - uri-specific versions of mime action functions
5 Copyright (C) 2000, 2001 Eazel, Inc.
7 The Gnome Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 The Gnome Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the Gnome Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
22 Authors: Maciej Stachowiak <mjs@eazel.com>
26 #include "nautilus-mime-actions.h"
28 #include <eel/eel-glib-extensions.h>
29 #include <eel/eel-stock-dialogs.h>
30 #include <eel/eel-string.h>
31 #include <eel/eel-mount-operation.h>
32 #include <glib/gi18n.h>
36 #include "nautilus-file-attributes.h"
37 #include "nautilus-file.h"
38 #include "nautilus-autorun.h"
39 #include "nautilus-file-operations.h"
40 #include "nautilus-metadata.h"
41 #include "nautilus-program-choosing.h"
42 #include "nautilus-desktop-icon-file.h"
43 #include "nautilus-global-preferences.h"
44 #include "nautilus-debug-log.h"
47 ACTIVATION_ACTION_LAUNCH_DESKTOP_FILE
,
48 ACTIVATION_ACTION_ASK
,
49 ACTIVATION_ACTION_LAUNCH
,
50 ACTIVATION_ACTION_LAUNCH_IN_TERMINAL
,
51 ACTIVATION_ACTION_OPEN_IN_VIEW
,
52 ACTIVATION_ACTION_OPEN_IN_APPLICATION
,
53 ACTIVATION_ACTION_DO_NOTHING
,
57 GAppInfo
*application
;
59 } ApplicationLaunchParameters
;
62 NautilusWindowInfo
*window_info
;
63 GtkWindow
*parent_window
;
64 GCancellable
*cancellable
;
68 NautilusWindowOpenMode mode
;
69 NautilusWindowOpenFlags flags
;
70 char *timed_wait_prompt
;
71 gboolean timed_wait_active
;
72 NautilusFileListHandle
*files_handle
;
73 gboolean tried_mounting
;
74 char *activation_directory
;
77 /* Number of seconds until cancel dialog shows up */
78 #define DELAY_UNTIL_CANCEL_MSECS 5000
80 #define RESPONSE_RUN 1000
81 #define RESPONSE_DISPLAY 1001
82 #define RESPONSE_RUN_IN_TERMINAL 1002
84 #define SILENT_WINDOW_OPEN_LIMIT 5
86 /* This number controls a maximum character count for a URL that is
87 * displayed as part of a dialog. It's fairly arbitrary -- big enough
88 * to allow most "normal" URIs to display in full, but small enough to
89 * prevent the dialog from getting insanely wide.
91 #define MAX_URI_IN_DIALOG_LENGTH 60
93 static void cancel_activate_callback (gpointer callback_data
);
94 static void activate_activation_uris_ready_callback (GList
*files
,
95 gpointer callback_data
);
96 static void activation_mount_mountables (ActivateParameters
*parameters
);
97 static void activate_callback (GList
*files
,
98 gpointer callback_data
);
99 static void activation_mount_not_mounted (ActivateParameters
*parameters
);
104 static ApplicationLaunchParameters
*
105 application_launch_parameters_new (GAppInfo
*application
,
108 ApplicationLaunchParameters
*result
;
110 result
= g_new0 (ApplicationLaunchParameters
, 1);
111 result
->application
= g_object_ref (application
);
112 result
->files
= nautilus_file_list_copy (files
);
118 application_launch_parameters_free (ApplicationLaunchParameters
*parameters
)
120 g_object_unref (parameters
->application
);
121 nautilus_file_list_free (parameters
->files
);
127 filter_nautilus_handler (GList
*apps
)
130 GAppInfo
*application
;
135 application
= (GAppInfo
*) l
->data
;
138 id
= g_app_info_get_id (application
);
141 "nautilus-folder-handler.desktop") == 0) {
142 g_object_unref (application
);
143 apps
= g_list_delete_link (apps
, l
);
153 filter_non_uri_apps (GList
*apps
)
158 for (l
= apps
; l
!= NULL
; l
= next
) {
162 if (!g_app_info_supports_uris (app
)) {
163 apps
= g_list_delete_link (apps
, l
);
164 g_object_unref (app
);
172 nautilus_mime_actions_check_if_required_attributes_ready (NautilusFile
*file
)
174 NautilusFileAttributes attributes
;
177 attributes
= nautilus_mime_actions_get_required_file_attributes ();
178 ready
= nautilus_file_check_if_ready (file
, attributes
);
183 NautilusFileAttributes
184 nautilus_mime_actions_get_required_file_attributes (void)
186 return NAUTILUS_FILE_ATTRIBUTE_INFO
|
187 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
|
188 NAUTILUS_FILE_ATTRIBUTE_METADATA
;
192 file_has_local_path (NautilusFile
*file
)
199 /* Don't only check _is_native, because we want to support
200 using the fuse path */
201 location
= nautilus_file_get_location (file
);
202 if (g_file_is_native (location
)) {
205 path
= g_file_get_path (location
);
211 g_object_unref (location
);
217 nautilus_mime_get_default_application_for_file (NautilusFile
*file
)
223 if (!nautilus_mime_actions_check_if_required_attributes_ready (file
)) {
227 mime_type
= nautilus_file_get_mime_type (file
);
228 app
= g_app_info_get_default_for_type (mime_type
, !file_has_local_path (file
));
232 uri_scheme
= nautilus_file_get_uri_scheme (file
);
233 if (uri_scheme
!= NULL
) {
234 app
= g_app_info_get_default_for_uri_scheme (uri_scheme
);
243 file_compare_by_mime_type (NautilusFile
*file_a
,
244 NautilusFile
*file_b
)
246 char *mime_type_a
, *mime_type_b
;
249 mime_type_a
= nautilus_file_get_mime_type (file_a
);
250 mime_type_b
= nautilus_file_get_mime_type (file_b
);
252 ret
= strcmp (mime_type_a
, mime_type_b
);
254 g_free (mime_type_a
);
255 g_free (mime_type_b
);
261 file_compare_by_parent_uri (NautilusFile
*file_a
,
262 NautilusFile
*file_b
) {
263 char *parent_uri_a
, *parent_uri_b
;
266 parent_uri_a
= nautilus_file_get_parent_uri (file_a
);
267 parent_uri_b
= nautilus_file_get_parent_uri (file_b
);
269 ret
= strcmp (parent_uri_a
, parent_uri_b
);
271 g_free (parent_uri_a
);
272 g_free (parent_uri_b
);
278 application_compare_by_name (const GAppInfo
*app_a
,
279 const GAppInfo
*app_b
)
281 return g_utf8_collate (g_app_info_get_name ((GAppInfo
*)app_a
),
282 g_app_info_get_name ((GAppInfo
*)app_b
));
286 application_compare_by_id (const GAppInfo
*app_a
,
287 const GAppInfo
*app_b
)
289 const char *id_a
, *id_b
;
291 id_a
= g_app_info_get_id ((GAppInfo
*)app_a
);
292 id_b
= g_app_info_get_id ((GAppInfo
*)app_b
);
294 if (id_a
== NULL
&& id_b
== NULL
) {
295 if (g_app_info_equal ((GAppInfo
*)app_a
, (GAppInfo
*)app_b
)) {
298 if ((gsize
)app_a
< (gsize
) app_b
) {
313 return strcmp (id_a
, id_b
);
317 nautilus_mime_get_applications_for_file (NautilusFile
*file
)
322 GAppInfo
*uri_handler
;
324 if (!nautilus_mime_actions_check_if_required_attributes_ready (file
)) {
327 mime_type
= nautilus_file_get_mime_type (file
);
328 result
= g_app_info_get_all_for_type (mime_type
);
330 uri_scheme
= nautilus_file_get_uri_scheme (file
);
331 if (uri_scheme
!= NULL
) {
332 uri_handler
= g_app_info_get_default_for_uri_scheme (uri_scheme
);
334 result
= g_list_prepend (result
, uri_handler
);
339 if (!file_has_local_path (file
)) {
340 /* Filter out non-uri supporting apps */
341 result
= filter_non_uri_apps (result
);
344 result
= g_list_sort (result
, (GCompareFunc
) application_compare_by_name
);
347 return filter_nautilus_handler (result
);
351 nautilus_mime_has_any_applications_for_file (NautilusFile
*file
)
357 GAppInfo
*uri_handler
;
359 mime_type
= nautilus_file_get_mime_type (file
);
361 apps
= g_app_info_get_all_for_type (mime_type
);
363 uri_scheme
= nautilus_file_get_uri_scheme (file
);
364 if (uri_scheme
!= NULL
) {
365 uri_handler
= g_app_info_get_default_for_uri_scheme (uri_scheme
);
367 apps
= g_list_prepend (apps
, uri_handler
);
372 if (!file_has_local_path (file
)) {
373 /* Filter out non-uri supporting apps */
374 apps
= filter_non_uri_apps (apps
);
376 apps
= filter_nautilus_handler (apps
);
380 eel_g_object_list_free (apps
);
391 nautilus_mime_get_default_application_for_files (GList
*files
)
393 GList
*l
, *sorted_files
;
395 GAppInfo
*app
, *one_app
;
397 g_assert (files
!= NULL
);
399 sorted_files
= g_list_sort (g_list_copy (files
), (GCompareFunc
) file_compare_by_mime_type
);
402 for (l
= sorted_files
; l
!= NULL
; l
= l
->next
) {
406 file_compare_by_mime_type (file
, l
->prev
->data
) == 0 &&
407 file_compare_by_parent_uri (file
, l
->prev
->data
) == 0) {
411 one_app
= nautilus_mime_get_default_application_for_file (file
);
412 if (one_app
== NULL
|| (app
!= NULL
&& !g_app_info_equal (app
, one_app
))) {
414 g_object_unref (app
);
417 g_object_unref (one_app
);
426 g_object_unref (one_app
);
430 g_list_free (sorted_files
);
435 /* returns an intersection of two mime application lists,
436 * and returns a new list, freeing a, b and all applications
437 * that are not in the intersection set.
438 * The lists are assumed to be pre-sorted by their IDs */
440 intersect_application_lists (GList
*a
,
445 GAppInfo
*a_app
, *b_app
;
453 while (l
!= NULL
&& m
!= NULL
) {
454 a_app
= (GAppInfo
*) l
->data
;
455 b_app
= (GAppInfo
*) m
->data
;
457 cmp
= application_compare_by_id (a_app
, b_app
);
459 g_object_unref (b_app
);
461 } else if (cmp
< 0) {
462 g_object_unref (a_app
);
465 g_object_unref (b_app
);
466 ret
= g_list_prepend (ret
, a_app
);
472 g_list_foreach (l
, (GFunc
) g_object_unref
, NULL
);
473 g_list_foreach (m
, (GFunc
) g_object_unref
, NULL
);
478 return g_list_reverse (ret
);
482 nautilus_mime_get_applications_for_files (GList
*files
)
484 GList
*l
, *sorted_files
;
486 GList
*one_ret
, *ret
;
488 g_assert (files
!= NULL
);
490 sorted_files
= g_list_sort (g_list_copy (files
), (GCompareFunc
) file_compare_by_mime_type
);
493 for (l
= sorted_files
; l
!= NULL
; l
= l
->next
) {
497 file_compare_by_mime_type (file
, l
->prev
->data
) == 0 &&
498 file_compare_by_parent_uri (file
, l
->prev
->data
) == 0) {
502 one_ret
= nautilus_mime_get_applications_for_file (file
);
503 one_ret
= g_list_sort (one_ret
, (GCompareFunc
) application_compare_by_id
);
505 ret
= intersect_application_lists (ret
, one_ret
);
515 g_list_free (sorted_files
);
517 ret
= g_list_sort (ret
, (GCompareFunc
) application_compare_by_name
);
523 nautilus_mime_has_any_applications_for_files (GList
*files
)
525 GList
*l
, *sorted_files
;
529 g_assert (files
!= NULL
);
531 sorted_files
= g_list_sort (g_list_copy (files
), (GCompareFunc
) file_compare_by_mime_type
);
534 for (l
= sorted_files
; l
!= NULL
; l
= l
->next
) {
535 file
= NAUTILUS_FILE (l
->data
);
538 file_compare_by_mime_type (file
, l
->prev
->data
) == 0 &&
539 file_compare_by_parent_uri (file
, l
->prev
->data
) == 0) {
543 if (!nautilus_mime_has_any_applications_for_file (file
)) {
549 g_list_free (sorted_files
);
557 trash_or_delete_files (GtkWindow
*parent_window
,
559 gboolean delete_if_all_already_in_trash
)
565 for (node
= files
; node
!= NULL
; node
= node
->next
) {
566 locations
= g_list_prepend (locations
,
567 nautilus_file_get_location ((NautilusFile
*) node
->data
));
570 locations
= g_list_reverse (locations
);
572 nautilus_file_operations_trash_or_delete (locations
,
575 eel_g_object_list_free (locations
);
579 report_broken_symbolic_link (GtkWindow
*parent_window
, NautilusFile
*file
)
589 g_assert (nautilus_file_is_broken_symbolic_link (file
));
591 display_name
= nautilus_file_get_display_name (file
);
592 if (nautilus_file_is_in_trash (file
)) {
593 prompt
= g_strdup_printf (_("The Link \"%s\" is Broken."), display_name
);
595 prompt
= g_strdup_printf (_("The Link \"%s\" is Broken. Move it to Trash?"), display_name
);
597 g_free (display_name
);
599 target_path
= nautilus_file_get_symbolic_link_target_path (file
);
600 if (target_path
== NULL
) {
601 detail
= g_strdup (_("This link can't be used, because it has no target."));
603 detail
= g_strdup_printf (_("This link can't be used, because its target "
604 "\"%s\" doesn't exist."), target_path
);
607 if (nautilus_file_is_in_trash (file
)) {
608 eel_run_simple_dialog (GTK_WIDGET (parent_window
), FALSE
, GTK_MESSAGE_WARNING
,
609 prompt
, detail
, GTK_STOCK_CANCEL
, NULL
);
613 dialog
= eel_show_yes_no_dialog (prompt
, detail
, _("Mo_ve to Trash"), GTK_STOCK_CANCEL
,
616 gtk_dialog_set_default_response (dialog
, GTK_RESPONSE_YES
);
618 /* Make this modal to avoid problems with reffing the view & file
619 * to keep them around in case the view changes, which would then
620 * cause the old view not to be destroyed, which would cause its
621 * merged Bonobo items not to be un-merged. Maybe we need to unmerge
622 * explicitly when disconnecting views instead of relying on the
623 * unmerge in Destroy. But since BonoboUIHandler is probably going
624 * to change wildly, I don't want to mess with this now.
627 response
= gtk_dialog_run (dialog
);
628 gtk_object_destroy (GTK_OBJECT (dialog
));
630 if (response
== GTK_RESPONSE_YES
) {
631 file_as_list
.data
= file
;
632 file_as_list
.next
= NULL
;
633 file_as_list
.prev
= NULL
;
634 trash_or_delete_files (parent_window
, &file_as_list
, TRUE
);
639 g_free (target_path
);
643 static ActivationAction
644 get_executable_text_file_action (GtkWindow
*parent_window
, NautilusFile
*file
)
650 int preferences_value
;
653 g_assert (nautilus_file_contains_text (file
));
655 preferences_value
= eel_preferences_get_enum
656 (NAUTILUS_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION
);
657 switch (preferences_value
) {
658 case NAUTILUS_EXECUTABLE_TEXT_LAUNCH
:
659 return ACTIVATION_ACTION_LAUNCH
;
660 case NAUTILUS_EXECUTABLE_TEXT_DISPLAY
:
661 return ACTIVATION_ACTION_OPEN_IN_APPLICATION
;
662 case NAUTILUS_EXECUTABLE_TEXT_ASK
:
665 /* Complain non-fatally, since preference data can't be trusted */
666 g_warning ("Unknown value %d for NAUTILUS_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION",
672 file_name
= nautilus_file_get_display_name (file
);
673 prompt
= g_strdup_printf (_("Do you want to run \"%s\", or display its contents?"),
675 detail
= g_strdup_printf (_("\"%s\" is an executable text file."),
679 dialog
= eel_create_question_dialog (prompt
,
681 _("Run in _Terminal"), RESPONSE_RUN_IN_TERMINAL
,
682 _("_Display"), RESPONSE_DISPLAY
,
684 gtk_dialog_add_button (dialog
, GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
);
685 gtk_dialog_add_button (dialog
, _("_Run"), RESPONSE_RUN
);
686 gtk_dialog_set_default_response (dialog
, GTK_RESPONSE_CANCEL
);
687 gtk_widget_show (GTK_WIDGET (dialog
));
692 response
= gtk_dialog_run (dialog
);
693 gtk_object_destroy (GTK_OBJECT (dialog
));
697 return ACTIVATION_ACTION_LAUNCH
;
698 case RESPONSE_RUN_IN_TERMINAL
:
699 return ACTIVATION_ACTION_LAUNCH_IN_TERMINAL
;
700 case RESPONSE_DISPLAY
:
701 return ACTIVATION_ACTION_OPEN_IN_APPLICATION
;
703 return ACTIVATION_ACTION_DO_NOTHING
;
707 static ActivationAction
708 get_default_executable_text_file_action (void)
710 int preferences_value
;
712 preferences_value
= eel_preferences_get_enum
713 (NAUTILUS_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION
);
714 switch (preferences_value
) {
715 case NAUTILUS_EXECUTABLE_TEXT_LAUNCH
:
716 return ACTIVATION_ACTION_LAUNCH
;
717 case NAUTILUS_EXECUTABLE_TEXT_DISPLAY
:
718 return ACTIVATION_ACTION_OPEN_IN_APPLICATION
;
719 case NAUTILUS_EXECUTABLE_TEXT_ASK
:
721 return ACTIVATION_ACTION_ASK
;
726 nautilus_mime_file_opens_in_view (NautilusFile
*file
)
728 return (nautilus_file_is_directory (file
) ||
729 NAUTILUS_IS_DESKTOP_ICON_FILE (file
) ||
730 nautilus_file_is_nautilus_link (file
));
733 static ActivationAction
734 get_activation_action (NautilusFile
*file
)
736 ActivationAction action
;
737 char *activation_uri
;
739 if (nautilus_file_is_launcher (file
)) {
740 return ACTIVATION_ACTION_LAUNCH_DESKTOP_FILE
;
743 activation_uri
= nautilus_file_get_activation_uri (file
);
744 if (activation_uri
== NULL
) {
745 activation_uri
= nautilus_file_get_uri (file
);
748 action
= ACTIVATION_ACTION_DO_NOTHING
;
749 if (nautilus_file_is_launchable (file
)) {
750 char *executable_path
;
752 action
= ACTIVATION_ACTION_LAUNCH
;
754 executable_path
= g_filename_from_uri (activation_uri
, NULL
, NULL
);
755 if (!executable_path
) {
756 action
= ACTIVATION_ACTION_DO_NOTHING
;
757 } else if (nautilus_file_contains_text (file
)) {
758 action
= get_default_executable_text_file_action ();
760 g_free (executable_path
);
763 if (action
== ACTIVATION_ACTION_DO_NOTHING
) {
764 if (nautilus_mime_file_opens_in_view (file
)) {
765 action
= ACTIVATION_ACTION_OPEN_IN_VIEW
;
767 action
= ACTIVATION_ACTION_OPEN_IN_APPLICATION
;
770 g_free (activation_uri
);
776 nautilus_mime_file_opens_in_external_app (NautilusFile
*file
)
778 ActivationAction activation_action
;
780 activation_action
= get_activation_action (file
);
782 return (activation_action
== ACTIVATION_ACTION_OPEN_IN_APPLICATION
);
787 mime_application_hash (GAppInfo
*app
)
791 id
= g_app_info_get_id (app
);
794 return GPOINTER_TO_UINT(app
);
797 return g_str_hash (id
);
801 list_to_parameters_foreach (GAppInfo
*application
,
805 ApplicationLaunchParameters
*parameters
;
807 files
= g_list_reverse (files
);
809 parameters
= application_launch_parameters_new
810 (application
, files
);
811 *ret
= g_list_prepend (*ret
, parameters
);
816 * fm_directory_view_make_activation_parameters
818 * Construct a list of ApplicationLaunchParameters from a list of NautilusFiles,
819 * where files that have the same default application are put into the same
820 * launch parameter, and others are put into the unhandled_files list.
822 * @files: Files to use for construction.
823 * @unhandled_files: Files without any default application will be put here.
825 * Return value: Newly allocated list of ApplicationLaunchParameters.
828 fm_directory_view_make_activation_parameters (GList
*files
,
829 GList
**unhandled_files
)
831 GList
*ret
, *l
, *app_files
;
833 GAppInfo
*app
, *old_app
;
834 GHashTable
*app_table
;
837 *unhandled_files
= NULL
;
839 app_table
= g_hash_table_new_full
840 ((GHashFunc
) mime_application_hash
,
841 (GEqualFunc
) g_app_info_equal
,
842 (GDestroyNotify
) g_object_unref
,
843 (GDestroyNotify
) g_list_free
);
845 for (l
= files
; l
!= NULL
; l
= l
->next
) {
846 file
= NAUTILUS_FILE (l
->data
);
848 app
= nautilus_mime_get_default_application_for_file (file
);
852 if (g_hash_table_lookup_extended (app_table
, app
,
853 (gpointer
*) &old_app
,
854 (gpointer
*) &app_files
)) {
855 g_hash_table_steal (app_table
, old_app
);
857 app_files
= g_list_prepend (app_files
, file
);
859 g_object_unref (app
);
862 app_files
= g_list_prepend (NULL
, file
);
865 g_hash_table_insert (app_table
, app
, app_files
);
867 *unhandled_files
= g_list_prepend (*unhandled_files
, file
);
871 g_hash_table_foreach (app_table
,
872 (GHFunc
) list_to_parameters_foreach
,
875 g_hash_table_destroy (app_table
);
877 *unhandled_files
= g_list_reverse (*unhandled_files
);
879 return g_list_reverse (ret
);
883 file_was_cancelled (NautilusFile
*file
)
887 error
= nautilus_file_get_file_info_error (file
);
890 error
->domain
== G_IO_ERROR
&&
891 error
->code
== G_IO_ERROR_CANCELLED
;
895 file_was_not_mounted (NautilusFile
*file
)
899 error
= nautilus_file_get_file_info_error (file
);
902 error
->domain
== G_IO_ERROR
&&
903 error
->code
== G_IO_ERROR_NOT_MOUNTED
;
907 activation_parameters_free (ActivateParameters
*parameters
)
909 if (parameters
->timed_wait_active
) {
910 eel_timed_wait_stop (cancel_activate_callback
, parameters
);
913 if (parameters
->window_info
) {
914 g_object_remove_weak_pointer (G_OBJECT (parameters
->window_info
), (gpointer
*)¶meters
->window_info
);
916 if (parameters
->parent_window
) {
917 g_object_remove_weak_pointer (G_OBJECT (parameters
->parent_window
), (gpointer
*)¶meters
->parent_window
);
919 g_object_unref (parameters
->cancellable
);
920 nautilus_file_list_free (parameters
->files
);
921 nautilus_file_list_free (parameters
->mountables
);
922 nautilus_file_list_free (parameters
->not_mounted
);
923 g_free (parameters
->activation_directory
);
924 g_free (parameters
->timed_wait_prompt
);
925 g_assert (parameters
->files_handle
== NULL
);
930 cancel_activate_callback (gpointer callback_data
)
932 ActivateParameters
*parameters
= callback_data
;
934 parameters
->timed_wait_active
= FALSE
;
936 g_cancellable_cancel (parameters
->cancellable
);
938 if (parameters
->files_handle
) {
939 nautilus_file_list_cancel_call_when_ready (parameters
->files_handle
);
940 parameters
->files_handle
= NULL
;
941 activation_parameters_free (parameters
);
946 activation_start_timed_cancel (ActivateParameters
*parameters
)
948 parameters
->timed_wait_active
= TRUE
;
949 eel_timed_wait_start_with_duration
950 (DELAY_UNTIL_CANCEL_MSECS
,
951 cancel_activate_callback
,
953 parameters
->timed_wait_prompt
,
954 parameters
->parent_window
);
958 activate_mount_op_active (EelMountOperation
*operation
,
960 ActivateParameters
*parameters
)
963 if (parameters
->timed_wait_active
) {
964 eel_timed_wait_stop (cancel_activate_callback
, parameters
);
965 parameters
->timed_wait_active
= FALSE
;
968 if (!parameters
->timed_wait_active
) {
969 activation_start_timed_cancel (parameters
);
975 confirm_multiple_windows (GtkWindow
*parent_window
, int count
)
982 if (count
<= SILENT_WINDOW_OPEN_LIMIT
) {
986 prompt
= _("Are you sure you want to open all files?");
987 detail
= g_strdup_printf (ngettext("This will open %d separate window.",
988 "This will open %d separate windows.", count
), count
);
989 dialog
= eel_show_yes_no_dialog (prompt
, detail
,
990 GTK_STOCK_OK
, GTK_STOCK_CANCEL
,
994 response
= gtk_dialog_run (dialog
);
995 gtk_object_destroy (GTK_OBJECT (dialog
));
997 return response
== GTK_RESPONSE_YES
;
1001 activate_files (ActivateParameters
*parameters
)
1004 GList
*launch_desktop_files
;
1005 GList
*launch_files
;
1006 GList
*launch_in_terminal_files
;
1007 GList
*open_in_app_files
;
1008 GList
*open_in_app_parameters
;
1009 GList
*unhandled_open_in_app_files
;
1010 ApplicationLaunchParameters
*one_parameters
;
1011 GList
*open_in_view_files
;
1015 char *executable_path
, *quoted_path
, *name
;
1016 char *old_working_dir
;
1017 ActivationAction action
;
1020 screen
= gtk_widget_get_screen (GTK_WIDGET (parameters
->parent_window
));
1022 launch_desktop_files
= NULL
;
1023 launch_files
= NULL
;
1024 launch_in_terminal_files
= NULL
;
1025 open_in_app_files
= NULL
;
1026 open_in_view_files
= NULL
;
1028 for (l
= parameters
->files
; l
!= NULL
; l
= l
->next
) {
1029 file
= NAUTILUS_FILE (l
->data
);
1031 if (file_was_cancelled (file
)) {
1035 action
= get_activation_action (file
);
1036 if (action
== ACTIVATION_ACTION_ASK
) {
1037 /* Special case for executable text files, since it might be
1038 * dangerous & unexpected to launch these.
1040 action
= get_executable_text_file_action (parameters
->parent_window
, file
);
1044 case ACTIVATION_ACTION_LAUNCH_DESKTOP_FILE
:
1045 launch_desktop_files
= g_list_prepend (launch_desktop_files
, file
);
1047 case ACTIVATION_ACTION_LAUNCH
:
1048 launch_files
= g_list_prepend (launch_files
, file
);
1050 case ACTIVATION_ACTION_LAUNCH_IN_TERMINAL
:
1051 launch_in_terminal_files
= g_list_prepend (launch_in_terminal_files
, file
);
1053 case ACTIVATION_ACTION_OPEN_IN_VIEW
:
1054 open_in_view_files
= g_list_prepend (open_in_view_files
, file
);
1056 case ACTIVATION_ACTION_OPEN_IN_APPLICATION
:
1057 open_in_app_files
= g_list_prepend (open_in_app_files
, file
);
1059 case ACTIVATION_ACTION_DO_NOTHING
:
1061 case ACTIVATION_ACTION_ASK
:
1062 g_assert_not_reached ();
1067 launch_desktop_files
= g_list_reverse (launch_desktop_files
);
1068 for (l
= launch_desktop_files
; l
!= NULL
; l
= l
->next
) {
1069 file
= NAUTILUS_FILE (l
->data
);
1071 uri
= nautilus_file_get_uri (file
);
1072 nautilus_debug_log (FALSE
, NAUTILUS_DEBUG_LOG_DOMAIN_USER
,
1073 "directory view activate_callback launch_desktop_file window=%p: %s",
1074 parameters
->parent_window
, uri
);
1075 nautilus_launch_desktop_file (screen
, uri
, NULL
,
1076 parameters
->parent_window
);
1080 old_working_dir
= NULL
;
1081 if (parameters
->activation_directory
&&
1082 (launch_files
!= NULL
|| launch_in_terminal_files
!= NULL
)) {
1083 old_working_dir
= g_get_current_dir ();
1084 chdir (parameters
->activation_directory
);
1088 launch_files
= g_list_reverse (launch_files
);
1089 for (l
= launch_files
; l
!= NULL
; l
= l
->next
) {
1090 file
= NAUTILUS_FILE (l
->data
);
1092 uri
= nautilus_file_get_activation_uri (file
);
1093 executable_path
= g_filename_from_uri (uri
, NULL
, NULL
);
1094 quoted_path
= g_shell_quote (executable_path
);
1095 name
= nautilus_file_get_name (file
);
1097 nautilus_debug_log (FALSE
, NAUTILUS_DEBUG_LOG_DOMAIN_USER
,
1098 "directory view activate_callback launch_file window=%p: %s",
1099 parameters
->parent_window
, quoted_path
);
1101 nautilus_launch_application_from_command (screen
, name
, quoted_path
, NULL
, FALSE
);
1103 g_free (quoted_path
);
1104 g_free (executable_path
);
1109 launch_in_terminal_files
= g_list_reverse (launch_in_terminal_files
);
1110 for (l
= launch_in_terminal_files
; l
!= NULL
; l
= l
->next
) {
1111 file
= NAUTILUS_FILE (l
->data
);
1113 uri
= nautilus_file_get_activation_uri (file
);
1114 executable_path
= g_filename_from_uri (uri
, NULL
, NULL
);
1115 quoted_path
= g_shell_quote (executable_path
);
1116 name
= nautilus_file_get_name (file
);
1118 nautilus_debug_log (FALSE
, NAUTILUS_DEBUG_LOG_DOMAIN_USER
,
1119 "directory view activate_callback launch_in_terminal window=%p: %s",
1120 parameters
->parent_window
, quoted_path
);
1122 nautilus_launch_application_from_command (screen
, name
, quoted_path
, NULL
, TRUE
);
1124 g_free (quoted_path
);
1125 g_free (executable_path
);
1129 if (old_working_dir
!= NULL
) {
1130 chdir (old_working_dir
);
1131 g_free (old_working_dir
);
1134 open_in_view_files
= g_list_reverse (open_in_view_files
);
1135 count
= g_list_length (open_in_view_files
);
1136 if (parameters
->window_info
!= NULL
&&
1137 confirm_multiple_windows (parameters
->parent_window
, count
)) {
1138 NautilusWindowOpenFlags flags
;
1140 flags
= parameters
->flags
;
1142 flags
|= NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW
;
1145 for (l
= open_in_view_files
; l
!= NULL
; l
= l
->next
) {
1147 /* The ui should ask for navigation or object windows
1148 * depending on what the current one is */
1149 file
= NAUTILUS_FILE (l
->data
);
1151 uri
= nautilus_file_get_activation_uri (file
);
1152 f
= g_file_new_for_uri (uri
);
1153 nautilus_window_info_open_location (parameters
->window_info
,
1154 f
, parameters
->mode
, flags
, NULL
);
1160 open_in_app_parameters
= NULL
;
1161 unhandled_open_in_app_files
= NULL
;
1163 if (open_in_app_files
!= NULL
) {
1164 open_in_app_files
= g_list_reverse (open_in_app_files
);
1166 open_in_app_parameters
= fm_directory_view_make_activation_parameters
1167 (open_in_app_files
, &unhandled_open_in_app_files
);
1170 for (l
= open_in_app_parameters
; l
!= NULL
; l
= l
->next
) {
1171 one_parameters
= l
->data
;
1173 nautilus_launch_application (one_parameters
->application
,
1174 one_parameters
->files
,
1175 parameters
->parent_window
);
1176 application_launch_parameters_free (one_parameters
);
1179 for (l
= unhandled_open_in_app_files
; l
!= NULL
; l
= l
->next
) {
1181 char *full_uri_for_display
;
1182 char *uri_for_display
;
1183 char *error_message
;
1185 file
= NAUTILUS_FILE (l
->data
);
1187 location
= nautilus_file_get_location (file
);
1188 full_uri_for_display
= g_file_get_parse_name (location
);
1189 g_object_unref (location
);
1191 /* Truncate the URI so it doesn't get insanely wide. Note that even
1192 * though the dialog uses wrapped text, if the URI doesn't contain
1193 * white space then the text-wrapping code is too stupid to wrap it.
1195 uri_for_display
= eel_str_middle_truncate
1196 (full_uri_for_display
, MAX_URI_IN_DIALOG_LENGTH
);
1197 g_free (full_uri_for_display
);
1199 error_message
= g_strdup_printf (_("Couldn't display \"%s\"."),
1202 g_free (uri_for_display
);
1204 eel_show_error_dialog (error_message
,
1205 _("There is no application installed for this file type"),
1206 parameters
->parent_window
);
1207 g_free (error_message
);
1210 if (open_in_app_parameters
!= NULL
||
1211 unhandled_open_in_app_files
!= NULL
) {
1212 if ((parameters
->flags
& NAUTILUS_WINDOW_OPEN_FLAG_CLOSE_BEHIND
) != 0 &&
1213 parameters
->window_info
!= NULL
&&
1214 nautilus_window_info_get_window_type (parameters
->window_info
) == NAUTILUS_WINDOW_SPATIAL
) {
1215 nautilus_window_info_close (parameters
->window_info
);
1219 g_list_free (launch_desktop_files
);
1220 g_list_free (launch_files
);
1221 g_list_free (launch_in_terminal_files
);
1222 g_list_free (open_in_view_files
);
1223 g_list_free (open_in_app_files
);
1224 g_list_free (open_in_app_parameters
);
1225 g_list_free (unhandled_open_in_app_files
);
1227 activation_parameters_free (parameters
);
1231 activation_mount_not_mounted_callback (GObject
*source_object
,
1235 ActivateParameters
*parameters
= user_data
;
1239 file
= parameters
->not_mounted
->data
;
1242 if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object
), res
, &error
)) {
1243 if (error
->domain
!= G_IO_ERROR
||
1244 (error
->code
!= G_IO_ERROR_CANCELLED
&&
1245 error
->code
!= G_IO_ERROR_FAILED_HANDLED
&&
1246 error
->code
!= G_IO_ERROR_ALREADY_MOUNTED
)) {
1247 eel_show_error_dialog (_("Unable to mount location"),
1248 error
->message
, NULL
);
1251 if (error
->domain
!= G_IO_ERROR
||
1252 error
->code
!= G_IO_ERROR_ALREADY_MOUNTED
) {
1253 parameters
->files
= g_list_remove (parameters
->files
, file
);
1254 nautilus_file_unref (file
);
1257 g_error_free (error
);
1260 parameters
->not_mounted
= g_list_delete_link (parameters
->not_mounted
,
1261 parameters
->not_mounted
);
1262 nautilus_file_unref (file
);
1264 activation_mount_not_mounted (parameters
);
1268 activation_mount_not_mounted (ActivateParameters
*parameters
)
1272 GMountOperation
*mount_op
;
1274 if (parameters
->not_mounted
!= NULL
) {
1275 file
= parameters
->not_mounted
->data
;
1276 mount_op
= eel_mount_operation_new (parameters
->parent_window
);
1277 g_signal_connect (mount_op
, "active_changed", (GCallback
)activate_mount_op_active
, parameters
);
1278 location
= nautilus_file_get_location (file
);
1279 nautilus_inhibit_autorun_for_file (location
);
1280 g_file_mount_enclosing_volume (location
, 0, mount_op
, parameters
->cancellable
,
1281 activation_mount_not_mounted_callback
, parameters
);
1282 g_object_unref (location
);
1283 g_object_unref (mount_op
);
1287 parameters
->tried_mounting
= TRUE
;
1289 if (parameters
->files
== NULL
) {
1290 activation_parameters_free (parameters
);
1294 nautilus_file_list_call_when_ready
1296 nautilus_mime_actions_get_required_file_attributes () | NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
,
1297 ¶meters
->files_handle
,
1298 activate_callback
, parameters
);
1303 activate_callback (GList
*files
, gpointer callback_data
)
1305 ActivateParameters
*parameters
= callback_data
;
1309 parameters
->files_handle
= NULL
;
1311 for (l
= parameters
->files
; l
!= NULL
; l
= next
) {
1312 file
= NAUTILUS_FILE (l
->data
);
1315 if (file_was_cancelled (file
)) {
1316 nautilus_file_unref (file
);
1317 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1321 if (file_was_not_mounted (file
)) {
1322 if (parameters
->tried_mounting
) {
1323 nautilus_file_unref (file
);
1324 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1326 parameters
->not_mounted
= g_list_prepend (parameters
->not_mounted
,
1327 nautilus_file_ref (file
));
1334 if (parameters
->not_mounted
!= NULL
) {
1335 activation_mount_not_mounted (parameters
);
1337 activate_files (parameters
);
1342 activate_activation_uris_ready_callback (GList
*files_ignore
,
1343 gpointer callback_data
)
1345 ActivateParameters
*parameters
= callback_data
;
1349 parameters
->files_handle
= NULL
;
1351 for (l
= parameters
->files
; l
!= NULL
; l
= next
) {
1352 file
= NAUTILUS_FILE (l
->data
);
1355 if (file_was_cancelled (file
)) {
1356 nautilus_file_unref (file
);
1357 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1361 if (nautilus_file_is_broken_symbolic_link (file
)) {
1362 nautilus_file_unref (file
);
1363 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1364 report_broken_symbolic_link (parameters
->parent_window
, file
);
1368 if (nautilus_file_get_file_type (file
) == G_FILE_TYPE_MOUNTABLE
&&
1369 !nautilus_file_has_activation_uri (file
)) {
1370 /* Don't launch these... There is nothing we
1372 nautilus_file_unref (file
);
1373 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1379 if (parameters
->files
== NULL
) {
1380 activation_parameters_free (parameters
);
1384 /* Convert the files to the actual activation uri files */
1385 for (l
= parameters
->files
; l
!= NULL
; l
= l
->next
) {
1387 file
= NAUTILUS_FILE (l
->data
);
1389 /* We want the file for the activation URI since we care
1390 * about the attributes for that, not for the original file.
1392 uri
= nautilus_file_get_activation_uri (file
);
1394 NautilusFile
*actual_file
;
1396 actual_file
= nautilus_file_get_by_uri (uri
);
1397 if (actual_file
!= NULL
) {
1398 nautilus_file_unref (file
);
1399 l
->data
= actual_file
;
1406 /* get the parameters for the actual files */
1407 nautilus_file_list_call_when_ready
1409 nautilus_mime_actions_get_required_file_attributes () | NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
,
1410 ¶meters
->files_handle
,
1411 activate_callback
, parameters
);
1415 activation_get_activation_uris (ActivateParameters
*parameters
)
1420 /* link target info might be stale, re-read it */
1421 for (l
= parameters
->files
; l
!= NULL
; l
= l
->next
) {
1422 file
= NAUTILUS_FILE (l
->data
);
1424 if (file_was_cancelled (file
)) {
1425 nautilus_file_unref (file
);
1426 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1430 if (nautilus_file_is_symbolic_link (file
)) {
1431 nautilus_file_invalidate_attributes
1433 NAUTILUS_FILE_ATTRIBUTE_INFO
|
1434 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
);
1438 if (parameters
->files
== NULL
) {
1439 activation_parameters_free (parameters
);
1443 nautilus_file_list_call_when_ready
1445 NAUTILUS_FILE_ATTRIBUTE_INFO
|
1446 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
,
1447 ¶meters
->files_handle
,
1448 activate_activation_uris_ready_callback
, parameters
);
1453 activation_mountable_mounted (NautilusFile
*file
,
1454 GFile
*result_location
,
1456 gpointer callback_data
)
1458 ActivateParameters
*parameters
= callback_data
;
1459 NautilusFile
*target_file
;
1461 /* Remove from list of files that have to be mounted */
1462 parameters
->mountables
= g_list_remove (parameters
->mountables
, file
);
1463 nautilus_file_unref (file
);
1465 if (error
== NULL
) {
1466 /* Replace file with the result of the mount */
1468 target_file
= nautilus_file_get (result_location
);
1470 parameters
->files
= g_list_remove (parameters
->files
, file
);
1471 nautilus_file_unref (file
);
1473 parameters
->files
= g_list_prepend (parameters
->files
, target_file
);
1475 /* Remove failed file */
1477 if (error
->domain
!= G_IO_ERROR
||
1478 (error
->code
!= G_IO_ERROR_FAILED_HANDLED
&&
1479 error
->code
!= G_IO_ERROR_ALREADY_MOUNTED
)) {
1480 parameters
->files
= g_list_remove (parameters
->files
, file
);
1481 nautilus_file_unref (file
);
1484 if (error
->domain
!= G_IO_ERROR
||
1485 (error
->code
!= G_IO_ERROR_CANCELLED
&&
1486 error
->code
!= G_IO_ERROR_FAILED_HANDLED
&&
1487 error
->code
!= G_IO_ERROR_ALREADY_MOUNTED
)) {
1488 eel_show_error_dialog (_("Unable to mount location"),
1489 error
->message
, NULL
);
1492 if (error
->code
== G_IO_ERROR_CANCELLED
) {
1493 activation_parameters_free (parameters
);
1498 /* Mount more mountables */
1499 activation_mount_mountables (parameters
);
1504 activation_mount_mountables (ActivateParameters
*parameters
)
1507 GMountOperation
*mount_op
;
1509 if (parameters
->mountables
!= NULL
) {
1510 file
= parameters
->mountables
->data
;
1511 mount_op
= eel_mount_operation_new (parameters
->parent_window
);
1512 g_signal_connect (mount_op
, "active_changed", (GCallback
)activate_mount_op_active
, parameters
);
1513 nautilus_file_mount (file
,
1515 parameters
->cancellable
,
1516 activation_mountable_mounted
,
1518 g_object_unref (mount_op
);
1522 activation_get_activation_uris (parameters
);
1527 * fm_directory_view_activate_files:
1529 * Activate a list of files. Each one might launch with an application or
1530 * with a component. This is normally called only by subclasses.
1531 * @view: FMDirectoryView in question.
1532 * @files: A GList of NautilusFiles to activate.
1536 nautilus_mime_activate_files (GtkWindow
*parent_window
,
1537 NautilusWindowInfo
*window_info
,
1539 const char *launch_directory
,
1540 NautilusWindowOpenMode mode
,
1541 NautilusWindowOpenFlags flags
)
1543 ActivateParameters
*parameters
;
1549 if (files
== NULL
) {
1553 nautilus_debug_log_with_file_list (FALSE
, NAUTILUS_DEBUG_LOG_DOMAIN_USER
, files
,
1554 "fm_directory_view_activate_files window=%p",
1557 parameters
= g_new0 (ActivateParameters
, 1);
1558 parameters
->window_info
= window_info
;
1559 g_object_add_weak_pointer (G_OBJECT (parameters
->window_info
), (gpointer
*)¶meters
->window_info
);
1560 if (parent_window
) {
1561 parameters
->parent_window
= parent_window
;
1562 g_object_add_weak_pointer (G_OBJECT (parameters
->parent_window
), (gpointer
*)¶meters
->parent_window
);
1564 parameters
->cancellable
= g_cancellable_new ();
1565 parameters
->activation_directory
= g_strdup (launch_directory
);
1566 parameters
->files
= nautilus_file_list_copy (files
);
1567 parameters
->mode
= mode
;
1568 parameters
->flags
= flags
;
1570 file_count
= g_list_length (files
);
1571 if (file_count
== 1) {
1572 file_name
= nautilus_file_get_display_name (files
->data
);
1573 parameters
->timed_wait_prompt
= g_strdup_printf (_("Opening \"%s\"."), file_name
);
1576 parameters
->timed_wait_prompt
= g_strdup_printf (ngettext ("Opening %d item.",
1577 "Opening %d items.",
1583 for (l
= parameters
->files
; l
!= NULL
; l
= next
) {
1584 file
= NAUTILUS_FILE (l
->data
);
1587 if (nautilus_file_can_mount (file
)) {
1588 parameters
->mountables
= g_list_prepend (parameters
->mountables
,
1589 nautilus_file_ref (file
));
1593 activation_start_timed_cancel (parameters
);
1594 activation_mount_mountables (parameters
);
1598 * fm_directory_view_activate_file:
1600 * Activate a file in this view. This might involve switching the displayed
1601 * location for the current window, or launching an application.
1602 * @view: FMDirectoryView in question.
1603 * @file: A NautilusFile representing the file in this view to activate.
1604 * @use_new_window: Should this item be opened in a new window?
1609 nautilus_mime_activate_file (GtkWindow
*parent_window
,
1610 NautilusWindowInfo
*window_info
,
1612 const char *launch_directory
,
1613 NautilusWindowOpenMode mode
,
1614 NautilusWindowOpenFlags flags
)
1618 g_return_if_fail (NAUTILUS_IS_FILE (file
));
1620 files
= g_list_prepend (NULL
, file
);
1621 nautilus_mime_activate_files (parent_window
, window_info
, files
, launch_directory
, mode
, flags
);
1622 g_list_free (files
);