[gnome-software/wip/kalev/modulesets-rework: 6/7] Add a separate "featured" section to modulesets



commit abb58d4850b8875a0072b1eec23c89d7b48e3f29
Author: Kalev Lember <kalevlember gmail com>
Date:   Mon Mar 16 17:31:29 2015 +0100

    Add a separate "featured" section to modulesets
    
    ... and implement its parsing in the moduleset plugin.

 data/modulesets/default.xml       |    6 +-
 data/modulesets/gnome.xml         |    8 +-
 src/gs-category.c                 |   10 ++
 src/gs-category.h                 |    2 +
 src/gs-cmd.c                      |    2 -
 src/gs-plugin-loader-sync.c       |    4 -
 src/gs-plugin-loader-sync.h       |    2 -
 src/gs-plugin-loader.c            |  136 +-----------------------------
 src/gs-plugin-loader.h            |    2 -
 src/gs-plugin.h                   |    8 --
 src/gs-shell-overview.c           |   47 ++++++++---
 src/plugins/gs-moduleset.c        |  108 +++++++++++++++++++++++-
 src/plugins/gs-moduleset.h        |    8 ++
 src/plugins/gs-plugin-dummy.c     |    2 -
 src/plugins/gs-plugin-moduleset.c |  169 ++++++++++++++++++++++++++++++-------
 15 files changed, 310 insertions(+), 204 deletions(-)
---
diff --git a/data/modulesets/default.xml b/data/modulesets/default.xml
index 376ea51..51fee30 100644
--- a/data/modulesets/default.xml
+++ b/data/modulesets/default.xml
@@ -1,5 +1,5 @@
+<!-- Apps for the "Editor's Picks" list -->
 <moduleset name="popular">
-  <!-- Apps for the "Editor's Picks" list -->
   <module type="application">calibre-gui.desktop</module>
   <module type="application">gnucash.desktop</module>
   <module type="application">gtg.desktop</module>
@@ -11,8 +11,10 @@
   <module type="application">simple-scan.desktop</module>
   <module type="application">stellarium.desktop</module>
   <module type="application">transmission-gtk.desktop</module>
+</moduleset>
 
-  <!-- Apps that show up as featured in their respective categories -->
+<!-- Apps that show up as featured in their respective categories -->
+<moduleset name="featured">
   <module type="application" category="Audio">ardour2.desktop</module>
   <module type="application" category="Audio">audacity.desktop</module>
   <module type="application" category="Audio">rosegarden.desktop</module>
diff --git a/data/modulesets/gnome.xml b/data/modulesets/gnome.xml
index b7f8563..507293c 100644
--- a/data/modulesets/gnome.xml
+++ b/data/modulesets/gnome.xml
@@ -3,14 +3,16 @@
   <module type="pkgname">gtk3</module>
 </moduleset>
 
+<!-- Apps for the "Editor's Picks" list -->
 <moduleset name="popular">
-  <!-- Apps for the "Editor's Picks" list -->
   <module type="application">bijiben.desktop</module>
   <module type="application">geary.desktop</module>
   <module type="application">org.gnome.Maps.desktop</module>
   <module type="application">pdfmod.desktop</module>
+</moduleset>
 
-  <!-- Apps that show up as featured in their respective categories -->
+<!-- Apps that show up as featured in their respective categories -->
+<moduleset name="featured">
   <module type="application" category="Audio">banshee.desktop</module>
   <module type="application" category="Audio">brasero.desktop</module>
   <module type="application" category="Audio">rhythmbox.desktop</module>
@@ -51,8 +53,8 @@
   <module type="application" category="Video">org.gnome.Totem.desktop</module>
 </moduleset>
 
+<!-- Unremovable system apps -->
 <moduleset name="system">
-  <!-- Unremovable system apps -->
   <module type="application">empathy.desktop</module>
   <module type="application">eog.desktop</module>
   <module type="application">epiphany.desktop</module>
diff --git a/src/gs-category.c b/src/gs-category.c
index 2c96b25..4ccade1 100644
--- a/src/gs-category.c
+++ b/src/gs-category.c
@@ -55,6 +55,16 @@ gs_category_get_size (GsCategory *category)
 }
 
 /**
+ * gs_category_set_size:
+ **/
+void
+gs_category_set_size (GsCategory *category, guint size)
+{
+       g_return_val_if_fail (GS_IS_CATEGORY (category), 0);
+       category->priv->size = size;
+}
+
+/**
  * gs_category_increment_size:
  *
  * Adds one to the size count if an application is available
diff --git a/src/gs-category.h b/src/gs-category.h
index ae3b06e..1990d3a 100644
--- a/src/gs-category.h
+++ b/src/gs-category.h
@@ -62,6 +62,8 @@ GList         *gs_category_get_subcategories  (GsCategory     *category);
 void            gs_category_add_subcategory    (GsCategory     *category,
                                                 GsCategory     *subcategory);
 guint           gs_category_get_size           (GsCategory     *category);
+void            gs_category_set_size           (GsCategory     *category,
+                                                guint           size);
 void            gs_category_increment_size     (GsCategory     *category);
 
 G_END_DECLS
diff --git a/src/gs-cmd.c b/src/gs-cmd.c
index c810d21..931b6e7 100644
--- a/src/gs-cmd.c
+++ b/src/gs-cmd.c
@@ -318,8 +318,6 @@ main (int argc, char **argv)
                        list = gs_plugin_loader_get_popular (plugin_loader,
                                                             refine_flags,
                                                             NULL,
-                                                            NULL,
-                                                            NULL,
                                                             &error);
                        if (list == NULL) {
                                ret = FALSE;
diff --git a/src/gs-plugin-loader-sync.c b/src/gs-plugin-loader-sync.c
index 94c085c..462a2ba 100644
--- a/src/gs-plugin-loader-sync.c
+++ b/src/gs-plugin-loader-sync.c
@@ -254,8 +254,6 @@ gs_plugin_loader_get_popular_finish_sync (GsPluginLoader *plugin_loader,
 GList *
 gs_plugin_loader_get_popular (GsPluginLoader *plugin_loader,
                              GsPluginRefineFlags flags,
-                             const gchar *category,
-                             const gchar *category_exclude,
                              GCancellable *cancellable,
                              GError **error)
 {
@@ -271,8 +269,6 @@ gs_plugin_loader_get_popular (GsPluginLoader *plugin_loader,
        /* run async method */
        gs_plugin_loader_get_popular_async (plugin_loader,
                                            flags,
-                                           category,
-                                           category_exclude,
                                            cancellable,
                                            (GAsyncReadyCallback) gs_plugin_loader_get_popular_finish_sync,
                                            &helper);
diff --git a/src/gs-plugin-loader-sync.h b/src/gs-plugin-loader-sync.h
index 33771db..c600545 100644
--- a/src/gs-plugin-loader-sync.h
+++ b/src/gs-plugin-loader-sync.h
@@ -47,8 +47,6 @@ GList         *gs_plugin_loader_get_sources           (GsPluginLoader *plugin_loader,
                                                         GError         **error);
 GList          *gs_plugin_loader_get_popular           (GsPluginLoader *plugin_loader,
                                                         GsPluginRefineFlags flags,
-                                                        const gchar    *category,
-                                                        const gchar    *category_exclude,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
 GList          *gs_plugin_loader_get_featured          (GsPluginLoader *plugin_loader,
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index 813821d..6c30cd4 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -444,130 +444,6 @@ out:
 }
 
 /**
- * gs_plugin_loader_run_popular_plugin:
- **/
-static gboolean
-gs_plugin_loader_run_popular_plugin (GsPluginLoader *plugin_loader,
-                                    GsPlugin *plugin,
-                                    const gchar *function_name,
-                                    GList **list,
-                                    const gchar *category,
-                                    const gchar *category_exclude,
-                                    GCancellable *cancellable,
-                                    GError **error)
-{
-       GsPluginPopularFunc plugin_func = NULL;
-       gboolean exists;
-       gboolean ret = TRUE;
-       _cleanup_free_ gchar *profile_id = NULL;
-
-       /* get symbol */
-       exists = g_module_symbol (plugin->module,
-                                 function_name,
-                                 (gpointer *) &plugin_func);
-       if (!exists)
-               goto out;
-
-       /* run function */
-       profile_id = g_strdup_printf ("GsPlugin::%s(%s)",
-                                     plugin->name, function_name);
-       gs_profile_start (plugin_loader->priv->profile, profile_id);
-       g_assert (error == NULL || *error == NULL);
-       ret = plugin_func (plugin, list, category, category_exclude, cancellable, error);
-       if (!ret)
-               goto out;
-out:
-       if (profile_id != NULL) {
-               gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
-               gs_profile_stop (plugin_loader->priv->profile, profile_id);
-       }
-       return ret;
-}
-
-/**
- * gs_plugin_loader_run_popular:
- **/
-static GList *
-gs_plugin_loader_run_popular (GsPluginLoader *plugin_loader,
-                             const gchar *function_name,
-                             GsPluginRefineFlags flags,
-                             const gchar *category,
-                             const gchar *category_exclude,
-                             GCancellable *cancellable,
-                             GError **error)
-{
-       gboolean ret = TRUE;
-       GList *list = NULL;
-       GsPlugin *plugin;
-       guint i;
-       _cleanup_free_ gchar *profile_id_parent = NULL;
-
-       g_return_val_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader), NULL);
-       g_return_val_if_fail (function_name != NULL, NULL);
-       g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-       g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
-
-       /* profile */
-       profile_id_parent = g_strdup_printf ("GsPlugin::*(%s)",
-                                            function_name);
-       gs_profile_start (plugin_loader->priv->profile, profile_id_parent);
-
-       /* 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;
-                       goto out;
-               }
-               ret = gs_plugin_loader_run_popular_plugin (plugin_loader,
-                                                          plugin,
-                                                          function_name,
-                                                          &list,
-                                                          category,
-                                                          category_exclude,
-                                                          cancellable,
-                                                          error);
-               if (!ret)
-                       goto out;
-       }
-
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, list);
-
-       /* run refine() on each one */
-       ret = gs_plugin_loader_run_refine (plugin_loader,
-                                          function_name,
-                                          &list,
-                                          flags,
-                                          cancellable,
-                                          error);
-       if (!ret)
-               goto out;
-
-       /* filter package list */
-       gs_plugin_list_filter_duplicates (&list);
-
-       /* no results */
-       if (list == NULL) {
-               g_set_error (error,
-                            GS_PLUGIN_LOADER_ERROR,
-                            GS_PLUGIN_LOADER_ERROR_NO_RESULTS,
-                            "no results to show");
-               goto out;
-       }
-out:
-       gs_profile_stop (plugin_loader->priv->profile, profile_id_parent);
-       if (!ret) {
-               gs_plugin_list_free (list);
-               list = NULL;
-       }
-       return list;
-}
-
-/**
  * gs_plugin_loader_get_app_str:
  **/
 static const gchar *
@@ -854,8 +730,6 @@ typedef struct {
        GsPluginRefineFlags              flags;
        gchar                           *value;
        gchar                           *filename;
-       gchar                           *popular_category;
-       gchar                           *popular_category_exclude;
        guint                            cache_age;
        GsCategory                      *category;
        GsApp                           *app;
@@ -874,8 +748,6 @@ gs_plugin_loader_free_async_state (GsPluginLoaderAsyncState *state)
                g_object_unref (state->app);
 
        g_free (state->filename);
-       g_free (state->popular_category);
-       g_free (state->popular_category_exclude);
        g_free (state->value);
        gs_plugin_list_free (state->list);
        g_slice_free (GsPluginLoaderAsyncState, state);
@@ -1293,11 +1165,9 @@ gs_plugin_loader_get_popular_thread_cb (GTask *task,
        GError *error = NULL;
 
        /* do things that would block */
-       state->list = gs_plugin_loader_run_popular (plugin_loader,
+       state->list = gs_plugin_loader_run_results (plugin_loader,
                                                    "gs_plugin_add_popular",
                                                    state->flags,
-                                                   state->popular_category,
-                                                   state->popular_category_exclude,
                                                    cancellable,
                                                    &error);
        if (error != NULL) {
@@ -1327,8 +1197,6 @@ gs_plugin_loader_get_popular_thread_cb (GTask *task,
 void
 gs_plugin_loader_get_popular_async (GsPluginLoader *plugin_loader,
                                    GsPluginRefineFlags flags,
-                                   const gchar *category,
-                                   const gchar *category_exclude,
                                    GCancellable *cancellable,
                                    GAsyncReadyCallback callback,
                                    gpointer user_data)
@@ -1342,8 +1210,6 @@ gs_plugin_loader_get_popular_async (GsPluginLoader *plugin_loader,
        /* save state */
        state = g_slice_new0 (GsPluginLoaderAsyncState);
        state->flags = flags;
-       state->popular_category = g_strdup (category);
-       state->popular_category_exclude = g_strdup (category_exclude);
 
        /* run in a thread */
        task = g_task_new (plugin_loader, cancellable, callback, user_data);
diff --git a/src/gs-plugin-loader.h b/src/gs-plugin-loader.h
index 1146e81..5247ea0 100644
--- a/src/gs-plugin-loader.h
+++ b/src/gs-plugin-loader.h
@@ -104,8 +104,6 @@ GList               *gs_plugin_loader_get_sources_finish    (GsPluginLoader 
*plugin_loader,
                                                         GError         **error);
 void            gs_plugin_loader_get_popular_async     (GsPluginLoader *plugin_loader,
                                                         GsPluginRefineFlags flags,
-                                                        const gchar    *category,
-                                                        const gchar    *category_exclude,
                                                         GCancellable   *cancellable,
                                                         GAsyncReadyCallback callback,
                                                         gpointer        user_data);
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index 94c5268..810aabd 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -123,12 +123,6 @@ typedef gboolean    (*GsPluginCategoryFunc)        (GsPlugin       *plugin,
                                                         GList          **list,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
-typedef gboolean        (*GsPluginPopularFunc)         (GsPlugin       *plugin,
-                                                        GList          **list,
-                                                        const gchar    *category,
-                                                        const gchar    *category_exclude,
-                                                        GCancellable   *cancellable,
-                                                        GError         **error);
 typedef gboolean        (*GsPluginResultsFunc)         (GsPlugin       *plugin,
                                                         GList          **list,
                                                         GCancellable   *cancellable,
@@ -218,8 +212,6 @@ gboolean     gs_plugin_add_category_apps            (GsPlugin       *plugin,
                                                         GError         **error);
 gboolean        gs_plugin_add_popular                  (GsPlugin       *plugin,
                                                         GList          **list,
-                                                        const gchar    *category,
-                                                        const gchar    *category_exclude,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
 gboolean        gs_plugin_add_featured                 (GsPlugin       *plugin,
diff --git a/src/gs-shell-overview.c b/src/gs-shell-overview.c
index b75c95a..cfa42d4 100644
--- a/src/gs-shell-overview.c
+++ b/src/gs-shell-overview.c
@@ -72,6 +72,21 @@ enum {
 
 static guint signals [SIGNAL_LAST] = { 0 };
 
+typedef struct {
+        GsCategory     *category;
+        GsShellOverview        *shell_overview;
+} LoadData;
+
+static void
+load_data_free (LoadData *data)
+{
+        if (data->category != NULL)
+                g_object_unref (data->category);
+        if (data->shell_overview != NULL)
+                g_object_unref (data->shell_overview);
+        g_slice_free (LoadData, data);
+}
+
 /**
  * gs_shell_overview_invalidate:
  **/
@@ -157,7 +172,8 @@ gs_shell_overview_get_popular_rotating_cb (GObject *source_object,
                                           GAsyncResult *res,
                                           gpointer user_data)
 {
-       GsShellOverview *shell = GS_SHELL_OVERVIEW (user_data);
+       LoadData *load_data = (LoadData *) user_data;
+       GsShellOverview *shell = load_data->shell_overview;
        GsShellOverviewPrivate *priv = shell->priv;
        GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object);
        GList *l;
@@ -168,7 +184,7 @@ gs_shell_overview_get_popular_rotating_cb (GObject *source_object,
        _cleanup_error_free_ GError *error = NULL;
 
        /* get popular apps */
-       list = gs_plugin_loader_get_popular_finish (plugin_loader, res, &error);
+       list = gs_plugin_loader_get_category_apps_finish (plugin_loader, res, &error);
        if (list == NULL) {
                if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
                        g_warning ("failed to get recommended applications: %s", error->message);
@@ -200,6 +216,7 @@ gs_shell_overview_get_popular_rotating_cb (GObject *source_object,
 
 out:
        gs_plugin_list_free (list);
+       load_data_free (load_data);
        priv->loading_popular_rotating = FALSE;
        priv->refresh_count--;
        if (priv->refresh_count == 0) {
@@ -382,8 +399,6 @@ gs_shell_overview_load (GsShellOverview *shell_overview)
                priv->loading_popular = TRUE;
                gs_plugin_loader_get_popular_async (priv->plugin_loader,
                                                    GS_PLUGIN_REFINE_FLAGS_DEFAULT,
-                                                   NULL,
-                                                   category_of_day,
                                                    priv->cancellable,
                                                    gs_shell_overview_get_popular_cb,
                                                    shell_overview);
@@ -391,14 +406,24 @@ gs_shell_overview_load (GsShellOverview *shell_overview)
        }
 
        if (!priv->loading_popular_rotating) {
+               LoadData *load_data;
+               _cleanup_object_unref_ GsCategory *category = NULL;
+               _cleanup_object_unref_ GsCategory *featured_category = NULL;
+
+               category = gs_category_new (NULL, category_of_day, NULL);
+               featured_category = gs_category_new (category, "featured", NULL);
+
+               load_data = g_slice_new0 (LoadData);
+               load_data->category = g_object_ref (category);
+               load_data->shell_overview = g_object_ref (shell_overview);
+
                priv->loading_popular_rotating = TRUE;
-               gs_plugin_loader_get_popular_async (priv->plugin_loader,
-                                                   GS_PLUGIN_REFINE_FLAGS_DEFAULT,
-                                                   category_of_day,
-                                                   NULL,
-                                                   priv->cancellable,
-                                                   gs_shell_overview_get_popular_rotating_cb,
-                                                   shell_overview);
+               gs_plugin_loader_get_category_apps_async (priv->plugin_loader,
+                                                         featured_category,
+                                                         GS_PLUGIN_REFINE_FLAGS_DEFAULT,
+                                                         priv->cancellable,
+                                                         gs_shell_overview_get_popular_rotating_cb,
+                                                         load_data);
                priv->refresh_count++;
        }
 
diff --git a/src/plugins/gs-moduleset.c b/src/plugins/gs-moduleset.c
index a1c5a49..5f5c157 100644
--- a/src/plugins/gs-moduleset.c
+++ b/src/plugins/gs-moduleset.c
@@ -73,9 +73,9 @@ gs_moduleset_get_modules (GsModuleset *moduleset,
                entry = g_ptr_array_index (priv->array, i);
                if (entry->module_kind != module_kind)
                        continue;
-               if (g_strcmp0 (entry->name, name) != 0)
+               if (name && g_strcmp0 (entry->name, name) != 0)
                        continue;
-               if (g_strcmp0 (entry->category, category) != 0)
+               if (category && g_strcmp0 (entry->category, category) != 0)
                        continue;
                data[idx++] = g_strdup (entry->id);
        }
@@ -84,6 +84,110 @@ gs_moduleset_get_modules (GsModuleset *moduleset,
 }
 
 /**
+ * gs_moduleset_get_core_packages:
+ **/
+gchar **
+gs_moduleset_get_core_packages (GsModuleset *moduleset)
+{
+       return gs_moduleset_get_modules (moduleset,
+                                        GS_MODULESET_MODULE_KIND_PACKAGE,
+                                        "core",
+                                        NULL);
+}
+
+/**
+ * gs_moduleset_get_system_apps:
+ **/
+gchar **
+gs_moduleset_get_system_apps (GsModuleset *moduleset)
+{
+       return gs_moduleset_get_modules (moduleset,
+                                        GS_MODULESET_MODULE_KIND_APPLICATION,
+                                        "system",
+                                        NULL);
+}
+
+/**
+ * gs_moduleset_get_popular_apps:
+ **/
+gchar **
+gs_moduleset_get_popular_apps (GsModuleset *moduleset)
+{
+       return gs_moduleset_get_modules (moduleset,
+                                        GS_MODULESET_MODULE_KIND_APPLICATION,
+                                        "popular",
+                                        NULL);
+}
+
+/**
+ * gs_moduleset_get_featured_apps:
+ **/
+gchar **
+gs_moduleset_get_featured_apps (GsModuleset *moduleset,
+                                const gchar *category)
+{
+       return gs_moduleset_get_modules (moduleset,
+                                        GS_MODULESET_MODULE_KIND_APPLICATION,
+                                        "featured",
+                                        category);
+}
+
+/**
+ * gs_moduleset_get_categories:
+ **/
+gchar **
+gs_moduleset_get_featured_categories (GsModuleset *moduleset)
+{
+       GsModulesetPrivate *priv = gs_moduleset_get_instance_private (moduleset);
+       GsModulesetEntry *entry;
+       guint i;
+       _cleanup_hashtable_unref_ GHashTable *categories_hash = NULL;
+
+       g_return_val_if_fail (GS_IS_MODULESET (moduleset), NULL);
+
+       categories_hash = g_hash_table_new (g_str_hash, g_str_equal);
+       for (i = 0; i < priv->array->len; i++) {
+               entry = g_ptr_array_index (priv->array, i);
+               if (g_strcmp0 (entry->name, "featured") != 0)
+                       continue;
+               if (entry->category == NULL)
+                       continue;
+               g_hash_table_insert (categories_hash, g_strdup (entry->category), GINT_TO_POINTER (1));
+       }
+
+       return (gchar **) g_hash_table_get_keys_as_array (categories_hash, NULL);
+}
+
+/**
+ * gs_moduleset_get_n_featured:
+ **/
+guint
+gs_moduleset_get_n_featured (GsModuleset *moduleset,
+                             const gchar *category)
+{
+       GsModulesetPrivate *priv = gs_moduleset_get_instance_private (moduleset);
+       GsModulesetEntry *entry;
+       guint i;
+       guint cnt;
+
+       g_return_val_if_fail (GS_IS_MODULESET (moduleset), NULL);
+
+       cnt = 0;
+       for (i = 0; i < priv->array->len; i++) {
+               entry = g_ptr_array_index (priv->array, i);
+               if (entry->module_kind != GS_MODULESET_MODULE_KIND_APPLICATION)
+                       continue;
+               if (g_strcmp0 (entry->name, "featured") != 0)
+                       continue;
+               if (g_strcmp0 (entry->category, category) != 0)
+                       continue;
+               cnt++;
+       }
+
+       return cnt;
+}
+
+/**
  * gs_moduleset_section_from_string:
  **/
 static GsModulesetParserSection
diff --git a/src/plugins/gs-moduleset.h b/src/plugins/gs-moduleset.h
index 3473cb3..035d0e2 100644
--- a/src/plugins/gs-moduleset.h
+++ b/src/plugins/gs-moduleset.h
@@ -53,6 +53,14 @@ gchar                **gs_moduleset_get_modules              (GsModuleset            
*moduleset,
                                                         GsModulesetModuleKind   module_kind,
                                                         const gchar            *name,
                                                         const gchar            *category);
+gchar          **gs_moduleset_get_core_packages        (GsModuleset            *moduleset);
+gchar          **gs_moduleset_get_system_apps          (GsModuleset            *moduleset);
+gchar          **gs_moduleset_get_popular_apps         (GsModuleset            *moduleset);
+gchar          **gs_moduleset_get_featured_apps        (GsModuleset            *moduleset,
+                                                        const gchar            *category);
+gchar          **gs_moduleset_get_featured_categories  (GsModuleset            *moduleset);
+guint           gs_moduleset_get_n_featured            (GsModuleset            *moduleset,
+                                                        const gchar            *category);
 gboolean        gs_moduleset_parse_filename            (GsModuleset            *moduleset,
                                                         const gchar            *filename,
                                                         GError                 **error);
diff --git a/src/plugins/gs-plugin-dummy.c b/src/plugins/gs-plugin-dummy.c
index e261453..4814a87 100644
--- a/src/plugins/gs-plugin-dummy.c
+++ b/src/plugins/gs-plugin-dummy.c
@@ -146,8 +146,6 @@ gs_plugin_add_installed (GsPlugin *plugin,
 gboolean
 gs_plugin_add_popular (GsPlugin *plugin,
                       GList **list,
-                      const gchar *category,
-                      const gchar *category_exclude,
                       GCancellable *cancellable,
                       GError **error)
 {
diff --git a/src/plugins/gs-plugin-moduleset.c b/src/plugins/gs-plugin-moduleset.c
index 3c21e6b..09578ce 100644
--- a/src/plugins/gs-plugin-moduleset.c
+++ b/src/plugins/gs-plugin-moduleset.c
@@ -51,6 +51,7 @@ const gchar **
 gs_plugin_get_deps (GsPlugin *plugin)
 {
        static const gchar *deps[] = {
+               "menu-spec-categories", /* featured subcat added to existing categories */
                "packagekit",           /* pkgname */
                NULL };
        return deps;
@@ -95,14 +96,107 @@ out:
        return ret;
 }
 
+gboolean
+gs_plugin_add_categories (GsPlugin *plugin,
+                          GList **list,
+                          GCancellable *cancellable,
+                          GError **error)
+{
+       GList *l;
+       GsCategory *parent;
+       const gchar *id;
+       guint i;
+       _cleanup_strv_free_ gchar **categories = NULL;
+
+       /* load XML files */
+       if (g_once_init_enter (&plugin->priv->done_init)) {
+               gboolean ret = gs_plugin_startup (plugin, error);
+               g_once_init_leave (&plugin->priv->done_init, TRUE);
+               if (!ret)
+                       return FALSE;
+       }
+
+       categories = gs_moduleset_get_featured_categories (plugin->priv->moduleset);
+       if (categories == NULL) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "No moduleset data found");
+               return FALSE;
+       }
+
+       for (i = 0; categories[i]; i++) {
+               for (l = *list; l; l = l->next) {
+                       parent = l->data;
+                       id = gs_category_get_id (parent);
+                       if (g_strcmp0 (categories[i], id) == 0) {
+                               guint size;
+                               _cleanup_object_unref_ GsCategory *cat = NULL;
+
+                               cat = gs_category_new (parent, "featured", _("Featured"));
+                               gs_category_add_subcategory (parent, cat);
+                               size = gs_moduleset_get_n_featured (plugin->priv->moduleset, id);
+                               gs_category_set_size (cat, size);
+                               break;
+                       }
+               }
+       }
+
+       return TRUE;
+}
+
+gboolean
+gs_plugin_add_category_apps (GsPlugin *plugin,
+                            GsCategory *category,
+                            GList **list,
+                            GCancellable *cancellable,
+                            GError **error)
+{
+       GsCategory *parent;
+       guint i;
+
+       /* load XML files */
+       if (g_once_init_enter (&plugin->priv->done_init)) {
+               gboolean ret = gs_plugin_startup (plugin, error);
+               g_once_init_leave (&plugin->priv->done_init, TRUE);
+               if (!ret)
+                       return FALSE;
+       }
+
+       /* Populate the "featured" subcategory */
+       if (g_strcmp0 (gs_category_get_id (category), "featured") == 0) {
+               _cleanup_strv_free_ gchar **apps = NULL;
+
+               parent = gs_category_get_parent (category);
+               if (parent != NULL) {
+                       apps = gs_moduleset_get_featured_apps (plugin->priv->moduleset,
+                                                              gs_category_get_id (parent));
+               }
+               if (apps == NULL) {
+                       g_set_error (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_FAILED,
+                                    "No moduleset data found");
+                       return FALSE;
+               }
+
+               /* just add all */
+               for (i = 0; apps[i]; i++) {
+                       _cleanup_object_unref_ GsApp *app = NULL;
+                       app = gs_app_new (apps[i]);
+                       gs_plugin_add_app (list, app);
+               }
+       }
+
+       return TRUE;
+}
+
 /**
  * gs_plugin_add_popular:
  */
 gboolean
 gs_plugin_add_popular (GsPlugin *plugin,
                       GList **list,
-                      const gchar *category,
-                      const gchar *category_exclude,
                       GCancellable *cancellable,
                       GError **error)
 {
@@ -121,10 +215,7 @@ gs_plugin_add_popular (GsPlugin *plugin,
        if (g_getenv ("GNOME_SOFTWARE_POPULAR")) {
                apps = g_strsplit (g_getenv ("GNOME_SOFTWARE_POPULAR"), ",", 0);
        } else {
-               apps = gs_moduleset_get_modules (plugin->priv->moduleset,
-                                                GS_MODULESET_MODULE_KIND_APPLICATION,
-                                                "popular",
-                                                category);
+               apps = gs_moduleset_get_popular_apps (plugin->priv->moduleset);
        }
        if (apps == NULL) {
                g_set_error (error,
@@ -139,7 +230,6 @@ gs_plugin_add_popular (GsPlugin *plugin,
                _cleanup_object_unref_ GsApp *app = NULL;
                app = gs_app_new (apps[i]);
                gs_plugin_add_app (list, app);
-               gs_app_add_kudo (app, GS_APP_KUDO_FEATURED_RECOMMENDED);
        }
        return TRUE;
 }
@@ -158,8 +248,10 @@ gs_plugin_refine (GsPlugin *plugin,
        GsApp *app;
        gboolean ret = TRUE;
        guint i;
-       _cleanup_strv_free_ gchar **apps = NULL;
-       _cleanup_strv_free_ gchar **pkgs = NULL;
+       _cleanup_strv_free_ gchar **featured_apps = NULL;
+       _cleanup_strv_free_ gchar **popular_apps = NULL;
+       _cleanup_strv_free_ gchar **system_apps = NULL;
+       _cleanup_strv_free_ gchar **core_pkgs = NULL;
 
        /* load XML files */
        if (g_once_init_enter (&plugin->priv->done_init)) {
@@ -169,21 +261,14 @@ gs_plugin_refine (GsPlugin *plugin,
                        return FALSE;
        }
 
-       /* just mark each one as core */
-       apps = gs_moduleset_get_modules (plugin->priv->moduleset,
-                                        GS_MODULESET_MODULE_KIND_APPLICATION,
-                                        "system",
-                                        NULL);
-       for (l = *list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               for (i = 0; apps[i] != NULL; i++) {
-                       if (g_strcmp0 (apps[i], gs_app_get_id (app)) == 0) {
-                               gs_app_set_kind (app, GS_APP_KIND_SYSTEM);
-                               break;
-                       }
-               }
-       }
-       if (apps == NULL) {
+       featured_apps = gs_moduleset_get_featured_apps (plugin->priv->moduleset, NULL);
+       popular_apps = gs_moduleset_get_popular_apps (plugin->priv->moduleset);
+       system_apps = gs_moduleset_get_system_apps (plugin->priv->moduleset);
+       core_pkgs = gs_moduleset_get_core_packages (plugin->priv->moduleset);
+       if (featured_apps == NULL &&
+           popular_apps == NULL &&
+           system_apps == NULL &&
+           core_pkgs == NULL) {
                g_set_error (error,
                             GS_PLUGIN_ERROR,
                             GS_PLUGIN_ERROR_FAILED,
@@ -191,20 +276,42 @@ gs_plugin_refine (GsPlugin *plugin,
                return FALSE;
        }
 
-       /* just mark each one as core */
-       pkgs = gs_moduleset_get_modules (plugin->priv->moduleset,
-                                        GS_MODULESET_MODULE_KIND_PACKAGE,
-                                        "core",
-                                        NULL);
        for (l = *list; l != NULL; l = l->next) {
                app = GS_APP (l->data);
-               for (i = 0; pkgs[i] != NULL; i++) {
-                       if (g_strcmp0 (pkgs[i], gs_app_get_source_default (app)) == 0) {
+
+               /* add a kudo to featured apps */
+               for (i = 0; featured_apps[i] != NULL; i++) {
+                       if (g_strcmp0 (featured_apps[i], gs_app_get_id (app)) == 0) {
+                               gs_app_add_kudo (app, GS_APP_KUDO_FEATURED_RECOMMENDED);
+                               break;
+                       }
+               }
+
+               /* add a kudo to popular apps */
+               for (i = 0; popular_apps[i] != NULL; i++) {
+                       if (g_strcmp0 (popular_apps[i], gs_app_get_id (app)) == 0) {
+                               gs_app_add_kudo (app, GS_APP_KUDO_FEATURED_RECOMMENDED);
+                               break;
+                       }
+               }
+
+               /* mark each one as system */
+               for (i = 0; system_apps[i] != NULL; i++) {
+                       if (g_strcmp0 (system_apps[i], gs_app_get_id (app)) == 0) {
+                               gs_app_set_kind (app, GS_APP_KIND_SYSTEM);
+                               break;
+                       }
+               }
+
+               /* mark each one as core */
+               for (i = 0; core_pkgs[i] != NULL; i++) {
+                       if (g_strcmp0 (core_pkgs[i], gs_app_get_source_default (app)) == 0) {
                                gs_app_set_kind (app, GS_APP_KIND_CORE);
                                break;
                        }
                }
        }
+
        return TRUE;
 }
 


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