summaryrefslogtreecommitdiff
path: root/src/gui/core/theme.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/core/theme.c')
-rw-r--r--src/gui/core/theme.c260
1 files changed, 260 insertions, 0 deletions
diff --git a/src/gui/core/theme.c b/src/gui/core/theme.c
new file mode 100644
index 0000000..7e81497
--- /dev/null
+++ b/src/gui/core/theme.c
@@ -0,0 +1,260 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * theme.c - prototypes pour l'ajout d'extensions au thème GTK
+ *
+ * Copyright (C) 2009-2012 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "theme.h"
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#include <config.h>
+#include <i18n.h>
+
+
+#include "../panels/log.h"
+#include "../../common/extstr.h"
+#include "../../common/xdg.h"
+#include "../../core/params.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);
+
+
+/* Répertoires de recherche */
+static const char *_themes_directories[] = {
+
+ PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "themes",
+ PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "themes",
+ NULL
+
+};
+
+
+
+/******************************************************************************
+* *
+* 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);
+
+ if (dark)
+ result = browse_themes_directories(screen, name, true);
+
+ if (!result)
+ result = browse_themes_directories(screen, name, false);
+
+ legt_done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : screen = écran concerné par les éventuels chargements. *
+* 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. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool browse_themes_directories(GdkScreen *screen, const char *name, gboolean dark)
+{
+ bool result; /* Bilan à faire remonter */
+ 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");
+ suffix = stradd(suffix, G_DIR_SEPARATOR_S);
+ suffix = stradd(suffix, "themes");
+
+ owndir = get_xdg_config_dir(suffix);
+
+ free(suffix);
+
+ if (owndir != NULL)
+ {
+ result = look_for_named_theme(screen, owndir, name, dark);
+
+ 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;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : screen = écran concerné par les éventuels chargements. *
+* 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. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const char *name, gboolean dark)
+{
+ bool result; /* Bilan à faire remonter */
+ 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 */
+ char *filename; /* Chemin d'accès constitué */
+ GtkCssProvider *provider; /* Nouveau fournisseur CSS */
+ GError *error; /* Relevé d'éventuelles erreurs*/
+
+ result = false;
+
+ ret = asprintf(&path, "%s" G_DIR_SEPARATOR_S "%s", dirname, name);
+ if (ret == -1) goto lfnt_done;
+
+ 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
+ && endswith(entry->d_name, ".css")
+ && !endswith(entry->d_name, "-dark.css") ? 1 : 0);
+
+ }
+
+ count = scandirat(dirfd, ".", &namelist, dark ? keep_dark_css_only : 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;
+
+ provider = gtk_css_provider_new();
+
+ error = NULL;
+
+ gtk_css_provider_load_from_path(provider, filename, &error);
+
+ if (error == NULL)
+ {
+ log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), filename);
+
+ 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'"), filename);
+ g_error_free(error);
+ }
+
+ g_object_unref(G_OBJECT(provider));
+
+ free(filename);
+
+ }
+
+ if (count > 0)
+ free(namelist);
+
+ close(dirfd);
+
+ lfnt_not_found:
+
+ free(path);
+
+ lfnt_done:
+
+ return result;
+
+}