[yelp] Automatically install packages for missing documents



commit 231a2bf510a30b19419ef29f577eb952a7498bcc
Author: Shaun McCance <shaunm gnome org>
Date:   Wed Jan 5 10:14:04 2011 -0500

    Automatically install packages for missing documents

 libyelp/yelp-view.c    |    1 +
 src/yelp-application.c |  168 +++++++++++++++++++++++++++++++++++++++---------
 src/yelp-application.h |    6 ++-
 src/yelp-window.c      |  100 ++++++++++++++++++++++++----
 4 files changed, 229 insertions(+), 46 deletions(-)
---
diff --git a/libyelp/yelp-view.c b/libyelp/yelp-view.c
index e30d263..292d963 100644
--- a/libyelp/yelp-view.c
+++ b/libyelp/yelp-view.c
@@ -1464,6 +1464,7 @@ view_show_error_page (YelpView *view,
                             left, iconsize, left, iconsize, left, iconsize,
                             titlecolor, title, error->message);
     g_object_set (view, "state", YELP_VIEW_STATE_ERROR, NULL);
+    g_signal_emit (view, signals[LOADED], 0);
     g_signal_handler_block (view, priv->navigation_requested);
     webkit_web_view_load_string (WEBKIT_WEB_VIEW (view),
                                  page,
diff --git a/src/yelp-application.c b/src/yelp-application.c
index cae00dd..713ef6a 100644
--- a/src/yelp-application.c
+++ b/src/yelp-application.c
@@ -45,6 +45,7 @@ static gboolean editor_mode = FALSE;
 
 enum {
     READ_LATER_CHANGED,
+    HELP_INSTALLED,
     LAST_SIGNAL
 };
 static gint signals[LAST_SIGNAL] = { 0 };
@@ -171,6 +172,14 @@ yelp_application_class_init (YelpApplicationClass *klass)
                       g_cclosure_marshal_VOID__STRING,
                       G_TYPE_NONE, 1, G_TYPE_STRING);
 
+    signals[HELP_INSTALLED] =
+        g_signal_new ("help-installed",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST,
+                      0, NULL, NULL,
+                      g_cclosure_marshal_VOID__STRING,
+                      G_TYPE_NONE, 1, G_TYPE_STRING);
+
     g_type_class_add_private (klass, sizeof (YelpApplicationPrivate));
 }
 
@@ -707,8 +716,8 @@ yelp_application_is_bookmarked (YelpBookmarks     *bookmarks,
     GSettings *settings;
     YelpApplication *app = YELP_APPLICATION (bookmarks);
 
-    g_return_if_fail (page_id);
-    g_return_if_fail (doc_uri);
+    g_return_val_if_fail (page_id, FALSE);
+    g_return_val_if_fail (doc_uri, FALSE);
 
     settings = application_get_doc_settings (app, doc_uri);
     if (settings == NULL)
@@ -783,33 +792,6 @@ yelp_application_get_bookmarks (YelpApplication *app,
     return g_settings_get_value (settings, "bookmarks");
 }
 
-static void
-packages_installed (GDBusConnection *connection,
-                    GAsyncResult *res,
-                    YelpApplication *app)
-{
-    GError *error = NULL;
-    g_dbus_connection_call_finish (connection, res, &error);
-    if (error) {
-        const gchar *err = NULL;
-        if (error->domain == G_DBUS_ERROR) {
-            if (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN)
-                err = _("You do not have PackageKit installed. Package installation links require PackageKit.");
-            else
-                err = error->message;
-        }
-        if (err != NULL) {
-            GtkWidget *dialog = gtk_message_dialog_new (NULL, 0,
-                                                        GTK_MESSAGE_ERROR,
-                                                        GTK_BUTTONS_CLOSE,
-                                                        "%s", err);
-            gtk_dialog_run ((GtkDialog *) dialog);
-            gtk_widget_destroy (dialog);
-        }
-        g_error_free (error);
-    }
-}
-
 void
 yelp_application_add_read_later (YelpApplication   *app,
                                  const gchar       *doc_uri,
@@ -880,14 +862,140 @@ yelp_application_get_read_later (YelpApplication *app,
     return g_settings_get_value (settings, "readlater");
 }
 
+typedef struct _YelpHelpInstallInfo YelpHelpInstallInfo;
+struct _YelpHelpInstallInfo {
+    YelpApplication *app;
+    gchar *uri;
+};
+
+static void
+help_installed (GDBusConnection     *connection,
+                GAsyncResult        *res,
+                YelpHelpInstallInfo *info)
+{
+    GError *error = NULL;
+    g_dbus_connection_call_finish (connection, res, &error);
+
+    if (error != NULL)
+        g_error_free (error);
+    else
+        g_signal_emit (info->app, signals[HELP_INSTALLED], 0, info->uri);
+
+    g_free (info->uri);
+    g_object_unref (info->app);
+    g_free (info);
+}
+
+void
+yelp_application_install_help (YelpApplication *app,
+                               const gchar     *uri,
+                               GtkWindow       *window)
+{
+    const gchar * const *datadirs = g_get_system_data_dirs ();
+    YelpApplicationPrivate *priv = GET_PRIV (app);
+    gint datadirs_i;
+    GVariantBuilder *strv;
+    guint32 xid = 0;
+    gboolean ghelp;
+    const gchar *docname;
+    gchar *docbook, *fname;
+    YelpHelpInstallInfo *info;
+
+    if (g_str_has_prefix (uri, "help:")) {
+        ghelp = FALSE;
+        docname = (const gchar *) uri + 5;
+    }
+    else if (g_str_has_prefix (uri, "ghelp:")) {
+        ghelp = TRUE;
+        docname = (const gchar *) uri + 6;
+    }
+    else
+        return;
+    docbook = g_strconcat (docname, ".xml", NULL);
+
+    info = g_new0 (YelpHelpInstallInfo, 1);
+    info->app = g_object_ref (app);
+    info->uri = g_strdup (uri);
+
+    if (window != NULL)
+        xid = gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (window)));
+
+    strv = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+    for (datadirs_i = 0; datadirs[datadirs_i] != NULL; datadirs_i++) {
+        if (ghelp) {
+            fname = g_build_filename (datadirs[datadirs_i], "gnome", "help",
+                                      docname, "C", "index.page", NULL);
+            g_variant_builder_add (strv, "s", fname);
+            g_free (fname);
+            fname = g_build_filename (datadirs[datadirs_i], "gnome", "help",
+                                      docname, "C", docbook, NULL);
+            g_variant_builder_add (strv, "s", fname);
+            g_free (fname);
+        }
+        else {
+            fname = g_build_filename (datadirs[datadirs_i], "help", "C",
+                                      docname, "index.page", NULL);
+            g_variant_builder_add (strv, "s", fname);
+            g_free (fname);
+            fname = g_build_filename (datadirs[datadirs_i], "help", "C",
+                                      docname, "index.docbook", NULL);
+            g_variant_builder_add (strv, "s", fname);
+            g_free (fname);
+        }
+    }
+    g_free (docbook);
+    g_dbus_connection_call (priv->connection,
+                            "org.freedesktop.PackageKit",
+                            "/org/freedesktop/PackageKit",
+                            "org.freedesktop.PackageKit.Modify",
+                            "InstallProvideFiles",
+                            g_variant_new ("(uass)", xid, strv, "hide-warning"),
+                            NULL,
+                            G_DBUS_CALL_FLAGS_NONE,
+                            G_MAXINT, NULL,
+                            (GAsyncReadyCallback) help_installed,
+                            info);
+    g_variant_builder_unref (strv);
+}
+
+static void
+packages_installed (GDBusConnection *connection,
+                    GAsyncResult    *res,
+                    YelpApplication *app)
+{
+    GError *error = NULL;
+    g_dbus_connection_call_finish (connection, res, &error);
+    if (error) {
+        const gchar *err = NULL;
+        if (error->domain == G_DBUS_ERROR) {
+            if (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN)
+                err = _("You do not have PackageKit. Package install links require PackageKit.");
+            else
+                err = error->message;
+        }
+        if (err != NULL) {
+            GtkWidget *dialog = gtk_message_dialog_new (NULL, 0,
+                                                        GTK_MESSAGE_ERROR,
+                                                        GTK_BUTTONS_CLOSE,
+                                                        "%s", err);
+            gtk_dialog_run ((GtkDialog *) dialog);
+            gtk_widget_destroy (dialog);
+        }
+        g_error_free (error);
+    }
+}
+
 void
 yelp_application_install_package (YelpApplication  *app,
                                   const gchar      *pkg,
-                                  const gchar      *alt)
+                                  const gchar      *alt,
+                                  GtkWindow        *window)
 {
     GVariantBuilder *strv;
     YelpApplicationPrivate *priv = GET_PRIV (app);
     guint32 xid = 0;
+    if (window != NULL)
+        xid = gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (window)));
     strv = g_variant_builder_new (G_VARIANT_TYPE ("as"));
     g_variant_builder_add (strv, "s", pkg);
     g_dbus_connection_call (priv->connection,
diff --git a/src/yelp-application.h b/src/yelp-application.h
index 35ccbde..fa95294 100644
--- a/src/yelp-application.h
+++ b/src/yelp-application.h
@@ -88,8 +88,12 @@ void              yelp_application_remove_read_later    (YelpApplication   *app,
                                                          const gchar       *full_uri);
 GVariant *        yelp_application_get_read_later       (YelpApplication   *app,
                                                          const gchar       *doc_uri);
+void              yelp_application_install_help         (YelpApplication   *app,
+                                                         const gchar       *uri,
+                                                         GtkWindow         *window);
 void              yelp_application_install_package      (YelpApplication   *app,
                                                          const gchar       *pkg,
-                                                         const gchar       *alt);
+                                                         const gchar       *alt,
+                                                         GtkWindow         *window);
 
 #endif /* __YELP_APPLICATION_H__ */
diff --git a/src/yelp-window.c b/src/yelp-window.c
index 7605d11..a0febbf 100644
--- a/src/yelp-window.c
+++ b/src/yelp-window.c
@@ -95,6 +95,9 @@ static void          app_read_later_changed       (YelpApplication    *app,
 static void          app_bookmarks_changed        (YelpApplication    *app,
                                                    const gchar        *doc_uri,
                                                    YelpWindow         *window);
+static void          app_help_installed           (YelpApplication    *app,
+                                                   const gchar        *doc_uri,
+                                                   YelpWindow         *window);
 static void          window_set_bookmarks         (YelpWindow         *window,
                                                    const gchar        *doc_uri);
 static void          window_set_bookmark_action   (YelpWindow         *window);
@@ -226,6 +229,9 @@ struct _YelpWindowPrivate {
     GtkListStore *bookmarks_store;
     gulong        bookmarks_changed;
 
+    gulong        read_later_changed;
+    gulong        help_installed;
+
     /* no refs on these, owned by containers */
     YelpView *view;
     GtkWidget *vbox_view;
@@ -368,11 +374,21 @@ yelp_window_dispose (GObject *object)
         priv->bookmark_actions = NULL;
     }
 
+    if (priv->read_later_changed) {
+        g_source_remove (priv->read_later_changed);
+        priv->read_later_changed = 0;
+    }
+
     if (priv->bookmarks_changed) {
         g_source_remove (priv->bookmarks_changed);
         priv->bookmarks_changed = 0;
     }
 
+    if (priv->help_installed) {
+        g_source_remove (priv->help_installed);
+        priv->help_installed = 0;
+    }
+
     if (priv->align_location) {
         g_object_unref (priv->align_location);
         priv->align_location = NULL;
@@ -468,7 +484,9 @@ window_construct (YelpWindow *window)
     yelp_view_add_link_action (priv->view, action,
                                (YelpViewActionValidFunc) view_is_xref_uri,
                                window);
-    g_signal_connect (priv->application, "read-later-changed", G_CALLBACK (app_read_later_changed), window);
+    priv->read_later_changed =
+        g_signal_connect (priv->application, "read-later-changed",
+                          G_CALLBACK (app_read_later_changed), window);
 
     priv->vbox_full = gtk_vbox_new (FALSE, 3);
     gtk_container_add (GTK_CONTAINER (window), priv->vbox_full);
@@ -606,6 +624,10 @@ window_construct (YelpWindow *window)
     gtk_drag_dest_add_uri_targets (GTK_WIDGET (window));
     g_signal_connect (window, "drag-data-received",
                       G_CALLBACK (window_drag_received), NULL);
+
+    priv->help_installed =
+        g_signal_connect (priv->application, "help-installed",
+                          G_CALLBACK (app_help_installed), window);
 }
 
 /******************************************************************************/
@@ -883,6 +905,36 @@ app_bookmarks_changed (YelpApplication *app,
     g_object_unref (uri);
 }
 
+static void
+app_help_installed (YelpApplication  *app,
+                    const gchar      *doc_uri,
+                    YelpWindow       *window)
+{
+    YelpViewState state;
+    YelpWindowPrivate *priv = GET_PRIV (window);
+
+    g_object_get (priv->view, "state", &state, NULL);
+
+    if (state == YELP_VIEW_STATE_ERROR) {
+        YelpUri *uri;
+        gchar *view_doc_uri;
+
+        g_object_get (priv->view, "yelp-uri", &uri, NULL);
+        if (uri == NULL)
+            return;
+        view_doc_uri = yelp_uri_get_document_uri (uri);
+
+        if (g_str_equal (view_doc_uri, doc_uri)) {
+            gchar *fulluri = yelp_uri_get_canonical_uri (uri);
+            yelp_view_load (priv->view, fulluri);
+            g_free (fulluri);
+        }
+
+        g_free (view_doc_uri);
+        g_object_unref (uri);
+    }
+}
+
 typedef struct _YelpMenuEntry YelpMenuEntry;
 struct _YelpMenuEntry {
     gchar *page_id;
@@ -1429,7 +1481,8 @@ view_external_uri (YelpView   *view,
     if (g_str_has_prefix (struri, "install:")) {
         YelpWindowPrivate *priv = GET_PRIV (window);
         gchar *pkg = struri + 8;
-        yelp_application_install_package (priv->application, pkg, "");
+        yelp_application_install_package (priv->application, pkg, "",
+                                          (GtkWindow *) window);
     }
     else
         g_app_info_launch_default_for_uri (struri, NULL, NULL);
@@ -1452,28 +1505,45 @@ view_loaded (YelpView   *view,
 {
 
     YelpUri *uri;
-    gchar *doc_uri, *page_id, *icon, *title;
+    gchar *doc_uri;
+    YelpViewState state;
     YelpWindowPrivate *priv = GET_PRIV (window);
 
     g_object_get (view,
                   "yelp-uri", &uri,
-                  "page-id", &page_id,
-                  "page-icon", &icon,
-                  "page-title", &title,
+                  "state", &state,
                   NULL);
     doc_uri = yelp_uri_get_document_uri (uri);
-    yelp_application_update_bookmarks (priv->application,
-                                       doc_uri,
-                                       page_id,
-                                       icon,
-                                       title);
     gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), NULL);
-    g_free (page_id);
-    g_free (icon);
-    g_free (title);
 
-    app_read_later_changed (priv->application, doc_uri, window);
+    if (state == YELP_VIEW_STATE_ERROR) {
+        if (yelp_uri_get_document_type (uri) == YELP_URI_DOCUMENT_TYPE_NOT_FOUND) {
+            if (g_str_has_prefix (doc_uri, "ghelp:") ||
+                g_str_has_prefix (doc_uri, "help:")) {
+                yelp_application_install_help (priv->application, doc_uri,
+                                               (GtkWindow *) window);
+            }
+        }
+    }
+    else {
+        gchar *page_id, *icon, *title;
+        g_object_get (view,
+                      "page-id", &page_id,
+                      "page-icon", &icon,
+                      "page-title", &title,
+                      NULL);
+        yelp_application_update_bookmarks (priv->application,
+                                           doc_uri,
+                                           page_id,
+                                           icon,
+                                           title);
+        app_read_later_changed (priv->application, doc_uri, window);
+        g_free (page_id);
+        g_free (icon);
+        g_free (title);
+    }
 
+    g_free (doc_uri);
     g_object_unref (uri);
 }
 



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