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



At the moment, if I try to open a file that I don't have a viewer or
editor for, I get a message like this:
____________________________________________________________
|
| There is no application installed for this file type ***
|___________________________________________________________

This is very unhelpful to say the least.

Using PackageKit we can provide a cross distribution way of achieving
the following interaction:
____________________________________________________________
|
| There is no application installed for this file type
| Do you want to search for an application to open this file?
|
|  [Help]                                  [Cancel] [Search]
|___________________________________________________________

<user clicks Search>
____________________________________________________________
|
| The following applications can open this document:
|
| Please select an application and click install or cancel to abort
| ________________________________
| |[icon]  Application name1      |
| |        package-name.version   |
| |_______________________________|
| |[icon]  Application name2      |
| |        package-name.version   |
| |_______________________________|
|
|  [Help]                                  [Cancel] [Install]
|___________________________________________________________

or
____________________________________________________________
|
| No applications can be found to open this document.
|
|  [More info]                                       [Close]
|___________________________________________________________

Now, I'm not very familiar with the nautilus code base, so apologies if
my attached patch is wrong in any way. In an ideal world I would have
used DBUS to call into the session (to make this XFCE, KDE and GNOME
neutral) but using a command line helper isn't so bad. Using the DBus
interface would however give us a trivial way to specify the XID and
timespec to make modality and focus-stealing-prevention work correctly,
although you could specify these as environment variables to the helper
tool. I'm not sure how much you guys love DBUS, as I couldn't see a dep
on it in the configure.in file.

The bright eyed may notice that gpk-install-mime-type just asks the user
for the software choice, and installs it, but doesn't re-open the
original file. I think the best way to do that would be in the nautilus
code, although I'm open to creating a gpk-install-mime-type-and-run-file
helper if required.

Also note that this will not yet work when using Fedora as we need to
work a little on rpm to be able to extract the .desktop files at
rpmbuild time. The way this is planned to work on Fedora is the desktop
mime-types are added as package provides, which we can queried in
PackageKit. On Debian based distros this is far more straightforward as
a destop file cache is available (regenerated from the repo). I'm aiming
to have the yum backend and apt backends functional in a few weeks, and
for the others to follow shortly.

As an aside, PackageKit is currently installing Pango fonts[2] and
GStreamer codecs[3] on demand. Application installing is the next
logical step in my opinion.

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.

Richard Hughes

[1] http://www.packagekit.org/img/gpk-client-mime-type.png
[2] http://www.packagekit.org/img/gpk-client-font.png
[3] http://www.packagekit.org/img/gpk-client-codecs.png

Index: configure.in
===================================================================
--- configure.in	(revision 14796)
+++ configure.in	(working copy)
@@ -317,6 +317,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 +484,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)
@@ -1022,7 +1022,37 @@
 	return response == GTK_RESPONSE_YES;
 }
 
+#ifdef ENABLE_PACKAGEKIT
 static void
+search_for_application (ActivateParameters *parameters, const gchar *mime_type)
+{
+	GtkWidget *dialog;
+	GError *error = NULL;
+	char *command;
+
+	/* requires gnome-packagekit */
+	command = g_strdup_printf ("gpk-install-mime-type %s", mime_type);
+	gdk_spawn_command_line_on_screen (gtk_window_get_screen (GTK_WINDOW (parameters->parent_window)),
+					  command, &error);
+	if (error) {
+		dialog = gtk_message_dialog_new (GTK_WINDOW (parameters->parent_window),
+						 GTK_DIALOG_MODAL,
+						 GTK_MESSAGE_ERROR,
+						 GTK_BUTTONS_OK,
+						 _("Could not execute software helper: \n%s"),
+						 error->message);
+		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);
+		g_error_free (error);
+	}
+	g_free (command);
+}
+#endif
+
+static void
 activate_files (ActivateParameters *parameters)
 {
 	NautilusWindowInfo *window_info;
@@ -1229,7 +1259,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 +1284,40 @@
 		
 		g_free (uri_for_display);
 
+#ifdef ENABLE_PACKAGEKIT
+		/* 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
 		g_free (error_message);
 	}
 


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