2008-05-05 Paolo Borelli <pborelli@katamail.com>
[nautilus.git] / libnautilus-private / nautilus-mime-actions.c
blob0d94e23e4b0e2a46d30a60581166a1b342c018a4
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>
25 #include <config.h>
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>
33 #include <string.h>
34 #include <unistd.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"
46 typedef enum {
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,
54 } ActivationAction;
56 typedef struct {
57 GAppInfo *application;
58 GList *files;
59 } ApplicationLaunchParameters;
61 typedef struct {
62 NautilusWindowInfo *window_info;
63 GtkWindow *parent_window;
64 GCancellable *cancellable;
65 GList *files;
66 GList *mountables;
67 GList *not_mounted;
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;
75 } ActivateParameters;
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,
106 GList *files)
108 ApplicationLaunchParameters *result;
110 result = g_new0 (ApplicationLaunchParameters, 1);
111 result->application = g_object_ref (application);
112 result->files = nautilus_file_list_copy (files);
114 return result;
117 static void
118 application_launch_parameters_free (ApplicationLaunchParameters *parameters)
120 g_object_unref (parameters->application);
121 nautilus_file_list_free (parameters->files);
123 g_free (parameters);
126 static GList*
127 filter_nautilus_handler (GList *apps)
129 GList *l, *next;
130 GAppInfo *application;
131 const char *id;
133 l = apps;
134 while (l != NULL) {
135 application = (GAppInfo *) l->data;
136 next = l->next;
138 id = g_app_info_get_id (application);
139 if (id != NULL &&
140 strcmp (id,
141 "nautilus-folder-handler.desktop") == 0) {
142 g_object_unref (application);
143 apps = g_list_delete_link (apps, l);
146 l = next;
149 return apps;
152 static GList*
153 filter_non_uri_apps (GList *apps)
155 GList *l, *next;
156 GAppInfo *app;
158 for (l = apps; l != NULL; l = next) {
159 app = l->data;
160 next = l->next;
162 if (!g_app_info_supports_uris (app)) {
163 apps = g_list_delete_link (apps, l);
164 g_object_unref (app);
167 return apps;
171 static gboolean
172 nautilus_mime_actions_check_if_required_attributes_ready (NautilusFile *file)
174 NautilusFileAttributes attributes;
175 gboolean ready;
177 attributes = nautilus_mime_actions_get_required_file_attributes ();
178 ready = nautilus_file_check_if_ready (file, attributes);
180 return ready;
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;
191 static gboolean
192 file_has_local_path (NautilusFile *file)
194 GFile *location;
195 char *path;
196 gboolean res;
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)) {
203 res = TRUE;
204 } else {
205 path = g_file_get_path (location);
207 res = path != NULL;
209 g_free (path);
211 g_object_unref (location);
213 return res;
216 GAppInfo *
217 nautilus_mime_get_default_application_for_file (NautilusFile *file)
219 GAppInfo *app;
220 char *mime_type;
221 char *uri_scheme;
223 if (!nautilus_mime_actions_check_if_required_attributes_ready (file)) {
224 return NULL;
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));
229 g_free (mime_type);
231 if (app == NULL) {
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);
235 g_free (uri_scheme);
239 return app;
242 static int
243 file_compare_by_mime_type (NautilusFile *file_a,
244 NautilusFile *file_b)
246 char *mime_type_a, *mime_type_b;
247 int ret;
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);
257 return ret;
260 static int
261 file_compare_by_parent_uri (NautilusFile *file_a,
262 NautilusFile *file_b) {
263 char *parent_uri_a, *parent_uri_b;
264 int ret;
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);
274 return ret;
277 static int
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));
285 static int
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)) {
296 return 0;
298 if ((gsize)app_a < (gsize) app_b) {
299 return -1;
301 return 1;
304 if (id_a == NULL) {
305 return -1;
308 if (id_b == NULL) {
309 return 1;
313 return strcmp (id_a, id_b);
316 GList *
317 nautilus_mime_get_applications_for_file (NautilusFile *file)
319 char *mime_type;
320 char *uri_scheme;
321 GList *result;
322 GAppInfo *uri_handler;
324 if (!nautilus_mime_actions_check_if_required_attributes_ready (file)) {
325 return NULL;
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);
333 if (uri_handler) {
334 result = g_list_prepend (result, uri_handler);
336 g_free (uri_scheme);
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);
345 g_free (mime_type);
347 return filter_nautilus_handler (result);
350 gboolean
351 nautilus_mime_has_any_applications_for_file (NautilusFile *file)
353 GList *apps;
354 char *mime_type;
355 gboolean result;
356 char *uri_scheme;
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);
366 if (uri_handler) {
367 apps = g_list_prepend (apps, uri_handler);
369 g_free (uri_scheme);
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);
378 if (apps) {
379 result = TRUE;
380 eel_g_object_list_free (apps);
381 } else {
382 result = FALSE;
385 g_free (mime_type);
387 return result;
390 GAppInfo *
391 nautilus_mime_get_default_application_for_files (GList *files)
393 GList *l, *sorted_files;
394 NautilusFile *file;
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);
401 app = NULL;
402 for (l = sorted_files; l != NULL; l = l->next) {
403 file = l->data;
405 if (l->prev &&
406 file_compare_by_mime_type (file, l->prev->data) == 0 &&
407 file_compare_by_parent_uri (file, l->prev->data) == 0) {
408 continue;
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))) {
413 if (app) {
414 g_object_unref (app);
416 if (one_app) {
417 g_object_unref (one_app);
419 app = NULL;
420 break;
423 if (app == NULL) {
424 app = one_app;
425 } else {
426 g_object_unref (one_app);
430 g_list_free (sorted_files);
432 return app;
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 */
439 static GList *
440 intersect_application_lists (GList *a,
441 GList *b)
443 GList *l, *m;
444 GList *ret;
445 GAppInfo *a_app, *b_app;
446 int cmp;
448 ret = NULL;
450 l = a;
451 m = b;
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);
458 if (cmp > 0) {
459 g_object_unref (b_app);
460 m = m->next;
461 } else if (cmp < 0) {
462 g_object_unref (a_app);
463 l = l->next;
464 } else {
465 g_object_unref (b_app);
466 ret = g_list_prepend (ret, a_app);
467 l = l->next;
468 m = m->next;
472 g_list_foreach (l, (GFunc) g_object_unref, NULL);
473 g_list_foreach (m, (GFunc) g_object_unref, NULL);
475 g_list_free (a);
476 g_list_free (b);
478 return g_list_reverse (ret);
481 GList *
482 nautilus_mime_get_applications_for_files (GList *files)
484 GList *l, *sorted_files;
485 NautilusFile *file;
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);
492 ret = NULL;
493 for (l = sorted_files; l != NULL; l = l->next) {
494 file = l->data;
496 if (l->prev &&
497 file_compare_by_mime_type (file, l->prev->data) == 0 &&
498 file_compare_by_parent_uri (file, l->prev->data) == 0) {
499 continue;
502 one_ret = nautilus_mime_get_applications_for_file (file);
503 one_ret = g_list_sort (one_ret, (GCompareFunc) application_compare_by_id);
504 if (ret != NULL) {
505 ret = intersect_application_lists (ret, one_ret);
506 } else {
507 ret = one_ret;
510 if (ret == NULL) {
511 break;
515 g_list_free (sorted_files);
517 ret = g_list_sort (ret, (GCompareFunc) application_compare_by_name);
519 return ret;
522 gboolean
523 nautilus_mime_has_any_applications_for_files (GList *files)
525 GList *l, *sorted_files;
526 NautilusFile *file;
527 gboolean ret;
529 g_assert (files != NULL);
531 sorted_files = g_list_sort (g_list_copy (files), (GCompareFunc) file_compare_by_mime_type);
533 ret = TRUE;
534 for (l = sorted_files; l != NULL; l = l->next) {
535 file = NAUTILUS_FILE (l->data);
537 if (l->prev &&
538 file_compare_by_mime_type (file, l->prev->data) == 0 &&
539 file_compare_by_parent_uri (file, l->prev->data) == 0) {
540 continue;
543 if (!nautilus_mime_has_any_applications_for_file (file)) {
544 ret = FALSE;
545 break;
549 g_list_free (sorted_files);
551 return ret;
556 static void
557 trash_or_delete_files (GtkWindow *parent_window,
558 const GList *files,
559 gboolean delete_if_all_already_in_trash)
561 GList *locations;
562 const GList *node;
564 locations = NULL;
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,
573 parent_window,
574 NULL, NULL);
575 eel_g_object_list_free (locations);
578 static void
579 report_broken_symbolic_link (GtkWindow *parent_window, NautilusFile *file)
581 char *target_path;
582 char *display_name;
583 char *prompt;
584 char *detail;
585 GtkDialog *dialog;
586 GList file_as_list;
587 int response;
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);
594 } else {
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."));
602 } else {
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);
610 goto out;
613 dialog = eel_show_yes_no_dialog (prompt, detail, _("Mo_ve to Trash"), GTK_STOCK_CANCEL,
614 parent_window);
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);
637 out:
638 g_free (prompt);
639 g_free (target_path);
640 g_free (detail);
643 static ActivationAction
644 get_executable_text_file_action (GtkWindow *parent_window, NautilusFile *file)
646 GtkDialog *dialog;
647 char *file_name;
648 char *prompt;
649 char *detail;
650 int preferences_value;
651 int response;
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:
663 break;
664 default:
665 /* Complain non-fatally, since preference data can't be trusted */
666 g_warning ("Unknown value %d for NAUTILUS_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION",
667 preferences_value);
672 file_name = nautilus_file_get_display_name (file);
673 prompt = g_strdup_printf (_("Do you want to run \"%s\", or display its contents?"),
674 file_name);
675 detail = g_strdup_printf (_("\"%s\" is an executable text file."),
676 file_name);
677 g_free (file_name);
679 dialog = eel_create_question_dialog (prompt,
680 detail,
681 _("Run in _Terminal"), RESPONSE_RUN_IN_TERMINAL,
682 _("_Display"), RESPONSE_DISPLAY,
683 parent_window);
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));
689 g_free (prompt);
690 g_free (detail);
692 response = gtk_dialog_run (dialog);
693 gtk_object_destroy (GTK_OBJECT (dialog));
695 switch (response) {
696 case RESPONSE_RUN:
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;
702 default:
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:
720 default:
721 return ACTIVATION_ACTION_ASK;
725 gboolean
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;
766 } else {
767 action = ACTIVATION_ACTION_OPEN_IN_APPLICATION;
770 g_free (activation_uri);
772 return action;
775 gboolean
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);
786 static unsigned int
787 mime_application_hash (GAppInfo *app)
789 const char *id;
791 id = g_app_info_get_id (app);
793 if (id == NULL) {
794 return GPOINTER_TO_UINT(app);
797 return g_str_hash (id);
800 static void
801 list_to_parameters_foreach (GAppInfo *application,
802 GList *files,
803 GList **ret)
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.
827 static GList *
828 fm_directory_view_make_activation_parameters (GList *files,
829 GList **unhandled_files)
831 GList *ret, *l, *app_files;
832 NautilusFile *file;
833 GAppInfo *app, *old_app;
834 GHashTable *app_table;
836 ret = NULL;
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);
849 if (app != NULL) {
850 app_files = NULL;
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);
860 app = old_app;
861 } else {
862 app_files = g_list_prepend (NULL, file);
865 g_hash_table_insert (app_table, app, app_files);
866 } else {
867 *unhandled_files = g_list_prepend (*unhandled_files, file);
871 g_hash_table_foreach (app_table,
872 (GHFunc) list_to_parameters_foreach,
873 &ret);
875 g_hash_table_destroy (app_table);
877 *unhandled_files = g_list_reverse (*unhandled_files);
879 return g_list_reverse (ret);
882 static gboolean
883 file_was_cancelled (NautilusFile *file)
885 GError *error;
887 error = nautilus_file_get_file_info_error (file);
888 return
889 error != NULL &&
890 error->domain == G_IO_ERROR &&
891 error->code == G_IO_ERROR_CANCELLED;
894 static gboolean
895 file_was_not_mounted (NautilusFile *file)
897 GError *error;
899 error = nautilus_file_get_file_info_error (file);
900 return
901 error != NULL &&
902 error->domain == G_IO_ERROR &&
903 error->code == G_IO_ERROR_NOT_MOUNTED;
906 static void
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 *)&parameters->window_info);
916 if (parameters->parent_window) {
917 g_object_remove_weak_pointer (G_OBJECT (parameters->parent_window), (gpointer *)&parameters->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);
926 g_free (parameters);
929 static void
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);
945 static void
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,
952 parameters,
953 parameters->timed_wait_prompt,
954 parameters->parent_window);
957 static void
958 activate_mount_op_active (EelMountOperation *operation,
959 gboolean is_active,
960 ActivateParameters *parameters)
962 if (is_active) {
963 if (parameters->timed_wait_active) {
964 eel_timed_wait_stop (cancel_activate_callback, parameters);
965 parameters->timed_wait_active = FALSE;
967 } else {
968 if (!parameters->timed_wait_active) {
969 activation_start_timed_cancel (parameters);
974 static gboolean
975 confirm_multiple_windows (GtkWindow *parent_window, int count)
977 GtkDialog *dialog;
978 char *prompt;
979 char *detail;
980 int response;
982 if (count <= SILENT_WINDOW_OPEN_LIMIT) {
983 return TRUE;
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,
991 parent_window);
992 g_free (detail);
994 response = gtk_dialog_run (dialog);
995 gtk_object_destroy (GTK_OBJECT (dialog));
997 return response == GTK_RESPONSE_YES;
1000 static void
1001 activate_files (ActivateParameters *parameters)
1003 NautilusFile *file;
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;
1012 GList *l;
1013 int count;
1014 char *uri;
1015 char *executable_path, *quoted_path, *name;
1016 char *old_working_dir;
1017 ActivationAction action;
1018 GdkScreen *screen;
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)) {
1032 continue;
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);
1043 switch (action) {
1044 case ACTIVATION_ACTION_LAUNCH_DESKTOP_FILE :
1045 launch_desktop_files = g_list_prepend (launch_desktop_files, file);
1046 break;
1047 case ACTIVATION_ACTION_LAUNCH :
1048 launch_files = g_list_prepend (launch_files, file);
1049 break;
1050 case ACTIVATION_ACTION_LAUNCH_IN_TERMINAL :
1051 launch_in_terminal_files = g_list_prepend (launch_in_terminal_files, file);
1052 break;
1053 case ACTIVATION_ACTION_OPEN_IN_VIEW :
1054 open_in_view_files = g_list_prepend (open_in_view_files, file);
1055 break;
1056 case ACTIVATION_ACTION_OPEN_IN_APPLICATION :
1057 open_in_app_files = g_list_prepend (open_in_app_files, file);
1058 break;
1059 case ACTIVATION_ACTION_DO_NOTHING :
1060 break;
1061 case ACTIVATION_ACTION_ASK :
1062 g_assert_not_reached ();
1063 break;
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);
1077 g_free (uri);
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);
1102 g_free (name);
1103 g_free (quoted_path);
1104 g_free (executable_path);
1105 g_free (uri);
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);
1123 g_free (name);
1124 g_free (quoted_path);
1125 g_free (executable_path);
1126 g_free (uri);
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;
1141 if (count > 1) {
1142 flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW;
1145 for (l = open_in_view_files; l != NULL; l = l->next) {
1146 GFile *f;
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);
1155 g_object_unref (f);
1156 g_free (uri);
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) {
1180 GFile *location;
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\"."),
1200 uri_for_display);
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);
1230 static void
1231 activation_mount_not_mounted_callback (GObject *source_object,
1232 GAsyncResult *res,
1233 gpointer user_data)
1235 ActivateParameters *parameters = user_data;
1236 GError *error;
1237 NautilusFile *file;
1238 GFile *location;
1240 file = parameters->not_mounted->data;
1242 error = NULL;
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);
1259 } else {
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);
1271 static void
1272 activation_mount_not_mounted (ActivateParameters *parameters)
1274 NautilusFile *file;
1275 GFile *location;
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);
1287 return;
1290 parameters->tried_mounting = TRUE;
1292 if (parameters->files == NULL) {
1293 activation_parameters_free (parameters);
1294 return;
1297 nautilus_file_list_call_when_ready
1298 (parameters->files,
1299 nautilus_mime_actions_get_required_file_attributes () | NAUTILUS_FILE_ATTRIBUTE_LINK_INFO,
1300 &parameters->files_handle,
1301 activate_callback, parameters);
1305 static void
1306 activate_callback (GList *files, gpointer callback_data)
1308 ActivateParameters *parameters = callback_data;
1309 GList *l, *next;
1310 NautilusFile *file;
1312 parameters->files_handle = NULL;
1314 for (l = parameters->files; l != NULL; l = next) {
1315 file = NAUTILUS_FILE (l->data);
1316 next = l->next;
1318 if (file_was_cancelled (file)) {
1319 nautilus_file_unref (file);
1320 parameters->files = g_list_delete_link (parameters->files, l);
1321 continue;
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);
1328 } else {
1329 parameters->not_mounted = g_list_prepend (parameters->not_mounted,
1330 nautilus_file_ref (file));
1332 continue;
1337 if (parameters->not_mounted != NULL) {
1338 activation_mount_not_mounted (parameters);
1339 } else {
1340 activate_files (parameters);
1344 static void
1345 activate_activation_uris_ready_callback (GList *files_ignore,
1346 gpointer callback_data)
1348 ActivateParameters *parameters = callback_data;
1349 GList *l, *next;
1350 NautilusFile *file;
1352 parameters->files_handle = NULL;
1354 for (l = parameters->files; l != NULL; l = next) {
1355 file = NAUTILUS_FILE (l->data);
1356 next = l->next;
1358 if (file_was_cancelled (file)) {
1359 nautilus_file_unref (file);
1360 parameters->files = g_list_delete_link (parameters->files, l);
1361 continue;
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);
1368 continue;
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
1374 can do */
1375 nautilus_file_unref (file);
1376 parameters->files = g_list_delete_link (parameters->files, l);
1377 continue;
1382 if (parameters->files == NULL) {
1383 activation_parameters_free (parameters);
1384 return;
1387 /* Convert the files to the actual activation uri files */
1388 for (l = parameters->files; l != NULL; l = l->next) {
1389 char *uri;
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);
1396 if (uri != NULL) {
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;
1405 g_free (uri);
1409 /* get the parameters for the actual files */
1410 nautilus_file_list_call_when_ready
1411 (parameters->files,
1412 nautilus_mime_actions_get_required_file_attributes () | NAUTILUS_FILE_ATTRIBUTE_LINK_INFO,
1413 &parameters->files_handle,
1414 activate_callback, parameters);
1417 static void
1418 activation_get_activation_uris (ActivateParameters *parameters)
1420 GList *l;
1421 NautilusFile *file;
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);
1430 continue;
1433 if (nautilus_file_is_symbolic_link (file)) {
1434 nautilus_file_invalidate_attributes
1435 (file,
1436 NAUTILUS_FILE_ATTRIBUTE_INFO |
1437 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO);
1441 if (parameters->files == NULL) {
1442 activation_parameters_free (parameters);
1443 return;
1446 nautilus_file_list_call_when_ready
1447 (parameters->files,
1448 NAUTILUS_FILE_ATTRIBUTE_INFO |
1449 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO,
1450 &parameters->files_handle,
1451 activate_activation_uris_ready_callback, parameters);
1455 static void
1456 activation_mountable_mounted (NautilusFile *file,
1457 GFile *result_location,
1458 GError *error,
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);
1477 } else {
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);
1497 return;
1501 /* Mount more mountables */
1502 activation_mount_mountables (parameters);
1506 static void
1507 activation_mount_mountables (ActivateParameters *parameters)
1509 NautilusFile *file;
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,
1517 mount_op,
1518 parameters->cancellable,
1519 activation_mountable_mounted,
1520 parameters);
1521 g_object_unref (mount_op);
1522 return;
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.
1538 void
1539 nautilus_mime_activate_files (GtkWindow *parent_window,
1540 NautilusWindowInfo *window_info,
1541 GList *files,
1542 const char *launch_directory,
1543 NautilusWindowOpenMode mode,
1544 NautilusWindowOpenFlags flags)
1546 ActivateParameters *parameters;
1547 char *file_name;
1548 int file_count;
1549 GList *l, *next;
1550 NautilusFile *file;
1552 if (files == NULL) {
1553 return;
1556 nautilus_debug_log_with_file_list (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER, files,
1557 "fm_directory_view_activate_files window=%p",
1558 parent_window);
1560 parameters = g_new0 (ActivateParameters, 1);
1561 parameters->window_info = window_info;
1562 g_object_add_weak_pointer (G_OBJECT (parameters->window_info), (gpointer *)&parameters->window_info);
1563 if (parent_window) {
1564 parameters->parent_window = parent_window;
1565 g_object_add_weak_pointer (G_OBJECT (parameters->parent_window), (gpointer *)&parameters->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);
1577 g_free (file_name);
1578 } else {
1579 parameters->timed_wait_prompt = g_strdup_printf (ngettext ("Opening %d item.",
1580 "Opening %d items.",
1581 file_count),
1582 file_count);
1586 for (l = parameters->files; l != NULL; l = next) {
1587 file = NAUTILUS_FILE (l->data);
1588 next = l->next;
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?
1611 void
1612 nautilus_mime_activate_file (GtkWindow *parent_window,
1613 NautilusWindowInfo *window_info,
1614 NautilusFile *file,
1615 const char *launch_directory,
1616 NautilusWindowOpenMode mode,
1617 NautilusWindowOpenFlags flags)
1619 GList *files;
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);