[Xfce4-commits] [xfce/xfce4-settings] 01/02: Show Gtk+ theme palettes in the appearance dialog

noreply at xfce.org noreply at xfce.org
Mon Feb 16 00:48:16 CET 2015


This is an automated email from the git hooks/post-receive script.

ochosi pushed a commit to branch master
in repository xfce/xfce4-settings.

commit 0ac39335e4f9cafefc526dd0280d61062a8d35c5
Author: Simon Steinbeiss <simon.steinbeiss at elfenbeinturm.at>
Date:   Mon Feb 16 00:46:33 2015 +0100

    Show Gtk+ theme palettes in the appearance dialog
---
 dialogs/appearance-settings/main.c |  379 ++++++++++++++++++++++++++++++++++--
 1 file changed, 366 insertions(+), 13 deletions(-)

diff --git a/dialogs/appearance-settings/main.c b/dialogs/appearance-settings/main.c
index 42dab07..0d744b8 100644
--- a/dialogs/appearance-settings/main.c
+++ b/dialogs/appearance-settings/main.c
@@ -31,7 +31,10 @@
 #include <sys/wait.h>
 #endif
 
+#include <unistd.h>
 #include <glib.h>
+#include <glib/gstdio.h>
+#include <fcntl.h>
 #include <gtk/gtk.h>
 
 #include <libxfce4ui/libxfce4ui.h>
@@ -50,6 +53,16 @@
 /* Increase this number if new gtk settings have been added */
 #define INITIALIZE_UINT (1)
 
+#define COLOR_SCHEME_SYMBOL ((gpointer) 1)
+#define GTK_RC_TOKEN_FG ((gpointer) 2)
+#define GTK_RC_TOKEN_BG ((gpointer) 3)
+#define GTK_RC_TOKEN_NORMAL ((gpointer) 4)
+#define GTK_RC_TOKEN_SELECTED ((gpointer) 5)
+
+gchar *gtkrc_get_color_scheme_for_theme (const gchar *gtkrc_filename);
+gboolean color_scheme_parse_colors (const gchar *scheme, GdkColor *colors);
+static GdkPixbuf *theme_create_preview (GdkColor *colors);
+
 enum
 {
     COLUMN_THEME_PREVIEW,
@@ -67,6 +80,13 @@ enum
     N_RGBA_COLUMNS
 };
 
+enum {
+	COLOR_FG,
+	COLOR_BG,
+	COLOR_SELECTED_BG,
+	NUM_SYMBOLIC_COLORS
+};
+
 /* String arrays with the settings in combo boxes */
 static const gchar* toolbar_styles_array[] =
 {
@@ -125,6 +145,307 @@ compute_xsettings_dpi (GtkWidget *widget)
     return dpi;
 }
 
+/* Try to retrieve the color scheme and alternatively parse the colors from the gtkrc */
+gchar *
+gtkrc_get_color_scheme_for_theme (const gchar *gtkrc_filename)
+{
+    gint file = -1;
+    GString *result_string = g_string_new("");
+    GString *fallback_string = g_string_new("");
+    GString *tmp_string = g_string_new("");
+    gchar *result = NULL;
+    gboolean bg_normal = FALSE;
+    gboolean bg_selected = FALSE;
+    gboolean fg_normal = FALSE;
+    GSList *files = NULL;
+    GSList *read_files = NULL;
+    GTokenType token;
+    GScanner *scanner = gtk_rc_scanner_new ();
+
+    g_return_val_if_fail (gtkrc_filename != NULL, "");
+
+    g_scanner_scope_add_symbol (scanner, 0, "gtk_color_scheme", COLOR_SCHEME_SYMBOL);
+    g_scanner_scope_add_symbol (scanner, 0, "gtk-color-scheme", COLOR_SCHEME_SYMBOL);
+    g_scanner_scope_add_symbol (scanner, 0, "fg", GTK_RC_TOKEN_FG);
+    g_scanner_scope_add_symbol (scanner, 0, "bg", GTK_RC_TOKEN_BG);
+    g_scanner_scope_add_symbol (scanner, 0, "NORMAL", GTK_RC_TOKEN_NORMAL);
+    g_scanner_scope_add_symbol (scanner, 0, "SELECTED", GTK_RC_TOKEN_SELECTED);
+
+    files = g_slist_prepend (files, g_strdup (gtkrc_filename));
+    while (files != NULL)
+    {
+        gchar *filename = files->data;
+        files = g_slist_delete_link (files, files);
+
+        if (filename == NULL)
+            continue;
+
+        if (g_slist_find_custom (read_files, filename, (GCompareFunc) strcmp))
+        {
+            g_warning ("Recursion in the gtkrc detected!");
+            g_free (filename);
+            continue; /* skip this file since we've done it before... */
+        }
+
+        read_files = g_slist_prepend (read_files, filename);
+
+        file = g_open (filename, O_RDONLY);
+        if (file == -1)
+            g_warning ("Could not open file \"%s\"", filename);
+        else
+        {
+            g_scanner_input_file (scanner, file);
+            while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
+            {
+                /* Scan the gtkrc file for the gtk-color-scheme */
+                if (GINT_TO_POINTER (token) == COLOR_SCHEME_SYMBOL)
+                {
+                    if (g_scanner_get_next_token (scanner) == '=')
+                    {
+                        token = g_scanner_get_next_token (scanner);
+                        if (token == G_TOKEN_STRING)
+                        {
+                            g_string_append_printf(result_string, "\n%s", scanner->value.v_string);
+                        }
+                        bg_normal = g_strstr_len(result_string->str, -1, "bg_color") != NULL;
+                        bg_selected = g_strstr_len(result_string->str, -1, "selected_bg_color") != NULL;
+                        fg_normal = g_strstr_len(result_string->str, -1, "fg_color") != NULL;
+                    }
+                }
+                /* Scan the gtkrc file for first occurences of bg[NORMAL], bg[SELECTED] and fg[NORMAL] in case
+                 * it doesn't provide a gtk-color-scheme */
+                if (result_string->len == 0)
+                {
+                    if (GINT_TO_POINTER (token) == GTK_RC_TOKEN_BG)
+                    {
+                        if (g_scanner_get_next_token (scanner) == G_TOKEN_LEFT_BRACE)
+                        {
+                            /* bg[SELECTED] */
+                            if (GINT_TO_POINTER (token = g_scanner_get_next_token (scanner)) == GTK_RC_TOKEN_SELECTED
+                                && g_scanner_get_next_token (scanner) == G_TOKEN_RIGHT_BRACE
+                                && g_scanner_get_next_token (scanner) == '=')
+                            {
+                                token = g_scanner_get_next_token (scanner);
+                                /* Parse colors in hex #rrggbb format */
+                                if (token == G_TOKEN_STRING)
+                                {
+                                    if (!g_strrstr (fallback_string->str, "selected_bg_color"))
+                                    {
+                                        g_string_append_printf(fallback_string, "\nselected_bg_color:%s", scanner->value.v_string);
+                                        bg_selected = TRUE;
+                                    }
+                                }
+                                /* Parse colors in { r, g, b } format */
+                                else if (token == G_TOKEN_LEFT_CURLY)
+                                {
+                                    if (!g_strrstr (fallback_string->str, "selected_bg_color"))
+                                    {
+                                        g_string_erase(tmp_string, 0, -1);
+                                        while (token != G_TOKEN_RIGHT_CURLY)
+                                        {
+                                            token = g_scanner_get_next_token (scanner);
+                                            if (token == G_TOKEN_FLOAT)
+                                                g_string_append_printf(tmp_string, "%02x", (uint) (scanner->value.v_float*255));
+                                        }
+                                        g_string_append_printf(fallback_string, "\nselected_bg_color:#%s", tmp_string->str);
+                                        bg_selected = TRUE;
+                                    }
+                                }
+                            }
+                            /* bg[NORMAL] */
+                            else if (GINT_TO_POINTER (token) == GTK_RC_TOKEN_NORMAL
+                                     && g_scanner_get_next_token (scanner) == G_TOKEN_RIGHT_BRACE
+                                     && g_scanner_get_next_token (scanner) == '=')
+                            {
+                                token = g_scanner_get_next_token (scanner);
+                                /* Parse colors in hex #rrggbb format */
+                                if (token == G_TOKEN_STRING)
+                                {
+                                    if (!g_strrstr (fallback_string->str, "bg_color"))
+                                    {
+                                        g_string_append_printf(fallback_string, "\nbg_color:%s", scanner->value.v_string);
+                                        bg_normal = TRUE;
+                                    }
+                                }
+                                /* Parse colors in { r, g, b } format */
+                                else if (token == G_TOKEN_LEFT_CURLY)
+                                {
+                                    if (!g_strrstr (fallback_string->str, "bg_color"))
+                                    {
+                                        g_string_erase(tmp_string, 0, -1);
+                                        while (token != G_TOKEN_RIGHT_CURLY)
+                                        {
+                                            token = g_scanner_get_next_token (scanner);
+                                            if (token == G_TOKEN_FLOAT)
+                                                g_string_append_printf(tmp_string, "%02x", (uint) (scanner->value.v_float*255));
+                                        }
+                                        g_string_append_printf(fallback_string, "\nbg_color:#%s", tmp_string->str);
+                                        bg_normal = TRUE;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    else if (GINT_TO_POINTER (token) == GTK_RC_TOKEN_FG)
+                    {
+                        /* fg[NORMAL] */
+                        if (g_scanner_get_next_token (scanner) == G_TOKEN_LEFT_BRACE
+                            && GINT_TO_POINTER (token = g_scanner_get_next_token (scanner)) == GTK_RC_TOKEN_NORMAL
+                                && g_scanner_get_next_token (scanner) == G_TOKEN_RIGHT_BRACE
+                                && g_scanner_get_next_token (scanner) == '=')
+                        {
+                            token = g_scanner_get_next_token (scanner);
+                            /* Parse colors in hex #rrggbb format */
+                            if (token == G_TOKEN_STRING)
+                            {
+                                if (!g_strrstr (fallback_string->str, "fg_color"))
+                                {
+                                    g_string_append_printf(fallback_string, "\nfg_color:%s", scanner->value.v_string);
+                                    fg_normal = TRUE;
+                                }
+                            }
+                            /* Parse colors in { r, g, b } format */
+                            else if (token == G_TOKEN_LEFT_CURLY)
+                            {
+                                if (!g_strrstr (fallback_string->str, "fg_color"))
+                                {
+                                    g_string_erase(tmp_string, 0, -1);
+                                    while (token != G_TOKEN_RIGHT_CURLY)
+                                    {
+                                        token = g_scanner_get_next_token (scanner);
+                                        if (token == G_TOKEN_FLOAT)
+                                            g_string_append_printf(tmp_string, "%02x", (uint) (scanner->value.v_float*255));
+                                    }
+                                    g_string_append_printf(fallback_string, "\nfg_color:#%s", tmp_string->str);
+                                    fg_normal = TRUE;
+                                }
+                            }
+                        }
+                    }
+                }
+                /* Check whether we can stop parsing because all colors have been retrieved somehow */
+                if (bg_normal && bg_selected && fg_normal)
+                    break;
+            }
+        close (file);
+        }
+    }
+
+    g_slist_foreach (read_files, (GFunc) g_free, NULL);
+    g_slist_free (read_files);
+
+    g_scanner_destroy (scanner);
+
+    /* Use the fallback colors parsed from the theme if gtk-color-scheme is not defined */
+    /*
+    if (!result)
+        result = fallback;
+    */
+    if (result_string->len == 0)
+        result = g_strdup(fallback_string->str);
+    else
+        result = g_strdup(result_string->str);
+
+    g_string_free(result_string, TRUE);
+    g_string_free(fallback_string, TRUE);
+    g_string_free(tmp_string, TRUE);
+
+    return result;
+}
+
+gboolean
+color_scheme_parse_colors (const gchar *scheme, GdkColor *colors)
+{
+    gchar **color_scheme_strings, **color_scheme_pair, *current_string;
+    gboolean found = FALSE;
+    gint i;
+
+    if (!scheme || !strcmp (scheme, ""))
+        return FALSE;
+
+    /* Initialise the array, fallback color is white */
+    for (i = 0; i < NUM_SYMBOLIC_COLORS; i++)
+        colors[i].red = colors[i].green = colors[i].blue = 65535.0;
+
+    /* The color scheme string consists of name:color pairs, separated by
+     * either semicolons or newlines, so first we split the string up by delimiter */
+    if (g_strrstr (scheme, ";"))
+        color_scheme_strings = g_strsplit (scheme, ";", 0);
+    else
+        color_scheme_strings = g_strsplit (scheme, "\n", 0);
+
+    /* Loop through the name:color pairs, and save the color if we recognise the name */
+    i = 0;
+    while ((current_string = color_scheme_strings[i++]))
+    {
+        color_scheme_pair = g_strsplit (current_string, ":", 0);
+
+        if (color_scheme_pair[0] != NULL && color_scheme_pair[1] != NULL)
+        {
+            g_strstrip (color_scheme_pair[0]);
+            g_strstrip (color_scheme_pair[1]);
+
+            if (!strcmp ("fg_color", color_scheme_pair[0]))
+            {
+              gdk_color_parse (color_scheme_pair[1], &colors[COLOR_FG]);
+              found = TRUE;
+            }
+            else if (!strcmp ("bg_color", color_scheme_pair[0]))
+            {
+              gdk_color_parse (color_scheme_pair[1], &colors[COLOR_BG]);
+              found = TRUE;
+            }
+            else if (!strcmp ("selected_bg_color", color_scheme_pair[0]))
+            {
+              gdk_color_parse (color_scheme_pair[1], &colors[COLOR_SELECTED_BG]);
+              found = TRUE;
+            }
+        }
+
+        g_strfreev (color_scheme_pair);
+    }
+
+    g_strfreev (color_scheme_strings);
+
+    return found;
+}
+
+static GdkPixbuf *
+theme_create_preview (GdkColor *colors)
+{
+    GdkPixbuf *theme_preview;
+    GdkPixmap *drawable;
+    GdkColormap *cmap = gdk_colormap_get_system ();
+    cairo_t *cr;
+    gint width = 44;
+    gint height = 22;
+
+    drawable = gdk_pixmap_new (NULL, width, height, 24);
+    cr = gdk_cairo_create (drawable);
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+
+    /* Draw three rectangles showcasing the background, foreground and selected background colors */
+    cairo_rectangle (cr, 0, 0, 16, 22);
+    cairo_set_source_rgb (cr, colors[COLOR_BG].red / 65535.0, colors[COLOR_BG].green / 65535.0, colors[COLOR_BG].blue / 65535.0);
+    cairo_fill (cr);
+
+    cairo_rectangle (cr, 15, 0, 30, 22);
+    cairo_set_source_rgb (cr, colors[COLOR_FG].red / 65535.0, colors[COLOR_FG].green / 65535.0, colors[COLOR_FG].blue / 65535.0);
+    cairo_fill (cr);
+
+    cairo_rectangle (cr, 29, 0, 42, 22);
+    cairo_set_source_rgb (cr, colors[COLOR_SELECTED_BG].red / 65535.0, colors[COLOR_SELECTED_BG].green / 65535.0, colors[COLOR_SELECTED_BG].blue / 65535.0);
+    cairo_fill (cr);
+
+    theme_preview = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+    gdk_pixbuf_get_from_drawable (theme_preview, drawable, cmap, 0, 0, 0, 0, width, height);
+
+    g_object_unref (drawable);
+    cairo_destroy (cr);
+
+    return theme_preview;
+}
+
 static void
 cb_theme_tree_selection_changed (GtkTreeSelection *selection,
                                  const gchar      *property)
@@ -392,7 +713,7 @@ appearance_settings_load_icon_themes (GtkListStore *list_store,
                         cache_tooltip = g_strdup_printf (_("Warning: this icon theme has no cache file. You can create this by "
                                                            "running <i>gtk-update-icon-cache %s/%s/</i> in a terminal emulator."),
                                                          icon_theme_dirs[i], file);
-		    else
+                    else
                         cache_tooltip = NULL;
 
                     /* Append icon theme to the list store */
@@ -462,6 +783,9 @@ appearance_settings_load_ui_themes (GtkListStore *list_store,
     gchar        *comment_escaped;
     gint          i;
     GSList       *check_list = NULL;
+    gchar        *color_scheme = NULL;
+    GdkPixbuf    *preview;
+    GdkColor      colors[NUM_SYMBOLIC_COLORS];
 
     /* Determine current theme */
     active_theme_name = xfconf_channel_get_string (xsettings_channel, "/Net/ThemeName", "Default");
@@ -516,9 +840,22 @@ appearance_settings_load_ui_themes (GtkListStore *list_store,
                     comment_escaped = NULL;
                 }
 
+                /* Retrieve the color values from the theme, parse them and create the palette preview pixbuf */
+                color_scheme = gtkrc_get_color_scheme_for_theme (gtkrc_filename);
+                if (color_scheme_parse_colors (color_scheme, colors))
+                    preview = theme_create_preview (colors);
+                /* If the color scheme parsing doesn't return anything useful, show a blank pixbuf */
+                else
+                {
+                    preview = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 44, 22);
+                    gdk_pixbuf_fill (preview, 0x00);
+                }
+                g_free (color_scheme);
+
                 /* Append ui theme to the list store */
                 gtk_list_store_append (list_store, &iter);
                 gtk_list_store_set (list_store, &iter,
+                                    COLUMN_THEME_PREVIEW, preview,
                                     COLUMN_THEME_NAME, file,
                                     COLUMN_THEME_DISPLAY_NAME, theme_name,
                                     COLUMN_THEME_COMMENT, comment_escaped, -1);
@@ -527,6 +864,7 @@ appearance_settings_load_ui_themes (GtkListStore *list_store,
                 if (G_LIKELY (index_file != NULL))
                     xfce_rc_close (index_file);
                 g_free (comment_escaped);
+                g_object_unref (preview);
 
                 /* Check if this is the active theme, if so, select it */
                 if (G_UNLIKELY (g_utf8_collate (file, active_theme_name) == 0))
@@ -865,23 +1203,26 @@ appearance_settings_dialog_configure_widgets (GtkBuilder *builder)
     gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (object), COLUMN_THEME_COMMENT);
     gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (object), TRUE);
 
-    renderer = gtk_cell_renderer_pixbuf_new ();
-
+    /* Single-column layout */
     column = gtk_tree_view_column_new ();
+
+    /* Icon Previews */
+    renderer = gtk_cell_renderer_pixbuf_new ();
     gtk_tree_view_column_pack_start (column, renderer, FALSE);
-    gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", 0, NULL);
+    gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", COLUMN_THEME_PREVIEW, NULL);
     gtk_tree_view_append_column (GTK_TREE_VIEW (object), column);
 
+    /* Theme Name and Description */
     renderer = gtk_cell_renderer_text_new ();
-    gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (object), 1, "", renderer, "markup", COLUMN_THEME_DISPLAY_NAME, NULL);
+    gtk_tree_view_column_pack_start (column, renderer, TRUE);
+    gtk_tree_view_column_set_attributes (column, renderer, "markup", COLUMN_THEME_DISPLAY_NAME, NULL);
+    g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
 
+    /* Warning Icon */
     renderer = gtk_cell_renderer_pixbuf_new ();
-    g_object_set (G_OBJECT (renderer), "icon-name", GTK_STOCK_DIALOG_WARNING, NULL);
-
-    column = gtk_tree_view_get_column (GTK_TREE_VIEW (object), 1);
-
     gtk_tree_view_column_pack_start (column, renderer, FALSE);
-    gtk_tree_view_column_add_attribute (column, renderer, "visible", COLUMN_THEME_NO_CACHE);
+    gtk_tree_view_column_set_attributes (column, renderer, "visible", COLUMN_THEME_NO_CACHE, NULL);
+    g_object_set (G_OBJECT (renderer), "icon-name", GTK_STOCK_DIALOG_WARNING, NULL);
 
     appearance_settings_load_icon_themes (list_store, GTK_TREE_VIEW (object));
 
@@ -899,13 +1240,25 @@ appearance_settings_dialog_configure_widgets (GtkBuilder *builder)
     /* Gtk (UI) themes */
     object = gtk_builder_get_object (builder, "gtk_theme_treeview");
 
-    list_store = gtk_list_store_new (N_THEME_COLUMNS - 1, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    list_store = gtk_list_store_new (N_THEME_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
     gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list_store), COLUMN_THEME_DISPLAY_NAME, GTK_SORT_ASCENDING);
     gtk_tree_view_set_model (GTK_TREE_VIEW (object), GTK_TREE_MODEL (list_store));
     gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (object), COLUMN_THEME_COMMENT);
 
-    renderer = gtk_cell_renderer_text_new();
-    gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (object), 0, "", renderer, "text", COLUMN_THEME_DISPLAY_NAME, NULL);
+    /* Single-column layout */
+    column = gtk_tree_view_column_new ();
+
+    /* Icon Previews */
+    renderer = gtk_cell_renderer_pixbuf_new ();
+    gtk_tree_view_column_pack_start (column, renderer, FALSE);
+    gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", COLUMN_THEME_PREVIEW, NULL);
+    gtk_tree_view_append_column (GTK_TREE_VIEW (object), column);
+
+    /* Theme Name and Description */
+    renderer = gtk_cell_renderer_text_new ();
+    gtk_tree_view_column_pack_start (column, renderer, TRUE);
+    gtk_tree_view_column_set_attributes (column, renderer, "text", COLUMN_THEME_DISPLAY_NAME, NULL);
+    g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
 
     appearance_settings_load_ui_themes (list_store, GTK_TREE_VIEW (object));
 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list