data/domains: Drop unused msgs.xsl
[yelp.git] / libyelp / yelp-settings.c
blob155bf82ff52083e55da9a9b1d8c26b169a0fcde7
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 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <stdarg.h>
29 #include <gtk/gtk.h>
30 #include <glib/gi18n.h>
32 #include "yelp-settings.h"
34 struct _YelpSettingsPriv {
35 GMutex *mutex;
37 gchar colors[YELP_SETTINGS_NUM_COLORS][8];
38 gchar *setfonts[YELP_SETTINGS_NUM_FONTS];
39 gchar *fonts[YELP_SETTINGS_NUM_FONTS];
40 gchar *icons[YELP_SETTINGS_NUM_ICONS];
41 gint icon_size;
43 GtkSettings *gtk_settings;
44 GtkIconTheme *gtk_icon_theme;
46 gint font_adjustment;
48 gulong gtk_theme_changed;
49 gulong gtk_font_changed;
50 gulong icon_theme_changed;
52 gboolean show_text_cursor;
54 gboolean editor_mode;
56 GHashTable *tokens;
59 enum {
60 COLORS_CHANGED,
61 FONTS_CHANGED,
62 ICONS_CHANGED,
63 LAST_SIGNAL
65 static guint settings_signals[LAST_SIGNAL] = {0,};
67 enum {
68 PROP_0,
69 PROP_GTK_SETTINGS,
70 PROP_GTK_ICON_THEME,
71 PROP_FONT_ADJUSTMENT,
72 PROP_SHOW_TEXT_CURSOR,
73 PROP_EDITOR_MODE
76 gchar *icon_names[YELP_SETTINGS_NUM_ICONS];
78 G_DEFINE_TYPE (YelpSettings, yelp_settings, G_TYPE_OBJECT);
79 #define GET_PRIV(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_SETTINGS, YelpSettingsPriv))
81 static void yelp_settings_class_init (YelpSettingsClass *klass);
82 static void yelp_settings_init (YelpSettings *settings);
83 static void yelp_settings_constructed (GObject *object);
84 static void yelp_settings_dispose (GObject *object);
85 static void yelp_settings_finalize (GObject *object);
86 static void yelp_settings_get_property (GObject *object,
87 guint prop_id,
88 GValue *value,
89 GParamSpec *pspec);
90 static void yelp_settings_set_property (GObject *object,
91 guint prop_id,
92 const GValue *value,
93 GParamSpec *pspec);
94 static void yelp_settings_set_if_token (YelpSettings *settings,
95 const gchar *token);
97 static void gtk_theme_changed (GtkSettings *gtk_settings,
98 GParamSpec *pspec,
99 YelpSettings *settings);
100 static void gtk_font_changed (GtkSettings *gtk_settings,
101 GParamSpec *pspec,
102 YelpSettings *settings);
103 static void icon_theme_changed (GtkIconTheme *theme,
104 YelpSettings *settings);
106 static void rgb_to_hsv (gdouble r,
107 gdouble g,
108 gdouble b,
109 gdouble *h,
110 gdouble *s,
111 gdouble *v);
112 static void hsv_to_hex (gdouble h,
113 gdouble s,
114 gdouble v,
115 gchar *str);
117 /******************************************************************************/
119 static void
120 yelp_settings_class_init (YelpSettingsClass *klass)
122 GObjectClass *object_class = G_OBJECT_CLASS (klass);
123 gint i;
125 object_class->constructed = yelp_settings_constructed;
126 object_class->dispose = yelp_settings_dispose;
127 object_class->finalize = yelp_settings_finalize;
128 object_class->get_property = yelp_settings_get_property;
129 object_class->set_property = yelp_settings_set_property;
131 for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++) {
132 switch (i) {
133 case YELP_SETTINGS_ICON_BUG:
134 icon_names[i] = "yelp-note-bug";
135 break;
136 case YELP_SETTINGS_ICON_IMPORTANT:
137 icon_names[i] = "yelp-note-important";
138 break;
139 case YELP_SETTINGS_ICON_NOTE:
140 icon_names[i] = "yelp-note";
141 break;
142 case YELP_SETTINGS_ICON_TIP:
143 icon_names[i] = "yelp-note-tip";
144 break;
145 case YELP_SETTINGS_ICON_WARNING:
146 icon_names[i] = "yelp-note-warning";
147 break;
148 default:
149 g_assert_not_reached ();
153 g_object_class_install_property (object_class,
154 PROP_GTK_SETTINGS,
155 g_param_spec_object ("gtk-settings",
156 _("GtkSettings"),
157 _("A GtkSettings object to get settings from"),
158 GTK_TYPE_SETTINGS,
159 G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
160 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
162 g_object_class_install_property (object_class,
163 PROP_GTK_ICON_THEME,
164 g_param_spec_object ("gtk-icon-theme",
165 _("GtkIconTheme"),
166 _("A GtkIconTheme object to get icons from"),
167 GTK_TYPE_ICON_THEME,
168 G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
169 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
171 g_object_class_install_property (object_class,
172 PROP_FONT_ADJUSTMENT,
173 g_param_spec_int ("font-adjustment",
174 _("Font Adjustment"),
175 _("A size adjustment to add to font sizes"),
176 -3, 10, 0,
177 G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
178 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
180 g_object_class_install_property (object_class,
181 PROP_SHOW_TEXT_CURSOR,
182 g_param_spec_boolean ("show-text-cursor",
183 _("Show Text Cursor"),
184 _("Show the text cursor or caret for accessible navigation"),
185 FALSE,
186 G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
187 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
189 g_object_class_install_property (object_class,
190 PROP_EDITOR_MODE,
191 g_param_spec_boolean ("editor-mode",
192 _("Editor Mode"),
193 _("Enable features useful to editors"),
194 FALSE,
195 G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
196 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
198 settings_signals[COLORS_CHANGED] =
199 g_signal_new ("colors-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[FONTS_CHANGED] =
207 g_signal_new ("fonts-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 settings_signals[ICONS_CHANGED] =
215 g_signal_new ("icons-changed",
216 G_OBJECT_CLASS_TYPE (klass),
217 G_SIGNAL_RUN_LAST,
218 0, NULL, NULL,
219 g_cclosure_marshal_VOID__VOID,
220 G_TYPE_NONE, 0);
222 g_type_class_add_private (klass, sizeof (YelpSettingsPriv));
225 static void
226 yelp_settings_init (YelpSettings *settings)
228 gint i;
230 settings->priv = GET_PRIV (settings);
231 settings->priv->mutex = g_mutex_new ();
232 settings->priv->icon_size = 24;
234 for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++)
235 settings->priv->icons[i] = NULL;
236 for (i = 0; i < YELP_SETTINGS_NUM_FONTS; i++) {
237 settings->priv->setfonts[i] = NULL;
238 settings->priv->fonts[i] = NULL;
241 settings->priv->tokens = g_hash_table_new_full (g_str_hash, g_str_equal,
242 g_free, NULL);
245 static void
246 yelp_settings_constructed (GObject *object)
248 YelpSettings *settings = YELP_SETTINGS (object);
249 GDBusConnection *connection;
250 GVariant *ret, *names;
251 GVariantIter iter;
252 gchar *name;
253 gboolean env_shell, env_panel, env_unity, env_xfce;
254 GError *error = NULL;
256 connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
257 if (connection == NULL) {
258 g_warning ("Unable to connect to dbus: %s", error->message);
259 g_error_free (error);
260 return;
263 ret = g_dbus_connection_call_sync (connection,
264 "org.freedesktop.DBus",
265 "/org/freedesktop/DBus",
266 "org.freedesktop.DBus",
267 "ListNames",
268 NULL,
269 G_VARIANT_TYPE ("(as)"),
270 G_DBUS_CALL_FLAGS_NONE,
271 -1, NULL, &error);
272 if (ret == NULL) {
273 g_warning ("Unable to query dbus: %s", error->message);
274 g_error_free (error);
275 return;
277 env_shell = env_panel = env_unity = env_xfce = FALSE;
278 names = g_variant_get_child_value (ret, 0);
279 g_variant_iter_init (&iter, names);
280 while (g_variant_iter_loop (&iter, "&s", &name)) {
281 if (g_str_equal (name, "org.gnome.Panel"))
282 env_panel = TRUE;
283 else if (g_str_equal (name, "org.gnome.Shell"))
284 env_shell = TRUE;
285 else if (g_str_equal (name, "com.canonical.Unity"))
286 env_unity = TRUE;
287 else if (g_str_equal (name, "org.xfce.Panel"))
288 env_xfce = TRUE;
290 g_variant_unref (names);
291 g_variant_unref (ret);
292 if (env_shell)
293 yelp_settings_set_if_token (settings, "platform:gnome-shell");
294 else if (env_xfce)
295 yelp_settings_set_if_token (settings, "platform:xfce");
296 else if (env_unity)
297 yelp_settings_set_if_token (settings, "platform:unity");
298 else if (env_panel)
299 yelp_settings_set_if_token (settings, "platform:gnome-panel");
301 yelp_settings_set_if_token (settings, "action:install");
304 static void
305 yelp_settings_dispose (GObject *object)
307 YelpSettings *settings = YELP_SETTINGS (object);
309 G_OBJECT_CLASS (yelp_settings_parent_class)->dispose (object);
312 static void
313 yelp_settings_finalize (GObject *object)
315 YelpSettings *settings = YELP_SETTINGS (object);
317 g_mutex_free (settings->priv->mutex);
319 g_hash_table_destroy (settings->priv->tokens);
321 G_OBJECT_CLASS (yelp_settings_parent_class)->finalize (object);
324 static void
325 yelp_settings_get_property (GObject *object,
326 guint prop_id,
327 GValue *value,
328 GParamSpec *pspec)
330 YelpSettings *settings = YELP_SETTINGS (object);
332 switch (prop_id) {
333 case PROP_GTK_SETTINGS:
334 g_value_set_object (value, settings->priv->gtk_settings);
335 break;
336 case PROP_GTK_ICON_THEME:
337 g_value_set_object (value, settings->priv->gtk_icon_theme);
338 break;
339 case PROP_FONT_ADJUSTMENT:
340 g_value_set_int (value, settings->priv->font_adjustment);
341 break;
342 case PROP_SHOW_TEXT_CURSOR:
343 g_value_set_boolean (value, settings->priv->show_text_cursor);
344 break;
345 case PROP_EDITOR_MODE:
346 g_value_set_boolean (value, settings->priv->editor_mode);
347 break;
348 default:
349 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
350 break;
354 static void
355 yelp_settings_set_property (GObject *object,
356 guint prop_id,
357 const GValue *value,
358 GParamSpec *pspec)
360 YelpSettings *settings = YELP_SETTINGS (object);
362 switch (prop_id) {
363 case PROP_GTK_SETTINGS:
364 if (settings->priv->gtk_settings) {
365 g_signal_handler_disconnect (settings->priv->gtk_settings,
366 settings->priv->gtk_theme_changed);
367 g_signal_handler_disconnect (settings->priv->gtk_settings,
368 settings->priv->gtk_font_changed);
369 g_object_unref (settings->priv->gtk_settings);
371 settings->priv->gtk_settings = g_value_get_object (value);
372 if (settings->priv->gtk_settings != NULL) {
373 g_object_ref (settings->priv->gtk_settings);
374 settings->priv->gtk_theme_changed =
375 g_signal_connect (settings->priv->gtk_settings,
376 "notify::gtk-theme-name",
377 (GCallback) gtk_theme_changed,
378 settings);
379 settings->priv->gtk_font_changed =
380 g_signal_connect (settings->priv->gtk_settings,
381 "notify::gtk-font-name",
382 (GCallback) gtk_font_changed,
383 settings);
384 gtk_theme_changed (settings->priv->gtk_settings, NULL, settings);
385 gtk_font_changed (settings->priv->gtk_settings, NULL, settings);
387 else {
388 settings->priv->gtk_theme_changed = 0;
389 settings->priv->gtk_font_changed = 0;
391 break;
392 case PROP_GTK_ICON_THEME:
393 if (settings->priv->gtk_icon_theme) {
394 g_signal_handler_disconnect (settings->priv->gtk_icon_theme,
395 settings->priv->icon_theme_changed);
396 g_object_unref (settings->priv->gtk_icon_theme);
398 settings->priv->gtk_icon_theme = g_value_get_object (value);
399 if (settings->priv->gtk_icon_theme != NULL) {
400 gchar **search_path;
401 gint search_path_len, i;
402 gboolean append_search_path = TRUE;
403 gtk_icon_theme_get_search_path (settings->priv->gtk_icon_theme,
404 &search_path, &search_path_len);
405 for (i = search_path_len - 1; i >= 0; i--)
406 if (g_str_equal (search_path[i], YELP_ICON_PATH)) {
407 append_search_path = FALSE;
408 break;
410 if (append_search_path)
411 gtk_icon_theme_append_search_path (settings->priv->gtk_icon_theme,
412 YELP_ICON_PATH);
413 append_search_path = TRUE;
414 for (i = search_path_len - 1; i >= 0; i--)
415 if (g_str_equal (search_path[i], DATADIR"/yelp/icons")) {
416 append_search_path = FALSE;
417 break;
419 if (append_search_path)
420 gtk_icon_theme_append_search_path (settings->priv->gtk_icon_theme,
421 DATADIR"/yelp/icons");
422 g_strfreev (search_path);
423 g_object_ref (settings->priv->gtk_icon_theme);
424 settings->priv->icon_theme_changed =
425 g_signal_connect (settings->priv->gtk_icon_theme,
426 "changed",
427 (GCallback) icon_theme_changed,
428 settings);
429 icon_theme_changed (settings->priv->gtk_icon_theme, settings);
431 else {
432 settings->priv->icon_theme_changed = 0;
434 break;
435 case PROP_FONT_ADJUSTMENT:
436 settings->priv->font_adjustment = g_value_get_int (value);
437 gtk_font_changed (settings->priv->gtk_settings, NULL, settings);
438 break;
439 case PROP_SHOW_TEXT_CURSOR:
440 settings->priv->show_text_cursor = g_value_get_boolean (value);
441 break;
442 case PROP_EDITOR_MODE:
443 settings->priv->editor_mode = g_value_get_boolean (value);
444 break;
445 default:
446 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
447 break;
451 /******************************************************************************/
453 YelpSettings *
454 yelp_settings_get_default (void)
456 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
457 static YelpSettings *settings = NULL;
458 g_static_mutex_lock (&mutex);
459 if (settings == NULL)
460 settings = g_object_new (YELP_TYPE_SETTINGS,
461 "gtk-settings", gtk_settings_get_default (),
462 "gtk-icon-theme", gtk_icon_theme_get_default (),
463 NULL);
464 g_static_mutex_unlock (&mutex);
465 return settings;
468 /******************************************************************************/
470 gchar *
471 yelp_settings_get_color (YelpSettings *settings,
472 YelpSettingsColor color)
474 gchar *colorstr;
475 g_return_val_if_fail (color < YELP_SETTINGS_NUM_COLORS, NULL);
477 g_mutex_lock (settings->priv->mutex);
478 colorstr = g_strdup (settings->priv->colors[color]);
479 g_mutex_unlock (settings->priv->mutex);
481 return colorstr;
484 gchar **
485 yelp_settings_get_colors (YelpSettings *settings)
487 gchar **colors = g_new0 (gchar *, YELP_SETTINGS_NUM_COLORS + 1);
488 gint i;
489 for (i = 0; i < YELP_SETTINGS_NUM_COLORS; i++)
490 colors[i] = yelp_settings_get_color (settings, i);
491 return colors;
494 void
495 yelp_settings_set_colors (YelpSettings *settings,
496 YelpSettingsColor first_color,
497 ...)
499 YelpSettingsColor color;
500 va_list args;
502 g_mutex_lock (settings->priv->mutex);
503 va_start (args, first_color);
505 color = first_color;
506 while ((gint) color >= 0) {
507 gchar *colorstr = va_arg (args, gchar *);
508 gint i;
509 for (i = 0; i < 7; i++) {
510 settings->priv->colors[color][i] = colorstr[i];
511 if (colorstr[i] == '\0')
512 break;
514 settings->priv->colors[color][7] = '\0';
515 color = va_arg (args, YelpSettingsColor);
518 va_end (args);
519 g_mutex_unlock (settings->priv->mutex);
521 g_signal_emit (settings, settings_signals[COLORS_CHANGED], 0);
524 const gchar*
525 yelp_settings_get_color_param (YelpSettingsColor color)
527 static const gchar *params[YELP_SETTINGS_NUM_COLORS] = {
528 "color.background",
529 "color.text",
530 "color.text_light",
531 "color.link",
532 "color.link_visted",
533 "color.gray_background",
534 "color.dark_background",
535 "color.gray_border",
536 "color.blue_background",
537 "color.blue_border",
538 "color.red_background",
539 "color.red_border",
540 "color.yellow_background",
541 "color.yellow_border"
543 g_return_val_if_fail (color < YELP_SETTINGS_NUM_COLORS, NULL);
544 return params[color];
547 /******************************************************************************/
549 gchar *
550 yelp_settings_get_font (YelpSettings *settings,
551 YelpSettingsFont font)
553 gchar *ret;
554 g_return_val_if_fail (font < YELP_SETTINGS_NUM_FONTS, NULL);
556 g_mutex_lock (settings->priv->mutex);
557 if (settings->priv->setfonts[font])
558 ret = g_strdup (settings->priv->setfonts[font]);
559 else
560 ret = g_strdup (settings->priv->fonts[font]);
561 g_mutex_unlock (settings->priv->mutex);
563 return ret;
566 gchar *
567 yelp_settings_get_font_family (YelpSettings *settings,
568 YelpSettingsFont font)
570 const gchar *def = (font == YELP_SETTINGS_FONT_VARIABLE) ? "Sans" : "Monospace";
571 gchar *desc, *ret, *c; /* do not free */
572 g_return_val_if_fail (font < YELP_SETTINGS_NUM_FONTS, NULL);
574 g_mutex_lock (settings->priv->mutex);
576 if (settings->priv->setfonts[font])
577 desc = g_strdup (settings->priv->setfonts[font]);
578 else
579 desc = g_strdup (settings->priv->fonts[font]);
581 if (desc == NULL) {
582 ret = g_strdup (def);
583 goto done;
586 c = strrchr (desc, ' ');
587 if (c == NULL) {
588 g_warning ("Cannot parse font: %s", desc);
589 ret = g_strdup (def);
590 goto done;
593 ret = g_strndup (desc, c - desc);
595 done:
596 g_mutex_unlock (settings->priv->mutex);
597 return ret;
600 gint
601 yelp_settings_get_font_size (YelpSettings *settings,
602 YelpSettingsFont font)
604 gchar *desc, *c; /* do not free */
605 gint ret;
606 g_return_val_if_fail (font < YELP_SETTINGS_NUM_FONTS, 0);
608 g_mutex_lock (settings->priv->mutex);
610 if (settings->priv->setfonts[font])
611 desc = g_strdup (settings->priv->setfonts[font]);
612 else
613 desc = g_strdup (settings->priv->fonts[font]);
615 if (desc == NULL) {
616 ret = 10;
617 goto done;
620 c = strrchr (desc, ' ');
621 if (c == NULL) {
622 g_warning ("Cannot parse font %s", desc);
623 ret = 10;
624 goto done;
627 ret = g_ascii_strtod (c, NULL);
629 done:
630 g_mutex_unlock (settings->priv->mutex);
631 ret += settings->priv->font_adjustment;
632 ret = (ret < 5) ? 5 : ret;
633 return ret;
636 void
637 yelp_settings_set_fonts (YelpSettings *settings,
638 YelpSettingsFont first_font,
639 ...)
641 YelpSettingsFont font;
642 va_list args;
644 g_mutex_lock (settings->priv->mutex);
645 va_start (args, first_font);
647 font = first_font;
648 while ((gint) font >= 0) {
649 gchar *fontname = va_arg (args, gchar *);
650 if (settings->priv->setfonts[font] != NULL)
651 g_free (settings->priv->setfonts[font]);
652 settings->priv->setfonts[font] = g_strdup (fontname);
653 font = va_arg (args, YelpSettingsFont);
656 va_end (args);
657 g_mutex_unlock (settings->priv->mutex);
659 g_signal_emit (settings, settings_signals[FONTS_CHANGED], 0);
662 gint
663 yelp_settings_get_font_adjustment (YelpSettings *settings)
665 return settings->priv->font_adjustment;
668 void
669 yelp_settings_set_font_adjustment (YelpSettings *settings,
670 gint adjustment)
672 g_object_set (settings, "font-adjustment", adjustment, NULL);
675 /******************************************************************************/
677 gint
678 yelp_settings_get_icon_size (YelpSettings *settings)
680 return settings->priv->icon_size;
683 void
684 yelp_settings_set_icon_size (YelpSettings *settings,
685 gint size)
687 settings->priv->icon_size = size;
688 if (settings->priv->gtk_icon_theme != NULL)
689 icon_theme_changed (settings->priv->gtk_icon_theme, settings);
692 gchar *
693 yelp_settings_get_icon (YelpSettings *settings,
694 YelpSettingsIcon icon)
696 gchar *ret;
697 g_return_val_if_fail (icon < YELP_SETTINGS_NUM_ICONS, NULL);
699 g_mutex_lock (settings->priv->mutex);
700 ret = g_strdup (settings->priv->icons[icon]);
701 g_mutex_unlock (settings->priv->mutex);
703 return ret;
706 void
707 yelp_settings_set_icons (YelpSettings *settings,
708 YelpSettingsIcon first_icon,
709 ...)
711 YelpSettingsIcon icon;
712 va_list args;
714 g_mutex_lock (settings->priv->mutex);
715 va_start (args, first_icon);
717 icon = first_icon;
718 while ((gint) icon >= 0) {
719 gchar *filename = va_arg (args, gchar *);
720 if (settings->priv->icons[icon] != NULL)
721 g_free (settings->priv->icons[icon]);
722 settings->priv->icons[icon] = g_filename_to_uri (filename, NULL, NULL);
723 icon = va_arg (args, YelpSettingsIcon);
726 va_end (args);
727 g_mutex_unlock (settings->priv->mutex);
729 g_signal_emit (settings, settings_signals[ICONS_CHANGED], 0);
732 const gchar *
733 yelp_settings_get_icon_param (YelpSettingsIcon icon)
735 static const gchar *params[YELP_SETTINGS_NUM_ICONS] = {
736 "icons.note.bug",
737 "icons.note.important",
738 "icons.note",
739 "icons.note.tip",
740 "icons.note.warning"
742 g_return_val_if_fail (icon < YELP_SETTINGS_NUM_ICONS, NULL);
743 return params[icon];
746 /******************************************************************************/
748 gboolean
749 yelp_settings_get_show_text_cursor (YelpSettings *settings)
751 return settings->priv->show_text_cursor;
754 void
755 yelp_settings_set_show_text_cursor (YelpSettings *settings,
756 gboolean show)
758 g_object_set (settings, "show-text-cursor", show, NULL);
761 gboolean
762 yelp_settings_get_editor_mode (YelpSettings *settings)
764 return settings->priv->editor_mode;
767 void
768 yelp_settings_set_editor_mode (YelpSettings *settings,
769 gboolean editor_mode)
771 g_object_set (settings, "editor-mode", editor_mode, NULL);
774 /******************************************************************************/
776 static void
777 yelp_settings_set_if_token (YelpSettings *settings,
778 const gchar *token)
780 if (g_hash_table_lookup (settings->priv->tokens, token) == NULL) {
781 gchar *ins = g_strdup (token);
782 g_hash_table_insert (settings->priv->tokens, ins, ins);
786 /******************************************************************************/
788 gchar **
789 yelp_settings_get_all_params (YelpSettings *settings,
790 gint extra,
791 gint *end)
793 gchar **params;
794 gint i, ix;
795 GString *envstr;
796 GList *envs, *envi;
798 params = g_new0 (gchar *,
799 (2*YELP_SETTINGS_NUM_COLORS) + (2*YELP_SETTINGS_NUM_ICONS) + extra + 7);
801 for (i = 0; i < YELP_SETTINGS_NUM_COLORS; i++) {
802 gchar *val;
803 ix = 2 * i;
804 params[ix] = g_strdup (yelp_settings_get_color_param (i));
805 val = yelp_settings_get_color (settings, i);
806 params[ix + 1] = g_strdup_printf ("\"%s\"", val);
807 g_free (val);
809 for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++) {
810 gchar *val;
811 ix = 2 * (YELP_SETTINGS_NUM_COLORS + i);
812 params[ix] = g_strdup (yelp_settings_get_icon_param (i));
813 val = yelp_settings_get_icon (settings, i);
814 params[ix + 1] = g_strdup_printf ("\"%s\"", val);
815 g_free (val);
817 ix = 2 * (YELP_SETTINGS_NUM_COLORS + YELP_SETTINGS_NUM_ICONS);
818 params[ix++] = g_strdup ("icons.size.note");
819 params[ix++] = g_strdup_printf ("%i", yelp_settings_get_icon_size (settings));
820 params[ix++] = g_strdup ("yelp.editor_mode");
821 if (settings->priv->editor_mode)
822 params[ix++] = g_strdup ("true()");
823 else
824 params[ix++] = g_strdup ("false()");
826 envstr = g_string_new ("'");
827 envs = g_hash_table_get_keys (settings->priv->tokens);
828 for (envi = envs; envi != NULL; envi = envi->next) {
829 g_string_append_c (envstr, ' ');
830 g_string_append (envstr, (gchar *) envi->data);
832 g_string_append_c (envstr, '\'');
833 g_list_free (envs);
834 params[ix++] = g_strdup ("mal.if.custom");
835 params[ix++] = g_string_free (envstr, FALSE);
837 params[ix] = NULL;
839 if (end != NULL)
840 *end = ix;
841 return params;
844 /******************************************************************************/
846 static void
847 gtk_theme_changed (GtkSettings *gtk_settings,
848 GParamSpec *pspec,
849 YelpSettings *settings)
851 GtkWidget *widget;
852 GtkStyle *style;
853 GdkColor *color;
854 GdkColor blue = { 0, 0x1E1E, 0x3E3E, 0xE7E7 };
855 gdouble base_h, base_s, base_v;
856 gdouble text_h, text_s, text_v;
857 gint i;
859 g_mutex_lock (settings->priv->mutex);
861 style = gtk_rc_get_style_by_paths (gtk_settings,
862 "GtkTextView", "GtkTextView",
863 GTK_TYPE_TEXT_VIEW);
864 if (style)
865 g_object_ref (G_OBJECT (style));
866 else
867 style = gtk_style_new ();
870 rgb_to_hsv (style->text[GTK_STATE_NORMAL].red / 65535.0,
871 style->text[GTK_STATE_NORMAL].green / 65535.0,
872 style->text[GTK_STATE_NORMAL].blue / 65535.0,
873 &text_h, &text_s, &text_v);
874 rgb_to_hsv (style->base[GTK_STATE_NORMAL].red / 65535.0,
875 style->base[GTK_STATE_NORMAL].green / 65535.0,
876 style->base[GTK_STATE_NORMAL].blue / 65535.0,
877 &base_h, &base_s, &base_v);
879 /* YELP_SETTINGS_COLOR_BASE */
880 g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_BASE], 8,
881 "#%02X%02X%02X",
882 style->base[GTK_STATE_NORMAL].red >> 8,
883 style->base[GTK_STATE_NORMAL].green >> 8,
884 style->base[GTK_STATE_NORMAL].blue >> 8);
886 /* YELP_SETTINGS_COLOR_TEXT */
887 g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_TEXT], 8,
888 "#%02X%02X%02X",
889 style->text[GTK_STATE_NORMAL].red >> 8,
890 style->text[GTK_STATE_NORMAL].green >> 8,
891 style->text[GTK_STATE_NORMAL].blue >> 8);
893 /* YELP_SETTINGS_COLOR_LINK */
894 widget = gtk_link_button_new ("http://www.gnome.org");
895 gtk_widget_style_get (widget, "link-color", &color, NULL);
896 if (!color)
897 color = &blue;
898 g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_LINK], 8,
899 "#%02X%02X%02X",
900 color->red >> 8,
901 color->green >> 8,
902 color->blue >> 8);
903 if (color != &blue)
904 gdk_color_free (color);
906 /* YELP_SETTINGS_COLOR_LINK_VISITED */
907 color = NULL;
908 gtk_widget_style_get (widget, "visited-link-color", &color, NULL);
909 if (color) {
910 g_snprintf (settings->priv->colors[YELP_SETTINGS_COLOR_LINK_VISITED], 8,
911 "#%02X%02X%02X",
912 color->red >> 8,
913 color->green >> 8,
914 color->blue >> 8);
915 gdk_color_free (color);
918 g_object_ref_sink (widget);
919 g_object_unref (widget);
921 /* YELP_SETTINGS_COLOR_TEXT_LIGHT */
922 hsv_to_hex (text_h,
923 text_s,
924 text_v - ((text_v - base_v) * 0.25),
925 settings->priv->colors[YELP_SETTINGS_COLOR_TEXT_LIGHT]);
927 /* YELP_SETTINGS_COLOR_GRAY */
928 hsv_to_hex (base_h,
929 base_s,
930 base_v - ((base_v - text_v) * 0.05),
931 settings->priv->colors[YELP_SETTINGS_COLOR_GRAY_BASE]);
932 hsv_to_hex (base_h,
933 base_s,
934 base_v - ((base_v - text_v) * 0.1),
935 settings->priv->colors[YELP_SETTINGS_COLOR_DARK_BASE]);
936 hsv_to_hex (base_h,
937 base_s,
938 base_v - ((base_v - text_v) * 0.26),
939 settings->priv->colors[YELP_SETTINGS_COLOR_GRAY_BORDER]);
941 /* YELP_SETTINGS_COLOR_BLUE */
942 hsv_to_hex (211,
943 0.1,
944 base_v - ((base_v - text_v) * 0.01),
945 settings->priv->colors[YELP_SETTINGS_COLOR_BLUE_BASE]);
946 hsv_to_hex (211,
947 0.45,
948 base_v - ((base_v - text_v) * 0.19),
949 settings->priv->colors[YELP_SETTINGS_COLOR_BLUE_BORDER]);
951 /* YELP_SETTINGS_COLOR_RED */
952 hsv_to_hex (0,
953 0.13,
954 base_v - ((base_v - text_v) * 0.01),
955 settings->priv->colors[YELP_SETTINGS_COLOR_RED_BASE]);
956 hsv_to_hex (0,
957 0.83,
958 base_v - ((base_v - text_v) * 0.06),
959 settings->priv->colors[YELP_SETTINGS_COLOR_RED_BORDER]);
961 /* YELP_SETTINGS_COLOR_YELLOW */
962 hsv_to_hex (60,
963 0.25,
964 base_v - ((base_v - text_v) * 0.01),
965 settings->priv->colors[YELP_SETTINGS_COLOR_YELLOW_BASE]);
966 hsv_to_hex (60,
967 1.0,
968 base_v - ((base_v - text_v) * 0.07),
969 settings->priv->colors[YELP_SETTINGS_COLOR_YELLOW_BORDER]);
971 g_object_unref (G_OBJECT (style));
973 g_mutex_unlock (settings->priv->mutex);
975 g_signal_emit (settings, settings_signals[COLORS_CHANGED], 0);
978 static void
979 gtk_font_changed (GtkSettings *gtk_settings,
980 GParamSpec *pspec,
981 YelpSettings *settings)
983 gchar *font, *c;
985 /* This happens when font_adjustment is set during init */
986 if (gtk_settings == NULL)
987 return;
989 g_free (settings->priv->fonts[YELP_SETTINGS_FONT_VARIABLE]);
990 g_object_get (gtk_settings, "gtk-font-name", &font, NULL);
991 settings->priv->fonts[YELP_SETTINGS_FONT_VARIABLE] = font;
993 c = strrchr (font, ' ');
994 if (c == NULL) {
995 g_warning ("Cannot parse font: %s", font);
996 font = g_strdup ("Monospace 10");
998 else {
999 font = g_strconcat ("Monospace", c, NULL);
1002 g_free (settings->priv->fonts[YELP_SETTINGS_FONT_FIXED]);
1003 settings->priv->fonts[YELP_SETTINGS_FONT_FIXED] = font;
1005 g_signal_emit (settings, settings_signals[FONTS_CHANGED], 0);
1008 static void
1009 icon_theme_changed (GtkIconTheme *theme,
1010 YelpSettings *settings)
1012 GtkIconInfo *info;
1013 gint i;
1015 g_mutex_lock (settings->priv->mutex);
1017 for (i = 0; i < YELP_SETTINGS_NUM_ICONS; i++) {
1018 if (settings->priv->icons[i] != NULL)
1019 g_free (settings->priv->icons[i]);
1020 info = gtk_icon_theme_lookup_icon (theme,
1021 icon_names[i],
1022 settings->priv->icon_size,
1023 GTK_ICON_LOOKUP_NO_SVG);
1024 if (info != NULL) {
1025 settings->priv->icons[i] = g_filename_to_uri (gtk_icon_info_get_filename (info),
1026 NULL, NULL);
1027 gtk_icon_info_free (info);
1029 else {
1030 settings->priv->icons[i] = NULL;
1034 g_mutex_unlock (settings->priv->mutex);
1036 g_signal_emit (settings, settings_signals[ICONS_CHANGED], 0);
1039 gint
1040 yelp_settings_cmp_icons (const gchar *icon1,
1041 const gchar *icon2)
1043 static const gchar *icons[] = {
1044 "yelp-page-search-symbolic",
1045 "yelp-page-video-symbolic",
1046 "yelp-page-task-symbolic",
1047 "yelp-page-tip-symbolic",
1048 "yelp-page-problem-symbolic",
1049 "yelp-page-ui-symbolic",
1050 "yelp-page-symbolic",
1051 NULL
1053 gint i;
1054 for (i = 0; icons[i] != NULL; i++) {
1055 gboolean eq1 = icon1 ? g_str_has_prefix (icon1, icons[i]) : FALSE;
1056 gboolean eq2 = icon2 ? g_str_has_prefix (icon2, icons[i]) : FALSE;
1057 if (eq1 && eq2)
1058 return 0;
1059 else if (eq1)
1060 return -1;
1061 else if (eq2)
1062 return 1;
1064 if (icon1 == NULL && icon2 == NULL)
1065 return 0;
1066 else if (icon2 == NULL)
1067 return -1;
1068 else if (icon1 == NULL)
1069 return 1;
1070 else
1071 return strcmp (icon1, icon2);
1074 /******************************************************************************/
1076 static void
1077 rgb_to_hsv (gdouble r, gdouble g, gdouble b, gdouble *h, gdouble *s, gdouble *v)
1079 gdouble min, max, delta;
1081 max = (r > g) ? r : g;
1082 max = (max > b) ? max : b;
1083 min = (r < g) ? r : g;
1084 min = (min < b) ? min : b;
1086 delta = max - min;
1088 *v = max;
1089 *s = 0;
1090 *h = 0;
1092 if (max != min) {
1093 *s = delta / *v;
1095 if (r == max)
1096 *h = (g - b) / delta;
1097 else if (g == max)
1098 *h = 2 + (b - r) / delta;
1099 else if (b == max)
1100 *h = 4 + (r - g) / delta;
1102 *h *= 60;
1103 if (*h < 0.0)
1104 *h += 360;
1108 static void
1109 hsv_to_hex (gdouble h, gdouble s, gdouble v, gchar *str)
1111 gint hue;
1112 gdouble c;
1113 gdouble m1, m2, m3;
1114 gdouble r, g, b;
1115 guint8 red, green, blue;
1117 c = v * s;
1118 h /= 60;
1119 hue = (int) h;
1120 m1 = v * (1 - s);
1121 m2 = v * (1 - s * (h - hue));
1122 m3 = v * (1 - s * (-h + hue + 1));
1124 r = g = b = v;
1125 switch (hue) {
1126 case 0:
1127 b = m1; g = m3; break;
1128 case 1:
1129 b = m1; r = m2; break;
1130 case 2:
1131 r = m1; b = m3; break;
1132 case 3:
1133 r = m1; g = m2; break;
1134 case 4:
1135 g = m1; r = m3; break;
1136 case 5:
1137 g = m1; b = m2; break;
1140 red = r * 255;
1141 green = g * 255;
1142 blue = b * 255;
1143 g_snprintf (str, 8, "#%02X%02X%02X", red, green, blue);