Re: [rfc][patch] Add optional PackageKit hook to install new applications
- From: Richard Hughes <hughsient gmail com>
- To: Kenneth MacDonald <K MacDonald ed ac uk>
- Cc: nautilus-list gnome org
- Subject: Re: [rfc][patch] Add optional PackageKit hook to install new applications
- Date: Thu, 04 Dec 2008 18:08:37 +0000
On Thu, 2008-12-04 at 17:29 +0000, Kenneth MacDonald wrote:
> On Thu, 2008-12-04 at 13:09 +0000, Richard Hughes wrote:
>
> > Of course, an admin can switch off this functionality in
> > gnome-packagekit, or I can even add a nautilus GConf key to not even
> > show the question if you guys would prefer.
> >
> > Comments appreciated.
>
> Very cool, but we'd really want to be able to turn it off on e.g. lab
> machines so a GConf key would be ideal.
Version 3 attached for review.
Richard.
Index: configure.in
===================================================================
--- configure.in (revision 14796)
+++ configure.in (working copy)
@@ -65,6 +65,7 @@
gtk+-2.0 >= gtk_minver
libxml-2.0 >= xml_minver
unique-1.0
+ dbus-glib-1
])
dnl ==========================================================================
@@ -317,6 +318,17 @@
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,
@@ -473,6 +485,7 @@
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}
Index: libnautilus-private/nautilus-mime-actions.c
===================================================================
--- libnautilus-private/nautilus-mime-actions.c (revision 14796)
+++ libnautilus-private/nautilus-mime-actions.c (working copy)
@@ -32,6 +32,11 @@
#include <glib/gstdio.h>
#include <string.h>
+#ifdef ENABLE_PACKAGEKIT
+ #include <dbus/dbus-glib.h>
+ #include <gdk/gdkx.h>
+#endif
+
#include "nautilus-file-attributes.h"
#include "nautilus-file.h"
#include "nautilus-autorun.h"
@@ -73,6 +78,7 @@
gboolean tried_mounting;
char *activation_directory;
gboolean user_confirmation;
+ gboolean activate_retry;
} ActivateParameters;
/* Number of seconds until cancel dialog shows up */
@@ -1022,7 +1028,195 @@
return response == GTK_RESPONSE_YES;
}
+#ifdef ENABLE_PACKAGEKIT
+
+/* prototype only required for ENABLE_PACKAGEKIT */
+static void activate_files (ActivateParameters *parameters);
+
static void
+search_for_application_dbus_call_notify_cb (DBusGProxy *proxy, DBusGProxyCall *call, ActivateParameters *parameters)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ ret = dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID);
+ if (!ret) {
+ g_debug ("Did not install handler: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* FIXME: activate the file again */
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
+ "need to activate file again");
+ activate_files (parameters);
+out:
+ return;
+}
+
+static void
+search_for_application_mime_type (ActivateParameters *parameters, const gchar *mime_type)
+{
+ DBusGConnection *connection;
+ DBusGProxy *proxy = NULL;
+ guint xid = 0;
+ GError *error = NULL;
+ DBusGProxyCall *call;
+ 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->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,
+ NULL, NULL,
+ G_TYPE_UINT, xid,
+ G_TYPE_UINT, 0,
+ G_TYPE_STRING, mime_type,
+ G_TYPE_INVALID);
+ if (call == NULL) {
+ g_warning ("Could not send method");
+ dialog = gtk_message_dialog_new (GTK_WINDOW (parameters->parent_window),
+ 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;
+ }
+
+ /* signal this, as we don't want to get stuck into a loop if
+ * the application doesn't for some reason register the mime handler
+ * it advertised
+ */
+ parameters->activate_retry = TRUE;
+
+ nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
+ "InstallMimeType method invoked for %s", mime_type);
+out:
+ if (proxy != NULL)
+ g_object_unref (proxy);
+}
+#endif
+
+static void
+application_unhandled_file (ActivateParameters *parameters, NautilusFile *file)
+{
+ GFile *location;
+ char *full_uri_for_display;
+ char *uri_for_display;
+ char *error_message;
+#ifdef ENABLE_PACKAGEKIT
+ char *secondary_text;
+ GtkWidget *dialog;
+ GtkButtonsType button;
+ gboolean show_install_mime;
+#endif
+ 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);
+
+#ifndef ENABLE_PACKAGEKIT
+ /* show an unhelpful dialog */
+ eel_show_error_dialog (error_message,
+ _("There is no application installed for this file type"),
+ parameters->parent_window);
+ goto out;
+#else
+
+ /* we've installed something, that failed to register this mime type */
+ if (parameters->activate_retry) {
+ eel_show_error_dialog (error_message,
+ _("The application installed could not open this file type"),
+ parameters->parent_window);
+ goto out;
+ }
+
+ /* allow an admin to disable the PackageKit search functionality */
+ show_install_mime = eel_preferences_get_boolean (NAUTILUS_PREFERENCES_INSTALL_MIME_ACTIVATION);
+ if (!show_install_mime) {
+ eel_show_error_dialog (error_message,
+ _("There is no application installed for this file type "
+ "and application search has been disabled"),
+ parameters->parent_window);
+ goto out;
+ }
+
+ /* pause the cancel dialog */
+ pause_activation_timed_cancel (parameters);
+
+ /* use a custom dialog to prompt the user to install new software */
+ dialog = gtk_message_dialog_new (GTK_WINDOW (parameters->parent_window),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_YES_NO,
+ error_message);
+ secondary_text = g_strdup_printf ("%s\n%s",
+ _("There is no application installed for this file type."),
+ _("Do you want to search for an application to open this file?"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), secondary_text);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+ button = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ if (button == GTK_RESPONSE_YES) {
+ char *mime_type;
+ mime_type = nautilus_file_get_mime_type (file);
+ search_for_application_mime_type (parameters, mime_type);
+ g_free (mime_type);
+ }
+
+ g_free (secondary_text);
+
+ /* if we failed, use the cancel dialog */
+ unpause_activation_timed_cancel (parameters);
+#endif
+out:
+ g_free (error_message);
+}
+
+static void
activate_files (ActivateParameters *parameters)
{
NautilusWindowInfo *window_info;
@@ -1225,34 +1419,9 @@
}
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);
+ application_unhandled_file (parameters, file);
}
window_info = NULL;
@@ -1630,6 +1799,7 @@
parameters->mode = mode;
parameters->flags = flags;
parameters->user_confirmation = user_confirmation;
+ parameters->activate_retry = FALSE;
file_count = g_list_length (files);
if (file_count == 1) {
Index: libnautilus-private/apps_nautilus_preferences.schemas.in
===================================================================
--- libnautilus-private/apps_nautilus_preferences.schemas.in (revision 14796)
+++ libnautilus-private/apps_nautilus_preferences.schemas.in (working copy)
@@ -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>
Index: libnautilus-private/nautilus-global-preferences.c
===================================================================
--- libnautilus-private/nautilus-global-preferences.c (revision 14796)
+++ libnautilus-private/nautilus-global-preferences.c (working copy)
@@ -278,6 +278,10 @@
NULL, NULL,
"executable_text_activation"
},
+ { NAUTILUS_PREFERENCES_INSTALL_MIME_ACTIVATION,
+ PREFERENCE_BOOLEAN,
+ GINT_TO_POINTER (TRUE)
+ },
{ NAUTILUS_PREFERENCES_THEME,
PREFERENCE_STRING,
"default"
Index: libnautilus-private/nautilus-global-preferences.h
===================================================================
--- libnautilus-private/nautilus-global-preferences.h (revision 14796)
+++ libnautilus-private/nautilus-global-preferences.h (working copy)
@@ -93,6 +93,9 @@
/* 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"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]