[gnome-software] Implement the sorting of apps in the category view
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Implement the sorting of apps in the category view
- Date: Fri, 8 Sep 2017 10:38:00 +0000 (UTC)
commit 65f03f6045524236d2eebbc2d52298e9189dc97c
Author: Joaquim Rocha <jrocha endlessm com>
Date: Thu Aug 10 22:42:18 2017 +0100
Implement the sorting of apps in the category view
This implementation follows the new designs and uses a popover
to select between sorting by rating or by name.
src/gs-category-page.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++
src/gs-category-page.ui | 89 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 188 insertions(+), 0 deletions(-)
---
diff --git a/src/gs-category-page.c b/src/gs-category-page.c
index fb3432d..3959027 100644
--- a/src/gs-category-page.c
+++ b/src/gs-category-page.c
@@ -23,11 +23,17 @@
#include "config.h"
#include <string.h>
+#include <glib/gi18n.h>
#include "gs-common.h"
#include "gs-summary-tile.h"
#include "gs-category-page.h"
+typedef enum {
+ SUBCATEGORY_SORT_TYPE_RATING,
+ SUBCATEGORY_SORT_TYPE_NAME
+} SubcategorySortType;
+
struct _GsCategoryPage
{
GsPage parent_instance;
@@ -38,6 +44,9 @@ struct _GsCategoryPage
GsShell *shell;
GsCategory *category;
GsCategory *subcategory;
+ guint sort_rating_handler_id;
+ guint sort_name_handler_id;
+ SubcategorySortType sort_type;
GtkWidget *infobar_category_shell_extensions;
GtkWidget *button_category_shell_extensions;
@@ -46,6 +55,9 @@ struct _GsCategoryPage
GtkWidget *subcats_filter_button_label;
GtkWidget *subcats_filter_button;
GtkWidget *popover_filter_box;
+ GtkWidget *subcats_sort_button_label;
+ GtkWidget *sort_rating_button;
+ GtkWidget *sort_name_button;
};
G_DEFINE_TYPE (GsCategoryPage, gs_category_page, GS_TYPE_PAGE)
@@ -72,6 +84,40 @@ app_tile_clicked (GsAppTile *tile, gpointer data)
}
static void
+gs_category_page_sort_by_type (GsCategoryPage *self,
+ SubcategorySortType sort_type)
+{
+ const gchar *button_label;
+
+ if (sort_type == SUBCATEGORY_SORT_TYPE_NAME)
+ /* TRANSLATORS: button text when apps have been sorted alphabetically */
+ button_label = _("Sorted by Name");
+ else
+ /* TRANSLATORS: button text when apps have been sorted by their rating */
+ button_label = _("Sorted by Rating");
+
+ gtk_label_set_text (GTK_LABEL (self->subcats_sort_button_label), button_label);
+
+ /* only sort again if the sort type is different */
+ if (self->sort_type == sort_type)
+ return;
+
+ self->sort_type = sort_type;
+ gtk_flow_box_invalidate_sort (GTK_FLOW_BOX (self->category_detail_box));
+}
+
+static void
+sort_button_clicked (GtkButton *button, gpointer data)
+{
+ GsCategoryPage *self = GS_CATEGORY_PAGE (data);
+
+ if (button == GTK_BUTTON (self->sort_rating_button))
+ gs_category_page_sort_by_type (self, SUBCATEGORY_SORT_TYPE_RATING);
+ else
+ gs_category_page_sort_by_type (self, SUBCATEGORY_SORT_TYPE_NAME);
+}
+
+static void
gs_category_page_get_apps_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
@@ -105,6 +151,15 @@ gs_category_page_get_apps_cb (GObject *source_object,
gtk_widget_set_can_focus (gtk_widget_get_parent (tile), FALSE);
}
+ self->sort_rating_handler_id = g_signal_connect (self->sort_rating_button,
+ "clicked",
+ G_CALLBACK (sort_button_clicked),
+ self);
+ self->sort_name_handler_id = g_signal_connect (self->sort_name_button,
+ "clicked",
+ G_CALLBACK (sort_button_clicked),
+ self);
+
/* seems a good place */
gs_shell_profile_dump (self->shell);
}
@@ -115,6 +170,31 @@ _max_results_sort_cb (GsApp *app1, GsApp *app2, gpointer user_data)
return gs_app_get_rating (app1) < gs_app_get_rating (app2);
}
+static gint
+gs_category_page_sort_flow_box_sort_func (GtkFlowBoxChild *child1,
+ GtkFlowBoxChild *child2,
+ gpointer data)
+{
+ GsApp *app1 = gs_app_tile_get_app (GS_APP_TILE (gtk_bin_get_child (GTK_BIN (child1))));
+ GsApp *app2 = gs_app_tile_get_app (GS_APP_TILE (gtk_bin_get_child (GTK_BIN (child2))));
+ SubcategorySortType sort_type;
+
+ if (!GS_IS_APP (app1) || !GS_IS_APP (app2))
+ return 0;
+
+ sort_type = GS_CATEGORY_PAGE (data)->sort_type;
+
+ if (sort_type == SUBCATEGORY_SORT_TYPE_RATING) {
+ gint rating_app1 = gs_app_get_rating (app1);
+ gint rating_app2 = gs_app_get_rating (app2);
+ if (rating_app1 > rating_app2)
+ return -1;
+ if (rating_app1 < rating_app2)
+ return 1;
+ }
+ return g_strcmp0 (gs_app_get_name (app1), gs_app_get_name (app2));
+}
+
static void
gs_category_page_reload (GsPage *page)
{
@@ -144,7 +224,19 @@ gs_category_page_reload (GsPage *page)
gtk_widget_set_visible (self->infobar_category_shell_extensions, FALSE);
}
+ if (self->sort_rating_handler_id > 0)
+ g_signal_handler_disconnect (self->sort_rating_button,
+ self->sort_rating_handler_id);
+
+ if (self->sort_name_handler_id > 0)
+ g_signal_handler_disconnect (self->sort_name_button,
+ self->sort_name_handler_id);
+
gs_container_remove_all (GTK_CONTAINER (self->category_detail_box));
+
+ /* just ensure the sort button has the correct label */
+ gs_category_page_sort_by_type (self, self->sort_type);
+
count = MIN(30, gs_category_get_size (self->subcategory));
for (i = 0; i < count; i++) {
tile = gs_summary_tile_new (NULL);
@@ -300,6 +392,10 @@ gs_category_page_setup (GsPage *page,
self->plugin_loader = g_object_ref (plugin_loader);
self->builder = g_object_ref (builder);
self->shell = shell;
+ self->sort_type = SUBCATEGORY_SORT_TYPE_RATING;
+ gtk_flow_box_set_sort_func (GTK_FLOW_BOX (self->category_detail_box),
+ gs_category_page_sort_flow_box_sort_func,
+ self, NULL);
adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->scrolledwindow_category));
gtk_container_set_focus_vadjustment (GTK_CONTAINER (self->category_detail_box), adj);
@@ -330,6 +426,9 @@ gs_category_page_class_init (GsCategoryPageClass *klass)
gtk_widget_class_bind_template_child (widget_class, GsCategoryPage, subcats_filter_button_label);
gtk_widget_class_bind_template_child (widget_class, GsCategoryPage, subcats_filter_button);
gtk_widget_class_bind_template_child (widget_class, GsCategoryPage, popover_filter_box);
+ gtk_widget_class_bind_template_child (widget_class, GsCategoryPage, subcats_sort_button_label);
+ gtk_widget_class_bind_template_child (widget_class, GsCategoryPage, sort_rating_button);
+ gtk_widget_class_bind_template_child (widget_class, GsCategoryPage, sort_name_button);
}
GsCategoryPage *
diff --git a/src/gs-category-page.ui b/src/gs-category-page.ui
index a45177f..59ff7a5 100644
--- a/src/gs-category-page.ui
+++ b/src/gs-category-page.ui
@@ -11,6 +11,28 @@
</object>
</child>
</object>
+ <object class="GtkPopover" id="sorting_popover">
+ <property name="position">bottom</property>
+ <child>
+ <object class="GtkBox" id="sorting_popover_box">
+ <property name="visible">True</property>
+ <property name="margin">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkModelButton" id="sort_rating_button">
+ <property name="visible">True</property>
+ <property name="text" translatable="yes" comments="Translators: A label for a button to sort
apps by their rating.">Top Rated</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkModelButton" id="sort_name_button">
+ <property name="visible">True</property>
+ <property name="text" translatable="yes" comments="Translators: A label for a button to sort
apps alphabetically.">Name</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
<template class="GsCategoryPage" parent="GsPage">
<child>
<object class="GtkBox" id="box_category">
@@ -165,6 +187,65 @@
<class name="text-button"/>
</style>
</object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack-type">start</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="subcats_sort_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">normal</property>
+ <property name="popover">sorting_popover</property>
+ <child internal-child="accessible">
+ <object class="AtkObject">
+ <property name="accessible-name" translatable="yes">Subcategories
sorting menu</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="spacing">6</property>
+ <property name="orientation">horizontal</property>
+ <child>
+ <object class="GtkLabel" id="subcats_sort_button_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0.0</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkArrow" id="arrow2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="arrow_type">down</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack-type">end</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack-type">end</property>
+ </packing>
</child>
</object>
</child>
@@ -210,4 +291,12 @@
<widget name="popover_filter_box"/>
</widgets>
</object>
+ <object class="GtkSizeGroup">
+ <property name="ignore-hidden">False</property>
+ <property name="mode">horizontal</property>
+ <widgets>
+ <widget name="subcats_sort_button_label"/>
+ <widget name="sorting_popover_box"/>
+ </widgets>
+ </object>
</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]