[gnome-software] Add the initial framework to query plugins for category data



commit 98c0b21f296d39e629481f4ebd161d201ccb5647
Author: Richard Hughes <richard hughsie com>
Date:   Fri Aug 30 16:32:42 2013 +0100

    Add the initial framework to query plugins for category data
    
    This still needs wiring up to AppStream data, and some of the groups may have to
    be renamed or removed.

 src/gs-application.c                        |    1 +
 src/gs-plugin-loader.c                      |  287 +++++++++++++
 src/gs-plugin-loader.h                      |   16 +
 src/gs-plugin.h                             |   10 +
 src/gs-shell-overview.c                     |  106 ++---
 src/plugins/Makefile.am                     |    6 +
 src/plugins/gs-plugin-hardcoded-menu-spec.c |  597 +++++++++++++++++++++++++++
 src/plugins/gs-plugin-packagekit.c          |   31 ++
 8 files changed, 988 insertions(+), 66 deletions(-)
---
diff --git a/src/gs-application.c b/src/gs-application.c
index 474e4ce..ff3ada6 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -155,6 +155,7 @@ gs_application_startup (GApplication *application)
         gs_plugin_loader_set_enabled (app->plugin_loader, "hardcoded-popular", TRUE);
         gs_plugin_loader_set_enabled (app->plugin_loader, "hardcoded-ratings", TRUE);
         gs_plugin_loader_set_enabled (app->plugin_loader, "hardcoded-screenshots", TRUE);
+        gs_plugin_loader_set_enabled (app->plugin_loader, "hardcoded-menu-spec", TRUE);
         gs_plugin_loader_set_enabled (app->plugin_loader, "local-ratings", TRUE);
         gs_plugin_loader_set_enabled (app->plugin_loader, "packagekit", TRUE);
         gs_plugin_loader_set_enabled (app->plugin_loader, "packagekit-refine", TRUE);
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index b93c7e0..db4029e 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -946,6 +946,293 @@ gs_plugin_loader_search_finish (GsPluginLoader *plugin_loader,
 /******************************************************************************/
 
 /**
+ * gs_plugin_loader_category_sort_cb:
+ **/
+static gint
+gs_plugin_loader_category_sort_cb (gconstpointer a, gconstpointer b)
+{
+       return g_strcmp0 (gs_category_get_name (GS_CATEGORY (a)),
+                         gs_category_get_name (GS_CATEGORY (b)));
+}
+
+/**
+ * cd_plugin_loader_get_categories_thread_cb:
+ **/
+static void
+cd_plugin_loader_get_categories_thread_cb (GSimpleAsyncResult *res,
+                                          GObject *object,
+                                          GCancellable *cancellable)
+{
+       const gchar *function_name = "gs_plugin_add_categories";
+       gboolean ret = TRUE;
+       GError *error = NULL;
+       GsPluginLoaderAsyncState *state = (GsPluginLoaderAsyncState *) g_object_get_data (G_OBJECT 
(cancellable), "state");
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (object);
+       GsPlugin *plugin;
+       GsPluginResultsFunc plugin_func = NULL;
+       guint i;
+
+       /* run each plugin */
+       for (i = 0; i < plugin_loader->priv->plugins->len; i++) {
+               plugin = g_ptr_array_index (plugin_loader->priv->plugins, i);
+               if (!plugin->enabled)
+                       continue;
+               ret = g_cancellable_set_error_if_cancelled (cancellable, &error);
+               if (ret) {
+                       ret = FALSE;
+                       cd_plugin_loader_get_all_state_finish (state, error);
+                       g_error_free (error);
+                       goto out;
+               }
+               ret = g_module_symbol (plugin->module,
+                                      function_name,
+                                      (gpointer *) &plugin_func);
+               if (!ret)
+                       continue;
+               g_debug ("run %s on %s", function_name,
+                        g_module_name (plugin->module));
+               g_timer_start (plugin->timer);
+               ret = plugin_func (plugin, &state->list, cancellable, &error);
+               if (!ret) {
+                       cd_plugin_loader_get_all_state_finish (state, error);
+                       g_error_free (error);
+                       goto out;
+               }
+               gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
+               g_debug ("%s(%s) took %.0fms",
+                        plugin->name,
+                        function_name,
+                        g_timer_elapsed (plugin->timer, NULL) * 1000);
+       }
+
+       /* sort by name */
+       state->list = g_list_sort (state->list, gs_plugin_loader_category_sort_cb);
+
+       /* success */
+       if (state->list == NULL) {
+               g_set_error (&error,
+                            GS_PLUGIN_LOADER_ERROR,
+                            GS_PLUGIN_LOADER_ERROR_FAILED,
+                            "no categories to show");
+               cd_plugin_loader_get_all_state_finish (state, error);
+               g_error_free (error);
+               goto out;
+       }
+
+       /* success */
+       state->ret = TRUE;
+       cd_plugin_loader_get_all_state_finish (state, NULL);
+out:
+       return;
+}
+
+/**
+ * gs_plugin_loader_get_categories_async:
+ **/
+void
+gs_plugin_loader_get_categories_async (GsPluginLoader *plugin_loader,
+                                      GCancellable *cancellable,
+                                      GAsyncReadyCallback callback,
+                                      gpointer user_data)
+{
+       GCancellable *tmp;
+       GsPluginLoaderAsyncState *state;
+
+       g_return_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader));
+       g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+       /* save state */
+       state = g_slice_new0 (GsPluginLoaderAsyncState);
+       state->res = g_simple_async_result_new (G_OBJECT (plugin_loader),
+                                               callback,
+                                               user_data,
+                                               gs_plugin_loader_get_categories_async);
+       state->plugin_loader = g_object_ref (plugin_loader);
+       if (cancellable != NULL)
+               state->cancellable = g_object_ref (cancellable);
+
+       /* run in a thread */
+       tmp = g_cancellable_new ();
+       g_object_set_data (G_OBJECT (tmp), "state", state);
+       g_simple_async_result_run_in_thread (G_SIMPLE_ASYNC_RESULT (state->res),
+                                            cd_plugin_loader_get_categories_thread_cb,
+                                            0,
+                                            (GCancellable *) tmp);
+       g_object_unref (tmp);
+}
+
+/**
+ * gs_plugin_loader_get_categories_finish:
+ **/
+GList *
+gs_plugin_loader_get_categories_finish (GsPluginLoader *plugin_loader,
+                                       GAsyncResult *res,
+                                       GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader), NULL);
+       g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), NULL);
+       g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+       /* failed */
+       simple = G_SIMPLE_ASYNC_RESULT (res);
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
+
+       /* grab detail */
+       return g_list_copy (g_simple_async_result_get_op_res_gpointer (simple));
+}
+
+/******************************************************************************/
+
+/**
+ * cd_plugin_loader_get_category_apps_thread_cb:
+ **/
+static void
+cd_plugin_loader_get_category_apps_thread_cb (GSimpleAsyncResult *res,
+                                             GObject *object,
+                                             GCancellable *cancellable)
+{
+       const gchar *function_name = "gs_plugin_add_category_apps";
+       gboolean ret = TRUE;
+       GError *error = NULL;
+       GsPluginLoaderAsyncState *state = (GsPluginLoaderAsyncState *) g_object_get_data (G_OBJECT 
(cancellable), "state");
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (object);
+       GsPlugin *plugin;
+       GsPluginSearchFunc plugin_func = NULL;
+       guint i;
+
+       /* run each plugin */
+       for (i = 0; i < plugin_loader->priv->plugins->len; i++) {
+               plugin = g_ptr_array_index (plugin_loader->priv->plugins, i);
+               if (!plugin->enabled)
+                       continue;
+               ret = g_cancellable_set_error_if_cancelled (cancellable, &error);
+               if (ret) {
+                       ret = FALSE;
+                       cd_plugin_loader_get_all_state_finish (state, error);
+                       g_error_free (error);
+                       goto out;
+               }
+               ret = g_module_symbol (plugin->module,
+                                      function_name,
+                                      (gpointer *) &plugin_func);
+               if (!ret)
+                       continue;
+               g_debug ("run %s on %s", function_name,
+                        g_module_name (plugin->module));
+               g_timer_start (plugin->timer);
+               ret = plugin_func (plugin, state->value, &state->list, cancellable, &error);
+               if (!ret) {
+                       cd_plugin_loader_get_all_state_finish (state, error);
+                       g_error_free (error);
+                       goto out;
+               }
+               gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
+               g_debug ("%s(%s) took %.0fms",
+                        plugin->name,
+                        function_name,
+                        g_timer_elapsed (plugin->timer, NULL) * 1000);
+       }
+
+       /* dedupe applications we already know about */
+       gs_plugin_loader_list_dedupe (plugin_loader, state->list);
+
+       /* run refine() on each one */
+       ret = gs_plugin_loader_run_refine (plugin_loader,
+                                          state->list,
+                                          cancellable,
+                                          &error);
+       if (!ret) {
+               cd_plugin_loader_get_all_state_finish (state, error);
+               g_error_free (error);
+               goto out;
+       }
+
+       /* success */
+       state->list = gs_plugin_loader_remove_system (state->list);
+       state->list = gs_plugin_loader_remove_invalid (state->list);
+       if (state->list == NULL) {
+               g_set_error (&error,
+                            GS_PLUGIN_LOADER_ERROR,
+                            GS_PLUGIN_LOADER_ERROR_FAILED,
+                            "no get_category_apps results to show");
+               cd_plugin_loader_get_all_state_finish (state, error);
+               g_error_free (error);
+               goto out;
+       }
+
+       /* success */
+       state->ret = TRUE;
+       cd_plugin_loader_get_all_state_finish (state, NULL);
+out:
+       return;
+}
+
+/**
+ * gs_plugin_loader_get_category_apps_async:
+ **/
+void
+gs_plugin_loader_get_category_apps_async (GsPluginLoader *plugin_loader,
+                                      GsCategory *category,
+                                      GCancellable *cancellable,
+                                      GAsyncReadyCallback callback,
+                                      gpointer user_data)
+{
+       GCancellable *tmp;
+       GsPluginLoaderAsyncState *state;
+
+       g_return_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader));
+       g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+       /* save state */
+       state = g_slice_new0 (GsPluginLoaderAsyncState);
+       state->res = g_simple_async_result_new (G_OBJECT (plugin_loader),
+                                               callback,
+                                               user_data,
+                                               gs_plugin_loader_get_category_apps_async);
+       state->plugin_loader = g_object_ref (plugin_loader);
+       state->value = g_strdup (gs_category_get_id (category));
+       if (cancellable != NULL)
+               state->cancellable = g_object_ref (cancellable);
+
+       /* run in a thread */
+       tmp = g_cancellable_new ();
+       g_object_set_data (G_OBJECT (tmp), "state", state);
+       g_simple_async_result_run_in_thread (G_SIMPLE_ASYNC_RESULT (state->res),
+                                            cd_plugin_loader_get_category_apps_thread_cb,
+                                            0,
+                                            (GCancellable *) tmp);
+       g_object_unref (tmp);
+}
+
+/**
+ * gs_plugin_loader_get_category_apps_finish:
+ **/
+GList *
+gs_plugin_loader_get_category_apps_finish (GsPluginLoader *plugin_loader,
+                                       GAsyncResult *res,
+                                       GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader), NULL);
+       g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), NULL);
+       g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+       /* failed */
+       simple = G_SIMPLE_ASYNC_RESULT (res);
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
+
+       /* grab detail */
+       return g_list_copy (g_simple_async_result_get_op_res_gpointer (simple));
+}
+
+/******************************************************************************/
+
+/**
  * gs_plugin_loader_run_action:
  **/
 static gboolean
diff --git a/src/gs-plugin-loader.h b/src/gs-plugin-loader.h
index 27637d8..2e5828f 100644
--- a/src/gs-plugin-loader.h
+++ b/src/gs-plugin-loader.h
@@ -25,6 +25,7 @@
 #include <glib-object.h>
 
 #include "gs-app.h"
+#include "gs-category.h"
 #include "gs-plugin.h"
 
 G_BEGIN_DECLS
@@ -96,6 +97,21 @@ void          gs_plugin_loader_get_featured_async    (GsPluginLoader *plugin_loader,
 GList          *gs_plugin_loader_get_featured_finish   (GsPluginLoader *plugin_loader,
                                                         GAsyncResult   *res,
                                                         GError         **error);
+void            gs_plugin_loader_get_categories_async  (GsPluginLoader *plugin_loader,
+                                                        GCancellable   *cancellable,
+                                                        GAsyncReadyCallback callback,
+                                                        gpointer        user_data);
+GList          *gs_plugin_loader_get_categories_finish (GsPluginLoader *plugin_loader,
+                                                        GAsyncResult   *res,
+                                                        GError         **error);
+void            gs_plugin_loader_get_category_apps_async (GsPluginLoader       *plugin_loader,
+                                                        GsCategory     *category,
+                                                        GCancellable   *cancellable,
+                                                        GAsyncReadyCallback callback,
+                                                        gpointer        user_data);
+GList          *gs_plugin_loader_get_category_apps_finish (GsPluginLoader      *plugin_loader,
+                                                        GAsyncResult   *res,
+                                                        GError         **error);
 void            gs_plugin_loader_search_async          (GsPluginLoader *plugin_loader,
                                                         const gchar    *value,
                                                         GCancellable   *cancellable,
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index d45de2d..6fd56c6 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -28,6 +28,7 @@
 #include <gtk/gtk.h>
 
 #include "gs-app.h"
+#include "gs-category.h"
 
 G_BEGIN_DECLS
 
@@ -116,6 +117,15 @@ gboolean    gs_plugin_add_updates                  (GsPlugin       *plugin,
                                                         GList          **list,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
+gboolean        gs_plugin_add_categories               (GsPlugin       *plugin,
+                                                        GList          **list,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
+gboolean        gs_plugin_add_category_apps            (GsPlugin       *plugin,
+                                                        const gchar    *id,
+                                                        GList          **list,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 gboolean        gs_plugin_add_popular                  (GsPlugin       *plugin,
                                                         GList          **list,
                                                         GCancellable   *cancellable,
diff --git a/src/gs-shell-overview.c b/src/gs-shell-overview.c
index 9a986d0..31e0a45 100644
--- a/src/gs-shell-overview.c
+++ b/src/gs-shell-overview.c
@@ -237,60 +237,42 @@ out:
                 g_signal_emit (shell_overview, signals[SIGNAL_REFRESHED], 0);
 }
 
-static GList *
-gs_shell_overview_get_categories (GsShellOverview *shell_overview)
+/**
+ * gs_shell_overview_get_categories_cb:
+ **/
+static void
+gs_shell_overview_get_categories_cb (GObject *source_object,
+                                    GAsyncResult *res,
+                                    gpointer user_data)
 {
-        GsCategory *category;
-        GList *list = NULL;
-
-        category = gs_category_new (NULL, "add-ons", _("Add-ons"));
-        list = g_list_append (list, category);
-        gs_category_add_subcategory (category, gs_category_new (category, "codecs", _("Codecs")));
-        gs_category_add_subcategory (category, gs_category_new (category, "fonts", _("Fonts")));
-        gs_category_add_subcategory (category, gs_category_new (category, "inputs", _("Input Sources")));
-        gs_category_add_subcategory (category, gs_category_new (category, "languages", _("Language Packs")));
-        category = gs_category_new (NULL, "books", _("Books"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "business", _("Business & Finance"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "entertainment", _("Entertainment"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "education", _("Education"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "games", _("Games"));
-        list = g_list_append (list, category);
-        gs_category_add_subcategory (category, gs_category_new (category, "action", _("Action")));
-        gs_category_add_subcategory (category, gs_category_new (category, "arcade", _("Arcade")));
-        gs_category_add_subcategory (category, gs_category_new (category, "board", _("Board")));
-        gs_category_add_subcategory (category, gs_category_new (category, "blocks", _("Blocks")));
-        gs_category_add_subcategory (category, gs_category_new (category, "card", _("Card")));
-        gs_category_add_subcategory (category, gs_category_new (category, "kids", _("Kids")));
-        gs_category_add_subcategory (category, gs_category_new (category, "logic", _("Logic")));
-        gs_category_add_subcategory (category, gs_category_new (category, "role", _("Role Playing")));
-        gs_category_add_subcategory (category, gs_category_new (category, "shooter", _("Shooter")));
-        gs_category_add_subcategory (category, gs_category_new (category, "simulation", _("Simulation")));
-        gs_category_add_subcategory (category, gs_category_new (category, "sports", _("Sports")));
-        gs_category_add_subcategory (category, gs_category_new (category, "strategy", _("Strategy")));
-        category = gs_category_new (NULL, "lifestyle", _("Lifestyle"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "music", _("Music"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "navigation", _("Navigation"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "overviews", _("Overviews"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "photos", _("Photo & Video"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "productivity", _("Productivity"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "social", _("Social Networking"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "utility", _("Utility"));
-        list = g_list_append (list, category);
-        category = gs_category_new (NULL, "weather", _("Weather"));
-        list = g_list_append (list, category);
-
-        return list;
+       GError *error = NULL;
+       gint i;
+       GList *l;
+       GList *list;
+       GsCategory *cat;
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object);
+       GsShellOverview *shell_overview = GS_SHELL_OVERVIEW (user_data);
+       GsShellOverviewPrivate *priv = shell_overview->priv;
+       GtkWidget *grid;
+       GtkWidget *tile;
+
+       list = gs_plugin_loader_get_featured_finish (plugin_loader,
+                                                    res,
+                                                    &error);
+       if (list == NULL) {
+               g_warning ("failed to get categories: %s", error->message);
+               g_error_free (error);
+               goto out;
+       }
+       grid = GTK_WIDGET (gtk_builder_get_object (priv->builder, "grid_categories"));
+       for (l = list, i = 0; l; l = l->next, i++) {
+               cat = GS_CATEGORY (l->data);
+               tile = create_category_tile (shell_overview, cat);
+               gtk_grid_attach (GTK_GRID (grid), tile, i % 3, i / 3, 1, 1);
+       }
+        g_list_free_full (list, g_object_unref);
+out:
+       priv->cache_valid = TRUE;
 }
 
 /**
@@ -302,10 +284,6 @@ gs_shell_overview_refresh (GsShellOverview *shell_overview)
        GsShellOverviewPrivate *priv = shell_overview->priv;
        GtkWidget *widget;
        GtkWidget *grid;
-        GList *list, *l;
-        gint i;
-        GtkWidget *tile;
-        GsCategory *category;
 
         widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "buttonbox_main"));
         gtk_widget_show (widget);
@@ -338,15 +316,11 @@ gs_shell_overview_refresh (GsShellOverview *shell_overview)
        grid = GTK_WIDGET (gtk_builder_get_object (priv->builder, "grid_categories"));
        container_remove_all (GTK_CONTAINER (grid));
 
-        list = gs_shell_overview_get_categories (shell_overview);
-       for (l = list, i = 0; l; l = l->next, i++) {
-                category = l->data;
-               tile = create_category_tile (shell_overview, category);
-               gtk_grid_attach (GTK_GRID (grid), tile, i % 3, i / 3, 1, 1);
-       }
-        g_list_free_full (list, g_object_unref);
-
-       priv->cache_valid = TRUE;
+       /* get categories */
+       gs_plugin_loader_get_categories_async (priv->plugin_loader,
+                                              priv->cancellable,
+                                              gs_shell_overview_get_categories_cb,
+                                              shell_overview);
 }
 
 void
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 167a4e3..47da7a5 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -34,6 +34,7 @@ plugin_LTLIBRARIES =                                  \
        libgs_plugin_hardcoded-featured.la              \
        libgs_plugin_hardcoded-kind.la                  \
        libgs_plugin_hardcoded-popular.la               \
+       libgs_plugin_hardcoded-menu-spec.la             \
        libgs_plugin_hardcoded-ratings.la               \
        libgs_plugin_hardcoded-screenshots.la           \
        libgs_plugin_local-ratings.la                   \
@@ -55,6 +56,11 @@ libgs_plugin_hardcoded_popular_la_LIBADD = $(GS_PLUGIN_LIBS)
 libgs_plugin_hardcoded_popular_la_LDFLAGS = -module -avoid-version
 libgs_plugin_hardcoded_popular_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARNINGFLAGS_C)
 
+libgs_plugin_hardcoded_menu_spec_la_SOURCES = gs-plugin-hardcoded-menu-spec.c
+libgs_plugin_hardcoded_menu_spec_la_LIBADD = $(GS_PLUGIN_LIBS)
+libgs_plugin_hardcoded_menu_spec_la_LDFLAGS = -module -avoid-version
+libgs_plugin_hardcoded_menu_spec_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARNINGFLAGS_C)
+
 libgs_plugin_hardcoded_descriptions_la_SOURCES = gs-plugin-hardcoded-descriptions.c
 libgs_plugin_hardcoded_descriptions_la_LIBADD = $(GS_PLUGIN_LIBS)
 libgs_plugin_hardcoded_descriptions_la_LDFLAGS = -module -avoid-version
diff --git a/src/plugins/gs-plugin-hardcoded-menu-spec.c b/src/plugins/gs-plugin-hardcoded-menu-spec.c
new file mode 100644
index 0000000..8a8d15b
--- /dev/null
+++ b/src/plugins/gs-plugin-hardcoded-menu-spec.c
@@ -0,0 +1,597 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011-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 <gs-plugin.h>
+#include <glib/gi18n.h>
+
+/**
+ * gs_plugin_get_name:
+ */
+const gchar *
+gs_plugin_get_name (void)
+{
+       return "hardcoded-menu-spec";
+}
+
+/**
+ * gs_plugin_get_priority:
+ */
+gdouble
+gs_plugin_get_priority (GsPlugin *plugin)
+{
+       return 0.0f;
+}
+
+/**
+ * gs_plugin_add_categories:
+ */
+gboolean
+gs_plugin_add_categories (GsPlugin *plugin,
+                         GList **list,
+                         GCancellable *cancellable,
+                         GError **error)
+{
+       GsCategory *category;
+
+       /* Audio */
+       category = gs_category_new (NULL, "Audio", _("Audio"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "AudioVideoEditing",
+                                                               _("Editing")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Database",
+                                                               _("Databases")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "DiscBurning",
+                                                               _("Disc Burning")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "HamRadio",
+                                                               _("Ham Radio")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Midi",
+                                                               _("MIDI")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Mixer",
+                                                               _("Mixer")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Music",
+                                                               _("Music")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Player",
+                                                               _("Players")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Recorder",
+                                                               _("Recorders")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Sequencer",
+                                                               _("Sequencers")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Tuner",
+                                                               _("Tuners")));
+       *list = g_list_prepend (*list, category);
+
+       /* Development */
+       category = gs_category_new (NULL, "Development", _("Development Tools"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Building",
+                                                               _("Building")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Database",
+                                                               _("Databases")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Debugger",
+                                                               _("Debuggers")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "GUIDesigner",
+                                                               _("GUI Designers")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "IDE",
+                                                               _("IDE")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Profiling",
+                                                               _("Profiling")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ProjectManagement",
+                                                               _("Project Management")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "RevisionControl",
+                                                               _("Revision Control")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Translation",
+                                                               _("Translation")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "WebDevelopment",
+                                                               _("Web Development")));
+       *list = g_list_prepend (*list, category);
+
+       /* Education */
+       category = gs_category_new (NULL, "Education", _("Education"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Art",
+                                                               _("Art")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ArtificialIntelligence",
+                                                               _("Artificial Intelligence")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Astronomy",
+                                                               _("Astronomy")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Biology",
+                                                               _("Biology")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Chemistry",
+                                                               _("Chemistry")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ComputerScience",
+                                                               _("Computer Science")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Construction",
+                                                               _("Construction")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "DataVisualization",
+                                                               _("Data Visualization")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Economy",
+                                                               _("Economy")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Electricity",
+                                                               _("Electricity")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Electronics",
+                                                               _("Electronics")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Engineering",
+                                                               _("Engineering")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Geography",
+                                                               _("Geography")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Geology",
+                                                               _("Geology")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Geoscience",
+                                                               _("Geoscience")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "History",
+                                                               _("History")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Humanities",
+                                                               _("Humanities")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ImageProcessing",
+                                                               _("Image Processing")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Languages",
+                                                               _("Languages")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Literature",
+                                                               _("Literature")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Maps",
+                                                               _("Maps")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Math",
+                                                               _("Math")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "MedicalSoftware",
+                                                               _("Medical")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Music",
+                                                               _("Music")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "NumericalAnalysis",
+                                                               _("Numerical Analysis")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ParallelComputing",
+                                                               _("Parallel Computing")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Physics",
+                                                               _("Physics")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Robotics",
+                                                               _("Robotics")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Spirituality",
+                                                               _("Spirituality")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Sports",
+                                                               _("Sports")));
+       *list = g_list_prepend (*list, category);
+
+       /* Games */
+       category = gs_category_new (NULL, "Game", _("Games"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ActionGame",
+                                                               _("Action")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "AdventureGame",
+                                                               _("Adventure")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ArcadeGame",
+                                                               _("Arcade")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "BlocksGame",
+                                                               _("Blocks")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "BoardGame",
+                                                               _("Board")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "CardGame",
+                                                               _("Card")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Emulator",
+                                                               _("Emulators")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "KidsGame",
+                                                               _("Kids")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "LogicGame",
+                                                               _("Logic")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "RolePlaying",
+                                                               _("Role Playing")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Shooter",
+                                                               _("Shooter")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Simulation",
+                                                               _("Simulation")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "SportsGame",
+                                                               _("Sports")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "StrategyGame",
+                                                               _("Strategy")));
+       *list = g_list_prepend (*list, category);
+
+       /* Graphics */
+       category = gs_category_new (NULL, "Graphics", _("Graphics"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "2DGraphics",
+                                                               _("2D Graphics")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "3DGraphics",
+                                                               _("3D Graphics")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "OCR",
+                                                               _("OCR")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Photography",
+                                                               _("Photography")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Publishing",
+                                                               _("Publishing")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "RasterGraphics",
+                                                               _("Raster Graphics")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Scanning",
+                                                               _("Scanning")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "VectorGraphics",
+                                                               _("Vector Graphics")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Viewer",
+                                                               _("Viewer")));
+       *list = g_list_prepend (*list, category);
+
+       /* Network */
+       category = gs_category_new (NULL, "Network", _("Network"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Chat",
+                                                               _("Chat")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Dialup",
+                                                               _("Dialup")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Email",
+                                                               _("Email")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Feed",
+                                                               _("Feed")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "FileTransfer",
+                                                               _("File Transfer")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "HamRadio",
+                                                               _("Ham Radio")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "InstantMessaging",
+                                                               _("Instant Messaging")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "IRCClient",
+                                                               _("IRC Clients")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Monitor",
+                                                               _("Monitor")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "News",
+                                                               _("News")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "P2P",
+                                                               _("P2P")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "RemoteAccess",
+                                                               _("Remote Access")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Telephony",
+                                                               _("Telephony")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "VideoConference",
+                                                               _("Video Conference")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "WebBrowser",
+                                                               _("Web Browser")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "WebDevelopment",
+                                                               _("Web Development")));
+       *list = g_list_prepend (*list, category);
+
+       /* Office */
+       category = gs_category_new (NULL, "Office", _("Office"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Calendar",
+                                                               _("Calendar")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Chart",
+                                                               _("Chart")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ContactManagement",
+                                                               _("Contact Management")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Database",
+                                                               _("Database")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Dictionary",
+                                                               _("Dictionary")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Email",
+                                                               _("Email")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Finance",
+                                                               _("Finance")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "FlowChart",
+                                                               _("Flow Chart")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "PDA",
+                                                               _("PDA")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Photography",
+                                                               _("Photography")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Presentation",
+                                                               _("Presentation")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ProjectManagement",
+                                                               _("Project Management")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Publishing",
+                                                               _("Publishing")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Spreadsheet",
+                                                               _("Spreadsheet")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Viewer",
+                                                               _("Viewer")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "WordProcessor",
+                                                               _("Word Processor")));
+       *list = g_list_prepend (*list, category);
+
+       /* Science */
+       category = gs_category_new (NULL, "Science", _("Science"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Art",
+                                                               _("Art")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ArtificialIntelligence",
+                                                               _("Artificial Intelligence")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Astronomy",
+                                                               _("Astronomy")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Biology",
+                                                               _("Biology")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Chemistry",
+                                                               _("Chemistry")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ComputerScience",
+                                                               _("Computer Science")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Construction",
+                                                               _("Construction")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "DataVisualization",
+                                                               _("DataVisualization")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Economy",
+                                                               _("Economy")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Electricity",
+                                                               _("Electricity")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Electronics",
+                                                               _("Electronics")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Engineering",
+                                                               _("Engineering")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Geography",
+                                                               _("Geography")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Geology",
+                                                               _("Geology")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Geoscience",
+                                                               _("Geoscience")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "History",
+                                                               _("History")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Humanities",
+                                                               _("Humanities")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ImageProcessing",
+                                                               _("Image Processing")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Languages",
+                                                               _("Languages")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Literature",
+                                                               _("Literature")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Maps",
+                                                               _("Maps")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Math",
+                                                               _("Math")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "MedicalSoftware",
+                                                               _("Medical Software")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "NumericalAnalysis",
+                                                               _("Numerical Analysis")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "ParallelComputing",
+                                                               _("Parallel Computing")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Physics",
+                                                               _("Physics")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Robotics",
+                                                               _("Robotics")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Spirituality",
+                                                               _("Spirituality")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Sports",
+                                                               _("Sports")));
+       *list = g_list_prepend (*list, category);
+
+       /* Settings */
+       category = gs_category_new (NULL, "Settings", _("Settings"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Accessibility",
+                                                               _("Accessibility")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "DesktopSettings",
+                                                               _("Desktop Settings")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "HardwareSettings",
+                                                               _("Hardware Settings")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "PackageManager",
+                                                               _("Package Manager")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Printing",
+                                                               _("Printing")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Security",
+                                                               _("Security")));
+       *list = g_list_prepend (*list, category);
+
+       /* System */
+       category = gs_category_new (NULL, "System", _("System"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Emulator",
+                                                               _("Emulator")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "FileManager",
+                                                               _("File Manager")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Filesystem",
+                                                               _("Filesystem")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "FileTools",
+                                                               _("File Tools")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Monitor",
+                                                               _("Monitor")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Security",
+                                                               _("Security")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "TerminalEmulator",
+                                                               _("Terminal Emulator")));
+       *list = g_list_prepend (*list, category);
+
+       /* Utility */
+       category = gs_category_new (NULL, "Utility", _("Utility"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Accessibility",
+                                                               _("Accessibility")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Archiving",
+                                                               _("Archiving")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Calculator",
+                                                               _("Calculator")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Clock",
+                                                               _("Clock")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Compression",
+                                                               _("Compression")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "FileTools",
+                                                               _("File Tools")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Maps",
+                                                               _("Maps")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Spirituality",
+                                                               _("Spirituality")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "TelephonyTools",
+                                                               _("Telephony Tools")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "TextEditor",
+                                                               _("Text Editor")));
+       *list = g_list_prepend (*list, category);
+
+       /* Video */
+       category = gs_category_new (NULL, "Video", _("Video"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "AudioVideoEditing",
+                                                               _("Editing")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Database",
+                                                               _("Database")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "DiscBurning",
+                                                               _("Disc Burning")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Player",
+                                                               _("Players")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "Recorder",
+                                                               _("Recorders")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "TV",
+                                                               _("TV")));
+       *list = g_list_prepend (*list, category);
+
+       return TRUE;
+}
diff --git a/src/plugins/gs-plugin-packagekit.c b/src/plugins/gs-plugin-packagekit.c
index 6a71552..34a2716 100644
--- a/src/plugins/gs-plugin-packagekit.c
+++ b/src/plugins/gs-plugin-packagekit.c
@@ -23,6 +23,7 @@
 
 #define I_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE
 #include <packagekit-glib2/packagekit.h>
+#include <glib/gi18n.h>
 
 #include <gs-plugin.h>
 
@@ -549,3 +550,33 @@ out:
                g_object_unref (results);
        return ret;
 }
+
+/**
+ * gs_plugin_add_categories:
+ */
+gboolean
+gs_plugin_add_categories (GsPlugin *plugin,
+                         GList **list,
+                         GCancellable *cancellable,
+                         GError **error)
+{
+       GsCategory *category;
+
+       /* Add Ons */
+       category = gs_category_new (NULL, "PK::add-ons", _("Add-ons"));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "PK::codecs",
+                                                               _("Codecs")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "PK::fonts",
+                                                               _("Fonts")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "PK::inputs",
+                                                               _("Input Sources")));
+       gs_category_add_subcategory (category, gs_category_new (category,
+                                                               "PK::languages",
+                                                               _("Language Packs")));
+       *list = g_list_prepend (*list, category);
+
+       return TRUE;
+}



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