summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRamiro Estrugo <ramiro@src.gnome.org>2001-03-31 00:56:38 +0000
committerRamiro Estrugo <ramiro@src.gnome.org>2001-03-31 00:56:38 +0000
commitcbb03695e597a5c216cecd388646723b617d546f (patch)
treed36f6e5ee419fca9afc9ac8177d144ccbd3c60a2
parent982aef48f1cfe184370216a792076885d155e7be (diff)
downloadnautilus-cbb03695e597a5c216cecd388646723b617d546f.tar.gz
reviewed by: John Sullivan <sullivan@eazel.com>
* components/text/nautilus-text-view.c: (merge_bonobo_menu_items): Add a FIXME for a bug. * libnautilus-extensions/nautilus-gconf-extensions.h: * libnautilus-extensions/nautilus-gconf-extensions.c: (nautilus_gconf_get_value), (nautilus_gconf_value_is_equal), (nautilus_gconf_value_free): New convenience functions for using GConf values directly. * libnautilus-extensions/nautilus-gdk-font-extensions.c: Remove a FIXME for a bug i fixed recently. * libnautilus-extensions/nautilus-preferences.c: (preferences_callback_entry_invoke_function), (preferences_entry_invoke_callbacks_if_needed), (preferences_something_changed_notice), (preferences_global_table_check_changes_function), (preferences_entry_update_cached_value), (preferences_entry_ensure_gconf_connection), (preferences_callback_entry_free_func), (preferences_entry_free), (preferences_global_table_insert): Fix bug 5875 - Preference callbacks should only trigger when values change. The problem was twofold. First, when the user level changed, we would invoke all callbacks regardless of whether the value had changed or not. Second, when a GConf value changed notice triggered, we would invoke the corresponding Nautilus preference callback regardless of whether the value according to Nautilus changed or not. The fact that Nautilus preferences have a visibility attribute means that even if the GConf value changes, they may have a different value (a default due to high visibility for example)
-rw-r--r--ChangeLog37
-rw-r--r--components/text/nautilus-text-view.c5
-rw-r--r--libnautilus-extensions/nautilus-gconf-extensions.c80
-rw-r--r--libnautilus-extensions/nautilus-gconf-extensions.h38
-rw-r--r--libnautilus-extensions/nautilus-gdk-font-extensions.c10
-rw-r--r--libnautilus-extensions/nautilus-preferences.c138
-rw-r--r--libnautilus-private/nautilus-gconf-extensions.c80
-rw-r--r--libnautilus-private/nautilus-gconf-extensions.h38
-rw-r--r--libnautilus-private/nautilus-gdk-font-extensions.c10
-rw-r--r--libnautilus-private/nautilus-preferences.c138
10 files changed, 440 insertions, 134 deletions
diff --git a/ChangeLog b/ChangeLog
index d65b436f7..89b7e76ef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2001-03-30 Ramiro Estrugo <ramiro@eazel.com>
+
+ reviewed by: John Sullivan <sullivan@eazel.com>
+
+ * components/text/nautilus-text-view.c: (merge_bonobo_menu_items):
+ Add a FIXME for a bug.
+
+ * libnautilus-extensions/nautilus-gconf-extensions.h:
+ * libnautilus-extensions/nautilus-gconf-extensions.c:
+ (nautilus_gconf_get_value), (nautilus_gconf_value_is_equal),
+ (nautilus_gconf_value_free): New convenience functions for using
+ GConf values directly.
+
+ * libnautilus-extensions/nautilus-gdk-font-extensions.c:
+ Remove a FIXME for a bug i fixed recently.
+
+ * libnautilus-extensions/nautilus-preferences.c:
+ (preferences_callback_entry_invoke_function),
+ (preferences_entry_invoke_callbacks_if_needed),
+ (preferences_something_changed_notice),
+ (preferences_global_table_check_changes_function),
+ (preferences_entry_update_cached_value),
+ (preferences_entry_ensure_gconf_connection),
+ (preferences_callback_entry_free_func), (preferences_entry_free),
+ (preferences_global_table_insert):
+ Fix bug 5875 - Preference callbacks should only trigger when
+ values change.
+ The problem was twofold. First, when the user level changed, we
+ would invoke all callbacks regardless of whether the value had
+ changed or not. Second, when a GConf value changed notice
+ triggered, we would invoke the corresponding Nautilus preference
+ callback regardless of whether the value according to Nautilus
+ changed or not.
+ The fact that Nautilus preferences have a visibility attribute
+ means that even if the GConf value changes, they may have a
+ different value (a default due to high visibility for example)
+
2001-03-30 John Sullivan <sullivan@eazel.com>
* libnautilus-extensions/nautilus-preferences.c:
diff --git a/components/text/nautilus-text-view.c b/components/text/nautilus-text-view.c
index 1a06590f1..b00b6a2c7 100644
--- a/components/text/nautilus-text-view.c
+++ b/components/text/nautilus-text-view.c
@@ -769,6 +769,11 @@ merge_bonobo_menu_items (BonoboControl *control, gboolean state, gpointer user_d
* See nautilus-text-view-ui.xml. Need to query system for
* available fonts instead of hard coding the font list
*/
+
+ /* FIXME bugzilla.eazel.com 7907:
+ * The "GTK System Font" string is hard coded in many places.
+ * Please see nautilus-text-view-ui.xml.
+ */
nautilus_view_set_up_ui (NAUTILUS_VIEW (text_view),
DATADIR,
"nautilus-text-view-ui.xml",
diff --git a/libnautilus-extensions/nautilus-gconf-extensions.c b/libnautilus-extensions/nautilus-gconf-extensions.c
index 15b92e229..65ec1845d 100644
--- a/libnautilus-extensions/nautilus-gconf-extensions.c
+++ b/libnautilus-extensions/nautilus-gconf-extensions.c
@@ -27,6 +27,8 @@
#include "nautilus-glib-extensions.h"
#include "nautilus-stock-dialogs.h"
+#include "nautilus-string.h"
+
#include <gconf/gconf-client.h>
#include <gconf/gconf.h>
#include <libgnome/gnome-i18n.h>
@@ -318,3 +320,81 @@ nautilus_gconf_suggest_sync (void)
gconf_client_suggest_sync (client, &error);
nautilus_gconf_handle_error (&error);
}
+
+GConfValue*
+nautilus_gconf_get_value (const char *key)
+{
+ GConfValue *value = NULL;
+ GConfClient *client;
+ GError *error = NULL;
+
+ g_return_val_if_fail (key != NULL, NULL);
+
+ client = nautilus_gconf_client_get_global ();
+ g_return_val_if_fail (client != NULL, NULL);
+
+ value = gconf_client_get (client, key, &error);
+
+ if (nautilus_gconf_handle_error (&error)) {
+ if (value != NULL) {
+ gconf_value_free (value);
+ value = NULL;
+ }
+ }
+
+ return value;
+}
+
+gboolean
+nautilus_gconf_value_is_equal (const GConfValue *a,
+ const GConfValue *b)
+{
+ if (a == NULL && b == NULL) {
+ return TRUE;
+ }
+
+ if (a == NULL || b == NULL) {
+ return FALSE;
+ }
+
+ if (a->type != b->type) {
+ return FALSE;
+ }
+
+ switch (a->type) {
+ case GCONF_VALUE_STRING:
+ return nautilus_str_is_equal (a->d.string_data, b->d.string_data);
+ break;
+
+ case GCONF_VALUE_INT:
+ return a->d.int_data == b->d.int_data;
+ break;
+
+ case GCONF_VALUE_FLOAT:
+ return a->d.float_data == b->d.float_data;
+ break;
+
+ case GCONF_VALUE_BOOL:
+ return a->d.bool_data == b->d.bool_data;
+ break;
+
+ case GCONF_VALUE_LIST:
+ /* FIXME */
+ g_assert (0);
+ return FALSE;
+ default:
+ }
+
+ g_assert_not_reached ();
+ return FALSE;
+}
+
+void
+nautilus_gconf_value_free (GConfValue *value)
+{
+ if (value == NULL) {
+ return;
+ }
+
+ gconf_value_free (value);
+}
diff --git a/libnautilus-extensions/nautilus-gconf-extensions.h b/libnautilus-extensions/nautilus-gconf-extensions.h
index a9393feb4..7c566b8e3 100644
--- a/libnautilus-extensions/nautilus-gconf-extensions.h
+++ b/libnautilus-extensions/nautilus-gconf-extensions.h
@@ -31,23 +31,27 @@
BEGIN_GNOME_DECLS
-GConfClient *nautilus_gconf_client_get_global (void);
-gboolean nautilus_gconf_handle_error (GError **error);
-void nautilus_gconf_set_boolean (const char *key,
- gboolean boolean_value);
-gboolean nautilus_gconf_get_boolean (const char *key);
-int nautilus_gconf_get_integer (const char *key);
-void nautilus_gconf_set_integer (const char *key,
- int int_value);
-char * nautilus_gconf_get_string (const char *key);
-void nautilus_gconf_set_string (const char *key,
- const char *string_value);
-GList * nautilus_gconf_get_string_list (const char *key);
-void nautilus_gconf_set_string_list (const char *key,
- GList *string_list_value);
-gboolean nautilus_gconf_is_default (const char *key);
-gboolean nautilus_gconf_monitor_directory (const char *directory);
-void nautilus_gconf_suggest_sync (void);
+GConfClient *nautilus_gconf_client_get_global (void);
+gboolean nautilus_gconf_handle_error (GError **error);
+void nautilus_gconf_set_boolean (const char *key,
+ gboolean boolean_value);
+gboolean nautilus_gconf_get_boolean (const char *key);
+int nautilus_gconf_get_integer (const char *key);
+void nautilus_gconf_set_integer (const char *key,
+ int int_value);
+char * nautilus_gconf_get_string (const char *key);
+void nautilus_gconf_set_string (const char *key,
+ const char *string_value);
+GList * nautilus_gconf_get_string_list (const char *key);
+void nautilus_gconf_set_string_list (const char *key,
+ GList *string_list_value);
+gboolean nautilus_gconf_is_default (const char *key);
+gboolean nautilus_gconf_monitor_directory (const char *directory);
+void nautilus_gconf_suggest_sync (void);
+GConfValue* nautilus_gconf_get_value (const char *key);
+gboolean nautilus_gconf_value_is_equal (const GConfValue *a,
+ const GConfValue *b);
+void nautilus_gconf_value_free (GConfValue *value);
END_GNOME_DECLS
diff --git a/libnautilus-extensions/nautilus-gdk-font-extensions.c b/libnautilus-extensions/nautilus-gdk-font-extensions.c
index c3e3a4784..43c60efe8 100644
--- a/libnautilus-extensions/nautilus-gdk-font-extensions.c
+++ b/libnautilus-extensions/nautilus-gdk-font-extensions.c
@@ -1062,16 +1062,6 @@ unref_fixed_font (void)
gdk_font_unref (fixed_font);
}
-
-/* FIXME bugzilla.eazel.com 7204:
- * Instead of picking fixed, we could create a temporary GtkStyle
- * and fetch the default font from there. That way we wash our
- * hands on the matter and let gtk be the one to pick the fallback
- * font. One tricky aspect of this strategy is where to put such
- * a call since this file contains on gdk_font stuff. Perhaps
- * nautilus-gtk-extensions.[ch] ?
- */
-
/**
* nautilus_gdk_font_get_fixed
*
diff --git a/libnautilus-extensions/nautilus-preferences.c b/libnautilus-extensions/nautilus-preferences.c
index a2aa70f77..3eea6df57 100644
--- a/libnautilus-extensions/nautilus-preferences.c
+++ b/libnautilus-extensions/nautilus-preferences.c
@@ -70,6 +70,7 @@ typedef struct {
GList *auto_storage_list;
int gconf_connection_id;
NautilusEnumeration *enumeration;
+ GConfValue *cached_value;
} PreferencesEntry;
/*
@@ -129,6 +130,7 @@ static void preferences_global_table_check_changes_function (gpointer
static GHashTable *preferences_global_table_get_global (void);
static void preferences_callback_entry_free (PreferencesCallbackEntry *callback_entry);
static int preferences_user_level_check_range (int user_level);
+static void preferences_entry_update_auto_storage (PreferencesEntry *entry);
static int user_level_changed_connection_id = -1;
static GHashTable *global_table = NULL;
@@ -747,10 +749,10 @@ nautilus_preferences_default_get_string_list (const char *name,
**/
static void
preferences_callback_entry_invoke_function (gpointer data,
- gpointer callback_data)
+ gpointer callback_data)
{
PreferencesCallbackEntry *callback_entry;
-
+
g_return_if_fail (data != NULL);
callback_entry = data;
@@ -758,6 +760,56 @@ preferences_callback_entry_invoke_function (gpointer data,
(* callback_entry->callback) (callback_entry->callback_data);
}
+/**
+ * preferences_entry_invoke_callbacks_if_needed
+ *
+ * @entry: A PreferencesEntry
+ *
+ * This function checks the cached value in the entry with the current
+ * value of the preference. If the value has changed, then callbacks
+ * are invoked and auto storage updated.
+ *
+ * We need this check because even though the GConf value of a preference
+ * could indeed have changed, its representation on the Nautilus side
+ * of things could still be the same. The best example of this is
+ * user level changes, where the value of the preference on the Nautilus
+ * end of things is determined by visibility.
+ **/
+static void
+preferences_entry_invoke_callbacks_if_needed (PreferencesEntry *entry)
+{
+ GConfValue *new_value;
+ char *getter_key;
+
+ g_return_if_fail (entry != NULL);
+
+ getter_key = preferences_key_make_for_getter (entry->name);
+ new_value = nautilus_gconf_get_value (getter_key);
+ g_free (getter_key);
+
+ /* If the values are the same, then we dont need to invoke any callbacks */
+ if (nautilus_gconf_value_is_equal (entry->cached_value, new_value)) {
+ nautilus_gconf_value_free (new_value);
+ return;
+ }
+
+ /* Update the auto storage preferences */
+ if (entry->auto_storage_list != NULL) {
+ preferences_entry_update_auto_storage (entry);
+ }
+
+ /* Store the new cached value */
+ nautilus_gconf_value_free (entry->cached_value);
+ entry->cached_value = new_value;
+
+ /* Invoke callbacks for this entry if any */
+ if (entry->callback_list != NULL) {
+ g_list_foreach (entry->callback_list,
+ preferences_callback_entry_invoke_function,
+ NULL);
+ }
+}
+
static void
update_auto_string (gpointer data, gpointer callback_data)
{
@@ -820,26 +872,11 @@ preferences_something_changed_notice (GConfClient *client,
GConfEntry *entry,
gpointer notice_data)
{
- PreferencesEntry *preferences_entry;
-
g_return_if_fail (entry != NULL);
g_return_if_fail (entry->key != NULL);
g_return_if_fail (notice_data != NULL);
-
- preferences_entry = notice_data;
- if (preferences_entry->auto_storage_list != NULL) {
- preferences_entry_update_auto_storage (preferences_entry);
- }
-
- /* FIXME bugzilla.eazel.com 5875:
- * We need to make sure that the value has actually changed before
- * invoking the callbacks.
- */
- /* Invoke callbacks for this entry */
- g_list_foreach (preferences_entry->callback_list,
- preferences_callback_entry_invoke_function,
- NULL);
+ preferences_entry_invoke_callbacks_if_needed (notice_data);
}
static void
@@ -861,22 +898,21 @@ preferences_global_table_check_changes_function (gpointer key,
return;
}
- /* FIXME: We need to make sure that the value changed before
- * invoking the callbacks.
- */
-#if 0
- int user_level;
- int visible_user_level;
- user_level = nautilus_preferences_get_user_level ();
- visible_user_level = nautilus_preferences_get_visible_user_level (entry->name);
-#endif
-
- /* Invoke callbacks for this entry */
- if (entry->callback_list) {
- g_list_foreach (entry->callback_list,
- preferences_callback_entry_invoke_function,
- NULL);
- }
+ preferences_entry_invoke_callbacks_if_needed (entry);
+}
+
+static void
+preferences_entry_update_cached_value (PreferencesEntry *entry)
+{
+ char *getter_key;
+
+ g_return_if_fail (entry != NULL);
+
+ nautilus_gconf_value_free (entry->cached_value);
+
+ getter_key = preferences_key_make_for_getter (entry->name);
+ entry->cached_value = nautilus_gconf_get_value (getter_key);
+ g_free (getter_key);
}
static void
@@ -920,16 +956,25 @@ preferences_entry_ensure_gconf_connection (PreferencesEntry *entry)
error = NULL;
entry->gconf_connection_id = gconf_client_notify_add (client,
- key,
- preferences_something_changed_notice,
- entry,
- NULL,
- &error);
+ key,
+ preferences_something_changed_notice,
+ entry,
+ NULL,
+ &error);
if (nautilus_gconf_handle_error (&error)) {
entry->gconf_connection_id = 0;
}
g_free (key);
+
+ /* Update the cached value.
+ * From now onwards the cached value will be updated
+ * each time preferences_something_changed_notice() triggers
+ * so that it can be later compared with new values to
+ * determine if the gconf value is different from the
+ * Nautilus value.
+ */
+ preferences_entry_update_cached_value (entry);
}
/**
@@ -1129,7 +1174,7 @@ preferences_callback_entry_free (PreferencesCallbackEntry *callback_entry)
**/
static void
preferences_callback_entry_free_func (gpointer data,
- gpointer callback_data)
+ gpointer callback_data)
{
g_return_if_fail (data != NULL);
@@ -1168,6 +1213,7 @@ preferences_entry_free (PreferencesEntry *entry)
g_free (entry->name);
g_free (entry->description);
+ nautilus_gconf_value_free (entry->cached_value);
nautilus_enumeration_free (entry->enumeration);
g_free (entry);
@@ -1240,6 +1286,18 @@ preferences_global_table_insert (const char *name)
g_return_val_if_fail (entry == preferences_global_table_lookup (name), NULL);
+ /* Update the cached value for the first time.
+ *
+ * We need to do this because checks for value changes
+ * happen not only as a result of callbacks triggering, but
+ * also as a result of user_level changes. When a user level
+ * changes, all the preferences entries are iterated to invoke
+ * callbacks for those that changed as a result.
+ *
+ * See preferences_global_table_check_changes_function().
+ */
+ preferences_entry_update_cached_value (entry);
+
return entry;
}
diff --git a/libnautilus-private/nautilus-gconf-extensions.c b/libnautilus-private/nautilus-gconf-extensions.c
index 15b92e229..65ec1845d 100644
--- a/libnautilus-private/nautilus-gconf-extensions.c
+++ b/libnautilus-private/nautilus-gconf-extensions.c
@@ -27,6 +27,8 @@
#include "nautilus-glib-extensions.h"
#include "nautilus-stock-dialogs.h"
+#include "nautilus-string.h"
+
#include <gconf/gconf-client.h>
#include <gconf/gconf.h>
#include <libgnome/gnome-i18n.h>
@@ -318,3 +320,81 @@ nautilus_gconf_suggest_sync (void)
gconf_client_suggest_sync (client, &error);
nautilus_gconf_handle_error (&error);
}
+
+GConfValue*
+nautilus_gconf_get_value (const char *key)
+{
+ GConfValue *value = NULL;
+ GConfClient *client;
+ GError *error = NULL;
+
+ g_return_val_if_fail (key != NULL, NULL);
+
+ client = nautilus_gconf_client_get_global ();
+ g_return_val_if_fail (client != NULL, NULL);
+
+ value = gconf_client_get (client, key, &error);
+
+ if (nautilus_gconf_handle_error (&error)) {
+ if (value != NULL) {
+ gconf_value_free (value);
+ value = NULL;
+ }
+ }
+
+ return value;
+}
+
+gboolean
+nautilus_gconf_value_is_equal (const GConfValue *a,
+ const GConfValue *b)
+{
+ if (a == NULL && b == NULL) {
+ return TRUE;
+ }
+
+ if (a == NULL || b == NULL) {
+ return FALSE;
+ }
+
+ if (a->type != b->type) {
+ return FALSE;
+ }
+
+ switch (a->type) {
+ case GCONF_VALUE_STRING:
+ return nautilus_str_is_equal (a->d.string_data, b->d.string_data);
+ break;
+
+ case GCONF_VALUE_INT:
+ return a->d.int_data == b->d.int_data;
+ break;
+
+ case GCONF_VALUE_FLOAT:
+ return a->d.float_data == b->d.float_data;
+ break;
+
+ case GCONF_VALUE_BOOL:
+ return a->d.bool_data == b->d.bool_data;
+ break;
+
+ case GCONF_VALUE_LIST:
+ /* FIXME */
+ g_assert (0);
+ return FALSE;
+ default:
+ }
+
+ g_assert_not_reached ();
+ return FALSE;
+}
+
+void
+nautilus_gconf_value_free (GConfValue *value)
+{
+ if (value == NULL) {
+ return;
+ }
+
+ gconf_value_free (value);
+}
diff --git a/libnautilus-private/nautilus-gconf-extensions.h b/libnautilus-private/nautilus-gconf-extensions.h
index a9393feb4..7c566b8e3 100644
--- a/libnautilus-private/nautilus-gconf-extensions.h
+++ b/libnautilus-private/nautilus-gconf-extensions.h
@@ -31,23 +31,27 @@
BEGIN_GNOME_DECLS
-GConfClient *nautilus_gconf_client_get_global (void);
-gboolean nautilus_gconf_handle_error (GError **error);
-void nautilus_gconf_set_boolean (const char *key,
- gboolean boolean_value);
-gboolean nautilus_gconf_get_boolean (const char *key);
-int nautilus_gconf_get_integer (const char *key);
-void nautilus_gconf_set_integer (const char *key,
- int int_value);
-char * nautilus_gconf_get_string (const char *key);
-void nautilus_gconf_set_string (const char *key,
- const char *string_value);
-GList * nautilus_gconf_get_string_list (const char *key);
-void nautilus_gconf_set_string_list (const char *key,
- GList *string_list_value);
-gboolean nautilus_gconf_is_default (const char *key);
-gboolean nautilus_gconf_monitor_directory (const char *directory);
-void nautilus_gconf_suggest_sync (void);
+GConfClient *nautilus_gconf_client_get_global (void);
+gboolean nautilus_gconf_handle_error (GError **error);
+void nautilus_gconf_set_boolean (const char *key,
+ gboolean boolean_value);
+gboolean nautilus_gconf_get_boolean (const char *key);
+int nautilus_gconf_get_integer (const char *key);
+void nautilus_gconf_set_integer (const char *key,
+ int int_value);
+char * nautilus_gconf_get_string (const char *key);
+void nautilus_gconf_set_string (const char *key,
+ const char *string_value);
+GList * nautilus_gconf_get_string_list (const char *key);
+void nautilus_gconf_set_string_list (const char *key,
+ GList *string_list_value);
+gboolean nautilus_gconf_is_default (const char *key);
+gboolean nautilus_gconf_monitor_directory (const char *directory);
+void nautilus_gconf_suggest_sync (void);
+GConfValue* nautilus_gconf_get_value (const char *key);
+gboolean nautilus_gconf_value_is_equal (const GConfValue *a,
+ const GConfValue *b);
+void nautilus_gconf_value_free (GConfValue *value);
END_GNOME_DECLS
diff --git a/libnautilus-private/nautilus-gdk-font-extensions.c b/libnautilus-private/nautilus-gdk-font-extensions.c
index c3e3a4784..43c60efe8 100644
--- a/libnautilus-private/nautilus-gdk-font-extensions.c
+++ b/libnautilus-private/nautilus-gdk-font-extensions.c
@@ -1062,16 +1062,6 @@ unref_fixed_font (void)
gdk_font_unref (fixed_font);
}
-
-/* FIXME bugzilla.eazel.com 7204:
- * Instead of picking fixed, we could create a temporary GtkStyle
- * and fetch the default font from there. That way we wash our
- * hands on the matter and let gtk be the one to pick the fallback
- * font. One tricky aspect of this strategy is where to put such
- * a call since this file contains on gdk_font stuff. Perhaps
- * nautilus-gtk-extensions.[ch] ?
- */
-
/**
* nautilus_gdk_font_get_fixed
*
diff --git a/libnautilus-private/nautilus-preferences.c b/libnautilus-private/nautilus-preferences.c
index a2aa70f77..3eea6df57 100644
--- a/libnautilus-private/nautilus-preferences.c
+++ b/libnautilus-private/nautilus-preferences.c
@@ -70,6 +70,7 @@ typedef struct {
GList *auto_storage_list;
int gconf_connection_id;
NautilusEnumeration *enumeration;
+ GConfValue *cached_value;
} PreferencesEntry;
/*
@@ -129,6 +130,7 @@ static void preferences_global_table_check_changes_function (gpointer
static GHashTable *preferences_global_table_get_global (void);
static void preferences_callback_entry_free (PreferencesCallbackEntry *callback_entry);
static int preferences_user_level_check_range (int user_level);
+static void preferences_entry_update_auto_storage (PreferencesEntry *entry);
static int user_level_changed_connection_id = -1;
static GHashTable *global_table = NULL;
@@ -747,10 +749,10 @@ nautilus_preferences_default_get_string_list (const char *name,
**/
static void
preferences_callback_entry_invoke_function (gpointer data,
- gpointer callback_data)
+ gpointer callback_data)
{
PreferencesCallbackEntry *callback_entry;
-
+
g_return_if_fail (data != NULL);
callback_entry = data;
@@ -758,6 +760,56 @@ preferences_callback_entry_invoke_function (gpointer data,
(* callback_entry->callback) (callback_entry->callback_data);
}
+/**
+ * preferences_entry_invoke_callbacks_if_needed
+ *
+ * @entry: A PreferencesEntry
+ *
+ * This function checks the cached value in the entry with the current
+ * value of the preference. If the value has changed, then callbacks
+ * are invoked and auto storage updated.
+ *
+ * We need this check because even though the GConf value of a preference
+ * could indeed have changed, its representation on the Nautilus side
+ * of things could still be the same. The best example of this is
+ * user level changes, where the value of the preference on the Nautilus
+ * end of things is determined by visibility.
+ **/
+static void
+preferences_entry_invoke_callbacks_if_needed (PreferencesEntry *entry)
+{
+ GConfValue *new_value;
+ char *getter_key;
+
+ g_return_if_fail (entry != NULL);
+
+ getter_key = preferences_key_make_for_getter (entry->name);
+ new_value = nautilus_gconf_get_value (getter_key);
+ g_free (getter_key);
+
+ /* If the values are the same, then we dont need to invoke any callbacks */
+ if (nautilus_gconf_value_is_equal (entry->cached_value, new_value)) {
+ nautilus_gconf_value_free (new_value);
+ return;
+ }
+
+ /* Update the auto storage preferences */
+ if (entry->auto_storage_list != NULL) {
+ preferences_entry_update_auto_storage (entry);
+ }
+
+ /* Store the new cached value */
+ nautilus_gconf_value_free (entry->cached_value);
+ entry->cached_value = new_value;
+
+ /* Invoke callbacks for this entry if any */
+ if (entry->callback_list != NULL) {
+ g_list_foreach (entry->callback_list,
+ preferences_callback_entry_invoke_function,
+ NULL);
+ }
+}
+
static void
update_auto_string (gpointer data, gpointer callback_data)
{
@@ -820,26 +872,11 @@ preferences_something_changed_notice (GConfClient *client,
GConfEntry *entry,
gpointer notice_data)
{
- PreferencesEntry *preferences_entry;
-
g_return_if_fail (entry != NULL);
g_return_if_fail (entry->key != NULL);
g_return_if_fail (notice_data != NULL);
-
- preferences_entry = notice_data;
- if (preferences_entry->auto_storage_list != NULL) {
- preferences_entry_update_auto_storage (preferences_entry);
- }
-
- /* FIXME bugzilla.eazel.com 5875:
- * We need to make sure that the value has actually changed before
- * invoking the callbacks.
- */
- /* Invoke callbacks for this entry */
- g_list_foreach (preferences_entry->callback_list,
- preferences_callback_entry_invoke_function,
- NULL);
+ preferences_entry_invoke_callbacks_if_needed (notice_data);
}
static void
@@ -861,22 +898,21 @@ preferences_global_table_check_changes_function (gpointer key,
return;
}
- /* FIXME: We need to make sure that the value changed before
- * invoking the callbacks.
- */
-#if 0
- int user_level;
- int visible_user_level;
- user_level = nautilus_preferences_get_user_level ();
- visible_user_level = nautilus_preferences_get_visible_user_level (entry->name);
-#endif
-
- /* Invoke callbacks for this entry */
- if (entry->callback_list) {
- g_list_foreach (entry->callback_list,
- preferences_callback_entry_invoke_function,
- NULL);
- }
+ preferences_entry_invoke_callbacks_if_needed (entry);
+}
+
+static void
+preferences_entry_update_cached_value (PreferencesEntry *entry)
+{
+ char *getter_key;
+
+ g_return_if_fail (entry != NULL);
+
+ nautilus_gconf_value_free (entry->cached_value);
+
+ getter_key = preferences_key_make_for_getter (entry->name);
+ entry->cached_value = nautilus_gconf_get_value (getter_key);
+ g_free (getter_key);
}
static void
@@ -920,16 +956,25 @@ preferences_entry_ensure_gconf_connection (PreferencesEntry *entry)
error = NULL;
entry->gconf_connection_id = gconf_client_notify_add (client,
- key,
- preferences_something_changed_notice,
- entry,
- NULL,
- &error);
+ key,
+ preferences_something_changed_notice,
+ entry,
+ NULL,
+ &error);
if (nautilus_gconf_handle_error (&error)) {
entry->gconf_connection_id = 0;
}
g_free (key);
+
+ /* Update the cached value.
+ * From now onwards the cached value will be updated
+ * each time preferences_something_changed_notice() triggers
+ * so that it can be later compared with new values to
+ * determine if the gconf value is different from the
+ * Nautilus value.
+ */
+ preferences_entry_update_cached_value (entry);
}
/**
@@ -1129,7 +1174,7 @@ preferences_callback_entry_free (PreferencesCallbackEntry *callback_entry)
**/
static void
preferences_callback_entry_free_func (gpointer data,
- gpointer callback_data)
+ gpointer callback_data)
{
g_return_if_fail (data != NULL);
@@ -1168,6 +1213,7 @@ preferences_entry_free (PreferencesEntry *entry)
g_free (entry->name);
g_free (entry->description);
+ nautilus_gconf_value_free (entry->cached_value);
nautilus_enumeration_free (entry->enumeration);
g_free (entry);
@@ -1240,6 +1286,18 @@ preferences_global_table_insert (const char *name)
g_return_val_if_fail (entry == preferences_global_table_lookup (name), NULL);
+ /* Update the cached value for the first time.
+ *
+ * We need to do this because checks for value changes
+ * happen not only as a result of callbacks triggering, but
+ * also as a result of user_level changes. When a user level
+ * changes, all the preferences entries are iterated to invoke
+ * callbacks for those that changed as a result.
+ *
+ * See preferences_global_table_check_changes_function().
+ */
+ preferences_entry_update_cached_value (entry);
+
return entry;
}