[gnome-software] Move the PackageKit historical updates logic into the plugin
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Move the PackageKit historical updates logic into the plugin
- Date: Wed, 27 Jan 2016 14:35:06 +0000 (UTC)
commit 0c4797934d407d74884f48f1aeb8e5ab61ca0de4
Author: Richard Hughes <richard hughsie com>
Date: Wed Jan 27 14:24:57 2016 +0000
Move the PackageKit historical updates logic into the plugin
This does mean adding a few error codes, but means we can make showing the
offline updates failure dialog a lot easier. Since we already got all the
information we need in the update monitor it makes no sense to re-get this
data when we could just save one GError.
Plus, it's two less source files to worry about...
po/POTFILES.in | 1 -
src/Makefile.am | 2 -
src/gs-application.c | 3 +-
src/gs-offline-updates.c | 303 ----------------------------
src/gs-offline-updates.h | 37 ----
src/gs-plugin.h | 4 +
src/gs-update-dialog.c | 1 -
src/gs-update-monitor.c | 172 ++++++++++++++++-
src/gs-update-monitor.h | 8 +-
src/plugins/gs-plugin-packagekit-offline.c | 89 +++++++-
10 files changed, 259 insertions(+), 361 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f4cb828..643e044 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -19,7 +19,6 @@ src/gs-hiding-box.c
src/gs-history-dialog.c
[type: gettext/glade]src/gs-history-dialog.ui
src/gs-main.c
-src/gs-offline-updates.c
src/gs-page.c
src/gs-plugin-loader.c
src/gs-popular-tile.c
diff --git a/src/Makefile.am b/src/Makefile.am
index a0c4c1f..bb27a78 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -174,8 +174,6 @@ gnome_software_SOURCES = \
gs-update-monitor.h \
gs-vendor.c \
gs-vendor.h \
- gs-offline-updates.c \
- gs-offline-updates.h \
gs-plugin-loader.c \
gs-plugin-loader.h \
gs-plugin-loader-sync.c \
diff --git a/src/gs-application.c b/src/gs-application.c
index 98beeb5..0af7b33 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -40,7 +40,6 @@
#include "gs-shell.h"
#include "gs-update-monitor.h"
#include "gs-shell-search-provider.h"
-#include "gs-offline-updates.h"
#include "gs-folders.h"
#include "gs-utils.h"
@@ -524,7 +523,7 @@ show_offline_updates_error (GSimpleAction *action,
initialize_ui_and_present_window (app);
gs_shell_set_mode (app->shell, GS_SHELL_MODE_UPDATES);
- gs_offline_updates_show_error (app->shell);
+ gs_update_monitor_show_error (app->update_monitor, app->shell);
}
static void
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index c737dc8..3cfdf7b 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -80,6 +80,10 @@ struct GsPlugin {
typedef enum {
GS_PLUGIN_ERROR_FAILED,
GS_PLUGIN_ERROR_NOT_SUPPORTED,
+ GS_PLUGIN_ERROR_CANCELLED,
+ GS_PLUGIN_ERROR_NO_NETWORK,
+ GS_PLUGIN_ERROR_NO_SECURITY,
+ GS_PLUGIN_ERROR_NO_SPACE,
GS_PLUGIN_ERROR_LAST
} GsPluginError;
diff --git a/src/gs-update-dialog.c b/src/gs-update-dialog.c
index 7acb8a7..a44b5a3 100644
--- a/src/gs-update-dialog.c
+++ b/src/gs-update-dialog.c
@@ -27,7 +27,6 @@
#include "gs-update-dialog.h"
#include "gs-app-row.h"
#include "gs-markdown.h"
-#include "gs-offline-updates.h"
#include "gs-update-list.h"
#include "gs-utils.h"
diff --git a/src/gs-update-monitor.c b/src/gs-update-monitor.c
index 8f8b311..330aa6a 100644
--- a/src/gs-update-monitor.c
+++ b/src/gs-update-monitor.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2013-2015 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2016 Richard Hughes <richard hughsie com>
* Copyright (C) 2013 Matthias Clasen <mclasen redhat com>
*
* Licensed under the GNU General Public License Version 2
@@ -30,7 +30,6 @@
#include "gs-update-monitor.h"
#include "gs-plugin-loader.h"
#include "gs-utils.h"
-#include "gs-offline-updates.h"
struct _GsUpdateMonitor {
GObject parent;
@@ -39,6 +38,7 @@ struct _GsUpdateMonitor {
GCancellable *cancellable;
GSettings *settings;
GsPluginLoader *plugin_loader;
+ GError *last_offline_error;
guint cleanup_notifications_id; /* at startup */
guint check_startup_id; /* 60s after startup */
@@ -411,6 +411,11 @@ get_updates_historical_cb (GObject *object, GAsyncResult *res, gpointer data)
g_application_withdraw_notification (monitor->application,
"updates-available");
} else {
+ /* save this in case the user clicks the
+ * 'Show Details' button from the notification below */
+ g_clear_error (&monitor->last_offline_error);
+ monitor->last_offline_error = g_error_copy (error);
+
/* TRANSLATORS: title when we offline updates have failed */
notification = g_notification_new (_("Software Updates Failed"));
/* TRANSLATORS: message when we offline updates have failed */
@@ -474,6 +479,168 @@ cleanup_notifications_cb (gpointer user_data)
}
static void
+do_not_expand (GtkWidget *child, gpointer data)
+{
+ gtk_container_child_set (GTK_CONTAINER (gtk_widget_get_parent (child)),
+ child, "expand", FALSE, "fill", FALSE, NULL);
+}
+
+static gboolean
+unset_focus (GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+ if (GTK_IS_WINDOW (widget))
+ gtk_window_set_focus(GTK_WINDOW (widget), NULL);
+ return FALSE;
+}
+
+/**
+ * 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, *tv;
+ GtkTextBuffer *buffer;
+ GList *children;
+ g_autoptr(GString) msg = NULL;
+
+ if (!details)
+ return;
+ g_return_if_fail (dialog != NULL);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+
+ msg = g_string_new ("");
+ g_string_append_printf (msg, "%s\n\n%s",
+ /* TRANSLATORS: these are show_detailed_error 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);
+
+ /* Find the secondary label and set its width_chars. */
+ /* Otherwise the label will tend to expand vertically. */
+ children = gtk_container_get_children (GTK_CONTAINER (message_area));
+ if (children && children->next && GTK_IS_LABEL (children->next->data)) {
+ gtk_label_set_width_chars (GTK_LABEL (children->next->data), 40);
+ }
+
+ label = gtk_label_new (_("Details"));
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_visible (label, TRUE);
+ gtk_box_pack_start (GTK_BOX (message_area), label, FALSE, FALSE, 0);
+
+ 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_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (sw), 150);
+ gtk_widget_set_visible (sw, TRUE);
+
+ tv = gtk_text_view_new ();
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
+ gtk_text_view_set_editable (GTK_TEXT_VIEW (tv), FALSE);
+ gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD);
+ gtk_style_context_add_class (gtk_widget_get_style_context (tv),
+ "update-failed-details");
+ gtk_text_buffer_set_text (buffer, msg->str, -1);
+ gtk_widget_set_visible (tv, TRUE);
+
+ gtk_container_add (GTK_CONTAINER (sw), tv);
+ gtk_box_pack_end (GTK_BOX (message_area), sw, TRUE, TRUE, 0);
+
+ g_signal_connect (dialog, "map-event", G_CALLBACK (unset_focus), NULL);
+}
+
+void
+gs_update_monitor_show_error (GsUpdateMonitor *monitor, GsShell *shell)
+{
+ const gchar *title;
+ const gchar *msg;
+ gboolean show_detailed_error;
+ GtkWidget *dialog;
+
+ /* can this happen in reality? */
+ if (monitor->last_offline_error == NULL)
+ return;
+
+ /* TRANSLATORS: this is when the offline update failed */
+ title = _("Failed To Update");
+
+ switch (monitor->last_offline_error->code) {
+ case GS_PLUGIN_ERROR_NOT_SUPPORTED:
+ /* TRANSLATORS: the user must have updated manually after
+ * the updates were prepared */
+ msg = _("The system was already up to date.");
+ show_detailed_error = TRUE;
+ break;
+ case GS_PLUGIN_ERROR_CANCELLED:
+ /* TRANSLATORS: the user aborted the update manually */
+ msg = _("The update was cancelled.");
+ show_detailed_error = FALSE;
+ break;
+ case GS_PLUGIN_ERROR_NO_NETWORK:
+ /* TRANSLATORS: the package manager needed to download
+ * something with no network available */
+ msg = _("Internet access was required but wasn’t available. "
+ "Please make sure that you have internet access and try again.");
+ show_detailed_error = FALSE;
+ break;
+ case GS_PLUGIN_ERROR_NO_SECURITY:
+ /* TRANSLATORS: if the package is not signed correctly */
+ msg = _("There were security issues with the update. "
+ "Please consult your software provider for more details.");
+ show_detailed_error = TRUE;
+ break;
+ case GS_PLUGIN_ERROR_NO_SPACE:
+ /* TRANSLATORS: we ran out of disk space */
+ msg = _("There wasn’t enough disk space. Please free up some space and try again.");
+ show_detailed_error = FALSE;
+ break;
+ default:
+ /* TRANSLATORS: We didn't handle the error type */
+ msg = _("We’re sorry: the update failed to install. "
+ "Please wait for another update and try again. "
+ "If the problem persists, contact your software provider.");
+ show_detailed_error = TRUE;
+ break;
+ }
+
+ dialog = gtk_message_dialog_new_with_markup (gs_shell_get_window (shell),
+ 0,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE,
+ "<big><b>%s</b></big>", title);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", msg);
+ if (show_detailed_error) {
+ insert_details_widget (GTK_MESSAGE_DIALOG (dialog),
+ monitor->last_offline_error->message);
+ }
+ g_signal_connect_swapped (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog);
+ gtk_widget_show (dialog);
+}
+
+static void
gs_update_monitor_init (GsUpdateMonitor *monitor)
{
monitor->settings = g_settings_new ("org.gnome.software");
@@ -538,6 +705,7 @@ gs_update_monitor_finalize (GObject *object)
GsUpdateMonitor *monitor = GS_UPDATE_MONITOR (object);
g_application_release (monitor->application);
+ g_clear_error (&monitor->last_offline_error);
G_OBJECT_CLASS (gs_update_monitor_parent_class)->finalize (object);
}
diff --git a/src/gs-update-monitor.h b/src/gs-update-monitor.h
index bc9ce8a..d30552d 100644
--- a/src/gs-update-monitor.h
+++ b/src/gs-update-monitor.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2016 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -23,7 +23,9 @@
#define __GS_UPDATE_MONITOR_H
#include <glib-object.h>
+
#include "gs-application.h"
+#include "gs-shell.h"
G_BEGIN_DECLS
@@ -31,7 +33,9 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (GsUpdateMonitor, gs_update_monitor, GS, UPDATE_MONITOR, GObject)
-GsUpdateMonitor *gs_update_monitor_new (GsApplication *app);
+GsUpdateMonitor *gs_update_monitor_new (GsApplication *app);
+void gs_update_monitor_show_error (GsUpdateMonitor *monitor,
+ GsShell *shell);
GPermission *gs_update_monitor_permission_get (void);
gboolean gs_update_monitor_is_managed (void);
diff --git a/src/plugins/gs-plugin-packagekit-offline.c b/src/plugins/gs-plugin-packagekit-offline.c
index 831c3dc..a386858 100644
--- a/src/plugins/gs-plugin-packagekit-offline.c
+++ b/src/plugins/gs-plugin-packagekit-offline.c
@@ -21,6 +21,9 @@
#include <config.h>
+#define I_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE
+#include <packagekit-glib2/packagekit.h>
+
#include <gs-plugin.h>
/*
@@ -44,6 +47,65 @@ gs_plugin_get_name (void)
#define PK_OFFLINE_UPDATE_RESULTS_FILENAME "/var/lib/PackageKit/offline-update-competed"
/**
+ * gs_plugin_packagekit_convert_error:
+ */
+static gboolean
+gs_plugin_packagekit_convert_error (GError **error,
+ PkErrorEnum error_enum,
+ const gchar *details)
+{
+ switch (error_enum) {
+ 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:
+ case PK_ERROR_ENUM_UNFINISHED_TRANSACTION:
+ g_set_error_literal (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_NO_NETWORK,
+ details);
+ 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:
+ g_set_error_literal (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_NO_SECURITY,
+ details);
+ break;
+ case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
+ g_set_error_literal (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_CANCELLED,
+ details);
+ break;
+ case PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE:
+ case PK_ERROR_ENUM_UPDATE_NOT_FOUND:
+ g_set_error_literal (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_NOT_SUPPORTED,
+ details);
+ break;
+ case PK_ERROR_ENUM_NO_SPACE_ON_DEVICE:
+ g_set_error_literal (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_NO_SPACE,
+ details);
+ break;
+ default:
+ g_set_error_literal (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_FAILED,
+ details);
+ break;
+ }
+ return FALSE;
+}
+
+/**
* gs_plugin_add_updates_historical:
*/
gboolean
@@ -56,7 +118,6 @@ gs_plugin_add_updates_historical (GsPlugin *plugin,
guint64 mtime;
guint i;
g_auto(GStrv) package_ids = NULL;
- g_autofree gchar *error_details = NULL;
g_autofree gchar *packages = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GFileInfo) info = NULL;
@@ -92,17 +153,23 @@ gs_plugin_add_updates_historical (GsPlugin *plugin,
"Success",
NULL);
if (!ret) {
- error_details = g_key_file_get_string (key_file,
- PK_OFFLINE_UPDATE_RESULTS_GROUP,
- "ErrorDetails",
- error);
- if (error_details == NULL)
+ g_autofree gchar *code = NULL;
+ g_autofree gchar *details = NULL;
+ code = g_key_file_get_string (key_file,
+ PK_OFFLINE_UPDATE_RESULTS_GROUP,
+ "ErrorCode",
+ error);
+ if (code == NULL)
return FALSE;
- g_set_error_literal (error,
- GS_PLUGIN_ERROR,
- GS_PLUGIN_ERROR_FAILED,
- error_details);
- return FALSE;
+ details = g_key_file_get_string (key_file,
+ PK_OFFLINE_UPDATE_RESULTS_GROUP,
+ "ErrorDetails",
+ error);
+ if (details == NULL)
+ return FALSE;
+ return gs_plugin_packagekit_convert_error (error,
+ pk_error_enum_from_string (code),
+ details);
}
/* get list of package-ids */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]