[gnome-software] Break out category page as separate object



commit fab85436f563efea486403e23c9c890624686134
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Aug 26 15:43:13 2013 -0400

    Break out category page as separate object
    
    Introduce a GsShellCategory object, and move most of the
    category-related code from GsShellOverview there. At the
    same time, stop using a signal in GsShellCategory to communicate
    page changes - instead add API in GsShell to do it.

 src/Makefile.am         |    2 +
 src/gs-shell-category.c |  291 +++++++++++++++++++++++++++++++++++++++++++++++
 src/gs-shell-category.h |   64 ++++++++++
 src/gs-shell-overview.c |  207 +--------------------------------
 src/gs-shell-overview.h |    7 +-
 src/gs-shell.c          |   54 ++++-----
 src/gs-shell.h          |    4 +
 7 files changed, 393 insertions(+), 236 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 347a0bd..c99b1a5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,6 +40,8 @@ gnome_software_SOURCES =                              \
        gs-shell.h                                      \
        gs-shell-details.c                              \
        gs-shell-details.h                              \
+       gs-shell-category.c                             \
+       gs-shell-category.h                             \
        gs-shell-installed.c                            \
        gs-shell-installed.h                            \
        gs-shell-overview.c                             \
diff --git a/src/gs-shell-category.c b/src/gs-shell-category.c
new file mode 100644
index 0000000..b8effdc
--- /dev/null
+++ b/src/gs-shell-category.c
@@ -0,0 +1,291 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 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 category.
+ *
+ * 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 <string.h>
+#include <glib/gi18n.h>
+
+#include "gs-shell-category.h"
+
+static void    gs_shell_category_finalize      (GObject        *object);
+
+#define GS_SHELL_CATEGORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GS_TYPE_SHELL_CATEGORY, 
GsShellCategoryPrivate))
+
+struct GsShellCategoryPrivate
+{
+        GtkBuilder        *builder;
+        GsShell           *shell;
+       gchar             *category;
+};
+
+G_DEFINE_TYPE (GsShellCategory, gs_shell_category, G_TYPE_OBJECT)
+
+void
+gs_shell_category_refresh (GsShellCategory *shell)
+{
+       GsShellCategoryPrivate *priv = shell->priv;
+        GtkWidget *widget;
+
+        widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "application_details_header"));
+        gtk_label_set_label (GTK_LABEL (widget), priv->category);
+}
+
+static void
+container_remove_all (GtkContainer *container)
+{
+        GList *children, *l;
+        children = gtk_container_get_children (container);
+        for (l = children; l; l = l->next)
+                gtk_container_remove (container, GTK_WIDGET (l->data));
+        g_list_free (children);
+}
+
+static void
+app_tile_clicked (GtkButton *button, gpointer data)
+{
+        GsShellCategory *shell = GS_SHELL_CATEGORY (data);
+        GsApp *app;
+
+        app = g_object_get_data (G_OBJECT (button), "app");
+        gs_shell_show_details (shell->priv->shell, app);
+}
+
+static GtkWidget *
+create_app_tile (GsShellCategory *shell, GsApp *app)
+{
+        GtkWidget *button, *frame, *label;
+        GtkWidget *image, *grid;
+        const gchar *tmp;
+        PangoAttrList *attrs;
+
+        button = gtk_button_new ();
+        gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+        frame = gtk_frame_new (NULL);
+        gtk_container_add (GTK_CONTAINER (button), frame);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+        gtk_style_context_add_class (gtk_widget_get_style_context (frame), "view");
+        grid = gtk_grid_new ();
+        gtk_container_add (GTK_CONTAINER (frame), grid);
+        g_object_set (grid, "margin", 12, "row-spacing", 6, "column-spacing", 6, NULL);
+        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));
+        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);
+        pango_attr_list_unref (attrs);
+        g_object_set (label, "xalign", 0, NULL);
+        gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1);
+        tmp = gs_app_get_summary (app);
+        if (tmp != NULL && tmp[0] != '\0') {
+                label = gtk_label_new (tmp);
+                g_object_set (label, "xalign", 0, NULL);
+                gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
+                gtk_grid_attach (GTK_GRID (grid), label, 1, 1, 1, 1);
+        }
+
+        gtk_widget_show_all (button);
+
+        g_object_set_data_full (G_OBJECT (button), "app", g_object_ref (app), g_object_unref);
+        g_signal_connect (button, "clicked",
+                          G_CALLBACK (app_tile_clicked), shell);
+
+        return button;
+}
+
+static void
+gs_shell_category_populate_filtered (GsShellCategory *shell, const gchar *category, const gchar *filter)
+{
+        GsShellCategoryPrivate *priv = shell->priv;
+        gint i;
+        GtkWidget *tile;
+        GsApp *app;
+        GtkWidget *grid;
+
+        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);
+        if (filter == NULL) {
+                gtk_grid_remove_column (GTK_GRID (grid), 0);
+        }
+
+        /* FIXME load apps for this category and filter */
+        app = gs_app_new ("gnome-boxes");
+        gs_app_set_name (app, "Boxes");
+        gs_app_set_summary (app, "View and use virtual machines");
+        gs_app_set_url (app, "http://www.box.org";);
+        gs_app_set_kind (app, GS_APP_KIND_NORMAL);
+        gs_app_set_state (app, GS_APP_STATE_AVAILABLE);
+        gs_app_set_pixbuf (app, gdk_pixbuf_new_from_file 
("/usr/share/icons/hicolor/48x48/apps/gnome-boxes.png", NULL));
+
+        for (i = 0; i < 30; i++) {
+                tile = create_app_tile (shell, app);
+                if (filter) {
+                        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);
+                }
+        }
+
+        g_object_unref (app);
+}
+
+static void
+add_separator (GtkListBoxRow *row, GtkListBoxRow *before, gpointer data)
+{
+        if (!before) {
+                return;
+        }
+
+        gtk_list_box_row_set_header (row, gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
+}
+
+static void
+filter_selected (GtkListBox *filters, GtkListBoxRow *row, gpointer data)
+{
+        GsShellCategory *shell = GS_SHELL_CATEGORY (data);
+        const gchar *filter;
+        const gchar *category;
+
+        if (row == NULL)
+                return;
+
+        filter = gtk_label_get_label (GTK_LABEL (gtk_bin_get_child (GTK_BIN (row))));
+        category = (const gchar*)g_object_get_data (G_OBJECT (filters), "category");
+        gs_shell_category_populate_filtered (shell, category, filter);
+}
+
+static void
+create_filter_list (GsShellCategory *shell, const gchar *category, const gchar *filters[])
+{
+        GsShellCategoryPrivate *priv = shell->priv;
+        GtkWidget *grid;
+        GtkWidget *list;
+        GtkWidget *row;
+        GtkWidget *frame;
+        guint i;
+
+        grid = GTK_WIDGET (gtk_builder_get_object (priv->builder, "category_detail_grid"));
+        list = gtk_list_box_new ();
+        g_object_set_data (G_OBJECT (list), "category", (gpointer)category);
+        gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_BROWSE);
+        g_signal_connect (list, "row-selected", G_CALLBACK (filter_selected), shell);
+        gtk_list_box_set_header_func (GTK_LIST_BOX (list), add_separator, NULL, NULL);
+        for (i = 0; filters[i]; i++) {
+                row = gtk_label_new (filters[i]);
+                g_object_set (row, "xalign", 0.0, "margin", 6, NULL);
+                gtk_list_box_insert (GTK_LIST_BOX (list), row, i);
+        }
+        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);
+        gtk_widget_show_all (frame);
+        gtk_widget_set_valign (frame, GTK_ALIGN_START);
+        gtk_grid_attach (GTK_GRID (grid), frame, 0, 0, 1, 5);
+        gtk_list_box_select_row (GTK_LIST_BOX (list),
+                                 gtk_list_box_get_row_at_index (GTK_LIST_BOX (list), 0));
+}
+
+void
+gs_shell_category_set_category (GsShellCategory *shell, const gchar *category)
+{
+       GsShellCategoryPrivate *priv = shell->priv;
+        GtkWidget *grid;
+
+       g_free (priv->category);
+       priv->category = g_strdup (category);
+
+        grid = GTK_WIDGET (gtk_builder_get_object (priv->builder, "category_detail_grid"));
+        container_remove_all (GTK_CONTAINER (grid));
+
+        /* FIXME: get actual filters */
+        if (g_str_equal (category, "Games")) {
+                const gchar *filters[] = {
+                        "Popular", "Action", "Arcade", "Board",
+                        "Blocks", "Card", "Kids", "Logic", "Role Playing",
+                        "Shooter", "Simulation", "Sports", "Strategy",
+                        NULL
+                };
+                create_filter_list (shell, category, filters);
+        }
+        else if (g_str_equal (category, "Add-ons")) {
+                const gchar *filters[] = {
+                        "Popular", "Codecs", "Fonts",
+                        "Input Sources", "Language Packs",
+                        NULL
+                };
+                create_filter_list (shell, category, filters);
+        }
+        else {
+                gs_shell_category_populate_filtered (shell, category, NULL);
+        }
+}
+
+static void
+gs_shell_category_class_init (GsShellCategoryClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       object_class->finalize = gs_shell_category_finalize;
+
+       g_type_class_add_private (klass, sizeof (GsShellCategoryPrivate));
+}
+
+static void
+gs_shell_category_init (GsShellCategory *shell)
+{
+       shell->priv = GS_SHELL_CATEGORY_GET_PRIVATE (shell);
+}
+
+static void
+gs_shell_category_finalize (GObject *object)
+{
+       GsShellCategory *shell = GS_SHELL_CATEGORY (object);
+       GsShellCategoryPrivate *priv = shell->priv;
+
+       g_object_unref (priv->builder);
+        g_free (priv->category);
+
+       G_OBJECT_CLASS (gs_shell_category_parent_class)->finalize (object);
+}
+
+void
+gs_shell_category_setup (GsShellCategory *shell_category, GsShell *shell, GtkBuilder *builder)
+{
+       GsShellCategoryPrivate *priv = shell_category->priv;
+
+        priv->builder = g_object_ref (builder);
+        priv->shell = shell;
+}
+
+/**
+ * gs_shell_category_new:
+ **/
+GsShellCategory *
+gs_shell_category_new (void)
+{
+       GsShellCategory *shell;
+       shell = g_object_new (GS_TYPE_SHELL_CATEGORY, NULL);
+       return GS_SHELL_CATEGORY (shell);
+}
diff --git a/src/gs-shell-category.h b/src/gs-shell-category.h
new file mode 100644
index 0000000..e2ef8b7
--- /dev/null
+++ b/src/gs-shell-category.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 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 category.
+ *
+ * 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_SHELL_CATEGORY_H
+#define __GS_SHELL_CATEGORY_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gs-app.h"
+#include "gs-shell.h"
+#include "gs-plugin-loader.h"
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_SHELL_CATEGORY         (gs_shell_category_get_type ())
+#define GS_SHELL_CATEGORY(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GS_TYPE_SHELL_CATEGORY, 
GsShellCategory))
+#define GS_SHELL_CATEGORY_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GS_TYPE_SHELL_CATEGORY, 
GsShellCategoryClass))
+#define GS_IS_SHELL_CATEGORY(o)                (G_TYPE_CHECK_INSTANCE_TYPE ((o), GS_TYPE_SHELL_CATEGORY))
+#define GS_IS_SHELL_CATEGORY_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GS_TYPE_SHELL_CATEGORY))
+#define GS_SHELL_CATEGORY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GS_TYPE_SHELL_CATEGORY, 
GsShellCategoryClass))
+
+typedef struct GsShellCategoryPrivate GsShellCategoryPrivate;
+
+typedef struct
+{
+        GObject                         parent;
+        GsShellCategoryPrivate         *priv;
+} GsShellCategory;
+
+typedef struct
+{
+       GObjectClass                     parent_class;
+} GsShellCategoryClass;
+
+GType           gs_shell_category_get_type     (void);
+
+GsShellCategory        *gs_shell_category_new          (void);
+void            gs_shell_category_set_category (GsShellCategory *shell_category,
+                                                const gchar     *category);
+void            gs_shell_category_refresh      (GsShellCategory *shell_category);
+void             gs_shell_category_setup        (GsShellCategory *shell_category,
+                                                 GsShell         *shell,
+                                                 GtkBuilder      *builder);
+
+#endif /* __GS_SHELL_CATEGORY_H */
diff --git a/src/gs-shell-overview.c b/src/gs-shell-overview.c
index d7153e5..0fb0bfd 100644
--- a/src/gs-shell-overview.c
+++ b/src/gs-shell-overview.c
@@ -36,17 +36,11 @@ struct GsShellOverviewPrivate
        GtkBuilder              *builder;
        GCancellable            *cancellable;
        gboolean                 cache_valid;
-};
-
-enum {
-       SIGNAL_SET_OVERVIEW_MODE,
-       SIGNAL_LAST
+        GsShell                 *shell;
 };
 
 G_DEFINE_TYPE (GsShellOverview, gs_shell_overview, G_TYPE_OBJECT)
 
-static guint signals [SIGNAL_LAST] = { 0 };
-
 /**
  * gs_shell_overview_invalidate:
  **/
@@ -67,19 +61,13 @@ container_remove_all (GtkContainer *container)
 }
 
 static void
-gs_shell_overview_set_overview_mode (GsShellOverview *shell_overview, GsShellMode mode, GsApp *app, const 
gchar *category)
-{
-       g_signal_emit (shell_overview, signals[SIGNAL_SET_OVERVIEW_MODE], 0, mode, app, category);
-}
-
-static void
 app_tile_clicked (GtkButton *button, gpointer data)
 {
        GsShellOverview *shell_overview = GS_SHELL_OVERVIEW (data);
        GsApp *app;
 
        app = g_object_get_data (G_OBJECT (button), "app");
-       gs_shell_overview_set_overview_mode (shell_overview, GS_SHELL_MODE_DETAILS, app, NULL);
+        gs_shell_show_details (shell_overview->priv->shell, app);
 }
 
 static GtkWidget *
@@ -163,11 +151,10 @@ static void
 category_tile_clicked (GtkButton *button, gpointer data)
 {
        GsShellOverview *shell_overview = GS_SHELL_OVERVIEW (data);
-//     GsShellOverviewPrivate *priv = shell_overview->priv;
        const gchar *category;
 
        category = g_object_get_data (G_OBJECT (button), "category");
-       gs_shell_overview_set_overview_mode (shell_overview, GS_SHELL_MODE_CATEGORY, NULL, category);
+        gs_shell_show_category (shell_overview->priv->shell, category);
 }
 
 static GtkWidget *
@@ -192,183 +179,6 @@ create_category_tile (GsShellOverview *shell_overview, const gchar *category)
        return button;
 }
 
-static GtkWidget *
-create_app_tile (GsShellOverview *shell_overview, GsApp *app)
-{
-       GtkWidget *button, *frame, *label;
-       GtkWidget *image, *grid;
-       const gchar *tmp;
-       PangoAttrList *attrs;
-
-       button = gtk_button_new ();
-       gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
-       frame = gtk_frame_new (NULL);
-       gtk_container_add (GTK_CONTAINER (button), frame);
-       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-       gtk_style_context_add_class (gtk_widget_get_style_context (frame), "view");
-       grid = gtk_grid_new ();
-       gtk_container_add (GTK_CONTAINER (frame), grid);
-       g_object_set (grid, "margin", 12, "row-spacing", 6, "column-spacing", 6, NULL);
-       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));
-       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);
-       pango_attr_list_unref (attrs);
-       g_object_set (label, "xalign", 0, NULL);
-       gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1);
-       tmp = gs_app_get_summary (app);
-       if (tmp != NULL && tmp[0] != '\0') {
-               label = gtk_label_new (tmp);
-               g_object_set (label, "xalign", 0, NULL);
-               gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
-               gtk_grid_attach (GTK_GRID (grid), label, 1, 1, 1, 1);
-       }
-
-       gtk_widget_show_all (button);
-
-       g_object_set_data_full (G_OBJECT (button), "app", g_object_ref (app), g_object_unref);
-       g_signal_connect (button, "clicked",
-                         G_CALLBACK (app_tile_clicked), shell_overview);
-
-       return button;
-}
-
-static void
-gs_shell_overview_populate_filtered_category (GsShellOverview *shell_overview,
-                                   const gchar   *category,
-                                   const gchar   *filter)
-{
-       gint i;
-       GtkWidget *tile;
-       GsApp *app;
-       GtkWidget *grid;
-       GsShellOverviewPrivate *priv = shell_overview->priv;
-
-       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);
-       if (filter == NULL) {
-               gtk_grid_remove_column (GTK_GRID (grid), 0);
-       }
-
-       /* FIXME load apps for this category and filter */
-       app = gs_app_new ("gnome-boxes");
-       gs_app_set_name (app, "Boxes");
-       gs_app_set_summary (app, "View and use virtual machines");
-       gs_app_set_url (app, "http://www.box.org";);
-       gs_app_set_kind (app, GS_APP_KIND_NORMAL);
-       gs_app_set_state (app, GS_APP_STATE_AVAILABLE);
-       gs_app_set_pixbuf (app, gdk_pixbuf_new_from_file 
("/usr/share/icons/hicolor/48x48/apps/gnome-boxes.png", NULL));
-
-       for (i = 0; i < 30; i++) {
-               tile = create_app_tile (shell_overview, app);
-               if (filter) {
-                       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);
-               }
-       }
-
-       g_object_unref (app);
-}
-
-static void
-add_separator (GtkListBoxRow *row,
-              GtkListBoxRow *before,
-              gpointer       data)
-{
-       if (!before) {
-               return;
-       }
-
-       gtk_list_box_row_set_header (row, gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
-}
-
-static void
-filter_selected (GtkListBox    *filters,
-                GtkListBoxRow *row,
-                gpointer       data)
-{
-       GsShellOverview *shell_overview = GS_SHELL_OVERVIEW (data);
-       const gchar *filter;
-       const gchar *category;
-
-       if (row == NULL)
-               return;
-
-       filter = gtk_label_get_label (GTK_LABEL (gtk_bin_get_child (GTK_BIN (row))));
-       category = (const gchar*)g_object_get_data (G_OBJECT (filters), "category");
-       gs_shell_overview_populate_filtered_category (shell_overview, category, filter);
-}
-
-static void
-create_filter_list (GsShellOverview *shell_overview, const gchar *category, const gchar *filters[])
-{
-       GtkWidget *grid;
-       GtkWidget *list;
-       GtkWidget *row;
-       GtkWidget *frame;
-       guint i;
-       GsShellOverviewPrivate *priv = shell_overview->priv;
-
-       grid = GTK_WIDGET (gtk_builder_get_object (priv->builder, "category_detail_grid"));
-       list = gtk_list_box_new ();
-       g_object_set_data (G_OBJECT (list), "category", (gpointer)category);
-       gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_BROWSE);
-       g_signal_connect (list, "row-selected", G_CALLBACK (filter_selected), shell_overview);
-       gtk_list_box_set_header_func (GTK_LIST_BOX (list), add_separator, NULL, NULL);
-       for (i = 0; filters[i]; i++) {
-               row = gtk_label_new (filters[i]);
-               g_object_set (row, "xalign", 0.0, "margin", 6, NULL);
-               gtk_list_box_insert (GTK_LIST_BOX (list), row, i);
-       }
-       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);
-       gtk_widget_show_all (frame);
-       gtk_widget_set_valign (frame, GTK_ALIGN_START);
-       gtk_grid_attach (GTK_GRID (grid), frame, 0, 0, 1, 5);
-       gtk_list_box_select_row (GTK_LIST_BOX (list),
-                                gtk_list_box_get_row_at_index (GTK_LIST_BOX (list), 0));
-}
-
-void
-gs_shell_overview_set_category (GsShellOverview *shell_overview, const gchar *category)
-{
-       GtkWidget *grid;
-       GsShellOverviewPrivate *priv = shell_overview->priv;
-
-       grid = GTK_WIDGET (gtk_builder_get_object (priv->builder, "category_detail_grid"));
-       container_remove_all (GTK_CONTAINER (grid));
-
-       /* FIXME: get actual filters */
-       if (g_str_equal (category, "Games")) {
-               const gchar *filters[] = {
-                       "Popular", "Action", "Arcade", "Board",
-                       "Blocks", "Card", "Kids", "Logic", "Role Playing",
-                       "Shooter", "Simulation", "Sports", "Strategy",
-                       NULL
-               };
-               create_filter_list (shell_overview, category, filters);
-       }
-       else if (g_str_equal (category, "Add-ons")) {
-               const gchar *filters[] = {
-                       "Popular", "Codecs", "Fonts",
-                       "Input Sources", "Language Packs",
-                       NULL
-               };
-               create_filter_list (shell_overview, category, filters);
-       }
-       else {
-               gs_shell_overview_populate_filtered_category (shell_overview, category, NULL);
-       }
-}
-
 /**
  * gs_shell_overview_get_featured_cb:
  **/
@@ -481,6 +291,7 @@ gs_shell_overview_refresh (GsShellOverview *shell_overview)
  */
 void
 gs_shell_overview_setup (GsShellOverview *shell_overview,
+                         GsShell *shell,
                         GsPluginLoader *plugin_loader,
                         GtkBuilder *builder,
                         GCancellable *cancellable)
@@ -492,6 +303,9 @@ gs_shell_overview_setup (GsShellOverview *shell_overview,
        priv->plugin_loader = g_object_ref (plugin_loader);
        priv->builder = g_object_ref (builder);
        priv->cancellable = g_object_ref (cancellable);
+
+        /* avoid a ref cycle */
+        priv->shell = shell;
 }
 
 /**
@@ -503,13 +317,6 @@ gs_shell_overview_class_init (GsShellOverviewClass *klass)
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
        object_class->finalize = gs_shell_overview_finalize;
 
-       signals [SIGNAL_SET_OVERVIEW_MODE] =
-               g_signal_new ("set-overview-mode",
-                             G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (GsShellOverviewClass, set_overview_mode),
-                             NULL, NULL, g_cclosure_marshal_generic,
-                             G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_POINTER, G_TYPE_STRING);
-
        g_type_class_add_private (klass, sizeof (GsShellOverviewPrivate));
 }
 
diff --git a/src/gs-shell-overview.h b/src/gs-shell-overview.h
index 851ecae..e0c9522 100644
--- a/src/gs-shell-overview.h
+++ b/src/gs-shell-overview.h
@@ -25,6 +25,8 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
+#include "gs-app.h"
+#include "gs-shell.h"
 #include "gs-plugin-loader.h"
 
 G_BEGIN_DECLS
@@ -47,10 +49,6 @@ typedef struct
 typedef struct
 {
        GObjectClass             parent_class;
-       void                    (*set_overview_mode)    (GsShellOverview *shell_overview,
-                                                        GsShellMode     mode,
-                                                        GsApp          *app,
-                                                        const gchar    *cat);
 } GsShellOverviewClass;
 
 GType           gs_shell_overview_get_type     (void);
@@ -59,6 +57,7 @@ GsShellOverview       *gs_shell_overview_new          (void);
 void            gs_shell_overview_invalidate   (GsShellOverview        *shell_overview);
 void            gs_shell_overview_refresh      (GsShellOverview        *shell_overview);
 void            gs_shell_overview_setup        (GsShellOverview        *shell_overview,
+                                                 GsShell                *shell,
                                                 GsPluginLoader         *plugin_loader,
                                                 GtkBuilder             *builder,
                                                 GCancellable           *cancellable);
diff --git a/src/gs-shell.c b/src/gs-shell.c
index 408d570..e8af28a 100644
--- a/src/gs-shell.c
+++ b/src/gs-shell.c
@@ -29,6 +29,7 @@
 #include "gs-shell-installed.h"
 #include "gs-shell-overview.h"
 #include "gs-shell-updates.h"
+#include "gs-shell-category.h"
 
 static void    gs_shell_finalize       (GObject        *object);
 
@@ -44,6 +45,7 @@ struct GsShellPrivate
        GsShellOverview         *shell_overview;
        GsShellUpdates          *shell_updates;
        GsShellDetails          *shell_details;
+       GsShellCategory         *shell_category;
        GtkBuilder              *builder;
        guint                    tab_back_id;
 };
@@ -181,7 +183,6 @@ static void
 gs_shell_set_overview_mode (GsShell *shell, GsShellMode mode, GsApp *app, const gchar *category)
 {
        GsShellPrivate *priv = shell->priv;
-       GtkWidget *widget;
 
        if (priv->ignore_primary_buttons)
                return;
@@ -206,9 +207,8 @@ gs_shell_set_overview_mode (GsShell *shell, GsShellMode mode, GsApp *app, const
                gs_shell_details_refresh (priv->shell_details);
                break;
        case GS_SHELL_MODE_CATEGORY:
-               widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "application_details_header"));
-               gtk_label_set_label (GTK_LABEL (widget), category);
-               gs_shell_overview_set_category (priv->shell_overview, category);
+               gs_shell_category_set_category (priv->shell_category, category);
+               gs_shell_category_refresh (priv->shell_category);
                break;
        default:
                g_assert_not_reached ();
@@ -236,32 +236,6 @@ gs_shell_back_button_cb (GtkWidget *widget, GsShell *shell)
        gs_shell_set_overview_mode (shell, shell->priv->tab_back_id, NULL, NULL);
 }
 
-#if 0
-/**
- * gs_shell_refresh:
- **/
-void
-gs_shell_refresh (GsShell *shell, GCancellable *cancellable)
-{
-       GsShellPrivate *priv = shell->priv;
-
-}
-#endif
-
-/**
- * gs_shell_set_overview_mode_cb:
- **/
-static void
-gs_shell_set_overview_mode_cb (GsShellOverview *shell_overview,
-                              GsShellMode mode,
-                              GsApp *app,
-                              const gchar *cat,
-                              GsShell *shell)
-{
-       g_return_if_fail (GS_IS_SHELL (shell));
-       gs_shell_set_overview_mode (shell, mode, app, cat);
-}
-
 /**
  * gs_shell_setup:
  */
@@ -330,15 +304,17 @@ gs_shell_setup (GsShell *shell, GsPluginLoader *plugin_loader, GCancellable *can
                                  priv->builder,
                                  priv->cancellable);
        gs_shell_overview_setup (priv->shell_overview,
+                                 shell,
                                 priv->plugin_loader,
                                 priv->builder,
                                 priv->cancellable);
-       g_signal_connect (priv->shell_overview, "set-overview-mode",
-                         G_CALLBACK (gs_shell_set_overview_mode_cb), shell);
        gs_shell_details_setup (priv->shell_details,
                                priv->plugin_loader,
                                priv->builder,
                                priv->cancellable);
+       gs_shell_category_setup (priv->shell_category,
+                                 shell,
+                                priv->builder);
 
        /* show main UI */
         gs_shell_set_mode (shell, GS_SHELL_MODE_OVERVIEW);
@@ -355,6 +331,18 @@ gs_shell_set_mode (GsShell *shell, GsShellMode mode)
         gs_shell_set_overview_mode (shell, mode, NULL, NULL);
 }
 
+void
+gs_shell_show_details (GsShell *shell, GsApp *app)
+{
+        gs_shell_set_overview_mode (shell, GS_SHELL_MODE_DETAILS, app, NULL);
+}
+
+void
+gs_shell_show_category (GsShell *shell, const gchar *category)
+{
+        gs_shell_set_overview_mode (shell, GS_SHELL_MODE_CATEGORY, NULL, category);
+}
+
 /**
  * gs_shell_class_init:
  **/
@@ -378,6 +366,7 @@ gs_shell_init (GsShell *shell)
        shell->priv->shell_installed = gs_shell_installed_new ();
        shell->priv->shell_overview = gs_shell_overview_new ();
        shell->priv->shell_details = gs_shell_details_new ();
+       shell->priv->shell_category = gs_shell_category_new ();
        shell->priv->ignore_primary_buttons = FALSE;
 }
 
@@ -397,6 +386,7 @@ gs_shell_finalize (GObject *object)
        g_object_unref (priv->shell_updates);
        g_object_unref (priv->shell_installed);
        g_object_unref (priv->shell_details);
+       g_object_unref (priv->shell_overview);
 
        G_OBJECT_CLASS (gs_shell_parent_class)->finalize (object);
 }
diff --git a/src/gs-shell.h b/src/gs-shell.h
index 512aa1c..2a7f1e1 100644
--- a/src/gs-shell.h
+++ b/src/gs-shell.h
@@ -65,6 +65,10 @@ void          gs_shell_refresh               (GsShell        *shell,
                                                 GCancellable   *cancellable);
 void            gs_shell_set_mode              (GsShell        *shell,
                                                 GsShellMode     mode);
+void             gs_shell_show_details          (GsShell        *shell,
+                                                 GsApp          *app);
+void             gs_shell_show_category         (GsShell        *shell,
+                                                 const gchar    *category);
 GtkWindow      *gs_shell_setup                 (GsShell        *shell,
                                                 GsPluginLoader *plugin_loader,
                                                 GCancellable   *cancellable);


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