Re: [rfc][patch] Add optional PackageKit hook to install new applications



On Thu, 2008-12-04 at 15:25 +0100, Cosimo Cecchi wrote:
> This is great stuff, thanks for working on it :)

No problem.

> I don't think depending on DBus is bad for Nautilus. It's been some time
> since there are multiple requests for a FileManager interface on the
> bus, so it should be something we want to do anyway at some point.

Yes, I thought it was pretty strange. Version 2 of the patch is
attached, which uses dbus and gtk to get the XID which makes focus
stealing prevention and modality work correctly. Using the dbus
interface also allows us to detect when we actually installed a package,
or just exited without anything found.

I've also added a check so we don't try to recurse which will happen if
you're using the dummy (testing) PackageKit backend.

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,106 @@
 	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 (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
 activate_files (ActivateParameters *parameters)
 {
 	NautilusWindowInfo *window_info;
@@ -1229,7 +1334,12 @@
 		char *full_uri_for_display;
 		char *uri_for_display;
 		char *error_message;
-		
+#ifdef ENABLE_PACKAGEKIT
+		char *secondary_text;
+		GtkWidget *dialog;
+		GtkButtonsType button;
+#endif
+
 		file = NAUTILUS_FILE (l->data);
 
 		location = nautilus_file_get_location (file);
@@ -1249,9 +1359,49 @@
 		
 		g_free (uri_for_display);
 
+#ifdef ENABLE_PACKAGEKIT
+		/* 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;
+		}
+
+		/* 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 (parameters, mime_type);
+			g_free (mime_type);
+		}
+
+		g_free (secondary_text);
+
+		/* if we failed, use the cancel dialog */
+		unpause_activation_timed_cancel (parameters);
+#else
 		eel_show_error_dialog (error_message,
 				       _("There is no application installed for this file type"),
 				       parameters->parent_window);
+#endif
+out:
 		g_free (error_message);
 	}
 
@@ -1630,6 +1780,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) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]