summaryrefslogtreecommitdiff
path: root/src/gui/core/theme.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2019-04-09 06:14:53 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2019-04-09 06:14:53 (GMT)
commit799edfed201e47b5d16fa811ffc77231695000d7 (patch)
tree5f539bb5498a594db48299fac059f72bcd92df9c /src/gui/core/theme.c
parent010c4d4c07d19ff3f50d0f3caa9fc519ec17df14 (diff)
Introduced a new theme format.
Diffstat (limited to 'src/gui/core/theme.c')
-rw-r--r--src/gui/core/theme.c294
1 files changed, 133 insertions, 161 deletions
diff --git a/src/gui/core/theme.c b/src/gui/core/theme.c
index 77eff7f..83bcf4e 100644
--- a/src/gui/core/theme.c
+++ b/src/gui/core/theme.c
@@ -39,22 +39,16 @@
#include <i18n.h>
+#include "../theme.h"
#include "../../common/extstr.h"
#include "../../common/xdg.h"
#include "../../core/logs.h"
-#include "../../core/params.h"
#include "../../plugins/pglist.h"
-/* Parcourt tous les répertoires connus pour trouver un thème. */
-static bool browse_themes_directories(GdkScreen *, 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);
-
-/* Ajoute les définitions CSS à partir d'un chemin donné. */
-static bool load_css_content(GdkScreen *, const char *, gboolean);
+/* Parcourt un répertoire donné à la recherche de thèmes. */
+static void look_for_editor_themes(const char *);
/* Parcourt tous les greffons à la recherche de définitions CSS. */
static bool extend_with_plugins_themes(GdkScreen *, gboolean);
@@ -72,56 +66,15 @@ static const char *_themes_directories[] = {
};
+/* Liste de thèmes utilisables */
+static GEditorTheme **_themes = NULL;
+static size_t _theme_count = 0;
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Charge le thème GTK pour les composants spécifiques. *
-* *
-* Retour : true ou false selon le bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool load_extra_gtk_theme(void)
-{
- bool result; /* Bilan à faire remonter */
- const char *name; /* Nom du thème recherché */
- GdkScreen *screen; /* Ecran(s) concerné(s) */
- GtkSettings *settings; /* Propriétés du système */
- gboolean dark; /* Envie d'un thème sombre ? */
-
- result = false;
-
- if (!g_generic_config_get_value(get_main_configuration(), MPK_INTERNAL_THEME, &name))
- goto legt_done;
-
- screen = gdk_screen_get_default();
-
- settings = gtk_settings_get_for_screen(screen);
-
- g_object_get(settings, "gtk-application-prefer-dark-theme", &dark, NULL);
-
- result = browse_themes_directories(screen, name, dark);
-
- if (result)
- result = extend_with_plugins_themes(screen, dark);
-
- legt_done:
-
- return result;
-
-}
-
/******************************************************************************
* *
-* Paramètres : screen = écran visé par le chargement d'un thème. *
-* name = nom du thème recherché, et donc de son répertoire. *
-* dark = indique une préférence pour la variante foncée. *
+* Paramètres : - *
* *
* Description : Parcourt tous les répertoires connus pour trouver un thème. *
* *
@@ -131,15 +84,12 @@ bool load_extra_gtk_theme(void)
* *
******************************************************************************/
-static bool browse_themes_directories(GdkScreen *screen, const char *name, gboolean dark)
+void load_all_themes(void)
{
- bool result; /* Bilan à renvoyer */
char *suffix; /* Fin du répertoire personnel */
char *owndir; /* Thèmes personnels ? */
const char **iter; /* Boucle de parcours */
- result = false;
-
/* Répertoire de l'utilisateur en premier ! */
suffix = strdup("chrysalide");
@@ -152,74 +102,70 @@ static bool browse_themes_directories(GdkScreen *screen, const char *name, gbool
if (owndir != NULL)
{
- result = look_for_named_theme(screen, owndir, name, dark);
-
+ look_for_editor_themes(owndir);
free(owndir);
-
}
/* 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);
-
- return result;
+ for (iter = _themes_directories; *iter != NULL; iter++)
+ look_for_editor_themes(*iter);
}
/******************************************************************************
* *
-* Paramètres : screen = écran visé par le chargement d'un thème. *
-* 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. *
+* Paramètres : dirname = chemin du répertoire où effectuer des recherches. *
* *
-* Description : Parcourt un répertoire donné à la recherche d'un thème. *
+* Description : Parcourt un répertoire donné à la recherche de thèmes. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const char *name, gboolean dark)
+static void look_for_editor_themes(const char *dirname)
{
- bool result; /* Bilan à 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 */
int count; /* Nombre de fichiers trouvés */
int i; /* Boucle de parcours */
+ struct dirent *entry; /* Raccourci d'usage */
+ int ret; /* Bilan d'un appel */
char *filename; /* Chemin d'accès constitué */
+ GEditorTheme *theme; /* Nouveau thème valide */
- result = false;
-
- ret = asprintf(&path, "%s" G_DIR_SEPARATOR_S "%s", dirname, name);
- if (ret == -1) goto lfnt_done;
+ dirfd = open(dirname, O_RDONLY | O_DIRECTORY);
+ if (dirfd == -1) goto not_found;
- dirfd = open(path, O_RDONLY | O_DIRECTORY);
- if (dirfd == -1) goto lfnt_not_found;
+ count = scandirat(dirfd, ".", &namelist, NULL, alphasort);
- int keep_css_only(const struct dirent *entry)
+ for (i = 0; i < count; i++)
{
- return (entry->d_type == DT_REG
- && endswith(entry->d_name, ".css")
- && !endswith(entry->d_name, "-dark.css") ? 1 : 0);
+ entry = namelist[i];
- }
+ if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+ continue;
- count = scandirat(dirfd, ".", &namelist, keep_css_only, alphasort);
+ ret = asprintf(&filename, "%s%s%s", dirname, G_DIR_SEPARATOR_S, entry->d_name);
+ if (ret == -1) continue;
- result = (count > 0);
+ if (entry->d_type == DT_DIR)
+ look_for_editor_themes(filename);
- for (i = 0; i < count && result; i++)
- {
- ret = asprintf(&filename, "%s%s%s", path, G_DIR_SEPARATOR_S, namelist[i]->d_name);
- if (ret == -1) continue;
+ else if (entry->d_type == DT_REG)
+ {
+ theme = g_editor_theme_new(filename, true);
- result = load_css_content(screen, filename, dark);
+ if (theme != NULL)
+ {
+ _themes = realloc(_themes, ++_theme_count * sizeof(GEditorTheme *));
+ _themes[_theme_count - 1] = theme;
+ }
+
+ }
free(filename);
@@ -230,11 +176,80 @@ static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const c
close(dirfd);
- lfnt_not_found:
+ not_found:
- free(path);
+ ;
- lfnt_done:
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Décharge tous les thèmes référencés en mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void unload_all_themes(void)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < _theme_count; i++)
+ g_object_unref(G_OBJECT(_themes[i]));
+
+ if (_themes != NULL)
+ free(_themes);
+
+ _theme_count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : name = désignation du thème GTK à charger. *
+* *
+* Description : Charge le thème GTK pour les composants spécifiques. *
+* *
+* Retour : true ou false selon le bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool apply_gtk_theme(const char *name)
+{
+ bool result; /* Bilan à faire remonter */
+ size_t i; /* Boucle de parcours */
+ GdkScreen *screen; /* Ecran(s) concerné(s) */
+ GtkSettings *settings; /* Propriétés du système */
+ gboolean dark; /* Envie d'un thème sombre ? */
+
+ result = false;
+
+ for (i = 0; i < _theme_count; i++)
+ if (strcmp(name, g_editor_theme_get_name(_themes[i])) == 0)
+ {
+ result = true;
+ break;
+ }
+
+ if (result)
+ {
+ screen = gdk_screen_get_default();
+
+ settings = gtk_settings_get_for_screen(screen);
+
+ g_object_get(settings, "gtk-application-prefer-dark-theme", &dark, NULL);
+
+ g_editor_theme_load(_themes[i], screen, dark);
+
+ }
return result;
@@ -255,16 +270,12 @@ static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const c
* *
******************************************************************************/
-static bool load_css_content(GdkScreen *screen, const char *path, gboolean dark)
+GtkCssProvider *load_css_content(GdkScreen *screen, const char *path)
{
- bool result; /* Bilan à renvoyer */
- GtkCssProvider *provider; /* Nouveau fournisseur CSS */
- char *dark_path; /* Version sombre du chemin */
+ GtkCssProvider *result; /* Fournisseur à renvoyer */
GFile *file; /* Fichier à charger */
GError *error; /* Relevé d'éventuelles erreurs*/
- result = false;
-
/**
* Comme GTK exporte les images sous forme de données encodées en base 64
* (cf. gtk_css_image_surface_print()) et ne sait pas recharger ensuite
@@ -278,75 +289,32 @@ static bool load_css_content(GdkScreen *screen, const char *path, gboolean dark)
* Ce constat est valable pour la version 3.22.11-1 de Debian, au moins.
*/
- if (dark)
- {
- provider = gtk_css_provider_new();
-
- error = NULL;
+ result = gtk_css_provider_new();
- dark_path = strdup(path);
- dark_path = strrpl(dark_path, ".css", "-dark.css");
+ error = NULL;
- if (strstr(path, "://") != NULL)
- file = g_file_new_for_uri(dark_path);
- else
- file = g_file_new_for_path(dark_path);
+ assert(strstr(path, "://") != NULL);
- gtk_css_provider_load_from_file(provider, file, &error);
+ file = g_file_new_for_uri(path);
- g_object_unref(G_OBJECT(file));
+ gtk_css_provider_load_from_file(result, file, &error);
- if (error == NULL)
- {
- log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), dark_path);
+ g_object_unref(G_OBJECT(file));
- gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider),
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-
- result = true;
-
- }
- else
- g_error_free(error);
-
- free(dark_path);
+ if (error == NULL)
+ {
+ log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), path);
- g_object_unref(G_OBJECT(provider));
+ gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(result),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
-
- if (!result)
+ else
{
- provider = gtk_css_provider_new();
-
- error = NULL;
-
- 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));
+ log_variadic_message(LMT_ERROR, _("Failed to load CSS definitions from '%s'"), path);
+ g_error_free(error);
- if (error == NULL)
- {
- log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), path);
-
- gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider),
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-
- result = true;
-
- }
- else
- {
- log_variadic_message(LMT_ERROR, _("Failed to load CSS definitions from '%s'"), path);
- g_error_free(error);
- }
-
- g_object_unref(G_OBJECT(provider));
+ g_object_unref(G_OBJECT(result));
}
@@ -374,6 +342,7 @@ static bool extend_with_plugins_themes(GdkScreen *screen, gboolean dark)
char **resources; /* Fichiers supplémentaires */
size_t count; /* Nombre de ces fichiers */
size_t i; /* Boucle de parcours */
+ GtkCssProvider *provider; /* Nouveau fournisseur CSS */
result = true;
@@ -384,8 +353,11 @@ static bool extend_with_plugins_themes(GdkScreen *screen, gboolean dark)
for (i = 0; i < count && result; i++)
{
- result = load_css_content(screen, resources[i], dark);
+ provider = load_css_content(screen, resources[i]);
+ g_clear_object(&provider);
+
free(resources[i]);
+
}
if (resources != NULL)