Move from GnomeVFS to GIO
[anjuta-git-plugin.git] / libanjuta / anjuta-preferences.c
blob672e3f5249801a49f43593d2fef4a1757cb7e545
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>
68 #include <glade/glade-parser.h>
69 #include <gconf/gconf-client.h>
70 #include <libgnomevfs/gnome-vfs.h>
72 #include <libanjuta/anjuta-preferences.h>
73 #include <libanjuta/anjuta-utils.h>
74 #include <libanjuta/resources.h>
75 #include <libanjuta/anjuta-debug.h>
76 #include <libanjuta/interfaces/ianjuta-preferences.h>
78 struct _AnjutaProperty
80 GtkWidget *object;
81 gchar *key;
82 gchar *default_value;
83 guint flags;
84 gint notify_id;
85 GConfClient *gclient;
87 /* Set true if custom set/get to be used */
88 gboolean custom;
90 /* For inbuilt generic objects */
91 AnjutaPropertyObjectType object_type;
92 AnjutaPropertyDataType data_type;
94 /* For custom objects */
95 void (*set_property) (AnjutaProperty *prop, const gchar *value);
96 gchar * (*get_property) (AnjutaProperty *prop);
100 struct _AnjutaPreferencesPriv
102 GConfClient *gclient;
103 GHashTable *properties;
104 GtkWidget *prefs_dialog;
105 AnjutaPluginManager *plugin_manager;
106 gboolean is_showing;
109 /* Internal structure for anjuta_preferences_foreach */
110 struct _AnjutaPreferencesForeachData
112 AnjutaPreferences *pr;
113 AnjutaPreferencesFilterType filter;
114 AnjutaPreferencesCallback callback;
115 gpointer callback_data;
118 #define PREFERENCE_PROPERTY_PREFIX "preferences_"
119 #define GCONF_KEY_PREFIX "/apps/anjuta/preferences"
121 static const gchar *
122 build_key (const gchar *key)
124 static gchar buffer[1024];
125 snprintf (buffer, 1024, "%s/%s", GCONF_KEY_PREFIX, key);
126 return buffer;
130 * anjuta_preferences_get:
131 * @pr: A #AnjutaPreferences object
132 * @key: Property key
134 * Gets the value of @key as string. Returned string should be g_freed() when not
135 * required.
137 * Return value: Key value as string or NULL if the key is not defined.
139 #ifdef __GNUC__
140 inline
141 #endif
142 gchar *
143 anjuta_preferences_get (AnjutaPreferences *pr, const gchar *key)
145 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), NULL);
146 g_return_val_if_fail (key != NULL, NULL);
148 return gconf_client_get_string (pr->priv->gclient, build_key (key), NULL);
152 * anjuta_preferences_get_list:
153 * @pr: A #AnjutaPreferences object
154 * @key: Property key
155 * @list_type: Type of each list element
157 * Gets the list of @key.
159 * Return value: Key list or NULL if the key is not defined.
161 #ifdef __GNUC__
162 inline
163 #endif
164 GSList *
165 anjuta_preferences_get_list (AnjutaPreferences *pr, const gchar *key,
166 GConfValueType list_type)
168 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), NULL);
169 g_return_val_if_fail (key != NULL, NULL);
171 return gconf_client_get_list(pr->priv->gclient, build_key (key), list_type, NULL);
175 * anjuta_preferences_get_pair:
176 * @pr: A #AnjutaPreferences object
177 * @key: Property key
178 * @car_type: Desired type of the pair's first field (car).
179 * @cdr_type: Desired type of the pair's second field (cdr).
180 * @car_retloc: Address of a return location for the car.
181 * @cdr_retloc: Address of a return location for the cdr.
183 * Gets the pair of @key.
185 * Return value: TRUE or FALSE.
187 #ifdef __GNUC__
188 inline
189 #endif
190 gboolean
191 anjuta_preferences_get_pair (AnjutaPreferences *pr, const gchar *key,
192 GConfValueType car_type, GConfValueType cdr_type,
193 gpointer car_retloc, gpointer cdr_retloc)
195 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), FALSE);
196 g_return_val_if_fail (key != NULL, FALSE);
198 return gconf_client_get_pair(pr->priv->gclient, build_key (key),
199 car_type, cdr_type,
200 car_retloc, cdr_retloc, NULL);
204 * anjuta_preferences_get_int:
205 * @pr: A #AnjutaPreferences object
206 * @key: Property key
208 * Gets the value of @key as integer.
210 * Return value: Key value as integer or 0 if the key is not defined.
212 #ifdef __GNUC__
213 inline
214 #endif
215 gint
216 anjuta_preferences_get_int (AnjutaPreferences *pr, const gchar *key)
218 gint ret_val;
219 GConfValue *value;
221 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), 0);
222 g_return_val_if_fail (key != NULL, 0);
224 ret_val = 0;
225 value = gconf_client_get (pr->priv->gclient, build_key (key), NULL);
226 if (value)
228 switch (value->type)
230 case GCONF_VALUE_INT:
231 ret_val = gconf_value_get_int (value);
232 break;
233 case GCONF_VALUE_BOOL:
234 ret_val = gconf_value_get_bool (value);
235 break;
236 default:
237 g_warning ("Invalid gconf type for key: %s", key);
239 gconf_value_free (value);
241 /* else
242 g_warning ("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 case GCONF_VALUE_BOOL:
280 ret_val = gconf_value_get_bool (value);
281 break;
282 default:
283 g_warning ("Invalid gconf type for key: %s", key);
285 gconf_value_free (value);
287 return ret_val;
291 * anjuta_preferences_default_get:
292 * @pr: A #AnjutaPreferences object
293 * @key: Property key
295 * Gets the default value of @key as string. The default value of the key
296 * is the value defined in System defaults (generally installed during
297 * program installation). Returned value must be g_freed() when not required.
299 * Return value: Default key value as string or NULL if not defined.
301 #ifdef __GNUC__
302 inline
303 #endif
304 gchar *
305 anjuta_preferences_default_get (AnjutaPreferences * pr, const gchar * key)
307 GConfValue *val;
308 gchar *str;
309 GError *err = NULL;
311 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), NULL);
312 g_return_val_if_fail (key != NULL, NULL);
314 val = gconf_client_get_default_from_schema (pr->priv->gclient, build_key (key), &err);
315 if (err) {
316 g_error_free (err);
317 return NULL;
319 str = g_strdup (gconf_value_get_string (val));
320 gconf_value_free (val);
321 return str;
325 * anjuta_preferences_default_get_int:
326 * @pr: A #AnjutaPreferences object
327 * @key: Property key
329 * Gets the default value of @key as integer. The default value of the key
330 * is the value defined in System defaults (generally installed during
331 * program installation).
333 * Return value: Default key value as integer or 0 if the key is not defined.
335 #ifdef __GNUC__
336 inline
337 #endif
338 gint
339 anjuta_preferences_default_get_int (AnjutaPreferences *pr, const gchar *key)
341 GConfValue *val;
342 gint ret;
343 GError *err = NULL;
345 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), 0);
346 g_return_val_if_fail (key != NULL, 0);
347 val = gconf_client_get_default_from_schema (pr->priv->gclient, build_key (key), &err);
348 if (err) {
349 g_error_free (err);
350 return 0;
352 ret = gconf_value_get_int (val);
353 gconf_value_free (val);
354 return ret;
358 * anjuta_preferences_set:
359 * @pr: A #AnjutaPreferences object.
360 * @key: Property key.
361 * @value: Value of the key.
363 * Sets the value of @key in current session.
365 #ifdef __GNUC__
366 inline
367 #endif
368 void
369 anjuta_preferences_set (AnjutaPreferences *pr, const gchar *key,
370 const gchar *value)
372 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
373 g_return_if_fail (key != NULL);
375 if (value && (strlen (value) > 0))
377 gconf_client_set_string (pr->priv->gclient, build_key (key), value, NULL);
379 else
381 gconf_client_set_string (pr->priv->gclient, build_key (key), "", NULL);
386 * anjuta_preferences_set_list:
387 * @pr: A #AnjutaPreferences object.
388 * @key: Property key.
389 * @list_type: Type of each element.
390 * @list: New value of the key.
392 * Sets a list in current session.
394 #ifdef __GNUC__
395 inline
396 #endif
397 void
398 anjuta_preferences_set_list (AnjutaPreferences *pr, const gchar *key,
399 GConfValueType list_type, GSList *list)
401 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
402 g_return_if_fail (key != NULL);
404 gconf_client_set_list(pr->priv->gclient, build_key (key),
405 list_type, list, NULL);
409 * anjuta_preferences_set_pair:
410 * @pr: A #AnjutaPreferences object.
411 * @key: Property key.
412 * @car_type: Type of the pair's first field (car).
413 * @cdr_type: Type of the pair's second field (cdr).
414 * @address_of_car: Address of the car.
415 * @address_of_cdr: Address of the cdr.
418 #ifdef __GNUC__
419 inline
420 #endif
421 gboolean
422 anjuta_preferences_set_pair (AnjutaPreferences *pr, const gchar *key,
423 GConfValueType car_type, GConfValueType cdr_type,
424 gconstpointer address_of_car,
425 gconstpointer address_of_cdr)
427 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), FALSE);
428 g_return_val_if_fail (key != NULL, FALSE);
430 return gconf_client_set_pair (pr->priv->gclient, build_key (key),
431 car_type, cdr_type,
432 address_of_car, address_of_cdr,
433 NULL);
437 * anjuta_preferences_set_int:
438 * @pr: A #AnjutaPreferences object.
439 * @key: Property key.
440 * @value: Integer value of the key.
442 * Sets the value of @key in current session.
444 #ifdef __GNUC__
445 inline
446 #endif
447 void
448 anjuta_preferences_set_int (AnjutaPreferences *pr, const gchar *key,
449 gint value)
451 GConfValue *gvalue;
453 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
454 g_return_if_fail (key != NULL);
456 gvalue = gconf_client_get (pr->priv->gclient, build_key (key), NULL);
457 if (gvalue)
459 switch (gvalue->type)
461 case GCONF_VALUE_BOOL:
462 gconf_client_set_bool (pr->priv->gclient, build_key (key),
463 value, NULL);
464 break;
465 case GCONF_VALUE_INT:
466 gconf_client_set_int (pr->priv->gclient, build_key (key),
467 value, NULL);
468 break;
469 default:
470 g_warning ("Invalid gconf type for key: %s", key);
472 gconf_value_free (gvalue);
474 else
476 /* g_warning ("The preference key %s is not defined", key); */
477 gconf_client_set_int (pr->priv->gclient, build_key (key),
478 value, NULL);
482 static void
483 property_destroy (AnjutaProperty *property)
485 g_return_if_fail (property);
486 if (property->key) g_free (property->key);
487 if (property->default_value) g_free (property->default_value);
488 g_object_unref (property->object);
489 gconf_client_notify_remove (property->gclient, property->notify_id);
490 g_free (property);
494 * anjuta_property_get_widget:
495 * @prop: an #AnjutaProperty reference
497 * Gets the widget associated with the property.
499 * Returns: a #GtkWidget object associated with the property.
501 GtkWidget*
502 anjuta_property_get_widget (AnjutaProperty *prop)
504 return prop->object;
507 static AnjutaPropertyObjectType
508 get_object_type_from_string (const gchar* object_type)
510 if (strcmp (object_type, "entry") == 0)
511 return ANJUTA_PROPERTY_OBJECT_TYPE_ENTRY;
512 else if (strcmp (object_type, "combo") == 0)
513 return ANJUTA_PROPERTY_OBJECT_TYPE_COMBO;
514 else if (strcmp (object_type, "spin") == 0)
515 return ANJUTA_PROPERTY_OBJECT_TYPE_SPIN;
516 else if (strcmp (object_type, "toggle") == 0)
517 return ANJUTA_PROPERTY_OBJECT_TYPE_TOGGLE;
518 else if (strcmp (object_type, "text") == 0)
519 return ANJUTA_PROPERTY_OBJECT_TYPE_TEXT;
520 else if (strcmp (object_type, "color") == 0)
521 return ANJUTA_PROPERTY_OBJECT_TYPE_COLOR;
522 else if (strcmp (object_type, "font") == 0)
523 return ANJUTA_PROPERTY_OBJECT_TYPE_FONT;
524 else if (strcmp (object_type, "file") == 0)
525 return ANJUTA_PROPERTY_OBJECT_TYPE_FILE;
526 else if (strcmp (object_type, "folder") == 0)
527 return ANJUTA_PROPERTY_OBJECT_TYPE_FOLDER;
528 else
529 return (AnjutaPropertyObjectType)(-1);
532 static AnjutaPropertyDataType
533 get_data_type_from_string (const gchar* data_type)
535 if (strcmp (data_type, "bool") == 0)
536 return ANJUTA_PROPERTY_DATA_TYPE_BOOL;
537 else if (strcmp (data_type, "int") == 0)
538 return ANJUTA_PROPERTY_DATA_TYPE_INT;
539 else if (strcmp (data_type, "text") == 0)
540 return ANJUTA_PROPERTY_DATA_TYPE_TEXT;
541 else if (strcmp (data_type, "color") == 0)
542 return ANJUTA_PROPERTY_DATA_TYPE_COLOR;
543 else if (strcmp (data_type, "font") == 0)
544 return ANJUTA_PROPERTY_DATA_TYPE_FONT;
545 else
546 return (AnjutaPropertyDataType)(-1);
549 static gchar*
550 get_property_value_as_string (AnjutaProperty *prop)
552 gint int_value;
553 gchar** values;
554 gchar *text_value = NULL;
555 gchar *uri;
557 if (prop->custom)
559 if (prop->get_property != NULL)
560 return prop->get_property (prop);
561 else
563 g_warning ("%s: Undefined get_property() for custom object",
564 prop->key);
565 return NULL;
568 switch (prop->object_type)
570 case ANJUTA_PROPERTY_OBJECT_TYPE_TOGGLE:
571 int_value =
572 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (prop->object));
573 text_value = g_strdup_printf ("%d", int_value);
574 break;
576 case ANJUTA_PROPERTY_OBJECT_TYPE_SPIN:
577 int_value =
578 gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (prop->object));
579 text_value = g_strdup_printf ("%d", int_value);
580 break;
582 case ANJUTA_PROPERTY_OBJECT_TYPE_ENTRY:
583 text_value =
584 gtk_editable_get_chars (GTK_EDITABLE (prop->object), 0, -1);
585 break;
586 case ANJUTA_PROPERTY_OBJECT_TYPE_COMBO:
588 gint idx;
589 values = g_object_get_data(G_OBJECT(prop->object), "untranslated");
590 idx = gtk_combo_box_get_active(GTK_COMBO_BOX(prop->object));
591 if (values[idx] != NULL)
592 text_value = g_strdup(values[idx]);
593 break;
595 case ANJUTA_PROPERTY_OBJECT_TYPE_TEXT:
597 GtkTextBuffer *buffer;
598 GtkTextIter start_iter;
599 GtkTextIter end_iter;
600 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (prop->object));
601 gtk_text_buffer_get_start_iter (buffer, &start_iter);
602 gtk_text_buffer_get_end_iter (buffer, &end_iter);
603 text_value =
604 gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, TRUE);
605 break;
607 case ANJUTA_PROPERTY_OBJECT_TYPE_COLOR:
609 GdkColor color;
610 gtk_color_button_get_color(GTK_COLOR_BUTTON (prop->object),
611 &color);
612 text_value = anjuta_util_string_from_color (color.red, color.green, color.blue);
614 break;
615 case ANJUTA_PROPERTY_OBJECT_TYPE_FONT:
617 const gchar *font;
618 font = gtk_font_button_get_font_name (GTK_FONT_BUTTON
619 (prop->object));
620 text_value = g_strdup (font);
622 break;
623 case ANJUTA_PROPERTY_OBJECT_TYPE_FOLDER:
624 uri = gtk_file_chooser_get_uri (
625 GTK_FILE_CHOOSER (prop->object));
626 text_value = gnome_vfs_get_local_path_from_uri (uri);
627 g_free (uri);
628 break;
629 case ANJUTA_PROPERTY_OBJECT_TYPE_FILE:
630 text_value = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (prop->object));
631 break;
633 if (text_value && (strlen (text_value) == 0))
635 g_free (text_value);
636 text_value = NULL;
638 return text_value;
641 static gint
642 get_property_value_as_int (AnjutaProperty *prop)
644 gint int_value;
645 gchar *text_value;
646 text_value = get_property_value_as_string (prop);
647 int_value = atoi (text_value);
648 g_free (text_value);
649 return int_value;
652 static void
653 set_property_value_as_string (AnjutaProperty *prop, const gchar *value)
655 gint int_value;
656 char** values;
657 gint i;
659 if (prop->custom)
661 if (prop->set_property != NULL)
663 prop->set_property (prop, value);
664 return;
666 else
668 g_warning ("%s: Undefined set_property() for custom object",
669 prop->key);
670 return;
673 switch (prop->object_type)
675 case ANJUTA_PROPERTY_OBJECT_TYPE_TOGGLE:
676 if (value)
677 int_value = atoi (value);
678 else
679 int_value = 0;
681 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prop->object),
682 int_value);
683 break;
685 case ANJUTA_PROPERTY_OBJECT_TYPE_SPIN:
686 if (value)
687 int_value = atoi (value);
688 else
689 int_value = 0;
691 gtk_spin_button_set_value (GTK_SPIN_BUTTON (prop->object), int_value);
692 break;
694 case ANJUTA_PROPERTY_OBJECT_TYPE_ENTRY:
695 if (value)
696 gtk_entry_set_text (GTK_ENTRY (prop->object), value);
697 else
698 gtk_entry_set_text (GTK_ENTRY (prop->object), "");
699 break;
700 case ANJUTA_PROPERTY_OBJECT_TYPE_COMBO:
701 values = g_object_get_data(G_OBJECT(prop->object), "untranslated");
702 if (value != NULL)
704 for (i=0; values[i] != NULL; i++)
706 if (strcmp(value, values[i]) == 0)
708 gtk_combo_box_set_active(GTK_COMBO_BOX(prop->object), i);
709 break;
713 break;
714 case ANJUTA_PROPERTY_OBJECT_TYPE_TEXT:
716 GtkTextBuffer *buffer;
717 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (prop->object));
718 if (value)
719 gtk_text_buffer_set_text (buffer, value, -1);
720 else
721 gtk_text_buffer_set_text (buffer, "", -1);
723 break;
725 case ANJUTA_PROPERTY_OBJECT_TYPE_COLOR:
727 GdkColor color;
729 if (value)
730 anjuta_util_color_from_string (value, &color.red, &color.green, &color.blue);
732 gtk_color_button_set_color(GTK_COLOR_BUTTON(prop->object), &color);
734 break;
736 case ANJUTA_PROPERTY_OBJECT_TYPE_FONT:
737 if (value)
739 /* If the font name is Xfont name, convert it into
740 Pango font description text -- Just take the family name :) */
741 if (value[0] == '-')
743 /* Font is xfont name */
744 gchar *font_name, *tmp;
745 const gchar *end, *start;
746 start = value;
747 start = g_strstr_len (&start[1], strlen (&start[1]), "-");
748 end = g_strstr_len (&start[1], strlen (&start[1]), "-");
749 font_name = g_strndup (&start[1], end-start-1);
750 tmp = font_name;
752 /* Set font size to (arbitrary) 12 points */
753 font_name = g_strconcat (tmp, " 12", NULL);
754 g_free (tmp);
756 /* DEBUG_PRINT ("Font set as: %s", font_name); */
758 gtk_font_button_set_font_name (GTK_FONT_BUTTON
759 (prop->object), font_name);
760 g_free (font_name);
762 else
764 gtk_font_button_set_font_name (GTK_FONT_BUTTON
765 (prop->object), value);
768 /* FIXME: Set a standard font as default.
769 else
771 gnome_font_picker_set_font_name (GNOME_FONT_PICKER (prop->object),
772 "A standard font");
774 break;
776 case ANJUTA_PROPERTY_OBJECT_TYPE_FOLDER:
777 if (value)
779 gchar *old_folder;
781 /* When the user change the folder, the
782 * current-folder-changed signal is emitted the
783 * gconf key is updated and this function is called.
784 * But setting the current folder here emits
785 * the current-folder-changed signal too.
786 * Moreover this signal is emitted asynchronously so
787 * it is not possible to block it here.
789 * The solution here is to update the widget only
790 * if it is really needed.
792 old_folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (prop->object));
793 if ((old_folder == NULL) || strcmp (old_folder, value))
795 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (prop->object), value);
797 g_free (old_folder);
799 break;
800 case ANJUTA_PROPERTY_OBJECT_TYPE_FILE:
801 if (value)
803 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (prop->object),
804 value);
806 break;
810 static void
811 set_property_value_as_int (AnjutaProperty *prop, gint value)
813 gchar *text_value;
814 text_value = g_strdup_printf ("%d", value);
815 set_property_value_as_string (prop, text_value);
816 g_free (text_value);
819 static gboolean
820 update_property_on_event_str (GtkWidget *widget, GdkEvent *event,
821 gpointer user_data)
823 AnjutaPreferences *pr;
824 AnjutaProperty *p;
825 gchar *val;
827 pr = ANJUTA_PREFERENCES (g_object_get_data (G_OBJECT (widget),
828 "AnjutaPreferences"));
829 p = (AnjutaProperty *) user_data;
830 val = get_property_value_as_string (p);
831 anjuta_preferences_set (pr, p->key, val);
832 g_free (val);
833 return FALSE;
836 static void
837 update_property_on_change_str (GtkWidget *widget, gpointer user_data)
839 AnjutaPreferences *pr;
840 AnjutaProperty *p;
841 gchar *val;
843 pr = ANJUTA_PREFERENCES (g_object_get_data (G_OBJECT (widget),
844 "AnjutaPreferences"));
845 p = (AnjutaProperty *) user_data;
846 val = get_property_value_as_string (p);
847 anjuta_preferences_set (pr, p->key, val);
848 g_free (val);
851 static gboolean
852 block_update_property_on_change_str (GtkWidget *widget, GdkEvent *event,
853 gpointer user_data)
855 AnjutaProperty *p = (AnjutaProperty *) user_data;
857 gtk_signal_handler_block_by_func (GTK_OBJECT(p->object), G_CALLBACK (update_property_on_change_str), p);
858 return FALSE;
861 static gboolean
862 unblock_update_property_on_change_str (GtkWidget *widget, GdkEvent *event,
863 gpointer user_data)
865 AnjutaProperty *p = (AnjutaProperty *) user_data;
867 gtk_signal_handler_unblock_by_func (GTK_OBJECT(p->object), G_CALLBACK (update_property_on_change_str), p);
868 return FALSE;
871 static void
872 update_property_on_change_int (GtkWidget *widget, gpointer user_data)
874 AnjutaPreferences *pr;
875 AnjutaProperty *p;
876 gint val;
878 pr = ANJUTA_PREFERENCES (g_object_get_data (G_OBJECT (widget),
879 "AnjutaPreferences"));
880 p = (AnjutaProperty *) user_data;
881 val = get_property_value_as_int (p);
882 anjuta_preferences_set_int (pr, p->key, val);
885 static void
886 update_property_on_change_color (GtkWidget *widget, gpointer user_data)
888 AnjutaPreferences *pr;
889 AnjutaProperty *p;
890 gchar *val;
892 pr = ANJUTA_PREFERENCES (g_object_get_data (G_OBJECT (widget),
893 "AnjutaPreferences"));
894 p = (AnjutaProperty *) user_data;
895 val = get_property_value_as_string (p);
896 anjuta_preferences_set (pr, p->key, val);
897 g_free (val);
900 static void
901 update_property_on_change_font (GtkWidget *widget,
902 gpointer user_data)
904 AnjutaPreferences *pr;
905 AnjutaProperty *p;
906 gchar *val;
908 pr = ANJUTA_PREFERENCES (g_object_get_data (G_OBJECT (widget),
909 "AnjutaPreferences"));
910 p = (AnjutaProperty *) user_data;
911 val = get_property_value_as_string (p);
912 anjuta_preferences_set (pr, p->key, val);
913 g_free (val);
916 static void
917 unregister_preferences_key (GtkWidget *widget,
918 gpointer user_data)
920 AnjutaProperty *p;
921 AnjutaPreferences *pr;
922 gchar *key;
924 p = (AnjutaProperty *) user_data;
925 pr = g_object_get_data (G_OBJECT (widget),
926 "AnjutaPreferences");
927 key = g_strdup (p->key);
929 g_hash_table_remove (pr->priv->properties, key);
930 g_free (key);
933 static void
934 get_property (GConfClient *gclient, guint cnxt_id,
935 GConfEntry *entry, gpointer user_data)
937 const gchar *key;
938 GConfValue *value;
940 AnjutaProperty *p = (AnjutaProperty *) user_data;
941 key = gconf_entry_get_key (entry);
942 value = gconf_entry_get_value (entry);
943 /* DEBUG_PRINT ("Preference changed %s", key); */
945 if (p->data_type == ANJUTA_PROPERTY_DATA_TYPE_BOOL)
947 gboolean gconf_value;
949 gconf_value = gconf_value_get_bool (value);
950 set_property_value_as_int (p, gconf_value);
952 else if (p->data_type == ANJUTA_PROPERTY_DATA_TYPE_INT)
954 int gconf_value;
956 gconf_value = gconf_value_get_int (value);
957 set_property_value_as_int (p, gconf_value);
959 else
961 const gchar *gconf_value;
962 gconf_value = gconf_value_get_string (value);
963 set_property_value_as_string (p, gconf_value);
967 static void
968 register_callbacks (AnjutaPreferences *pr, AnjutaProperty *p)
970 GConfClient *gclient;
971 gchar *key_error_msg;
973 gclient = pr->priv->gclient;
974 g_object_set_data (G_OBJECT (p->object), "AnjutaPreferences", pr);
975 switch (p->object_type) {
976 case ANJUTA_PROPERTY_OBJECT_TYPE_ENTRY:
977 g_signal_connect (G_OBJECT(p->object), "changed",
978 G_CALLBACK (update_property_on_change_str), p);
979 g_signal_connect (G_OBJECT(p->object), "focus_out_event",
980 G_CALLBACK (update_property_on_event_str), p);
981 g_signal_connect (G_OBJECT(p->object), "focus_out_event",
982 G_CALLBACK (unblock_update_property_on_change_str), p);
983 g_signal_connect (G_OBJECT(p->object), "focus_in_event",
984 G_CALLBACK (block_update_property_on_change_str), p);
985 break;
986 case ANJUTA_PROPERTY_OBJECT_TYPE_SPIN:
987 g_signal_connect (G_OBJECT(p->object), "value-changed",
988 G_CALLBACK (update_property_on_change_int), p);
989 break;
990 case ANJUTA_PROPERTY_OBJECT_TYPE_FONT:
991 g_signal_connect (G_OBJECT(p->object), "font-set",
992 G_CALLBACK (update_property_on_change_font), p);
993 break;
994 case ANJUTA_PROPERTY_OBJECT_TYPE_TEXT:
995 g_signal_connect (G_OBJECT(p->object), "focus_out_event",
996 G_CALLBACK (update_property_on_event_str), p);
997 break;
998 case ANJUTA_PROPERTY_OBJECT_TYPE_COMBO:
999 g_signal_connect (G_OBJECT(p->object), "changed",
1000 G_CALLBACK (update_property_on_change_str), p);
1001 break;
1002 case ANJUTA_PROPERTY_OBJECT_TYPE_TOGGLE:
1003 g_signal_connect (G_OBJECT(p->object), "toggled",
1004 G_CALLBACK (update_property_on_change_int), p);
1005 break;
1006 case ANJUTA_PROPERTY_OBJECT_TYPE_COLOR:
1007 g_signal_connect (G_OBJECT(p->object), "color-set",
1008 G_CALLBACK (update_property_on_change_color), p);
1009 break;
1010 case ANJUTA_PROPERTY_OBJECT_TYPE_FILE:
1011 g_signal_connect (G_OBJECT(p->object), "file-set",
1012 G_CALLBACK (update_property_on_change_str), p);
1013 break;
1014 case ANJUTA_PROPERTY_OBJECT_TYPE_FOLDER:
1015 g_signal_connect (G_OBJECT(p->object), "current-folder-changed",
1016 G_CALLBACK (update_property_on_change_str), p);
1017 break;
1018 default:
1019 break;
1021 if (!gconf_valid_key (build_key (p->key), &key_error_msg))
1023 g_warning ("Invalid key \"%s\": Error: \"%s\"", build_key (p->key),
1024 key_error_msg);
1025 g_free (key_error_msg);
1027 p->notify_id = gconf_client_notify_add (gclient, build_key (p->key),
1028 get_property, p, NULL, NULL);
1030 /* Connect to widget destroy signal so we can automatically unregister
1031 * keys so there aren't any potential conflicts or references to
1032 * nonexistent widgets on subsequent uses of the prefs dialog. */
1033 g_signal_connect (G_OBJECT (p->object), "destroy",
1034 G_CALLBACK (unregister_preferences_key),
1038 static gboolean
1039 preferences_foreach_callback (gchar *key, struct _AnjutaProperty *p,
1040 struct _AnjutaPreferencesForeachData *data)
1042 if (p->object_type != ANJUTA_PROPERTY_OBJECT_TYPE_COMBO)
1044 if (data->filter == ANJUTA_PREFERENCES_FILTER_NONE)
1045 return data->callback (data->pr, key, data->callback_data);
1046 else if (p->flags & data->filter)
1047 return data->callback (data->pr, key, data->callback_data);
1050 return TRUE;
1053 static void
1054 connect_prop_to_object (AnjutaPreferences *pr, AnjutaProperty *p)
1056 int gconf_value;
1057 gchar *value;
1059 if (p->data_type == ANJUTA_PROPERTY_DATA_TYPE_BOOL ||
1060 p->data_type == ANJUTA_PROPERTY_DATA_TYPE_INT)
1062 gconf_value = anjuta_preferences_get_int (pr, p->key);
1063 value = g_strdup_printf ("%d", gconf_value);
1064 set_property_value_as_string (p, value);
1066 else
1068 value = anjuta_preferences_get (pr, p->key);
1069 set_property_value_as_string (p, value);
1070 g_free (value);
1076 * anjuta_preferences_register_property_raw:
1077 * @pr: a #AnjutaPreferences object
1078 * @object: Widget to register
1079 * @key: Property key
1080 * @default_value: Default value of the key
1081 * @flags: Flags
1082 * @object_type: Object type of widget
1083 * @data_type: Data type of the property
1085 * This also registers only one widget, but instead of supplying the property
1086 * parameters as a single parsable string (as done in previous method), it
1087 * takes them separately.
1089 * Return value: TRUE if sucessful.
1091 gboolean
1092 anjuta_preferences_register_property_raw (AnjutaPreferences *pr,
1093 GtkWidget *object,
1094 const gchar *key,
1095 const gchar *default_value,
1096 guint flags,
1097 AnjutaPropertyObjectType object_type,
1098 AnjutaPropertyDataType data_type)
1100 AnjutaProperty *p;
1101 GConfValue *value;
1103 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), FALSE);
1104 g_return_val_if_fail (GTK_IS_WIDGET (object), FALSE);
1105 g_return_val_if_fail (key != NULL, FALSE);
1106 g_return_val_if_fail (strlen(key) > 0, FALSE);
1107 g_return_val_if_fail ((object_type != ANJUTA_PROPERTY_OBJECT_TYPE_COMBO) ||
1108 ((default_value != NULL) &&
1109 (*default_value != '\0')), FALSE);
1111 p = g_new0 (AnjutaProperty, 1);
1112 g_object_ref (object);
1113 p->object = object;
1114 p->object_type = object_type;
1115 p->data_type = data_type;
1116 p->key = g_strdup (key);
1117 p->gclient = pr->priv->gclient;
1119 value = gconf_client_get (pr->priv->gclient,
1120 build_key (p->key), NULL);
1121 if (value)
1123 /* Verify key type. Unset key if type mismatch. */
1124 if (!((value->type == GCONF_VALUE_BOOL &&
1125 data_type == ANJUTA_PROPERTY_DATA_TYPE_BOOL) ||
1126 (value->type == GCONF_VALUE_INT &&
1127 data_type == ANJUTA_PROPERTY_DATA_TYPE_INT) ||
1128 (value->type == GCONF_VALUE_STRING &&
1129 data_type != ANJUTA_PROPERTY_DATA_TYPE_BOOL &&
1130 data_type != ANJUTA_PROPERTY_DATA_TYPE_INT)))
1132 gconf_client_unset (pr->priv->gclient, build_key (key), NULL);
1134 gconf_value_free (value);
1136 if (default_value)
1138 p->default_value = g_strdup (default_value);
1139 if (strlen (default_value) > 0)
1141 /* For combo, initialize the untranslated strings */
1142 if (object_type == ANJUTA_PROPERTY_OBJECT_TYPE_COMBO)
1144 gchar *old_value;
1145 gchar **vstr;
1147 vstr = g_strsplit (default_value, ",", 100);
1148 g_object_set_data(G_OBJECT(p->object), "untranslated",
1149 vstr);
1150 old_value = anjuta_preferences_get (pr, p->key);
1151 if (old_value == NULL && vstr[0])
1153 /* DEBUG_PRINT ("Setting default pref value: %s = %s",
1154 p->key, default_value); */
1155 anjuta_preferences_set (pr, p->key, vstr[0]);
1157 if (old_value)
1158 g_free (old_value);
1160 else if (p->data_type != ANJUTA_PROPERTY_DATA_TYPE_BOOL &&
1161 p->data_type != ANJUTA_PROPERTY_DATA_TYPE_INT)
1163 gchar *old_value;
1164 old_value = anjuta_preferences_get (pr, p->key);
1165 if (old_value == NULL)
1167 /* DEBUG_PRINT ("Setting default pref value: %s = %s",
1168 p->key, default_value);*/
1169 anjuta_preferences_set (pr, p->key, default_value);
1171 if (old_value)
1172 g_free (old_value);
1174 else
1176 value = gconf_client_get (pr->priv->gclient,
1177 build_key (p->key), NULL);
1178 if (value == NULL)
1180 /* DEBUG_PRINT ("Setting default pref value: %s = %s",
1181 p->key, default_value);*/
1182 if (p->data_type == ANJUTA_PROPERTY_DATA_TYPE_INT)
1183 gconf_client_set_int (pr->priv->gclient,
1184 build_key (p->key),
1185 atoi (default_value), NULL);
1186 else
1187 gconf_client_set_bool (pr->priv->gclient,
1188 build_key (p->key),
1189 atoi (default_value), NULL);
1191 if (value)
1192 gconf_value_free (value);
1196 p->flags = flags;
1197 p->custom = FALSE;
1198 p->set_property = NULL;
1199 p->get_property = NULL;
1201 g_hash_table_insert (pr->priv->properties, g_strdup (key), p);
1202 connect_prop_to_object (pr, p);
1203 register_callbacks (pr, p);
1204 return TRUE;
1208 * anjuta_preferences_register_property_custom:
1209 * @pr: a #AnjutaPreferences object.
1210 * @object: Object to register.
1211 * @key: Property key.
1212 * @default_value: Default value of the key.
1213 * @data_type: property data type.
1214 * @flags: Flags
1215 * @set_property: Set property to widget callback.
1216 * @get_property: Get property from widget callback.
1218 * This is meant for complex widgets which can not be set/get with the
1219 * standard object set/get methods. Custom set/get methods are passed for
1220 * the property to set/get the value to/from the widget.
1222 * Return value: TRUE if sucessful.
1224 gboolean
1225 anjuta_preferences_register_property_custom (AnjutaPreferences *pr,
1226 GtkWidget *object,
1227 const gchar *key,
1228 const gchar *default_value,
1229 AnjutaPropertyDataType data_type,
1230 guint flags,
1231 void (*set_property) (AnjutaProperty *prop, const gchar *value),
1232 gchar * (*get_property) (AnjutaProperty *))
1234 AnjutaProperty *p;
1235 GConfValue *value;
1237 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), FALSE);
1238 g_return_val_if_fail (GTK_IS_WIDGET (object), FALSE);
1239 g_return_val_if_fail (key != NULL, FALSE);
1240 g_return_val_if_fail (strlen(key) > 0, FALSE);
1242 p = g_new0 (AnjutaProperty, 1);
1243 g_object_ref (object);
1244 p->object = object;
1245 p->object_type = (AnjutaPropertyObjectType) 0;
1246 p->data_type = data_type;
1247 p->key = g_strdup (key);
1248 p->gclient = pr->priv->gclient;
1250 value = gconf_client_get (pr->priv->gclient,
1251 build_key (p->key), NULL);
1252 if (value)
1254 /* Verify key type. Unset key if type mismatch. */
1255 if (!((value->type == GCONF_VALUE_BOOL &&
1256 data_type == ANJUTA_PROPERTY_DATA_TYPE_BOOL) ||
1257 (value->type == GCONF_VALUE_INT &&
1258 data_type == ANJUTA_PROPERTY_DATA_TYPE_INT) ||
1259 (value->type == GCONF_VALUE_STRING &&
1260 data_type != ANJUTA_PROPERTY_DATA_TYPE_BOOL &&
1261 data_type != ANJUTA_PROPERTY_DATA_TYPE_INT)))
1263 gconf_client_unset (pr->priv->gclient, build_key (key), NULL);
1265 gconf_value_free (value);
1267 if (default_value)
1269 p->default_value = g_strdup (default_value);
1270 if (p->data_type != ANJUTA_PROPERTY_DATA_TYPE_BOOL &&
1271 p->data_type != ANJUTA_PROPERTY_DATA_TYPE_INT)
1273 gchar *old_value;
1274 old_value = anjuta_preferences_get (pr, p->key);
1275 if (old_value == NULL)
1277 /* DEBUG_PRINT ("Setting default pref value: %s = %s",
1278 p->key, default_value); */
1279 anjuta_preferences_set (pr, p->key, default_value);
1281 if (old_value)
1282 g_free (old_value);
1284 else
1286 value = gconf_client_get (pr->priv->gclient,
1287 build_key (p->key), NULL);
1288 if (value == NULL)
1290 /* DEBUG_PRINT ("Setting default pref value: %s = %s",
1291 p->key, default_value);*/
1292 if (p->data_type == ANJUTA_PROPERTY_DATA_TYPE_INT)
1293 gconf_client_set_int (pr->priv->gclient,
1294 build_key (p->key),
1295 atoi (default_value), NULL);
1296 else
1297 gconf_client_set_bool (pr->priv->gclient,
1298 build_key (p->key),
1299 atoi (default_value), NULL);
1301 if (value)
1302 gconf_value_free (value);
1305 p->custom = TRUE;
1306 p->flags = flags;
1307 p->set_property = set_property;
1308 p->get_property = get_property;
1310 g_hash_table_insert (pr->priv->properties, g_strdup (key), p);
1312 /* Connect to widget destroy signal so we can automatically unregister
1313 * keys so there aren't any potential conflicts or references to
1314 * nonexistent widgets on subsequent uses of the prefs dialog. */
1315 g_object_set_data (G_OBJECT (p->object), "AnjutaPreferences", pr);
1316 g_signal_connect (G_OBJECT (p->object), "destroy",
1317 G_CALLBACK (unregister_preferences_key),
1319 return TRUE;
1323 * anjuta_preferences_register_property_from_string:
1324 * @pr: a #AnjutaPreferences object
1325 * @object: Widget to register
1326 * @property_desc: Property description (see anjuta_preferences_add_page())
1328 * This registers only one widget. The widget could be shown elsewhere.
1329 * the property_description should be of the form described before.
1331 * Return value: TRUE if sucessful.
1333 gboolean
1334 anjuta_preferences_register_property_from_string (AnjutaPreferences *pr,
1335 GtkWidget *object,
1336 const gchar *property_desc)
1338 gchar **fields;
1339 gint n_fields;
1341 AnjutaPropertyObjectType object_type;
1342 AnjutaPropertyDataType data_type;
1343 gchar *key;
1344 gchar *default_value;
1345 gint flags;
1347 g_return_val_if_fail (ANJUTA_IS_PREFERENCES(pr), FALSE);
1348 g_return_val_if_fail ((GTK_IS_WIDGET (object)), FALSE);
1349 g_return_val_if_fail (property_desc != NULL, FALSE);
1351 fields = g_strsplit (property_desc, ":", 5);
1352 g_return_val_if_fail (fields, FALSE);
1353 for (n_fields = 0; fields[n_fields]; n_fields++);
1354 if (n_fields != 5)
1356 g_strfreev (fields);
1357 return FALSE;
1359 object_type = get_object_type_from_string (fields[0]);
1360 data_type = get_data_type_from_string (fields[1]);
1361 default_value = fields[2];
1362 flags = atoi (fields[3]);
1363 key = fields[4];
1364 if (object_type < 0)
1366 g_warning ("Invalid property object type in property description");
1367 g_strfreev (fields);
1368 return FALSE;
1370 if (data_type < 0)
1372 g_warning ("Invalid property data type in property description");
1373 g_strfreev (fields);
1374 return FALSE;
1376 anjuta_preferences_register_property_raw (pr, object, key, default_value,
1377 flags, object_type,
1378 data_type);
1379 g_strfreev (fields);
1380 return TRUE;
1384 * anjuta_preferences_register_all_properties_from_glade_xml:
1385 * @pr: a #AnjutaPreferences Object
1386 * @gxml: GladeXML object containing the properties widgets.
1387 * @parent: Parent widget in the gxml object
1389 * This will register all the properties names of the format described above
1390 * without considering the UI. Useful if you have the widgets shown elsewhere
1391 * but you want them to be part of preferences system.
1393 void
1394 anjuta_preferences_register_all_properties_from_glade_xml (AnjutaPreferences *pr,
1395 GladeXML *gxml,
1396 GtkWidget *parent)
1398 GList *widgets;
1399 GList *node;
1401 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
1402 g_return_if_fail (gxml != NULL);
1404 widgets = glade_xml_get_widget_prefix (gxml, "preferences_");
1405 node = widgets;
1406 while (node)
1408 const gchar *name;
1409 GtkWidget *widget, *p;
1410 gboolean cont_flag = FALSE;
1412 widget = node->data;
1414 p = gtk_widget_get_parent (widget);
1415 /* Added only if it's a desendend child of the parent */
1416 while (p != parent)
1418 if (p == NULL)
1420 cont_flag = TRUE;
1421 break;
1423 p = gtk_widget_get_parent (p);
1425 if (cont_flag == TRUE)
1427 node = g_list_next (node);
1428 continue;
1431 name = glade_get_widget_name (widget);
1432 if (strncmp (name, PREFERENCE_PROPERTY_PREFIX,
1433 strlen (PREFERENCE_PROPERTY_PREFIX)) == 0)
1435 const gchar *property = &name[strlen (PREFERENCE_PROPERTY_PREFIX)];
1436 anjuta_preferences_register_property_from_string (pr, widget,
1437 property);
1439 node = g_list_next (node);
1444 * anjuta_preferences_reset_defaults:
1445 * @pr: a #AnjutaPreferences object.
1447 * Resets the default values into the keys
1449 void
1450 anjuta_preferences_reset_defaults (AnjutaPreferences * pr)
1452 GtkWidget *dlg;
1454 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
1456 dlg = gtk_message_dialog_new (GTK_WINDOW (pr),
1457 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
1458 GTK_BUTTONS_NONE,
1459 _("Are you sure you want to reset the preferences to\n"
1460 "their default settings?"));
1461 gtk_dialog_add_button (GTK_DIALOG (dlg), GTK_STOCK_CANCEL,
1462 GTK_RESPONSE_CANCEL);
1463 anjuta_util_dialog_add_button (GTK_DIALOG (dlg), _("_Reset"),
1464 GTK_STOCK_REVERT_TO_SAVED,
1465 GTK_RESPONSE_YES);
1466 if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_YES)
1468 /* FIXME: Reset preferences to built-in default values. */
1470 gtk_widget_destroy (dlg);
1474 * anjuta_preferences_foreach:
1475 * @pr: A #AnjutaPreferences object.
1476 * @filter: Keys to filter out from the loop.
1477 * @callback: User callback function.
1478 * @data: User data passed to @callback
1480 * Calls @callback function for each of the registered property keys. Keys
1481 * with matching @filter flags are left out of the loop. If @filter is
1482 * ANJUTA_PREFERENCES_FILTER_NONE, all properties are selected for the loop.
1484 void
1485 anjuta_preferences_foreach (AnjutaPreferences *pr,
1486 AnjutaPreferencesFilterType filter,
1487 AnjutaPreferencesCallback callback,
1488 gpointer data)
1490 struct _AnjutaPreferencesForeachData foreach_data;
1492 foreach_data.pr = pr;
1493 foreach_data.filter = filter;
1494 foreach_data.callback = callback;
1495 foreach_data.callback_data = data;
1497 g_hash_table_find (pr->priv->properties,
1498 (GHRFunc) preferences_foreach_callback,
1499 &foreach_data);
1504 * anjuta_preferences_add_page:
1505 * @pr: a #AnjutaPreferences object
1506 * @gxml: #GladeXML object containing the preferences page
1507 * @glade_widget_name: Page widget name (as give with glade interface editor).
1508 * The widget will be searched with the given name and detached
1509 * (that is, removed from the container, if present) from it's parent.
1510 * @icon_filename: File name (of the form filename.png) of the icon representing
1511 * the preference page.
1513 * Add a page to the preferences sytem.
1514 * gxml is the GladeXML object of the glade dialog containing the page widget.
1515 * The glade dialog will contain the layout of the preferences widgets.
1516 * The widgets which are preference widgets (e.g. toggle button) should have
1517 * widget names of the form:
1519 * <programlisting>
1520 * preferences_OBJECTTYPE:DATATYPE:DEFAULT:FLAGS:PROPERTYKEY
1521 * where,
1522 * OBJECTTYPE is 'toggle', 'spin', 'entry', 'text', 'color', 'font' or 'file' .
1523 * DATATYPE is 'bool', 'int', 'float', 'text', 'color' or 'font'.
1524 * DEFAULT is the default value (in the appropriate format). The format
1525 * for color is '#XXXXXX' representing RGB value and for
1526 * font, it is the pango font description.
1527 * FLAGS is any flag associated with the property. Currently it
1528 * has only two values -- 0 and 1. For normal preference
1529 * property which is saved/retrieved globally, the flag = 0.
1530 * For preference property which is also saved/retrieved
1531 * along with the project, the flag = 1.
1532 * PROPERTYKEY is the property key. e.g - 'tab.size'.
1533 * </programlisting>
1535 * All widgets having the above names in the gxml tree will be registered
1536 * and will become part of auto saving/loading. For example, refer to
1537 * anjuta preferences dialogs and study the widget names.
1539 void
1540 anjuta_preferences_add_page (AnjutaPreferences* pr, GladeXML *gxml,
1541 const gchar* glade_widget_name,
1542 const gchar* title,
1543 const gchar *icon_filename)
1545 GtkWidget *parent;
1546 GtkWidget *page;
1547 GdkPixbuf *pixbuf;
1548 gchar *image_path;
1550 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
1551 g_return_if_fail (glade_widget_name != NULL);
1552 g_return_if_fail (icon_filename != NULL);
1554 page = glade_xml_get_widget (gxml, glade_widget_name);
1555 g_object_ref (page);
1556 g_return_if_fail (GTK_IS_WIDGET (page));
1557 parent = gtk_widget_get_parent (page);
1558 if (parent && GTK_IS_CONTAINER (parent))
1560 if (GTK_IS_NOTEBOOK (parent))
1562 gint page_num;
1564 page_num = gtk_notebook_page_num (GTK_NOTEBOOK (parent), page);
1565 gtk_notebook_remove_page (GTK_NOTEBOOK (parent), page_num);
1567 else
1569 gtk_container_remove (GTK_CONTAINER (parent), page);
1572 image_path = anjuta_res_get_pixmap_file (icon_filename);
1573 pixbuf = gdk_pixbuf_new_from_file (image_path, NULL);
1574 anjuta_preferences_dialog_add_page (ANJUTA_PREFERENCES_DIALOG (pr->priv->prefs_dialog),
1575 glade_widget_name, title, pixbuf, page);
1576 anjuta_preferences_register_all_properties_from_glade_xml (pr, gxml, page);
1577 g_object_unref (page);
1578 g_free (image_path);
1579 g_object_unref (pixbuf);
1582 void
1583 anjuta_preferences_remove_page (AnjutaPreferences *pr,
1584 const gchar *page_name)
1586 if (pr->priv->prefs_dialog)
1588 anjuta_preferences_dialog_remove_page (ANJUTA_PREFERENCES_DIALOG (pr->priv->prefs_dialog),
1589 page_name);
1593 static void
1594 on_preferences_dialog_destroyed (GtkWidget *preferencess_dialog,
1595 AnjutaPreferences *pr)
1597 GList *plugins;
1598 GList *current_plugin;
1600 plugins = anjuta_plugin_manager_get_active_plugin_objects (pr->priv->plugin_manager);
1601 current_plugin = plugins;
1603 while (current_plugin)
1605 if (IANJUTA_IS_PREFERENCES (current_plugin->data))
1607 ianjuta_preferences_unmerge (IANJUTA_PREFERENCES (current_plugin->data),
1608 pr, NULL);
1611 current_plugin = g_list_next (current_plugin);
1615 g_object_unref (pr->priv->prefs_dialog);
1617 g_list_free (plugins);
1618 pr->priv->prefs_dialog = NULL;
1621 GtkWidget *
1622 anjuta_preferences_get_dialog (AnjutaPreferences *pr)
1624 GList *plugins;
1625 GList *current_plugin;
1627 if (pr->priv->prefs_dialog)
1628 return pr->priv->prefs_dialog;
1629 else
1631 pr->priv->prefs_dialog = anjuta_preferences_dialog_new ();
1633 g_signal_connect (G_OBJECT (pr->priv->prefs_dialog), "destroy",
1634 G_CALLBACK (on_preferences_dialog_destroyed),
1635 pr);
1637 plugins = anjuta_plugin_manager_get_active_plugin_objects (pr->priv->plugin_manager);
1638 current_plugin = plugins;
1640 while (current_plugin)
1642 if (IANJUTA_IS_PREFERENCES (current_plugin->data))
1644 ianjuta_preferences_merge (IANJUTA_PREFERENCES (current_plugin->data),
1645 pr, NULL);
1648 current_plugin = g_list_next (current_plugin);
1651 g_list_free (plugins);
1653 return g_object_ref_sink (pr->priv->prefs_dialog);
1657 gboolean
1658 anjuta_preferences_is_dialog_created (AnjutaPreferences *pr)
1660 return pr->priv->prefs_dialog;
1663 static void anjuta_preferences_class_init (AnjutaPreferencesClass *class);
1664 static void anjuta_preferences_instance_init (AnjutaPreferences *pr);
1666 GType
1667 anjuta_preferences_get_type ()
1669 static GType obj_type = 0;
1671 if (!obj_type)
1673 static const GTypeInfo obj_info =
1675 sizeof (AnjutaPreferencesClass),
1676 (GBaseInitFunc) NULL,
1677 (GBaseFinalizeFunc) NULL,
1678 (GClassInitFunc) anjuta_preferences_class_init,
1679 (GClassFinalizeFunc) NULL,
1680 NULL, /* class_data */
1681 sizeof (AnjutaPreferencesClass),
1682 0, /* n_preallocs */
1683 (GInstanceInitFunc) anjuta_preferences_instance_init,
1684 NULL /* value_table */
1686 obj_type = g_type_register_static (G_TYPE_OBJECT,
1687 "AnjutaPreferences", &obj_info, 0);
1689 return obj_type;
1692 static void
1693 anjuta_preferences_dispose (GObject *obj)
1695 AnjutaPreferences *pr = ANJUTA_PREFERENCES (obj);
1697 if (pr->priv->properties)
1699 /* This will release the refs on property objects */
1700 g_hash_table_destroy (pr->priv->properties);
1701 pr->priv->properties = NULL;
1705 static void
1706 anjuta_preferences_instance_init (AnjutaPreferences *pr)
1708 pr->priv = g_new0 (AnjutaPreferencesPriv, 1);
1710 pr->priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal,
1711 g_free,
1712 (GDestroyNotify) property_destroy);
1714 pr->priv->gclient = gconf_client_get_default();
1715 gconf_client_add_dir (pr->priv->gclient, GCONF_KEY_PREFIX,
1716 GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
1720 static void
1721 anjuta_preferences_finalize (GObject *obj)
1723 AnjutaPreferences *pr = ANJUTA_PREFERENCES (obj);
1725 if (pr->priv->prefs_dialog)
1726 gtk_widget_destroy (pr->priv->prefs_dialog);
1728 g_object_unref (pr->priv->plugin_manager);
1729 g_free (pr->priv);
1732 static void
1733 anjuta_preferences_class_init (AnjutaPreferencesClass *class)
1735 GObjectClass *object_class = G_OBJECT_CLASS (class);
1737 object_class->dispose = anjuta_preferences_dispose;
1738 object_class->finalize = anjuta_preferences_finalize;
1742 * anjuta_preferences_new:
1744 * Creates a new #AnjutaPreferences object
1746 * Return value: A #AnjutaPreferences object.
1748 AnjutaPreferences *
1749 anjuta_preferences_new (AnjutaPluginManager *plugin_manager)
1751 AnjutaPreferences *pr;
1753 pr = g_object_new (ANJUTA_TYPE_PREFERENCES, NULL);
1754 pr->priv->plugin_manager = g_object_ref (plugin_manager);
1756 return pr;
1761 * anjuta_preferences_notify_add:
1762 * @pr: A #AnjutaPreferences object.
1763 * @key: Key to monitor.
1764 * @func: User callback function.
1765 * @data: User data passed to @func
1766 * @destroy_notify: Destroy notify function - called when notify is removed.
1768 * This is similar to gconf_client_notify_add(), except that the key is not
1769 * given as full path. Only anjuta preference key is given. The key prefix
1770 * is added internally.
1772 * Return value: Notify ID.
1774 guint
1775 anjuta_preferences_notify_add (AnjutaPreferences *pr,
1776 const gchar *key,
1777 GConfClientNotifyFunc func,
1778 gpointer data,
1779 GFreeFunc destroy_notify)
1781 return gconf_client_notify_add (pr->priv->gclient,
1782 build_key (key),
1783 func, data, destroy_notify, NULL);
1787 * anjuta_preferences_notify_remove:
1788 * @pr: A #AnjutaPreferences object.
1789 * @notify_id: Notify ID returned by anjuta_preferences_notify_add().
1791 * Removes the notify callback added with anjuta_preferences_notify_add().
1793 void
1794 anjuta_preferences_notify_remove (AnjutaPreferences *pr, guint notify_id)
1796 gconf_client_notify_remove (pr->priv->gclient, notify_id);
1800 * anjuta_preferences_get_prefix:
1801 * @pr: A #AnjutaPreferences object.
1803 * Returns the gconf key prefix used by anjuta to store its preferences.
1805 * Return value: preferences keys prefix.
1807 const gchar*
1808 anjuta_preferences_get_prefix (AnjutaPreferences *pr)
1810 return PREFERENCE_PROPERTY_PREFIX;
1814 * anjuta_preferences_dir_exists:
1815 * @pr: A #AnjutaPreferences object.
1816 * @dir: Directory to checkfor.
1818 * Returns TRUE if dir exists.
1820 #ifdef __GNUC__
1821 inline
1822 #endif
1823 gboolean
1824 anjuta_preferences_dir_exists (AnjutaPreferences *pr, const gchar *dir)
1826 g_return_val_if_fail (ANJUTA_IS_PREFERENCES (pr), FALSE);
1827 g_return_val_if_fail (dir != NULL, FALSE);
1829 return gconf_client_dir_exists(pr->priv->gclient, build_key (dir), NULL);
1833 * anjuta_preferences_add_dir:
1834 * @pr: A #AnjutaPreferences object.
1835 * @dir: Directory to add to the list.
1836 * @preload: Degree of preload.
1838 * Add a directory to the list of directories the GConfClient.
1840 #ifdef __GNUC__
1841 inline
1842 #endif
1843 void
1844 anjuta_preferences_add_dir (AnjutaPreferences *pr, const gchar *dir,
1845 GConfClientPreloadType preload)
1847 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
1848 g_return_if_fail (dir != NULL);
1850 gconf_client_add_dir(pr->priv->gclient, build_key (dir),
1851 preload, NULL);
1855 * anjuta_preferences_remove_dir:
1856 * @pr: A #AnjutaPreferences object.
1857 * @dir: Directory to remove from the list.
1859 * Remove a directory from the list of directories.
1861 #ifdef __GNUC__
1862 inline
1863 #endif
1864 void
1865 anjuta_preferences_remove_dir (AnjutaPreferences *pr, const gchar *dir)
1867 g_return_if_fail (ANJUTA_IS_PREFERENCES (pr));
1868 g_return_if_fail (dir != NULL);
1870 gconf_client_remove_dir(pr->priv->gclient, build_key (dir), NULL);