summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2008-12-10 11:50:43 +0000
committerAlexander Larsson <alexl@src.gnome.org>2008-12-10 11:50:43 +0000
commit384ca4a1911525ae214e8c4d0a189c209db9e587 (patch)
treeec19ceb95eec524c3668490eab4d17a3025f55af
parentd5a8c169eca1b0186135178e0e039f7fc2f4d415 (diff)
downloadnautilus-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--ChangeLog10
-rw-r--r--configure.in15
-rw-r--r--libnautilus-private/apps_nautilus_preferences.schemas.in15
-rw-r--r--libnautilus-private/nautilus-global-preferences.c4
-rw-r--r--libnautilus-private/nautilus-global-preferences.h3
-rw-r--r--libnautilus-private/nautilus-mime-actions.c274
6 files changed, 294 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index c27122476..a81d6cd2d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 *)&parameters_install->slot_info);
+ }
+ if (parameters_install->parent_window) {
+ g_object_remove_weak_pointer (G_OBJECT (parameters_install->parent_window), (gpointer *)&parameters_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 *)&parameters_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 *)&parameters_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;