[gnome-software/wip/kalev/confirm-upgrade-removals] Add a dialog to confirm upgrade removals



commit 8bbb466960e7ddea53d02c296d512eabc8e28384
Author: Kalev Lember <klember redhat com>
Date:   Mon Jul 4 10:37:46 2016 +0200

    Add a dialog to confirm upgrade removals
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1336530

 po/POTFILES.in                   |    1 +
 src/Makefile.am                  |    3 +
 src/gnome-software.gresource.xml |    1 +
 src/gs-removal-dialog.c          |  185 ++++++++++++++++++++++++++++++++++++++
 src/gs-removal-dialog.h          |   43 +++++++++
 src/gs-removal-dialog.ui         |   49 ++++++++++
 src/gs-shell-updates.c           |   70 +++++++++++++--
 7 files changed, 343 insertions(+), 9 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 56562af..418aa16 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -25,6 +25,7 @@ src/gs-main.c
 src/gs-page.c
 src/gs-plugin-loader.c
 src/gs-popular-tile.c
+[type: gettext/glade]src/gs-removal-dialog.ui
 src/gs-review-dialog.c
 [type: gettext/glade]src/gs-review-dialog.ui
 [type: gettext/glade]src/gs-review-histogram.ui
diff --git a/src/Makefile.am b/src/Makefile.am
index 6af354f..ae71985 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,6 +59,7 @@ UI_FILES =                                            \
        gs-info-bar.ui                                  \
        gs-menus.ui                                     \
        gs-popular-tile.ui                              \
+       gs-removal-dialog.ui                            \
        gs-review-dialog.ui                             \
        gs-review-histogram.ui                          \
        gs-review-row.ui                                \
@@ -195,6 +196,8 @@ gnome_software_SOURCES =                            \
        gs-plugin-vfuncs.h                              \
        gs-progress-button.c                            \
        gs-progress-button.h                            \
+       gs-removal-dialog.c                             \
+       gs-removal-dialog.h                             \
        gs-review.c                                     \
        gs-review.h                                     \
        gs-review-bar.c                                 \
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index d3a9391..e6b4e79 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -14,6 +14,7 @@
   <file preprocess="xml-stripblanks">gs-history-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-info-bar.ui</file>
   <file preprocess="xml-stripblanks">gs-popular-tile.ui</file>
+  <file preprocess="xml-stripblanks">gs-removal-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-review-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-review-histogram.ui</file>
   <file preprocess="xml-stripblanks">gs-review-row.ui</file>
diff --git a/src/gs-removal-dialog.c b/src/gs-removal-dialog.c
new file mode 100644
index 0000000..8b36d03
--- /dev/null
+++ b/src/gs-removal-dialog.c
@@ -0,0 +1,185 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Kalev Lember <klember redhat com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include "gs-removal-dialog.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+struct _GsRemovalDialog
+{
+       GtkMessageDialog         parent_instance;
+       GtkWidget               *listbox;
+       GtkWidget               *scrolledwindow;
+};
+
+G_DEFINE_TYPE (GsRemovalDialog, gs_removal_dialog, GTK_TYPE_MESSAGE_DIALOG)
+
+static void
+list_header_func (GtkListBoxRow *row,
+                  GtkListBoxRow *before,
+                  gpointer user_data)
+{
+       GtkWidget *header = NULL;
+       if (before != NULL)
+               header = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+       gtk_list_box_row_set_header (row, header);
+}
+
+static gint
+list_sort_func (GtkListBoxRow *a,
+                GtkListBoxRow *b,
+                gpointer user_data)
+{
+       GObject *o1 = G_OBJECT (gtk_bin_get_child (GTK_BIN (a)));
+       GObject *o2 = G_OBJECT (gtk_bin_get_child (GTK_BIN (b)));
+       const gchar *key1 = g_object_get_data (o1, "sort");
+       const gchar *key2 = g_object_get_data (o2, "sort");
+       return g_strcmp0 (key1, key2);
+}
+
+static void
+add_app (GtkListBox *listbox, GsApp *app)
+{
+       GtkWidget *box;
+       GtkWidget *widget;
+       GtkWidget *row;
+
+       box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+       gtk_widget_set_margin_top (box, 12);
+       gtk_widget_set_margin_start (box, 12);
+       gtk_widget_set_margin_bottom (box, 12);
+       gtk_widget_set_margin_end (box, 12);
+
+       widget = gtk_label_new (gs_app_get_name (app));
+       gtk_widget_set_halign (widget, GTK_ALIGN_START);
+       gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+       gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0);
+
+       g_object_set_data_full (G_OBJECT (box),
+                               "sort",
+                               g_utf8_casefold (gs_app_get_name (app), -1),
+                               g_free);
+
+       gtk_list_box_prepend (listbox, box);
+       gtk_widget_show (widget);
+       gtk_widget_show (box);
+
+       row = gtk_widget_get_parent (box);
+       gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
+}
+
+static void
+insert_details_widget (GtkMessageDialog *dialog, GtkWidget *widget)
+{
+       GList *children, *l;
+       GtkWidget *message_area;
+
+       message_area = gtk_message_dialog_get_message_area (dialog);
+       g_assert (GTK_IS_BOX (message_area));
+
+       /* find all label children and set the width chars properties */
+       children = gtk_container_get_children (GTK_CONTAINER (message_area));
+       for (l = children; l != NULL; l = l->next) {
+               if (!GTK_IS_LABEL (l->data))
+                       continue;
+
+               gtk_label_set_width_chars (GTK_LABEL (l->data), 40);
+               gtk_label_set_max_width_chars (GTK_LABEL (l->data), 40);
+       }
+
+       gtk_container_add (GTK_CONTAINER (message_area), widget);
+}
+
+void
+gs_removal_dialog_show_system_upgrade_removals (GsRemovalDialog *self,
+                                                GsApp *system_upgrade)
+{
+       GPtrArray *removals;
+       guint i;
+       g_autofree gchar *name_version = NULL;
+
+       name_version = g_strdup_printf ("%s %s",
+                                       gs_app_get_name (system_upgrade),
+                                       gs_app_get_version (system_upgrade));
+       /* TRANSLATORS: This is a text displayed during a distro upgrade. %s
+          will be replaced by the name and version of distro, e.g. 'Fedora 23'. */
+       gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (self), _("Some of the currently 
installed software is not compatible with %s. If you continue, the following will be automatically removed 
during the upgrade:"), name_version);
+
+       removals = gs_app_get_related (system_upgrade);
+       for (i = 0; i < removals->len; i++) {
+               GsApp *app = g_ptr_array_index (removals, i);
+               g_autofree gchar *tmp = NULL;
+
+               tmp = gs_app_to_string (app);
+               g_debug ("removal %d: %s", i, tmp);
+               add_app (GTK_LIST_BOX (self->listbox), app);
+       }
+}
+
+static void
+unset_focus (GtkWidget *widget)
+{
+       gtk_window_set_focus (GTK_WINDOW (widget), NULL);
+}
+
+static void
+gs_removal_dialog_init (GsRemovalDialog *self)
+{
+       gtk_widget_init_template (GTK_WIDGET (self));
+
+       insert_details_widget (GTK_MESSAGE_DIALOG (self), self->scrolledwindow);
+
+       gtk_list_box_set_header_func (GTK_LIST_BOX (self->listbox),
+                                     list_header_func,
+                                     self,
+                                     NULL);
+       gtk_list_box_set_sort_func (GTK_LIST_BOX (self->listbox),
+                                   list_sort_func,
+                                   self, NULL);
+
+       g_signal_connect_after (self, "show", G_CALLBACK (unset_focus), NULL);
+}
+
+static void
+gs_removal_dialog_class_init (GsRemovalDialogClass *klass)
+{
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+       gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/Software/gs-removal-dialog.ui");
+
+       gtk_widget_class_bind_template_child (widget_class, GsRemovalDialog, listbox);
+       gtk_widget_class_bind_template_child (widget_class, GsRemovalDialog, scrolledwindow);
+}
+
+GtkWidget *
+gs_removal_dialog_new (void)
+{
+       GsRemovalDialog *dialog;
+
+       dialog = g_object_new (GS_TYPE_REMOVAL_DIALOG,
+                              NULL);
+       return GTK_WIDGET (dialog);
+}
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-removal-dialog.h b/src/gs-removal-dialog.h
new file mode 100644
index 0000000..0e1da3d
--- /dev/null
+++ b/src/gs-removal-dialog.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Kalev Lember <klember redhat com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef GS_REMOVAL_DIALOG_H
+#define GS_REMOVAL_DIALOG_H
+
+#include <gtk/gtk.h>
+
+#include "gs-app.h"
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_REMOVAL_DIALOG (gs_removal_dialog_get_type ())
+
+G_DECLARE_FINAL_TYPE (GsRemovalDialog, gs_removal_dialog, GS, REMOVAL_DIALOG, GtkMessageDialog)
+
+GtkWidget      *gs_removal_dialog_new                          (void);
+void            gs_removal_dialog_show_system_upgrade_removals (GsRemovalDialog         *self,
+                                                                GsApp                   *system_upgrade);
+
+G_END_DECLS
+
+#endif /* GS_REMOVAL_DIALOG_H */
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-removal-dialog.ui b/src/gs-removal-dialog.ui
new file mode 100644
index 0000000..44bfe2b
--- /dev/null
+++ b/src/gs-removal-dialog.ui
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <object class="GtkScrolledWindow" id="scrolledwindow">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="min_content_height">160</property>
+    <property name="hscrollbar_policy">never</property>
+    <property name="vscrollbar_policy">automatic</property>
+    <property name="shadow_type">none</property>
+    <child>
+      <object class="GtkFrame" id="frame">
+        <property name="visible">True</property>
+        <property name="shadow_type">in</property>
+        <property name="halign">fill</property>
+        <property name="valign">start</property>
+        <child>
+          <object class="GtkListBox" id="listbox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="selection_mode">none</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+  <template class="GsRemovalDialog" parent="GtkMessageDialog">
+    <property name="text" translatable="yes">Incompatible Software</property>
+    <property name="modal">True</property>
+    <property name="destroy_with_parent">True</property>
+    <child type="action">
+      <object class="GtkButton" id="button_cancel">
+        <property name="visible">True</property>
+        <property name="label" translatable="yes">_Cancel</property>
+        <property name="use_underline">True</property>
+      </object>
+    </child>
+    <child type="action">
+      <object class="GtkButton" id="button_continue">
+        <property name="visible">True</property>
+        <property name="label" translatable="yes">_Continue</property>
+        <property name="use_underline">True</property>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="accept">button_continue</action-widget>
+      <action-widget response="cancel">button_cancel</action-widget>
+    </action-widgets>
+  </template>
+</interface>
diff --git a/src/gs-shell-updates.c b/src/gs-shell-updates.c
index 81097cf..2421d7c 100644
--- a/src/gs-shell-updates.c
+++ b/src/gs-shell-updates.c
@@ -29,6 +29,7 @@
 #include "gs-common.h"
 #include "gs-app-private.h"
 #include "gs-app-row.h"
+#include "gs-removal-dialog.h"
 #include "gs-update-dialog.h"
 #include "gs-update-list.h"
 #include "gs-update-monitor.h"
@@ -580,6 +581,7 @@ gs_shell_updates_load (GsShellUpdates *self)
 
        /* don't refresh every each time */
        if ((self->result_flags & GS_SHELL_UPDATES_FLAG_HAS_UPGRADES) == 0) {
+               refine_flags |= GS_PLUGIN_REFINE_FLAGS_REQUIRE_UPGRADE_REMOVED;
                gs_plugin_loader_get_distro_upgrades_async (self->plugin_loader,
                                                            refine_flags,
                                                            self->cancellable,
@@ -1107,23 +1109,73 @@ upgrade_trigger_finished_cb (GObject *source,
 }
 
 static void
+trigger_upgrade (GsShellUpdates *self)
+{
+       GsApp *upgrade;
+
+       upgrade = gs_upgrade_banner_get_app (GS_UPGRADE_BANNER (self->upgrade_banner));
+       if (upgrade == NULL) {
+               g_warning ("no upgrade available to install");
+               return;
+       }
+
+       gs_plugin_loader_app_action_async (self->plugin_loader,
+                                          upgrade,
+                                          GS_PLUGIN_LOADER_ACTION_UPGRADE_TRIGGER,
+                                          self->cancellable,
+                                          upgrade_trigger_finished_cb,
+                                          self);
+}
+
+static void
+gs_shell_updates_upgrade_confirm_cb (GtkDialog *dialog,
+                                     GtkResponseType response_type,
+                                     GsShellUpdates *self)
+{
+       /* unmap the dialog */
+       gtk_widget_destroy (GTK_WIDGET (dialog));
+
+       switch (response_type) {
+       case GTK_RESPONSE_ACCEPT:
+               g_debug ("agreed to upgrade removing apps");
+               trigger_upgrade (self);
+               break;
+       case GTK_RESPONSE_CANCEL:
+               g_debug ("cancelled removal dialog");
+               break;
+       case GTK_RESPONSE_DELETE_EVENT:
+               break;
+       default:
+               g_assert_not_reached ();
+       }
+}
+
+static void
 gs_shell_updates_upgrade_install_cb (GsUpgradeBanner *upgrade_banner,
                                      GsShellUpdates *self)
 {
-       GsApp *app;
+       GsApp *upgrade;
+       GtkWidget *dialog;
 
-       app = gs_upgrade_banner_get_app (upgrade_banner);
-       if (app == NULL) {
+       upgrade = gs_upgrade_banner_get_app (GS_UPGRADE_BANNER (self->upgrade_banner));
+       if (upgrade == NULL) {
                g_warning ("no upgrade available to install");
                return;
        }
 
-       gs_plugin_loader_app_action_async (self->plugin_loader,
-                                          app,
-                                          GS_PLUGIN_LOADER_ACTION_UPGRADE_TRIGGER,
-                                          self->cancellable,
-                                          upgrade_trigger_finished_cb,
-                                          self);
+       if (gs_app_get_related (upgrade) == NULL) {
+               /* no need for a removal confirmation dialog */
+               trigger_upgrade (self);
+               return;
+       }
+
+       dialog = gs_removal_dialog_new ();
+       g_signal_connect (dialog, "response",
+                         G_CALLBACK (gs_shell_updates_upgrade_confirm_cb),
+                         self);
+       gs_removal_dialog_show_system_upgrade_removals (GS_REMOVAL_DIALOG (dialog),
+                                                       upgrade);
+       gs_shell_modal_dialog_present (self->shell, GTK_DIALOG (dialog));
 }
 
 static void


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