From 30411ff58e8c495953d09b5b796ce129056c20fb Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 17 Oct 2018 20:52:51 +0200 Subject: Written a better version of CSS definitions loading. --- src/gui/core/theme.c | 205 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 141 insertions(+), 64 deletions(-) diff --git a/src/gui/core/theme.c b/src/gui/core/theme.c index 4b097d0..be060be 100644 --- a/src/gui/core/theme.c +++ b/src/gui/core/theme.c @@ -25,13 +25,14 @@ #include "theme.h" -#include -#include +#include #include #include #include #include #include +#include +#include #include @@ -46,10 +47,16 @@ /* Parcourt tous les répertoires connus pour trouver un thème. */ -static bool browse_themes_directories(GdkScreen *, const char *, gboolean); +static char *browse_themes_directories(const char *, gboolean); /* Parcourt un répertoire donné à la recherche d'un thème. */ -static bool look_for_named_theme(GdkScreen *, const char *, const char *, gboolean); +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); + +/* Etend le thème courant de GTK. */ +static void activate_css_content(GdkScreen *, const char *); /* Répertoires de recherche */ @@ -82,6 +89,7 @@ bool load_extra_gtk_theme(void) GdkScreen *screen; /* Ecran(s) concerné(s) */ GtkSettings *settings; /* Propriétés du système */ gboolean dark; /* Envie d'un thème sombre ? */ + char *content; /* Définitions CSS à charger */ result = false; @@ -94,11 +102,16 @@ bool load_extra_gtk_theme(void) g_object_get(settings, "gtk-application-prefer-dark-theme", &dark, NULL); - if (dark) - result = browse_themes_directories(screen, name, true); + content = browse_themes_directories(name, dark); - if (!result) - result = browse_themes_directories(screen, name, false); + if (content != NULL) + { + activate_css_content(screen, content); + free(content); + + result = true; + + } legt_done: @@ -109,26 +122,25 @@ bool load_extra_gtk_theme(void) /****************************************************************************** * * -* Paramètres : screen = écran concerné par les éventuels chargements. * -* name = nom du thème recherché, et donc de son répertoire. * +* Paramètres : name = nom du thème recherché, et donc de son répertoire. * * dark = indique une préférence pour la variante foncée. * * * * Description : Parcourt tous les répertoires connus pour trouver un thème. * * * -* Retour : true si un élément de thème a pu être chargé, false sinon. * +* Retour : Contenu CSS chargé ou NULL si aucun. * * * * Remarques : - * * * ******************************************************************************/ -static bool browse_themes_directories(GdkScreen *screen, const char *name, gboolean dark) +static char *browse_themes_directories(const char *name, gboolean dark) { - bool result; /* Bilan à faire remonter */ + char *result; /* Défintions CSS à renvoyer */ char *suffix; /* Fin du répertoire personnel */ char *owndir; /* Thèmes personnels ? */ const char **iter; /* Boucle de parcours */ - result = false; + result = NULL; /* Répertoire de l'utilisateur en premier ! */ @@ -142,7 +154,7 @@ static bool browse_themes_directories(GdkScreen *screen, const char *name, gbool if (owndir != NULL) { - result = look_for_named_theme(screen, owndir, name, dark); + result = look_for_named_theme(owndir, name, dark); free(owndir); @@ -150,8 +162,8 @@ static bool browse_themes_directories(GdkScreen *screen, const char *name, gbool /* Parcours des autres répertoires classiques au besoin */ - for (iter = _themes_directories; *iter != NULL && !result; iter++) - result = look_for_named_theme(screen, *iter, name, dark); + for (iter = _themes_directories; *iter != NULL && result == NULL; iter++) + result = look_for_named_theme(*iter, name, dark); return result; @@ -160,35 +172,30 @@ static bool browse_themes_directories(GdkScreen *screen, const char *name, gbool /****************************************************************************** * * -* Paramètres : screen = écran concerné par les éventuels chargements. * -* dirname = chemin du répertoire où effectuer des recherches. * +* Paramètres : dirname = chemin du répertoire où effectuer des recherches. * * name = nom du thème recherché, et donc de son répertoire. * * dark = indique une préférence pour la variante foncée. * * * * Description : Parcourt un répertoire donné à la recherche d'un thème. * * * -* Retour : true si un élément de thème a pu être chargé, false sinon. * +* Retour : Contenu CSS chargé ou NULL si aucun. * * * * Remarques : - * * * ******************************************************************************/ -static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const char *name, gboolean dark) +static char *look_for_named_theme(const char *dirname, const char *name, gboolean dark) { - bool result; /* Bilan à faire remonter */ + char *result; /* Défintions CSS à renvoyer */ char *path; /* Chemin d'accès à essayer */ int ret; /* Bilan d'un appel */ int dirfd; /* Canal de lecture */ struct dirent **namelist; /* Liste des trouvailles */ - char *css_content; /* Contenu de style cumulé */ int count; /* Nombre de fichiers trouvés */ int i; /* Boucle de parcours */ char *filename; /* Chemin d'accès constitué */ - GtkCssProvider *provider; /* Nouveau fournisseur CSS */ - GError *error; /* Relevé d'éventuelles erreurs*/ - char *content; /* Contenu d'une feuille */ - result = false; + result = NULL; ret = asprintf(&path, "%s" G_DIR_SEPARATOR_S "%s", dirname, name); if (ret == -1) goto lfnt_done; @@ -196,13 +203,6 @@ static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const c dirfd = open(path, O_RDONLY | O_DIRECTORY); if (dirfd == -1) goto lfnt_not_found; - int keep_dark_css_only(const struct dirent *entry) - { - return (entry->d_type == DT_REG - && endswith(entry->d_name, "-dark.css") ? 1 : 0); - - } - int keep_css_only(const struct dirent *entry) { return (entry->d_type == DT_REG @@ -211,83 +211,160 @@ static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const c } - css_content = NULL; - - count = scandirat(dirfd, ".", &namelist, dark ? keep_dark_css_only : keep_css_only, alphasort); + count = scandirat(dirfd, ".", &namelist, keep_css_only, alphasort); for (i = 0; i < count; i++) { ret = asprintf(&filename, "%s%s%s", path, G_DIR_SEPARATOR_S, namelist[i]->d_name); if (ret == -1) continue; + load_css_partial_content(&result, filename, dark); + + free(filename); + + } + + if (count > 0) + free(namelist); + + close(dirfd); + + lfnt_not_found: + + free(path); + + lfnt_done: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = définitions CSS à compléter. [OUT] * +* path = chemin vers la nouvelle définition à ajouter. * +* dark = indique une préférence pour la variante foncée. * +* * +* Description : Ajoute les définitions CSS à partir d'un chemin donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +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 */ + GError *error; /* Relevé d'éventuelles erreurs*/ + char *extra; /* Contenu d'une feuille */ + + got_it = false; + + if (dark) + { + dark_path = strdup(path); + dark_path = strrpl(dark_path, ".css", "-dark.css"); + provider = gtk_css_provider_new(); error = NULL; - gtk_css_provider_load_from_path(provider, filename, &error); + gtk_css_provider_load_from_path(provider, dark_path, &error); if (error == NULL) { - log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), filename); + log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), dark_path); + + extra = gtk_css_provider_to_string(provider); - content = gtk_css_provider_to_string(provider); + *content = stradd(*content, extra); - css_content = stradd(css_content, content); + free(extra); - free(content); + got_it = true; } else - { - log_variadic_message(LMT_ERROR, _("Failed to load CSS definitions from '%s'"), filename); g_error_free(error); - } g_object_unref(G_OBJECT(provider)); - free(filename); - } - if (count > 0) - free(namelist); - - close(dirfd); - - if (css_content != NULL) + if (!got_it) { provider = gtk_css_provider_new(); error = NULL; - gtk_css_provider_load_from_data(provider, css_content, -1, &error); + gtk_css_provider_load_from_path(provider, path, &error); if (error == NULL) { - gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), path); + + extra = gtk_css_provider_to_string(provider); + + *content = stradd(*content, extra); - result = true; + free(extra); } else { - log_variadic_message(LMT_ERROR, _("Failed to load CSS definitions")); + log_variadic_message(LMT_ERROR, _("Failed to load CSS definitions from '%s'"), path); g_error_free(error); } - free(css_content); - g_object_unref(G_OBJECT(provider)); } - lfnt_not_found: +} - free(path); - lfnt_done: +/****************************************************************************** +* * +* Paramètres : screen = écran concerné par les éventuels chargements. * +* content = contenu CSS reconstitué à charger. * +* * +* Description : Etend le thème courant de GTK. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - return result; +static void activate_css_content(GdkScreen *screen, const char *content) +{ + GtkCssProvider *provider; /* Nouveau fournisseur CSS */ + GError *error; /* Relevé d'éventuelles erreurs*/ + + provider = gtk_css_provider_new(); + + error = NULL; + + gtk_css_provider_load_from_data(provider, content, -1, &error); + + if (error == NULL) + { + gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } + else + { + assert(false); + + log_variadic_message(LMT_ERROR, _("Failed to load the global CSS extra definition")); + g_error_free(error); + + } + + g_object_unref(G_OBJECT(provider)); } -- cgit v0.11.2-87-g4458