Resolves: #2012863 (gs-installed-page: Change section on application state change)

This commit is contained in:
Milan Crha 2021-10-19 07:57:57 +02:00
parent 5b411a73e7
commit 77240ed208
2 changed files with 269 additions and 1 deletions

View File

@ -0,0 +1,264 @@
From 65551cf41c8d6b3dcf0cf9b2ee2d46201b4e0ea4 Mon Sep 17 00:00:00 2001
From: Milan Crha <mcrha@redhat.com>
Date: Thu, 14 Oct 2021 15:17:52 +0200
Subject: [PATCH] gs-installed-page: Change section on application state change
When an application is being installed, it's shown in the "In Progress"
section, but when the installation is finished it had been left in
that section, even it belongs to a different section.
Similarly with the uninstall, the application was sorted to the top
of the section, but it might be better to be added to the "In Progress"
section.
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1492
---
src/gs-installed-page.c | 168 +++++++++++++++++++++++++++++++++-------
1 file changed, 141 insertions(+), 27 deletions(-)
diff --git a/src/gs-installed-page.c b/src/gs-installed-page.c
index 67a4b7a51..56bf19df7 100644
--- a/src/gs-installed-page.c
+++ b/src/gs-installed-page.c
@@ -59,6 +59,9 @@ static GParamSpec *obj_props[PROP_IS_NARROW + 1] = { NULL, };
static void gs_installed_page_pending_apps_changed_cb (GsPluginLoader *plugin_loader,
GsInstalledPage *self);
+static void gs_installed_page_notify_state_changed_cb (GsApp *app,
+ GParamSpec *pspec,
+ GsInstalledPage *self);
typedef enum {
GS_UPDATE_LIST_SECTION_INSTALLING_AND_REMOVING,
@@ -91,6 +94,30 @@ gs_installed_page_get_app_section (GsApp *app)
return GS_UPDATE_LIST_SECTION_ADDONS;
}
+static GsInstalledPageSection
+gs_installed_page_get_row_section (GsInstalledPage *self,
+ GsAppRow *app_row)
+{
+ GtkWidget *parent;
+
+ g_return_val_if_fail (GS_IS_INSTALLED_PAGE (self), GS_UPDATE_LIST_SECTION_LAST);
+ g_return_val_if_fail (GS_IS_APP_ROW (app_row), GS_UPDATE_LIST_SECTION_LAST);
+
+ parent = gtk_widget_get_parent (GTK_WIDGET (app_row));
+ if (parent == self->list_box_install_in_progress)
+ return GS_UPDATE_LIST_SECTION_INSTALLING_AND_REMOVING;
+ if (parent == self->list_box_install_apps)
+ return GS_UPDATE_LIST_SECTION_REMOVABLE_APPS;
+ if (parent == self->list_box_install_system_apps)
+ return GS_UPDATE_LIST_SECTION_SYSTEM_APPS;
+ if (parent == self->list_box_install_addons)
+ return GS_UPDATE_LIST_SECTION_ADDONS;
+
+ g_warn_if_reached ();
+
+ return GS_UPDATE_LIST_SECTION_LAST;
+}
+
static void
gs_installed_page_invalidate (GsInstalledPage *self)
{
@@ -121,15 +148,29 @@ row_unrevealed (GObject *row, GParamSpec *pspec, gpointer data)
static void
gs_installed_page_unreveal_row (GsAppRow *app_row)
{
- g_signal_connect (app_row, "unrevealed",
- G_CALLBACK (row_unrevealed), NULL);
- gs_app_row_unreveal (app_row);
+ GsApp *app = gs_app_row_get_app (app_row);
+ if (app != NULL) {
+ g_signal_handlers_disconnect_matched (app, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
+ G_CALLBACK (gs_installed_page_notify_state_changed_cb), NULL);
+ }
+
+ /* This check is required, because GsAppRow does not emit
+ * the signal when the row is not realized. This can happen
+ * when installing/uninstalling an app without visiting
+ * the Installed page. */
+ if (!gtk_widget_get_mapped (GTK_WIDGET (app_row))) {
+ row_unrevealed (G_OBJECT (app_row), NULL, NULL);
+ } else {
+ g_signal_connect (app_row, "unrevealed",
+ G_CALLBACK (row_unrevealed), NULL);
+ gs_app_row_unreveal (app_row);
+ }
}
-static void
-gs_installed_page_app_removed (GsPage *page, GsApp *app)
+static GsAppRow * /* (transfer none) */
+gs_installed_page_find_app_row (GsInstalledPage *self,
+ GsApp *app)
{
- GsInstalledPage *self = GS_INSTALLED_PAGE (page);
GtkWidget *lists[] = {
self->list_box_install_in_progress,
self->list_box_install_apps,
@@ -145,10 +186,22 @@ gs_installed_page_app_removed (GsPage *page, GsApp *app)
for (GList *l = children; l; l = l->next) {
GsAppRow *app_row = GS_APP_ROW (l->data);
if (gs_app_row_get_app (app_row) == app) {
- gs_installed_page_unreveal_row (app_row);
+ return app_row;
}
}
}
+
+ return NULL;
+}
+
+
+static void
+gs_installed_page_app_removed (GsPage *page, GsApp *app)
+{
+ GsInstalledPage *self = GS_INSTALLED_PAGE (page);
+ GsAppRow *app_row = gs_installed_page_find_app_row (self, app);
+ if (app_row != NULL)
+ gs_installed_page_unreveal_row (app_row);
}
static void
@@ -161,12 +214,56 @@ gs_installed_page_app_remove_cb (GsAppRow *app_row,
gs_page_remove_app (GS_PAGE (self), app, self->cancellable);
}
-static gboolean
-gs_installed_page_invalidate_sort_idle (gpointer user_data)
+static void
+gs_installed_page_maybe_move_app_row (GsInstalledPage *self,
+ GsAppRow *app_row)
+{
+ GsInstalledPageSection current_section, expected_section;
+
+ current_section = gs_installed_page_get_row_section (self, app_row);
+ g_return_if_fail (current_section != GS_UPDATE_LIST_SECTION_LAST);
+
+ expected_section = gs_installed_page_get_app_section (gs_app_row_get_app (app_row));
+ if (expected_section != current_section) {
+ GtkWidget *widget = GTK_WIDGET (app_row);
+
+ g_object_ref (app_row);
+ gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (widget)), widget);
+ switch (expected_section) {
+ case GS_UPDATE_LIST_SECTION_INSTALLING_AND_REMOVING:
+ widget = self->list_box_install_in_progress;
+ break;
+ case GS_UPDATE_LIST_SECTION_REMOVABLE_APPS:
+ widget = self->list_box_install_apps;
+ break;
+ case GS_UPDATE_LIST_SECTION_SYSTEM_APPS:
+ widget = self->list_box_install_system_apps;
+ break;
+ case GS_UPDATE_LIST_SECTION_ADDONS:
+ widget = self->list_box_install_addons;
+ break;
+ default:
+ g_warn_if_reached ();
+ widget = NULL;
+ break;
+ }
+
+ if (widget != NULL)
+ gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (app_row));
+
+ g_object_unref (app_row);
+ }
+}
+
+static void
+gs_installed_page_notify_state_changed_cb (GsApp *app,
+ GParamSpec *pspec,
+ GsInstalledPage *self)
{
- GsAppRow *app_row = user_data;
- GsApp *app = gs_app_row_get_app (app_row);
GsAppState state = gs_app_get_state (app);
+ GsAppRow *app_row = gs_installed_page_find_app_row (self, app);
+
+ g_assert (app_row != NULL);
gtk_list_box_row_changed (GTK_LIST_BOX_ROW (app_row));
@@ -177,17 +274,8 @@ gs_installed_page_invalidate_sort_idle (gpointer user_data)
state != GS_APP_STATE_UPDATABLE &&
state != GS_APP_STATE_UPDATABLE_LIVE)
gs_installed_page_unreveal_row (app_row);
-
- g_object_unref (app_row);
- return G_SOURCE_REMOVE;
-}
-
-static void
-gs_installed_page_notify_state_changed_cb (GsApp *app,
- GParamSpec *pspec,
- GsAppRow *app_row)
-{
- g_idle_add (gs_installed_page_invalidate_sort_idle, g_object_ref (app_row));
+ else
+ gs_installed_page_maybe_move_app_row (self, app_row);
}
static gboolean
@@ -229,7 +317,7 @@ gs_installed_page_add_app (GsInstalledPage *self, GsAppList *list, GsApp *app)
G_CALLBACK (gs_installed_page_app_remove_cb), self);
g_signal_connect_object (app, "notify::state",
G_CALLBACK (gs_installed_page_notify_state_changed_cb),
- app_row, 0);
+ self, 0);
switch (gs_installed_page_get_app_section (app)) {
case GS_UPDATE_LIST_SECTION_INSTALLING_AND_REMOVING:
@@ -294,6 +382,32 @@ out:
gs_installed_page_pending_apps_changed_cb (plugin_loader, self);
}
+static void
+gs_installed_page_remove_all_cb (GtkWidget *child,
+ gpointer user_data)
+{
+ GtkContainer *container = user_data;
+
+ if (GS_IS_APP_ROW (child)) {
+ GsApp *app = gs_app_row_get_app (GS_APP_ROW (child));
+ if (app != NULL) {
+ g_signal_handlers_disconnect_matched (app, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
+ G_CALLBACK (gs_installed_page_notify_state_changed_cb), NULL);
+ }
+ } else {
+ g_warn_if_reached ();
+ }
+
+ gtk_container_remove (container, child);
+}
+
+static void
+gs_container_remove_all_with_cb (GtkContainer *container,
+ GtkCallback callback)
+{
+ gtk_container_foreach (container, callback, container);
+}
+
static void
gs_installed_page_load (GsInstalledPage *self)
{
@@ -305,10 +419,10 @@ gs_installed_page_load (GsInstalledPage *self)
self->waiting = TRUE;
/* remove old entries */
- gs_container_remove_all (GTK_CONTAINER (self->list_box_install_in_progress));
- gs_container_remove_all (GTK_CONTAINER (self->list_box_install_apps));
- gs_container_remove_all (GTK_CONTAINER (self->list_box_install_system_apps));
- gs_container_remove_all (GTK_CONTAINER (self->list_box_install_addons));
+ gs_container_remove_all_with_cb (GTK_CONTAINER (self->list_box_install_in_progress), gs_installed_page_remove_all_cb);
+ gs_container_remove_all_with_cb (GTK_CONTAINER (self->list_box_install_apps), gs_installed_page_remove_all_cb);
+ gs_container_remove_all_with_cb (GTK_CONTAINER (self->list_box_install_system_apps), gs_installed_page_remove_all_cb);
+ gs_container_remove_all_with_cb (GTK_CONTAINER (self->list_box_install_addons), gs_installed_page_remove_all_cb);
flags = GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_HISTORY |
--
GitLab

View File

@ -12,7 +12,7 @@
Name: gnome-software
Version: 41.0
Release: 5%{?dist}
Release: 6%{?dist}
Summary: A software center for GNOME
License: GPLv2+
@ -26,6 +26,7 @@ Patch04: 0004-filtered-system-flathub.patch
Patch05: 0005-repos-dialog-can-show-apps.patch
Patch06: 0006-optional-repos-cannot-be-disabled.patch
Patch07: 0007-compulsory-only-for-repos.patch
Patch08: 0008-installed-page-section-change.patch
BuildRequires: appstream-devel >= %{appstream_version}
BuildRequires: gcc
@ -209,6 +210,9 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop
%{_datadir}/gtk-doc/html/gnome-software
%changelog
* Tue Oct 19 2021 Milan Crha <mcrha@redhat.com> - 41.0-6
- Resolves: #2012863 (gs-installed-page: Change section on application state change)
* Mon Oct 11 2021 Milan Crha <mcrha@redhat.com> - 41.0-5
- Add patch to mark compulsory only repos, not apps from it