[yelp/yelp-3-0] [yelp-settings] Implementing YelpSettings API for libyelp



commit b46d3d6d479ae34b4f5fb688e10d51e57fa068f3
Author: Shaun McCance <shaunm gnome org>
Date:   Mon Sep 28 21:48:02 2009 -0500

    [yelp-settings] Implementing YelpSettings API for libyelp

 libyelp/Makefile.am     |   20 +-
 libyelp/yelp-settings.c |  808 +++++++++++++++++++++++++++++++++++++++++++
 libyelp/yelp-settings.h |  113 ++++++
 src/yelp-settings.c     |  865 -----------------------------------------------
 src/yelp-settings.h     |  102 ------
 tests/Makefile.am       |    4 +
 tests/test-settings.c   |  334 ++++++++++++++++++
 7 files changed, 1270 insertions(+), 976 deletions(-)
---
diff --git a/libyelp/Makefile.am b/libyelp/Makefile.am
index ad40c35..c1946a8 100644
--- a/libyelp/Makefile.am
+++ b/libyelp/Makefile.am
@@ -1,15 +1,17 @@
 noinst_LTLIBRARIES = libyelp.la
 
-libyelp_la_SOURCES =		\
-	yelp-debug.c		\
-	yelp-document.c		\
-	yelp-location-entry.c	\
-	yelp-simple-document.c	\
-	yelp-uri.c		\
+libyelp_la_SOURCES =				\
+	yelp-debug.c				\
+	yelp-document.c				\
+	yelp-location-entry.c			\
+	yelp-settings.c				\
+	yelp-simple-document.c			\
+	yelp-uri.c				\
 	yelp-view.c
 
-libyelp_la_CFLAGS =		\
-	$(YELP_CFLAGS)
+libyelp_la_CFLAGS =				\
+	$(YELP_CFLAGS)				\
+	-DGDU_ICON_PATH=\"$(GDU_ICON_PATH)\"
 
-libyelp_la_LIBADD =		\
+libyelp_la_LIBADD =				\
 	$(YELP_LIBS)
diff --git a/libyelp/yelp-settings.c b/libyelp/yelp-settings.c
new file mode 100644
index 0000000..b1cb232
--- /dev/null
+++ b/libyelp/yelp-settings.c
@@ -0,0 +1,808 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2004-2009 Shaun McCance <shaunm gnome org>
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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.
+ *
+ * Author: Shaun McCance <shaunm gnome org>
+ */
+
+#include <stdarg.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "yelp-settings.h"
+
+struct _YelpSettingsPriv {
+    GMutex       *mutex;
+
+    gchar         colors[YELP_SETTINGS_NUM_COLORS][8];
+    gchar        *fonts[YELP_SETTINGS_NUM_FONTS];
+    gchar        *icons[YELP_SETTINGS_NUM_ICONS];
+    gint          icon_size;
+
+    GtkSettings  *gtk_settings;
+    GtkIconTheme *gtk_icon_theme;
+
+    gulong        gtk_theme_changed;
+    gulong        icon_theme_changed;
+};
+
+enum {
+    COLORS_CHANGED,
+    FONTS_CHANGED,
+    ICONS_CHANGED,
+    LAST_SIGNAL
+};
+static guint settings_signals[LAST_SIGNAL] = {0,};
+
+enum {  
+  PROP_0,
+  PROP_GTK_SETTINGS,
+  PROP_GTK_ICON_THEME
+};
+
+gchar *icon_names[YELP_SETTINGS_NUM_ICONS];
+
+G_DEFINE_TYPE (YelpSettings, yelp_settings, G_TYPE_OBJECT);
+#define GET_PRIV(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_SETTINGS, YelpSettingsPriv))
+
+static void           yelp_settings_class_init   (YelpSettingsClass    *klass);
+static void           yelp_settings_init         (YelpSettings         *settings);
+static void           yelp_settings_dispose      (GObject              *object);
+static void           yelp_settings_finalize     (GObject              *object);
+static void           yelp_settings_get_property (GObject              *object,
+						  guint                 prop_id,
+						  GValue               *value,
+						  GParamSpec           *pspec);
+static void           yelp_settings_set_property (GObject              *object,
+						  guint                 prop_id,
+						  const GValue         *value,
+						  GParamSpec           *pspec);
+
+static void           gtk_theme_changed          (GtkSettings          *gtk_settings,
+						  GParamSpec           *pspec,
+					          YelpSettings         *settings);
+static void           icon_theme_changed         (GtkIconTheme         *theme,
+						  YelpSettings         *settings);
+
+static void           rgb_to_hls                 (gdouble  r,
+						  gdouble  g,
+						  gdouble  b,
+						  gdouble *h,
+						  gdouble *l,
+						  gdouble *s);
+static void           hls_to_hex                 (gdouble  h,
+						  gdouble  l,
+						  gdouble  s,
+						  gchar    *str);
+
+/******************************************************************************/
+
+static void
+yelp_settings_class_init (YelpSettingsClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+    gint i;
+
+    object_class->dispose  = yelp_settings_dispose;
+    object_class->finalize = yelp_settings_finalize;
+    object_class->get_property = yelp_settings_get_property;
+    object_class->set_property = yelp_settings_set_property;
+
+    for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++) {
+	switch (i) {
+	case YELP_SETTINGS_ICON_BUG:
+	    icon_names[i] = "admon-bug";
+	    break;
+	case YELP_SETTINGS_ICON_CAUTION:
+	    icon_names[i] = "admon-caution";
+	    break;
+	case YELP_SETTINGS_ICON_IMPORTANT:
+	    icon_names[i] = "admon-important";
+	    break;
+	case YELP_SETTINGS_ICON_NOTE:
+	    icon_names[i] = "admon-note";
+	    break;
+	case YELP_SETTINGS_ICON_TIP:
+	    icon_names[i] = "admon-tip";
+	    break;
+	case YELP_SETTINGS_ICON_WARNING:
+	    icon_names[i] = "admon-warning";
+	    break;
+	default:
+	    g_assert_not_reached ();
+	}
+    }
+
+    g_object_class_install_property (object_class,
+                                     PROP_GTK_SETTINGS,
+                                     g_param_spec_object ("gtk-settings",
+							  _("GtkSettings"),
+							  _("A GtkSettings object to get settings from"),
+							  GTK_TYPE_SETTINGS,
+							  G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
+							  G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+    g_object_class_install_property (object_class,
+                                     PROP_GTK_ICON_THEME,
+                                     g_param_spec_object ("gtk-icon-theme",
+							  _("GtkIconTheme"),
+							  _("A GtkIconTheme object to get icons from"),
+							  GTK_TYPE_ICON_THEME,
+							  G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
+							  G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+    settings_signals[COLORS_CHANGED] =
+	g_signal_new ("colors-changed",
+		      G_OBJECT_CLASS_TYPE (klass),
+		      G_SIGNAL_RUN_LAST,
+		      0, NULL, NULL,
+		      g_cclosure_marshal_VOID__VOID,
+		      G_TYPE_NONE, 0);
+
+    settings_signals[FONTS_CHANGED] =
+	g_signal_new ("fonts-changed",
+		      G_OBJECT_CLASS_TYPE (klass),
+		      G_SIGNAL_RUN_LAST,
+		      0, NULL, NULL,
+		      g_cclosure_marshal_VOID__VOID,
+		      G_TYPE_NONE, 0);
+
+    settings_signals[ICONS_CHANGED] =
+	g_signal_new ("icons-changed",
+		      G_OBJECT_CLASS_TYPE (klass),
+		      G_SIGNAL_RUN_LAST,
+		      0, NULL, NULL,
+		      g_cclosure_marshal_VOID__VOID,
+		      G_TYPE_NONE, 0);
+
+    g_type_class_add_private (klass, sizeof (YelpSettingsPriv));
+}
+
+static void
+yelp_settings_init (YelpSettings *settings)
+{
+    gint i;
+
+    settings->priv = GET_PRIV (settings);
+    settings->priv->mutex = g_mutex_new ();
+    settings->priv->icon_size = 48;
+
+    for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++)
+	settings->priv->icons[i] = NULL;
+}
+
+static void
+yelp_settings_dispose (GObject *object)
+{
+    YelpSettings *settings = YELP_SETTINGS (object);
+
+    G_OBJECT_CLASS (yelp_settings_parent_class)->dispose (object);
+}
+
+static void
+yelp_settings_finalize (GObject *object)
+{
+    YelpSettings *settings = YELP_SETTINGS (object);
+
+    g_mutex_free (settings->priv->mutex);
+
+    G_OBJECT_CLASS (yelp_settings_parent_class)->finalize (object);
+}
+
+static void
+yelp_settings_get_property (GObject    *object,
+			    guint       prop_id,
+			    GValue     *value,
+			    GParamSpec *pspec)
+{
+    YelpSettings *settings = YELP_SETTINGS (object);
+
+    switch (prop_id) {
+    case PROP_GTK_SETTINGS:
+	g_value_set_object (value, settings->priv->gtk_settings);
+	break;
+    case PROP_GTK_ICON_THEME:
+	g_value_set_object (value, settings->priv->gtk_icon_theme);
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+static void
+yelp_settings_set_property (GObject      *object,
+			    guint         prop_id,
+			    const GValue *value,
+			    GParamSpec   *pspec)
+{
+    YelpSettings *settings = YELP_SETTINGS (object);
+
+    switch (prop_id) {
+    case PROP_GTK_SETTINGS:
+	if (settings->priv->gtk_settings) {
+	    g_signal_handler_disconnect (settings->priv->gtk_settings,
+					 settings->priv->gtk_theme_changed);
+	    g_object_unref (settings->priv->gtk_settings);
+	}
+	settings->priv->gtk_settings = g_value_get_object (value);
+	if (settings->priv->gtk_settings != NULL) {
+	    g_object_ref (settings->priv->gtk_settings);
+	    settings->priv->gtk_theme_changed =
+		g_signal_connect (settings->priv->gtk_settings,
+				  "notify::gtk-theme-name",
+				  (GCallback) gtk_theme_changed,
+				  settings);
+	    gtk_theme_changed (settings->priv->gtk_settings, NULL, settings);
+	}
+	else {
+	    settings->priv->gtk_theme_changed = 0;
+	}
+	break;
+    case PROP_GTK_ICON_THEME:
+	if (settings->priv->gtk_icon_theme) {
+	    g_signal_handler_disconnect (settings->priv->gtk_icon_theme,
+					 settings->priv->icon_theme_changed);
+	    g_object_unref (settings->priv->gtk_icon_theme);
+	}
+	settings->priv->gtk_icon_theme = g_value_get_object (value);
+	if (settings->priv->gtk_icon_theme != NULL) {
+	    gchar **search_path;
+	    gint search_path_len, i;
+	    gboolean append_search_path = TRUE;
+	    gtk_icon_theme_get_search_path (settings->priv->gtk_icon_theme,
+					    &search_path, &search_path_len);
+	    for (i = search_path_len - 1; i >= 0; i--)
+		if (g_str_equal (search_path[i], GDU_ICON_PATH)) {
+		    append_search_path = FALSE;
+		    break;
+		}
+	    g_strfreev (search_path);
+	    if (append_search_path)
+		gtk_icon_theme_append_search_path (settings->priv->gtk_icon_theme,
+						   GDU_ICON_PATH);
+	    g_object_ref (settings->priv->gtk_icon_theme);
+	    settings->priv->icon_theme_changed =
+		g_signal_connect (settings->priv->gtk_icon_theme,
+				  "changed",
+				  (GCallback) icon_theme_changed,
+				  settings);
+	    icon_theme_changed (settings->priv->gtk_icon_theme, settings);
+	}
+	else {
+	    settings->priv->icon_theme_changed = 0;
+	}
+	break;
+    default:
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	break;
+    }
+}
+
+/******************************************************************************/
+
+YelpSettings *
+yelp_settings_get_default (void)
+{
+    static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+    static YelpSettings *settings = NULL;
+    g_static_mutex_lock (&mutex);
+    if (settings == NULL)
+	settings = g_object_new (YELP_TYPE_SETTINGS,
+				 "gtk-settings", gtk_settings_get_default (),
+				 "gtk-icon-theme", gtk_icon_theme_get_default (),
+				 NULL);
+    g_static_mutex_unlock (&mutex);
+    return settings;
+}
+
+/******************************************************************************/
+
+gchar *
+yelp_settings_get_color (YelpSettings       *settings,
+			 YelpSettingsColor   color)
+{
+    gchar *colorstr;
+    g_return_val_if_fail (color < YELP_SETTINGS_NUM_COLORS, NULL);
+
+    g_mutex_lock (settings->priv->mutex);
+    colorstr = g_strdup (settings->priv->colors[color]);
+    g_mutex_unlock (settings->priv->mutex);
+
+    return colorstr;
+}
+
+gchar **
+yelp_settings_get_colors (YelpSettings *settings)
+{
+    gchar **colors = g_new0 (gchar *, YELP_SETTINGS_NUM_COLORS + 1);
+    gint i;
+    for (i = 0; i < YELP_SETTINGS_NUM_COLORS; i++)
+	colors[i] = yelp_settings_get_color (settings, i);
+    return colors;
+}
+
+void
+yelp_settings_set_colors (YelpSettings      *settings,
+			  YelpSettingsColor  first_color,
+			  ...)
+{
+    YelpSettingsColor color;
+    va_list args;
+
+    g_mutex_lock (settings->priv->mutex);
+    va_start (args, first_color);
+
+    color = first_color;
+    while ((gint) color >= 0) {
+	gchar *colorstr = va_arg (args, gchar *);
+	gint i;
+	for (i = 0; i < 7; i++) {
+	    settings->priv->colors[color][i] = colorstr[i];
+	    if (colorstr[i] == '\0')
+		break;
+	}
+	settings->priv->colors[color][7] = '\0';
+	color = va_arg (args, YelpSettingsColor);
+    }
+
+    va_end (args);
+    g_mutex_unlock (settings->priv->mutex);
+
+    g_signal_emit (settings, settings_signals[COLORS_CHANGED], 0);
+}
+
+/******************************************************************************/
+
+gchar *
+yelp_settings_get_font (YelpSettings     *settings,
+			YelpSettingsFont  font)
+{
+    gchar *ret;
+    g_return_val_if_fail (font < YELP_SETTINGS_NUM_FONTS, NULL);
+
+    g_mutex_lock (settings->priv->mutex);
+    ret = g_strdup (settings->priv->fonts[font]);
+    g_mutex_unlock (settings->priv->mutex);
+
+    return ret;
+}
+
+gchar *
+yelp_settings_get_font_family (YelpSettings     *settings,
+			       YelpSettingsFont  font)
+{
+    const gchar *def = (font == YELP_SETTINGS_FONT_VARIABLE) ? "Sans" : "Monospace";
+    gchar *ret, *c;
+    g_return_val_if_fail (font < YELP_SETTINGS_NUM_FONTS, NULL);
+
+    g_mutex_lock (settings->priv->mutex);
+
+    if (settings->priv->fonts[font] == NULL) {
+	ret = g_strdup (def);
+	goto done;
+    }
+
+    c = strrchr (settings->priv->fonts[font], ' ');
+    if (c == NULL) {
+	g_warning ("Cannot parse font %s", settings->priv->fonts[font]);
+	ret = g_strdup (def);
+	goto done;
+    }
+
+    ret = g_strndup (settings->priv->fonts[font], c - settings->priv->fonts[font]);
+
+ done:
+    g_mutex_unlock (settings->priv->mutex);
+    return ret;
+}
+
+gint
+yelp_settings_get_font_size (YelpSettings     *settings,
+			     YelpSettingsFont  font)
+{
+    gchar *c;
+    gint ret;
+    g_return_val_if_fail (font < YELP_SETTINGS_NUM_FONTS, 0);
+
+    g_mutex_lock (settings->priv->mutex);
+
+    if (settings->priv->fonts[font] == NULL) {
+	ret = 10;
+	goto done;
+    }
+
+    c = strrchr (settings->priv->fonts[font], ' ');
+    if (c == NULL) {
+	g_warning ("Cannot parse font %s", settings->priv->fonts[font]);
+	ret = 10;
+	goto done;
+    }
+
+    ret = g_ascii_strtod (c, NULL);
+
+ done:
+    g_mutex_unlock (settings->priv->mutex);
+    return ret;
+}
+
+void
+yelp_settings_set_fonts (YelpSettings     *settings,
+			 YelpSettingsFont  first_font,
+			 ...)
+{
+    YelpSettingsFont font;
+    va_list args;
+
+    g_mutex_lock (settings->priv->mutex);
+    va_start (args, first_font);
+
+    font = first_font;
+    while ((gint) font >= 0) {
+	gchar *fontname = va_arg (args, gchar *);
+	if (settings->priv->fonts[font] != NULL)
+	    g_free (settings->priv->fonts[font]);
+	settings->priv->fonts[font] = g_strdup (fontname);
+	font = va_arg (args, YelpSettingsFont);
+    }
+
+    va_end (args);
+    g_mutex_unlock (settings->priv->mutex);
+
+    g_signal_emit (settings, settings_signals[FONTS_CHANGED], 0);
+}
+
+/******************************************************************************/
+
+gint
+yelp_settings_get_icon_size (YelpSettings *settings)
+{
+    return settings->priv->icon_size;
+}
+
+void
+yelp_settings_set_icon_size (YelpSettings *settings,
+			     gint          size)
+{
+    settings->priv->icon_size = size;
+    if (settings->priv->gtk_icon_theme != NULL)
+	icon_theme_changed (settings->priv->gtk_icon_theme, settings);
+}
+
+gchar *
+yelp_settings_get_icon (YelpSettings     *settings,
+			YelpSettingsIcon  icon)
+{
+    gchar *ret;
+    g_return_val_if_fail (icon < YELP_SETTINGS_NUM_ICONS, NULL);
+
+    g_mutex_lock (settings->priv->mutex);
+    ret = g_strdup (settings->priv->icons[icon]);
+    g_mutex_unlock (settings->priv->mutex);
+
+    return ret;
+}
+
+void
+yelp_settings_set_icons (YelpSettings     *settings,
+			 YelpSettingsIcon  first_icon,
+			 ...)
+{
+    YelpSettingsIcon icon;
+    va_list args;
+
+    g_mutex_lock (settings->priv->mutex);
+    va_start (args, first_icon);
+
+    icon = first_icon;
+    while ((gint) icon >= 0) {
+	gchar *filename = va_arg (args, gchar *);
+	if (settings->priv->icons[icon] != NULL)
+	    g_free (settings->priv->icons[icon]);
+	settings->priv->icons[icon] = g_strdup (filename);
+	icon = va_arg (args, YelpSettingsIcon);
+    }
+
+    va_end (args);
+    g_mutex_unlock (settings->priv->mutex);
+
+    g_signal_emit (settings, settings_signals[ICONS_CHANGED], 0);
+}
+
+/******************************************************************************/
+
+static void
+gtk_theme_changed (GtkSettings  *gtk_settings,
+		   GParamSpec   *pspec,
+		   YelpSettings *settings)
+{
+    GtkWidget *widget;
+    GtkStyle  *style;
+    GdkColor  *color;
+    GdkColor   blue = { 0, 0x1E1E, 0x3E3E, 0xE7E7 };
+    gdouble    base_h, base_l, base_s;
+    gdouble    text_h, text_l, text_s;
+    gint i;
+
+    g_mutex_lock (settings->priv->mutex);
+
+    style = gtk_rc_get_style_by_paths (gtk_settings,
+				       "GtkTextView", "GtkTextView",
+				       GTK_TYPE_TEXT_VIEW);
+    if (style)
+	g_object_ref (G_OBJECT (style));
+    else
+	style = gtk_style_new ();
+
+
+    rgb_to_hls (style->text[GTK_STATE_NORMAL].red / 65535.0,
+		style->text[GTK_STATE_NORMAL].green / 65535.0,
+		style->text[GTK_STATE_NORMAL].blue / 65535.0,
+		&text_h, &text_l, &text_s);
+    rgb_to_hls (style->base[GTK_STATE_NORMAL].red / 65535.0,
+		style->base[GTK_STATE_NORMAL].green / 65535.0,
+		style->base[GTK_STATE_NORMAL].blue / 65535.0,
+		&base_h, &base_l, &base_s);
+
+    /* YELP_SETTINGS_COLOR_BASE */
+    g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_BASE], 8,
+		"#%02X%02X%02X",
+		style->base[GTK_STATE_NORMAL].red >> 8,
+		style->base[GTK_STATE_NORMAL].green >> 8,
+		style->base[GTK_STATE_NORMAL].blue >> 8);
+
+    /* YELP_SETTINGS_COLOR_TEXT */
+    g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_TEXT], 8,
+		"#%02X%02X%02X",
+		style->text[GTK_STATE_NORMAL].red >> 8,
+		style->text[GTK_STATE_NORMAL].green >> 8,
+		style->text[GTK_STATE_NORMAL].blue >> 8);
+
+    /* YELP_SETTINGS_COLOR_LINK */
+    widget = gtk_link_button_new ("http://www.gnome.org";);
+    gtk_widget_style_get (widget, "link-color", &color, NULL);
+    if (!color)
+	color = &blue;
+    g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_LINK], 8,
+		"#%02X%02X%02X",
+		color->red >> 8,
+		color->green >> 8,
+		color->blue >> 8);
+    if (color != &blue)
+	gdk_color_free (color);
+	
+    /* YELP_SETTINGS_COLOR_LINK_VISITED */
+    color = NULL;
+    gtk_widget_style_get (widget, "visited-link-color", &color, NULL);
+    if (color) {
+	g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_LINK_VISITED], 8,
+		    "#%02X%02X%02X",
+		    color->red >> 8,
+		    color->green >> 8,
+		    color->blue >> 8);
+	gdk_color_free (color);
+    }
+
+    g_object_ref_sink (widget);
+    g_object_unref (widget);
+
+    /* YELP_SETTINGS_COLOR_TEXT_LIGHT */
+    hls_to_hex (text_h, 
+		text_l - ((text_l - base_l) * 0.25),
+		text_s,
+		settings->priv->colors[YELP_SETTINGS_COLOR_TEXT_LIGHT]);
+
+    /* YELP_SETTINGS_COLOR_GRAY */
+    hls_to_hex (base_h, 
+		base_l - ((base_l - text_l) * 0.03),
+		base_s,
+		settings->priv->colors[YELP_SETTINGS_COLOR_GRAY_BASE]);
+    hls_to_hex (base_h, 
+		base_l - ((base_l - text_l) * 0.25),
+		base_s,
+		settings->priv->colors[YELP_SETTINGS_COLOR_GRAY_BORDER]);
+
+    /* YELP_SETTINGS_COLOR_BLUE */
+    hls_to_hex (204,
+		base_l - ((base_l - text_l) * 0.03),
+		0.75,
+		settings->priv->colors[YELP_SETTINGS_COLOR_BLUE_BASE]);
+    hls_to_hex (204,
+		base_l - ((base_l - text_l) * 0.25),
+		0.75,
+		settings->priv->colors[YELP_SETTINGS_COLOR_BLUE_BORDER]);
+
+    /* YELP_SETTINGS_COLOR_RED */
+    hls_to_hex (0,
+		base_l - ((base_l - text_l) * 0.03),
+		0.75,
+		settings->priv->colors[YELP_SETTINGS_COLOR_RED_BASE]);
+    hls_to_hex (0,
+		base_l - ((base_l - text_l) * 0.25),
+		0.75,
+		settings->priv->colors[YELP_SETTINGS_COLOR_RED_BORDER]);
+
+    /* YELP_SETTINGS_COLOR_YELLOW */
+    hls_to_hex (60,
+		base_l - ((base_l - text_l) * 0.03),
+		0.75,
+		settings->priv->colors[YELP_SETTINGS_COLOR_YELLOW_BASE]);
+    hls_to_hex (60,
+		base_l - ((base_l - text_l) * 0.25),
+		0.75,
+		settings->priv->colors[YELP_SETTINGS_COLOR_YELLOW_BORDER]);
+
+    g_object_unref (G_OBJECT (style));
+
+    g_mutex_unlock (settings->priv->mutex);
+
+    g_signal_emit (settings, settings_signals[COLORS_CHANGED], 0);
+}
+
+static void
+icon_theme_changed (GtkIconTheme *theme,
+		    YelpSettings *settings)
+{
+    GtkIconInfo *info;
+    gint i;
+
+    g_mutex_lock (settings->priv->mutex);
+
+    for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++) {
+	if (settings->priv->icons[i] != NULL)
+	    g_free (settings->priv->icons[i]);
+	info = gtk_icon_theme_lookup_icon (theme,
+					   icon_names[i],
+					   settings->priv->icon_size,
+					   GTK_ICON_LOOKUP_NO_SVG);
+	if (info != NULL) {
+	    settings->priv->icons[i] = g_strdup (gtk_icon_info_get_filename (info));
+	    gtk_icon_info_free (info);
+	}
+	else {
+	    settings->priv->icons[i] = NULL;
+	}
+    }
+
+    g_mutex_unlock (settings->priv->mutex);
+
+    g_signal_emit (settings, settings_signals[ICONS_CHANGED], 0);
+}
+
+/******************************************************************************/
+
+static void
+rgb_to_hls (gdouble r, gdouble g, gdouble b, gdouble *h, gdouble *l, gdouble *s)
+{
+    gdouble min, max, delta;
+
+    if (r > g) {
+	if (r > b)
+	    max = r;
+	else
+	    max = b;
+	if (g < b)
+	    min = g;
+	else
+	    min = b;
+    }
+    else {
+	if (g > b)
+	    max = g;
+	else
+	    max = b;
+	if (r < b)
+	    min = r;
+	else
+	    min = b;
+    }
+
+    *l = (max + min) / 2;
+    *s = 0;
+    *h = 0;
+
+    if (max != min) {
+	if (*l <= 0.5)
+	    *s = (max - min) / (max + min);
+	else
+	    *s = (max - min) / (2 - max - min);
+
+	delta = max - min;
+	if (r == max)
+	    *h = (g - b) / delta;
+	else if (g == max)
+	    *h = 2 + (b - r) / delta;
+	else if (b == max)
+	    *h = 4 + (r - g) / delta;
+
+	*h *= 60;
+	if (*h < 0.0)
+	    *h += 360;
+    }
+}
+
+static void
+hls_to_hex (gdouble h, gdouble l, gdouble s, gchar *str)
+{
+    gdouble hue;
+    gdouble m1, m2;
+    gdouble r, g, b;
+    guint8 red, green, blue;
+
+    if (l <= 0.5)
+	m2 = l * (1 + s);
+    else
+	m2 = l + s - l * s;
+    m1 = 2 * l - m2;
+
+    if (s == 0) {
+	r = g = b = l;
+    }
+    else {
+	hue = h + 120;
+	while (hue > 360)
+	    hue -= 360;
+	while (hue < 0)
+	    hue += 360;
+
+	if (hue < 60)
+	    r = m1 + (m2 - m1) * hue / 60;
+	else if (hue < 180)
+	    r = m2;
+	else if (hue < 240)
+	    r = m1 + (m2 - m1) * (240 - hue) / 60;
+	else
+	    r = m1;
+
+	hue = h;
+	while (hue > 360)
+	    hue -= 360;
+	while (hue < 0)
+	    hue += 360;
+
+	if (hue < 60)
+	    g = m1 + (m2 - m1) * hue / 60;
+	else if (hue < 180)
+	    g = m2;
+	else if (hue < 240)
+	    g = m1 + (m2 - m1) * (240 - hue) / 60;
+	else
+	    g = m1;
+
+	hue = h - 120;
+	while (hue > 360)
+	    hue -= 360;
+	while (hue < 0)
+	    hue += 360;
+
+	if (hue < 60)
+	    b = m1 + (m2 - m1) * hue / 60;
+	else if (hue < 180)
+	    b = m2;
+	else if (hue < 240)
+	    b = m1 + (m2 - m1) * (240 - hue) / 60;
+	else
+	    b = m1;
+    }
+
+    red = r * 255;
+    green = g * 255;
+    blue = b * 255;
+    g_snprintf (str, 8, "#%02X%02X%02X", red, green, blue);
+}
diff --git a/libyelp/yelp-settings.h b/libyelp/yelp-settings.h
new file mode 100644
index 0000000..91a8e32
--- /dev/null
+++ b/libyelp/yelp-settings.h
@@ -0,0 +1,113 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2004-2009 Shaun McCance <shaunm gnome org>
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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.
+ *
+ * Author: Shaun McCance <shaunm gnome org>
+ */
+
+#ifndef __YELP_SETTINGS_H__
+#define __YELP_SETTINGS_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define YELP_TYPE_SETTINGS         (yelp_settings_get_type ())
+#define YELP_SETTINGS(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_SETTINGS, YelpSettings))
+#define YELP_SETTINGS_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_SETTINGS, YelpSettingsClass))
+#define YELP_IS_SETTINGS(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_SETTINGS))
+#define YELP_IS_SETTINGS_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_SETTINGS))
+#define YELP_SETTINGS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_SETTINGS, YelpSettingsClass))
+
+typedef struct _YelpSettings      YelpSettings;
+typedef struct _YelpSettingsClass YelpSettingsClass;
+typedef struct _YelpSettingsPriv  YelpSettingsPriv;
+
+struct _YelpSettings {
+    GObject           parent;
+    YelpSettingsPriv *priv;
+};
+
+struct _YelpSettingsClass {
+    GObjectClass      parent_class;
+};
+
+typedef enum {
+    YELP_SETTINGS_COLOR_BASE = 0,
+    YELP_SETTINGS_COLOR_TEXT,
+    YELP_SETTINGS_COLOR_TEXT_LIGHT,
+    YELP_SETTINGS_COLOR_LINK,
+    YELP_SETTINGS_COLOR_LINK_VISITED,
+    YELP_SETTINGS_COLOR_GRAY_BASE,
+    YELP_SETTINGS_COLOR_GRAY_BORDER,
+    YELP_SETTINGS_COLOR_BLUE_BASE,
+    YELP_SETTINGS_COLOR_BLUE_BORDER,
+    YELP_SETTINGS_COLOR_RED_BASE,
+    YELP_SETTINGS_COLOR_RED_BORDER,
+    YELP_SETTINGS_COLOR_YELLOW_BASE,
+    YELP_SETTINGS_COLOR_YELLOW_BORDER,
+    YELP_SETTINGS_NUM_COLORS
+} YelpSettingsColor;
+
+typedef enum {
+    YELP_SETTINGS_FONT_VARIABLE = 0,
+    YELP_SETTINGS_FONT_FIXED,
+    YELP_SETTINGS_NUM_FONTS
+} YelpSettingsFont;
+
+typedef enum {
+    YELP_SETTINGS_ICON_BUG = 0,
+    YELP_SETTINGS_ICON_CAUTION,
+    YELP_SETTINGS_ICON_IMPORTANT,
+    YELP_SETTINGS_ICON_NOTE,
+    YELP_SETTINGS_ICON_TIP,
+    YELP_SETTINGS_ICON_WARNING,
+    YELP_SETTINGS_NUM_ICONS
+} YelpSettingsIcon;
+
+YelpSettings *      yelp_settings_get_default          (void);
+
+gchar *             yelp_settings_get_color            (YelpSettings       *settings,
+							YelpSettingsColor   color);
+gchar **            yelp_settings_get_colors           (YelpSettings       *settings);
+void                yelp_settings_set_colors           (YelpSettings       *settings,
+							YelpSettingsColor   first_color,
+							...);
+
+gchar *             yelp_settings_get_font             (YelpSettings       *settings,
+							YelpSettingsFont    font);
+gchar *             yelp_settings_get_font_family      (YelpSettings       *settings,
+							YelpSettingsFont    font);
+gint                yelp_settings_get_font_size        (YelpSettings       *settings,
+							YelpSettingsFont    font);
+void                yelp_settings_set_fonts            (YelpSettings       *settings,
+							YelpSettingsFont    first_font,
+							...);
+
+gint                yelp_settings_get_icon_size        (YelpSettings       *settings);
+void                yelp_settings_set_icon_size        (YelpSettings       *settings,
+							gint                size);
+gchar *             yelp_settings_get_icon             (YelpSettings       *settings,
+							YelpSettingsIcon    icon);
+void                yelp_settings_set_icons            (YelpSettings       *settings,
+							YelpSettingsIcon    first_icon,
+							...);
+
+G_END_DECLS
+
+#endif /* __YELP_SETTINGS_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d9cfd0f..14d53e2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -9,12 +9,16 @@ YELP_COMMON_LDADD =				\
 
 check_PROGRAMS =				\
 	test-location-entry			\
+	test-settings				\
 	test-uri				\
 	test-view
 
 test_location_entry_CFLAGS = $(YELP_COMMON_CFLAGS)
 test_location_entry_LDADD = $(YELP_COMMON_LDADD)
 
+test_settings_CFLAGS = $(YELP_COMMON_CFLAGS)
+test_settings_LDADD = $(YELP_COMMON_LDADD)
+
 test_uri_CFLAGS = $(YELP_COMMON_CFLAGS)
 test_uri_LDADD = $(YELP_COMMON_LDADD)
 
diff --git a/tests/test-settings.c b/tests/test-settings.c
new file mode 100644
index 0000000..392f560
--- /dev/null
+++ b/tests/test-settings.c
@@ -0,0 +1,334 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2009 Shaun McCance  <shaunm gnome org>
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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.
+ *
+ * Author: Shaun McCance  <shaunm gnome org>
+ */
+
+#include <gtk/gtk.h>
+#include <webkit/webkit.h>
+
+#include "yelp-settings.h"
+
+static YelpSettings *settings;
+static WebKitWebSettings *websettings;
+static GtkWidget *webview;
+static GtkWidget *color_table;
+static GtkWidget *color_buttons[YELP_SETTINGS_NUM_COLORS];
+static GtkWidget *icon_table;
+static GtkWidget *icon_choosers[YELP_SETTINGS_NUM_ICONS];
+static GtkWidget *icon_images[YELP_SETTINGS_NUM_ICONS];
+static GtkWidget *font_choosers[YELP_SETTINGS_NUM_FONTS];
+
+static void
+colors_changed (YelpSettings *settings, gpointer user_data)
+{
+    static const gchar *tmpl =
+	"<html><head>"
+	"<style>"
+	"body { background-color: %s; color: %s; }"
+	"div, pre {"
+	"  margin: 0.5em; padding: 0.2em;"
+	"  border: solid 3px %s;"
+	"}"
+	"</style>"
+	"</head><body>"
+	"<pre>SOME\nMONOSPACE\nTEXT</pre>"
+	"<div><table>"
+	"<tr><td>YELP_SETTINGS_COLOR_BASE:</td><td>%s</td></tr>"
+	"<tr style='color: %s'><td>YELP_SETTINGS_COLOR_TEXT:</td><td>%s</td></tr>"
+	"<tr style='color: %s'><td>YELP_SETTINGS_COLOR_TEXT_LIGHT:</td><td>%s</td></tr>"
+	"<tr style='color: %s'><td>YELP_SETTINGS_COLOR_LINK:</td><td>%s</td></tr>"
+	"<tr style='color: %s'><td>YELP_SETTINGS_COLOR_LINK_VISITED:</td><td>%s</td></tr>"
+	"</table></div>"
+	"<div style='background-color:%s;border-color:%s'>"
+	"<table><tr><td>YELP_SETTINGS_COLOR_GRAY_BASE:</td><td>%s</td></tr>"
+	"<tr><td>YELP_SETTINGS_COLOR_GRAY_BORDER:</td><td>%s</tr></table></div>"
+	"<div style='background-color:%s;border-color:%s'>"
+	"<table><tr><td>YELP_SETTINGS_COLOR_BLUE_BASE:</td><td>%s</td></tr>"
+	"<tr><td>YELP_SETTINGS_COLOR_BLUE_BORDER:</td><td>%s</tr></table></div>"
+	"<div style='background-color:%s;border-color:%s'>"
+	"<table><tr><td>YELP_SETTINGS_COLOR_RED_BASE:</td><td>%s</td></tr>"
+	"<tr><td>YELP_SETTINGS_COLOR_RED_BORDER:</td><td>%s</tr></table></div>"
+	"<div style='background-color:%s;border-color:%s'>"
+	"<table><tr><td>YELP_SETTINGS_COLOR_YELLOW_BASE:</td><td>%s</td></tr>"
+	"<tr><td>YELP_SETTINGS_COLOR_YELLOW_BORDER:</td><td>%s</tr></table></div>"
+	"</body></html>";
+    gchar **colors = yelp_settings_get_colors (settings);
+    gchar *page;
+    page = g_strdup_printf (tmpl,
+			    colors[YELP_SETTINGS_COLOR_BASE], colors[YELP_SETTINGS_COLOR_TEXT],
+			    colors[YELP_SETTINGS_COLOR_BASE], colors[YELP_SETTINGS_COLOR_BASE],
+			    colors[YELP_SETTINGS_COLOR_TEXT], colors[YELP_SETTINGS_COLOR_TEXT],
+			    colors[YELP_SETTINGS_COLOR_TEXT_LIGHT], colors[YELP_SETTINGS_COLOR_TEXT_LIGHT],
+			    colors[YELP_SETTINGS_COLOR_LINK], colors[YELP_SETTINGS_COLOR_LINK],
+			    colors[YELP_SETTINGS_COLOR_LINK_VISITED], colors[YELP_SETTINGS_COLOR_LINK_VISITED],
+			    colors[YELP_SETTINGS_COLOR_GRAY_BASE], colors[YELP_SETTINGS_COLOR_GRAY_BORDER],
+			    colors[YELP_SETTINGS_COLOR_GRAY_BASE], colors[YELP_SETTINGS_COLOR_GRAY_BORDER],
+			    colors[YELP_SETTINGS_COLOR_BLUE_BASE], colors[YELP_SETTINGS_COLOR_BLUE_BORDER],
+			    colors[YELP_SETTINGS_COLOR_BLUE_BASE], colors[YELP_SETTINGS_COLOR_BLUE_BORDER],
+			    colors[YELP_SETTINGS_COLOR_RED_BASE], colors[YELP_SETTINGS_COLOR_RED_BORDER],
+			    colors[YELP_SETTINGS_COLOR_RED_BASE], colors[YELP_SETTINGS_COLOR_RED_BORDER],
+			    colors[YELP_SETTINGS_COLOR_YELLOW_BASE], colors[YELP_SETTINGS_COLOR_YELLOW_BORDER],
+			    colors[YELP_SETTINGS_COLOR_YELLOW_BASE], colors[YELP_SETTINGS_COLOR_YELLOW_BORDER]);
+    webkit_web_view_load_string (WEBKIT_WEB_VIEW (webview),
+                                 page,
+                                 "text/html",
+                                 "UTF-8",
+                                 "file:///dev/null");
+    g_free (page);
+    g_strfreev (colors);
+}
+
+static void
+icons_changed (YelpSettings *settings, gpointer user_data)
+{
+    gint i;
+    for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++) {
+	gchar *filename = yelp_settings_get_icon (settings, i);
+	if (filename != NULL) {
+	    gtk_image_set_from_file (GTK_IMAGE (icon_images[i]), filename);
+	    g_free (filename);
+	}
+    }
+}
+
+static void
+fonts_changed (YelpSettings *settings, gpointer user_data)
+{
+    g_object_set (websettings,
+		  "default-font-family", yelp_settings_get_font_family (settings, YELP_SETTINGS_FONT_VARIABLE),
+		  "default-font-size", yelp_settings_get_font_size (settings, YELP_SETTINGS_FONT_VARIABLE),
+		  "monospace-font-family", yelp_settings_get_font_family (settings, YELP_SETTINGS_FONT_FIXED),
+		  "default-monospace-font-size", yelp_settings_get_font_size (settings, YELP_SETTINGS_FONT_FIXED),
+		  NULL);
+}
+
+static void
+color_set (GtkColorButton *button,
+	   gpointer        user_data)
+{
+    GdkColor color;
+    gchar str[8];
+    gint i;
+    for (i = 0; i < YELP_SETTINGS_NUM_COLORS; i++)
+	if ((gpointer) color_buttons[i] == (gpointer) button)
+	    break;
+    g_return_if_fail (i < YELP_SETTINGS_NUM_COLORS);
+
+    gtk_color_button_get_color (button, &color);
+    g_snprintf (str, 8, "#%02X%02X%02X", color.red / 255, color.green / 255, color.blue / 255);
+    yelp_settings_set_colors (settings, i, str, -1);
+}
+
+static void
+font_set (GtkFontButton *button,
+	  GParamSpec    *pspec,
+	  gpointer       user_data)
+{
+    gint i;
+    for (i = 0; i < YELP_SETTINGS_NUM_FONTS; i++)
+	if ((gpointer) font_choosers[i] == (gpointer) button)
+	    break;
+    g_return_if_fail (i < YELP_SETTINGS_NUM_FONTS);
+
+    yelp_settings_set_fonts (settings, i, gtk_font_button_get_font_name (button), -1);
+}
+
+static void
+icon_file_set (GtkFileChooserButton *button,
+	       gpointer              user_data)
+{
+    gchar *filename;
+    gint i;
+    for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++)
+	if ((gpointer) icon_choosers[i] == (gpointer) button)
+	    break;
+    g_return_if_fail (i < YELP_SETTINGS_NUM_ICONS);
+
+    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (button));
+    yelp_settings_set_icons (settings, i, filename, -1);
+    g_free (filename);
+}
+
+static void
+use_gtk_settings_toggled (GtkToggleButton *button,
+			  gpointer         user_data)
+{
+    if (gtk_toggle_button_get_active (button)) {
+	g_object_set (settings, "gtk-settings", gtk_settings_get_default (), NULL);
+	gtk_widget_set_sensitive (color_table, FALSE);
+    }
+    else {
+	g_object_set (settings, "gtk-settings", NULL, NULL);
+	gtk_widget_set_sensitive (color_table, TRUE);
+    }
+}
+
+static void
+use_gtk_icon_theme_toggled (GtkToggleButton *button,
+			    gpointer         user_data)
+{
+    if (gtk_toggle_button_get_active (button)) {
+	g_object_set (settings, "gtk-icon-theme", gtk_icon_theme_get_default (), NULL);
+	gtk_widget_set_sensitive (icon_table, FALSE);
+    }
+    else {
+	g_object_set (settings, "gtk-icon-theme", NULL, NULL);
+	gtk_widget_set_sensitive (icon_table, TRUE);
+    }
+}
+
+static void
+use_small_icons_toggled (GtkToggleButton *button,
+			 gpointer         user_data)
+{
+    yelp_settings_set_icon_size (settings, gtk_toggle_button_get_active (button) ? 24 : 48);
+}
+
+int
+main (int argc, char **argv)
+{
+    GtkWidget *window, *hbox, *vbox, *widget, *scroll, *table;
+    gint i;
+
+    g_thread_init (NULL);
+    gtk_init (&argc, &argv);
+
+    settings = yelp_settings_get_default ();
+
+    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    gtk_window_set_default_size (GTK_WINDOW (window), 1024, 600);
+    g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+    hbox = gtk_hbox_new (FALSE, 12);
+    g_object_set (hbox, "border-width", 6, NULL);
+    gtk_container_add (GTK_CONTAINER (window), hbox);
+
+    vbox = gtk_vbox_new (FALSE, 6);
+    gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+
+    widget = gtk_check_button_new_with_label ("Use GtkSettings");
+    g_object_set (widget, "active", TRUE, NULL);
+    g_signal_connect (widget, "toggled", G_CALLBACK (use_gtk_settings_toggled), NULL);
+    gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
+
+    color_table = gtk_table_new (2, 7, TRUE);
+    gtk_widget_set_sensitive (color_table, FALSE);
+    gtk_box_pack_start (GTK_BOX (vbox), color_table, FALSE, FALSE, 0);
+
+    for (i = 0; i < YELP_SETTINGS_NUM_COLORS; i++) {
+	color_buttons[i] = gtk_color_button_new ();
+	g_signal_connect (color_buttons[i], "color-set", G_CALLBACK (color_set), NULL);
+	if (i == 0) {
+	    gtk_table_attach (GTK_TABLE (color_table), color_buttons[i],
+			      0, 1, 0, 2, 0, GTK_FILL, 0, 0);
+	}
+	else {
+	    gtk_table_attach (GTK_TABLE (color_table), color_buttons[i],
+			      (i + 1) / 2,
+			      (i + 1) / 2 + 1,
+			      (i + 1) % 2, 
+			      (i + 1) % 2 + 1,
+			      0, 0, 0, 0);
+	}
+    }
+
+    scroll = gtk_scrolled_window_new (NULL, NULL);
+    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+				    GTK_POLICY_AUTOMATIC,
+				    GTK_POLICY_AUTOMATIC);
+    gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
+
+    webview = webkit_web_view_new ();
+    websettings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (webview));
+    gtk_container_add (GTK_CONTAINER (scroll), webview);
+
+    vbox = gtk_vbox_new (FALSE, 6);
+    gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+
+    table = gtk_table_new (2, 2, FALSE);
+    gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
+
+    widget = gtk_label_new ("Variable");
+    g_object_set (widget, "xalign", 0.0, NULL);
+    gtk_table_attach (GTK_TABLE (table), widget, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
+    font_choosers[YELP_SETTINGS_FONT_VARIABLE] = gtk_font_button_new ();
+    g_signal_connect (font_choosers[YELP_SETTINGS_FONT_VARIABLE], "notify::font-name",
+		      G_CALLBACK (font_set), NULL);
+    gtk_font_button_set_font_name (GTK_FONT_BUTTON (font_choosers[YELP_SETTINGS_FONT_VARIABLE]),
+				   "Sans 8");
+    gtk_table_attach (GTK_TABLE (table), font_choosers[YELP_SETTINGS_FONT_VARIABLE],
+		      1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 6, 0);
+
+    widget = gtk_label_new ("Fixed");
+    g_object_set (widget, "xalign", 0.0, NULL);
+    gtk_table_attach (GTK_TABLE (table), widget, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
+    font_choosers[YELP_SETTINGS_FONT_FIXED] = gtk_font_button_new ();
+    g_signal_connect (font_choosers[YELP_SETTINGS_FONT_FIXED], "notify::font-name",
+		      G_CALLBACK (font_set), NULL);
+    gtk_font_button_set_font_name (GTK_FONT_BUTTON (font_choosers[YELP_SETTINGS_FONT_FIXED]),
+				   "Monospace 8");
+    gtk_table_attach (GTK_TABLE (table), font_choosers[YELP_SETTINGS_FONT_FIXED],
+		      1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 6, 0);
+
+    widget = gtk_check_button_new_with_label ("Use GtkIconTheme");
+    g_object_set (widget, "active", TRUE, NULL);
+    g_signal_connect (widget, "toggled", G_CALLBACK (use_gtk_icon_theme_toggled), NULL);
+    gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
+
+    widget = gtk_check_button_new_with_label ("Use small icons");
+    g_signal_connect (widget, "toggled", G_CALLBACK (use_small_icons_toggled), NULL);
+    gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
+
+    icon_table = gtk_table_new (6, 2, FALSE);
+    gtk_widget_set_sensitive (icon_table, FALSE);
+    gtk_box_pack_start (GTK_BOX (vbox), icon_table, FALSE, FALSE, 0);
+
+    for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++) {
+	const gchar *labels[YELP_SETTINGS_NUM_ICONS] =
+	    {"BUG", "CAUTION", "IMPORTANT", "NOTE", "TIP", "WARNING"};
+	widget = gtk_label_new (labels[i]);
+	g_object_set (widget, "xalign", 0.0, NULL);
+	gtk_table_attach (GTK_TABLE (icon_table), widget,
+			  0, 1, i, i + 1, GTK_FILL, 0, 0, 0);
+	icon_choosers[i] = gtk_file_chooser_button_new (labels[i], GTK_FILE_CHOOSER_ACTION_OPEN);
+	gtk_table_attach (GTK_TABLE (icon_table), icon_choosers[i],
+			  1, 2, i, i + 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 6, 0);
+	g_signal_connect (icon_choosers[i], "file-set", G_CALLBACK (icon_file_set), NULL);
+    }
+
+    hbox = gtk_hbox_new (TRUE, 6);
+    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+    for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++) {
+	icon_images[i] = gtk_image_new ();
+	gtk_box_pack_start (GTK_BOX (hbox), icon_images[i], FALSE, FALSE, 0);
+    }
+
+    g_signal_connect (settings, "fonts-changed", G_CALLBACK (fonts_changed), NULL);
+    fonts_changed (settings, NULL);
+    g_signal_connect (settings, "colors-changed", G_CALLBACK (colors_changed), NULL);
+    colors_changed (settings, NULL);
+    g_signal_connect (settings, "icons-changed", G_CALLBACK (icons_changed), NULL);
+    icons_changed (settings, NULL);
+
+    gtk_widget_show_all (GTK_WIDGET (window));
+
+    gtk_main ();
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]