[gnome-software] Add a cancel button to the details page



commit 2577941028c09c8dc58a674ec3a4d2385f9ca248
Author: Richard Hughes <richard hughsie com>
Date:   Fri Jul 8 17:50:23 2016 +0100

    Add a cancel button to the details page
    
    This means creating a new cancellable for each action, but this is what we
    should be doing anyway...

 src/gs-page.c            |   43 ++++++++++++++++++++++-------------------
 src/gs-page.h            |   18 +++++++++++-----
 src/gs-shell-details.c   |   48 +++++++++++++++++++++++++++++++++++++++------
 src/gs-shell-details.ui  |   26 +++++++++++++++++++++---
 src/gs-shell-extras.c    |    4 +-
 src/gs-shell-installed.c |    2 +-
 src/gs-shell-search.c    |    6 ++--
 src/gs-shell-updates.c   |    9 ++++++-
 8 files changed, 111 insertions(+), 45 deletions(-)
---
diff --git a/src/gs-page.c b/src/gs-page.c
index 798c844..3e6cb08 100644
--- a/src/gs-page.c
+++ b/src/gs-page.c
@@ -33,7 +33,6 @@
 typedef struct
 {
        GsPluginLoader          *plugin_loader;
-       GCancellable            *cancellable;
        GsShell                 *shell;
        GtkWidget               *header_start_widget;
        GtkWidget               *header_end_widget;
@@ -44,6 +43,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GsPage, gs_page, GTK_TYPE_BIN)
 typedef struct {
        GsApp           *app;
        GsPage          *page;
+       GCancellable    *cancellable;
 } GsPageHelper;
 
 static void
@@ -53,6 +53,8 @@ gs_page_helper_free (GsPageHelper *helper)
                g_object_unref (helper->app);
        if (helper->page != NULL)
                g_object_unref (helper->page);
+       if (helper->cancellable != NULL)
+               g_object_unref (helper->cancellable);
        g_slice_free (GsPageHelper, helper);
 }
 
@@ -80,7 +82,7 @@ gs_page_install_authenticate_cb (GtkDialog *dialog,
        gs_plugin_loader_app_action_async (priv->plugin_loader,
                                           helper->app,
                                           GS_PLUGIN_LOADER_ACTION_INSTALL,
-                                          priv->cancellable,
+                                          helper->cancellable,
                                           gs_page_app_installed_cb,
                                           helper);
 }
@@ -107,7 +109,7 @@ gs_page_remove_authenticate_cb (GtkDialog *dialog,
        gs_plugin_loader_app_action_async (priv->plugin_loader,
                                           helper->app,
                                           GS_PLUGIN_LOADER_ACTION_REMOVE,
-                                          priv->cancellable,
+                                          helper->cancellable,
                                           gs_page_app_removed_cb,
                                           helper);
 }
@@ -290,7 +292,7 @@ gs_page_set_header_end_widget (GsPage *page, GtkWidget *widget)
 }
 
 void
-gs_page_install_app (GsPage *page, GsApp *app)
+gs_page_install_app (GsPage *page, GsApp *app, GCancellable *cancellable)
 {
        GsPagePrivate *priv = gs_page_get_instance_private (page);
        GsPageHelper *helper;
@@ -306,10 +308,11 @@ gs_page_install_app (GsPage *page, GsApp *app)
        helper = g_slice_new0 (GsPageHelper);
        helper->app = g_object_ref (app);
        helper->page = g_object_ref (page);
+       helper->cancellable = g_object_ref (cancellable);
        gs_plugin_loader_app_action_async (priv->plugin_loader,
                                           app,
                                           GS_PLUGIN_LOADER_ACTION_INSTALL,
-                                          priv->cancellable,
+                                          helper->cancellable,
                                           gs_page_app_installed_cb,
                                           helper);
 }
@@ -333,13 +336,13 @@ gs_page_update_app_response_cb (GtkDialog *dialog,
        gs_plugin_loader_app_action_async (priv->plugin_loader,
                                           helper->app,
                                           GS_PLUGIN_LOADER_ACTION_UPDATE,
-                                          priv->cancellable,
+                                          helper->cancellable,
                                           gs_page_app_installed_cb,
                                           helper);
 }
 
 void
-gs_page_update_app (GsPage *page, GsApp *app)
+gs_page_update_app (GsPage *page, GsApp *app, GCancellable *cancellable)
 {
        GsPagePrivate *priv = gs_page_get_instance_private (page);
        GsPageHelper *helper;
@@ -351,12 +354,13 @@ gs_page_update_app (GsPage *page, GsApp *app)
        helper = g_slice_new0 (GsPageHelper);
        helper->app = g_object_ref (app);
        helper->page = g_object_ref (page);
+       helper->cancellable = g_object_ref (cancellable);
        if (gs_app_get_kind (app) != AS_APP_KIND_FIRMWARE ||
            gs_app_get_screenshots (app)->len == 0) {
                gs_plugin_loader_app_action_async (priv->plugin_loader,
                                                   helper->app,
                                                   GS_PLUGIN_LOADER_ACTION_UPDATE,
-                                                  priv->cancellable,
+                                                  helper->cancellable,
                                                   gs_page_app_installed_cb,
                                                   helper);
                return;
@@ -368,7 +372,7 @@ gs_page_update_app (GsPage *page, GsApp *app)
                gs_plugin_loader_app_action_async (priv->plugin_loader,
                                                   helper->app,
                                                   GS_PLUGIN_LOADER_ACTION_UPDATE,
-                                                  priv->cancellable,
+                                                  helper->cancellable,
                                                   gs_page_app_installed_cb,
                                                   helper);
                return;
@@ -414,13 +418,13 @@ gs_page_remove_app_response_cb (GtkDialog *dialog,
        gs_plugin_loader_app_action_async (priv->plugin_loader,
                                           helper->app,
                                           GS_PLUGIN_LOADER_ACTION_REMOVE,
-                                          priv->cancellable,
+                                          helper->cancellable,
                                           gs_page_app_removed_cb,
                                           helper);
 }
 
 void
-gs_page_remove_app (GsPage *page, GsApp *app)
+gs_page_remove_app (GsPage *page, GsApp *app, GCancellable *cancellable)
 {
        GsPagePrivate *priv = gs_page_get_instance_private (page);
        GsPageHelper *helper;
@@ -431,12 +435,13 @@ gs_page_remove_app (GsPage *page, GsApp *app)
        helper = g_slice_new0 (GsPageHelper);
        helper->app = g_object_ref (app);
        helper->page = g_object_ref (page);
+       helper->cancellable = g_object_ref (cancellable);
        if (gs_app_get_state (app) == AS_APP_STATE_QUEUED_FOR_INSTALL) {
                g_debug ("remove %s", gs_app_get_id (app));
                gs_plugin_loader_app_action_async (priv->plugin_loader,
                                                   app,
                                                   GS_PLUGIN_LOADER_ACTION_REMOVE,
-                                                  priv->cancellable,
+                                                  helper->cancellable,
                                                   gs_page_app_removed_cb,
                                                   helper);
                return;
@@ -480,13 +485,13 @@ gs_page_app_launched_cb (GObject *source,
 }
 
 void
-gs_page_launch_app (GsPage *page, GsApp *app)
+gs_page_launch_app (GsPage *page, GsApp *app, GCancellable *cancellable)
 {
        GsPagePrivate *priv = gs_page_get_instance_private (page);
        gs_plugin_loader_app_action_async (priv->plugin_loader,
                                           app,
                                           GS_PLUGIN_LOADER_ACTION_LAUNCH,
-                                          priv->cancellable,
+                                          cancellable,
                                           gs_page_app_launched_cb,
                                           NULL);
 }
@@ -505,13 +510,13 @@ gs_page_app_shortcut_added_cb (GObject *source,
 }
 
 void
-gs_page_shortcut_add (GsPage *page, GsApp *app)
+gs_page_shortcut_add (GsPage *page, GsApp *app, GCancellable *cancellable)
 {
        GsPagePrivate *priv = gs_page_get_instance_private (page);
        gs_plugin_loader_app_action_async (priv->plugin_loader,
                                           app,
                                           GS_PLUGIN_LOADER_ACTION_ADD_SHORTCUT,
-                                          priv->cancellable,
+                                          cancellable,
                                           gs_page_app_shortcut_added_cb,
                                           NULL);
 }
@@ -530,13 +535,13 @@ gs_page_app_shortcut_removed_cb (GObject *source,
 }
 
 void
-gs_page_shortcut_remove (GsPage *page, GsApp *app)
+gs_page_shortcut_remove (GsPage *page, GsApp *app, GCancellable *cancellable)
 {
        GsPagePrivate *priv = gs_page_get_instance_private (page);
        gs_plugin_loader_app_action_async (priv->plugin_loader,
                                           app,
                                           GS_PLUGIN_LOADER_ACTION_REMOVE_SHORTCUT,
-                                          priv->cancellable,
+                                          cancellable,
                                           gs_page_app_shortcut_removed_cb,
                                           NULL);
 }
@@ -582,7 +587,6 @@ gs_page_setup (GsPage *page,
        g_return_if_fail (GS_IS_PAGE (page));
 
        priv->plugin_loader = g_object_ref (plugin_loader);
-       priv->cancellable = g_object_ref (cancellable);
        priv->shell = shell;
 }
 
@@ -593,7 +597,6 @@ gs_page_dispose (GObject *object)
        GsPagePrivate *priv = gs_page_get_instance_private (page);
 
        g_clear_object (&priv->plugin_loader);
-       g_clear_object (&priv->cancellable);
        g_clear_object (&priv->header_start_widget);
        g_clear_object (&priv->header_end_widget);
 
diff --git a/src/gs-page.h b/src/gs-page.h
index 426e3b4..1f6b59c 100644
--- a/src/gs-page.h
+++ b/src/gs-page.h
@@ -55,17 +55,23 @@ GtkWidget   *gs_page_get_header_end_widget          (GsPage         *page);
 void            gs_page_set_header_end_widget          (GsPage         *page,
                                                         GtkWidget      *widget);
 void            gs_page_install_app                    (GsPage         *page,
-                                                        GsApp          *app);
+                                                        GsApp          *app,
+                                                        GCancellable   *cancellable);
 void            gs_page_remove_app                     (GsPage         *page,
-                                                        GsApp          *app);
+                                                        GsApp          *app,
+                                                        GCancellable   *cancellable);
 void            gs_page_update_app                     (GsPage         *page,
-                                                        GsApp          *app);
+                                                        GsApp          *app,
+                                                        GCancellable   *cancellable);
 void            gs_page_launch_app                     (GsPage         *page,
-                                                        GsApp          *app);
+                                                        GsApp          *app,
+                                                        GCancellable   *cancellable);
 void            gs_page_shortcut_add                   (GsPage         *page,
-                                                        GsApp          *app);
+                                                        GsApp          *app,
+                                                        GCancellable   *cancellable);
 void            gs_page_shortcut_remove                (GsPage         *page,
-                                                        GsApp          *app);
+                                                        GsApp          *app,
+                                                        GCancellable   *cancellable);
 void            gs_page_switch_to                      (GsPage         *page,
                                                         gboolean        scroll_up);
 void            gs_page_reload                         (GsPage         *page);
diff --git a/src/gs-shell-details.c b/src/gs-shell-details.c
index 379c8fd..48fd972 100644
--- a/src/gs-shell-details.c
+++ b/src/gs-shell-details.c
@@ -80,6 +80,7 @@ struct _GsShellDetails
        GtkWidget               *button_details_website;
        GtkWidget               *button_install;
        GtkWidget               *button_remove;
+       GtkWidget               *button_cancel;
        GtkWidget               *button_more_reviews;
        GtkWidget               *infobar_details_app_norepo;
        GtkWidget               *infobar_details_app_repo;
@@ -377,6 +378,18 @@ gs_shell_details_switch_to (GsPage *page, gboolean scroll_up)
                }
        }
 
+       /* cancel button */
+       switch (state) {
+       case AS_APP_STATE_REMOVING:
+       case AS_APP_STATE_INSTALLING:
+               gtk_widget_set_visible (self->button_cancel, TRUE);
+               gtk_widget_set_sensitive (self->button_cancel, TRUE);
+               break;
+       default:
+               gtk_widget_set_visible (self->button_cancel, FALSE);
+               break;
+       }
+
        /* do a fill bar for the current progress */
        switch (gs_app_get_state (self->app)) {
        case AS_APP_STATE_INSTALLING:
@@ -1606,7 +1619,16 @@ gs_shell_details_get_app (GsShellDetails *self)
 static void
 gs_shell_details_app_remove_button_cb (GtkWidget *widget, GsShellDetails *self)
 {
-       gs_page_remove_app (GS_PAGE (self), self->app);
+       g_autoptr(GCancellable) cancellable = g_cancellable_new ();
+       g_set_object (&self->cancellable, cancellable);
+       gs_page_remove_app (GS_PAGE (self), self->app, self->cancellable);
+}
+
+static void
+gs_shell_details_app_cancel_button_cb (GtkWidget *widget, GsShellDetails *self)
+{
+       g_cancellable_cancel (self->cancellable);
+       gtk_widget_set_sensitive (widget, FALSE);
 }
 
 static void
@@ -1614,6 +1636,7 @@ gs_shell_details_app_install_button_cb (GtkWidget *widget, GsShellDetails *self)
 {
        GList *l;
        g_autoptr(GList) addons = NULL;
+       g_autoptr(GCancellable) cancellable = g_cancellable_new ();
 
        /* Mark ticked addons to be installed together with the app */
        addons = gtk_container_get_children (GTK_CONTAINER (self->list_box_addons));
@@ -1626,7 +1649,8 @@ gs_shell_details_app_install_button_cb (GtkWidget *widget, GsShellDetails *self)
                }
        }
 
-       gs_page_install_app (GS_PAGE (self), self->app);
+       g_set_object (&self->cancellable, cancellable);
+       gs_page_install_app (GS_PAGE (self), self->app, self->cancellable);
 }
 
 static void
@@ -1646,9 +1670,9 @@ gs_shell_details_addon_selected_cb (GsAppAddonRow *row,
        case AS_APP_STATE_UPDATABLE:
        case AS_APP_STATE_UPDATABLE_LIVE:
                if (gs_app_addon_row_get_selected (row)) {
-                       gs_page_install_app (GS_PAGE (self), addon);
+                       gs_page_install_app (GS_PAGE (self), addon, self->cancellable);
                } else {
-                       gs_page_remove_app (GS_PAGE (self), addon);
+                       gs_page_remove_app (GS_PAGE (self), addon, self->cancellable);
                        /* make sure the addon checkboxes are synced if the
                         * user clicks cancel in the remove confirmation dialog */
                        gs_shell_details_refresh_addons (self);
@@ -1663,21 +1687,27 @@ gs_shell_details_addon_selected_cb (GsAppAddonRow *row,
 static void
 gs_shell_details_app_launch_button_cb (GtkWidget *widget, GsShellDetails *self)
 {
-       gs_page_launch_app (GS_PAGE (self), self->app);
+       g_autoptr(GCancellable) cancellable = g_cancellable_new ();
+       g_set_object (&self->cancellable, cancellable);
+       gs_page_launch_app (GS_PAGE (self), self->app, self->cancellable);
 }
 
 static void
 gs_shell_details_app_add_shortcut_button_cb (GtkWidget *widget,
                                             GsShellDetails *self)
 {
-       gs_page_shortcut_add (GS_PAGE (self), self->app);
+       g_autoptr(GCancellable) cancellable = g_cancellable_new ();
+       g_set_object (&self->cancellable, cancellable);
+       gs_page_shortcut_add (GS_PAGE (self), self->app, self->cancellable);
 }
 
 static void
 gs_shell_details_app_remove_shortcut_button_cb (GtkWidget *widget,
                                                GsShellDetails *self)
 {
-       gs_page_shortcut_remove (GS_PAGE (self), self->app);
+       g_autoptr(GCancellable) cancellable = g_cancellable_new ();
+       g_set_object (&self->cancellable, cancellable);
+       gs_page_shortcut_remove (GS_PAGE (self), self->app, self->cancellable);
 }
 
 static void
@@ -1787,6 +1817,9 @@ gs_shell_details_setup (GsShellDetails *self,
        g_signal_connect (self->button_remove, "clicked",
                          G_CALLBACK (gs_shell_details_app_remove_button_cb),
                          self);
+       g_signal_connect (self->button_cancel, "clicked",
+                         G_CALLBACK (gs_shell_details_app_cancel_button_cb),
+                         self);
        g_signal_connect (self->button_more_reviews, "clicked",
                          G_CALLBACK (gs_shell_details_more_reviews_button_cb),
                          self);
@@ -1866,6 +1899,7 @@ gs_shell_details_class_init (GsShellDetailsClass *klass)
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, button_details_website);
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, button_install);
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, button_remove);
+       gtk_widget_class_bind_template_child (widget_class, GsShellDetails, button_cancel);
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, button_more_reviews);
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, infobar_details_app_norepo);
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, infobar_details_app_repo);
diff --git a/src/gs-shell-details.ui b/src/gs-shell-details.ui
index 813b796..3218be7 100644
--- a/src/gs-shell-details.ui
+++ b/src/gs-shell-details.ui
@@ -189,6 +189,24 @@
                                         <property name="position">2</property>
                                       </packing>
                                     </child>
+
+                                    <child>
+                                      <object class="GtkButton" id="button_cancel">
+                                        <property name="use_underline">True</property>
+                                        <property name="label" translatable="yes">_Cancel</property>
+                                        <property name="width_request">105</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">True</property>
+                                        <property name="halign">start</property>
+                                        <property name="valign">start</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">False</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+
                                     <child>
                                       <object class="GtkLabel" id="label_pending">
                                         <property name="can_focus">False</property>
@@ -197,7 +215,7 @@
                                       <packing>
                                         <property name="expand">False</property>
                                         <property name="fill">False</property>
-                                        <property name="position">3</property>
+                                        <property name="position">4</property>
                                       </packing>
                                     </child>
                                     <child>
@@ -214,7 +232,7 @@
                                       <packing>
                                         <property name="expand">False</property>
                                         <property name="fill">False</property>
-                                        <property name="position">4</property>
+                                        <property name="position">5</property>
                                       </packing>
                                     </child>
                                     <child>
@@ -228,7 +246,7 @@
                                       <packing>
                                         <property name="expand">False</property>
                                         <property name="fill">False</property>
-                                        <property name="position">5</property>
+                                        <property name="position">6</property>
                                         <property name="pack-type">end</property>
                                       </packing>
                                     </child>
@@ -243,7 +261,7 @@
                                       <packing>
                                         <property name="expand">False</property>
                                         <property name="fill">False</property>
-                                        <property name="position">6</property>
+                                        <property name="position">7</property>
                                         <property name="pack-type">end</property>
                                       </packing>
                                     </child>
diff --git a/src/gs-shell-extras.c b/src/gs-shell-extras.c
index 156c8a5..8be12b5 100644
--- a/src/gs-shell-extras.c
+++ b/src/gs-shell-extras.c
@@ -264,9 +264,9 @@ app_row_button_clicked_cb (GsAppRow *app_row,
        app = gs_app_row_get_app (app_row);
        if (gs_app_get_state (app) == AS_APP_STATE_AVAILABLE ||
            gs_app_get_state (app) == AS_APP_STATE_AVAILABLE_LOCAL)
-               gs_page_install_app (GS_PAGE (self), app);
+               gs_page_install_app (GS_PAGE (self), app, self->search_cancellable);
        else if (gs_app_get_state (app) == AS_APP_STATE_INSTALLED)
-               gs_page_remove_app (GS_PAGE (self), app);
+               gs_page_remove_app (GS_PAGE (self), app, self->search_cancellable);
        else
                g_critical ("extras: app in unexpected state %d", gs_app_get_state (app));
 }
diff --git a/src/gs-shell-installed.c b/src/gs-shell-installed.c
index 5a2543a..c611fab 100644
--- a/src/gs-shell-installed.c
+++ b/src/gs-shell-installed.c
@@ -122,7 +122,7 @@ gs_shell_installed_app_remove_cb (GsAppRow *app_row,
        GsApp *app;
 
        app = gs_app_row_get_app (app_row);
-       gs_page_remove_app (GS_PAGE (self), app);
+       gs_page_remove_app (GS_PAGE (self), app, self->cancellable);
 }
 
 static gboolean
diff --git a/src/gs-shell-search.c b/src/gs-shell-search.c
index bf45bc7..ecc2130 100644
--- a/src/gs-shell-search.c
+++ b/src/gs-shell-search.c
@@ -71,12 +71,12 @@ gs_shell_search_app_row_clicked_cb (GsAppRow *app_row,
        GsApp *app;
        app = gs_app_row_get_app (app_row);
        if (gs_app_get_state (app) == AS_APP_STATE_AVAILABLE)
-               gs_page_install_app (GS_PAGE (self), app);
+               gs_page_install_app (GS_PAGE (self), app, self->cancellable);
        else if (gs_app_get_state (app) == AS_APP_STATE_INSTALLED)
-               gs_page_remove_app (GS_PAGE (self), app);
+               gs_page_remove_app (GS_PAGE (self), app, self->cancellable);
        else if (gs_app_get_state (app) == AS_APP_STATE_UNAVAILABLE) {
                if (gs_app_get_url (app, AS_URL_KIND_MISSING) == NULL) {
-                       gs_page_install_app (GS_PAGE (self), app);
+                       gs_page_install_app (GS_PAGE (self), app, self->cancellable);
                        return;
                }
                gs_app_show_url (app, AS_URL_KIND_MISSING);
diff --git a/src/gs-shell-updates.c b/src/gs-shell-updates.c
index c8a1b7a..6e0279e 100644
--- a/src/gs-shell-updates.c
+++ b/src/gs-shell-updates.c
@@ -665,8 +665,11 @@ gs_shell_updates_button_clicked_cb (GsUpdateList *update_list,
                                    GsApp *app,
                                    GsShellUpdates *self)
 {
-       if (gs_app_get_state (app) == AS_APP_STATE_UPDATABLE_LIVE)
-               gs_page_update_app (GS_PAGE (self), app);
+       g_autoptr(GCancellable) cancellable = g_cancellable_new ();
+       if (gs_app_get_state (app) != AS_APP_STATE_UPDATABLE_LIVE)
+               return;
+       g_set_object (&self->cancellable, cancellable);
+       gs_page_update_app (GS_PAGE (self), app, self->cancellable);
 }
 
 static void
@@ -954,8 +957,10 @@ gs_shell_updates_button_update_all_cb (GtkButton      *button,
 {
        g_autoptr(GError) error = NULL;
        g_autoptr(GsAppList) apps = NULL;
+       g_autoptr(GCancellable) cancellable = g_cancellable_new ();
 
        /* do the offline update */
+       g_set_object (&self->cancellable, cancellable);
        apps = gs_update_list_get_apps (GS_UPDATE_LIST (self->list_box_updates));
        gs_plugin_loader_update_async (self->plugin_loader,
                                       apps,


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