Skip to content

Commit

Permalink
install-button: Disable during installation
Browse files Browse the repository at this point in the history
Introduces a new installing state that is set before activating
`ext.install` action. To deal with cancellations, a new `install-status`
signal is added to ExmManager which is emitted whenever it happens
andreverts the button state to the last one it had, either default or
unsupported.

ExmSearchRow drops `is-installed` and `is-supported` properties in favor
of a new `manager` property to connect to ExmManager's `install-status
signal.
  • Loading branch information
oscfdezdz committed Feb 12, 2025
1 parent 49439a8 commit 0e14966
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 84 deletions.
12 changes: 1 addition & 11 deletions src/exm-browse-page.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ struct _ExmBrowsePage

GtkStringList *suggestions;
GListModel *search_results_model;
gchar *shell_version;

int current_page;
int max_pages;
Expand Down Expand Up @@ -135,17 +134,9 @@ search_widget_factory (ExmSearchResult *result,
ExmBrowsePage *self)
{
ExmSearchRow *row;
gchar *uuid;
gboolean is_installed;
gboolean is_supported;
GValue value = G_VALUE_INIT;

g_object_get (result, "uuid", &uuid, NULL);

is_installed = exm_manager_is_installed_uuid (self->manager, uuid);
is_supported = exm_search_result_supports_shell_version (result, self->shell_version);

row = exm_search_row_new (result, is_installed, is_supported);
row = exm_search_row_new (self->manager, result);

g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, TRUE);
Expand Down Expand Up @@ -355,7 +346,6 @@ on_bind_manager (ExmBrowsePage *self)
&shell_version,
NULL);

self->shell_version = shell_version;
g_object_set (self->search, "shell-version", shell_version, NULL);

refresh_search (self);
Expand Down
43 changes: 36 additions & 7 deletions src/exm-detail-view.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ struct _ExmDetailView
AdwActionRow *link_extensions;
gchar *uri_extensions;
int pk;
guint signal_id;
guint comments_signal_id;
guint install_signal_id;
};

G_DEFINE_FINAL_TYPE (ExmDetailView, exm_detail_view, ADW_TYPE_NAVIGATION_PAGE)
Expand Down Expand Up @@ -281,6 +282,14 @@ show_more_comments (GtkButton *button G_GNUC_UNUSED,
adw_dialog_present (ADW_DIALOG (dlg), GTK_WIDGET (toplevel));
}

static void
on_install_status (ExmManager *manager G_GNUC_UNUSED,
ExmInstallButtonState state,
ExmDetailView *self)
{
g_object_set (self->ext_install, "state", state, NULL);
}

static void
install_remote (GtkButton *button,
ExmDetailView *self)
Expand All @@ -291,6 +300,12 @@ install_remote (GtkButton *button,
g_object_get (self->ext_install, "state", &state, NULL);

warn = (state == EXM_INSTALL_BUTTON_STATE_UNSUPPORTED);

g_object_set (self->ext_install, "state", EXM_INSTALL_BUTTON_STATE_INSTALLING, NULL);

// Move focus to previous widget to avoid losing it after the button becomes insensitive
gtk_widget_grab_focus (GTK_WIDGET (self->ext_author));

gtk_widget_activate_action (GTK_WIDGET (button),
"ext.install",
"(sb)", self->uuid, warn);
Expand Down Expand Up @@ -510,13 +525,13 @@ on_data_loaded (GObject *source,

self->pk = pk;

if (self->signal_id > 0)
g_signal_handler_disconnect (self->show_more_btn, self->signal_id);
if (self->comments_signal_id > 0)
g_signal_handler_disconnect (self->show_more_btn, self->comments_signal_id);

self->signal_id = g_signal_connect (self->show_more_btn,
"clicked",
G_CALLBACK (show_more_comments),
self);
self->comments_signal_id = g_signal_connect (self->show_more_btn,
"clicked",
G_CALLBACK (show_more_comments),
self);

queue_resolve_comments (self, pk, self->resolver_cancel);

Expand Down Expand Up @@ -567,17 +582,23 @@ open_link (ExmDetailView *self,
toplevel = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (self)));

if (strcmp (action_name, "detail.open-extensions") == 0)
{
uri = gtk_uri_launcher_new (self->uri_extensions);
}
else if (strcmp (action_name, "detail.open-homepage") == 0)
{
uri = gtk_uri_launcher_new (self->uri_homepage);
}
else if (strcmp (action_name, "detail.open-donation") == 0)
{
guint val;
g_variant_get (param, "i", &val);
uri = gtk_uri_launcher_new (self->uri_donations[val]);
}
else
{
g_critical ("open_link() invalid action: %s", action_name);
}

gtk_uri_launcher_launch (uri, GTK_WINDOW (toplevel), NULL, NULL, NULL);
}
Expand All @@ -591,6 +612,14 @@ on_bind_manager (ExmDetailView *self)
"extensions", &ext_model,
NULL);

if (self->install_signal_id > 0)
g_signal_handler_disconnect (self->ext_install, self->install_signal_id);

self->install_signal_id = g_signal_connect (self->manager,
"install-status",
G_CALLBACK (on_install_status),
self);

g_signal_connect_swapped (ext_model,
"items-changed",
G_CALLBACK (exm_detail_view_update),
Expand Down
4 changes: 4 additions & 0 deletions src/exm-install-button.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ update_state (ExmInstallButton *button)
gtk_widget_set_sensitive (GTK_WIDGET (button), TRUE);
gtk_widget_add_css_class (GTK_WIDGET (button), "suggested-action");
break;
case EXM_INSTALL_BUTTON_STATE_INSTALLING:
gtk_label_set_label (button->label, _("Installing"));
gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
break;
case EXM_INSTALL_BUTTON_STATE_INSTALLED:
gtk_label_set_label (button->label, C_("State", "Installed"));
gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
Expand Down
90 changes: 53 additions & 37 deletions src/exm-search-row.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,38 +31,35 @@ struct _ExmSearchRow
{
GtkListBoxRow parent_instance;

ExmManager *manager;
ExmSearchResult *search_result;
gboolean is_installed;
gboolean is_supported;
gboolean compact;
gchar *uuid;

GtkLabel *description_label;
ExmInstallButton *install_btn;
guint signal_id;
};

G_DEFINE_FINAL_TYPE (ExmSearchRow, exm_search_row, GTK_TYPE_LIST_BOX_ROW)

enum {
PROP_0,
PROP_MANAGER,
PROP_SEARCH_RESULT,
PROP_IS_INSTALLED,
PROP_IS_SUPPORTED,
PROP_COMPACT,
N_PROPS
};

static GParamSpec *properties [N_PROPS];

ExmSearchRow *
exm_search_row_new (ExmSearchResult *search_result,
gboolean is_installed,
gboolean is_supported)
exm_search_row_new (ExmManager *manager,
ExmSearchResult *search_result)
{
return g_object_new (EXM_TYPE_SEARCH_ROW,
"manager", manager,
"search-result", search_result,
"is-installed", is_installed,
"is-supported", is_supported,
NULL);
}

Expand All @@ -76,15 +73,12 @@ exm_search_row_get_property (GObject *object,

switch (prop_id)
{
case PROP_MANAGER:
g_value_set_object (value, self->manager);
break;
case PROP_SEARCH_RESULT:
g_value_set_object (value, self->search_result);
break;
case PROP_IS_INSTALLED:
g_value_set_boolean (value, self->is_installed);
break;
case PROP_IS_SUPPORTED:
g_value_set_boolean (value, self->is_supported);
break;
case PROP_COMPACT:
g_value_set_boolean (value, self->compact);
break;
Expand All @@ -103,6 +97,9 @@ exm_search_row_set_property (GObject *object,

switch (prop_id)
{
case PROP_MANAGER:
self->manager = g_value_get_object (value);
break;
case PROP_SEARCH_RESULT:
self->search_result = g_value_get_object (value);
if (self->search_result)
Expand All @@ -113,12 +110,6 @@ exm_search_row_set_property (GObject *object,
NULL);
}
break;
case PROP_IS_INSTALLED:
self->is_installed = g_value_get_boolean (value);
break;
case PROP_IS_SUPPORTED:
self->is_supported = g_value_get_boolean (value);
break;
case PROP_COMPACT:
self->compact = g_value_get_boolean (value);
break;
Expand All @@ -127,6 +118,17 @@ exm_search_row_set_property (GObject *object,
}
}

static void
on_install_status (ExmManager *manager G_GNUC_UNUSED,
ExmInstallButtonState state,
ExmSearchRow *self)
{
g_object_set (self->install_btn, "state", state, NULL);

if (self->signal_id > 0)
g_signal_handler_disconnect (self->manager, self->signal_id);
}

static void
install_remote (GtkButton *button,
ExmSearchRow *self)
Expand All @@ -136,7 +138,18 @@ install_remote (GtkButton *button,

g_object_get (self->install_btn, "state", &state, NULL);

self->signal_id = g_signal_connect_object (self->manager,
"install-status",
G_CALLBACK (on_install_status),
self,
G_CONNECT_DEFAULT);

warn = (state == EXM_INSTALL_BUTTON_STATE_UNSUPPORTED);

g_object_set (self->install_btn, "state", EXM_INSTALL_BUTTON_STATE_INSTALLING, NULL);

gtk_widget_grab_focus (GTK_WIDGET (self));

gtk_widget_activate_action (GTK_WIDGET (button),
"ext.install",
"(sb)", self->uuid, warn);
Expand All @@ -148,18 +161,28 @@ exm_search_row_constructed (GObject *object)
ExmSearchRow *self = EXM_SEARCH_ROW (object);

ExmInstallButtonState install_state;
gboolean is_installed;
gboolean is_supported;

gchar *uuid, *description;
g_object_get (self->search_result,
"uuid", &uuid,
"description", &description,
NULL);

gchar *shell_version;
g_object_get (self->manager,
"shell-version",
&shell_version,
NULL);

gtk_actionable_set_action_target (GTK_ACTIONABLE (self), "s", uuid);
is_installed = exm_manager_is_installed_uuid (self->manager, uuid);
is_supported = exm_search_result_supports_shell_version (self->search_result, shell_version);

install_state = self->is_installed
install_state = is_installed
? EXM_INSTALL_BUTTON_STATE_INSTALLED
: (self->is_supported
: (is_supported
? EXM_INSTALL_BUTTON_STATE_DEFAULT
: EXM_INSTALL_BUTTON_STATE_UNSUPPORTED);

Expand Down Expand Up @@ -190,27 +213,20 @@ exm_search_row_class_init (ExmSearchRowClass *klass)
object_class->set_property = exm_search_row_set_property;
object_class->constructed = exm_search_row_constructed;

properties [PROP_MANAGER]
= g_param_spec_object ("manager",
"Manager",
"Manager",
EXM_TYPE_MANAGER,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);

properties [PROP_SEARCH_RESULT] =
g_param_spec_object ("search-result",
"Search Result",
"Search Result",
EXM_TYPE_SEARCH_RESULT,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);

properties [PROP_IS_INSTALLED] =
g_param_spec_boolean ("is-installed",
"Is Installed",
"Is Installed",
FALSE,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);

properties [PROP_IS_SUPPORTED] =
g_param_spec_boolean ("is-supported",
"Is Supported",
"Is Supported",
FALSE,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);

properties [PROP_COMPACT] =
g_param_spec_boolean ("compact",
"Compact",
Expand Down
29 changes: 25 additions & 4 deletions src/exm-search-row.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
/*
* exm-search-row.h
*
* Copyright 2022-2025 Matthew Jakeman <mjakeman26@outlook.co.nz>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/

#pragma once

#include <adwaita.h>
#include <gtk/gtk.h>

#include "local/exm-manager.h"
#include "web/model/exm-search-result.h"

G_BEGIN_DECLS
Expand All @@ -10,8 +32,7 @@ G_BEGIN_DECLS

G_DECLARE_FINAL_TYPE (ExmSearchRow, exm_search_row, EXM, SEARCH_ROW, GtkListBoxRow)

ExmSearchRow *exm_search_row_new (ExmSearchResult *search_result,
gboolean is_installed,
gboolean is_supported);
ExmSearchRow *exm_search_row_new (ExmManager *manager,
ExmSearchResult *search_result);

G_END_DECLS
Loading

0 comments on commit 0e14966

Please sign in to comment.