[gnome-software] Improve the category pages



commit 9d4149a67cb858e9f66ea76bde8d875545887045
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Sep 4 00:00:58 2013 -0400

    Improve the category pages
    
    Make it so that the filter list doesn't scroll with the
    content. To do so, we take the filter list out of the grid,
    and instead use a simple custom container which allocates
    its children with fixed relative sizes, to allocate the
    filter list and the content at a ratio of 1:2.

 src/Makefile.am         |    2 +
 src/gnome-software.ui   |   96 +++++++++-------
 src/gs-application.c    |    3 +
 src/gs-box.c            |  289 +++++++++++++++++++++++++++++++++++++++++++++++
 src/gs-box.h            |   48 ++++++++
 src/gs-shell-category.c |   58 ++++------
 6 files changed, 418 insertions(+), 78 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 4b74eab..f34b7e4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,6 +38,8 @@ gnome_software_SOURCES =                              \
        gs-category.h                                   \
        gs-app-widget.c                                 \
        gs-app-widget.h                                 \
+       gs-box.h                                        \
+       gs-box.c                                        \
        gs-plugin.c                                     \
        gs-plugin.h                                     \
        gs-shell.c                                      \
diff --git a/src/gnome-software.ui b/src/gnome-software.ui
index a026e90..65b133c 100644
--- a/src/gnome-software.ui
+++ b/src/gnome-software.ui
@@ -795,62 +795,70 @@ with multi-level undo.
               </object>
             </child>
             <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow_category">
+              <object class="GsBox" id="box_category">
                 <property name="visible">True</property>
-                <property name="shadow_type">none</property>
-                <property name="can_focus">False</property>
-                <property name="hscrollbar_policy">never</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <style>
-                  <class name="main-scrolled-software"/>
-                </style>
                 <child>
-                  <object class="GtkViewport" id="viewport3">
+                  <object class="GtkFrame" id="frame_filter">
+                    <property name="visible">True</property>
+                    <property name="margin-top">18</property>
+                    <property name="margin-bottom">18</property>
+                    <property name="margin-left">12</property>
+                    <property name="margin-right">12</property>
+                    <property name="shadow_type">in</property>
+                    <property name="halign">fill</property>
+                    <property name="valign">start</property>
+                    <style>
+                      <class name="view"/>
+                    </style>
+                    <child>
+                      <object class="GtkListBox" id="listbox_filter">
+                        <property name="visible">True</property>
+                        <property name="selection_mode">browse</property>
+                        <property name="halign">fill</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="relative_size">1.0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow_category">
                     <property name="visible">True</property>
+                    <property name="shadow_type">none</property>
                     <property name="can_focus">False</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <style>
+                      <class name="main-scrolled-software"/>
+                    </style>
                     <child>
-                      <object class="GtkGrid" id="category_detail_grid">
+                      <object class="GtkViewport" id="viewport3">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="margin_left">12</property>
-                        <property name="margin_right">12</property>
-                        <property name="margin_top">12</property>
-                        <property name="margin_bottom">12</property>
-                        <property name="row_spacing">12</property>
-                        <property name="column_spacing">12</property>
-                        <property name="row_homogeneous">True</property>
-                        <property name="column_homogeneous">True</property>
-                        <property name="hexpand">True</property>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
                         <child>
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <placeholder/>
+                          <object class="GtkGrid" id="category_detail_grid">
+                            <property name="margin_left">12</property>
+                            <property name="margin_right">12</property>
+                            <property name="margin_top">12</property>
+                            <property name="margin_bottom">12</property>
+                            <property name="halign">fill</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="row_spacing">12</property>
+                            <property name="column_spacing">12</property>
+                            <property name="row_homogeneous">True</property>
+                            <property name="column_homogeneous">True</property>
+                            <property name="hexpand">True</property>
+                            <property name="valign">start</property>
+                          </object>
                         </child>
                       </object>
                     </child>
                   </object>
+                  <packing>
+                    <property name="relative_size">2.0</property>
+                  </packing>
                 </child>
               </object>
             </child>
diff --git a/src/gs-application.c b/src/gs-application.c
index 885f2a6..4026f78 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -28,6 +28,7 @@
 #include <gtk/gtk.h>
 #include <packagekit-glib2/packagekit.h>
 
+#include "gs-box.h"
 #include "gs-shell.h"
 #include "gs-plugin-loader.h"
 
@@ -120,6 +121,8 @@ gs_application_startup (GApplication *application)
 
         G_APPLICATION_CLASS (gs_application_parent_class)->startup (application);
 
+        g_type_ensure (GS_TYPE_BOX);
+
         /* set up the app menu */
         g_action_map_add_action_entries (G_ACTION_MAP (app),
                                          actions, G_N_ELEMENTS (actions),
diff --git a/src/gs-box.c b/src/gs-box.c
new file mode 100644
index 0000000..2eb7199
--- /dev/null
+++ b/src/gs-box.c
@@ -0,0 +1,289 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012-2013 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gs-box.h"
+
+typedef struct {
+        GtkWidget       *widget;
+        gdouble          relative_size;
+} GsBoxChild;
+
+struct _GsBox {
+        GtkContainer parent;
+        GList *children;
+        gdouble total;
+};
+
+struct _GsBoxClass {
+        GtkContainerClass parent_class;
+};
+
+G_DEFINE_TYPE (GsBox, gs_box, GTK_TYPE_CONTAINER)
+
+enum {
+        CHILD_PROP_0,
+        CHILD_PROP_RELATIVE_SIZE
+};
+
+static void
+gs_box_real_add (GtkContainer *container, GtkWidget *widget)
+{
+        gs_box_add (GS_BOX (container), widget, 1.0);
+}
+
+static void
+gs_box_remove (GtkContainer *container, GtkWidget *widget)
+{
+        GsBox *box = GS_BOX (container);
+        GList *l;
+
+        for (l = box->children; l; l = l->next) {
+                GsBoxChild *child = l->data;
+                if (child->widget == widget) {
+                        gtk_widget_unparent (child->widget);
+                        box->children = g_list_delete_link (box->children, l);
+                        box->total -= child->relative_size;
+                        g_free (child);
+                        gtk_widget_queue_resize (GTK_WIDGET (container));
+                        break;
+                }
+        }
+}
+
+static void
+gs_box_forall (GtkContainer *container,
+               gboolean      include_internals,
+               GtkCallback   callback,
+               gpointer      callback_data)
+{
+        GsBox *box = GS_BOX (container);
+        GsBoxChild *child;
+        GList *children;
+
+        children = box->children;
+        while (children) {
+                child = children->data;
+                children = children->next;
+                (* callback) (child->widget, callback_data);
+        }
+}
+
+static void
+gs_box_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+        GsBox *box = GS_BOX (widget);
+        GsBoxChild *child;
+        GtkAllocation child_allocation;
+        gint x;
+        GList *l;
+        gboolean rtl;
+
+        rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
+
+        gtk_widget_set_allocation (widget, allocation);
+
+        x = allocation->x;
+        for (l = box->children; l; l = l->next) {
+                child = l->data;
+                child_allocation.x = x;
+                child_allocation.y = allocation->y;
+                child_allocation.width = allocation->width * (child->relative_size / box->total);
+                child_allocation.height = allocation->height;
+                if (rtl) {
+                        child_allocation.x = allocation->x + allocation->width - child_allocation.x - 
child_allocation.width;
+                }
+                gtk_widget_size_allocate (child->widget, &child_allocation);
+                x += child_allocation.width;
+        }
+}
+
+static void
+gs_box_get_preferred_width (GtkWidget *widget, gint *min, gint *nat)
+{
+        GsBox *box = GS_BOX (widget);
+        GsBoxChild *child;
+        gint cm, *cn;
+        gint n_children;
+        gint ms, m, n;
+        GList *l;
+        gint i;
+
+        n_children = g_list_length (box->children);
+
+        cn = g_new0 (gint, n_children);
+
+        ms = 0;
+        for (l = box->children, i = 0; l; l = l->next, i++) {
+                child = l->data;
+                gtk_widget_get_preferred_width (child->widget, &cm, cn + i);
+                ms = MAX (ms, cm / child->relative_size);
+        }
+
+        m = n = 0;
+        for (l = box->children, i = 0; l; l = l->next, i++) {
+                cm = ms * child->relative_size;
+                m += cm;
+                n += MAX (cn[i], cm);
+        }
+
+        g_free (cn);
+
+        if (min)
+                *min = m;
+        if (nat)
+                *nat = n;
+}
+
+static void
+gs_box_get_preferred_height (GtkWidget *widget, gint *min, gint *nat)
+{
+        GsBox *box = GS_BOX (widget);
+        gint m, n;
+        gint cm, cn;
+        GsBoxChild *child;
+        GList *l;
+
+        m = n = 0;
+        for (l = box->children; l; l = l->next) {
+                child = l->data;
+                gtk_widget_get_preferred_height (child->widget, &cm, &cn);
+                m = MAX (m, cm);
+                n = MAX (n, cn);
+        }
+        if (min)
+                *min = m;
+        if (nat)
+                *nat = n;
+}
+
+static void
+gs_box_get_child_property (GtkContainer *container,
+                           GtkWidget    *widget,
+                           guint         property_id,
+                           GValue       *value,
+                           GParamSpec   *pspec)
+{
+        GsBox *box = GS_BOX (container);
+        GList *l;
+        GsBoxChild *child;
+
+        child = NULL;
+        for (l = box->children; l; l = l->next) {
+                child = l->data;
+                if (child->widget == widget) {
+                        break;
+                }
+        }
+
+        switch (property_id) {
+        case CHILD_PROP_RELATIVE_SIZE:
+                g_value_set_double (value, child->relative_size);
+                break;
+        default:
+                GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
+        }
+}
+
+static void
+gs_box_set_child_property (GtkContainer *container,
+                           GtkWidget    *widget,
+                           guint         property_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
+{
+        GsBox *box = GS_BOX (container);
+        GList *l;
+        GsBoxChild *child;
+
+        child = NULL;
+        for (l = box->children; l; l = l->next) {
+                child = l->data;
+                if (child->widget == widget) {
+                        break;
+                }
+        }
+
+        switch (property_id) {
+        case CHILD_PROP_RELATIVE_SIZE:
+                box->total -= child->relative_size;
+                child->relative_size = g_value_get_double (value);
+                box->total += child->relative_size;
+                break;
+        default:
+                GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
+        }
+}
+
+static void
+gs_box_init (GsBox *box)
+{
+        gtk_widget_set_has_window (GTK_WIDGET (box), FALSE);
+}
+
+static void
+gs_box_class_init (GsBoxClass *class)
+{
+        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+        GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+
+        widget_class->size_allocate = gs_box_size_allocate;
+        widget_class->get_preferred_width = gs_box_get_preferred_width;
+        widget_class->get_preferred_height = gs_box_get_preferred_height;
+
+        container_class->add = gs_box_real_add;
+        container_class->remove = gs_box_remove;
+        container_class->forall = gs_box_forall;
+        container_class->get_child_property = gs_box_get_child_property;
+        container_class->set_child_property = gs_box_set_child_property;
+
+        gtk_container_class_install_child_property (container_class,
+                CHILD_PROP_RELATIVE_SIZE,
+                g_param_spec_double ("relative-size", NULL, NULL,
+                                     0.0, G_MAXDOUBLE, 1.0,
+                                     G_PARAM_READWRITE));
+}
+
+GtkWidget *
+gs_box_new (void)
+{
+        return g_object_new (GS_TYPE_BOX, NULL);
+}
+
+void
+gs_box_add (GsBox *box, GtkWidget *widget, gdouble relative_size)
+{
+        GsBoxChild *child;
+
+        child = g_new (GsBoxChild, 1);
+
+        child->widget = widget;
+        child->relative_size = relative_size;
+
+        box->total += relative_size;
+
+        box->children = g_list_append (box->children, child);
+        gtk_widget_set_parent (widget, GTK_WIDGET (box));
+}
diff --git a/src/gs-box.h b/src/gs-box.h
new file mode 100644
index 0000000..d318156
--- /dev/null
+++ b/src/gs-box.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef GS_BOX_H
+#define GS_BOX_H
+
+#include <gtk/gtk.h>
+
+#define GS_TYPE_BOX            (gs_box_get_type())
+#define GS_BOX(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GS_TYPE_BOX, GsBox))
+#define GS_BOX_CLASS(cls)      (G_TYPE_CHECK_CLASS_CAST((cls), GS_TYPE_BOX, GsBoxClass))
+#define GS_IS_BOX(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GS_TYPE_BOX))
+#define GS_IS_BOX_CLASS(cls)   (G_TYPE_CHECK_CLASS_TYPE((cls), GS_TYPE_BOX))
+#define GS_BOX_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GS_TYPE_BOX, GsBoxClass))
+
+G_BEGIN_DECLS
+
+typedef struct _GsBox          GsBox;
+typedef struct _GsBoxClass     GsBoxClass;
+
+GType           gs_box_get_type        (void);
+GtkWidget      *gs_box_new             (void);
+void             gs_box_add             (GsBox     *box,
+                                         GtkWidget *child,
+                                         gdouble    relative_size);
+
+G_END_DECLS
+
+#endif /* GS_BOX_H */
+
diff --git a/src/gs-shell-category.c b/src/gs-shell-category.c
index 8f9ce96..dbce924 100644
--- a/src/gs-shell-category.c
+++ b/src/gs-shell-category.c
@@ -33,8 +33,8 @@ struct GsShellCategoryPrivate {
        GCancellable      *cancellable;
         GsShell           *shell;
         GsCategory        *category;
+        GtkWidget         *col0_placeholder;
         GtkWidget         *col1_placeholder;
-        GtkWidget         *col2_placeholder;
 };
 
 G_DEFINE_TYPE (GsShellCategory, gs_shell_category, G_TYPE_OBJECT)
@@ -75,6 +75,7 @@ create_app_tile (GsShellCategory *shell, GsApp *app)
         PangoAttrList *attrs;
 
         button = gtk_button_new ();
+        gtk_widget_set_hexpand (button, TRUE);
         gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
         frame = gtk_frame_new (NULL);
         gtk_container_add (GTK_CONTAINER (button), frame);
@@ -86,6 +87,7 @@ create_app_tile (GsShellCategory *shell, GsApp *app)
         image = gtk_image_new_from_pixbuf (gs_app_get_pixbuf (app));
         gtk_grid_attach (GTK_GRID (grid), image, 0, 0, 1, 2);
         label = gtk_label_new (gs_app_get_name (app));
+        gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
         attrs = pango_attr_list_new ();
         pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
         gtk_label_set_attributes (GTK_LABEL (label), attrs);
@@ -138,20 +140,17 @@ gs_shell_category_get_apps_cb (GObject *source_object,
                goto out;
        }
         grid = GTK_WIDGET (gtk_builder_get_object (priv->builder, "category_detail_grid"));
-        gtk_grid_remove_column (GTK_GRID (grid), 2);
         gtk_grid_remove_column (GTK_GRID (grid), 1);
+        gtk_grid_remove_column (GTK_GRID (grid), 0);
 
         for (l = list, i = 0; l != NULL; l = l->next, i++) {
                 app = GS_APP (l->data);
                 tile = create_app_tile (shell, app);
-                if (gs_category_get_parent (priv->category) != NULL)
-                        gtk_grid_attach (GTK_GRID (grid), tile, 1 + (i % 2), i / 2, 1, 1);
-                else
-                        gtk_grid_attach (GTK_GRID (grid), tile, i % 3, i / 3, 1, 1);
+                gtk_grid_attach (GTK_GRID (grid), tile, (i % 2), i / 2, 1, 1);
         }
 
         if (i == 1)
-                gtk_grid_attach (GTK_GRID (grid), priv->col2_placeholder, 2, 0, 1, 1);
+                gtk_grid_attach (GTK_GRID (grid), priv->col1_placeholder, 1, 0, 1, 1);
 
 out:
        g_list_free (list);
@@ -178,15 +177,12 @@ gs_shell_category_populate_filtered (GsShellCategory *shell)
                          gs_category_get_id (priv->category));
         }
 
-        /* Remove old content. Be careful not to remove the
-         * subcategories and put placeholders there to keep
-         * the subcategory list from growing
-         */
         grid = GTK_WIDGET (gtk_builder_get_object (priv->builder, "category_detail_grid"));
-        gtk_grid_remove_column (GTK_GRID (grid), 2);
         gtk_grid_remove_column (GTK_GRID (grid), 1);
+        gtk_grid_remove_column (GTK_GRID (grid), 0);
+
+        gtk_grid_attach (GTK_GRID (grid), priv->col0_placeholder, 0, 0, 1, 1);
         gtk_grid_attach (GTK_GRID (grid), priv->col1_placeholder, 1, 0, 1, 1);
-        gtk_grid_attach (GTK_GRID (grid), priv->col2_placeholder, 2, 0, 1, 1);
 
         gs_plugin_loader_get_category_apps_async (priv->plugin_loader,
                                                   priv->category,
@@ -227,8 +223,6 @@ gs_shell_category_create_filter_list (GsShellCategory *shell, GsCategory *catego
         GtkWidget *grid;
         GtkWidget *list_box;
         GtkWidget *row;
-        GtkWidget *frame;
-        guint i;
         GList *list, *l;
         GsCategory *s;
 
@@ -239,32 +233,23 @@ gs_shell_category_create_filter_list (GsShellCategory *shell, GsCategory *catego
         if (!list)
                 return;
 
+        gtk_grid_attach (GTK_GRID (grid), priv->col0_placeholder, 0, 0, 1, 1);
         gtk_grid_attach (GTK_GRID (grid), priv->col1_placeholder, 1, 0, 1, 1);
-        gtk_grid_attach (GTK_GRID (grid), priv->col2_placeholder, 2, 0, 1, 1);
 
-        list_box = gtk_list_box_new ();
-        gtk_list_box_set_selection_mode (GTK_LIST_BOX (list_box), GTK_SELECTION_BROWSE);
-        g_signal_connect (list_box, "row-selected", G_CALLBACK (filter_selected), shell);
-        gtk_list_box_set_header_func (GTK_LIST_BOX (list_box), add_separator, NULL, NULL);
-        for  (l = list, i = 0; l; l = l->next, i++) {
+        list_box = GTK_WIDGET (gtk_builder_get_object (priv->builder, "listbox_filter"));
+        gs_container_remove_all (GTK_CONTAINER (list_box));
+
+        for  (l = list; l; l = l->next) {
                 s = l->data;
                 row = gtk_label_new (gs_category_get_name (s));
                 g_object_set_data_full (G_OBJECT (row), "category", g_object_ref (s), g_object_unref);
                 g_object_set (row, "xalign", 0.0, "margin", 6, NULL);
-                gtk_list_box_insert (GTK_LIST_BOX (list_box), row, i);
+                gtk_widget_show (row);
+                gtk_list_box_insert (GTK_LIST_BOX (list_box), row, -1);
                 if (subcategory == s)
                         gtk_list_box_select_row (GTK_LIST_BOX (list_box), GTK_LIST_BOX_ROW 
(gtk_widget_get_parent (row)));
         }
         g_list_free (list);
-
-        frame = gtk_frame_new (NULL);
-        g_object_set (frame, "margin", 6, NULL);
-        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-        gtk_style_context_add_class (gtk_widget_get_style_context (frame), "view");
-        gtk_container_add (GTK_CONTAINER (frame), list_box);
-        gtk_widget_show_all (frame);
-        gtk_widget_set_valign (frame, GTK_ALIGN_START);
-        gtk_grid_attach (GTK_GRID (grid), frame, 0, 0, 1, 20);
 }
 
 void
@@ -317,11 +302,11 @@ gs_shell_category_init (GsShellCategory *shell)
        priv = G_TYPE_INSTANCE_GET_PRIVATE (shell, GS_TYPE_SHELL_CATEGORY, GsShellCategoryPrivate);
         shell->priv = priv;
 
+        priv->col0_placeholder = g_object_ref_sink (gtk_label_new (""));
         priv->col1_placeholder = g_object_ref_sink (gtk_label_new (""));
-        priv->col2_placeholder = g_object_ref_sink (gtk_label_new (""));
 
+        gtk_widget_show (priv->col0_placeholder);
         gtk_widget_show (priv->col1_placeholder);
-        gtk_widget_show (priv->col2_placeholder);
 }
 
 static void
@@ -334,8 +319,8 @@ gs_shell_category_finalize (GObject *object)
         g_clear_object (&priv->category);
        g_clear_object (&priv->plugin_loader);
        g_clear_object (&priv->cancellable);
+        g_clear_object (&priv->col0_placeholder);
         g_clear_object (&priv->col1_placeholder);
-        g_clear_object (&priv->col2_placeholder);
 
        G_OBJECT_CLASS (gs_shell_category_parent_class)->finalize (object);
 }
@@ -358,11 +343,16 @@ gs_shell_category_setup (GsShellCategory *shell_category,
                          GCancellable *cancellable)
 {
        GsShellCategoryPrivate *priv = shell_category->priv;
+        GtkWidget *list_box;
 
        priv->plugin_loader = g_object_ref (plugin_loader);
         priv->builder = g_object_ref (builder);
        priv->cancellable = g_cancellable_new ();
         priv->shell = shell;
+
+        list_box = GTK_WIDGET (gtk_builder_get_object (priv->builder, "listbox_filter"));
+        g_signal_connect (list_box, "row-selected", G_CALLBACK (filter_selected), shell_category);
+        gtk_list_box_set_header_func (GTK_LIST_BOX (list_box), add_separator, NULL, NULL);
 }
 
 GsShellCategory *


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