[gnome-software: 16/29] gs-page: Add GsPage:title property
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software: 16/29] gs-page: Add GsPage:title property
- Date: Wed, 31 Mar 2021 16:03:46 +0000 (UTC)
commit c275ddc3b0758b2325774f6a9ca65ebf08590241
Author: Philip Withnall <pwithnall endlessos org>
Date: Thu Jan 21 11:42:31 2021 +0000
gs-page: Add GsPage:title property
Implement it in the category, details and extras pages as a way to
expose the text they want to display in the `application_details_header`
label. This is one step towards preventing those pages from modifying
the widget directly (which is a layering violation).
Signed-off-by: Philip Withnall <pwithnall endlessos org>
src/gs-category-page.c | 34 ++++++++++++++++++++-
src/gs-details-page.c | 80 ++++++++++++++++++++++++++++++++++++++++++++-----
src/gs-extras-page.c | 51 ++++++++++++++++++++++---------
src/gs-installed-page.c | 10 +++++++
src/gs-overview-page.c | 10 +++++++
src/gs-page.c | 63 ++++++++++++++++++++++++++++++++++++++
src/gs-page.h | 2 ++
src/gs-updates-page.c | 9 ++++++
8 files changed, 236 insertions(+), 23 deletions(-)
---
diff --git a/src/gs-category-page.c b/src/gs-category-page.c
index e57aab1f6..78606fa33 100644
--- a/src/gs-category-page.c
+++ b/src/gs-category-page.c
@@ -57,6 +57,10 @@ struct _GsCategoryPage
G_DEFINE_TYPE (GsCategoryPage, gs_category_page, GS_TYPE_PAGE)
+typedef enum {
+ PROP_TITLE = 1,
+} GsCategoryPageProperty;
+
static void
gs_category_page_switch_to (GsPage *page)
{
@@ -65,7 +69,7 @@ gs_category_page_switch_to (GsPage *page)
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "application_details_header"));
gtk_widget_show (widget);
- gtk_label_set_label (GTK_LABEL (widget), gs_category_get_name (self->category));
+ gtk_label_set_label (GTK_LABEL (widget), gs_page_get_title (page));
}
static void
@@ -480,6 +484,9 @@ gs_category_page_set_category (GsCategoryPage *self, GsCategory *category)
* with the previous scroll value */
adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->scrolledwindow_category));
gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj));
+
+ /* notify of the updated title */
+ g_object_notify (G_OBJECT (self), "title");
}
GsCategory *
@@ -494,6 +501,27 @@ gs_category_page_init (GsCategoryPage *self)
gtk_widget_init_template (GTK_WIDGET (self));
}
+static void
+gs_category_page_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsCategoryPage *self = GS_CATEGORY_PAGE (object);
+
+ switch ((GsCategoryPageProperty) prop_id) {
+ case PROP_TITLE:
+ if (self->category != NULL)
+ g_value_set_string (value, gs_category_get_name (self->category));
+ else
+ g_value_set_string (value, NULL);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
static void
gs_category_page_dispose (GObject *object)
{
@@ -559,11 +587,15 @@ gs_category_page_class_init (GsCategoryPageClass *klass)
GsPageClass *page_class = GS_PAGE_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ object_class->get_property = gs_category_page_get_property;
object_class->dispose = gs_category_page_dispose;
+
page_class->switch_to = gs_category_page_switch_to;
page_class->reload = gs_category_page_reload;
page_class->setup = gs_category_page_setup;
+ g_object_class_override_property (object_class, PROP_TITLE, "title");
+
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-category-page.ui");
gtk_widget_class_bind_template_child (widget_class, GsCategoryPage, category_detail_box);
diff --git a/src/gs-details-page.c b/src/gs-details-page.c
index b8010416c..a4b266133 100644
--- a/src/gs-details-page.c
+++ b/src/gs-details-page.c
@@ -163,10 +163,32 @@ struct _GsDetailsPage
G_DEFINE_TYPE (GsDetailsPage, gs_details_page, GS_TYPE_PAGE)
+typedef enum {
+ PROP_TITLE = 1,
+} GsDetailsPageProperty;
+
+static GsDetailsPageState
+gs_details_page_get_state (GsDetailsPage *self)
+{
+ const gchar *visible_child_name = gtk_stack_get_visible_child_name (GTK_STACK (self->stack_details));
+
+ if (g_str_equal (visible_child_name, "spinner"))
+ return GS_DETAILS_PAGE_STATE_LOADING;
+ else if (g_str_equal (visible_child_name, "ready"))
+ return GS_DETAILS_PAGE_STATE_READY;
+ else if (g_str_equal (visible_child_name, "failed"))
+ return GS_DETAILS_PAGE_STATE_FAILED;
+ else
+ g_assert_not_reached ();
+}
+
static void
gs_details_page_set_state (GsDetailsPage *self,
GsDetailsPageState state)
{
+ if (state == gs_details_page_get_state (self))
+ return;
+
/* spinner */
switch (state) {
case GS_DETAILS_PAGE_STATE_LOADING:
@@ -196,6 +218,9 @@ gs_details_page_set_state (GsDetailsPage *self,
default:
g_assert_not_reached ();
}
+
+ /* the page title will have changed */
+ g_object_notify (G_OBJECT (self), "title");
}
static void
@@ -268,14 +293,13 @@ app_has_pending_action (GsApp *app)
}
static void
-gs_details_page_set_header_label (GsDetailsPage *self,
- const gchar *text)
+gs_details_page_update_header_label (GsDetailsPage *self)
{
GtkWidget *widget;
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "application_details_header"));
- gtk_label_set_label (GTK_LABEL (widget), text ? text : "");
- gtk_widget_set_visible (widget, text != NULL);
+ gtk_label_set_label (GTK_LABEL (widget), gs_page_get_title (GS_PAGE (self)));
+ gtk_widget_set_visible (widget, gtk_label_get_label (GTK_LABEL (widget)) != NULL);
}
static void
@@ -294,7 +318,7 @@ gs_details_page_switch_to (GsPage *page)
if (self->app == NULL)
return;
- gs_details_page_set_header_label (self, gs_app_get_name (self->app));
+ gs_details_page_update_header_label (self);
adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->scrolledwindow_details));
gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj));
@@ -1198,7 +1222,7 @@ gs_details_page_refresh_all (GsDetailsPage *self)
/* change widgets */
tmp = gs_app_get_name (self->app);
- gs_details_page_set_header_label (self, tmp);
+ gs_details_page_update_header_label (self);
if (tmp != NULL && tmp[0] != '\0') {
gtk_label_set_label (GTK_LABEL (self->application_details_title), tmp);
gtk_widget_set_visible (self->application_details_title, TRUE);
@@ -1914,6 +1938,10 @@ _set_app (GsDetailsPage *self, GsApp *app)
/* save app */
g_set_object (&self->app, app);
+
+ /* title/app name will have changed */
+ g_object_notify (G_OBJECT (self), "title");
+
if (self->app == NULL) {
/* switch away from the details view that failed to load */
gs_shell_set_mode (self->shell, GS_SHELL_MODE_OVERVIEW);
@@ -2089,7 +2117,7 @@ gs_details_page_set_local_file (GsDetailsPage *self, GFile *file)
gs_details_page_set_state (self, GS_DETAILS_PAGE_STATE_LOADING);
g_clear_object (&self->app_local_file);
g_clear_object (&self->app);
- gs_details_page_set_header_label (self, _("Loading…"));
+ gs_details_page_update_header_label (self);
plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_FILE_TO_APP,
"file", file,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON |
@@ -2124,7 +2152,7 @@ gs_details_page_set_url (GsDetailsPage *self, const gchar *url)
gs_details_page_set_state (self, GS_DETAILS_PAGE_STATE_LOADING);
g_clear_object (&self->app_local_file);
g_clear_object (&self->app);
- gs_details_page_set_header_label (self, _("Loading…"));
+ gs_details_page_update_header_label (self);
plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_URL_TO_APP,
"search", url,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON |
@@ -2902,6 +2930,38 @@ gs_details_page_setup (GsPage *page,
return TRUE;
}
+static void
+gs_details_page_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsDetailsPage *self = GS_DETAILS_PAGE (object);
+
+ switch ((GsDetailsPageProperty) prop_id) {
+ case PROP_TITLE:
+ switch (gs_details_page_get_state (self)) {
+ case GS_DETAILS_PAGE_STATE_LOADING:
+ /* TRANSLATORS: This is a title for the app details page,
+ * shown when it’s loading the details of an app. */
+ g_value_set_string (value, _("Loading…"));
+ break;
+ case GS_DETAILS_PAGE_STATE_READY:
+ g_value_set_string (value, gs_app_get_name (self->app));
+ break;
+ case GS_DETAILS_PAGE_STATE_FAILED:
+ g_value_set_string (value, NULL);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
static void
gs_details_page_dispose (GObject *object)
{
@@ -2933,13 +2993,17 @@ gs_details_page_class_init (GsDetailsPageClass *klass)
GsPageClass *page_class = GS_PAGE_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ object_class->get_property = gs_details_page_get_property;
object_class->dispose = gs_details_page_dispose;
+
page_class->app_installed = gs_details_page_app_installed;
page_class->app_removed = gs_details_page_app_removed;
page_class->switch_to = gs_details_page_switch_to;
page_class->reload = gs_details_page_reload;
page_class->setup = gs_details_page_setup;
+ g_object_class_override_property (object_class, PROP_TITLE, "title");
+
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-details-page.ui");
gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, application_details_icon);
diff --git a/src/gs-extras-page.c b/src/gs-extras-page.c
index 6f7df2045..736ced3bb 100644
--- a/src/gs-extras-page.c
+++ b/src/gs-extras-page.c
@@ -76,6 +76,7 @@ typedef enum {
PROP_VADJUSTMENT,
PROP_HSCROLL_POLICY,
PROP_VSCROLL_POLICY,
+ PROP_TITLE,
} GsExtrasPageProperty;
static void
@@ -216,20 +217,7 @@ gs_extras_page_update_ui_state (GsExtrasPage *self)
/* headerbar title */
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "application_details_header"));
- switch (self->state) {
- case GS_EXTRAS_PAGE_STATE_LOADING:
- case GS_EXTRAS_PAGE_STATE_READY:
- title = build_title (self);
- gtk_label_set_label (GTK_LABEL (widget), title);
- break;
- case GS_EXTRAS_PAGE_STATE_NO_RESULTS:
- case GS_EXTRAS_PAGE_STATE_FAILED:
- gtk_label_set_label (GTK_LABEL (widget), _("Unable to Find Requested Software"));
- break;
- default:
- g_assert_not_reached ();
- break;
- }
+ gtk_label_set_label (GTK_LABEL (widget), gs_page_get_title (GS_PAGE (self)));
/* stack */
switch (self->state) {
@@ -280,7 +268,12 @@ static void
gs_extras_page_set_state (GsExtrasPage *self,
GsExtrasPageState state)
{
+ if (self->state == state)
+ return;
+
self->state = state;
+
+ g_object_notify (G_OBJECT (self), "title");
gs_extras_page_update_ui_state (self);
gs_extras_page_maybe_emit_installed_resources_done (self);
}
@@ -779,6 +772,9 @@ gs_extras_page_load (GsExtrasPage *self, GPtrArray *array_search_data)
}
self->pending_search_cnt++;
}
+
+ /* the page title will have changed */
+ g_object_notify (G_OBJECT (self), "title");
}
static void
@@ -1048,7 +1044,14 @@ gs_extras_page_search (GsExtrasPage *self,
const gchar *desktop_id,
const gchar *ident)
{
+ GsExtrasPageMode old_mode;
+
+ old_mode = self->mode;
self->mode = gs_extras_page_mode_from_string (mode_str);
+
+ if (old_mode != self->mode)
+ g_object_notify (G_OBJECT (self), "title");
+
g_clear_pointer (&self->caller_app_name, g_free);
self->caller_app_name = gs_extras_page_get_app_name (desktop_id);
g_clear_pointer (&self->install_resources_ident, g_free);
@@ -1234,6 +1237,21 @@ gs_extras_page_get_property (GObject *object,
case PROP_VSCROLL_POLICY:
g_value_set_enum (value, GTK_SCROLL_MINIMUM);
break;
+ case PROP_TITLE:
+ switch (self->state) {
+ case GS_EXTRAS_PAGE_STATE_LOADING:
+ case GS_EXTRAS_PAGE_STATE_READY:
+ g_value_take_string (value, build_title (self));
+ break;
+ case GS_EXTRAS_PAGE_STATE_NO_RESULTS:
+ case GS_EXTRAS_PAGE_STATE_FAILED:
+ g_value_set_string (value, _("Unable to Find Requested Software"));
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1262,6 +1280,10 @@ gs_extras_page_set_property (GObject *object,
/* Not supported yet */
g_assert_not_reached ();
break;
+ case PROP_TITLE:
+ /* Read-only */
+ g_assert_not_reached ();
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1332,6 +1354,7 @@ gs_extras_page_class_init (GsExtrasPageClass *klass)
g_object_class_override_property (object_class, PROP_VADJUSTMENT, "vadjustment");
g_object_class_override_property (object_class, PROP_HSCROLL_POLICY, "hscroll-policy");
g_object_class_override_property (object_class, PROP_VSCROLL_POLICY, "vscroll-policy");
+ g_object_class_override_property (object_class, PROP_TITLE, "title");
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-extras-page.ui");
diff --git a/src/gs-installed-page.c b/src/gs-installed-page.c
index 5ff4fc8d4..f3c595cd2 100644
--- a/src/gs-installed-page.c
+++ b/src/gs-installed-page.c
@@ -51,6 +51,7 @@ typedef enum {
PROP_VADJUSTMENT,
PROP_HSCROLL_POLICY,
PROP_VSCROLL_POLICY,
+ PROP_TITLE,
} GsInstalledPageProperty;
static void gs_installed_page_pending_apps_changed_cb (GsPluginLoader *plugin_loader,
@@ -630,6 +631,10 @@ gs_installed_page_get_property (GObject *object,
case PROP_VSCROLL_POLICY:
g_value_set_enum (value, GTK_SCROLL_MINIMUM);
break;
+ case PROP_TITLE:
+ /* Translators: This is in the context of a list of apps which are installed on the system. */
+ g_value_set_string (value, _("Installed"));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -658,6 +663,10 @@ gs_installed_page_set_property (GObject *object,
/* Not supported yet */
g_assert_not_reached ();
break;
+ case PROP_TITLE:
+ /* Read only. */
+ g_assert_not_reached ();
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -702,6 +711,7 @@ gs_installed_page_class_init (GsInstalledPageClass *klass)
g_object_class_override_property (object_class, PROP_VADJUSTMENT, "vadjustment");
g_object_class_override_property (object_class, PROP_HSCROLL_POLICY, "hscroll-policy");
g_object_class_override_property (object_class, PROP_VSCROLL_POLICY, "vscroll-policy");
+ g_object_class_override_property (object_class, PROP_TITLE, "title");
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/Software/gs-installed-page.ui");
diff --git a/src/gs-overview-page.c b/src/gs-overview-page.c
index d1ddc71b9..fe67feb27 100644
--- a/src/gs-overview-page.c
+++ b/src/gs-overview-page.c
@@ -70,6 +70,7 @@ typedef enum {
PROP_VADJUSTMENT,
PROP_HSCROLL_POLICY,
PROP_VSCROLL_POLICY,
+ PROP_TITLE,
} GsOverviewPageProperty;
enum {
@@ -907,6 +908,10 @@ gs_overview_page_get_property (GObject *object,
case PROP_VSCROLL_POLICY:
g_value_set_enum (value, GTK_SCROLL_MINIMUM);
break;
+ case PROP_TITLE:
+ /* Translators: This is the title of the main page of the UI. */
+ g_value_set_string (value, _("Explore"));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -935,6 +940,10 @@ gs_overview_page_set_property (GObject *object,
/* Not supported yet */
g_assert_not_reached ();
break;
+ case PROP_TITLE:
+ /* Read only. */
+ g_assert_not_reached ();
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -976,6 +985,7 @@ gs_overview_page_class_init (GsOverviewPageClass *klass)
g_object_class_override_property (object_class, PROP_VADJUSTMENT, "vadjustment");
g_object_class_override_property (object_class, PROP_HSCROLL_POLICY, "hscroll-policy");
g_object_class_override_property (object_class, PROP_VSCROLL_POLICY, "vscroll-policy");
+ g_object_class_override_property (object_class, PROP_TITLE, "title");
signals [SIGNAL_REFRESHED] =
g_signal_new ("refreshed",
diff --git a/src/gs-page.c b/src/gs-page.c
index 30fb303b2..8adba6f96 100644
--- a/src/gs-page.c
+++ b/src/gs-page.c
@@ -28,6 +28,12 @@ typedef struct
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GsPage, gs_page, GTK_TYPE_BIN)
+typedef enum {
+ PROP_TITLE = 1,
+} GsPageProperty;
+
+static GParamSpec *obj_props[PROP_TITLE + 1] = { NULL, };
+
GsShell *
gs_page_get_shell (GsPage *page)
{
@@ -594,6 +600,30 @@ gs_page_is_active (GsPage *page)
return priv->is_active;
}
+/**
+ * gs_page_get_title:
+ * @page: a #GsPage
+ *
+ * Get the value of #GsPage:title.
+ *
+ * Returns: (nullable): human readable title for the page, or %NULL if one isn’t set
+ *
+ * Since: 40
+ */
+const gchar *
+gs_page_get_title (GsPage *page)
+{
+ g_auto(GValue) value = G_VALUE_INIT;
+
+ g_return_val_if_fail (GS_IS_PAGE (page), NULL);
+
+ /* The property is typically overridden by subclasses; the
+ * implementation in #GsPage itself is just a placeholder. */
+ g_object_get_property (G_OBJECT (page), "title", &value);
+
+ return g_value_get_string (&value);
+}
+
/**
* gs_page_switch_to:
*
@@ -680,6 +710,23 @@ gs_page_setup (GsPage *page,
return klass->setup (page, shell, plugin_loader, builder, cancellable, error);
}
+static void
+gs_page_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch ((GsPageProperty) prop_id) {
+ case PROP_TITLE:
+ /* Should be overridden by subclasses. */
+ g_value_set_string (value, NULL);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
static void
gs_page_dispose (GObject *object)
{
@@ -703,7 +750,23 @@ gs_page_class_init (GsPageClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = gs_page_get_property;
object_class->dispose = gs_page_dispose;
+
+ /**
+ * GsPage:title: (nullable)
+ *
+ * A human readable title for this page, or %NULL if one isn’t set or
+ * doesn’t make sense.
+ *
+ * Since: 40
+ */
+ obj_props[PROP_TITLE] =
+ g_param_spec_string ("title", NULL, NULL,
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_props), obj_props);
}
GsPage *
diff --git a/src/gs-page.h b/src/gs-page.h
index 6594e3aae..aba930a52 100644
--- a/src/gs-page.h
+++ b/src/gs-page.h
@@ -75,4 +75,6 @@ gboolean gs_page_setup (GsPage *page,
GError **error);
gboolean gs_page_is_active (GsPage *page);
+const gchar *gs_page_get_title (GsPage *page);
+
G_END_DECLS
diff --git a/src/gs-updates-page.c b/src/gs-updates-page.c
index 2c0c5291f..24e4bf5c5 100644
--- a/src/gs-updates-page.c
+++ b/src/gs-updates-page.c
@@ -103,6 +103,7 @@ typedef enum {
PROP_VADJUSTMENT,
PROP_HSCROLL_POLICY,
PROP_VSCROLL_POLICY,
+ PROP_TITLE,
} GsUpdatesPageProperty;
static void
@@ -1320,6 +1321,9 @@ gs_updates_page_get_property (GObject *object,
case PROP_VSCROLL_POLICY:
g_value_set_enum (value, GTK_SCROLL_MINIMUM);
break;
+ case PROP_TITLE:
+ g_value_set_string (value, _("Updates"));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1348,6 +1352,10 @@ gs_updates_page_set_property (GObject *object,
/* Not supported yet */
g_assert_not_reached ();
break;
+ case PROP_TITLE:
+ /* Read only */
+ g_assert_not_reached ();
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1405,6 +1413,7 @@ gs_updates_page_class_init (GsUpdatesPageClass *klass)
g_object_class_override_property (object_class, PROP_VADJUSTMENT, "vadjustment");
g_object_class_override_property (object_class, PROP_HSCROLL_POLICY, "hscroll-policy");
g_object_class_override_property (object_class, PROP_VSCROLL_POLICY, "vscroll-policy");
+ g_object_class_override_property (object_class, PROP_TITLE, "title");
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-updates-page.ui");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]