[gnome-software] Show two sets of featured categories on the overview page



commit 6b8ad2cf0e2880bc3d21676ce3331b4305030e4e
Author: Richard Hughes <richard hughsie com>
Date:   Tue Jul 12 09:19:55 2016 +0100

    Show two sets of featured categories on the overview page

 src/gs-shell-overview.c  |  187 +++++++++++++++++++++++++++++-----------------
 src/gs-shell-overview.ui |   55 +-------------
 2 files changed, 120 insertions(+), 122 deletions(-)
---
diff --git a/src/gs-shell-overview.c b/src/gs-shell-overview.c
index 897bdd2..795a7e2 100644
--- a/src/gs-shell-overview.c
+++ b/src/gs-shell-overview.c
@@ -22,6 +22,7 @@
 #include "config.h"
 
 #include <glib/gi18n.h>
+#include <math.h>
 
 #include "gs-shell.h"
 #include "gs-shell-overview.h"
@@ -31,6 +32,7 @@
 #include "gs-popular-tile.h"
 #include "gs-feature-tile.h"
 #include "gs-category-tile.h"
+#include "gs-hiding-box.h"
 #include "gs-common.h"
 
 #define N_TILES 9
@@ -54,12 +56,10 @@ typedef struct
        GtkWidget               *bin_featured;
        GtkWidget               *box_overview;
        GtkWidget               *box_popular;
-       GtkWidget               *box_popular_rotating;
        GtkWidget               *category_heading;
        GtkWidget               *flowbox_categories;
        GtkWidget               *flowbox_categories2;
        GtkWidget               *popular_heading;
-       GtkWidget               *popular_rotating_heading;
        GtkWidget               *scrolledwindow_overview;
        GtkWidget               *stack_overview;
        GtkWidget               *categories_expander_button;
@@ -79,6 +79,7 @@ static guint signals [SIGNAL_LAST] = { 0 };
 typedef struct {
         GsCategory     *category;
         GsShellOverview        *self;
+        const gchar    *title;
 } LoadData;
 
 static void
@@ -178,6 +179,8 @@ gs_shell_overview_get_category_apps_cb (GObject *source_object,
        guint i;
        GsApp *app;
        GtkWidget *tile;
+       GtkWidget *label;
+       GtkWidget *box;
        g_autoptr(GError) error = NULL;
        g_autoptr(GsAppList) list = NULL;
 
@@ -186,30 +189,39 @@ gs_shell_overview_get_category_apps_cb (GObject *source_object,
        if (list == NULL) {
                if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
                        g_warning ("failed to get recommended applications: %s", error->message);
-               gtk_widget_hide (priv->popular_rotating_heading);
-               gtk_widget_hide (priv->box_popular_rotating);
                goto out;
        } else if (gs_app_list_length (list) < N_TILES) {
                g_warning ("hiding recommended applications: "
                           "found only %d to show, need at least %d",
                           gs_app_list_length (list), N_TILES);
-               gtk_widget_hide (priv->popular_rotating_heading);
-               gtk_widget_hide (priv->box_popular_rotating);
                goto out;
        }
        gs_app_list_randomize (list);
 
-       gtk_widget_show (priv->popular_rotating_heading);
-       gtk_widget_show (priv->box_popular_rotating);
-
-       gs_container_remove_all (GTK_CONTAINER (priv->box_popular_rotating));
-
+       /* add header */
+       label = gtk_label_new (load_data->title);
+       gtk_widget_set_visible (label, TRUE);
+       gtk_label_set_xalign (GTK_LABEL (label), 0.f);
+       gtk_widget_set_margin_top (label, 24);
+       gtk_widget_set_margin_bottom (label, 6);
+       gtk_style_context_add_class (gtk_widget_get_style_context (label),
+                                    "index-title-alignment-software");
+       gtk_container_add (GTK_CONTAINER (priv->box_overview), label);
+
+       /* add hiding box */
+       box = gs_hiding_box_new ();
+       gs_hiding_box_set_spacing (GS_HIDING_BOX (box), 14);
+       gtk_widget_set_visible (box, TRUE);
+       gtk_widget_set_valign (box, GTK_ALIGN_START);
+       gtk_container_add (GTK_CONTAINER (priv->box_overview), box);
+
+       /* add all the apps */
        for (i = 0; i < gs_app_list_length (list) && i < N_TILES; i++) {
                app = gs_app_list_index (list, i);
                tile = gs_popular_tile_new (app);
                g_signal_connect (tile, "clicked",
                          G_CALLBACK (app_tile_clicked), self);
-               gtk_container_add (GTK_CONTAINER (priv->box_popular_rotating), tile);
+               gtk_container_add (GTK_CONTAINER (box), tile);
        }
 
        priv->empty = FALSE;
@@ -381,44 +393,75 @@ out:
        }
 }
 
+static const gchar *
+gs_shell_overview_get_category_label (const gchar *id)
+{
+       if (g_strcmp0 (id, "audio-video") == 0) {
+               /* TRANSLATORS: this is a heading for audio applications which
+                * have been featured ('recommended') by the distribution */
+               return _("Recommended Audio & Video Applications");
+       }
+       if (g_strcmp0 (id, "games") == 0) {
+               /* TRANSLATORS: this is a heading for games which have been
+                * featured ('recommended') by the distribution */
+               return _("Recommended Games");
+       }
+       if (g_strcmp0 (id, "graphics") == 0) {
+               /* TRANSLATORS: this is a heading for graphics applications
+                * which have been featured ('recommended') by the distribution */
+               return _("Recommended Graphics Applications");
+       }
+       if (g_strcmp0 (id, "productivity") == 0) {
+               /* TRANSLATORS: this is a heading for office applications which
+                * have been featured ('recommended') by the distribution */
+               return _("Recommended Productivity Applications");
+       }
+       return NULL;
+}
+
+static GPtrArray *
+gs_shell_overview_get_random_categories (void)
+{
+       GPtrArray *cats;
+       guint i;
+       g_autoptr(GDateTime) date = NULL;
+       g_autoptr(GRand) rand = NULL;
+       const gchar *ids[] = { "audio-video",
+                              "games",
+                              "graphics",
+                              "productivity",
+                              NULL };
+
+       date = g_date_time_new_now_utc ();
+       rand = g_rand_new_with_seed (g_date_time_get_day_of_year (date));
+       cats = g_ptr_array_new_with_free_func (g_free);
+       for (i = 0; ids[i] != NULL; i++)
+               g_ptr_array_add (cats, g_strdup (ids[i]));
+       for (i = 0; i < powl (cats->len + 1, 2); i++) {
+               gpointer tmp;
+               guint rnd1 = g_rand_int_range (rand, 0, cats->len);
+               guint rnd2 = g_rand_int_range (rand, 0, cats->len);
+               if (rnd1 == rnd2)
+                       continue;
+               tmp = cats->pdata[rnd1];
+               cats->pdata[rnd1] = cats->pdata[rnd2];
+               cats->pdata[rnd2] = tmp;
+       }
+       for (i = 0; i < cats->len; i++) {
+               const gchar *tmp = g_ptr_array_index (cats, i);
+               g_debug ("%i = %s", i + 1, tmp);
+       }
+       return cats;
+}
+
 static void
 gs_shell_overview_load (GsShellOverview *self)
 {
        GsShellOverviewPrivate *priv = gs_shell_overview_get_instance_private (self);
-       const gchar *category_of_day;
-       g_autoptr(GDateTime) date = NULL;
+       guint i;
 
        priv->empty = TRUE;
 
-       date = g_date_time_new_now_utc ();
-       switch (g_date_time_get_day_of_year (date) % 4) {
-       case 0:
-               category_of_day = "audio-video";
-               /* TRANSLATORS: this is a heading for audio applications which have been featured 
('recommended') by the distribution */
-               gtk_label_set_label (GTK_LABEL (priv->popular_rotating_heading), _("Recommended Audio & Video 
Applications"));
-               break;
-       case 1:
-               category_of_day = "games";
-               /* TRANSLATORS: this is a heading for games which have been featured ('recommended') by the 
distribution */
-               gtk_label_set_label (GTK_LABEL (priv->popular_rotating_heading), _("Recommended Games"));
-               break;
-       case 2:
-               category_of_day = "graphics";
-               /* TRANSLATORS: this is a heading for graphics applications which have been featured 
('recommended') by the distribution */
-               gtk_label_set_label (GTK_LABEL (priv->popular_rotating_heading), _("Recommended Graphics 
Applications"));
-               break;
-       case 3:
-               category_of_day = "productivity";
-               /* TRANSLATORS: this is a heading for office applications which have been featured 
('recommended') by the distribution */
-               gtk_label_set_label (GTK_LABEL (priv->popular_rotating_heading), _("Recommended Productivity 
Applications"));
-               break;
-       default:
-               g_assert_not_reached ();
-               break;
-       }
-       g_free (priv->category_of_day);
-       priv->category_of_day = g_strdup (category_of_day);
-
        if (!priv->loading_featured) {
                priv->loading_featured = TRUE;
                gs_plugin_loader_get_featured_async (priv->plugin_loader,
@@ -441,27 +484,40 @@ gs_shell_overview_load (GsShellOverview *self)
        }
 
        if (!priv->loading_popular_rotating) {
-               LoadData *load_data;
-               g_autoptr(GsCategory) category = NULL;
-               g_autoptr(GsCategory) featured_category = NULL;
-
-               category = gs_category_new (category_of_day);
-               featured_category = gs_category_new ("featured");
-               gs_category_add_child (category, featured_category);
-
-               load_data = g_slice_new0 (LoadData);
-               load_data->category = g_object_ref (category);
-               load_data->self = g_object_ref (self);
-
+               const guint MAX_CATS = 2;
+               g_autoptr(GPtrArray) cats_random = NULL;
+               cats_random = gs_shell_overview_get_random_categories ();
+
+               /* load all the categories */
+               for (i = 0; i < cats_random->len && i < MAX_CATS; i++) {
+                       LoadData *load_data;
+                       const gchar *cat_id = g_ptr_array_index (cats_random, 0);
+                       g_autoptr(GsCategory) category = NULL;
+                       g_autoptr(GsCategory) featured_category = NULL;
+
+                       cat_id = g_ptr_array_index (cats_random, i);
+                       if (i == 0) {
+                               g_free (priv->category_of_day);
+                               priv->category_of_day = g_strdup (cat_id);
+                       }
+                       category = gs_category_new (cat_id);
+                       featured_category = gs_category_new ("featured");
+                       gs_category_add_child (category, featured_category);
+
+                       load_data = g_slice_new0 (LoadData);
+                       load_data->category = g_object_ref (category);
+                       load_data->self = g_object_ref (self);
+                       load_data->title = gs_shell_overview_get_category_label (cat_id);
+                       gs_plugin_loader_get_category_apps_async (priv->plugin_loader,
+                                                                 featured_category,
+                                                                 
GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEW_RATINGS |
+                                                                 GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
+                                                                 priv->cancellable,
+                                                                 gs_shell_overview_get_category_apps_cb,
+                                                                 load_data);
+                       priv->refresh_count++;
+               }
                priv->loading_popular_rotating = TRUE;
-               gs_plugin_loader_get_category_apps_async (priv->plugin_loader,
-                                                         featured_category,
-                                                         GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEW_RATINGS |
-                                                         GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
-                                                         priv->cancellable,
-                                                         gs_shell_overview_get_category_apps_cb,
-                                                         load_data);
-               priv->refresh_count++;
        }
 
        if (!priv->loading_categories) {
@@ -562,9 +618,6 @@ gs_shell_overview_setup (GsShellOverview *self,
        for (i = 0; i < N_TILES; i++) {
                tile = gs_popular_tile_new (NULL);
                gtk_container_add (GTK_CONTAINER (priv->box_popular), tile);
-
-               tile = gs_popular_tile_new (NULL);
-               gtk_container_add (GTK_CONTAINER (priv->box_popular_rotating), tile);
        }
 
        /* handle category expander */
@@ -640,12 +693,10 @@ gs_shell_overview_class_init (GsShellOverviewClass *klass)
        gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, bin_featured);
        gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, box_overview);
        gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, box_popular);
-       gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, box_popular_rotating);
        gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, category_heading);
        gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, flowbox_categories);
        gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, flowbox_categories2);
        gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, popular_heading);
-       gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, 
popular_rotating_heading);
        gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, scrolledwindow_overview);
        gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, stack_overview);
        gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, 
categories_expander_button);
diff --git a/src/gs-shell-overview.ui b/src/gs-shell-overview.ui
index aa470bc..a9023a6 100644
--- a/src/gs-shell-overview.ui
+++ b/src/gs-shell-overview.ui
@@ -27,14 +27,12 @@
                     <property name="can_focus">False</property>
                     <property name="halign">center</property>
                     <property name="hexpand">False</property>
+                    <property name="border_width">12</property>
                     <property name="orientation">vertical</property>
                     <child>
                       <object class="GtkAlignment" id="bin_featured">
                         <property name="visible">True</property>
                         <property name="halign">fill</property>
-                        <property name="margin_start">12</property>
-                        <property name="margin_end">12</property>
-                        <property name="margin-top">12</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -51,8 +49,6 @@
                         <property name="label" translatable="yes">Categories</property>
                         <property name="margin-top">24</property>
                         <property name="margin-bottom">6</property>
-                        <property name="margin-start">12</property>
-                        <property name="margin-end">24</property>
                         <accessibility>
                           <relation target="flowbox_categories" type="label-for"/>
                         </accessibility>
@@ -70,8 +66,6 @@
                       <object class="GtkFlowBox" id="flowbox_categories">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="margin_start">9</property>
-                        <property name="margin_end">9</property>
                         <property name="margin-bottom">9</property>
                         <property name="row_spacing">6</property>
                         <property name="column_spacing">6</property>
@@ -96,8 +90,6 @@
                           <object class="GtkFlowBox" id="flowbox_categories2">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
-                            <property name="margin_start">12</property>
-                            <property name="margin_end">12</property>
                             <property name="margin-bottom">24</property>
                             <property name="row_spacing">8</property>
                             <property name="column_spacing">8</property>
@@ -196,8 +188,6 @@
                         <property name="label" translatable="yes" comments="Translators: This is a heading 
for software which has been featured (&apos;picked&apos;) by the distribution.">Editor's Picks</property>
                         <property name="margin-top">0</property>
                         <property name="margin-bottom">6</property>
-                        <property name="margin-start">12</property>
-                        <property name="margin-end">24</property>
                         <accessibility>
                           <relation target="box_popular" type="label-for"/>
                         </accessibility>
@@ -215,8 +205,6 @@
                       <object class="GsHidingBox" id="box_popular">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="margin_start">12</property>
-                        <property name="margin_end">12</property>
                         <property name="spacing">14</property>
                         <property name="valign">start</property>
                         <accessibility>
@@ -229,47 +217,6 @@
                         <property name="position">6</property>
                       </packing>
                     </child>
-                    <child>
-                      <object class="GtkLabel" id="popular_rotating_heading">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
-                        <property name="label" comments="Don&apos;t translate, this is just a 
placeholder">Recommended Games</property>
-                        <property name="margin-top">24</property>
-                        <property name="margin-bottom">6</property>
-                        <property name="margin-start">12</property>
-                        <property name="margin-end">24</property>
-                        <accessibility>
-                          <relation target="box_popular_rotating" type="label-for"/>
-                        </accessibility>
-                        <style>
-                          <class name="index-title-alignment-software"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">7</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GsHidingBox" id="box_popular_rotating">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="margin_start">12</property>
-                        <property name="margin_end">12</property>
-                        <property name="spacing">14</property>
-                        <property name="valign">start</property>
-                        <accessibility>
-                          <relation target="popular_rotating_heading" type="labelled-by"/>
-                        </accessibility>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">8</property>
-                      </packing>
-                    </child>
                   </object>
                 </child>
               </object>


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