[libyelp/yelp-mallard-document] Support for Mallard Facets extension
[yelp.git] / libyelp / yelp-settings.c
blobb1f2f9097881c4c2c343f43d49b4d185c386ee7d
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * Copyright (C) 2004-2009 Shaun McCance <shaunm@gnome.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Shaun McCance <shaunm@gnome.org>
23 #include <stdarg.h>
25 #include <gtk/gtk.h>
26 #include <glib/gi18n.h>
28 #include "yelp-settings.h"
30 struct _YelpSettingsPriv {
31 GMutex *mutex;
33 gchar colors[YELP_SETTINGS_NUM_COLORS][8];
34 gchar *setfonts[YELP_SETTINGS_NUM_FONTS];
35 gchar *fonts[YELP_SETTINGS_NUM_FONTS];
36 gchar *icons[YELP_SETTINGS_NUM_ICONS];
37 gint icon_size;
39 GtkSettings *gtk_settings;
40 GtkIconTheme *gtk_icon_theme;
42 gint font_adjustment;
44 gulong gtk_theme_changed;
45 gulong gtk_font_changed;
46 gulong icon_theme_changed;
48 gboolean show_text_cursor;
50 gboolean editor_mode;
52 GHashTable *bookmarks;
55 enum {
56 COLORS_CHANGED,
57 FONTS_CHANGED,
58 ICONS_CHANGED,
59 LAST_SIGNAL
61 static guint settings_signals[LAST_SIGNAL] = {0,};
63 enum {
64 PROP_0,
65 PROP_GTK_SETTINGS,
66 PROP_GTK_ICON_THEME,
67 PROP_FONT_ADJUSTMENT,
68 PROP_SHOW_TEXT_CURSOR,
69 PROP_EDITOR_MODE
72 gchar *icon_names[YELP_SETTINGS_NUM_ICONS];
74 G_DEFINE_TYPE (YelpSettings, yelp_settings, G_TYPE_OBJECT);
75 #define GET_PRIV(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_SETTINGS, YelpSettingsPriv))
77 static void yelp_settings_class_init (YelpSettingsClass *klass);
78 static void yelp_settings_init (YelpSettings *settings);
79 static void yelp_settings_dispose (GObject *object);
80 static void yelp_settings_finalize (GObject *object);
81 static void yelp_settings_get_property (GObject *object,
82 guint prop_id,
83 GValue *value,
84 GParamSpec *pspec);
85 static void yelp_settings_set_property (GObject *object,
86 guint prop_id,
87 const GValue *value,
88 GParamSpec *pspec);
90 static void gtk_theme_changed (GtkSettings *gtk_settings,
91 GParamSpec *pspec,
92 YelpSettings *settings);
93 static void gtk_font_changed (GtkSettings *gtk_settings,
94 GParamSpec *pspec,
95 YelpSettings *settings);
96 static void icon_theme_changed (GtkIconTheme *theme,
97 YelpSettings *settings);
99 static void rgb_to_hsv (gdouble r,
100 gdouble g,
101 gdouble b,
102 gdouble *h,
103 gdouble *s,
104 gdouble *v);
105 static void hsv_to_hex (gdouble h,
106 gdouble s,
107 gdouble v,
108 gchar *str);
110 /******************************************************************************/
112 static void
113 yelp_settings_class_init (YelpSettingsClass *klass)
115 GObjectClass *object_class = G_OBJECT_CLASS (klass);
116 gint i;
118 object_class->dispose = yelp_settings_dispose;
119 object_class->finalize = yelp_settings_finalize;
120 object_class->get_property = yelp_settings_get_property;
121 object_class->set_property = yelp_settings_set_property;
123 for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++) {
124 switch (i) {
125 case YELP_SETTINGS_ICON_BUG:
126 icon_names[i] = "yelp-note-bug";
127 break;
128 case YELP_SETTINGS_ICON_IMPORTANT:
129 icon_names[i] = "yelp-note-important";
130 break;
131 case YELP_SETTINGS_ICON_NOTE:
132 icon_names[i] = "yelp-note";
133 break;
134 case YELP_SETTINGS_ICON_TIP:
135 icon_names[i] = "yelp-note-tip";
136 break;
137 case YELP_SETTINGS_ICON_WARNING:
138 icon_names[i] = "yelp-note-warning";
139 break;
140 default:
141 g_assert_not_reached ();
145 g_object_class_install_property (object_class,
146 PROP_GTK_SETTINGS,
147 g_param_spec_object ("gtk-settings",
148 _("GtkSettings"),
149 _("A GtkSettings object to get settings from"),
150 GTK_TYPE_SETTINGS,
151 G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
152 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
154 g_object_class_install_property (object_class,
155 PROP_GTK_ICON_THEME,
156 g_param_spec_object ("gtk-icon-theme",
157 _("GtkIconTheme"),
158 _("A GtkIconTheme object to get icons from"),
159 GTK_TYPE_ICON_THEME,
160 G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
161 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
163 g_object_class_install_property (object_class,
164 PROP_FONT_ADJUSTMENT,
165 g_param_spec_int ("font-adjustment",
166 _("Font Adjustment"),
167 _("A size adjustment to add to font sizes"),
168 -3, 10, 0,
169 G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
170 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
172 g_object_class_install_property (object_class,
173 PROP_SHOW_TEXT_CURSOR,
174 g_param_spec_boolean ("show-text-cursor",
175 _("Show Text Cursor"),
176 _("Show the text cursor or caret for accessible navigation"),
177 FALSE,
178 G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
179 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
181 g_object_class_install_property (object_class,
182 PROP_EDITOR_MODE,
183 g_param_spec_boolean ("editor-mode",
184 _("Editor Mode"),
185 _("Enable features useful to editors"),
186 FALSE,
187 G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
188 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
190 settings_signals[COLORS_CHANGED] =
191 g_signal_new ("colors-changed",
192 G_OBJECT_CLASS_TYPE (klass),
193 G_SIGNAL_RUN_LAST,
194 0, NULL, NULL,
195 g_cclosure_marshal_VOID__VOID,
196 G_TYPE_NONE, 0);
198 settings_signals[FONTS_CHANGED] =
199 g_signal_new ("fonts-changed",
200 G_OBJECT_CLASS_TYPE (klass),
201 G_SIGNAL_RUN_LAST,
202 0, NULL, NULL,
203 g_cclosure_marshal_VOID__VOID,
204 G_TYPE_NONE, 0);
206 settings_signals[ICONS_CHANGED] =
207 g_signal_new ("icons-changed",
208 G_OBJECT_CLASS_TYPE (klass),
209 G_SIGNAL_RUN_LAST,
210 0, NULL, NULL,
211 g_cclosure_marshal_VOID__VOID,
212 G_TYPE_NONE, 0);
214 g_type_class_add_private (klass, sizeof (YelpSettingsPriv));
217 static void
218 yelp_settings_init (YelpSettings *settings)
220 gint i;
222 settings->priv = GET_PRIV (settings);
223 settings->priv->mutex = g_mutex_new ();
224 settings->priv->icon_size = 24;
226 for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++)
227 settings->priv->icons[i] = NULL;
228 for (i = 0; i < YELP_SETTINGS_NUM_FONTS; i++) {
229 settings->priv->setfonts[i] = NULL;
230 settings->priv->fonts[i] = NULL;
233 settings->priv->bookmarks = g_hash_table_new_full (g_str_hash, g_str_equal,
234 g_free, NULL);
237 static void
238 yelp_settings_dispose (GObject *object)
240 YelpSettings *settings = YELP_SETTINGS (object);
242 G_OBJECT_CLASS (yelp_settings_parent_class)->dispose (object);
245 static void
246 yelp_settings_finalize (GObject *object)
248 YelpSettings *settings = YELP_SETTINGS (object);
250 g_mutex_free (settings->priv->mutex);
252 G_OBJECT_CLASS (yelp_settings_parent_class)->finalize (object);
255 static void
256 yelp_settings_get_property (GObject *object,
257 guint prop_id,
258 GValue *value,
259 GParamSpec *pspec)
261 YelpSettings *settings = YELP_SETTINGS (object);
263 switch (prop_id) {
264 case PROP_GTK_SETTINGS:
265 g_value_set_object (value, settings->priv->gtk_settings);
266 break;
267 case PROP_GTK_ICON_THEME:
268 g_value_set_object (value, settings->priv->gtk_icon_theme);
269 break;
270 case PROP_FONT_ADJUSTMENT:
271 g_value_set_int (value, settings->priv->font_adjustment);
272 break;
273 case PROP_SHOW_TEXT_CURSOR:
274 g_value_set_boolean (value, settings->priv->show_text_cursor);
275 break;
276 case PROP_EDITOR_MODE:
277 g_value_set_boolean (value, settings->priv->editor_mode);
278 break;
279 default:
280 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
281 break;
285 static void
286 yelp_settings_set_property (GObject *object,
287 guint prop_id,
288 const GValue *value,
289 GParamSpec *pspec)
291 YelpSettings *settings = YELP_SETTINGS (object);
293 switch (prop_id) {
294 case PROP_GTK_SETTINGS:
295 if (settings->priv->gtk_settings) {
296 g_signal_handler_disconnect (settings->priv->gtk_settings,
297 settings->priv->gtk_theme_changed);
298 g_signal_handler_disconnect (settings->priv->gtk_settings,
299 settings->priv->gtk_font_changed);
300 g_object_unref (settings->priv->gtk_settings);
302 settings->priv->gtk_settings = g_value_get_object (value);
303 if (settings->priv->gtk_settings != NULL) {
304 g_object_ref (settings->priv->gtk_settings);
305 settings->priv->gtk_theme_changed =
306 g_signal_connect (settings->priv->gtk_settings,
307 "notify::gtk-theme-name",
308 (GCallback) gtk_theme_changed,
309 settings);
310 settings->priv->gtk_font_changed =
311 g_signal_connect (settings->priv->gtk_settings,
312 "notify::gtk-font-name",
313 (GCallback) gtk_font_changed,
314 settings);
315 gtk_theme_changed (settings->priv->gtk_settings, NULL, settings);
316 gtk_font_changed (settings->priv->gtk_settings, NULL, settings);
318 else {
319 settings->priv->gtk_theme_changed = 0;
320 settings->priv->gtk_font_changed = 0;
322 break;
323 case PROP_GTK_ICON_THEME:
324 if (settings->priv->gtk_icon_theme) {
325 g_signal_handler_disconnect (settings->priv->gtk_icon_theme,
326 settings->priv->icon_theme_changed);
327 g_object_unref (settings->priv->gtk_icon_theme);
329 settings->priv->gtk_icon_theme = g_value_get_object (value);
330 if (settings->priv->gtk_icon_theme != NULL) {
331 gchar **search_path;
332 gint search_path_len, i;
333 gboolean append_search_path = TRUE;
334 gtk_icon_theme_get_search_path (settings->priv->gtk_icon_theme,
335 &search_path, &search_path_len);
336 for (i = search_path_len - 1; i >= 0; i--)
337 if (g_str_equal (search_path[i], YELP_ICON_PATH)) {
338 append_search_path = FALSE;
339 break;
341 if (append_search_path)
342 gtk_icon_theme_append_search_path (settings->priv->gtk_icon_theme,
343 YELP_ICON_PATH);
344 append_search_path = TRUE;
345 for (i = search_path_len - 1; i >= 0; i--)
346 if (g_str_equal (search_path[i], DATADIR"/yelp/icons")) {
347 append_search_path = FALSE;
348 break;
350 if (append_search_path)
351 gtk_icon_theme_append_search_path (settings->priv->gtk_icon_theme,
352 DATADIR"/yelp/icons");
353 g_strfreev (search_path);
354 g_object_ref (settings->priv->gtk_icon_theme);
355 settings->priv->icon_theme_changed =
356 g_signal_connect (settings->priv->gtk_icon_theme,
357 "changed",
358 (GCallback) icon_theme_changed,
359 settings);
360 icon_theme_changed (settings->priv->gtk_icon_theme, settings);
362 else {
363 settings->priv->icon_theme_changed = 0;
365 break;
366 case PROP_FONT_ADJUSTMENT:
367 settings->priv->font_adjustment = g_value_get_int (value);
368 gtk_font_changed (settings->priv->gtk_settings, NULL, settings);
369 break;
370 case PROP_SHOW_TEXT_CURSOR:
371 settings->priv->show_text_cursor = g_value_get_boolean (value);
372 break;
373 case PROP_EDITOR_MODE:
374 settings->priv->editor_mode = g_value_get_boolean (value);
375 break;
376 default:
377 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
378 break;
382 /******************************************************************************/
384 YelpSettings *
385 yelp_settings_get_default (void)
387 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
388 static YelpSettings *settings = NULL;
389 g_static_mutex_lock (&mutex);
390 if (settings == NULL)
391 settings = g_object_new (YELP_TYPE_SETTINGS,
392 "gtk-settings", gtk_settings_get_default (),
393 "gtk-icon-theme", gtk_icon_theme_get_default (),
394 NULL);
395 g_static_mutex_unlock (&mutex);
396 return settings;
399 /******************************************************************************/
401 gchar *
402 yelp_settings_get_color (YelpSettings *settings,
403 YelpSettingsColor color)
405 gchar *colorstr;
406 g_return_val_if_fail (color < YELP_SETTINGS_NUM_COLORS, NULL);
408 g_mutex_lock (settings->priv->mutex);
409 colorstr = g_strdup (settings->priv->colors[color]);
410 g_mutex_unlock (settings->priv->mutex);
412 return colorstr;
415 gchar **
416 yelp_settings_get_colors (YelpSettings *settings)
418 gchar **colors = g_new0 (gchar *, YELP_SETTINGS_NUM_COLORS + 1);
419 gint i;
420 for (i = 0; i < YELP_SETTINGS_NUM_COLORS; i++)
421 colors[i] = yelp_settings_get_color (settings, i);
422 return colors;
425 void
426 yelp_settings_set_colors (YelpSettings *settings,
427 YelpSettingsColor first_color,
428 ...)
430 YelpSettingsColor color;
431 va_list args;
433 g_mutex_lock (settings->priv->mutex);
434 va_start (args, first_color);
436 color = first_color;
437 while ((gint) color >= 0) {
438 gchar *colorstr = va_arg (args, gchar *);
439 gint i;
440 for (i = 0; i < 7; i++) {
441 settings->priv->colors[color][i] = colorstr[i];
442 if (colorstr[i] == '\0')
443 break;
445 settings->priv->colors[color][7] = '\0';
446 color = va_arg (args, YelpSettingsColor);
449 va_end (args);
450 g_mutex_unlock (settings->priv->mutex);
452 g_signal_emit (settings, settings_signals[COLORS_CHANGED], 0);
455 const gchar*
456 yelp_settings_get_color_param (YelpSettingsColor color)
458 static const gchar *params[YELP_SETTINGS_NUM_COLORS] = {
459 "color.background",
460 "color.text",
461 "color.text_light",
462 "color.link",
463 "color.link_visted",
464 "color.gray_background",
465 "color.dark_background",
466 "color.gray_border",
467 "color.blue_background",
468 "color.blue_border",
469 "color.red_background",
470 "color.red_border",
471 "color.yellow_background",
472 "color.yellow_border"
474 g_return_val_if_fail (color < YELP_SETTINGS_NUM_COLORS, NULL);
475 return params[color];
478 /******************************************************************************/
480 gchar *
481 yelp_settings_get_font (YelpSettings *settings,
482 YelpSettingsFont font)
484 gchar *ret;
485 g_return_val_if_fail (font < YELP_SETTINGS_NUM_FONTS, NULL);
487 g_mutex_lock (settings->priv->mutex);
488 if (settings->priv->setfonts[font])
489 ret = g_strdup (settings->priv->setfonts[font]);
490 else
491 ret = g_strdup (settings->priv->fonts[font]);
492 g_mutex_unlock (settings->priv->mutex);
494 return ret;
497 gchar *
498 yelp_settings_get_font_family (YelpSettings *settings,
499 YelpSettingsFont font)
501 const gchar *def = (font == YELP_SETTINGS_FONT_VARIABLE) ? "Sans" : "Monospace";
502 gchar *desc, *ret, *c; /* do not free */
503 g_return_val_if_fail (font < YELP_SETTINGS_NUM_FONTS, NULL);
505 g_mutex_lock (settings->priv->mutex);
507 if (settings->priv->setfonts[font])
508 desc = g_strdup (settings->priv->setfonts[font]);
509 else
510 desc = g_strdup (settings->priv->fonts[font]);
512 if (desc == NULL) {
513 ret = g_strdup (def);
514 goto done;
517 c = strrchr (desc, ' ');
518 if (c == NULL) {
519 g_warning ("Cannot parse font: %s", desc);
520 ret = g_strdup (def);
521 goto done;
524 ret = g_strndup (desc, c - desc);
526 done:
527 g_mutex_unlock (settings->priv->mutex);
528 return ret;
531 gint
532 yelp_settings_get_font_size (YelpSettings *settings,
533 YelpSettingsFont font)
535 gchar *desc, *c; /* do not free */
536 gint ret;
537 g_return_val_if_fail (font < YELP_SETTINGS_NUM_FONTS, 0);
539 g_mutex_lock (settings->priv->mutex);
541 if (settings->priv->setfonts[font])
542 desc = g_strdup (settings->priv->setfonts[font]);
543 else
544 desc = g_strdup (settings->priv->fonts[font]);
546 if (desc == NULL) {
547 ret = 10;
548 goto done;
551 c = strrchr (desc, ' ');
552 if (c == NULL) {
553 g_warning ("Cannot parse font %s", desc);
554 ret = 10;
555 goto done;
558 ret = g_ascii_strtod (c, NULL);
560 done:
561 g_mutex_unlock (settings->priv->mutex);
562 ret += settings->priv->font_adjustment;
563 ret = (ret < 5) ? 5 : ret;
564 return ret;
567 void
568 yelp_settings_set_fonts (YelpSettings *settings,
569 YelpSettingsFont first_font,
570 ...)
572 YelpSettingsFont font;
573 va_list args;
575 g_mutex_lock (settings->priv->mutex);
576 va_start (args, first_font);
578 font = first_font;
579 while ((gint) font >= 0) {
580 gchar *fontname = va_arg (args, gchar *);
581 if (settings->priv->setfonts[font] != NULL)
582 g_free (settings->priv->setfonts[font]);
583 settings->priv->setfonts[font] = g_strdup (fontname);
584 font = va_arg (args, YelpSettingsFont);
587 va_end (args);
588 g_mutex_unlock (settings->priv->mutex);
590 g_signal_emit (settings, settings_signals[FONTS_CHANGED], 0);
593 gint
594 yelp_settings_get_font_adjustment (YelpSettings *settings)
596 return settings->priv->font_adjustment;
599 void
600 yelp_settings_set_font_adjustment (YelpSettings *settings,
601 gint adjustment)
603 g_object_set (settings, "font-adjustment", adjustment, NULL);
606 /******************************************************************************/
608 gint
609 yelp_settings_get_icon_size (YelpSettings *settings)
611 return settings->priv->icon_size;
614 void
615 yelp_settings_set_icon_size (YelpSettings *settings,
616 gint size)
618 settings->priv->icon_size = size;
619 if (settings->priv->gtk_icon_theme != NULL)
620 icon_theme_changed (settings->priv->gtk_icon_theme, settings);
623 gchar *
624 yelp_settings_get_icon (YelpSettings *settings,
625 YelpSettingsIcon icon)
627 gchar *ret;
628 g_return_val_if_fail (icon < YELP_SETTINGS_NUM_ICONS, NULL);
630 g_mutex_lock (settings->priv->mutex);
631 ret = g_strdup (settings->priv->icons[icon]);
632 g_mutex_unlock (settings->priv->mutex);
634 return ret;
637 void
638 yelp_settings_set_icons (YelpSettings *settings,
639 YelpSettingsIcon first_icon,
640 ...)
642 YelpSettingsIcon icon;
643 va_list args;
645 g_mutex_lock (settings->priv->mutex);
646 va_start (args, first_icon);
648 icon = first_icon;
649 while ((gint) icon >= 0) {
650 gchar *filename = va_arg (args, gchar *);
651 if (settings->priv->icons[icon] != NULL)
652 g_free (settings->priv->icons[icon]);
653 settings->priv->icons[icon] = g_filename_to_uri (filename, NULL, NULL);
654 icon = va_arg (args, YelpSettingsIcon);
657 va_end (args);
658 g_mutex_unlock (settings->priv->mutex);
660 g_signal_emit (settings, settings_signals[ICONS_CHANGED], 0);
663 const gchar *
664 yelp_settings_get_icon_param (YelpSettingsIcon icon)
666 static const gchar *params[YELP_SETTINGS_NUM_ICONS] = {
667 "icons.note.bug",
668 "icons.note.important",
669 "icons.note",
670 "icons.note.tip",
671 "icons.note.warning"
673 g_return_val_if_fail (icon < YELP_SETTINGS_NUM_ICONS, NULL);
674 return params[icon];
677 /******************************************************************************/
679 gboolean
680 yelp_settings_get_show_text_cursor (YelpSettings *settings)
682 return settings->priv->show_text_cursor;
685 void
686 yelp_settings_set_show_text_cursor (YelpSettings *settings,
687 gboolean show)
689 g_object_set (settings, "show-text-cursor", show, NULL);
692 gboolean
693 yelp_settings_get_editor_mode (YelpSettings *settings)
695 return settings->priv->editor_mode;
698 void
699 yelp_settings_set_editor_mode (YelpSettings *settings,
700 gboolean editor_mode)
702 g_object_set (settings, "editor-mode", editor_mode, NULL);
705 /******************************************************************************/
707 gchar **
708 yelp_settings_get_all_params (YelpSettings *settings,
709 gint extra,
710 gint *end)
712 gchar **params;
713 gint i, ix;
715 params = g_new0 (gchar *,
716 (2*YELP_SETTINGS_NUM_COLORS) + (2*YELP_SETTINGS_NUM_ICONS) + extra + 5);
718 for (i = 0; i < YELP_SETTINGS_NUM_COLORS; i++) {
719 gchar *val;
720 ix = 2 * i;
721 params[ix] = g_strdup (yelp_settings_get_color_param (i));
722 val = yelp_settings_get_color (settings, i);
723 params[ix + 1] = g_strdup_printf ("\"%s\"", val);
724 g_free (val);
726 for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++) {
727 gchar *val;
728 ix = 2 * (YELP_SETTINGS_NUM_COLORS + i);
729 params[ix] = g_strdup (yelp_settings_get_icon_param (i));
730 val = yelp_settings_get_icon (settings, i);
731 params[ix + 1] = g_strdup_printf ("\"%s\"", val);
732 g_free (val);
734 ix = 2 * (YELP_SETTINGS_NUM_COLORS + YELP_SETTINGS_NUM_ICONS);
735 params[ix++] = g_strdup ("icons.size.note");
736 params[ix++] = g_strdup_printf ("%i", yelp_settings_get_icon_size (settings));
737 params[ix++] = g_strdup ("yelp.editor_mode");
738 if (settings->priv->editor_mode)
739 params[ix++] = g_strdup ("true()");
740 else
741 params[ix++] = g_strdup ("false()");
742 params[ix] = NULL;
744 if (end != NULL)
745 *end = ix;
746 return params;
749 /******************************************************************************/
751 static void
752 gtk_theme_changed (GtkSettings *gtk_settings,
753 GParamSpec *pspec,
754 YelpSettings *settings)
756 GtkWidget *widget;
757 GtkStyle *style;
758 GdkColor *color;
759 GdkColor blue = { 0, 0x1E1E, 0x3E3E, 0xE7E7 };
760 gdouble base_h, base_s, base_v;
761 gdouble text_h, text_s, text_v;
762 gint i;
764 g_mutex_lock (settings->priv->mutex);
766 style = gtk_rc_get_style_by_paths (gtk_settings,
767 "GtkTextView", "GtkTextView",
768 GTK_TYPE_TEXT_VIEW);
769 if (style)
770 g_object_ref (G_OBJECT (style));
771 else
772 style = gtk_style_new ();
775 rgb_to_hsv (style->text[GTK_STATE_NORMAL].red / 65535.0,
776 style->text[GTK_STATE_NORMAL].green / 65535.0,
777 style->text[GTK_STATE_NORMAL].blue / 65535.0,
778 &text_h, &text_s, &text_v);
779 rgb_to_hsv (style->base[GTK_STATE_NORMAL].red / 65535.0,
780 style->base[GTK_STATE_NORMAL].green / 65535.0,
781 style->base[GTK_STATE_NORMAL].blue / 65535.0,
782 &base_h, &base_s, &base_v);
784 /* YELP_SETTINGS_COLOR_BASE */
785 g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_BASE], 8,
786 "#%02X%02X%02X",
787 style->base[GTK_STATE_NORMAL].red >> 8,
788 style->base[GTK_STATE_NORMAL].green >> 8,
789 style->base[GTK_STATE_NORMAL].blue >> 8);
791 /* YELP_SETTINGS_COLOR_TEXT */
792 g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_TEXT], 8,
793 "#%02X%02X%02X",
794 style->text[GTK_STATE_NORMAL].red >> 8,
795 style->text[GTK_STATE_NORMAL].green >> 8,
796 style->text[GTK_STATE_NORMAL].blue >> 8);
798 /* YELP_SETTINGS_COLOR_LINK */
799 widget = gtk_link_button_new ("http://www.gnome.org");
800 gtk_widget_style_get (widget, "link-color", &color, NULL);
801 if (!color)
802 color = &blue;
803 g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_LINK], 8,
804 "#%02X%02X%02X",
805 color->red >> 8,
806 color->green >> 8,
807 color->blue >> 8);
808 if (color != &blue)
809 gdk_color_free (color);
811 /* YELP_SETTINGS_COLOR_LINK_VISITED */
812 color = NULL;
813 gtk_widget_style_get (widget, "visited-link-color", &color, NULL);
814 if (color) {
815 g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_LINK_VISITED], 8,
816 "#%02X%02X%02X",
817 color->red >> 8,
818 color->green >> 8,
819 color->blue >> 8);
820 gdk_color_free (color);
823 g_object_ref_sink (widget);
824 g_object_unref (widget);
826 /* YELP_SETTINGS_COLOR_TEXT_LIGHT */
827 hsv_to_hex (text_h,
828 text_s,
829 text_v - ((text_v - base_v) * 0.25),
830 settings->priv->colors[YELP_SETTINGS_COLOR_TEXT_LIGHT]);
832 /* YELP_SETTINGS_COLOR_GRAY */
833 hsv_to_hex (base_h,
834 base_s,
835 base_v - ((base_v - text_v) * 0.05),
836 settings->priv->colors[YELP_SETTINGS_COLOR_GRAY_BASE]);
837 hsv_to_hex (base_h,
838 base_s,
839 base_v - ((base_v - text_v) * 0.1),
840 settings->priv->colors[YELP_SETTINGS_COLOR_DARK_BASE]);
841 hsv_to_hex (base_h,
842 base_s,
843 base_v - ((base_v - text_v) * 0.26),
844 settings->priv->colors[YELP_SETTINGS_COLOR_GRAY_BORDER]);
846 /* YELP_SETTINGS_COLOR_BLUE */
847 hsv_to_hex (211,
848 0.1,
849 base_v - ((base_v - text_v) * 0.01),
850 settings->priv->colors[YELP_SETTINGS_COLOR_BLUE_BASE]);
851 hsv_to_hex (211,
852 0.45,
853 base_v - ((base_v - text_v) * 0.19),
854 settings->priv->colors[YELP_SETTINGS_COLOR_BLUE_BORDER]);
856 /* YELP_SETTINGS_COLOR_RED */
857 hsv_to_hex (0,
858 0.13,
859 base_v - ((base_v - text_v) * 0.01),
860 settings->priv->colors[YELP_SETTINGS_COLOR_RED_BASE]);
861 hsv_to_hex (0,
862 0.83,
863 base_v - ((base_v - text_v) * 0.06),
864 settings->priv->colors[YELP_SETTINGS_COLOR_RED_BORDER]);
866 /* YELP_SETTINGS_COLOR_YELLOW */
867 hsv_to_hex (60,
868 0.25,
869 base_v - ((base_v - text_v) * 0.01),
870 settings->priv->colors[YELP_SETTINGS_COLOR_YELLOW_BASE]);
871 hsv_to_hex (60,
872 1.0,
873 base_v - ((base_v - text_v) * 0.07),
874 settings->priv->colors[YELP_SETTINGS_COLOR_YELLOW_BORDER]);
876 g_object_unref (G_OBJECT (style));
878 g_mutex_unlock (settings->priv->mutex);
880 g_signal_emit (settings, settings_signals[COLORS_CHANGED], 0);
883 static void
884 gtk_font_changed (GtkSettings *gtk_settings,
885 GParamSpec *pspec,
886 YelpSettings *settings)
888 gchar *font, *c;
890 /* This happens when font_adjustment is set during init */
891 if (gtk_settings == NULL)
892 return;
894 g_free (settings->priv->fonts[YELP_SETTINGS_FONT_VARIABLE]);
895 g_object_get (gtk_settings, "gtk-font-name", &font, NULL);
896 settings->priv->fonts[YELP_SETTINGS_FONT_VARIABLE] = font;
898 c = strrchr (font, ' ');
899 if (c == NULL) {
900 g_warning ("Cannot parse font: %s", font);
901 font = g_strdup ("Monospace 10");
903 else {
904 font = g_strconcat ("Monospace", c, NULL);
907 g_free (settings->priv->fonts[YELP_SETTINGS_FONT_FIXED]);
908 settings->priv->fonts[YELP_SETTINGS_FONT_FIXED] = font;
910 g_signal_emit (settings, settings_signals[FONTS_CHANGED], 0);
913 static void
914 icon_theme_changed (GtkIconTheme *theme,
915 YelpSettings *settings)
917 GtkIconInfo *info;
918 gint i;
920 g_mutex_lock (settings->priv->mutex);
922 for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++) {
923 if (settings->priv->icons[i] != NULL)
924 g_free (settings->priv->icons[i]);
925 info = gtk_icon_theme_lookup_icon (theme,
926 icon_names[i],
927 settings->priv->icon_size,
928 GTK_ICON_LOOKUP_NO_SVG);
929 if (info != NULL) {
930 settings->priv->icons[i] = g_filename_to_uri (gtk_icon_info_get_filename (info),
931 NULL, NULL);
932 gtk_icon_info_free (info);
934 else {
935 settings->priv->icons[i] = NULL;
939 g_mutex_unlock (settings->priv->mutex);
941 g_signal_emit (settings, settings_signals[ICONS_CHANGED], 0);
944 gint
945 yelp_settings_cmp_icons (const gchar *icon1,
946 const gchar *icon2)
948 static const gchar *icons[] = {
949 "yelp-page-task",
950 "yelp-page-video",
951 "yelp-page-tip",
952 "yelp-page-ui",
953 "help-contents",
954 NULL
956 gint i;
957 for (i = 0; icons[i] != NULL; i++) {
958 gboolean eq1 = icon1 ? g_str_equal (icon1, icons[i]) : FALSE;
959 gboolean eq2 = icon2 ? g_str_equal (icon2, icons[i]) : FALSE;
960 if (eq1 && eq2)
961 return 0;
962 else if (eq1)
963 return -1;
964 else if (eq2)
965 return 1;
967 if (icon1 == NULL && icon2 == NULL)
968 return 0;
969 else if (icon2 == NULL)
970 return -1;
971 else if (icon1 == NULL)
972 return 1;
973 else
974 return strcmp (icon1, icon2);
977 /******************************************************************************/
979 static void
980 rgb_to_hsv (gdouble r, gdouble g, gdouble b, gdouble *h, gdouble *s, gdouble *v)
982 gdouble min, max, delta;
984 max = (r > g) ? r : g;
985 max = (max > b) ? max : b;
986 min = (r < g) ? r : g;
987 min = (min < b) ? min : b;
989 delta = max - min;
991 *v = max;
992 *s = 0;
993 *h = 0;
995 if (max != min) {
996 *s = delta / *v;
998 if (r == max)
999 *h = (g - b) / delta;
1000 else if (g == max)
1001 *h = 2 + (b - r) / delta;
1002 else if (b == max)
1003 *h = 4 + (r - g) / delta;
1005 *h *= 60;
1006 if (*h < 0.0)
1007 *h += 360;
1011 static void
1012 hsv_to_hex (gdouble h, gdouble s, gdouble v, gchar *str)
1014 gint hue;
1015 gdouble c;
1016 gdouble m1, m2, m3;
1017 gdouble r, g, b;
1018 guint8 red, green, blue;
1020 c = v * s;
1021 h /= 60;
1022 hue = (int) h;
1023 m1 = v * (1 - s);
1024 m2 = v * (1 - s * (h - hue));
1025 m3 = v * (1 - s * (-h + hue + 1));
1027 r = g = b = v;
1028 switch (hue) {
1029 case 0:
1030 b = m1; g = m3; break;
1031 case 1:
1032 b = m1; r = m2; break;
1033 case 2:
1034 r = m1; b = m3; break;
1035 case 3:
1036 r = m1; g = m2; break;
1037 case 4:
1038 g = m1; r = m3; break;
1039 case 5:
1040 g = m1; b = m2; break;
1043 red = r * 255;
1044 green = g * 255;
1045 blue = b * 255;
1046 g_snprintf (str, 8, "#%02X%02X%02X", red, green, blue);