From acbd3ac3899bd1230097df2f1afea6c3690a5cb8 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 17 Oct 2018 23:01:17 +0200
Subject: Extended themes from plugins CSS definitions.

---
 src/gui/core/core.c      | 13 ++++---
 src/gui/core/theme.c     | 92 +++++++++++++++++++++++++++++++++++++++++-------
 src/plugins/pglist.h     |  4 ++-
 src/plugins/plugin-def.h | 16 +++++++--
 src/plugins/plugin-int.h |  5 +++
 src/plugins/plugin.c     | 55 +++++++++++++++++++++++++++++
 src/plugins/plugin.h     |  3 ++
 7 files changed, 167 insertions(+), 21 deletions(-)

diff --git a/src/gui/core/core.c b/src/gui/core/core.c
index 2cb75b1..8783783 100644
--- a/src/gui/core/core.c
+++ b/src/gui/core/core.c
@@ -55,11 +55,9 @@ bool load_all_gui_components(void)
     GMenuBar *bar;                          /* Gestion des menus           */
     GtkMenuItem *submenuitem;               /* Sous-élément de menu        */
 
-    load_main_panels();
-
-    load_extra_gtk_theme();
+    result = true;
 
-    result = load_segment_rendering_parameters();
+    load_main_panels();
 
     /**
      * Charge une liste initiale pour activer les raccourcis clavier.
@@ -95,6 +93,10 @@ bool complete_loading_of_all_gui_components(GGenConfig *config)
     GtkTiledGrid *grid;                     /* Composant d'affichage       */
     GPanelItem *welcome;                    /* Panneau d'accueil           */
 
+    load_extra_gtk_theme();
+
+    result = load_segment_rendering_parameters();
+
     grid = get_tiled_grid();
 
     welcome = get_panel_item_by_name(PANEL_WELCOME_ID);
@@ -112,7 +114,8 @@ bool complete_loading_of_all_gui_components(GGenConfig *config)
      * Donc on doit sauter ce panneau d'accueil lors de l'appel suivant.
      */
 
-    result = _browse_all_item_panels(true, (handle_panel_item_fc)gtk_panel_item_apply_configuration, config);
+    if (result)
+        result = _browse_all_item_panels(true, (handle_panel_item_fc)gtk_panel_item_apply_configuration, config);
 
     gtk_tiled_grid_restore_positions(grid, config);
 
diff --git a/src/gui/core/theme.c b/src/gui/core/theme.c
index be060be..daf0bfe 100644
--- a/src/gui/core/theme.c
+++ b/src/gui/core/theme.c
@@ -43,6 +43,7 @@
 #include "../../common/xdg.h"
 #include "../../core/logs.h"
 #include "../../core/params.h"
+#include "../../plugins/pglist.h"
 
 
 
@@ -55,6 +56,9 @@ static char *look_for_named_theme(const char *, const char *, gboolean);
 /* Ajoute les définitions CSS à partir d'un chemin donné. */
 static void load_css_partial_content(char **, const char *, gboolean);
 
+/* Parcourt tous les greffons à la recherche de définitions CSS. */
+static void prepend_plugins_themes(char **, gboolean);
+
 /* Etend le thème courant de GTK. */
 static void activate_css_content(GdkScreen *, const char *);
 
@@ -106,6 +110,8 @@ bool load_extra_gtk_theme(void)
 
     if (content != NULL)
     {
+        prepend_plugins_themes(&content, dark);
+
         activate_css_content(screen, content);
         free(content);
 
@@ -257,33 +263,43 @@ static char *look_for_named_theme(const char *dirname, const char *name, gboolea
 static void load_css_partial_content(char **content, const char *path, gboolean dark)
 {
     bool got_it;                            /* Version sombre présente ?   */
-    char *dark_path;                        /* Version sombre du chemin    */
     GtkCssProvider *provider;               /* Nouveau fournisseur CSS     */
+    char *dark_path;                        /* Version sombre du chemin    */
+    GFile *file;                            /* Fichier à charger           */
     GError *error;                          /* Relevé d'éventuelles erreurs*/
-    char *extra;                            /* Contenu d'une feuille       */
+    char *css;                              /* Contenu d'une feuille       */
 
     got_it = false;
 
     if (dark)
     {
+        provider = gtk_css_provider_new();
+
+        error = NULL;
+
         dark_path = strdup(path);
         dark_path = strrpl(dark_path, ".css", "-dark.css");
 
-        provider = gtk_css_provider_new();
+        if (strstr(path, "://") != NULL)
+            file = g_file_new_for_uri(dark_path);
+        else
+            file = g_file_new_for_path(dark_path);
 
-        error = NULL;
+        free(dark_path);
 
-        gtk_css_provider_load_from_path(provider, dark_path, &error);
+        gtk_css_provider_load_from_file(provider, file, &error);
+
+        g_object_unref(G_OBJECT(file));
 
         if (error == NULL)
         {
             log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), dark_path);
 
-            extra = gtk_css_provider_to_string(provider);
+            css = gtk_css_provider_to_string(provider);
 
-            *content = stradd(*content, extra);
+            *content = stradd(*content, css);
 
-            free(extra);
+            free(css);
 
             got_it = true;
 
@@ -301,17 +317,24 @@ static void load_css_partial_content(char **content, const char *path, gboolean
 
         error = NULL;
 
-        gtk_css_provider_load_from_path(provider, path, &error);
+        if (strstr(path, "://") != NULL)
+            file = g_file_new_for_uri(path);
+        else
+            file = g_file_new_for_path(path);
+
+        gtk_css_provider_load_from_file(provider, file, &error);
+
+        g_object_unref(G_OBJECT(file));
 
         if (error == NULL)
         {
             log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), path);
 
-            extra = gtk_css_provider_to_string(provider);
+            css = gtk_css_provider_to_string(provider);
 
-            *content = stradd(*content, extra);
+            *content = stradd(*content, css);
 
-            free(extra);
+            free(css);
 
         }
         else
@@ -329,6 +352,51 @@ static void load_css_partial_content(char **content, const char *path, gboolean
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : content = définitions CSS à compléter. [OUT]                 *
+*                dark    = indique une préférence pour la variante foncée.    *
+*                                                                             *
+*  Description : Parcourt tous les greffons à la recherche de définitions CSS.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void prepend_plugins_themes(char **content, gboolean dark)
+{
+    char *extra;                            /* Nouvelles définitions CSS   */
+    char **resources;                       /* Fichiers supplémentaires    */
+    size_t count;                           /* Nombre de ces fichiers      */
+    size_t i;                               /* Boucle de parcours          */
+
+    extra = NULL;
+
+    resources = NULL;
+    count = 0;
+
+    include_plugin_theme(&resources, &count);
+
+    for (i = 0; i < count; i++)
+    {
+        load_css_partial_content(&extra, resources[i], dark);
+        free(resources[i]);
+    }
+
+    if (resources != NULL)
+        free(resources);
+
+    if (extra != NULL)
+    {
+        *content = strprep(*content, extra);
+        free(extra);
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : screen  = écran concerné par les éventuels chargements.      *
 *                content = contenu CSS reconstitué à charger.                 *
 *                                                                             *
diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h
index 5fc2867..31c9c29 100644
--- a/src/plugins/pglist.h
+++ b/src/plugins/pglist.h
@@ -85,8 +85,10 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
     while (0)
 
 
+/* DPS_SETUP */
 
-
+#define include_plugin_theme(r, c) \
+    process_all_plugins_for(PGA_GUI_THEME, g_plugin_module_include_theme, r, c)
 
 /* DPS_CONTENT */
 
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index f404b14..fd05b00 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -69,15 +69,18 @@ typedef uint32_t plugin_action_t;
 
 
 #define DPC_BASIC               DEFINE_PLUGIN_CATEGORY(0)
-#define DPC_BINARY_PROCESSING   DEFINE_PLUGIN_CATEGORY(1)
-
-// GUI
+#define DPC_GUI                 DEFINE_PLUGIN_CATEGORY(1)
+#define DPC_BINARY_PROCESSING   DEFINE_PLUGIN_CATEGORY(2)
 
 /* DPC_BASIC */
 
 #define DPS_NONE                DEFINE_PLUGIN_SUB_CATEGORY(0)
 #define DPS_PG_MANAGEMENT       DEFINE_PLUGIN_SUB_CATEGORY(1)
 
+/* DPC_GUI */
+
+#define DPS_SETUP               DEFINE_PLUGIN_SUB_CATEGORY(0)
+
 /* DPC_BINARY_PROCESSING */
 
 #define DPS_CONTENT             DEFINE_PLUGIN_SUB_CATEGORY(0)
@@ -114,6 +117,13 @@ typedef enum _PluginAction
     PGA_PLUGIN_EXIT = DPC_BASIC | DPS_PG_MANAGEMENT | DEFINE_PLUGIN_ACTION(1),
 
     /**
+     * DPC_GUI | DPS_SETUP
+     */
+
+    /* Inclusion de thèmes */
+    PGA_GUI_THEME = DPC_GUI | DPS_SETUP | DEFINE_PLUGIN_ACTION(0),
+
+    /**
      * DPC_BINARY_PROCESSING | DPS_CONTENT
      */
 
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index 19993e9..cee6242 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -47,6 +47,9 @@ typedef void (* pg_handle_content_fc) (const GPluginModule *, PluginAction, GBin
 /* Procède à une opération liée à un contenu chargé. */
 typedef void (* pg_handle_loaded_fc) (const GPluginModule *, PluginAction, GLoadedContent *, wgroup_id_t, GtkStatusStack *);
 
+/* Complète une liste de resources pour thème. */
+typedef void (* pg_include_theme_fc) (const GPluginModule *, PluginAction, char ***, size_t *);
+
 /* Assure l'interprétation d'un format en différé. */
 typedef bool (* pg_handle_format_analysis_fc) (const GPluginModule *, PluginAction, GBinFormat *, wgroup_id_t, GtkStatusStack *);
 
@@ -80,6 +83,8 @@ struct _GPluginModule
     pg_management_fc init;                  /* Procédure d'initialisation  */
     pg_management_fc exit;                  /* Procédure d'extinction      */
 
+    pg_include_theme_fc include_theme;      /* Extension d'un thème        */
+
     pg_handle_content_fc handle_content;    /* Explorations ou résolutions */
     pg_handle_loaded_fc handle_loaded;      /* Traitement de contenu chargé*/
 
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index b63b263..161d6a6 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -297,6 +297,39 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
 
                 break;
 
+            case DPC_GUI:
+
+                switch (sub)
+                {
+                    case DPS_SETUP:
+
+                        switch (action)
+                        {
+                            case PGA_GUI_THEME:
+                                if (!load_plugin_symbol(result->module,
+                                                        "chrysalide_plugin_include_theme", &result->include_theme))
+                                    goto bad_plugin;
+                                break;
+
+                            default:
+                                log_variadic_message(LMT_WARNING,
+                                                     _("Unknown action '0x%02x' in plugin '%s'..."),
+                                                     result->interface->actions[i], filename);
+                                break;
+
+                        }
+
+                        break;
+
+                    default:
+                        log_variadic_message(LMT_WARNING,
+                                             _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+                        break;
+
+                }
+
+                break;
+
             case DPC_BINARY_PROCESSING:
 
                 switch (sub)
@@ -742,6 +775,28 @@ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessag
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : plugin    = greffon à manipuler.                             *
+*                action    = type d'action attendue.                          *
+*                resources = liste de ressources à constituer. [OUT]          *
+*                count     = taille de cette liste. [OUT]                     *
+*                                                                             *
+*  Description : Complète une liste de resources pour thème.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_plugin_module_include_theme(const GPluginModule *plugin, PluginAction action, char ***resources, size_t *count)
+{
+    plugin->include_theme(plugin, action, resources, count);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : plugin  = greffon à manipuler.                               *
 *                action  = type d'action attendue.                            *
 *                content = contenu binaire à traiter.                         *
diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h
index 718531a..1127604 100644
--- a/src/plugins/plugin.h
+++ b/src/plugins/plugin.h
@@ -91,6 +91,9 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *, GPluginModule **, siz
 /* Termine le chargement du greffon préparé. */
 bool g_plugin_module_load(GPluginModule *, GPluginModule **, size_t);
 
+/* Complète une liste de resources pour thème. */
+void g_plugin_module_include_theme(const GPluginModule *, PluginAction, char ***, size_t *);
+
 /* Procède à une opération liée à un contenu binaire. */
 void g_plugin_module_handle_binary_content(const GPluginModule *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *);
 
-- 
cgit v0.11.2-87-g4458