[gnome-software/gnome-3-14] offline updates: GtkExpander in the error message dialog



commit defde71598a0fc815ee4db331831b1b41d40f06a
Author: Rafal Luzynski <digitalfreak lingonborough com>
Date:   Wed May 6 02:51:17 2015 +0200

    offline updates: GtkExpander in the error message dialog
    
    The previous patch turned out to be not so perfect because
    the detailed error message can be too wide, not only too high.
    This patch introduces: GtkExpander, wrapped label inside it,
    and few other minor improvements.
    
    This is not the final solution of the problem but is backward
    compatible and can be backported to the old branches.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=748936

 src/gs-offline-updates.c |  253 +++++++++++++++++++++++++++++++++++-----------
 1 files changed, 194 insertions(+), 59 deletions(-)
---
diff --git a/src/gs-offline-updates.c b/src/gs-offline-updates.c
index 28fde90..5438e04 100644
--- a/src/gs-offline-updates.c
+++ b/src/gs-offline-updates.c
@@ -24,50 +24,34 @@
 #include <glib/gi18n.h>
 #include <packagekit-glib2/packagekit.h>
 #include <polkit/polkit.h>
+#include <pango/pango-font.h>
 
 #include "gs-offline-updates.h"
 #include "gs-utils.h"
 
 static void
-gs_offline_updates_label_allocate_cb (GtkWidget *label,
-                                     GdkRectangle *allocation, gpointer data)
+expander_cb (GtkExpander *expander, GParamSpec *pspec, GtkWindow *dialog)
 {
-       GtkScrolledWindow *sw = GTK_SCROLLED_WINDOW (data);
-       gtk_scrolled_window_set_min_content_height (
-                       sw, MIN (allocation->height, 300));
+       gtk_window_set_resizable (dialog, gtk_expander_get_expanded (expander));
 }
 
-void
-gs_offline_updates_show_error (void)
+static void
+do_not_expand (GtkWidget *child, gpointer data)
 {
-       const gchar *title;
-       gboolean show_geeky = FALSE;
-       GString *msg;
-       GtkWidget *dialog, *message_area, *sw, *label;
-       GError *error = NULL;
-       PkResults *results = NULL;
-       PkError *pk_error = NULL;
-
-       results = pk_offline_get_results (NULL);
-       if (results == NULL)
-               goto out;
-       pk_error = pk_results_get_error_code (results);
-       if (pk_error == NULL)
-               goto out;
+       gtk_container_child_set (GTK_CONTAINER (gtk_widget_get_parent (child)),
+                                child, "expand", FALSE, "fill", FALSE, NULL);
+}
 
-       /* can this happen in reality? */
-       if (pk_results_get_exit_code (results) == PK_EXIT_ENUM_SUCCESS)
-               goto out;
+static const gchar *
+prepare_secondary_text (PkError *pk_error)
+{
+       g_return_val_if_fail (pk_error != NULL, NULL);
 
-       /* TRANSLATORS: this is when the offline update failed */
-       title = _("Failed To Update");
-       msg = g_string_new ("");
        switch (pk_error_get_code (pk_error)) {
        case PK_ERROR_ENUM_UNFINISHED_TRANSACTION:
                /* TRANSLATORS: the transaction could not be completed
                 * as a previous transaction was unfinished */
-               g_string_append (msg, _("A previous update was unfinished."));
-               show_geeky = TRUE;
+               return _("A previous update was unfinished.");
                break;
        case PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED:
        case PK_ERROR_ENUM_NO_CACHE:
@@ -76,7 +60,7 @@ gs_offline_updates_show_error (void)
        case PK_ERROR_ENUM_CANNOT_FETCH_SOURCES:
                /* TRANSLATORS: the package manager needed to download
                 * something with no network available */
-               g_string_append (msg, _("Network access was required but not available."));
+               return _("Network access was required but not available.");
                break;
        case PK_ERROR_ENUM_BAD_GPG_SIGNATURE:
        case PK_ERROR_ENUM_CANNOT_UPDATE_REPO_UNSIGNED:
@@ -85,8 +69,7 @@ gs_offline_updates_show_error (void)
        case PK_ERROR_ENUM_PACKAGE_CORRUPT:
                /* TRANSLATORS: if the package is not signed correctly
                 *  */
-               g_string_append (msg, _("An update was not signed in the correct way."));
-               show_geeky = TRUE;
+               return _("An update was not signed in the correct way.");
                break;
        case PK_ERROR_ENUM_DEP_RESOLUTION_FAILED:
        case PK_ERROR_ENUM_FILE_CONFLICTS:
@@ -95,22 +78,21 @@ gs_offline_updates_show_error (void)
                /* TRANSLATORS: the transaction failed in a way the user
                 * probably cannot comprehend. Package management systems
                 * really are teh suck.*/
-               g_string_append (msg, _("The update could not be completed."));
-               show_geeky = TRUE;
+               return _("The update could not be completed.");
                break;
        case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
                /* TRANSLATORS: the user aborted the update manually */
-               g_string_append (msg, _("The update was cancelled."));
+               return _("The update was cancelled.");
                break;
        case PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE:
        case PK_ERROR_ENUM_UPDATE_NOT_FOUND:
                /* TRANSLATORS: the user must have updated manually after
                 * the updates were prepared */
-               g_string_append (msg, _("An offline update was requested but no packages required 
updating."));
+               return _("An offline update was requested but no packages required updating.");
                break;
        case PK_ERROR_ENUM_NO_SPACE_ON_DEVICE:
                /* TRANSLATORS: we ran out of disk space */
-               g_string_append (msg, _("No space was left on the drive."));
+               return _("No space was left on the drive.");
                break;
        case PK_ERROR_ENUM_PACKAGE_FAILED_TO_BUILD:
        case PK_ERROR_ENUM_PACKAGE_FAILED_TO_INSTALL:
@@ -118,42 +100,196 @@ gs_offline_updates_show_error (void)
                /* TRANSLATORS: the update process failed in a general
                 * way, usually this message will come from source distros
                 * like gentoo */
-               g_string_append (msg, _("An update failed to install correctly."));
-               show_geeky = TRUE;
+               return _("An update failed to install correctly.");
                break;
        default:
                /* TRANSLATORS: We didn't handle the error type */
-               g_string_append (msg, _("The offline update failed in an unexpected way."));
-               show_geeky = TRUE;
+               return _("The offline update failed in an unexpected way.");
                break;
        }
-       if (show_geeky) {
-               g_string_append_printf (msg, "\n%s\n\n%s",
-                                       /* TRANSLATORS: these are geeky messages from the
-                                        * package manager no mortal is supposed to understand,
-                                        * but google might know what they mean */
-                                       _("Detailed errors from the package manager follow:"),
-                                       pk_error_get_details (pk_error));
+}
+
+static const gchar *
+prepare_details (PkError *pk_error)
+{
+       gboolean show_geeky;
+       g_return_val_if_fail (pk_error != NULL, NULL);
+
+       switch (pk_error_get_code (pk_error)) {
+       case PK_ERROR_ENUM_UNFINISHED_TRANSACTION:
+               /* A previous update was unfinished */
+               show_geeky = TRUE;
+               break;
+       case PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED:
+       case PK_ERROR_ENUM_NO_CACHE:
+       case PK_ERROR_ENUM_NO_NETWORK:
+       case PK_ERROR_ENUM_NO_MORE_MIRRORS_TO_TRY:
+       case PK_ERROR_ENUM_CANNOT_FETCH_SOURCES:
+               /* Network access was required but not available */
+               show_geeky = FALSE;
+               break;
+       case PK_ERROR_ENUM_BAD_GPG_SIGNATURE:
+       case PK_ERROR_ENUM_CANNOT_UPDATE_REPO_UNSIGNED:
+       case PK_ERROR_ENUM_GPG_FAILURE:
+       case PK_ERROR_ENUM_MISSING_GPG_SIGNATURE:
+       case PK_ERROR_ENUM_PACKAGE_CORRUPT:
+               /* An update was not signed in the correct way */
+               show_geeky = TRUE;
+               break;
+       case PK_ERROR_ENUM_DEP_RESOLUTION_FAILED:
+       case PK_ERROR_ENUM_FILE_CONFLICTS:
+       case PK_ERROR_ENUM_INCOMPATIBLE_ARCHITECTURE:
+       case PK_ERROR_ENUM_PACKAGE_CONFLICTS:
+               /* The update could not be completed */
+               show_geeky = TRUE;
+               break;
+       case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
+               /* The update was cancelled */
+               show_geeky = FALSE;
+               break;
+       case PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE:
+       case PK_ERROR_ENUM_UPDATE_NOT_FOUND:
+               /* An offline update was requested but no packages required updating */
+               show_geeky = FALSE;
+               break;
+       case PK_ERROR_ENUM_NO_SPACE_ON_DEVICE:
+               /* No space was left on the drive */
+               show_geeky = FALSE;
+               break;
+       case PK_ERROR_ENUM_PACKAGE_FAILED_TO_BUILD:
+       case PK_ERROR_ENUM_PACKAGE_FAILED_TO_INSTALL:
+       case PK_ERROR_ENUM_PACKAGE_FAILED_TO_REMOVE:
+               /* An update failed to install correctly */
+               show_geeky = TRUE;
+               break;
+       default:
+               /* The offline update failed in an unexpected way */
+               show_geeky = TRUE;
+               break;
        }
-       dialog = gtk_message_dialog_new (NULL,
-                                        0,
-                                        GTK_MESSAGE_INFO,
-                                        GTK_BUTTONS_CLOSE,
-                                        "%s", title);
 
-       message_area = gtk_message_dialog_get_message_area (GTK_MESSAGE_DIALOG (dialog));
+       if (show_geeky)
+               return pk_error_get_details (pk_error);
+       else
+               return NULL;
+}
+
+/**
+ * insert_details_widget:
+ * @dialog: the message dialog where the widget will be inserted
+ * @details: (allow-none): the detailed message text to display
+ *
+ * Inserts a widget displaying the detailed message into the message dialog.
+ * Does nothing if @details is %NULL so it is safe to call this function
+ * without checking if there is anything to display.
+ */
+static void
+insert_details_widget (GtkMessageDialog *dialog, const gchar *details)
+{
+       GtkWidget *message_area, *sw, *label;
+       GtkWidget *box, *expander;
+       PangoFontMetrics *metrics;
+       int lineheight;
+       GString *msg;
+
+       if (!details)
+               return;
+       g_return_if_fail (dialog != NULL);
+
+       msg = g_string_new ("");
+       g_string_append_printf (msg, "%s\n\n%s",
+                               /* TRANSLATORS: these are geeky messages from the
+                                * package manager no mortal is supposed to understand,
+                                * but google might know what they mean */
+                               _("Detailed errors from the package manager follow:"),
+                               details);
+
+       message_area = gtk_message_dialog_get_message_area (dialog);
        g_assert (GTK_IS_BOX (message_area));
+       /* make the hbox expand */
+       box = gtk_widget_get_parent (message_area);
+       gtk_container_child_set (GTK_CONTAINER (gtk_widget_get_parent (box)), box,
+                                "expand", TRUE, "fill", TRUE, NULL);
+       /* make the labels not expand */
+       gtk_container_foreach (GTK_CONTAINER (message_area), do_not_expand, NULL);
+
+       /* TODO: In 3.18 the label will be "Details:" (":" appended) */
+       expander = gtk_expander_new (_("Details"));
+       gtk_widget_set_visible (expander, TRUE);
        sw = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+                                            GTK_SHADOW_IN);
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
-                                       GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+                                       GTK_POLICY_NEVER,
+                                       GTK_POLICY_AUTOMATIC);
        gtk_widget_set_visible (sw, TRUE);
 
        label = gtk_label_new (msg->str);
+       gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+       gtk_label_set_line_wrap_mode (GTK_LABEL (label), GTK_WRAP_WORD);
+       gtk_widget_set_halign (label, GTK_ALIGN_START);
+       gtk_widget_set_valign (label, GTK_ALIGN_START);
+       gtk_label_set_xalign (GTK_LABEL (label), 0.0);
        gtk_widget_set_visible (label, TRUE);
-       g_signal_connect (label, "size-allocate",
-                       G_CALLBACK (gs_offline_updates_label_allocate_cb), sw);
+
+       /* Setup the minimum size of the text label */
+       gtk_label_set_width_chars (GTK_LABEL (label), 50);
+       metrics = pango_context_get_metrics (
+                       gtk_widget_get_pango_context (label), NULL, NULL);
+       lineheight = PANGO_PIXELS_CEIL (
+                       pango_font_metrics_get_ascent (metrics)
+                       + pango_font_metrics_get_descent (metrics));
+       pango_font_metrics_unref (metrics);
+       gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW (sw),
+                                                  5 * lineheight);
+
        gtk_container_add (GTK_CONTAINER (sw), label);
-       gtk_container_add (GTK_CONTAINER (message_area), sw);
+       gtk_container_add (GTK_CONTAINER (expander), sw);
+       gtk_box_pack_end (GTK_BOX (message_area), expander, TRUE, TRUE, 0);
+       g_signal_connect (expander, "notify::expanded",
+                         G_CALLBACK (expander_cb), dialog);
+
+       g_string_free (msg, TRUE);
+}
+
+void
+gs_offline_updates_show_error (void)
+{
+       const gchar *title;
+       const gchar *secondary;
+       const gchar *geeky;
+       GtkWidget *dialog;
+       GError *error = NULL;
+       PkError *pk_error = NULL;
+       PkResults *results = NULL;
+
+       results = pk_offline_get_results (NULL);
+       if (results == NULL)
+               goto out;
+       pk_error = pk_results_get_error_code (results);
+       if (pk_error == NULL)
+               goto out;
+
+       /* can this happen in reality? */
+       if (pk_results_get_exit_code (results) == PK_EXIT_ENUM_SUCCESS)
+               goto out;
+
+       /* TRANSLATORS: this is when the offline update failed */
+       title = _("Failed To Update");
+       secondary = prepare_secondary_text (pk_error);
+       geeky = prepare_details (pk_error);
+
+       dialog = gtk_message_dialog_new_with_markup (NULL,
+                                        0,
+                                        GTK_MESSAGE_INFO,
+                                        GTK_BUTTONS_CLOSE,
+                                        "<big><b>%s</b></big>", title);
+       if (secondary)
+               gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                                 "%s", secondary);
+
+       insert_details_widget (GTK_MESSAGE_DIALOG (dialog), geeky);
 
        g_signal_connect_swapped (dialog, "response",
                                  G_CALLBACK (gtk_widget_destroy),
@@ -165,7 +301,6 @@ gs_offline_updates_show_error (void)
                           error->message);
                g_error_free (error);
        }
-       g_string_free (msg, TRUE);
 out:
        if (pk_error != NULL)
                g_object_unref (pk_error);


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