Re: [rfc][patch] Add optional PackageKit hook to install new applications
- From: Richard Hughes <hughsient gmail com>
- To: Alexander Larsson <alexl redhat com>
- Cc: nautilus-list gnome org, Kenneth MacDonald <K MacDonald ed ac uk>
- Subject: Re: [rfc][patch] Add optional PackageKit hook to install new applications
- Date: Tue, 09 Dec 2008 12:36:45 +0000
On Tue, 2008-12-09 at 12:00 +0100, Alexander Larsson wrote:
> Not really. Just let it fall through and the activation will be
> destroyed. No need to keep it around paused.
Fair enough.
> I think you can just save (ref) the NautilusFile objects and some extra
> info, then after the install start over with
> nautilus_mime_activate_files().
Something like the attached (v.5)?
Richard.
Index: configure.in
===================================================================
--- configure.in (revision 14805)
+++ 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 14805)
+++ libnautilus-private/nautilus-mime-actions.c (working copy)
@@ -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,7 +1024,217 @@
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;
+} 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
+search_for_application_dbus_call_notify_cb (DBusGProxy *proxy, DBusGProxyCall *call, ActivateParametersInstall *parameters_install)
+{
+ 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;
+ }
+
+ /* 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);
+out:
+ /* we're done with this data now */
+ activate_parameters_install_free (parameters_install);
+}
+
+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,
+ NULL, NULL,
+ 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;
+ 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);
+
+#ifndef 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
+ if (!show_install_mime) {
+ /* show an unhelpful dialog */
+ eel_show_error_dialog (error_message,
+ _("There is no application installed for this file type"),
+ parameters->parent_window);
+ 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), "%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_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_swapped (dialog, "response", G_CALLBACK (application_unhandled_file_install), parameters_install);
+ gtk_widget_show_all (dialog);
+out:
+ g_free (error_message);
+}
+
+static void
activate_files (ActivateParameters *parameters)
{
NautilusWindowInfo *window_info;
@@ -1225,34 +1437,10 @@
}
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;
Index: libnautilus-private/apps_nautilus_preferences.schemas.in
===================================================================
--- libnautilus-private/apps_nautilus_preferences.schemas.in (revision 14805)
+++ 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 14805)
+++ libnautilus-private/nautilus-global-preferences.c (working copy)
@@ -280,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 14805)
+++ 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]