diff options
author | Alexander Larsson <alexl@redhat.com> | 2008-12-10 11:50:43 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2008-12-10 11:50:43 +0000 |
commit | 384ca4a1911525ae214e8c4d0a189c209db9e587 (patch) | |
tree | ec19ceb95eec524c3668490eab4d17a3025f55af | |
parent | d5a8c169eca1b0186135178e0e039f7fc2f4d415 (diff) | |
download | nautilus-384ca4a1911525ae214e8c4d0a189c209db9e587.tar.gz |
Support PackageConfig application install for unsupported mime types.
2008-12-10 Alexander Larsson <alexl@redhat.com>
* configure.in:
* libnautilus-private/apps_nautilus_preferences.schemas.in:
* libnautilus-private/nautilus-global-preferences.c:
* libnautilus-private/nautilus-global-preferences.h:
* libnautilus-private/nautilus-mime-actions.c:
Support PackageConfig application install for unsupported mime types.
Based on patch from Richard Hughes
svn path=/trunk/; revision=14807
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | configure.in | 15 | ||||
-rw-r--r-- | libnautilus-private/apps_nautilus_preferences.schemas.in | 15 | ||||
-rw-r--r-- | libnautilus-private/nautilus-global-preferences.c | 4 | ||||
-rw-r--r-- | libnautilus-private/nautilus-global-preferences.h | 3 | ||||
-rw-r--r-- | libnautilus-private/nautilus-mime-actions.c | 274 |
6 files changed, 294 insertions, 27 deletions
@@ -1,5 +1,15 @@ 2008-12-10 Alexander Larsson <alexl@redhat.com> + * configure.in: + * libnautilus-private/apps_nautilus_preferences.schemas.in: + * libnautilus-private/nautilus-global-preferences.c: + * libnautilus-private/nautilus-global-preferences.h: + * libnautilus-private/nautilus-mime-actions.c: + Support PackageConfig application install for unsupported mime types. + Based on patch from Richard Hughes + +2008-12-10 Alexander Larsson <alexl@redhat.com> + * libnautilus-private/nautilus-file.c: * libnautilus-private/nautilus-global-preferences.c: * src/nautilus-file-management-properties.c: diff --git a/configure.in b/configure.in index 7612fd279..2b07b0e60 100644 --- a/configure.in +++ b/configure.in @@ -65,6 +65,7 @@ PKG_CHECK_MODULES(ALL, [ gtk+-2.0 >= gtk_minver libxml-2.0 >= xml_minver unique-1.0 + dbus-glib-1 ]) dnl ========================================================================== @@ -317,6 +318,17 @@ AM_CONDITIONAL(ENABLE_EMPTY_VIEW, test "x$ENABLE_EMPTY_VIEW" = "x1") dnl ========================================================================== +AC_ARG_ENABLE(packagekit, + AC_HELP_STRING([--disable-packagekit], + [build without PackageKit support])) +msg_packagekit=no +if test "x$enable_packagekit" != "xno"; then + msg_packagekit=yes + AC_DEFINE(ENABLE_PACKAGEKIT, 1, [define to enable PackageKit mimetype installer]) +fi + +dnl ========================================================================== + dnl Turn on the additional warnings last, so -Werror doesn't affect other tests. AC_ARG_ENABLE(more-warnings, @@ -374,7 +386,7 @@ LIBNAUTILUS_EXTENSION_LIBS="`$PKG_CONFIG --libs $LIBNAUTILUS_EXTENSION_MODULES`" AC_SUBST(LIBNAUTILUS_EXTENSION_LIBS) dnl core nautilus -CORE_MODULES="glib-2.0 eel-2.0 gnome-desktop-2.0 gio-2.0 gio-unix-2.0 unique-1.0 $EXTRA_CORE_MODULES" +CORE_MODULES="glib-2.0 eel-2.0 gnome-desktop-2.0 gio-2.0 gio-unix-2.0 unique-1.0 dbus-glib-1 $EXTRA_CORE_MODULES" CORE_CFLAGS="`$PKG_CONFIG --cflags $CORE_MODULES` $x_cflags $WARNING_CFLAGS" AC_SUBST(CORE_CFLAGS) CORE_LIBS="`$PKG_CONFIG --libs $CORE_MODULES` $x_libs" @@ -473,6 +485,7 @@ nautilus-$VERSION: tracker support: $msg_tracker beagle support: $msg_beagle xmp support: $msg_xmp + PackageKit support: $msg_packagekit profiling support: ${profiling_support} nautilus-extension documentation: ${enable_gtk_doc} diff --git a/libnautilus-private/apps_nautilus_preferences.schemas.in b/libnautilus-private/apps_nautilus_preferences.schemas.in index 106a322b6..edb2d5e24 100644 --- a/libnautilus-private/apps_nautilus_preferences.schemas.in +++ b/libnautilus-private/apps_nautilus_preferences.schemas.in @@ -301,6 +301,21 @@ </schema> <schema> + <key>/schemas/apps/nautilus/preferences/install_mime_activation</key> + <applyto>/apps/nautilus/preferences/install_mime_activation</applyto> + <owner>nautilus</owner> + <type>bool</type> + <default>true</default> + <locale name="C"> + <short>If to show the package installer for unknown mime types</short> + <long> + Whether to present the user a dialog to search using the package + installer for an application that can open an unknown mime type. + </long> + </locale> + </schema> + + <schema> <key>/schemas/apps/nautilus/preferences/theme</key> <applyto>/apps/nautilus/preferences/theme</applyto> <owner>nautilus</owner> diff --git a/libnautilus-private/nautilus-global-preferences.c b/libnautilus-private/nautilus-global-preferences.c index 0bf526407..b04561a96 100644 --- a/libnautilus-private/nautilus-global-preferences.c +++ b/libnautilus-private/nautilus-global-preferences.c @@ -280,6 +280,10 @@ static const PreferenceDefault preference_defaults[] = { NULL, NULL, "executable_text_activation" }, + { NAUTILUS_PREFERENCES_INSTALL_MIME_ACTIVATION, + PREFERENCE_BOOLEAN, + GINT_TO_POINTER (TRUE) + }, { NAUTILUS_PREFERENCES_THEME, PREFERENCE_STRING, "default" diff --git a/libnautilus-private/nautilus-global-preferences.h b/libnautilus-private/nautilus-global-preferences.h index 4386b3537..3a3fe3250 100644 --- a/libnautilus-private/nautilus-global-preferences.h +++ b/libnautilus-private/nautilus-global-preferences.h @@ -93,6 +93,9 @@ typedef enum /* Activating executable text files */ #define NAUTILUS_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION "preferences/executable_text_activation" +/* Installing new packages when unknown mime type activated */ +#define NAUTILUS_PREFERENCES_INSTALL_MIME_ACTIVATION "preferences/install_mime_activation" + /* Spatial or browser mode */ #define NAUTILUS_PREFERENCES_ALWAYS_USE_BROWSER "preferences/always_use_browser" #define NAUTILUS_PREFERENCES_ENABLE_TABS "preferences/tabs_enable" diff --git a/libnautilus-private/nautilus-mime-actions.c b/libnautilus-private/nautilus-mime-actions.c index 8f57ec3dc..8cb21632c 100644 --- a/libnautilus-private/nautilus-mime-actions.c +++ b/libnautilus-private/nautilus-mime-actions.c @@ -31,6 +31,8 @@ #include <glib/gi18n.h> #include <glib/gstdio.h> #include <string.h> +#include <dbus/dbus-glib.h> +#include <gdk/gdkx.h> #include "nautilus-file-attributes.h" #include "nautilus-file.h" @@ -1022,6 +1024,250 @@ confirm_multiple_windows (GtkWindow *parent_window, return response == GTK_RESPONSE_YES; } +typedef struct { + NautilusWindowSlotInfo *slot_info; + GtkWindow *parent_window; + NautilusFile *file; + GList *files; + NautilusWindowOpenMode mode; + NautilusWindowOpenFlags flags; + char *activation_directory; + gboolean user_confirmation; + gboolean got_reply; +} ActivateParametersInstall; + +static void +activate_parameters_install_free (ActivateParametersInstall *parameters_install) +{ + if (parameters_install->slot_info) { + g_object_remove_weak_pointer (G_OBJECT (parameters_install->slot_info), (gpointer *)¶meters_install->slot_info); + } + if (parameters_install->parent_window) { + g_object_remove_weak_pointer (G_OBJECT (parameters_install->parent_window), (gpointer *)¶meters_install->parent_window); + } + nautilus_file_list_free (parameters_install->files); + g_free (parameters_install->activation_directory); + g_free (parameters_install); +} + +static void +activate_parameters_install_free_with_error (ActivateParametersInstall *parameters_install) +{ + if (!parameters_install->got_reply) { + eel_show_error_dialog (_("Unable to search for application"), + _("There was an internal error trying to search for applications"), + parameters_install->parent_window); + } + + activate_parameters_install_free (parameters_install); +} + +static void +search_for_application_dbus_call_notify_cb (DBusGProxy *proxy, DBusGProxyCall *call, ActivateParametersInstall *parameters_install) +{ + gboolean ret; + GError *error = NULL; + + parameters_install->got_reply = TRUE; + + ret = dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID); + if (!ret) { + eel_show_error_dialog (_("Unable to search for application"), + _("There was an internal error trying to search for applications"), + parameters_install->parent_window); + g_error_free (error); + return; + } + + /* activate the file again */ + nautilus_mime_activate_files (parameters_install->parent_window, + parameters_install->slot_info, + parameters_install->files, + parameters_install->activation_directory, + parameters_install->mode, + parameters_install->flags, + parameters_install->user_confirmation); + + /* parameters_install freed by destroy notify */ +} + +static void +search_for_application_mime_type (ActivateParametersInstall *parameters_install, const gchar *mime_type) +{ + DBusGConnection *connection; + DBusGProxy *proxy = NULL; + guint xid = 0; + GError *error = NULL; + DBusGProxyCall *call = NULL; + GtkWidget *dialog; + GdkWindow *window; + + /* get bus */ + connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + if (connection == NULL) { + g_warning ("Could not connect to session bus: %s\n", error->message); + g_error_free (error); + goto out; + } + + /* get proxy - native clients for for KDE and GNOME */ + proxy = dbus_g_proxy_new_for_name (connection, + "org.freedesktop.PackageKit", + "/org/freedesktop/PackageKit", + "org.freedesktop.PackageKit"); + if (proxy == NULL) { + g_warning ("Could not connect to PackageKit session service\n"); + goto out; + } + + /* get XID from parent window */ + window = gtk_widget_get_window (GTK_WIDGET (parameters_install->parent_window)); + if (window != NULL) { + xid = GDK_WINDOW_XID (window); + } + + /* don't timeout, as dbus-glib sets the timeout ~25 seconds */ + dbus_g_proxy_set_default_timeout (proxy, INT_MAX); + + /* invoke the method */ + call = dbus_g_proxy_begin_call (proxy, "InstallMimeType", + (DBusGProxyCallNotify) search_for_application_dbus_call_notify_cb, + parameters_install, activate_parameters_install_free_with_error, + G_TYPE_UINT, xid, + G_TYPE_UINT, 0, + G_TYPE_STRING, mime_type, + G_TYPE_INVALID); + if (call == NULL) { + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("Could not use system package installer")); + g_signal_connect (G_OBJECT (dialog), "response", + G_CALLBACK (gtk_widget_destroy), NULL); + gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); + gtk_widget_show (dialog); + goto out; + } + + nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER, + "InstallMimeType method invoked for %s", mime_type); +out: + if (call == NULL) { + /* dbus method was not called, so we're not going to get the async dbus callback */ + activate_parameters_install_free (parameters_install); + } + if (proxy != NULL) { + g_object_unref (proxy); + } +} + +static void +application_unhandled_file_install (GtkDialog *dialog, gint response_id, ActivateParametersInstall *parameters_install) +{ + char *mime_type; + + gtk_widget_destroy (GTK_WIDGET (dialog)); + + if (response_id == GTK_RESPONSE_YES) { + mime_type = nautilus_file_get_mime_type (parameters_install->file); + search_for_application_mime_type (parameters_install, mime_type); + g_free (mime_type); + } else { + /* free as we're not going to get the async dbus callback */ + activate_parameters_install_free (parameters_install); + } +} + +static void +application_unhandled_file (ActivateParameters *parameters, NautilusFile *file) +{ + GFile *location; + char *full_uri_for_display; + char *uri_for_display; + char *error_message; + gboolean show_install_mime; + GtkWidget *dialog; + char *mime_type; + char *text; + ActivateParametersInstall *parameters_install; + + location = nautilus_file_get_location (file); + full_uri_for_display = g_file_get_parse_name (location); + g_object_unref (location); + + /* Truncate the URI so it doesn't get insanely wide. Note that even + * though the dialog uses wrapped text, if the URI doesn't contain + * white space then the text-wrapping code is too stupid to wrap it. + */ + uri_for_display = eel_str_middle_truncate (full_uri_for_display, MAX_URI_IN_DIALOG_LENGTH); + g_free (full_uri_for_display); + + error_message = g_strdup_printf (_("Could not display \"%s\"."), uri_for_display); + + g_free (uri_for_display); + + mime_type = nautilus_file_get_mime_type (file); + +#ifdef ENABLE_PACKAGEKIT + /* allow an admin to disable the PackageKit search functionality */ + show_install_mime = eel_preferences_get_boolean (NAUTILUS_PREFERENCES_INSTALL_MIME_ACTIVATION); +#else + /* we have no install functionality */ + show_install_mime = FALSE; +#endif + /* There is no use trying to look for handlers of application/octet-stream */ + if (g_content_type_is_unknown (mime_type)) { + show_install_mime = FALSE; + } + if (!show_install_mime) { + /* show an unhelpful dialog */ + if (g_content_type_is_unknown (mime_type)) { + eel_show_error_dialog (error_message, + _("The file is of an unknown type"), + parameters->parent_window); + } else { + text = g_strdup_printf (_("There is no application installed for %s files"), g_content_type_get_description (mime_type)); + eel_show_error_dialog (error_message, + text, + parameters->parent_window); + g_free (text); + } + goto out; + } + + /* use a custom dialog to prompt the user to install new software */ + dialog = gtk_message_dialog_new (NULL, 0, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_YES_NO, + error_message); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + _("There is no application installed for %s files.\nDo you want to search for an application to open this file?"), + g_content_type_get_description (mime_type)); + gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); + + /* copy the parts of parameters we are interested in as the orignal will be unref'd */ + parameters_install = g_new0 (ActivateParametersInstall, 1); + parameters_install->slot_info = parameters->slot_info; + g_object_add_weak_pointer (G_OBJECT (parameters_install->slot_info), (gpointer *)¶meters_install->slot_info); + if (parameters->parent_window) { + parameters_install->parent_window = parameters->parent_window; + g_object_add_weak_pointer (G_OBJECT (parameters_install->parent_window), (gpointer *)¶meters_install->parent_window); + } + parameters_install->activation_directory = g_strdup (parameters->activation_directory); + parameters_install->file = nautilus_file_ref (file); + parameters_install->files = nautilus_file_list_copy (parameters->files); + parameters_install->mode = parameters->mode; + parameters_install->flags = parameters->flags; + parameters_install->user_confirmation = parameters->user_confirmation; + + g_signal_connect (dialog, "response", G_CALLBACK (application_unhandled_file_install), parameters_install); + gtk_widget_show_all (dialog); +out: + g_free (mime_type); + g_free (error_message); +} + static void activate_files (ActivateParameters *parameters) { @@ -1225,34 +1471,10 @@ activate_files (ActivateParameters *parameters) } for (l = unhandled_open_in_app_files; l != NULL; l = l->next) { - GFile *location; - char *full_uri_for_display; - char *uri_for_display; - char *error_message; - file = NAUTILUS_FILE (l->data); - location = nautilus_file_get_location (file); - full_uri_for_display = g_file_get_parse_name (location); - g_object_unref (location); - - /* Truncate the URI so it doesn't get insanely wide. Note that even - * though the dialog uses wrapped text, if the URI doesn't contain - * white space then the text-wrapping code is too stupid to wrap it. - */ - uri_for_display = eel_str_middle_truncate - (full_uri_for_display, MAX_URI_IN_DIALOG_LENGTH); - g_free (full_uri_for_display); - - error_message = g_strdup_printf (_("Could not display \"%s\"."), - uri_for_display); - - g_free (uri_for_display); - - eel_show_error_dialog (error_message, - _("There is no application installed for this file type"), - parameters->parent_window); - g_free (error_message); + /* this does not block */ + application_unhandled_file (parameters, file); } window_info = NULL; |