[gnome-software/wip/detailed-preference-format] gs-details-page: Allow specify packaging format with origin name
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/wip/detailed-preference-format] gs-details-page: Allow specify packaging format with origin name
- Date: Tue, 4 Oct 2022 07:55:55 +0000 (UTC)
commit ce049b86ac62d74c95063d934953e7773e8397fd
Author: Milan Crha <mcrha redhat com>
Date: Tue Oct 4 09:51:00 2022 +0200
gs-details-page: Allow specify packaging format with origin name
Let the format be optionally extended with an origin name, to be able
to define packaging format in a more fine-grained way. An example is:
[ 'flatpak:flathub', 'rpm', 'flatpak' ]
which prefers apps from the Flathub Flatpak remote, if it does not exist,
then chooses an RPM version of the app, and if even that does not exist,
then chooses a Flatpak version from any remote.
data/org.gnome.software.gschema.xml | 2 +-
src/gs-details-page.c | 100 +++++++++++++++++-------------------
2 files changed, 48 insertions(+), 54 deletions(-)
---
diff --git a/data/org.gnome.software.gschema.xml b/data/org.gnome.software.gschema.xml
index aa074f168..d468d9cde 100644
--- a/data/org.gnome.software.gschema.xml
+++ b/data/org.gnome.software.gschema.xml
@@ -136,7 +136,7 @@
</key>
<key name="packaging-format-preference" type="as">
<default>['']</default>
- <summary>Priority order of packaging formats to prefer, with more important formats listed first. An
empty array means the default order. Omitted formats are assumed to be listed last. Example packaging formats
are: deb, flatpak, rpm, snap.</summary>
+ <summary>Priority order of packaging formats to prefer, with more important formats listed first. An
empty array means the default order. Omitted formats are assumed to be listed last. Example packaging formats
are: deb, flatpak, rpm, snap. The formats can be optionally specified with an origin name, divided by a
colon, for example 'flatpak:flathub'.</summary>
</key>
<child name="auth" schema="org.gnome.software.auth"/>
</schema>
diff --git a/src/gs-details-page.c b/src/gs-details-page.c
index 50b80e159..b15a2bf1f 100644
--- a/src/gs-details-page.c
+++ b/src/gs-details-page.c
@@ -90,7 +90,7 @@ struct _GsDetailsPage
GSettings *settings;
GsOdrsProvider *odrs_provider; /* (nullable) (owned), NULL if reviews are disabled */
GAppInfoMonitor *app_info_monitor; /* (owned) */
- GHashTable *packaging_format_preference; /* gchar * ~> gint */
+ gchar **packaging_format_preference; /* (owned) */
GtkWidget *app_reviews_dialog;
GtkCssProvider *origin_css_provider; /* (nullable) (owned) */
gboolean origin_by_packaging_format; /* when TRUE, change the 'app' to the most
preferred
@@ -598,24 +598,52 @@ app_origin_equal (GsApp *a,
return TRUE;
}
+static gint
+gs_details_page_get_app_packaging_format_preference_index (GsDetailsPage *self,
+ GsApp *app)
+{
+ const gchar *packaging_format;
+ guint packaging_format_len;
+
+ /* Index 0 means unspecified packaging format in the preference array */
+ if (self->packaging_format_preference == NULL)
+ return 0;
+
+ packaging_format = gs_app_get_packaging_format_raw (app);
+ if (packaging_format == NULL)
+ return 0;
+
+ packaging_format_len = strlen (packaging_format);
+
+ /* The preference can be defined either as the packaging format
+ on its own, like "rpm", or with an origin name, like "flatpak:flathub". */
+ for (guint i = 0; self->packaging_format_preference[i]; i++) {
+ const gchar *preference = self->packaging_format_preference[i];
+ if (g_ascii_strncasecmp (preference, packaging_format, packaging_format_len) == 0) {
+ if (preference[packaging_format_len] == '\0')
+ return (gint) i + 1;
+ if (preference[packaging_format_len] == ':') {
+ const gchar *origin = gs_app_get_origin (app);
+ if (origin != NULL &&
+ g_ascii_strcasecmp (origin, preference + packaging_format_len + 1) == 0)
+ return (gint) i + 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
static gint
sort_by_packaging_format_preference (GsApp *app1,
GsApp *app2,
gpointer user_data)
{
- GHashTable *preference = user_data;
- const gchar *packaging_format_raw1 = gs_app_get_packaging_format_raw (app1);
- const gchar *packaging_format_raw2 = gs_app_get_packaging_format_raw (app2);
+ GsDetailsPage *self = user_data;
gint index1, index2;
- if (g_strcmp0 (packaging_format_raw1, packaging_format_raw2) == 0)
- return 0;
-
- if (packaging_format_raw1 == NULL || packaging_format_raw2 == NULL)
- return packaging_format_raw1 == NULL ? -1 : 1;
-
- index1 = GPOINTER_TO_INT (g_hash_table_lookup (preference, packaging_format_raw1));
- index2 = GPOINTER_TO_INT (g_hash_table_lookup (preference, packaging_format_raw2));
+ index1 = gs_details_page_get_app_packaging_format_preference_index (self, app1);
+ index2 = gs_details_page_get_app_packaging_format_preference_index (self, app2);
if (index1 == index2)
return 0;
@@ -718,8 +746,8 @@ gs_details_page_get_alternates_cb (GObject *source_object,
self->app != NULL && gs_app_get_state (self->app) != GS_APP_STATE_INSTALLED;
/* Sort the alternates by the user's packaging preferences */
- if (g_hash_table_size (self->packaging_format_preference) > 0)
- gs_app_list_sort (list, sort_by_packaging_format_preference,
self->packaging_format_preference);
+ if (self->packaging_format_preference != NULL)
+ gs_app_list_sort (list, sort_by_packaging_format_preference, self);
for (guint i = 0; i < gs_app_list_length (list); i++) {
GsApp *app = gs_app_list_index (list, i);
@@ -746,8 +774,7 @@ gs_details_page_get_alternates_cb (GObject *source_object,
gtk_list_box_append (GTK_LIST_BOX (self->origin_popover_list_box), row);
if (origin_by_packaging_format) {
- const gchar *packaging_format = gs_app_get_packaging_format_raw (app);
- gint index = GPOINTER_TO_INT (g_hash_table_lookup (self->packaging_format_preference,
packaging_format));
+ gint index = gs_details_page_get_app_packaging_format_preference_index (self, app);
if (index > 0 && (index < origin_row_by_packaging_format_index ||
origin_row_by_packaging_format_index == 0)) {
origin_row_by_packaging_format_index = index;
origin_row_by_packaging_format = row;
@@ -1919,19 +1946,13 @@ gs_details_page_read_packaging_format_preference (GsDetailsPage *self)
{
g_auto(GStrv) preference = NULL;
- if (self->packaging_format_preference == NULL)
- return;
-
- g_hash_table_remove_all (self->packaging_format_preference);
+ g_clear_pointer (&self->packaging_format_preference, g_strfreev);
preference = g_settings_get_strv (self->settings, "packaging-format-preference");
if (preference == NULL || preference[0] == NULL)
return;
- for (gsize ii = 0; preference[ii] != NULL; ii++) {
- /* Using 'ii + 1' to easily distinguish between "not found" and "the first" index */
- g_hash_table_insert (self->packaging_format_preference, g_strdup (preference[ii]),
GINT_TO_POINTER (ii + 1));
- }
+ self->packaging_format_preference = g_steal_pointer (&preference);
}
static void
@@ -2263,30 +2284,6 @@ gs_details_page_setup (GsPage *page,
return TRUE;
}
-static guint
-gs_details_page_strcase_hash (gconstpointer key)
-{
- const gchar *ptr;
- guint hsh = 0, gg;
-
- for (ptr = (const gchar *) key; *ptr != '\0'; ptr++) {
- hsh = (hsh << 4) + g_ascii_toupper (*ptr);
- if ((gg = hsh & 0xf0000000)) {
- hsh = hsh ^ (gg >> 24);
- hsh = hsh ^ gg;
- }
- }
-
- return hsh;
-}
-
-static gboolean
-gs_details_page_strcase_equal (gconstpointer key1,
- gconstpointer key2)
-{
- return g_ascii_strcasecmp ((const gchar *) key1, (const gchar *) key2) == 0;
-}
-
static void
gs_details_page_get_property (GObject *object,
guint prop_id,
@@ -2359,10 +2356,8 @@ gs_details_page_dispose (GObject *object)
g_signal_handlers_disconnect_by_func (self->app, gs_details_page_progress_changed_cb, self);
g_clear_object (&self->app);
}
- if (self->packaging_format_preference) {
- g_hash_table_unref (self->packaging_format_preference);
- self->packaging_format_preference = NULL;
- }
+
+ g_clear_pointer (&self->packaging_format_preference, g_strfreev);
g_clear_object (&self->origin_css_provider);
g_clear_object (&self->app_local_file);
g_clear_object (&self->app_reviews_dialog);
@@ -2573,7 +2568,6 @@ gs_details_page_init (GsDetailsPage *self)
gtk_widget_init_template (GTK_WIDGET (self));
- self->packaging_format_preference = g_hash_table_new_full (gs_details_page_strcase_hash,
gs_details_page_strcase_equal, g_free, NULL);
self->settings = g_settings_new ("org.gnome.software");
g_signal_connect_swapped (self->settings, "changed",
G_CALLBACK (settings_changed_cb),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]