summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog38
-rw-r--r--libnautilus-private/nautilus-mime-actions.c151
-rw-r--r--libnautilus-private/nautilus-mime-actions.h5
-rw-r--r--libnautilus-private/nautilus-program-choosing.c79
-rw-r--r--libnautilus-private/nautilus-program-choosing.h2
-rw-r--r--src/file-manager/fm-directory-view.c400
-rw-r--r--src/nautilus-information-panel.c6
7 files changed, 531 insertions, 150 deletions
diff --git a/ChangeLog b/ChangeLog
index a82c4743d..c32ff3627 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,41 @@
+2006-01-11 Christian Neumair <chris@gnome-de.org>
+
+ * libnautilus-private/nautilus-mime-actions.c:
+ (nautilus_mime_get_default_application_for_files),
+ (intersect_application_lists),
+ (nautilus_mime_get_open_with_applications_for_files),
+ (nautilus_mime_has_any_applications_for_files):
+ * libnautilus-private/nautilus-mime-actions.h:
+ Add file list helpers for getting associated applications.
+
+ * libnautilus-private/nautilus-program-choosing.c:
+ * libnautilus-private/nautilus-program-choosing.h:
+ (nautilus_launch_application):
+ Allow to pass multiple files per application launch.
+
+ * src/nautilus-information-panel.c:
+ (command_button_callback):
+ Port to new API.
+
+ * src/file-manager/fm-directory-view.c:
+ (application_launch_parameters_new),
+ (application_launch_parameters_free),
+ (fm_directory_view_launch_application),
+ (fm_directory_view_chose_application_callback),
+ (application_selected_cb),
+ (open_with_launch_application_callback),
+ (add_application_to_open_with_menu), (reset_open_with_menu),
+ (real_update_menus), (list_to_parameters_foreach),
+ (mime_application_hash),
+ (fm_directory_view_make_activation_parameters),
+ (activate_callback):
+ Support activation of multiple files at once, correctly figure out
+ their associated applications. Fixes #105653.
+
+ * src/file-manager/fm-directory-view.c:
+ (activate_callback):
+ ref/unref the view before/after operating on it. Fixes #326231.
+
2006-01-11 Ryan Lortie <desrt@desrt.ca>
* src/nautilus-location-entry.c (try_to_expand_path): Use strlen()
diff --git a/libnautilus-private/nautilus-mime-actions.c b/libnautilus-private/nautilus-mime-actions.c
index 723c78e76..3915ec035 100644
--- a/libnautilus-private/nautilus-mime-actions.c
+++ b/libnautilus-private/nautilus-mime-actions.c
@@ -233,3 +233,154 @@ nautilus_mime_has_any_applications_for_file (NautilusFile *file)
return result;
}
+
+GnomeVFSMimeApplication *
+nautilus_mime_get_default_application_for_files (GList *files)
+{
+ GList *l;
+ NautilusFile *file;
+ GnomeVFSMimeApplication *app, *one_app;
+
+ g_assert (files != NULL);
+
+ app = NULL;
+ for (l = files; l != NULL; l = l->next) {
+ file = l->data;
+
+ one_app = nautilus_mime_get_default_application_for_file (file);
+ if (one_app == NULL || (app != NULL && !gnome_vfs_mime_application_equal (app, one_app))) {
+ gnome_vfs_mime_application_free (app);
+ gnome_vfs_mime_application_free (one_app);
+ app = NULL;
+ break;
+ }
+
+ if (app == NULL) {
+ app = one_app;
+ } else {
+ gnome_vfs_mime_application_free (one_app);
+ }
+ }
+
+ return app;
+}
+
+/* returns an intersection of two mime application lists,
+ * and returns a new list, freeing a, b and all applications
+ * that are not in the intersection set.
+ * The lists are assumed to be pre-sorted by their IDs */
+static GList *
+intersect_application_lists (GList *a,
+ GList *b)
+{
+ GList *l, *m;
+ GList *ret;
+ GnomeVFSMimeApplication *a_app, *b_app;
+ int cmp;
+
+ ret = NULL;
+
+ l = a;
+ m = b;
+
+ while (l != NULL && m != NULL) {
+ a_app = (GnomeVFSMimeApplication *) l->data;
+ b_app = (GnomeVFSMimeApplication *) m->data;
+
+ cmp = strcmp (a_app->id, b_app->id);
+ if (cmp > 0) {
+ gnome_vfs_mime_application_free (b_app);
+ m = m->next;
+ } else if (cmp < 0) {
+ gnome_vfs_mime_application_free (a_app);
+ l = l->next;
+ } else {
+ gnome_vfs_mime_application_free (b_app);
+ ret = g_list_prepend (ret, a_app);
+ l = l->next;
+ m = m->next;
+ }
+ }
+
+ g_list_foreach (l, (GFunc) gnome_vfs_mime_application_free, NULL);
+ g_list_foreach (m, (GFunc) gnome_vfs_mime_application_free, NULL);
+
+ g_list_free (a);
+ g_list_free (b);
+
+ return g_list_reverse (ret);
+}
+
+GList *
+nautilus_mime_get_open_with_applications_for_files (GList *files)
+{
+ GList *l;
+ NautilusFile *file;
+ GList *one_ret, *ret;
+
+ g_assert (files != NULL);
+
+ ret = NULL;
+ for (l = files; l != NULL; l = l->next) {
+ file = l->data;
+
+ one_ret = nautilus_mime_get_open_with_applications_for_file (file);
+ if (ret != NULL) {
+ ret = intersect_application_lists (ret, one_ret);
+ } else {
+ ret = one_ret;
+ }
+
+ if (ret == NULL) {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+GList *
+nautilus_mime_get_applications_for_files (GList *files)
+{
+ GList *l;
+ NautilusFile *file;
+ GList *one_ret, *ret;
+
+ g_assert (files != NULL);
+
+ ret = NULL;
+ for (l = files; l != NULL; l = l->next) {
+ file = l->data;
+
+ one_ret = nautilus_mime_get_applications_for_file (file);
+ if (ret != NULL) {
+ ret = intersect_application_lists (ret, one_ret);
+ } else {
+ ret = one_ret;
+ }
+
+ if (ret == NULL) {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+gboolean
+nautilus_mime_has_any_applications_for_files (GList *files)
+{
+ GList *l;
+ NautilusFile *file;
+
+ g_assert (files != NULL);
+
+ for (l = files; l != NULL; l = l->next) {
+ file = NAUTILUS_FILE (l->data);
+ if (!nautilus_mime_has_any_applications_for_file (file)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
diff --git a/libnautilus-private/nautilus-mime-actions.h b/libnautilus-private/nautilus-mime-actions.h
index f1035f387..d108bf7b7 100644
--- a/libnautilus-private/nautilus-mime-actions.h
+++ b/libnautilus-private/nautilus-mime-actions.h
@@ -36,6 +36,11 @@ GnomeVFSMimeApplication *nautilus_mime_get_default_application_for_file (Nautil
GList * nautilus_mime_get_open_with_applications_for_file (NautilusFile *file);
GList * nautilus_mime_get_applications_for_file (NautilusFile *file);
+GnomeVFSMimeApplication *nautilus_mime_get_default_application_for_files (GList *files);
+GList * nautilus_mime_get_open_with_applications_for_files (GList *files);
+GList * nautilus_mime_get_applications_for_files (GList *file);
+
gboolean nautilus_mime_has_any_applications_for_file (NautilusFile *file);
+gboolean nautilus_mime_has_any_applications_for_files (GList *files);
#endif /* NAUTILUS_MIME_ACTIONS_H */
diff --git a/libnautilus-private/nautilus-program-choosing.c b/libnautilus-private/nautilus-program-choosing.c
index 98782877b..fbe7e1c8b 100644
--- a/libnautilus-private/nautilus-program-choosing.c
+++ b/libnautilus-private/nautilus-program-choosing.c
@@ -664,18 +664,19 @@ void nautilus_launch_show_file (NautilusFile *file,
* parameter. Provide a parent window for error dialogs.
*
* @application: The application to be launched.
- * @file: The file whose location should be passed as a parameter to the application
+ * @files: The files whose locations should be passed as a parameter to the application.
* @parent_window: A window to use as the parent for any error dialogs.
*/
void
nautilus_launch_application (GnomeVFSMimeApplication *application,
- NautilusFile *file,
+ GList *files,
GtkWindow *parent_window)
{
GdkScreen *screen;
char *uri;
char *uri_scheme;
- GList uris;
+ GList *uris, *l;
+ NautilusFile *file;
char **envp;
GnomeVFSResult result;
#ifdef HAVE_STARTUP_NOTIFICATION
@@ -683,19 +684,26 @@ nautilus_launch_application (GnomeVFSMimeApplication *application,
SnDisplay *sn_display;
#endif
- uri = NULL;
- if (nautilus_file_is_nautilus_link (file)) {
- uri = nautilus_file_get_activation_uri (file);
- }
-
- if (uri == NULL) {
- uri = nautilus_file_get_uri (file);
+ g_assert (files != NULL);
+
+ uris = NULL;
+ for (l = files; l != NULL; l = l->next) {
+ file = NAUTILUS_FILE (l->data);
+
+ uri = NULL;
+
+ if (nautilus_file_is_nautilus_link (file)) {
+ uri = nautilus_file_get_activation_uri (file);
+ }
+
+ if (uri == NULL) {
+ uri = nautilus_file_get_uri (file);
+ }
+
+ uris = g_list_prepend (uris, uri);
}
+ uris = g_list_reverse (uris);
- uris.next = NULL;
- uris.prev = NULL;
- uris.data = uri;
-
screen = gtk_window_get_screen (parent_window);
envp = my_gdk_spawn_make_environment_for_screen (screen, NULL);
@@ -709,27 +717,44 @@ nautilus_launch_application (GnomeVFSMimeApplication *application,
if (gnome_vfs_mime_application_supports_startup_notification (application))
{
char *name;
+ char *description;
char *icon;
+ int files_count;
+
+ file = NAUTILUS_FILE (files->data);
sn_context = sn_launcher_context_new (sn_display,
screen ? gdk_screen_get_number (screen) :
DefaultScreen (gdk_display));
-
- name = nautilus_file_get_display_name (file);
- if (name != NULL) {
- char *description;
-
- sn_launcher_context_set_name (sn_context, name);
-
+
+ files_count = g_list_length (files);
+ if (files_count == 1) {
+ name = nautilus_file_get_display_name (file);
description = g_strdup_printf (_("Opening %s"), name);
-
- sn_launcher_context_set_description (sn_context, description);
+ } else {
+ name = NULL;
+ description = g_strdup_printf (ngettext ("Opening %d Item",
+ "Opening %d Items",
+ files_count),
+ files_count);
+ }
+ if (name != NULL) {
+ sn_launcher_context_set_name (sn_context, name);
g_free (name);
+ }
+
+ if (description != NULL) {
+ sn_launcher_context_set_description (sn_context, description);
g_free (description);
}
icon = nautilus_icon_factory_get_icon_for_file (file, FALSE);
+
+ if (icon == NULL) {
+ icon = g_strdup (gnome_vfs_mime_application_get_icon (application));
+ }
+
if (icon != NULL) {
sn_launcher_context_set_icon_name (sn_context, icon);
g_free (icon);
@@ -761,7 +786,7 @@ nautilus_launch_application (GnomeVFSMimeApplication *application,
}
#endif /* HAVE_STARTUP_NOTIFICATION */
- result = gnome_vfs_mime_application_launch_with_env (application, &uris, envp);
+ result = gnome_vfs_mime_application_launch_with_env (application, uris, envp);
#ifdef HAVE_STARTUP_NOTIFICATION
if (sn_context != NULL) {
@@ -783,7 +808,7 @@ nautilus_launch_application (GnomeVFSMimeApplication *application,
break;
case GNOME_VFS_ERROR_NOT_SUPPORTED:
- uri_scheme = nautilus_file_get_uri_scheme (file);
+ uri_scheme = nautilus_file_get_uri_scheme (NAUTILUS_FILE (files->data));
application_cannot_open_location (application,
file,
uri_scheme,
@@ -800,8 +825,8 @@ nautilus_launch_application (GnomeVFSMimeApplication *application,
#endif
break;
}
-
- g_free (uri);
+
+ eel_g_list_free_deep (uris);
g_strfreev (envp);
}
diff --git a/libnautilus-private/nautilus-program-choosing.h b/libnautilus-private/nautilus-program-choosing.h
index 48d5c3249..002073eb6 100644
--- a/libnautilus-private/nautilus-program-choosing.h
+++ b/libnautilus-private/nautilus-program-choosing.h
@@ -37,7 +37,7 @@ typedef void (*NautilusApplicationChoiceCallback) (GnomeVFSMimeApplication *app
gpointer callback_data);
void nautilus_launch_application (GnomeVFSMimeApplication *application,
- NautilusFile *file,
+ GList *files,
GtkWindow *parent_window);
void nautilus_launch_application_from_command (GdkScreen *screen,
const char *name,
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c
index e580cc325..066db9496 100644
--- a/src/file-manager/fm-directory-view.c
+++ b/src/file-manager/fm-directory-view.c
@@ -447,7 +447,7 @@ EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_zoom_level)
typedef struct {
GnomeVFSMimeApplication *application;
- NautilusFile *file;
+ GList *files;
FMDirectoryView *directory_view;
} ApplicationLaunchParameters;
@@ -537,17 +537,19 @@ file_and_directory_hash (gconstpointer v)
static ApplicationLaunchParameters *
application_launch_parameters_new (GnomeVFSMimeApplication *application,
- NautilusFile *file,
+ GList *files,
FMDirectoryView *directory_view)
{
ApplicationLaunchParameters *result;
result = g_new0 (ApplicationLaunchParameters, 1);
result->application = gnome_vfs_mime_application_copy (application);
- g_object_ref (directory_view);
- result->directory_view = directory_view;
- nautilus_file_ref (file);
- result->file = file;
+ result->files = nautilus_file_list_copy (files);
+
+ if (directory_view != NULL) {
+ g_object_ref (directory_view);
+ result->directory_view = directory_view;
+ }
return result;
}
@@ -556,8 +558,12 @@ static void
application_launch_parameters_free (ApplicationLaunchParameters *parameters)
{
gnome_vfs_mime_application_free (parameters->application);
- g_object_unref (parameters->directory_view);
- nautilus_file_unref (parameters->file);
+ nautilus_file_list_free (parameters->files);
+
+ if (parameters->directory_view != NULL) {
+ g_object_unref (parameters->directory_view);
+ }
+
g_free (parameters);
}
@@ -752,31 +758,37 @@ action_open_alternate_callback (GtkAction *action,
static void
fm_directory_view_launch_application (GnomeVFSMimeApplication *application,
- NautilusFile *file,
+ GList *files,
FMDirectoryView *directory_view)
{
char *uri;
GnomeVFSURI *vfs_uri;
+ NautilusFile *file;
+ GList *l;
g_assert (application != NULL);
- g_assert (NAUTILUS_IS_FILE (file));
+ g_assert (NAUTILUS_IS_FILE (files->data));
g_assert (FM_IS_DIRECTORY_VIEW (directory_view));
nautilus_launch_application
- (application, file,
+ (application, files,
fm_directory_view_get_containing_window (directory_view));
- uri = nautilus_file_get_uri (file);
+ for (l = files; l != NULL; l = l->next) {
+ file = NAUTILUS_FILE (l->data);
- /* Only add real gnome-vfs uris to recent. Not things like
- trash:// and x-nautilus-desktop:// */
- vfs_uri = gnome_vfs_uri_new (uri);
- if (vfs_uri != NULL) {
- egg_recent_model_add (nautilus_recent_get_model (), uri);
- gnome_vfs_uri_unref (vfs_uri);
- }
+ uri = nautilus_file_get_uri (file);
- g_free (uri);
+ /* Only add real gnome-vfs uris to recent. Not things like
+ trash:// and x-nautilus-desktop:// */
+ vfs_uri = gnome_vfs_uri_new (uri);
+ if (vfs_uri != NULL) {
+ egg_recent_model_add (nautilus_recent_get_model (), uri);
+ gnome_vfs_uri_unref (vfs_uri);
+ }
+
+ g_free (uri);
+ }
}
#if NEW_MIME_COMPLETE
@@ -794,7 +806,7 @@ fm_directory_view_chose_application_callback (GnomeVFSMimeApplication *applicati
if (application != NULL) {
fm_directory_view_launch_application
(application, /* NOT the (empty) application in launch_parameters */
- launch_parameters->file,
+ launch_parameters->files,
launch_parameters->directory_view);
}
@@ -835,12 +847,16 @@ application_selected_cb (EelOpenWithDialog *dialog,
{
FMDirectoryView *view;
NautilusFile *file;
+ GList uris;
view = FM_DIRECTORY_VIEW (user_data);
file = g_object_get_data (G_OBJECT (dialog), "directory-view:file");
- fm_directory_view_launch_application (app, file, view);
+ uris.next = NULL;
+ uris.prev = NULL;
+ uris.data = file;
+ fm_directory_view_launch_application (app, &uris, view);
}
static void
@@ -4203,7 +4219,7 @@ open_with_launch_application_callback (GtkAction *action,
launch_parameters = (ApplicationLaunchParameters *) callback_data;
fm_directory_view_launch_application
(launch_parameters->application,
- launch_parameters->file,
+ launch_parameters->files,
launch_parameters->directory_view);
}
@@ -4326,7 +4342,7 @@ add_submenu (GtkUIManager *ui_manager,
static void
add_application_to_open_with_menu (FMDirectoryView *view,
GnomeVFSMimeApplication *application,
- NautilusFile *file,
+ GList *files,
int index,
const char *menu_placeholder,
const char *popup_placeholder)
@@ -4339,10 +4355,13 @@ add_application_to_open_with_menu (FMDirectoryView *view,
GtkAction *action;
launch_parameters = application_launch_parameters_new
- (application, file, view);
+ (application, files, view);
escaped_app = eel_str_double_underscores (application->name);
label = g_strdup_printf (_("Open with \"%s\""), escaped_app);
- tip = g_strdup_printf (_("Use \"%s\" to open the selected item"), escaped_app);
+ tip = g_strdup_printf (ngettext ("Use \"%s\" to open the selected item",
+ "Use \"%s\" to open the selected items",
+ g_list_length (files)),
+ escaped_app);
g_free (escaped_app);
action_name = g_strdup_printf ("open_with_%d", index);
@@ -4521,14 +4540,16 @@ reset_open_with_menu (FMDirectoryView *view, GList *selection)
{
GList *applications, *node;
NautilusFile *file;
- gboolean submenu_visible;
- char *uri;
+ gboolean submenu_visible, filter_default;
int num_applications;
int index;
gboolean other_applications_visible;
+ gboolean open_with_chooser_visible;
GtkUIManager *ui_manager;
GtkAction *action;
-
+ GnomeVFSMimeApplication *default_app;
+ ActivationAction activation_action;
+
/* Clear any previous inserted items in the applications and viewers placeholders */
ui_manager = nautilus_window_info_get_ui_manager (view->details->window);
@@ -4543,84 +4564,88 @@ reset_open_with_menu (FMDirectoryView *view, GList *selection)
num_applications = 0;
- /* This menu is only displayed when there's one selected item. */
- if (!eel_g_list_exactly_one_item (selection)) {
- submenu_visible = FALSE;
- other_applications_visible = FALSE;
- } else {
- GnomeVFSMimeApplication *default_app;
- ActivationAction action;
-
- file = NAUTILUS_FILE (selection->data);
-
- uri = nautilus_file_get_uri (file);
+ other_applications_visible = (selection != NULL);
+ filter_default = (selection != NULL);
- other_applications_visible =
- !can_use_component_for_file (file) ||
- nautilus_file_is_directory (file);
+ for (node = selection; node != NULL; node = node->next) {
+ file = NAUTILUS_FILE (node->data);
+
+ other_applications_visible &=
+ (!can_use_component_for_file (file) ||
+ nautilus_file_is_directory (file));
+
+ activation_action = get_activation_action (file);
- action = get_activation_action (file);
/* Only use the default app for open if there is not
a mime mismatch, otherwise we can't use it in the
open with menu */
- if (action == ACTIVATION_ACTION_OPEN_IN_APPLICATION &&
- can_show_default_app (view, file)) {
- default_app = nautilus_mime_get_default_application_for_file (file);
- } else {
- default_app = NULL;
+ if (activation_action == ACTIVATION_ACTION_OPEN_IN_APPLICATION &&
+ !can_show_default_app (view, file)) {
+ filter_default = TRUE;
}
-
- applications = NULL;
- if (other_applications_visible) {
- applications = nautilus_mime_get_open_with_applications_for_file (NAUTILUS_FILE (selection->data));
+
+ if (filter_default && !other_applications_visible) {
+ break;
}
+ }
- num_applications = g_list_length (applications);
-
- for (node = applications, index = 0; node != NULL; node = node->next, index++) {
- GnomeVFSMimeApplication *application;
- char *menu_path;
- char *popup_path;
-
- application = node->data;
+ default_app = NULL;
+ if (filter_default) {
+ default_app = nautilus_mime_get_default_application_for_files (selection);
+ }
- if (default_app && gnome_vfs_mime_application_equal (default_app, application)) {
- continue;
- }
+ applications = NULL;
+ if (other_applications_visible) {
+ applications = nautilus_mime_get_open_with_applications_for_files (selection);
+ }
- if (num_applications > 3) {
- menu_path = FM_DIRECTORY_VIEW_MENU_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER;
- popup_path = FM_DIRECTORY_VIEW_POPUP_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER;
- } else {
- menu_path = FM_DIRECTORY_VIEW_MENU_PATH_APPLICATIONS_PLACEHOLDER;
- popup_path = FM_DIRECTORY_VIEW_POPUP_PATH_APPLICATIONS_PLACEHOLDER;
- }
+ num_applications = g_list_length (applications);
+
+ for (node = applications, index = 0; node != NULL; node = node->next, index++) {
+ GnomeVFSMimeApplication *application;
+ char *menu_path;
+ char *popup_path;
+
+ application = node->data;
- gtk_ui_manager_add_ui (nautilus_window_info_get_ui_manager (view->details->window),
- view->details->open_with_merge_id,
- menu_path,
- "separator",
- NULL,
- GTK_UI_MANAGER_SEPARATOR,
- FALSE);
-
- add_application_to_open_with_menu (view,
- node->data,
- file,
- index,
- menu_path, popup_path);
+ if (default_app != NULL && gnome_vfs_mime_application_equal (default_app, application)) {
+ continue;
}
- gnome_vfs_mime_application_list_free (applications);
- gnome_vfs_mime_application_free (default_app);
- g_free (uri);
- submenu_visible = (num_applications > 3);
+ if (num_applications > 3) {
+ menu_path = FM_DIRECTORY_VIEW_MENU_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER;
+ popup_path = FM_DIRECTORY_VIEW_POPUP_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER;
+ } else {
+ menu_path = FM_DIRECTORY_VIEW_MENU_PATH_APPLICATIONS_PLACEHOLDER;
+ popup_path = FM_DIRECTORY_VIEW_POPUP_PATH_APPLICATIONS_PLACEHOLDER;
+ }
+
+ gtk_ui_manager_add_ui (nautilus_window_info_get_ui_manager (view->details->window),
+ view->details->open_with_merge_id,
+ menu_path,
+ "separator",
+ NULL,
+ GTK_UI_MANAGER_SEPARATOR,
+ FALSE);
+
+ add_application_to_open_with_menu (view,
+ node->data,
+ selection,
+ index,
+ menu_path, popup_path);
}
+ gnome_vfs_mime_application_list_free (applications);
+ gnome_vfs_mime_application_free (default_app);
+
+ submenu_visible = (num_applications > 3);
+
+ open_with_chooser_visible = other_applications_visible &&
+ g_list_length (selection) == 1;
if (submenu_visible) {
action = gtk_action_group_get_action (view->details->dir_action_group,
FM_ACTION_OTHER_APPLICATION1);
- gtk_action_set_visible (action, other_applications_visible);
+ gtk_action_set_visible (action, open_with_chooser_visible);
action = gtk_action_group_get_action (view->details->dir_action_group,
FM_ACTION_OTHER_APPLICATION2);
gtk_action_set_visible (action, FALSE);
@@ -4630,7 +4655,7 @@ reset_open_with_menu (FMDirectoryView *view, GList *selection)
gtk_action_set_visible (action, FALSE);
action = gtk_action_group_get_action (view->details->dir_action_group,
FM_ACTION_OTHER_APPLICATION2);
- gtk_action_set_visible (action, other_applications_visible);
+ gtk_action_set_visible (action, open_with_chooser_visible);
}
}
@@ -7170,7 +7195,7 @@ clipboard_changed_callback (NautilusClipboardMonitor *monitor, FMDirectoryView *
static void
real_update_menus (FMDirectoryView *view)
{
- GList *selection;
+ GList *selection, *l;
gint selection_count;
const char *tip, *label;
char *label_with_underscore;
@@ -7186,11 +7211,13 @@ real_update_menus (FMDirectoryView *view)
gboolean vfolder_directory;
gboolean show_open_alternate;
gboolean can_open;
+ gboolean show_app;
gboolean show_save_search;
gboolean save_search_sensitive;
gboolean show_save_search_as;
ActivationAction activation_action;
GtkAction *action;
+ GnomeVFSMimeApplication *app;
selection = fm_directory_view_get_selection (view);
selection_count = g_list_length (selection);
@@ -7224,13 +7251,13 @@ real_update_menus (FMDirectoryView *view)
action = gtk_action_group_get_action (view->details->dir_action_group,
FM_ACTION_OPEN);
- gtk_action_set_sensitive (action, selection_count != 0);
+ gtk_action_set_sensitive (action, selection_count != 0);
- label_with_underscore = NULL;
- can_open = TRUE;
- if (selection_count == 1) {
+ can_open = show_app = selection_count != 0;
+
+ for (l = selection; l != NULL; l = l->next) {
NautilusFile *file;
-
+
file = NAUTILUS_FILE (selection->data);
activation_action = get_activation_action (file);
@@ -7239,23 +7266,35 @@ real_update_menus (FMDirectoryView *view)
a mime mismatch, otherwise we can't use it in the
open with menu */
if (activation_action == ACTIVATION_ACTION_OPEN_IN_APPLICATION &&
- can_show_default_app (view, file)) {
- GnomeVFSMimeApplication *app;
-
- app = nautilus_mime_get_default_application_for_file (file);
- if (app) {
- char *escaped_app;
- escaped_app = eel_str_double_underscores (app->name);
- label_with_underscore = g_strdup_printf (_("_Open with \"%s\""),
- escaped_app);
- g_free (escaped_app);
- gnome_vfs_mime_application_free (app);
- } else {
- can_open = FALSE;
- }
+ !can_show_default_app (view, file)) {
+ can_open = FALSE;
+ }
+
+ if (activation_action != ACTIVATION_ACTION_OPEN_IN_APPLICATION) {
+ show_app = FALSE;
+ }
+
+ if (!can_open && !show_app) {
+ break;
}
}
+ label_with_underscore = NULL;
+
+ app = NULL;
+ if (can_open && show_app) {
+ app = nautilus_mime_get_default_application_for_files (selection);
+ }
+
+ if (app != NULL) {
+ char *escaped_app;
+ escaped_app = eel_str_double_underscores (app->name);
+ label_with_underscore = g_strdup_printf (_("_Open with \"%s\""),
+ escaped_app);
+ g_free (escaped_app);
+ gnome_vfs_mime_application_free (app);
+ }
+
g_object_set (action, "label",
label_with_underscore ? label_with_underscore : _("_Open"),
NULL);
@@ -7766,6 +7805,93 @@ stop_activate (ActivateParameters *parameters)
}
static void
+list_to_parameters_foreach (GnomeVFSMimeApplication *application,
+ GList *files,
+ GList **ret)
+{
+ ApplicationLaunchParameters *parameters;
+
+ files = g_list_reverse (files);
+
+ parameters = application_launch_parameters_new
+ (application, files, NULL);
+ *ret = g_list_prepend (*ret, parameters);
+}
+
+static unsigned int
+mime_application_hash (GnomeVFSMimeApplication *app)
+{
+ return g_str_hash (app->id);
+}
+
+/**
+ * fm_directory_view_make_activation_parameters
+ *
+ * Construct a list of ApplicationLaunchParameters from a list of NautilusFiles,
+ * where files that have the same default application are put into the same
+ * launch parameter, and others are put into the unhandled_files list.
+ *
+ * @files: Files to use for construction.
+ * @unhandled_files: Files without any default application will be put here.
+ *
+ * Return value: Newly allocated list of ApplicationLaunchParameters.
+ **/
+static GList *
+fm_directory_view_make_activation_parameters (GList *files,
+ GList **unhandled_files)
+{
+ GList *ret, *l, *app_files;
+ NautilusFile *file;
+ GnomeVFSMimeApplication *app, *old_app;
+ GHashTable *app_table;
+
+ ret = NULL;
+ *unhandled_files = NULL;
+
+ app_table = g_hash_table_new_full
+ ((GHashFunc) mime_application_hash,
+ (GEqualFunc) gnome_vfs_mime_application_equal,
+ (GDestroyNotify) gnome_vfs_mime_application_free,
+ (GDestroyNotify) g_list_free);
+
+ for (l = files; l != NULL; l = l->next) {
+ file = NAUTILUS_FILE (l->data);
+
+ app = nautilus_mime_get_default_application_for_file (file);
+ if (app != NULL) {
+ app_files = NULL;
+
+ if (g_hash_table_lookup_extended (app_table, app,
+ (gpointer *) &old_app,
+ (gpointer *) &app_files)) {
+ g_hash_table_steal (app_table, old_app);
+
+ app_files = g_list_prepend (app_files, file);
+
+ gnome_vfs_mime_application_free (app);
+ app = old_app;
+ } else {
+ app_files = g_list_prepend (NULL, file);
+ }
+
+ g_hash_table_insert (app_table, app, app_files);
+ } else {
+ *unhandled_files = g_list_prepend (*unhandled_files, file);
+ }
+ }
+
+ g_hash_table_foreach (app_table,
+ (GHFunc) list_to_parameters_foreach,
+ &ret);
+
+ g_hash_table_destroy (app_table);
+
+ *unhandled_files = g_list_reverse (*unhandled_files);
+
+ return g_list_reverse (ret);
+}
+
+static void
activate_callback (GList *files, gpointer callback_data)
{
ActivateParameters *parameters;
@@ -7776,6 +7902,9 @@ activate_callback (GList *files, gpointer callback_data)
GList *launch_files;
GList *launch_in_terminal_files;
GList *open_in_app_files;
+ GList *open_in_app_parameters;
+ GList *unhandled_open_in_app_files;
+ ApplicationLaunchParameters *one_parameters;
GList *open_in_view_files;
GList *l;
int count;
@@ -7787,9 +7916,10 @@ activate_callback (GList *files, gpointer callback_data)
parameters = callback_data;
- stop_activate (parameters);
-
view = FM_DIRECTORY_VIEW (parameters->view);
+ g_object_ref (view);
+
+ stop_activate (parameters);
screen = gtk_widget_get_screen (GTK_WIDGET (view));
@@ -7928,19 +8058,40 @@ activate_callback (GList *files, gpointer callback_data)
}
}
- open_in_app_files = g_list_reverse (open_in_app_files);
- for (l = open_in_app_files; l != NULL; l = l->next) {
+ open_in_app_parameters = NULL;
+ unhandled_open_in_app_files = NULL;
+
+ if (open_in_app_files != NULL) {
+ open_in_app_files = g_list_reverse (open_in_app_files);
+
+ open_in_app_parameters = fm_directory_view_make_activation_parameters
+ (open_in_app_files, &unhandled_open_in_app_files);
+ }
+
+ if (open_in_app_parameters != NULL ||
+ unhandled_open_in_app_files != NULL) {
+ if ((parameters->flags & NAUTILUS_WINDOW_OPEN_FLAG_CLOSE_BEHIND) != 0 &&
+ nautilus_window_info_get_window_type (view->details->window) == NAUTILUS_WINDOW_SPATIAL) {
+ nautilus_window_info_close (view->details->window);
+ }
+ }
+
+ for (l = open_in_app_parameters; l != NULL; l = l->next) {
+ one_parameters = l->data;
+
+ fm_directory_view_launch_application (
+ one_parameters->application,
+ one_parameters->files,
+ view);
+ application_launch_parameters_free (one_parameters);
+ }
+
+ for (l = unhandled_open_in_app_files; l != NULL; l = l->next) {
file = NAUTILUS_FILE (l->data);
nautilus_launch_show_file
(file, fm_directory_view_get_containing_window (view));
- if ((parameters->flags & NAUTILUS_WINDOW_OPEN_FLAG_CLOSE_BEHIND) != 0) {
- if (nautilus_window_info_get_window_type (view->details->window) == NAUTILUS_WINDOW_SPATIAL) {
- nautilus_window_info_close (view->details->window);
- }
- }
-
/* We should not add trash and directory uris.*/
if ((!nautilus_file_is_in_trash (file)) &&
(!nautilus_file_is_directory (file))) {
@@ -7950,12 +8101,16 @@ activate_callback (GList *files, gpointer callback_data)
}
}
+ g_object_unref (view);
+
g_list_free (launch_desktop_files);
g_list_free (launch_from_command_files);
g_list_free (launch_files);
g_list_free (launch_in_terminal_files);
g_list_free (open_in_view_files);
g_list_free (open_in_app_files);
+ g_list_free (open_in_app_parameters);
+ g_list_free (unhandled_open_in_app_files);
nautilus_file_list_free (parameters->files);
g_free (parameters);
@@ -8149,7 +8304,10 @@ fm_directory_view_activate_files (FMDirectoryView *view,
int file_count;
g_return_if_fail (FM_IS_DIRECTORY_VIEW (view));
- g_return_if_fail (files != NULL);
+
+ if (files == NULL) {
+ return;
+ }
file_count = g_list_length (files);
diff --git a/src/nautilus-information-panel.c b/src/nautilus-information-panel.c
index d853f4afc..7e173d07e 100644
--- a/src/nautilus-information-panel.c
+++ b/src/nautilus-information-panel.c
@@ -852,13 +852,17 @@ command_button_callback (GtkWidget *button, char *id_str)
{
NautilusInformationPanel *information_panel;
GnomeVFSMimeApplication *application;
+ GList files;
information_panel = NAUTILUS_INFORMATION_PANEL (g_object_get_data (G_OBJECT (button), "user_data"));
application = gnome_vfs_mime_application_new_from_desktop_id (id_str);
if (application != NULL) {
- nautilus_launch_application (application, information_panel->details->file,
+ files.next = NULL;
+ files.prev = NULL;
+ files.data = information_panel->details->file;
+ nautilus_launch_application (application, &files,
nautilus_information_panel_get_window (information_panel));
gnome_vfs_mime_application_free (application);