[gnome-software/1409-add-available-for-fedora-section-to-the-explore-page] gs-overview-page: Add a distro-featured section



commit 658a918ed81051fbd65e1770eb3b05875a71687b
Author: Milan Crha <mcrha redhat com>
Date:   Wed Sep 8 16:15:49 2021 +0200

    gs-overview-page: Add a distro-featured section
    
    This requires distro-provided distro-featured.ini file at
    DATADIR/gnome-software/ (like at /usr/share/gnome-software/),
    which contains localized title for the section. An example
    file can be found at contrib/distro-featured.ini .
    When the file does not exist or when it does not contain the section
    title or when it is otherwise broken, then the distro-featured section
    is hidden.
    
    The distro-featured sections shows applications, which are tagged
    with "GnomeSoftware::DistroFeatured" key. This can be done with an appstream
    data file saved into /usr/share/app-info/xmls/.  An example file can be found
    at contrib/org.gnome.Software.DistroFeatured.xml . The applications can be
    tagged with this key by other means, this is only one way to do it.
    
    Once there are found enough applications (currently at least 12), and
    the distro-featured.ini is a correct file, the section is shown.

 contrib/distro-featured.ini                   |   7 ++
 contrib/org.gnome.Software.DistroFeatured.xml |  11 +++
 src/gs-overview-page.c                        | 105 ++++++++++++++++++++++++++
 src/gs-overview-page.ui                       |  28 +++++++
 4 files changed, 151 insertions(+)
---
diff --git a/contrib/distro-featured.ini b/contrib/distro-featured.ini
new file mode 100644
index 000000000..4c00bdce7
--- /dev/null
+++ b/contrib/distro-featured.ini
@@ -0,0 +1,7 @@
+# This file is only an example, it contains the localized title
+# for the distro-featured section of the overview page.
+# It should be saved to DATADIR/gnome-software/. When not found,
+# or otherwise broken, the distro-featured section is hidden.
+[Section]
+title=Available for Distro
+title[en_GB]=Available for Distribution
diff --git a/contrib/org.gnome.Software.DistroFeatured.xml b/contrib/org.gnome.Software.DistroFeatured.xml
new file mode 100644
index 000000000..1b5b7a216
--- /dev/null
+++ b/contrib/org.gnome.Software.DistroFeatured.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This is only an example file, what the distro-featured file can look like;
+     it should be installed beside the org.gnome.Software.Featured.xml file. -->
+<components>
+  <component merge="append">
+    <id>org.gnome.Software.desktop</id>
+    <custom>
+      <value key="GnomeSoftware::DistroFeatured">True</value>
+    </custom>
+  </component>
+</components>
diff --git a/src/gs-overview-page.c b/src/gs-overview-page.c
index 09ec17921..891351796 100644
--- a/src/gs-overview-page.c
+++ b/src/gs-overview-page.c
@@ -35,10 +35,12 @@ struct _GsOverviewPage
        GsShell                 *shell;
        gint                     action_cnt;
        gboolean                 loading_featured;
+       gboolean                 loading_distro_featured;
        gboolean                 loading_popular;
        gboolean                 loading_recent;
        gboolean                 loading_categories;
        gboolean                 empty;
+       gboolean                 distro_featured_available;
        GHashTable              *category_hash;         /* id : GsCategory */
        gchar                   *third_party_cmdtool;
        gboolean                 third_party_needs_question;
@@ -49,11 +51,13 @@ struct _GsOverviewPage
        GtkWidget               *box_overview;
        GtkWidget               *box_popular;
        GtkWidget               *box_recent;
+       GtkWidget               *box_distro_featured;
        GtkWidget               *flowbox_categories;
        GtkWidget               *flowbox_iconless_categories;
        GtkWidget               *iconless_categories_heading;
        GtkWidget               *popular_heading;
        GtkWidget               *recent_heading;
+       GtkWidget               *distro_featured_heading;
        GtkWidget               *scrolledwindow_overview;
        GtkWidget               *stack_overview;
 };
@@ -113,6 +117,7 @@ gs_overview_page_decrement_action_cnt (GsOverviewPage *self)
        self->cache_valid = TRUE;
        g_signal_emit (self, signals[SIGNAL_REFRESHED], 0);
        self->loading_categories = FALSE;
+       self->loading_distro_featured = FALSE;
        self->loading_featured = FALSE;
        self->loading_popular = FALSE;
        self->loading_recent = FALSE;
@@ -284,6 +289,56 @@ out:
        gs_overview_page_decrement_action_cnt (self);
 }
 
+static void
+gs_overview_page_get_distro_featured_cb (GObject *source_object,
+                                        GAsyncResult *res,
+                                        gpointer user_data)
+{
+       GsOverviewPage *self = GS_OVERVIEW_PAGE (user_data);
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object);
+       guint i;
+       GsApp *app;
+       GtkWidget *tile;
+       g_autoptr(GError) error = NULL;
+       g_autoptr(GsAppList) list = NULL;
+
+       /* get distro-featured apps */
+       list = gs_plugin_loader_job_process_finish (plugin_loader, res, &error);
+       if (list == NULL) {
+               if (!g_error_matches (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED))
+                       g_warning ("failed to get distro-featured apps: %s", error->message);
+               goto out;
+       }
+
+       /* not enough to show */
+       if (gs_app_list_length (list) < N_TILES) {
+               g_warning ("Only %u apps for distro-featured list, hiding",
+                          gs_app_list_length (list));
+               gtk_widget_set_visible (self->box_distro_featured, FALSE);
+               gtk_widget_set_visible (self->distro_featured_heading, FALSE);
+               goto out;
+       }
+
+       gs_app_list_randomize (list);
+
+       gs_container_remove_all (GTK_CONTAINER (self->box_distro_featured));
+
+       for (i = 0; i < gs_app_list_length (list) && i < N_TILES; i++) {
+               app = gs_app_list_index (list, i);
+               tile = gs_summary_tile_new (app);
+               g_signal_connect (tile, "clicked",
+                         G_CALLBACK (app_tile_clicked), self);
+               gtk_container_add (GTK_CONTAINER (self->box_distro_featured), tile);
+       }
+       gtk_widget_set_visible (self->box_distro_featured, TRUE);
+       gtk_widget_set_visible (self->distro_featured_heading, TRUE);
+
+       self->empty = FALSE;
+
+out:
+       gs_overview_page_decrement_action_cnt (self);
+}
+
 static void
 category_tile_clicked (GsCategoryTile *tile, gpointer data)
 {
@@ -574,6 +629,25 @@ gs_overview_page_load (GsOverviewPage *self)
                self->action_cnt++;
        }
 
+       if (!self->loading_distro_featured && self->distro_featured_available) {
+               g_autoptr(GsPluginJob) plugin_job = NULL;
+
+               self->loading_distro_featured = TRUE;
+               plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_DISTRO_FEATURED,
+                                                "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_RATING |
+                                                                GS_PLUGIN_REFINE_FLAGS_REQUIRE_CATEGORIES |
+                                                                GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
+                                                "dedupe-flags", GS_APP_LIST_FILTER_FLAG_PREFER_INSTALLED |
+                                                                GS_APP_LIST_FILTER_FLAG_KEY_ID_PROVIDES,
+                                                NULL);
+               gs_plugin_loader_job_process_async (self->plugin_loader,
+                                                   plugin_job,
+                                                   self->cancellable,
+                                                   gs_overview_page_get_distro_featured_cb,
+                                                   self);
+               self->action_cnt++;
+       }
+
        if (!self->loading_popular) {
                g_autoptr(GsPluginJob) plugin_job = NULL;
 
@@ -741,9 +815,38 @@ refreshed_cb (GsOverviewPage *self, gpointer user_data)
 static void
 gs_overview_page_init (GsOverviewPage *self)
 {
+       g_autofree gchar *filename;
+
        gtk_widget_init_template (GTK_WIDGET (self));
 
        g_signal_connect (self, "refreshed", G_CALLBACK (refreshed_cb), self);
+
+       filename = g_build_filename (DATADIR, "gnome-software", "distro-featured.ini", NULL);
+       self->distro_featured_available = g_file_test (filename, G_FILE_TEST_EXISTS);
+       if (self->distro_featured_available) {
+               g_autoptr(GKeyFile) key_file = NULL;
+               g_autoptr(GError) error = NULL;
+
+               key_file = g_key_file_new ();
+               if (g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, &error)) {
+                       g_autofree gchar *title = NULL;
+                       title = g_key_file_get_locale_string (key_file, "Section", "title", NULL, &error);
+                       self->distro_featured_available = title != NULL;
+                       if (title != NULL) {
+                               gtk_label_set_text (GTK_LABEL (self->distro_featured_heading), title);
+                               g_debug ("Read distro-featured information from '%s'", filename);
+                       } else {
+                               g_warning ("Failed to read [Section] title=... from '%s': %s", filename, 
error->message);
+                       }
+               } else {
+                       g_warning ("Failed to load '%s': %s", filename, error->message);
+               }
+       } else {
+               g_debug ("The distro-featured information file '%s' not found, skipping...", filename);
+       }
+
+       gtk_widget_set_visible (self->box_distro_featured, self->distro_featured_available);
+       gtk_widget_set_visible (self->distro_featured_heading, self->distro_featured_available);
 }
 
 static void
@@ -831,11 +934,13 @@ gs_overview_page_class_init (GsOverviewPageClass *klass)
        gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, box_overview);
        gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, box_popular);
        gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, box_recent);
+       gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, box_distro_featured);
        gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, flowbox_categories);
        gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, flowbox_iconless_categories);
        gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, iconless_categories_heading);
        gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, popular_heading);
        gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, recent_heading);
+       gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, distro_featured_heading);
        gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, scrolledwindow_overview);
        gtk_widget_class_bind_template_child (widget_class, GsOverviewPage, stack_overview);
        gtk_widget_class_bind_template_callback (widget_class, featured_carousel_app_clicked_cb);
diff --git a/src/gs-overview-page.ui b/src/gs-overview-page.ui
index 8cc16233d..8a635787a 100644
--- a/src/gs-overview-page.ui
+++ b/src/gs-overview-page.ui
@@ -168,6 +168,34 @@
                               </object>
                             </child>
 
+                            <child>
+                              <object class="GtkLabel" id="distro_featured_heading">
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label">Available for Distro</property> <!-- placeholder, set 
in the code -->
+                                <property name="margin-top">21</property>
+                                <property name="margin-bottom">6</property>
+                                <accessibility>
+                                  <relation target="box_distro_featured" type="label-for"/>
+                                </accessibility>
+                                <style>
+                                  <class name="index-title-alignment-software"/>
+                                </style>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkFlowBox" id="box_distro_featured">
+                                <property name="visible">True</property>
+                                <property name="homogeneous">True</property>
+                                <property name="column-spacing">14</property>
+                                <property name="row-spacing">14</property>
+                                <property name="valign">start</property>
+                                <accessibility>
+                                  <relation target="distro_featured_heading" type="labelled-by"/>
+                                </accessibility>
+                              </object>
+                            </child>
+
                             <child>
                               <object class="GtkLabel" id="iconless_categories_heading">
                                 <property name="visible">True</property>


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