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 cannot be used, because it has no target."));
603 detail
= g_strdup_printf (_("This link cannot 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 (_("Could not 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
;
1240 file
= parameters
->not_mounted
->data
;
1243 if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object
), res
, &error
)) {
1244 if (error
->domain
!= G_IO_ERROR
||
1245 (error
->code
!= G_IO_ERROR_CANCELLED
&&
1246 error
->code
!= G_IO_ERROR_FAILED_HANDLED
&&
1247 error
->code
!= G_IO_ERROR_ALREADY_MOUNTED
)) {
1248 eel_show_error_dialog (_("Unable to mount location"),
1249 error
->message
, NULL
);
1252 if (error
->domain
!= G_IO_ERROR
||
1253 error
->code
!= G_IO_ERROR_ALREADY_MOUNTED
) {
1254 parameters
->files
= g_list_remove (parameters
->files
, file
);
1255 nautilus_file_unref (file
);
1258 g_error_free (error
);
1260 location
= nautilus_file_get_location (file
);
1261 g_object_unref (G_OBJECT (location
));
1264 parameters
->not_mounted
= g_list_delete_link (parameters
->not_mounted
,
1265 parameters
->not_mounted
);
1266 nautilus_file_unref (file
);
1268 activation_mount_not_mounted (parameters
);
1272 activation_mount_not_mounted (ActivateParameters
*parameters
)
1276 GMountOperation
*mount_op
;
1278 if (parameters
->not_mounted
!= NULL
) {
1279 file
= parameters
->not_mounted
->data
;
1280 mount_op
= eel_mount_operation_new (parameters
->parent_window
);
1281 g_signal_connect (mount_op
, "active_changed", (GCallback
)activate_mount_op_active
, parameters
);
1282 location
= nautilus_file_get_location (file
);
1283 g_file_mount_enclosing_volume (location
, 0, mount_op
, parameters
->cancellable
,
1284 activation_mount_not_mounted_callback
, parameters
);
1285 g_object_unref (location
);
1286 g_object_unref (mount_op
);
1290 parameters
->tried_mounting
= TRUE
;
1292 if (parameters
->files
== NULL
) {
1293 activation_parameters_free (parameters
);
1297 nautilus_file_list_call_when_ready
1299 nautilus_mime_actions_get_required_file_attributes () | NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
,
1300 ¶meters
->files_handle
,
1301 activate_callback
, parameters
);
1306 activate_callback (GList
*files
, gpointer callback_data
)
1308 ActivateParameters
*parameters
= callback_data
;
1312 parameters
->files_handle
= NULL
;
1314 for (l
= parameters
->files
; l
!= NULL
; l
= next
) {
1315 file
= NAUTILUS_FILE (l
->data
);
1318 if (file_was_cancelled (file
)) {
1319 nautilus_file_unref (file
);
1320 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1324 if (file_was_not_mounted (file
)) {
1325 if (parameters
->tried_mounting
) {
1326 nautilus_file_unref (file
);
1327 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1329 parameters
->not_mounted
= g_list_prepend (parameters
->not_mounted
,
1330 nautilus_file_ref (file
));
1337 if (parameters
->not_mounted
!= NULL
) {
1338 activation_mount_not_mounted (parameters
);
1340 activate_files (parameters
);
1345 activate_activation_uris_ready_callback (GList
*files_ignore
,
1346 gpointer callback_data
)
1348 ActivateParameters
*parameters
= callback_data
;
1352 parameters
->files_handle
= NULL
;
1354 for (l
= parameters
->files
; l
!= NULL
; l
= next
) {
1355 file
= NAUTILUS_FILE (l
->data
);
1358 if (file_was_cancelled (file
)) {
1359 nautilus_file_unref (file
);
1360 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1364 if (nautilus_file_is_broken_symbolic_link (file
)) {
1365 nautilus_file_unref (file
);
1366 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1367 report_broken_symbolic_link (parameters
->parent_window
, file
);
1371 if (nautilus_file_get_file_type (file
) == G_FILE_TYPE_MOUNTABLE
&&
1372 !nautilus_file_has_activation_uri (file
)) {
1373 /* Don't launch these... There is nothing we
1375 nautilus_file_unref (file
);
1376 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1382 if (parameters
->files
== NULL
) {
1383 activation_parameters_free (parameters
);
1387 /* Convert the files to the actual activation uri files */
1388 for (l
= parameters
->files
; l
!= NULL
; l
= l
->next
) {
1390 file
= NAUTILUS_FILE (l
->data
);
1392 /* We want the file for the activation URI since we care
1393 * about the attributes for that, not for the original file.
1395 uri
= nautilus_file_get_activation_uri (file
);
1397 NautilusFile
*actual_file
;
1399 actual_file
= nautilus_file_get_by_uri (uri
);
1400 if (actual_file
!= NULL
) {
1401 nautilus_file_unref (file
);
1402 l
->data
= actual_file
;
1409 /* get the parameters for the actual files */
1410 nautilus_file_list_call_when_ready
1412 nautilus_mime_actions_get_required_file_attributes () | NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
,
1413 ¶meters
->files_handle
,
1414 activate_callback
, parameters
);
1418 activation_get_activation_uris (ActivateParameters
*parameters
)
1423 /* link target info might be stale, re-read it */
1424 for (l
= parameters
->files
; l
!= NULL
; l
= l
->next
) {
1425 file
= NAUTILUS_FILE (l
->data
);
1427 if (file_was_cancelled (file
)) {
1428 nautilus_file_unref (file
);
1429 parameters
->files
= g_list_delete_link (parameters
->files
, l
);
1433 if (nautilus_file_is_symbolic_link (file
)) {
1434 nautilus_file_invalidate_attributes
1436 NAUTILUS_FILE_ATTRIBUTE_INFO
|
1437 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
);
1441 if (parameters
->files
== NULL
) {
1442 activation_parameters_free (parameters
);
1446 nautilus_file_list_call_when_ready
1448 NAUTILUS_FILE_ATTRIBUTE_INFO
|
1449 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
,
1450 ¶meters
->files_handle
,
1451 activate_activation_uris_ready_callback
, parameters
);
1456 activation_mountable_mounted (NautilusFile
*file
,
1457 GFile
*result_location
,
1459 gpointer callback_data
)
1461 ActivateParameters
*parameters
= callback_data
;
1462 NautilusFile
*target_file
;
1464 /* Remove from list of files that have to be mounted */
1465 parameters
->mountables
= g_list_remove (parameters
->mountables
, file
);
1466 nautilus_file_unref (file
);
1468 if (error
== NULL
) {
1469 /* Replace file with the result of the mount */
1471 target_file
= nautilus_file_get (result_location
);
1473 parameters
->files
= g_list_remove (parameters
->files
, file
);
1474 nautilus_file_unref (file
);
1476 parameters
->files
= g_list_prepend (parameters
->files
, target_file
);
1478 /* Remove failed file */
1480 if (error
->domain
!= G_IO_ERROR
||
1481 (error
->code
!= G_IO_ERROR_FAILED_HANDLED
&&
1482 error
->code
!= G_IO_ERROR_ALREADY_MOUNTED
)) {
1483 parameters
->files
= g_list_remove (parameters
->files
, file
);
1484 nautilus_file_unref (file
);
1487 if (error
->domain
!= G_IO_ERROR
||
1488 (error
->code
!= G_IO_ERROR_CANCELLED
&&
1489 error
->code
!= G_IO_ERROR_FAILED_HANDLED
&&
1490 error
->code
!= G_IO_ERROR_ALREADY_MOUNTED
)) {
1491 eel_show_error_dialog (_("Unable to mount location"),
1492 error
->message
, NULL
);
1495 if (error
->code
== G_IO_ERROR_CANCELLED
) {
1496 activation_parameters_free (parameters
);
1501 /* Mount more mountables */
1502 activation_mount_mountables (parameters
);
1507 activation_mount_mountables (ActivateParameters
*parameters
)
1510 GMountOperation
*mount_op
;
1512 if (parameters
->mountables
!= NULL
) {
1513 file
= parameters
->mountables
->data
;
1514 mount_op
= eel_mount_operation_new (parameters
->parent_window
);
1515 g_signal_connect (mount_op
, "active_changed", (GCallback
)activate_mount_op_active
, parameters
);
1516 nautilus_file_mount (file
,
1518 parameters
->cancellable
,
1519 activation_mountable_mounted
,
1521 g_object_unref (mount_op
);
1525 activation_get_activation_uris (parameters
);
1530 * fm_directory_view_activate_files:
1532 * Activate a list of files. Each one might launch with an application or
1533 * with a component. This is normally called only by subclasses.
1534 * @view: FMDirectoryView in question.
1535 * @files: A GList of NautilusFiles to activate.
1539 nautilus_mime_activate_files (GtkWindow
*parent_window
,
1540 NautilusWindowInfo
*window_info
,
1542 const char *launch_directory
,
1543 NautilusWindowOpenMode mode
,
1544 NautilusWindowOpenFlags flags
)
1546 ActivateParameters
*parameters
;
1552 if (files
== NULL
) {
1556 nautilus_debug_log_with_file_list (FALSE
, NAUTILUS_DEBUG_LOG_DOMAIN_USER
, files
,
1557 "fm_directory_view_activate_files window=%p",
1560 parameters
= g_new0 (ActivateParameters
, 1);
1561 parameters
->window_info
= window_info
;
1562 g_object_add_weak_pointer (G_OBJECT (parameters
->window_info
), (gpointer
*)¶meters
->window_info
);
1563 if (parent_window
) {
1564 parameters
->parent_window
= parent_window
;
1565 g_object_add_weak_pointer (G_OBJECT (parameters
->parent_window
), (gpointer
*)¶meters
->parent_window
);
1567 parameters
->cancellable
= g_cancellable_new ();
1568 parameters
->activation_directory
= g_strdup (launch_directory
);
1569 parameters
->files
= nautilus_file_list_copy (files
);
1570 parameters
->mode
= mode
;
1571 parameters
->flags
= flags
;
1573 file_count
= g_list_length (files
);
1574 if (file_count
== 1) {
1575 file_name
= nautilus_file_get_display_name (files
->data
);
1576 parameters
->timed_wait_prompt
= g_strdup_printf (_("Opening \"%s\"."), file_name
);
1579 parameters
->timed_wait_prompt
= g_strdup_printf (ngettext ("Opening %d item.",
1580 "Opening %d items.",
1586 for (l
= parameters
->files
; l
!= NULL
; l
= next
) {
1587 file
= NAUTILUS_FILE (l
->data
);
1590 if (nautilus_file_can_mount (file
)) {
1591 parameters
->mountables
= g_list_prepend (parameters
->mountables
,
1592 nautilus_file_ref (file
));
1596 activation_start_timed_cancel (parameters
);
1597 activation_mount_mountables (parameters
);
1601 * fm_directory_view_activate_file:
1603 * Activate a file in this view. This might involve switching the displayed
1604 * location for the current window, or launching an application.
1605 * @view: FMDirectoryView in question.
1606 * @file: A NautilusFile representing the file in this view to activate.
1607 * @use_new_window: Should this item be opened in a new window?
1612 nautilus_mime_activate_file (GtkWindow
*parent_window
,
1613 NautilusWindowInfo
*window_info
,
1615 const char *launch_directory
,
1616 NautilusWindowOpenMode mode
,
1617 NautilusWindowOpenFlags flags
)
1621 g_return_if_fail (NAUTILUS_IS_FILE (file
));
1623 files
= g_list_prepend (NULL
, file
);
1624 nautilus_mime_activate_files (parent_window
, window_info
, files
, launch_directory
, mode
, flags
);
1625 g_list_free (files
);