git: Implement the Tags pane
[anjuta.git] / libanjuta / anjuta-preferences.c
bloba705f1da88708312a9738fd777a0dbc0664f37b7
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * preferences.c
4 * Copyright (C) 2000 - 2003 Naba Kumar <naba@gnome.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 /**
22 * SECTION:anjuta-preferences
23 * @short_description: Anjuta Prefereces system.
24 * @see_also: #AnjutaPreferencesDialog
25 * @stability: Unstable
26 * @include: libanjuta/anjuta-preferences.h
28 * #AnjutaPreferences is a way to let plugins register their preferences. There
29 * are mainly two ways a plugin could register its preferences in Anjuta.
31 * First is to not use #AnjutaPreferences at all. Simply register a
32 * preferences page in #AnjutaPreferencesDialog using the function
33 * anjuta_preferences_dialog_add_page(). The plugin should take
34 * care of loading, saving and widgets synchronization of the
35 * preferences values. It is particularly useful if the plugin
36 * uses gconf system for its preferences. Also no "changed"
37 * signal will be emitted from it.
39 * Second is to use anjuta_preferences_add_page(), which will
40 * automatically register the preferences keys and values from
41 * a glade xml file. The glade xml file contains a preferences
42 * page of the plugin. The widget names in the page are
43 * given in a particular way (see anjuta_preferences_add_page()) to
44 * let it know property key details. Loading, saving and
45 * widget synchronization are automatically done. "changed" signal is
46 * emitted when a preference is changed.
48 * anjuta_preferences_register_all_properties_from_glade_xml() only registers
49 * the preferences propery keys for automatic loading, saving and widget
50 * syncrhronization, but does not add the page in preferences dialog. It
51 * is useful if the plugin wants to show the preferences page somewhere else.
53 * anjuta_preferences_register_property_from_string() is similar to
54 * anjuta_preferences_register_all_properties_from_glade_xml(), but it only
55 * registers one property, the detail of which is given in its arguments.
56 * anjuta_preferences_register_property_custom() is used to register a
57 * property that uses a widget which is not supported by #AnjutaPreferences.
60 #ifdef HAVE_CONFIG_H
61 # include <config.h>
62 #endif
64 #include <sys/stat.h>
65 #include <unistd.h>
66 #include <string.h>
67 #include <stdlib.h>
69 #include <gconf/gconf-client.h>
71 #include <libanjuta/anjuta-preferences.h>
72 #include <libanjuta/anjuta-utils.h>
73 #include <libanjuta/resources.h>
74 #include <libanjuta/anjuta-debug.h>
75 #include <libanjuta/interfaces/ianjuta-preferences.h>
77 /* AnjutaPreferences is a singleton */
78 static AnjutaPreferences* default_preferences = NULL;
80 struct _AnjutaProperty
82 GtkWidget *object;
83 gchar *key;
84 gchar *default_value;
85 guint flags;
86 gint notify_id;
87 GConfClient *gclient;
89 /* Set true if custom set/get to be used */
90 gboolean custom;
92 /* For inbuilt generic objects */
93 AnjutaPropertyObjectType object_type;
94 AnjutaPropertyDataType data_type;
96 /* For custom objects */
97 void (*set_property) (AnjutaProperty *prop, const gchar *value);
98 gchar * (*get_property) (AnjutaProperty *prop);
102 struct _AnjutaPreferencesPriv
104 GConfClient *gclient;
105 GHashTable *properties;
106 GtkWidget *prefs_dialog;
107 AnjutaPluginManager *plugin_manager;
108 gboolean is_showing;
110 GHashTable *notifications;
113 /* Internal structure for anjuta_preferences_foreach */
114 struct _AnjutaPreferencesForeachData
116 AnjutaPreferences *pr;
117 AnjutaPreferencesCallback callback;
118 gpointer callback_data;
121 /* Data for notifications */
123 #define PREFERENCE_PROPERTY_PREFIX "preferences_"
124 #define GCONF_KEY_PREFIX "/apps/anjuta/preferences"
126 static const gchar *
127 build_key (const gchar *key)
129 static gchar buffer[1024];
130 snprintf (buffer, 1024, "%s/%s", GCONF_KEY_PREFIX, key);
131 return buffer;
134 static const gchar*
135 unbuild_key (const gchar* key)
137 if (g_str_has_prefix (key, GCONF_KEY_PREFIX))
138 return key + strlen (GCONF_KEY_PREFIX);
139 return NULL;
143 * anjuta_preferences_get:
144 * @pr: A #AnjutaPreferences object
145 * @key: Property key
147 * Gets the value of @key as string. Returned string should be g_freed() when not
148 * required.
150 * Return value: Key value as string or NULL if the key is not defined.
152 #ifdef __GNUC__
153 inline
154 #endif
155 gchar *
156 anjuta_preferences_get (AnjutaPreferences *pr, const gchar *key)
158 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), NULL);
159 g_return_val_if_fail (key != NULL, NULL);
161 return gconf_client_get_string (pr->priv->gclient, build_key (key), NULL);
165 * anjuta_preferences_get_int:
166 * @pr: A #AnjutaPreferences object
167 * @key: Property key
169 * Gets the value of @key as integer.
171 * Return value: Key value as integer or 0 if the key is not defined.
173 #ifdef __GNUC__
174 inline
175 #endif
176 gint
177 anjuta_preferences_get_int (AnjutaPreferences *pr, const gchar *key)
179 gint ret_val;
180 GConfValue *value;
182 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), 0);
183 g_return_val_if_fail (key != NULL, 0);
185 ret_val = 0;
186 value = gconf_client_get (pr->priv->gclient, build_key (key), NULL);
187 if (value)
189 switch (value->type)
191 case GCONF_VALUE_INT:
192 ret_val = gconf_value_get_int (value);
193 break;
194 default:
195 g_warning ("Invalid gconf type for key: %s", key);
197 gconf_value_free (value);
199 else
200 DEBUG_PRINT ("The preference key %s is not defined", key);
201 return ret_val;
205 * anjuta_preferences_get_int:
206 * @pr: A #AnjutaPreferences object
207 * @key: Property key
209 * Gets the value of @key as integer.
211 * Return value: Key value as boolean or FALSE if the key is not defined.
213 #ifdef __GNUC__
214 inline
215 #endif
216 gint
217 anjuta_preferences_get_bool (AnjutaPreferences *pr, const gchar *key)
219 gboolean ret_val;
220 GConfValue *value;
222 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), 0);
223 g_return_val_if_fail (key != NULL, 0);
225 ret_val = FALSE;
226 value = gconf_client_get (pr->priv->gclient, build_key (key), NULL);
227 if (value)
229 switch (value->type)
231 case GCONF_VALUE_BOOL:
232 ret_val = gconf_value_get_bool (value);
233 break;
234 case GCONF_VALUE_INT:
235 ret_val = (gboolean) gconf_value_get_int (value);
236 default:
237 g_warning ("Invalid gconf type for key: %s", key);
239 gconf_value_free (value);
241 else
242 DEBUG_PRINT ("The preference key %s is not defined", key);
243 return ret_val;
247 * anjuta_preferences_get_int_with_default:
248 * @pr: A #AnjutaPreferences object
249 * @key: Property key
250 * @default_value: Default value to return if the key is not defined.
252 * Gets the value of @key as integer.
254 * Return value: Key value as integer or @default_value if the
255 * key is not defined.
257 #ifdef __GNUC__
258 inline
259 #endif
260 gint
261 anjuta_preferences_get_int_with_default (AnjutaPreferences *pr,
262 const gchar *key, gint default_value)
264 gint ret_val;
265 GConfValue *value;
267 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), 0);
268 g_return_val_if_fail (key != NULL, 0);
270 ret_val = default_value;
271 value = gconf_client_get (pr->priv->gclient, build_key (key), NULL);
272 if (value)
274 switch (value->type)
276 case GCONF_VALUE_INT:
277 ret_val = gconf_value_get_int (value);
278 break;
279 default:
280 g_warning ("Invalid gconf type for key: %s", key);
282 gconf_value_free (value);
284 return ret_val;
288 * anjuta_preferences_get_int_with_default:
289 * @pr: A #AnjutaPreferences object
290 * @key: Property key
291 * @default_value: Default value to return if the key is not defined.
293 * Gets the value of @key as integer.
295 * Return value: Key value as integer or @default_value if the
296 * key is not defined.
298 #ifdef __GNUC__
299 inline
300 #endif
301 gint
302 anjuta_preferences_get_bool_with_default (AnjutaPreferences *pr,
303 const gchar *key, gboolean default_value)
305 gboolean ret_val;
306 GConfValue *value;
308 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), 0);
309 g_return_val_if_fail (key != NULL, 0);
311 ret_val = default_value;
312 value = gconf_client_get (pr->priv->gclient, build_key (key), NULL);
313 if (value)
315 switch (value->type)
317 case GCONF_VALUE_BOOL:
318 ret_val = gconf_value_get_bool (value);
319 break;
320 case GCONF_VALUE_INT:
321 ret_val = (gboolean) gconf_value_get_int (value);
322 default:
323 g_warning ("Invalid gconf type for key: %s", key);
325 gconf_value_free (value);
327 return ret_val;
331 * anjuta_preferences_default_get:
332 * @pr: A #AnjutaPreferences object
333 * @key: Property key
335 * Gets the default value of @key as string. The default value of the key
336 * is the value defined in System defaults (generally installed during
337 * program installation). Returned value must be g_freed() when not required.
339 * Return value: Default key value as string or NULL if not defined.
341 #ifdef __GNUC__
342 inline
343 #endif
344 gchar *
345 anjuta_preferences_default_get (AnjutaPreferences * pr, const gchar * key)
347 GConfValue *val;
348 gchar *str;
349 GError *err = NULL;
351 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), NULL);
352 g_return_val_if_fail (key != NULL, NULL);
354 val = gconf_client_get_default_from_schema (pr->priv->gclient, build_key (key), &err);
355 if (err) {
356 g_error_free (err);
357 return NULL;
359 str = g_strdup (gconf_value_get_string (val));
360 gconf_value_free (val);
361 return str;
365 * anjuta_preferences_default_get_int:
366 * @pr: A #AnjutaPreferences object
367 * @key: Property key
369 * Gets the default value of @key as integer. The default value of the key
370 * is the value defined in System defaults (generally installed during
371 * program installation).
373 * Return value: Default key value as integer or 0 if the key is not defined.
375 #ifdef __GNUC__
376 inline
377 #endif
378 gint
379 anjuta_preferences_default_get_int (AnjutaPreferences *pr, const gchar *key)
381 GConfValue *val;
382 gint ret;
383 GError *err = NULL;
385 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), 0);
386 g_return_val_if_fail (key != NULL, 0);
387 val = gconf_client_get_default_from_schema (pr->priv->gclient, build_key (key), &err);
388 if (err) {
389 g_error_free (err);
390 return 0;
392 ret = gconf_value_get_int (val);
393 gconf_value_free (val);
394 return ret;
398 * anjuta_preferences_default_get_int:
399 * @pr: A #AnjutaPreferences object
400 * @key: Property key
402 * Gets the default value of @key as integer. The default value of the key
403 * is the value defined in System defaults (generally installed during
404 * program installation).
406 * Return value: Default key value as integer or 0 if the key is not defined.
408 #ifdef __GNUC__
409 inline
410 #endif
411 gboolean
412 anjuta_preferences_default_get_bool (AnjutaPreferences *pr, const gchar *key)
414 GConfValue *val;
415 gint ret;
416 GError *err = NULL;
418 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), 0);
419 g_return_val_if_fail (key != NULL, 0);
420 val = gconf_client_get_default_from_schema (pr->priv->gclient, build_key (key), &err);
421 if (err) {
422 g_error_free (err);
423 return 0;
425 ret = gconf_value_get_bool (val);
426 gconf_value_free (val);
427 return ret;
431 * anjuta_preferences_set:
432 * @pr: A #AnjutaPreferences object.
433 * @key: Property key.
434 * @value: Value of the key.
436 * Sets the value of @key in current session.
438 #ifdef __GNUC__
439 inline
440 #endif
441 void
442 anjuta_preferences_set (AnjutaPreferences *pr, const gchar *key,
443 const gchar *value)
445 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
446 g_return_if_fail (key != NULL);
448 if (value && (strlen (value) > 0))
450 gconf_client_set_string (pr->priv->gclient, build_key (key), value, NULL);
452 else
454 gconf_client_set_string (pr->priv->gclient, build_key (key), "", NULL);
459 * anjuta_preferences_set_int:
460 * @pr: A #AnjutaPreferences object.
461 * @key: Property key.
462 * @value: Integer value of the key.
464 * Sets the value of @key in current session.
466 #ifdef __GNUC__
467 inline
468 #endif
469 void
470 anjuta_preferences_set_int (AnjutaPreferences *pr, const gchar *key,
471 gint value)
473 GConfValue *gvalue;
475 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
476 g_return_if_fail (key != NULL);
478 gvalue = gconf_client_get (pr->priv->gclient, build_key (key), NULL);
479 if (gvalue)
481 switch (gvalue->type)
483 case GCONF_VALUE_INT:
484 gconf_client_set_int (pr->priv->gclient, build_key (key),
485 value, NULL);
486 break;
487 default:
488 g_warning ("Invalid gconf type for key: %s", key);
490 gconf_value_free (gvalue);
492 else
494 DEBUG_PRINT ("The preference key %s is not defined", key);
495 gconf_client_set_int (pr->priv->gclient, build_key (key),
496 value, NULL);
501 * anjuta_preferences_set_bool:
502 * @pr: A #AnjutaPreferences object.
503 * @key: Property key.
504 * @value: Boolean value of the key.
506 * Sets the value of @key in current session.
508 #ifdef __GNUC__
509 inline
510 #endif
511 void
512 anjuta_preferences_set_bool (AnjutaPreferences *pr, const gchar *key,
513 gboolean value)
515 GConfValue *gvalue;
517 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
518 g_return_if_fail (key != NULL);
520 gvalue = gconf_client_get (pr->priv->gclient, build_key (key), NULL);
521 if (gvalue)
523 switch (gvalue->type)
525 case GCONF_VALUE_INT:
526 g_warning ("Invalid gconf type for key: %s", key);
527 case GCONF_VALUE_BOOL:
528 gconf_client_set_bool (pr->priv->gclient, build_key (key),
529 value, NULL);
530 break;
531 default:
532 g_warning ("Invalid gconf type for key: %s", key);
534 gconf_value_free (gvalue);
536 else
538 DEBUG_PRINT ("The preference key %s is not defined", key);
539 gconf_client_set_bool (pr->priv->gclient, build_key (key),
540 value, NULL);
544 static void
545 property_destroy (AnjutaProperty *property)
547 g_return_if_fail (property);
548 if (property->key) g_free (property->key);
549 if (property->default_value) g_free (property->default_value);
550 g_object_unref (property->object);
551 gconf_client_notify_remove (property->gclient, property->notify_id);
552 g_free (property);
556 * anjuta_property_get_widget:
557 * @prop: an #AnjutaProperty reference
559 * Gets the widget associated with the property.
561 * Returns: a #GtkWidget object associated with the property.
563 GtkWidget*
564 anjuta_property_get_widget (AnjutaProperty *prop)
566 return prop->object;
569 static AnjutaPropertyObjectType
570 get_object_type_from_string (const gchar* object_type)
572 if (strcmp (object_type, "entry") == 0)
573 return ANJUTA_PROPERTY_OBJECT_TYPE_ENTRY;
574 else if (strcmp (object_type, "combo") == 0)
575 return ANJUTA_PROPERTY_OBJECT_TYPE_COMBO;
576 else if (strcmp (object_type, "spin") == 0)
577 return ANJUTA_PROPERTY_OBJECT_TYPE_SPIN;
578 else if (strcmp (object_type, "toggle") == 0)
579 return ANJUTA_PROPERTY_OBJECT_TYPE_TOGGLE;
580 else if (strcmp (object_type, "text") == 0)
581 return ANJUTA_PROPERTY_OBJECT_TYPE_TEXT;
582 else if (strcmp (object_type, "color") == 0)
583 return ANJUTA_PROPERTY_OBJECT_TYPE_COLOR;
584 else if (strcmp (object_type, "font") == 0)
585 return ANJUTA_PROPERTY_OBJECT_TYPE_FONT;
586 else if (strcmp (object_type, "file") == 0)
587 return ANJUTA_PROPERTY_OBJECT_TYPE_FILE;
588 else if (strcmp (object_type, "folder") == 0)
589 return ANJUTA_PROPERTY_OBJECT_TYPE_FOLDER;
590 else
591 return (AnjutaPropertyObjectType)(-1);
594 static AnjutaPropertyDataType
595 get_data_type_from_string (const gchar* data_type)
597 if (strcmp (data_type, "bool") == 0)
598 return ANJUTA_PROPERTY_DATA_TYPE_BOOL;
599 else if (strcmp (data_type, "int") == 0)
600 return ANJUTA_PROPERTY_DATA_TYPE_INT;
601 else if (strcmp (data_type, "text") == 0)
602 return ANJUTA_PROPERTY_DATA_TYPE_TEXT;
603 else if (strcmp (data_type, "color") == 0)
604 return ANJUTA_PROPERTY_DATA_TYPE_COLOR;
605 else if (strcmp (data_type, "font") == 0)
606 return ANJUTA_PROPERTY_DATA_TYPE_FONT;
607 else
608 return (AnjutaPropertyDataType)(-1);
611 static gchar*
612 get_property_value_as_string (AnjutaProperty *prop)
614 gint int_value;
615 gchar** values;
616 gchar *text_value = NULL;
618 if (prop->custom)
620 if (prop->get_property != NULL)
621 return prop->get_property (prop);
622 else
624 g_warning ("%s: Undefined get_property() for custom object",
625 prop->key);
626 return NULL;
629 switch (prop->object_type)
631 case ANJUTA_PROPERTY_OBJECT_TYPE_TOGGLE:
632 int_value =
633 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (prop->object));
634 text_value = g_strdup_printf ("%d", int_value);
635 break;
637 case ANJUTA_PROPERTY_OBJECT_TYPE_SPIN:
638 int_value =
639 gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (prop->object));
640 text_value = g_strdup_printf ("%d", int_value);
641 break;
643 case ANJUTA_PROPERTY_OBJECT_TYPE_ENTRY:
644 text_value =
645 gtk_editable_get_chars (GTK_EDITABLE (prop->object), 0, -1);
646 break;
647 case ANJUTA_PROPERTY_OBJECT_TYPE_COMBO:
649 gint idx;
650 values = g_object_get_data(G_OBJECT(prop->object), "untranslated");
651 idx = gtk_combo_box_get_active(GTK_COMBO_BOX(prop->object));
652 if (values[idx] != NULL)
653 text_value = g_strdup(values[idx]);
654 break;
656 case ANJUTA_PROPERTY_OBJECT_TYPE_TEXT:
658 GtkTextBuffer *buffer;
659 GtkTextIter start_iter;
660 GtkTextIter end_iter;
661 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (prop->object));
662 gtk_text_buffer_get_start_iter (buffer, &start_iter);
663 gtk_text_buffer_get_end_iter (buffer, &end_iter);
664 text_value =
665 gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, TRUE);
666 break;
668 case ANJUTA_PROPERTY_OBJECT_TYPE_COLOR:
670 GdkColor color;
671 gtk_color_button_get_color(GTK_COLOR_BUTTON (prop->object),
672 &color);
673 text_value = anjuta_util_string_from_color (color.red, color.green, color.blue);
675 break;
676 case ANJUTA_PROPERTY_OBJECT_TYPE_FONT:
678 const gchar *font;
679 font = gtk_font_button_get_font_name (GTK_FONT_BUTTON
680 (prop->object));
681 text_value = g_strdup (font);
683 break;
684 case ANJUTA_PROPERTY_OBJECT_TYPE_FOLDER:
685 case ANJUTA_PROPERTY_OBJECT_TYPE_FILE:
686 text_value = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (prop->object));
687 break;
689 if (text_value && (strlen (text_value) == 0))
691 g_free (text_value);
692 text_value = NULL;
694 return text_value;
697 static gint
698 get_property_value_as_int (AnjutaProperty *prop)
700 gint int_value;
701 gchar *text_value;
702 text_value = get_property_value_as_string (prop);
703 int_value = atoi (text_value);
704 g_free (text_value);
705 return int_value;
708 static void
709 set_property_value_as_string (AnjutaProperty *prop, const gchar *value)
711 gint int_value;
712 char** values;
713 gint i;
715 if (prop->custom)
717 if (prop->set_property != NULL)
719 prop->set_property (prop, value);
720 return;
722 else
724 g_warning ("%s: Undefined set_property() for custom object",
725 prop->key);
726 return;
729 switch (prop->object_type)
731 case ANJUTA_PROPERTY_OBJECT_TYPE_TOGGLE:
732 if (value)
733 int_value = atoi (value);
734 else
735 int_value = 0;
737 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prop->object),
738 int_value);
739 break;
741 case ANJUTA_PROPERTY_OBJECT_TYPE_SPIN:
742 if (value)
743 int_value = atoi (value);
744 else
745 int_value = 0;
747 gtk_spin_button_set_value (GTK_SPIN_BUTTON (prop->object), int_value);
748 break;
750 case ANJUTA_PROPERTY_OBJECT_TYPE_ENTRY:
751 if (value)
752 gtk_entry_set_text (GTK_ENTRY (prop->object), value);
753 else
754 gtk_entry_set_text (GTK_ENTRY (prop->object), "");
755 break;
756 case ANJUTA_PROPERTY_OBJECT_TYPE_COMBO:
757 values = g_object_get_data(G_OBJECT(prop->object), "untranslated");
758 if (value != NULL)
760 for (i=0; values[i] != NULL; i++)
762 if (strcmp(value, values[i]) == 0)
764 gtk_combo_box_set_active(GTK_COMBO_BOX(prop->object), i);
765 break;
769 break;
770 case ANJUTA_PROPERTY_OBJECT_TYPE_TEXT:
772 GtkTextBuffer *buffer;
773 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (prop->object));
774 if (value)
775 gtk_text_buffer_set_text (buffer, value, -1);
776 else
777 gtk_text_buffer_set_text (buffer, "", -1);
779 break;
781 case ANJUTA_PROPERTY_OBJECT_TYPE_COLOR:
783 GdkColor color;
785 if (value)
786 anjuta_util_color_from_string (value, &color.red, &color.green, &color.blue);
788 gtk_color_button_set_color(GTK_COLOR_BUTTON(prop->object), &color);
790 break;
792 case ANJUTA_PROPERTY_OBJECT_TYPE_FONT:
793 if (value)
795 /* If the font name is Xfont name, convert it into
796 Pango font description text -- Just take the family name :) */
797 if (value[0] == '-')
799 /* Font is xfont name */
800 gchar *font_name, *tmp;
801 const gchar *end, *start;
802 start = value;
803 start = g_strstr_len (&start[1], strlen (&start[1]), "-");
804 end = g_strstr_len (&start[1], strlen (&start[1]), "-");
805 font_name = g_strndup (&start[1], end-start-1);
806 tmp = font_name;
808 /* Set font size to (arbitrary) 12 points */
809 font_name = g_strconcat (tmp, " 12", NULL);
810 g_free (tmp);
812 /* DEBUG_PRINT ("Font set as: %s", font_name); */
814 gtk_font_button_set_font_name (GTK_FONT_BUTTON
815 (prop->object), font_name);
816 g_free (font_name);
818 else
820 gtk_font_button_set_font_name (GTK_FONT_BUTTON
821 (prop->object), value);
824 break;
826 case ANJUTA_PROPERTY_OBJECT_TYPE_FOLDER:
827 if (value)
829 gchar *old_folder;
831 /* When the user change the folder, the
832 * current-folder-changed signal is emitted the
833 * gconf key is updated and this function is called.
834 * But setting the current folder here emits
835 * the current-folder-changed signal too.
836 * Moreover this signal is emitted asynchronously so
837 * it is not possible to block it here.
839 * The solution here is to update the widget only
840 * if it is really needed.
842 old_folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (prop->object));
843 if ((old_folder == NULL) || strcmp (old_folder, value))
845 gchar *expand_value = anjuta_util_shell_expand (value);
846 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (prop->object), expand_value);
847 g_free (expand_value);
849 g_free (old_folder);
851 break;
852 case ANJUTA_PROPERTY_OBJECT_TYPE_FILE:
853 if (value)
855 gchar *expand_value = anjuta_util_shell_expand (value);
856 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (prop->object),
857 expand_value);
858 g_free (expand_value);
860 break;
864 static void
865 set_property_value_as_int (AnjutaProperty *prop, gint value)
867 gchar *text_value;
868 text_value = g_strdup_printf ("%d", value);
869 set_property_value_as_string (prop, text_value);
870 g_free (text_value);
873 static void
874 set_property_value_as_bool (AnjutaProperty *prop, gboolean value)
876 gchar *text_value;
877 text_value = g_strdup_printf ("%d", value);
878 set_property_value_as_string (prop, text_value);
879 g_free (text_value);
882 static gboolean
883 update_property_on_event_str (GtkWidget *widget, GdkEvent *event,
884 gpointer user_data)
886 AnjutaPreferences *pr;
887 AnjutaProperty *p;
888 gchar *val;
890 pr = ANJUTA_PREFERENCES (g_object_get_data (G_OBJECT (widget),
891 "AnjutaPreferences"));
892 p = (AnjutaProperty *) user_data;
893 val = get_property_value_as_string (p);
894 anjuta_preferences_set (pr, p->key, val);
895 g_free (val);
896 return FALSE;
899 static void
900 update_property_on_change_str (GtkWidget *widget, gpointer user_data)
902 AnjutaPreferences *pr;
903 AnjutaProperty *p;
904 gchar *val;
906 pr = ANJUTA_PREFERENCES (g_object_get_data (G_OBJECT (widget),
907 "AnjutaPreferences"));
908 p = (AnjutaProperty *) user_data;
909 val = get_property_value_as_string (p);
910 anjuta_preferences_set (pr, p->key, val);
911 g_free (val);
914 static gboolean
915 block_update_property_on_change_str (GtkWidget *widget, GdkEvent *event,
916 gpointer user_data)
918 AnjutaProperty *p = (AnjutaProperty *) user_data;
920 g_signal_handlers_block_by_func (G_OBJECT(p->object), G_CALLBACK (update_property_on_change_str), p);
921 return FALSE;
924 static gboolean
925 unblock_update_property_on_change_str (GtkWidget *widget, GdkEvent *event,
926 gpointer user_data)
928 AnjutaProperty *p = (AnjutaProperty *) user_data;
930 g_signal_handlers_unblock_by_func (G_OBJECT(p->object), G_CALLBACK (update_property_on_change_str), p);
931 return FALSE;
934 static void
935 update_property_on_change_int (GtkWidget *widget, gpointer user_data)
937 AnjutaPreferences *pr;
938 AnjutaProperty *p;
939 gint val;
941 pr = ANJUTA_PREFERENCES (g_object_get_data (G_OBJECT (widget),
942 "AnjutaPreferences"));
943 p = (AnjutaProperty *) user_data;
944 val = get_property_value_as_int (p);
945 anjuta_preferences_set_int (pr, p->key, val);
948 static void
949 update_property_on_change_bool (GtkWidget *widget, gpointer user_data)
951 AnjutaPreferences *pr;
952 AnjutaProperty *p;
953 gint val;
955 pr = ANJUTA_PREFERENCES (g_object_get_data (G_OBJECT (widget),
956 "AnjutaPreferences"));
957 p = (AnjutaProperty *) user_data;
958 val = get_property_value_as_int (p);
959 anjuta_preferences_set_bool (pr, p->key, val);
962 static void
963 update_property_on_change_color (GtkWidget *widget, gpointer user_data)
965 AnjutaPreferences *pr;
966 AnjutaProperty *p;
967 gchar *val;
969 pr = ANJUTA_PREFERENCES (g_object_get_data (G_OBJECT (widget),
970 "AnjutaPreferences"));
971 p = (AnjutaProperty *) user_data;
972 val = get_property_value_as_string (p);
973 anjuta_preferences_set (pr, p->key, val);
974 g_free (val);
977 static void
978 update_property_on_change_font (GtkWidget *widget,
979 gpointer user_data)
981 AnjutaPreferences *pr;
982 AnjutaProperty *p;
983 gchar *val;
985 pr = ANJUTA_PREFERENCES (g_object_get_data (G_OBJECT (widget),
986 "AnjutaPreferences"));
987 p = (AnjutaProperty *) user_data;
988 val = get_property_value_as_string (p);
989 anjuta_preferences_set (pr, p->key, val);
990 g_free (val);
993 static void
994 unregister_preferences_key (GtkWidget *widget,
995 gpointer user_data)
997 AnjutaProperty *p;
998 AnjutaPreferences *pr;
999 gchar *key;
1001 p = (AnjutaProperty *) user_data;
1002 pr = g_object_get_data (G_OBJECT (widget),
1003 "AnjutaPreferences");
1004 key = g_strdup (p->key);
1006 g_hash_table_remove (pr->priv->properties, key);
1007 g_free (key);
1010 static void
1011 get_property (GConfClient *gclient, guint cnxt_id,
1012 GConfEntry *entry, gpointer user_data)
1014 const gchar *key;
1015 GConfValue *value;
1017 AnjutaProperty *p = (AnjutaProperty *) user_data;
1018 key = gconf_entry_get_key (entry);
1019 value = gconf_entry_get_value (entry);
1020 /* DEBUG_PRINT ("Preference changed %s", key); */
1022 if (p->data_type == ANJUTA_PROPERTY_DATA_TYPE_BOOL)
1024 gboolean gconf_value;
1026 gconf_value = gconf_value_get_bool (value);
1027 set_property_value_as_bool (p, gconf_value);
1029 else if (p->data_type == ANJUTA_PROPERTY_DATA_TYPE_INT)
1031 int gconf_value;
1033 gconf_value = gconf_value_get_int (value);
1034 set_property_value_as_int (p, gconf_value);
1036 else
1038 const gchar *gconf_value;
1039 gconf_value = gconf_value_get_string (value);
1040 set_property_value_as_string (p, gconf_value);
1044 static void
1045 register_callbacks (AnjutaPreferences *pr, AnjutaProperty *p)
1047 GConfClient *gclient;
1048 gchar *key_error_msg;
1050 gclient = pr->priv->gclient;
1051 g_object_set_data (G_OBJECT (p->object), "AnjutaPreferences", pr);
1052 switch (p->object_type) {
1053 case ANJUTA_PROPERTY_OBJECT_TYPE_ENTRY:
1054 g_signal_connect (G_OBJECT(p->object), "changed",
1055 G_CALLBACK (update_property_on_change_str), p);
1056 g_signal_connect (G_OBJECT(p->object), "focus_out_event",
1057 G_CALLBACK (update_property_on_event_str), p);
1058 g_signal_connect (G_OBJECT(p->object), "focus_out_event",
1059 G_CALLBACK (unblock_update_property_on_change_str), p);
1060 g_signal_connect (G_OBJECT(p->object), "focus_in_event",
1061 G_CALLBACK (block_update_property_on_change_str), p);
1062 break;
1063 case ANJUTA_PROPERTY_OBJECT_TYPE_SPIN:
1064 g_signal_connect (G_OBJECT(p->object), "value-changed",
1065 G_CALLBACK (update_property_on_change_int), p);
1066 break;
1067 case ANJUTA_PROPERTY_OBJECT_TYPE_FONT:
1068 g_signal_connect (G_OBJECT(p->object), "font-set",
1069 G_CALLBACK (update_property_on_change_font), p);
1070 break;
1071 case ANJUTA_PROPERTY_OBJECT_TYPE_TEXT:
1072 g_signal_connect (G_OBJECT(p->object), "focus_out_event",
1073 G_CALLBACK (update_property_on_event_str), p);
1074 break;
1075 case ANJUTA_PROPERTY_OBJECT_TYPE_COMBO:
1076 g_signal_connect (G_OBJECT(p->object), "changed",
1077 G_CALLBACK (update_property_on_change_str), p);
1078 break;
1079 case ANJUTA_PROPERTY_OBJECT_TYPE_TOGGLE:
1080 g_signal_connect (G_OBJECT(p->object), "toggled",
1081 G_CALLBACK (update_property_on_change_bool), p);
1082 break;
1083 case ANJUTA_PROPERTY_OBJECT_TYPE_COLOR:
1084 g_signal_connect (G_OBJECT(p->object), "color-set",
1085 G_CALLBACK (update_property_on_change_color), p);
1086 break;
1087 case ANJUTA_PROPERTY_OBJECT_TYPE_FILE:
1088 g_signal_connect (G_OBJECT(p->object), "file-set",
1089 G_CALLBACK (update_property_on_change_str), p);
1090 break;
1091 case ANJUTA_PROPERTY_OBJECT_TYPE_FOLDER:
1092 g_signal_connect (G_OBJECT(p->object), "current-folder-changed",
1093 G_CALLBACK (update_property_on_change_str), p);
1094 break;
1095 default:
1096 break;
1098 if (!gconf_valid_key (build_key (p->key), &key_error_msg))
1100 g_warning ("Invalid key \"%s\": Error: \"%s\"", build_key (p->key),
1101 key_error_msg);
1102 g_free (key_error_msg);
1104 p->notify_id = gconf_client_notify_add (gclient, build_key (p->key),
1105 get_property, p, NULL, NULL);
1107 /* Connect to widget destroy signal so we can automatically unregister
1108 * keys so there aren't any potential conflicts or references to
1109 * nonexistent widgets on subsequent uses of the prefs dialog. */
1110 g_signal_connect (G_OBJECT (p->object), "destroy",
1111 G_CALLBACK (unregister_preferences_key),
1115 static gboolean
1116 preferences_foreach_callback (gchar *key, struct _AnjutaProperty *p,
1117 struct _AnjutaPreferencesForeachData *data)
1119 if (p->object_type != ANJUTA_PROPERTY_OBJECT_TYPE_COMBO)
1121 return data->callback (data->pr, key, data->callback_data);
1124 return TRUE;
1127 static void
1128 connect_prop_to_object (AnjutaPreferences *pr, AnjutaProperty *p)
1130 int gconf_value;
1131 gchar *value;
1133 if (p->data_type == ANJUTA_PROPERTY_DATA_TYPE_BOOL)
1135 gconf_value = anjuta_preferences_get_bool (pr, p->key);
1136 value = g_strdup_printf ("%d", gconf_value);
1137 set_property_value_as_string (p, value);
1139 else if (p->data_type == ANJUTA_PROPERTY_DATA_TYPE_INT)
1141 gconf_value = anjuta_preferences_get_int (pr, p->key);
1142 value = g_strdup_printf ("%d", gconf_value);
1143 set_property_value_as_string (p, value);
1145 else
1147 value = anjuta_preferences_get (pr, p->key);
1148 set_property_value_as_string (p, value);
1149 g_free (value);
1155 * anjuta_preferences_register_property_raw:
1156 * @pr: a #AnjutaPreferences object
1157 * @object: Widget to register
1158 * @key: Property key
1159 * @default_value: Default value of the key
1160 * @flags: Flags
1161 * @object_type: Object type of widget
1162 * @data_type: Data type of the property
1164 * This also registers only one widget, but instead of supplying the property
1165 * parameters as a single parsable string (as done in previous method), it
1166 * takes them separately.
1168 * Return value: TRUE if sucessful.
1170 gboolean
1171 anjuta_preferences_register_property_raw (AnjutaPreferences *pr,
1172 GtkWidget *object,
1173 const gchar *key,
1174 const gchar *default_value,
1175 guint flags,
1176 AnjutaPropertyObjectType object_type,
1177 AnjutaPropertyDataType data_type)
1179 AnjutaProperty *p;
1180 GConfValue *value;
1182 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), FALSE);
1183 g_return_val_if_fail (GTK_IS_WIDGET (object), FALSE);
1184 g_return_val_if_fail (key != NULL, FALSE);
1185 g_return_val_if_fail (strlen(key) > 0, FALSE);
1186 g_return_val_if_fail ((object_type != ANJUTA_PROPERTY_OBJECT_TYPE_COMBO) ||
1187 ((default_value != NULL) &&
1188 (*default_value != '\0')), FALSE);
1190 p = g_new0 (AnjutaProperty, 1);
1191 g_object_ref (object);
1192 p->object = object;
1193 p->object_type = object_type;
1194 p->data_type = data_type;
1195 p->key = g_strdup (key);
1196 p->gclient = pr->priv->gclient;
1198 value = gconf_client_get (pr->priv->gclient,
1199 build_key (p->key), NULL);
1200 if (value)
1202 /* Verify key type. Unset key if type mismatch. */
1203 if (!((value->type == GCONF_VALUE_BOOL &&
1204 data_type == ANJUTA_PROPERTY_DATA_TYPE_BOOL) ||
1205 (value->type == GCONF_VALUE_INT &&
1206 data_type == ANJUTA_PROPERTY_DATA_TYPE_INT) ||
1207 (value->type == GCONF_VALUE_STRING &&
1208 data_type != ANJUTA_PROPERTY_DATA_TYPE_BOOL &&
1209 data_type != ANJUTA_PROPERTY_DATA_TYPE_INT)))
1211 gconf_client_unset (pr->priv->gclient, build_key (key), NULL);
1213 gconf_value_free (value);
1215 if (default_value)
1217 p->default_value = g_strdup (default_value);
1218 if (strlen (default_value) > 0)
1220 /* For combo, initialize the untranslated strings */
1221 if (object_type == ANJUTA_PROPERTY_OBJECT_TYPE_COMBO)
1223 gchar *old_value;
1224 gchar **vstr;
1226 vstr = g_strsplit (default_value, ",", 100);
1227 g_object_set_data(G_OBJECT(p->object), "untranslated",
1228 vstr);
1229 old_value = anjuta_preferences_get (pr, p->key);
1230 if (old_value == NULL && vstr[0])
1232 /* DEBUG_PRINT ("Setting default pref value: %s = %s",
1233 p->key, default_value); */
1234 anjuta_preferences_set (pr, p->key, vstr[0]);
1236 if (old_value)
1237 g_free (old_value);
1239 else if (p->data_type != ANJUTA_PROPERTY_DATA_TYPE_BOOL &&
1240 p->data_type != ANJUTA_PROPERTY_DATA_TYPE_INT)
1242 gchar *old_value;
1243 old_value = anjuta_preferences_get (pr, p->key);
1244 if (old_value == NULL)
1246 /* DEBUG_PRINT ("Setting default pref value: %s = %s",
1247 p->key, default_value);*/
1248 anjuta_preferences_set (pr, p->key, default_value);
1250 if (old_value)
1251 g_free (old_value);
1253 else
1255 value = gconf_client_get (pr->priv->gclient,
1256 build_key (p->key), NULL);
1257 if (value == NULL)
1259 /* DEBUG_PRINT ("Setting default pref value: %s = %s",
1260 p->key, default_value);*/
1261 if (p->data_type == ANJUTA_PROPERTY_DATA_TYPE_INT)
1262 gconf_client_set_int (pr->priv->gclient,
1263 build_key (p->key),
1264 atoi (default_value), NULL);
1265 else
1266 gconf_client_set_bool (pr->priv->gclient,
1267 build_key (p->key),
1268 atoi (default_value), NULL);
1270 if (value)
1271 gconf_value_free (value);
1275 p->flags = flags;
1276 p->custom = FALSE;
1277 p->set_property = NULL;
1278 p->get_property = NULL;
1280 g_hash_table_insert (pr->priv->properties, g_strdup (key), p);
1281 connect_prop_to_object (pr, p);
1282 register_callbacks (pr, p);
1283 return TRUE;
1287 * anjuta_preferences_register_property_custom:
1288 * @pr: a #AnjutaPreferences object.
1289 * @object: Object to register.
1290 * @key: Property key.
1291 * @default_value: Default value of the key.
1292 * @data_type: property data type.
1293 * @flags: Flags
1294 * @set_property: Set property to widget callback.
1295 * @get_property: Get property from widget callback.
1297 * This is meant for complex widgets which can not be set/get with the
1298 * standard object set/get methods. Custom set/get methods are passed for
1299 * the property to set/get the value to/from the widget.
1301 * Return value: TRUE if sucessful.
1303 gboolean
1304 anjuta_preferences_register_property_custom (AnjutaPreferences *pr,
1305 GtkWidget *object,
1306 const gchar *key,
1307 const gchar *default_value,
1308 AnjutaPropertyDataType data_type,
1309 guint flags,
1310 void (*set_property) (AnjutaProperty *prop, const gchar *value),
1311 gchar * (*get_property) (AnjutaProperty *))
1313 AnjutaProperty *p;
1314 GConfValue *value;
1316 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), FALSE);
1317 g_return_val_if_fail (GTK_IS_WIDGET (object), FALSE);
1318 g_return_val_if_fail (key != NULL, FALSE);
1319 g_return_val_if_fail (strlen(key) > 0, FALSE);
1321 p = g_new0 (AnjutaProperty, 1);
1322 g_object_ref (object);
1323 p->object = object;
1324 p->object_type = (AnjutaPropertyObjectType) 0;
1325 p->data_type = data_type;
1326 p->key = g_strdup (key);
1327 p->gclient = pr->priv->gclient;
1329 value = gconf_client_get (pr->priv->gclient,
1330 build_key (p->key), NULL);
1331 if (value)
1333 /* Verify key type. Unset key if type mismatch. */
1334 if (!((value->type == GCONF_VALUE_BOOL &&
1335 data_type == ANJUTA_PROPERTY_DATA_TYPE_BOOL) ||
1336 (value->type == GCONF_VALUE_INT &&
1337 data_type == ANJUTA_PROPERTY_DATA_TYPE_INT) ||
1338 (value->type == GCONF_VALUE_STRING)))
1340 gconf_client_unset (pr->priv->gclient, build_key (key), NULL);
1342 gconf_value_free (value);
1344 if (default_value)
1346 p->default_value = g_strdup (default_value);
1347 if (p->data_type != ANJUTA_PROPERTY_DATA_TYPE_BOOL &&
1348 p->data_type != ANJUTA_PROPERTY_DATA_TYPE_INT)
1350 gchar *old_value;
1351 old_value = anjuta_preferences_get (pr, p->key);
1352 if (old_value == NULL)
1354 /* DEBUG_PRINT ("Setting default pref value: %s = %s",
1355 p->key, default_value); */
1356 anjuta_preferences_set (pr, p->key, default_value);
1358 if (old_value)
1359 g_free (old_value);
1361 else
1363 value = gconf_client_get (pr->priv->gclient,
1364 build_key (p->key), NULL);
1365 if (value == NULL)
1367 /* DEBUG_PRINT ("Setting default pref value: %s = %s",
1368 p->key, default_value);*/
1369 if (p->data_type == ANJUTA_PROPERTY_DATA_TYPE_INT)
1370 gconf_client_set_int (pr->priv->gclient,
1371 build_key (p->key),
1372 atoi (default_value), NULL);
1373 else
1374 gconf_client_set_bool (pr->priv->gclient,
1375 build_key (p->key),
1376 atoi (default_value), NULL);
1378 if (value)
1379 gconf_value_free (value);
1382 p->custom = TRUE;
1383 p->flags = flags;
1384 p->set_property = set_property;
1385 p->get_property = get_property;
1387 g_hash_table_insert (pr->priv->properties, g_strdup (key), p);
1389 /* Connect to widget destroy signal so we can automatically unregister
1390 * keys so there aren't any potential conflicts or references to
1391 * nonexistent widgets on subsequent uses of the prefs dialog. */
1392 g_object_set_data (G_OBJECT (p->object), "AnjutaPreferences", pr);
1393 g_signal_connect (G_OBJECT (p->object), "destroy",
1394 G_CALLBACK (unregister_preferences_key),
1396 return TRUE;
1400 * anjuta_preferences_register_property_from_string:
1401 * @pr: a #AnjutaPreferences object
1402 * @object: Widget to register
1403 * @property_desc: Property description (see anjuta_preferences_add_page())
1405 * This registers only one widget. The widget could be shown elsewhere.
1406 * the property_description should be of the form described before.
1408 * Return value: TRUE if sucessful.
1410 gboolean
1411 anjuta_preferences_register_property_from_string (AnjutaPreferences *pr,
1412 GtkWidget *object,
1413 const gchar *property_desc)
1415 gchar **fields;
1416 gint n_fields;
1418 AnjutaPropertyObjectType object_type;
1419 AnjutaPropertyDataType data_type;
1420 gchar *key;
1421 gchar *default_value;
1422 gint flags;
1424 g_return_val_if_fail (ANJUTA_IS_PREFERENCES(pr), FALSE);
1425 g_return_val_if_fail ((GTK_IS_WIDGET (object)), FALSE);
1426 g_return_val_if_fail (property_desc != NULL, FALSE);
1428 fields = g_strsplit (property_desc, ":", 5);
1429 g_return_val_if_fail (fields, FALSE);
1430 for (n_fields = 0; fields[n_fields]; n_fields++);
1431 if (n_fields != 5)
1433 g_strfreev (fields);
1434 return FALSE;
1436 object_type = get_object_type_from_string (fields[0]);
1437 data_type = get_data_type_from_string (fields[1]);
1438 default_value = fields[2];
1439 flags = atoi (fields[3]);
1440 key = fields[4];
1441 if (object_type < 0)
1443 g_warning ("Invalid property object type in property description");
1444 g_strfreev (fields);
1445 return FALSE;
1447 if (data_type < 0)
1449 g_warning ("Invalid property data type in property description");
1450 g_strfreev (fields);
1451 return FALSE;
1453 anjuta_preferences_register_property_raw (pr, object, key, default_value,
1454 flags, object_type,
1455 data_type);
1456 g_strfreev (fields);
1457 return TRUE;
1461 * anjuta_preferences_register_all_properties_from_builder_xml:
1462 * @pr: a #AnjutaPreferences Object
1463 * @builder: GtkBuilder object containing the properties widgets.
1464 * @parent: Parent widget in the builder object
1466 * This will register all the properties names of the format described above
1467 * without considering the UI. Useful if you have the widgets shown elsewhere
1468 * but you want them to be part of preferences system.
1470 void
1471 anjuta_preferences_register_all_properties_from_builder_xml (AnjutaPreferences *pr,
1472 GtkBuilder *builder,
1473 GtkWidget *parent)
1475 GSList *widgets;
1476 GSList *node;
1478 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
1479 g_return_if_fail (builder != NULL);
1481 widgets = gtk_builder_get_objects (builder);
1482 for (node = widgets; node != NULL; node = g_slist_next (node))
1484 const gchar *name;
1485 const gchar *property;
1486 GtkWidget *widget, *p;
1487 gboolean cont_flag = FALSE;
1489 if (!GTK_IS_WIDGET (node->data) || !GTK_IS_BUILDABLE (node->data))
1490 continue;
1492 widget = node->data;
1493 name = gtk_buildable_get_name (GTK_BUILDABLE (widget));
1495 if (!g_str_has_prefix (name, PREFERENCE_PROPERTY_PREFIX))
1496 continue;
1498 p = gtk_widget_get_parent (widget);
1499 /* Added only if it's a desendend child of the parent */
1500 while (p != parent)
1502 if (p == NULL)
1504 cont_flag = TRUE;
1505 break;
1507 p = gtk_widget_get_parent (p);
1509 if (cont_flag)
1510 continue;
1512 property = &name[strlen (PREFERENCE_PROPERTY_PREFIX)];
1513 anjuta_preferences_register_property_from_string (pr, widget,
1514 property);
1519 * anjuta_preferences_reset_defaults:
1520 * @pr: a #AnjutaPreferences object.
1522 * Resets the default values into the keys
1524 void
1525 anjuta_preferences_reset_defaults (AnjutaPreferences * pr)
1527 GtkWidget *dlg;
1529 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
1531 dlg = gtk_message_dialog_new (GTK_WINDOW (pr),
1532 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
1533 GTK_BUTTONS_NONE,
1534 _("Are you sure you want to reset the preferences to\n"
1535 "their default settings?"));
1536 gtk_dialog_add_button (GTK_DIALOG (dlg), GTK_STOCK_CANCEL,
1537 GTK_RESPONSE_CANCEL);
1538 anjuta_util_dialog_add_button (GTK_DIALOG (dlg), _("_Reset"),
1539 GTK_STOCK_REVERT_TO_SAVED,
1540 GTK_RESPONSE_YES);
1541 if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_YES)
1543 /* FIXME: Reset preferences to built-in default values. */
1545 gtk_widget_destroy (dlg);
1549 * anjuta_preferences_foreach:
1550 * @pr: A #AnjutaPreferences object.
1551 * @callback: User callback function.
1552 * @data: User data passed to @callback
1554 * Calls @callback function for each of the registered property keys. Keys
1555 * with matching @filter flags are left out of the loop. If @filter is
1556 * ANJUTA_PREFERENCES_FILTER_NONE, all properties are selected for the loop.
1558 void
1559 anjuta_preferences_foreach (AnjutaPreferences *pr,
1560 AnjutaPreferencesCallback callback,
1561 gpointer data)
1563 struct _AnjutaPreferencesForeachData foreach_data;
1565 foreach_data.pr = pr;
1566 foreach_data.callback = callback;
1567 foreach_data.callback_data = data;
1569 g_hash_table_find (pr->priv->properties,
1570 (GHRFunc) preferences_foreach_callback,
1571 &foreach_data);
1576 * anjuta_preferences_add_page:
1577 * @pr: a #AnjutaPreferences object
1578 * @builder: #GtkBuilder object containing the preferences page
1579 * @gwidget_name: Page widget name (as give with glade interface editor).
1580 * The widget will be searched with the given name and detached
1581 * (that is, removed from the container, if present) from it's parent.
1582 * @icon_filename: File name (of the form filename.png) of the icon representing
1583 * the preference page.
1585 * Add a page to the preferences sytem.
1586 * builder is the GtkBuilder object of the dialog containing the page widget.
1587 * The dialog will contain the layout of the preferences widgets.
1588 * The widgets which are preference widgets (e.g. toggle button) should have
1589 * widget names of the form:
1591 * <programlisting>
1592 * preferences_OBJECTTYPE:DATATYPE:DEFAULT:FLAGS:PROPERTYKEY
1593 * where,
1594 * OBJECTTYPE is 'toggle', 'spin', 'entry', 'text', 'color', 'font' or 'file' .
1595 * DATATYPE is 'bool', 'int', 'float', 'text', 'color' or 'font'.
1596 * DEFAULT is the default value (in the appropriate format). The format
1597 * for color is '#XXXXXX' representing RGB value and for
1598 * font, it is the pango font description.
1599 * FLAGS is any flag associated with the property. Currently it
1600 * has only two values -- 0 and 1. For normal preference
1601 * property which is saved/retrieved globally, the flag = 0.
1602 * For preference property which is also saved/retrieved
1603 * along with the project, the flag = 1.
1604 * PROPERTYKEY is the property key. e.g - 'tab.size'.
1605 * </programlisting>
1607 * All widgets having the above names in the gxml tree will be registered
1608 * and will become part of auto saving/loading. For example, refer to
1609 * anjuta preferences dialogs and study the widget names.
1611 void
1612 anjuta_preferences_add_from_builder (AnjutaPreferences* pr,
1613 GtkBuilder* builder,
1614 const gchar* widget_name,
1615 const gchar* title,
1616 const gchar *icon_filename)
1618 GtkWidget *parent;
1619 GtkWidget *page;
1620 GdkPixbuf *pixbuf;
1621 gchar *image_path;
1623 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
1624 g_return_if_fail (widget_name != NULL);
1625 g_return_if_fail (icon_filename != NULL);
1627 page = GTK_WIDGET(gtk_builder_get_object (builder, widget_name));
1628 g_object_ref (page);
1629 g_return_if_fail (GTK_IS_WIDGET (page));
1630 parent = gtk_widget_get_parent (page);
1631 if (parent && GTK_IS_CONTAINER (parent))
1633 if (GTK_IS_NOTEBOOK (parent))
1635 gint page_num;
1637 page_num = gtk_notebook_page_num (GTK_NOTEBOOK (parent), page);
1638 gtk_notebook_remove_page (GTK_NOTEBOOK (parent), page_num);
1640 else
1642 gtk_container_remove (GTK_CONTAINER (parent), page);
1645 image_path = anjuta_res_get_pixmap_file (icon_filename);
1646 pixbuf = gdk_pixbuf_new_from_file (image_path, NULL);
1647 anjuta_preferences_dialog_add_page (ANJUTA_PREFERENCES_DIALOG (pr->priv->prefs_dialog),
1648 widget_name, title, pixbuf, page);
1649 anjuta_preferences_register_all_properties_from_builder_xml (pr, builder, page);
1650 g_object_unref (page);
1651 g_free (image_path);
1652 g_object_unref (pixbuf);
1655 void
1656 anjuta_preferences_remove_page (AnjutaPreferences *pr,
1657 const gchar *page_name)
1659 if (pr->priv->prefs_dialog)
1661 anjuta_preferences_dialog_remove_page (ANJUTA_PREFERENCES_DIALOG (pr->priv->prefs_dialog),
1662 page_name);
1666 static void
1667 on_preferences_dialog_destroyed (GtkWidget *preferencess_dialog,
1668 AnjutaPreferences *pr)
1670 GList *plugins;
1671 GList *current_plugin;
1673 plugins = anjuta_plugin_manager_get_active_plugin_objects (pr->priv->plugin_manager);
1674 current_plugin = plugins;
1676 while (current_plugin)
1678 if (IANJUTA_IS_PREFERENCES (current_plugin->data))
1680 ianjuta_preferences_unmerge (IANJUTA_PREFERENCES (current_plugin->data),
1681 pr, NULL);
1684 current_plugin = g_list_next (current_plugin);
1688 g_object_unref (pr->priv->prefs_dialog);
1690 g_list_free (plugins);
1691 pr->priv->prefs_dialog = NULL;
1694 GtkWidget *
1695 anjuta_preferences_get_dialog (AnjutaPreferences *pr)
1697 GList *plugins;
1698 GList *current_plugin;
1700 if (pr->priv->prefs_dialog)
1701 return pr->priv->prefs_dialog;
1702 else
1704 pr->priv->prefs_dialog = anjuta_preferences_dialog_new ();
1706 g_signal_connect (G_OBJECT (pr->priv->prefs_dialog), "destroy",
1707 G_CALLBACK (on_preferences_dialog_destroyed),
1708 pr);
1710 plugins = anjuta_plugin_manager_get_active_plugin_objects (pr->priv->plugin_manager);
1711 current_plugin = plugins;
1713 while (current_plugin)
1715 if (IANJUTA_IS_PREFERENCES (current_plugin->data))
1717 ianjuta_preferences_merge (IANJUTA_PREFERENCES (current_plugin->data),
1718 pr, NULL);
1721 current_plugin = g_list_next (current_plugin);
1724 g_list_free (plugins);
1726 return g_object_ref_sink (pr->priv->prefs_dialog);
1730 gboolean
1731 anjuta_preferences_is_dialog_created (AnjutaPreferences *pr)
1733 return (pr->priv->prefs_dialog != NULL);
1736 static void anjuta_preferences_class_init (AnjutaPreferencesClass *class);
1737 static void anjuta_preferences_instance_init (AnjutaPreferences *pr);
1739 GType
1740 anjuta_preferences_get_type ()
1742 static GType obj_type = 0;
1744 if (!obj_type)
1746 static const GTypeInfo obj_info =
1748 sizeof (AnjutaPreferencesClass),
1749 (GBaseInitFunc) NULL,
1750 (GBaseFinalizeFunc) NULL,
1751 (GClassInitFunc) anjuta_preferences_class_init,
1752 (GClassFinalizeFunc) NULL,
1753 NULL, /* class_data */
1754 sizeof (AnjutaPreferencesClass),
1755 0, /* n_preallocs */
1756 (GInstanceInitFunc) anjuta_preferences_instance_init,
1757 NULL /* value_table */
1759 obj_type = g_type_register_static (G_TYPE_OBJECT,
1760 "AnjutaPreferences", &obj_info, 0);
1762 return obj_type;
1765 static void
1766 anjuta_preferences_dispose (GObject *obj)
1768 AnjutaPreferences *pr = ANJUTA_PREFERENCES (obj);
1770 if (pr->priv->properties)
1772 /* This will release the refs on property objects */
1773 g_hash_table_destroy (pr->priv->properties);
1774 pr->priv->properties = NULL;
1778 static void
1779 anjuta_preferences_instance_init (AnjutaPreferences *pr)
1781 pr->priv = g_new0 (AnjutaPreferencesPriv, 1);
1783 pr->priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal,
1784 g_free,
1785 (GDestroyNotify) property_destroy);
1786 pr->priv->notifications = g_hash_table_new_full (g_int_hash,
1787 g_int_equal,
1788 g_free,
1789 NULL);
1791 pr->priv->gclient = gconf_client_get_default();
1792 gconf_client_add_dir (pr->priv->gclient, GCONF_KEY_PREFIX,
1793 GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
1797 static void
1798 anjuta_preferences_finalize (GObject *obj)
1800 AnjutaPreferences *pr = ANJUTA_PREFERENCES (obj);
1802 if (pr->priv->prefs_dialog)
1803 gtk_widget_destroy (pr->priv->prefs_dialog);
1805 g_object_unref (pr->priv->plugin_manager);
1806 g_free (pr->priv);
1809 static void
1810 anjuta_preferences_class_init (AnjutaPreferencesClass *class)
1812 GObjectClass *object_class = G_OBJECT_CLASS (class);
1814 object_class->dispose = anjuta_preferences_dispose;
1815 object_class->finalize = anjuta_preferences_finalize;
1819 * anjuta_preferences_new:
1820 * @plugin_manager: #AnjutaPluginManager to be used
1822 * Creates a new #AnjutaPreferences object
1824 * Return value: A #AnjutaPreferences object.
1826 AnjutaPreferences *
1827 anjuta_preferences_new (AnjutaPluginManager *plugin_manager)
1829 AnjutaPreferences *pr;
1831 if (!default_preferences)
1833 pr = g_object_new (ANJUTA_TYPE_PREFERENCES, NULL);
1834 pr->priv->plugin_manager = g_object_ref (plugin_manager);
1835 default_preferences = pr;
1836 return pr;
1838 else
1839 return default_preferences;
1844 * anjuta_preferences_default:
1846 * Get the default instace of anjuta preferences
1848 * Return value: A #AnjutaPreferences object.
1850 AnjutaPreferences *anjuta_preferences_default ()
1852 return default_preferences;
1855 static void
1856 gconf_notify (GConfEngine* conf,
1857 guint id,
1858 GConfEntry* entry,
1859 gpointer user_data)
1861 AnjutaPreferences* prefs = anjuta_preferences_default();
1862 gpointer notify =
1863 g_hash_table_lookup (prefs->priv->notifications,
1864 &id);
1866 if (entry->value)
1868 const gchar* real_key = unbuild_key (entry->key);
1869 switch (entry->value->type)
1871 case GCONF_VALUE_INT:
1873 AnjutaPreferencesNotifyInt int_func = notify;
1874 int_func (prefs, real_key,
1875 gconf_value_get_int (entry->value), user_data);
1876 break;
1878 case GCONF_VALUE_STRING:
1880 AnjutaPreferencesNotify str_func = notify;
1881 str_func (prefs, real_key,
1882 gconf_value_get_string (entry->value), user_data);
1883 break;
1885 case GCONF_VALUE_BOOL:
1887 AnjutaPreferencesNotifyBool bool_func = notify;
1888 bool_func (prefs, real_key,
1889 gconf_value_get_bool (entry->value), user_data);
1890 break;
1892 default:
1893 g_warning ("Notification for unknown type of key: %s", entry->key);
1898 guint
1899 anjuta_preferences_notify_add_int (AnjutaPreferences *pr,
1900 const gchar *key,
1901 AnjutaPreferencesNotifyInt func,
1902 gpointer data,
1903 GFreeFunc destroy_notify)
1905 guint* id = g_new0 (guint, 1);
1906 *id = gconf_client_notify_add (pr->priv->gclient,
1907 build_key (key),
1908 (GConfClientNotifyFunc) gconf_notify, data, destroy_notify, NULL);
1909 g_hash_table_insert (pr->priv->notifications,
1911 func);
1912 return *id;
1916 * anjuta_preferences_notify_add_string:
1917 * @pr: A #AnjutaPreferences object.
1918 * @key: Key to monitor.
1919 * @func: User callback function.
1920 * @data: User data passed to @func
1921 * @destroy_notify: Destroy notify function - called when notify is removed.
1923 * This is similar to gconf_client_notify_add(), except that the key is not
1924 * given as full path. Only anjuta preference key is given. The key prefix
1925 * is added internally.
1927 * Return value: Notify ID.
1929 guint
1930 anjuta_preferences_notify_add_string (AnjutaPreferences *pr,
1931 const gchar *key,
1932 AnjutaPreferencesNotify func,
1933 gpointer data,
1934 GFreeFunc destroy_notify)
1936 guint* id = g_new0 (guint, 1);
1937 *id = gconf_client_notify_add (pr->priv->gclient,
1938 build_key (key),
1939 (GConfClientNotifyFunc)gconf_notify, data, destroy_notify, NULL);
1940 g_hash_table_insert (pr->priv->notifications,
1942 func);
1943 return *id;
1946 guint
1947 anjuta_preferences_notify_add_bool (AnjutaPreferences *pr,
1948 const gchar *key,
1949 AnjutaPreferencesNotifyBool func,
1950 gpointer data,
1951 GFreeFunc destroy_notify)
1953 guint* id = g_new0 (guint, 1);
1954 *id = gconf_client_notify_add (pr->priv->gclient,
1955 build_key (key),
1956 (GConfClientNotifyFunc)gconf_notify, data, destroy_notify, NULL);
1957 g_hash_table_insert (pr->priv->notifications,
1959 func);
1960 return *id;
1965 * anjuta_preferences_notify_remove:
1966 * @pr: A #AnjutaPreferences object.
1967 * @notify_id: Notify ID returned by anjuta_preferences_notify_add().
1969 * Removes the notify callback added with anjuta_preferences_notify_add().
1971 void
1972 anjuta_preferences_notify_remove (AnjutaPreferences *pr, guint notify_id)
1974 gconf_client_notify_remove (pr->priv->gclient, notify_id);
1978 * anjuta_preferences_get_prefix:
1979 * @pr: A #AnjutaPreferences object.
1981 * Returns the gconf key prefix used by anjuta to store its preferences.
1983 * Return value: preferences keys prefix.
1985 const gchar*
1986 anjuta_preferences_get_prefix (AnjutaPreferences *pr)
1988 return PREFERENCE_PROPERTY_PREFIX;