diff options
author | John Sullivan <sullivan@src.gnome.org> | 2001-03-30 20:52:36 +0000 |
---|---|---|
committer | John Sullivan <sullivan@src.gnome.org> | 2001-03-30 20:52:36 +0000 |
commit | 3f3dd3bf8515a7ac72a9d318363f362a27763555 (patch) | |
tree | bcab9213698ed7750e93bf8fb84e4346fe35721d | |
parent | 31128bf3bc63dac98da65f76cb7867342bdde00a (diff) | |
download | nautilus-3f3dd3bf8515a7ac72a9d318363f362a27763555.tar.gz |
reviewed by: Darin Adler <darin@eazel.com>
Fixed bug 7913 (fm_get_text_attribute_names_preference
should cache preference value for speed)
Fixed bug 7914 (nautilus_icon_canvas_item_initialize
should cache smooth_font for speed)
Added a new way to stay up-to-date with the value of a
preference: you register a (typically global) variable
with a particular preference, and the preferences machinery
updates its value automatically whenever the preference
changes. This is a replacement for using
nautilus_preferences_get (and _get_integer and _get_boolean)
repeatedly, and is much more efficient. We might eventually
replace all the callers of _get_xxx with calls to this, and
remove those calls entirely.
I deployed this in the two specific cases Pavel found with
profiling (bugs 7913 & 7914) and some more places. I'll
deploy it in more places still later.
* libnautilus-extensions/nautilus-preferences.h:
* libnautilus-extensions/nautilus-preferences.c:
(update_auto_string), (update_auto_integer_or_boolean):
New helper functions to update an individual auto-storage variable.
(preferences_entry_update_auto_storage): New function, updates
all auto-storage variables for a particular preference.
(preferences_something_changed_notice): update auto-storage variables
before calling callbacks.
(preferences_entry_ensure_gconf_connection): New function, extracted
from preferences_entry_add_callback.
(preferences_entry_add_callback): Now calls extracted function.
(preferences_entry_add_auto_storage): New function, adds a single
auto-storage variable for a given preference.
(preferences_entry_check_remove_connection): New function, extracted
from preferences_entry_remove_callback.
(preferences_entry_remove_callback): Now calls extracted function.
(preferences_entry_remove_auto_storage): New function, removes a single
auto-storage variable for a given preference.
(preferences_entry_free): Free the auto-storage list.
(nautilus_preferences_add_auto_string),
(nautilus_preferences_add_auto_integer),
(nautilus_preferences_add_auto_boolean),
(nautilus_preferences_remove_auto_string),
(nautilus_preferences_remove_auto_integer),
(nautilus_preferences_remove_auto_boolean): Public cover functions
for the three basic types of auto-storage variables.
(nautilus_preferences_remove_callback): Fixed small bug where this
function would unnecessarily add an entry before removing it.
* libnautilus-extensions/nautilus-font-factory.c:
(nautilus_font_factory_get_font_from_preferences):
Reworked to use auto-storage variable.
* libnautilus-extensions/nautilus-global-preferences.c:
(nautilus_global_preferences_initialize): Set up auto-storage
variables for icon view & default smooth font preferences.
(global_preferences_get_smooth_font),
(global_preferences_get_smooth_bold_font): Changed to take
font file name instead of preferences name.
(nautilus_global_preferences_get_icon_view_smooth_font),
(nautilus_global_preferences_get_default_smooth_font),
(nautilus_global_preferences_get_default_smooth_bold_font):
Use auto-storage variables.
* libnautilus-extensions/nautilus-icon-canvas-item.c:
(nautilus_icon_canvas_item_initialize_class): Set up
auto-storage variable for click policy preference.
(in_single_click_mode): Use auto-storage variable.
* libnautilus-extensions/nautilus-icon-factory.c:
(should_display_image_file_as_itself): Use auto-storage
variable for thumbnail policy.
* src/file-manager/fm-icon-text-window.c:
(fm_get_text_attribute_names_preference): Use auto-storage
variable for icon captions.
* src/file-manager/fm-icon-view.c:
(should_preview_sound): Use auto-storage variable for
sound-preview preference.
(fm_icon_view_initialize_class): Set up auto-storage variable
for sound-preview preference.
-rw-r--r-- | ChangeLog | 87 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-font-factory.c | 20 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-global-preferences.c | 30 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-icon-canvas-item.c | 8 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-icon-factory.c | 19 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-preferences.c | 379 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-preferences.h | 14 | ||||
-rw-r--r-- | libnautilus-private/nautilus-font-factory.c | 20 | ||||
-rw-r--r-- | libnautilus-private/nautilus-global-preferences.c | 30 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-canvas-item.c | 8 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-factory.c | 19 | ||||
-rw-r--r-- | libnautilus-private/nautilus-preferences.c | 379 | ||||
-rw-r--r-- | libnautilus-private/nautilus-preferences.h | 14 | ||||
-rw-r--r-- | src/file-manager/fm-icon-text-window.c | 50 | ||||
-rw-r--r-- | src/file-manager/fm-icon-view.c | 11 |
15 files changed, 904 insertions, 184 deletions
@@ -1,3 +1,90 @@ +2001-03-30 John Sullivan <sullivan@eazel.com> + + reviewed by: Darin Adler <darin@eazel.com> + + Fixed bug 7913 (fm_get_text_attribute_names_preference + should cache preference value for speed) + + Fixed bug 7914 (nautilus_icon_canvas_item_initialize + should cache smooth_font for speed) + + Added a new way to stay up-to-date with the value of a + preference: you register a (typically global) variable + with a particular preference, and the preferences machinery + updates its value automatically whenever the preference + changes. This is a replacement for using + nautilus_preferences_get (and _get_integer and _get_boolean) + repeatedly, and is much more efficient. We might eventually + replace all the callers of _get_xxx with calls to this, and + remove those calls entirely. + + I deployed this in the two specific cases Pavel found with + profiling (bugs 7913 & 7914) and some more places. I'll + deploy it in more places still later. + + * libnautilus-extensions/nautilus-preferences.h: + * libnautilus-extensions/nautilus-preferences.c: + (update_auto_string), (update_auto_integer_or_boolean): + New helper functions to update an individual auto-storage variable. + (preferences_entry_update_auto_storage): New function, updates + all auto-storage variables for a particular preference. + (preferences_something_changed_notice): update auto-storage variables + before calling callbacks. + (preferences_entry_ensure_gconf_connection): New function, extracted + from preferences_entry_add_callback. + (preferences_entry_add_callback): Now calls extracted function. + (preferences_entry_add_auto_storage): New function, adds a single + auto-storage variable for a given preference. + (preferences_entry_check_remove_connection): New function, extracted + from preferences_entry_remove_callback. + (preferences_entry_remove_callback): Now calls extracted function. + (preferences_entry_remove_auto_storage): New function, removes a single + auto-storage variable for a given preference. + (preferences_entry_free): Free the auto-storage list. + (nautilus_preferences_add_auto_string), + (nautilus_preferences_add_auto_integer), + (nautilus_preferences_add_auto_boolean), + (nautilus_preferences_remove_auto_string), + (nautilus_preferences_remove_auto_integer), + (nautilus_preferences_remove_auto_boolean): Public cover functions + for the three basic types of auto-storage variables. + (nautilus_preferences_remove_callback): Fixed small bug where this + function would unnecessarily add an entry before removing it. + + * libnautilus-extensions/nautilus-font-factory.c: + (nautilus_font_factory_get_font_from_preferences): + Reworked to use auto-storage variable. + + * libnautilus-extensions/nautilus-global-preferences.c: + (nautilus_global_preferences_initialize): Set up auto-storage + variables for icon view & default smooth font preferences. + (global_preferences_get_smooth_font), + (global_preferences_get_smooth_bold_font): Changed to take + font file name instead of preferences name. + (nautilus_global_preferences_get_icon_view_smooth_font), + (nautilus_global_preferences_get_default_smooth_font), + (nautilus_global_preferences_get_default_smooth_bold_font): + Use auto-storage variables. + + * libnautilus-extensions/nautilus-icon-canvas-item.c: + (nautilus_icon_canvas_item_initialize_class): Set up + auto-storage variable for click policy preference. + (in_single_click_mode): Use auto-storage variable. + + * libnautilus-extensions/nautilus-icon-factory.c: + (should_display_image_file_as_itself): Use auto-storage + variable for thumbnail policy. + + * src/file-manager/fm-icon-text-window.c: + (fm_get_text_attribute_names_preference): Use auto-storage + variable for icon captions. + + * src/file-manager/fm-icon-view.c: + (should_preview_sound): Use auto-storage variable for + sound-preview preference. + (fm_icon_view_initialize_class): Set up auto-storage variable + for sound-preview preference. + 2001-03-29 Darin Adler <darin@eazel.com> reviewed by: Pavel Cisler <pavel@eazel.com> diff --git a/libnautilus-extensions/nautilus-font-factory.c b/libnautilus-extensions/nautilus-font-factory.c index c6c894cef..09abdb6e6 100644 --- a/libnautilus-extensions/nautilus-font-factory.c +++ b/libnautilus-extensions/nautilus-font-factory.c @@ -273,12 +273,20 @@ nautilus_font_factory_get_font_by_family (const char *family, GdkFont * nautilus_font_factory_get_font_from_preferences (guint size_in_pixels) { - char *family; - GdkFont *font; + static gboolean icon_view_font_auto_value_registered; + static const char *icon_view_font_auto_value; - family = nautilus_preferences_get (NAUTILUS_PREFERENCES_ICON_VIEW_FONT); - font = nautilus_font_factory_get_font_by_family (family, size_in_pixels); - g_free (family); + /* Can't initialize this in initialize_class, because no font factory + * instance may yet exist when this is called. + */ + if (!icon_view_font_auto_value_registered) { + nautilus_preferences_add_auto_string (NAUTILUS_PREFERENCES_ICON_VIEW_FONT, + &icon_view_font_auto_value); + icon_view_font_auto_value_registered = TRUE; + } - return font; + /* FIXME: We hardwire icon view font here, but some callers probably + * expect default font instead. + */ + return nautilus_font_factory_get_font_by_family (icon_view_font_auto_value, size_in_pixels); } diff --git a/libnautilus-extensions/nautilus-global-preferences.c b/libnautilus-extensions/nautilus-global-preferences.c index a1d69d4ab..b205a19f9 100644 --- a/libnautilus-extensions/nautilus-global-preferences.c +++ b/libnautilus-extensions/nautilus-global-preferences.c @@ -81,6 +81,8 @@ static GtkWidget *global_preferences_populate_pane (Nautilu const PreferenceDialogItem *preference_dialog_item); static GtkWidget *global_prefs_dialog = NULL; +static const char *default_smooth_font_auto_value; +static const char *icon_view_smooth_font_auto_value; /* An enumeration used for installing type specific preferences defaults. */ typedef enum @@ -1563,33 +1565,25 @@ nautilus_global_preferences_set_dialog_title (const char *title) } static NautilusScalableFont * -global_preferences_get_smooth_font (const char *preference_name) +global_preferences_get_smooth_font (const char *smooth_font_file_name) { NautilusScalableFont *smooth_font; - char *smooth_font_file_name; - g_return_val_if_fail (preference_name != NULL, NULL); - - smooth_font_file_name = nautilus_preferences_get (preference_name); - - smooth_font = (smooth_font_file_name && g_file_exists (smooth_font_file_name)) ? + smooth_font = (smooth_font_file_name != NULL && g_file_exists (smooth_font_file_name)) ? nautilus_scalable_font_new (smooth_font_file_name) : nautilus_scalable_font_get_default_font (); - g_free (smooth_font_file_name); g_assert (NAUTILUS_IS_SCALABLE_FONT (smooth_font)); return smooth_font; } static NautilusScalableFont * -global_preferences_get_smooth_bold_font (const char *preference_name) +global_preferences_get_smooth_bold_font (const char *file_name) { NautilusScalableFont *plain_font; NautilusScalableFont *bold_font; - g_return_val_if_fail (preference_name != NULL, NULL); - - plain_font = global_preferences_get_smooth_font (preference_name); + plain_font = global_preferences_get_smooth_font (file_name); g_assert (NAUTILUS_IS_SCALABLE_FONT (plain_font)); bold_font = nautilus_scalable_font_make_bold (plain_font); @@ -1613,7 +1607,7 @@ global_preferences_get_smooth_bold_font (const char *preference_name) NautilusScalableFont * nautilus_global_preferences_get_icon_view_smooth_font (void) { - return global_preferences_get_smooth_font (NAUTILUS_PREFERENCES_ICON_VIEW_SMOOTH_FONT); + return global_preferences_get_smooth_font (icon_view_smooth_font_auto_value); } /** @@ -1625,7 +1619,7 @@ nautilus_global_preferences_get_icon_view_smooth_font (void) NautilusScalableFont * nautilus_global_preferences_get_default_smooth_font (void) { - return global_preferences_get_smooth_font (NAUTILUS_PREFERENCES_DEFAULT_SMOOTH_FONT); + return global_preferences_get_smooth_font (default_smooth_font_auto_value); } /** @@ -1639,7 +1633,7 @@ nautilus_global_preferences_get_default_smooth_font (void) NautilusScalableFont * nautilus_global_preferences_get_default_smooth_bold_font (void) { - return global_preferences_get_smooth_bold_font (NAUTILUS_PREFERENCES_DEFAULT_SMOOTH_FONT); + return global_preferences_get_smooth_bold_font (default_smooth_font_auto_value); } void @@ -1655,4 +1649,10 @@ nautilus_global_preferences_initialize (void) /* Install defaults */ global_preferences_install_defaults (); + + /* Set up storage for values accessed in this file */ + nautilus_preferences_add_auto_string (NAUTILUS_PREFERENCES_ICON_VIEW_SMOOTH_FONT, + &icon_view_smooth_font_auto_value); + nautilus_preferences_add_auto_string (NAUTILUS_PREFERENCES_DEFAULT_SMOOTH_FONT, + &default_smooth_font_auto_value); } diff --git a/libnautilus-extensions/nautilus-icon-canvas-item.c b/libnautilus-extensions/nautilus-icon-canvas-item.c index 4d3606f15..01a83eb7b 100644 --- a/libnautilus-extensions/nautilus-icon-canvas-item.c +++ b/libnautilus-extensions/nautilus-icon-canvas-item.c @@ -147,6 +147,8 @@ static guint32 highlight_background_color = NAUTILUS_RGBA_COLOR_PACK (0x00, 0x00 static guint32 highlight_text_color = NAUTILUS_RGBA_COLOR_PACK (0xFF, 0xFF, 0xFF, 0xFF); static guint32 highlight_text_info_color = NAUTILUS_RGBA_COLOR_PACK (0xCC, 0xCC, 0xCC, 0xFF); +static int click_policy_auto_value; + /* GtkObject */ static void nautilus_icon_canvas_item_initialize_class (NautilusIconCanvasItemClass *class); static void nautilus_icon_canvas_item_initialize (NautilusIconCanvasItem *item); @@ -284,6 +286,9 @@ nautilus_icon_canvas_item_initialize_class (NautilusIconCanvasItemClass *class) item_class->point = nautilus_icon_canvas_item_point; item_class->bounds = nautilus_icon_canvas_item_bounds; item_class->event = nautilus_icon_canvas_item_event; + + nautilus_preferences_add_auto_integer (NAUTILUS_PREFERENCES_CLICK_POLICY, + &click_policy_auto_value); } /* Object initialization function for the icon item. */ @@ -719,8 +724,7 @@ gnome_icon_underline_text (GnomeIconTextInfo *text_info, static gboolean in_single_click_mode () { - /* Perhaps this should be computed elsewhere and passed in. */ - return nautilus_preferences_get_integer (NAUTILUS_PREFERENCES_CLICK_POLICY) == NAUTILUS_CLICK_POLICY_SINGLE; + return click_policy_auto_value == NAUTILUS_CLICK_POLICY_SINGLE; } /* Keep these for a bit while we work on performance of draw_or_measure_label_text. */ diff --git a/libnautilus-extensions/nautilus-icon-factory.c b/libnautilus-extensions/nautilus-icon-factory.c index 4bb3cd2ca..009ec9f51 100644 --- a/libnautilus-extensions/nautilus-icon-factory.c +++ b/libnautilus-extensions/nautilus-icon-factory.c @@ -1333,15 +1333,18 @@ nautilus_scalable_icon_equal (gconstpointer a, && icon_a->aa_mode == icon_b->aa_mode; } - static gboolean should_display_image_file_as_itself (NautilusFile *file, gboolean anti_aliased) { - NautilusSpeedTradeoffValue preference_value; - - preference_value = nautilus_preferences_get_integer - (NAUTILUS_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS); + static int show_thumbnails_auto_value; + static gboolean show_thumbnail_auto_value_registered; + if (!show_thumbnail_auto_value_registered) { + nautilus_preferences_add_auto_integer (NAUTILUS_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS, + &show_thumbnails_auto_value); + show_thumbnail_auto_value_registered = TRUE; + } + /* see if there's a proxy thumbnail to indicate that thumbnailing * failed, in which case we shouldn't use the thumbnail. */ @@ -1354,15 +1357,15 @@ should_display_image_file_as_itself (NautilusFile *file, gboolean anti_aliased) return FALSE; } - if (preference_value == NAUTILUS_SPEED_TRADEOFF_ALWAYS) { + if (show_thumbnails_auto_value == NAUTILUS_SPEED_TRADEOFF_ALWAYS) { return TRUE; } - if (preference_value == NAUTILUS_SPEED_TRADEOFF_NEVER) { + if (show_thumbnails_auto_value == NAUTILUS_SPEED_TRADEOFF_NEVER) { return FALSE; } - g_assert (preference_value == NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY); + g_assert (show_thumbnails_auto_value == NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY); return nautilus_file_is_local (file); } diff --git a/libnautilus-extensions/nautilus-preferences.c b/libnautilus-extensions/nautilus-preferences.c index f800cad33..b20d29cf8 100644 --- a/libnautilus-extensions/nautilus-preferences.c +++ b/libnautilus-extensions/nautilus-preferences.c @@ -44,6 +44,17 @@ #define DEFAULT_USER_LEVEL NAUTILUS_USER_LEVEL_INTERMEDIATE +/* An enumeration used for updating auto-storage variables in a type-specific way. + * FIXME: there is another enumeration like this in nautilus-global-preferences.c, + * used for different purposes but in a related way. Should we combine them? + */ +typedef enum +{ + PREFERENCE_BOOLEAN = 1, + PREFERENCE_INTEGER, + PREFERENCE_STRING +} PreferenceType; + /* * PreferencesEntry: * @@ -54,7 +65,9 @@ typedef struct { char *name; char *description; + PreferenceType type; GList *callback_list; + GList *auto_storage_list; int gconf_connection_id; NautilusEnumeration *enumeration; } PreferencesEntry; @@ -509,7 +522,7 @@ nautilus_preferences_get (const char *name) { char *result; char *key; - + g_return_val_if_fail (name != NULL, NULL); key = preferences_key_make_for_getter (name); @@ -746,6 +759,63 @@ preferences_callback_entry_invoke_function (gpointer data, } static void +update_auto_string (gpointer data, gpointer callback_data) +{ + char **storage; + const char *value; + + g_return_if_fail (data != NULL); + g_return_if_fail (callback_data != NULL); + + storage = (char **)data; + value = (const char *)callback_data; + + g_free (*storage); + *(char **)storage = g_strdup (value); +} + +static void +update_auto_integer_or_boolean (gpointer data, gpointer callback_data) +{ + g_return_if_fail (data != NULL); + g_return_if_fail (callback_data != NULL); + + *(int *)data = GPOINTER_TO_INT (callback_data); +} + +static void +preferences_entry_update_auto_storage (PreferencesEntry *entry) +{ + char *new_string_value; + int new_int_value; + gboolean new_boolean_value; + + switch (entry->type) { + case PREFERENCE_STRING: + new_string_value = nautilus_preferences_get (entry->name); + g_list_foreach (entry->auto_storage_list, + update_auto_string, + new_string_value); + g_free (new_string_value); + break; + case PREFERENCE_INTEGER: + new_int_value = nautilus_preferences_get_integer (entry->name); + g_list_foreach (entry->auto_storage_list, + update_auto_integer_or_boolean, + GINT_TO_POINTER (new_int_value)); + break; + case PREFERENCE_BOOLEAN: + new_boolean_value = nautilus_preferences_get_boolean (entry->name); + g_list_foreach (entry->auto_storage_list, + update_auto_integer_or_boolean, + GINT_TO_POINTER (new_boolean_value)); + break; + default: + g_warning ("unexpected preferences type %d in preferences_entry_update_auto_storage", entry->type); + } +} + +static void preferences_something_changed_notice (GConfClient *client, guint connection_id, GConfEntry *entry, @@ -758,17 +828,19 @@ preferences_something_changed_notice (GConfClient *client, 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 */ - if (preferences_entry->callback_list) { - g_list_foreach (preferences_entry->callback_list, - preferences_callback_entry_invoke_function, - NULL); - } + g_list_foreach (preferences_entry->callback_list, + preferences_callback_entry_invoke_function, + NULL); } static void @@ -823,14 +895,52 @@ preferences_user_level_changed_notice (GConfClient *client, NULL); } +static void +preferences_entry_ensure_gconf_connection (PreferencesEntry *entry) +{ + GError *error; + GConfClient *client; + char *key; + + /* + * We install only one gconf notification for each preference entry. + * Otherwise, we would invoke the installed callbacks more than once + * per registered callback. + */ + if (entry->gconf_connection_id != 0) { + return; + } + + g_return_if_fail (entry->name != NULL); + + client = preferences_global_client_get (); + + g_return_if_fail (client != NULL); + + key = preferences_key_make (entry->name); + + error = NULL; + entry->gconf_connection_id = gconf_client_notify_add (client, + key, + preferences_something_changed_notice, + entry, + NULL, + &error); + if (nautilus_gconf_handle_error (&error)) { + entry->gconf_connection_id = 0; + } + + g_free (key); +} + /** * preferences_entry_add_callback * * Add a callback to a pref node. Callbacks are fired whenever * the pref value changes. * @preferences_entry: The hash node. - * @callback: The user supplied callback. - * @callback_data: The user supplied closure. + * @callback: The user-supplied callback. + * @callback_data: The user-supplied closure. **/ static void preferences_entry_add_callback (PreferencesEntry *entry, @@ -850,36 +960,56 @@ preferences_entry_add_callback (PreferencesEntry *entry, entry->callback_list = g_list_append (entry->callback_list, callback_entry); - /* - * We install only one gconf notification for each preference entry. - * Otherwise, we would invoke the installed callbacks more than once - * per registered callback. - */ - if (entry->gconf_connection_id == 0) { - GError *error = NULL; - GConfClient *client; - char *key; - - g_return_if_fail (entry->name != NULL); + preferences_entry_ensure_gconf_connection (entry); +} - client = preferences_global_client_get (); +/** + * preferences_entry_add_auto_storage + * + * Add an auto-storage variable to a pref node. The variable will + * be updated to match the pref value whenever the pref + * the pref value changes. + * @preferences_entry: The hash node. + * @storage: The user-supplied location at which to store the value. + * @type: Which type of variable this is. + **/ +static void +preferences_entry_add_auto_storage (PreferencesEntry *entry, + gpointer storage, + PreferenceType type) +{ + g_return_if_fail (entry != NULL); + g_return_if_fail (storage != NULL); + g_return_if_fail (entry->type == 0 || entry->type == type); + g_return_if_fail (g_list_find (entry->auto_storage_list, storage) == NULL); - g_return_if_fail (client != NULL); + entry->type = type; + + entry->auto_storage_list = g_list_append (entry->auto_storage_list, storage); - key = preferences_key_make (entry->name); + preferences_entry_ensure_gconf_connection (entry); +} - entry->gconf_connection_id = gconf_client_notify_add (client, - key, - preferences_something_changed_notice, - entry, - NULL, - &error); - if (nautilus_gconf_handle_error (&error)) { - entry->gconf_connection_id = 0; - } +static void +preferences_entry_check_remove_connection (PreferencesEntry *entry) +{ + GConfClient *client; + + /* + * If there are no callbacks or auto-storage variables left in the entry, + * remove the gconf notification. + */ + if (entry->callback_list != NULL || entry->auto_storage_list != NULL) { + return; + } - g_free (key); + client = preferences_global_client_get (); + + if (entry->gconf_connection_id != 0) { + gconf_client_notify_remove (client, entry->gconf_connection_id); } + + entry->gconf_connection_id = 0; } /** @@ -888,8 +1018,8 @@ preferences_entry_add_callback (PreferencesEntry *entry, * remove a callback from a pref entry. Both the callback and the callback_data must * match in order for a callback to be removed from the entry. * @preferences_entry: The hash entry. - * @callback: The user supplied callback. - * @callback_data: The user supplied closure. + * @callback: The user-supplied callback. + * @callback_data: The user-supplied closure. **/ static void preferences_entry_remove_callback (PreferencesEntry *entry, @@ -920,22 +1050,57 @@ preferences_entry_remove_callback (PreferencesEntry *entry, } g_list_free (new_list); - - /* - * If there are no callbacks left in the entry, remove the gconf - * notification as well. - */ - if (entry->callback_list == NULL) { - GConfClient *client; - client = preferences_global_client_get (); + preferences_entry_check_remove_connection (entry); +} + +/** + * preferences_entry_remove_auto_storage + * + * remove an auto-storage variable from a pref entry. + * @preferences_entry: The hash entry. + * @storage: The user-supplied location. + **/ +static void +preferences_entry_remove_auto_storage (PreferencesEntry *entry, + gpointer storage) +{ + GList *new_list; + GList *iterator; + gpointer storage_in_entry; + + g_return_if_fail (entry != NULL); + g_return_if_fail (storage != NULL); + g_return_if_fail (entry->auto_storage_list != NULL); + + new_list = g_list_copy (entry->auto_storage_list); + + for (iterator = new_list; iterator != NULL; iterator = iterator->next) { + storage_in_entry = iterator->data; - if (entry->gconf_connection_id != 0) { - gconf_client_notify_remove (client, entry->gconf_connection_id); - } + g_return_if_fail (storage_in_entry != NULL); - entry->gconf_connection_id = 0; + if (storage_in_entry == storage) { + entry->auto_storage_list = g_list_remove (entry->auto_storage_list, + storage); + + switch (entry->type) { + case PREFERENCE_STRING: + update_auto_string (storage, NULL); + break; + case PREFERENCE_BOOLEAN: + case PREFERENCE_INTEGER: + update_auto_integer_or_boolean (storage, 0); + break; + default: + g_warning ("unexpected preference type %d in preferences_entry_remove_auto_storage", entry->type); + } + } } + + g_list_free (new_list); + + preferences_entry_check_remove_connection (entry); } /** @@ -975,7 +1140,7 @@ preferences_callback_entry_free_func (gpointer data, /** * preferences_entry_free * - * Free a preference hash node members along with the node itself. + * Free a preference hash node's members along with the node itself. * @preferences_hash_node: The node to free. **/ static void @@ -992,11 +1157,13 @@ preferences_entry_free (PreferencesEntry *entry) gconf_client_notify_remove (client, entry->gconf_connection_id); entry->gconf_connection_id = 0; } - + + g_list_free (entry->auto_storage_list); nautilus_g_list_free_deep_custom (entry->callback_list, preferences_callback_entry_free_func, NULL); + entry->auto_storage_list = NULL; entry->callback_list = NULL; g_free (entry->name); @@ -1112,6 +1279,118 @@ nautilus_preferences_add_callback (const char *name, preferences_entry_add_callback (entry, callback, callback_data); } +void +nautilus_preferences_add_auto_string (const char *name, + const char **storage) +{ + PreferencesEntry *entry; + char *value; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup_or_insert (name); + g_assert (entry != NULL); + + preferences_entry_add_auto_storage (entry, storage, PREFERENCE_STRING); + + value = nautilus_preferences_get (entry->name); + update_auto_string (storage, value); + g_free (value); +} + +void +nautilus_preferences_add_auto_integer (const char *name, + int *storage) +{ + PreferencesEntry *entry; + int value; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup_or_insert (name); + g_assert (entry != NULL); + + preferences_entry_add_auto_storage (entry, storage, PREFERENCE_INTEGER); + + value = nautilus_preferences_get_integer (entry->name); + update_auto_integer_or_boolean (storage, GINT_TO_POINTER (value)); +} + +void +nautilus_preferences_add_auto_boolean (const char *name, + gboolean *storage) +{ + PreferencesEntry *entry; + gboolean value; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup_or_insert (name); + g_assert (entry != NULL); + + preferences_entry_add_auto_storage (entry, storage, PREFERENCE_BOOLEAN); + + value = nautilus_preferences_get_boolean (entry->name); + update_auto_integer_or_boolean (storage, GINT_TO_POINTER (value)); +} + +void +nautilus_preferences_remove_auto_string (const char *name, + const char **storage) +{ + PreferencesEntry *entry; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup (name); + if (entry == NULL) { + g_warning ("Trying to remove auto-string for %s without adding it first.", name); + return; + } + + preferences_entry_remove_auto_storage (entry, storage); +} + +void +nautilus_preferences_remove_auto_integer (const char *name, + int *storage) +{ + PreferencesEntry *entry; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup (name); + if (entry == NULL) { + g_warning ("Trying to remove auto-integer for %s without adding it first.", name); + return; + } + + preferences_entry_remove_auto_storage (entry, storage); +} + +void +nautilus_preferences_remove_auto_boolean (const char *name, + gboolean *storage) +{ + PreferencesEntry *entry; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup (name); + if (entry == NULL) { + g_warning ("Trying to remove auto-boolean for %s without adding it first.", name); + return; + } + + preferences_entry_remove_auto_storage (entry, storage); +} + typedef struct { char *name; @@ -1172,10 +1451,10 @@ nautilus_preferences_remove_callback (const char *name, g_return_if_fail (name != NULL); g_return_if_fail (callback != NULL); - entry = preferences_global_table_lookup_or_insert (name); + entry = preferences_global_table_lookup (name); if (entry == NULL) { - g_warning ("Trying to remove a callback without adding it first."); + g_warning ("Trying to remove a callback for %s without adding it first.", name); return; } diff --git a/libnautilus-extensions/nautilus-preferences.h b/libnautilus-extensions/nautilus-preferences.h index 07a1d7ef2..7f6554d8c 100644 --- a/libnautilus-extensions/nautilus-preferences.h +++ b/libnautilus-extensions/nautilus-preferences.h @@ -99,6 +99,20 @@ void nautilus_preferences_remove_callback (const char NautilusPreferencesCallback callback, gpointer callback_data); +/* Variables that are automatically updated (lightweight "callbacks") */ +void nautilus_preferences_add_auto_string (const char *name, + const char **storage); +void nautilus_preferences_add_auto_integer (const char *name, + int *storage); +void nautilus_preferences_add_auto_boolean (const char *name, + gboolean *storage); +void nautilus_preferences_remove_auto_string (const char *name, + const char **storage); +void nautilus_preferences_remove_auto_integer (const char *name, + int *storage); +void nautilus_preferences_remove_auto_boolean (const char *name, + int *storage); + /* Preferences attributes */ int nautilus_preferences_get_visible_user_level (const char *name); void nautilus_preferences_set_visible_user_level (const char *name, diff --git a/libnautilus-private/nautilus-font-factory.c b/libnautilus-private/nautilus-font-factory.c index c6c894cef..09abdb6e6 100644 --- a/libnautilus-private/nautilus-font-factory.c +++ b/libnautilus-private/nautilus-font-factory.c @@ -273,12 +273,20 @@ nautilus_font_factory_get_font_by_family (const char *family, GdkFont * nautilus_font_factory_get_font_from_preferences (guint size_in_pixels) { - char *family; - GdkFont *font; + static gboolean icon_view_font_auto_value_registered; + static const char *icon_view_font_auto_value; - family = nautilus_preferences_get (NAUTILUS_PREFERENCES_ICON_VIEW_FONT); - font = nautilus_font_factory_get_font_by_family (family, size_in_pixels); - g_free (family); + /* Can't initialize this in initialize_class, because no font factory + * instance may yet exist when this is called. + */ + if (!icon_view_font_auto_value_registered) { + nautilus_preferences_add_auto_string (NAUTILUS_PREFERENCES_ICON_VIEW_FONT, + &icon_view_font_auto_value); + icon_view_font_auto_value_registered = TRUE; + } - return font; + /* FIXME: We hardwire icon view font here, but some callers probably + * expect default font instead. + */ + return nautilus_font_factory_get_font_by_family (icon_view_font_auto_value, size_in_pixels); } diff --git a/libnautilus-private/nautilus-global-preferences.c b/libnautilus-private/nautilus-global-preferences.c index a1d69d4ab..b205a19f9 100644 --- a/libnautilus-private/nautilus-global-preferences.c +++ b/libnautilus-private/nautilus-global-preferences.c @@ -81,6 +81,8 @@ static GtkWidget *global_preferences_populate_pane (Nautilu const PreferenceDialogItem *preference_dialog_item); static GtkWidget *global_prefs_dialog = NULL; +static const char *default_smooth_font_auto_value; +static const char *icon_view_smooth_font_auto_value; /* An enumeration used for installing type specific preferences defaults. */ typedef enum @@ -1563,33 +1565,25 @@ nautilus_global_preferences_set_dialog_title (const char *title) } static NautilusScalableFont * -global_preferences_get_smooth_font (const char *preference_name) +global_preferences_get_smooth_font (const char *smooth_font_file_name) { NautilusScalableFont *smooth_font; - char *smooth_font_file_name; - g_return_val_if_fail (preference_name != NULL, NULL); - - smooth_font_file_name = nautilus_preferences_get (preference_name); - - smooth_font = (smooth_font_file_name && g_file_exists (smooth_font_file_name)) ? + smooth_font = (smooth_font_file_name != NULL && g_file_exists (smooth_font_file_name)) ? nautilus_scalable_font_new (smooth_font_file_name) : nautilus_scalable_font_get_default_font (); - g_free (smooth_font_file_name); g_assert (NAUTILUS_IS_SCALABLE_FONT (smooth_font)); return smooth_font; } static NautilusScalableFont * -global_preferences_get_smooth_bold_font (const char *preference_name) +global_preferences_get_smooth_bold_font (const char *file_name) { NautilusScalableFont *plain_font; NautilusScalableFont *bold_font; - g_return_val_if_fail (preference_name != NULL, NULL); - - plain_font = global_preferences_get_smooth_font (preference_name); + plain_font = global_preferences_get_smooth_font (file_name); g_assert (NAUTILUS_IS_SCALABLE_FONT (plain_font)); bold_font = nautilus_scalable_font_make_bold (plain_font); @@ -1613,7 +1607,7 @@ global_preferences_get_smooth_bold_font (const char *preference_name) NautilusScalableFont * nautilus_global_preferences_get_icon_view_smooth_font (void) { - return global_preferences_get_smooth_font (NAUTILUS_PREFERENCES_ICON_VIEW_SMOOTH_FONT); + return global_preferences_get_smooth_font (icon_view_smooth_font_auto_value); } /** @@ -1625,7 +1619,7 @@ nautilus_global_preferences_get_icon_view_smooth_font (void) NautilusScalableFont * nautilus_global_preferences_get_default_smooth_font (void) { - return global_preferences_get_smooth_font (NAUTILUS_PREFERENCES_DEFAULT_SMOOTH_FONT); + return global_preferences_get_smooth_font (default_smooth_font_auto_value); } /** @@ -1639,7 +1633,7 @@ nautilus_global_preferences_get_default_smooth_font (void) NautilusScalableFont * nautilus_global_preferences_get_default_smooth_bold_font (void) { - return global_preferences_get_smooth_bold_font (NAUTILUS_PREFERENCES_DEFAULT_SMOOTH_FONT); + return global_preferences_get_smooth_bold_font (default_smooth_font_auto_value); } void @@ -1655,4 +1649,10 @@ nautilus_global_preferences_initialize (void) /* Install defaults */ global_preferences_install_defaults (); + + /* Set up storage for values accessed in this file */ + nautilus_preferences_add_auto_string (NAUTILUS_PREFERENCES_ICON_VIEW_SMOOTH_FONT, + &icon_view_smooth_font_auto_value); + nautilus_preferences_add_auto_string (NAUTILUS_PREFERENCES_DEFAULT_SMOOTH_FONT, + &default_smooth_font_auto_value); } diff --git a/libnautilus-private/nautilus-icon-canvas-item.c b/libnautilus-private/nautilus-icon-canvas-item.c index 4d3606f15..01a83eb7b 100644 --- a/libnautilus-private/nautilus-icon-canvas-item.c +++ b/libnautilus-private/nautilus-icon-canvas-item.c @@ -147,6 +147,8 @@ static guint32 highlight_background_color = NAUTILUS_RGBA_COLOR_PACK (0x00, 0x00 static guint32 highlight_text_color = NAUTILUS_RGBA_COLOR_PACK (0xFF, 0xFF, 0xFF, 0xFF); static guint32 highlight_text_info_color = NAUTILUS_RGBA_COLOR_PACK (0xCC, 0xCC, 0xCC, 0xFF); +static int click_policy_auto_value; + /* GtkObject */ static void nautilus_icon_canvas_item_initialize_class (NautilusIconCanvasItemClass *class); static void nautilus_icon_canvas_item_initialize (NautilusIconCanvasItem *item); @@ -284,6 +286,9 @@ nautilus_icon_canvas_item_initialize_class (NautilusIconCanvasItemClass *class) item_class->point = nautilus_icon_canvas_item_point; item_class->bounds = nautilus_icon_canvas_item_bounds; item_class->event = nautilus_icon_canvas_item_event; + + nautilus_preferences_add_auto_integer (NAUTILUS_PREFERENCES_CLICK_POLICY, + &click_policy_auto_value); } /* Object initialization function for the icon item. */ @@ -719,8 +724,7 @@ gnome_icon_underline_text (GnomeIconTextInfo *text_info, static gboolean in_single_click_mode () { - /* Perhaps this should be computed elsewhere and passed in. */ - return nautilus_preferences_get_integer (NAUTILUS_PREFERENCES_CLICK_POLICY) == NAUTILUS_CLICK_POLICY_SINGLE; + return click_policy_auto_value == NAUTILUS_CLICK_POLICY_SINGLE; } /* Keep these for a bit while we work on performance of draw_or_measure_label_text. */ diff --git a/libnautilus-private/nautilus-icon-factory.c b/libnautilus-private/nautilus-icon-factory.c index 4bb3cd2ca..009ec9f51 100644 --- a/libnautilus-private/nautilus-icon-factory.c +++ b/libnautilus-private/nautilus-icon-factory.c @@ -1333,15 +1333,18 @@ nautilus_scalable_icon_equal (gconstpointer a, && icon_a->aa_mode == icon_b->aa_mode; } - static gboolean should_display_image_file_as_itself (NautilusFile *file, gboolean anti_aliased) { - NautilusSpeedTradeoffValue preference_value; - - preference_value = nautilus_preferences_get_integer - (NAUTILUS_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS); + static int show_thumbnails_auto_value; + static gboolean show_thumbnail_auto_value_registered; + if (!show_thumbnail_auto_value_registered) { + nautilus_preferences_add_auto_integer (NAUTILUS_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS, + &show_thumbnails_auto_value); + show_thumbnail_auto_value_registered = TRUE; + } + /* see if there's a proxy thumbnail to indicate that thumbnailing * failed, in which case we shouldn't use the thumbnail. */ @@ -1354,15 +1357,15 @@ should_display_image_file_as_itself (NautilusFile *file, gboolean anti_aliased) return FALSE; } - if (preference_value == NAUTILUS_SPEED_TRADEOFF_ALWAYS) { + if (show_thumbnails_auto_value == NAUTILUS_SPEED_TRADEOFF_ALWAYS) { return TRUE; } - if (preference_value == NAUTILUS_SPEED_TRADEOFF_NEVER) { + if (show_thumbnails_auto_value == NAUTILUS_SPEED_TRADEOFF_NEVER) { return FALSE; } - g_assert (preference_value == NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY); + g_assert (show_thumbnails_auto_value == NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY); return nautilus_file_is_local (file); } diff --git a/libnautilus-private/nautilus-preferences.c b/libnautilus-private/nautilus-preferences.c index f800cad33..b20d29cf8 100644 --- a/libnautilus-private/nautilus-preferences.c +++ b/libnautilus-private/nautilus-preferences.c @@ -44,6 +44,17 @@ #define DEFAULT_USER_LEVEL NAUTILUS_USER_LEVEL_INTERMEDIATE +/* An enumeration used for updating auto-storage variables in a type-specific way. + * FIXME: there is another enumeration like this in nautilus-global-preferences.c, + * used for different purposes but in a related way. Should we combine them? + */ +typedef enum +{ + PREFERENCE_BOOLEAN = 1, + PREFERENCE_INTEGER, + PREFERENCE_STRING +} PreferenceType; + /* * PreferencesEntry: * @@ -54,7 +65,9 @@ typedef struct { char *name; char *description; + PreferenceType type; GList *callback_list; + GList *auto_storage_list; int gconf_connection_id; NautilusEnumeration *enumeration; } PreferencesEntry; @@ -509,7 +522,7 @@ nautilus_preferences_get (const char *name) { char *result; char *key; - + g_return_val_if_fail (name != NULL, NULL); key = preferences_key_make_for_getter (name); @@ -746,6 +759,63 @@ preferences_callback_entry_invoke_function (gpointer data, } static void +update_auto_string (gpointer data, gpointer callback_data) +{ + char **storage; + const char *value; + + g_return_if_fail (data != NULL); + g_return_if_fail (callback_data != NULL); + + storage = (char **)data; + value = (const char *)callback_data; + + g_free (*storage); + *(char **)storage = g_strdup (value); +} + +static void +update_auto_integer_or_boolean (gpointer data, gpointer callback_data) +{ + g_return_if_fail (data != NULL); + g_return_if_fail (callback_data != NULL); + + *(int *)data = GPOINTER_TO_INT (callback_data); +} + +static void +preferences_entry_update_auto_storage (PreferencesEntry *entry) +{ + char *new_string_value; + int new_int_value; + gboolean new_boolean_value; + + switch (entry->type) { + case PREFERENCE_STRING: + new_string_value = nautilus_preferences_get (entry->name); + g_list_foreach (entry->auto_storage_list, + update_auto_string, + new_string_value); + g_free (new_string_value); + break; + case PREFERENCE_INTEGER: + new_int_value = nautilus_preferences_get_integer (entry->name); + g_list_foreach (entry->auto_storage_list, + update_auto_integer_or_boolean, + GINT_TO_POINTER (new_int_value)); + break; + case PREFERENCE_BOOLEAN: + new_boolean_value = nautilus_preferences_get_boolean (entry->name); + g_list_foreach (entry->auto_storage_list, + update_auto_integer_or_boolean, + GINT_TO_POINTER (new_boolean_value)); + break; + default: + g_warning ("unexpected preferences type %d in preferences_entry_update_auto_storage", entry->type); + } +} + +static void preferences_something_changed_notice (GConfClient *client, guint connection_id, GConfEntry *entry, @@ -758,17 +828,19 @@ preferences_something_changed_notice (GConfClient *client, 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 */ - if (preferences_entry->callback_list) { - g_list_foreach (preferences_entry->callback_list, - preferences_callback_entry_invoke_function, - NULL); - } + g_list_foreach (preferences_entry->callback_list, + preferences_callback_entry_invoke_function, + NULL); } static void @@ -823,14 +895,52 @@ preferences_user_level_changed_notice (GConfClient *client, NULL); } +static void +preferences_entry_ensure_gconf_connection (PreferencesEntry *entry) +{ + GError *error; + GConfClient *client; + char *key; + + /* + * We install only one gconf notification for each preference entry. + * Otherwise, we would invoke the installed callbacks more than once + * per registered callback. + */ + if (entry->gconf_connection_id != 0) { + return; + } + + g_return_if_fail (entry->name != NULL); + + client = preferences_global_client_get (); + + g_return_if_fail (client != NULL); + + key = preferences_key_make (entry->name); + + error = NULL; + entry->gconf_connection_id = gconf_client_notify_add (client, + key, + preferences_something_changed_notice, + entry, + NULL, + &error); + if (nautilus_gconf_handle_error (&error)) { + entry->gconf_connection_id = 0; + } + + g_free (key); +} + /** * preferences_entry_add_callback * * Add a callback to a pref node. Callbacks are fired whenever * the pref value changes. * @preferences_entry: The hash node. - * @callback: The user supplied callback. - * @callback_data: The user supplied closure. + * @callback: The user-supplied callback. + * @callback_data: The user-supplied closure. **/ static void preferences_entry_add_callback (PreferencesEntry *entry, @@ -850,36 +960,56 @@ preferences_entry_add_callback (PreferencesEntry *entry, entry->callback_list = g_list_append (entry->callback_list, callback_entry); - /* - * We install only one gconf notification for each preference entry. - * Otherwise, we would invoke the installed callbacks more than once - * per registered callback. - */ - if (entry->gconf_connection_id == 0) { - GError *error = NULL; - GConfClient *client; - char *key; - - g_return_if_fail (entry->name != NULL); + preferences_entry_ensure_gconf_connection (entry); +} - client = preferences_global_client_get (); +/** + * preferences_entry_add_auto_storage + * + * Add an auto-storage variable to a pref node. The variable will + * be updated to match the pref value whenever the pref + * the pref value changes. + * @preferences_entry: The hash node. + * @storage: The user-supplied location at which to store the value. + * @type: Which type of variable this is. + **/ +static void +preferences_entry_add_auto_storage (PreferencesEntry *entry, + gpointer storage, + PreferenceType type) +{ + g_return_if_fail (entry != NULL); + g_return_if_fail (storage != NULL); + g_return_if_fail (entry->type == 0 || entry->type == type); + g_return_if_fail (g_list_find (entry->auto_storage_list, storage) == NULL); - g_return_if_fail (client != NULL); + entry->type = type; + + entry->auto_storage_list = g_list_append (entry->auto_storage_list, storage); - key = preferences_key_make (entry->name); + preferences_entry_ensure_gconf_connection (entry); +} - entry->gconf_connection_id = gconf_client_notify_add (client, - key, - preferences_something_changed_notice, - entry, - NULL, - &error); - if (nautilus_gconf_handle_error (&error)) { - entry->gconf_connection_id = 0; - } +static void +preferences_entry_check_remove_connection (PreferencesEntry *entry) +{ + GConfClient *client; + + /* + * If there are no callbacks or auto-storage variables left in the entry, + * remove the gconf notification. + */ + if (entry->callback_list != NULL || entry->auto_storage_list != NULL) { + return; + } - g_free (key); + client = preferences_global_client_get (); + + if (entry->gconf_connection_id != 0) { + gconf_client_notify_remove (client, entry->gconf_connection_id); } + + entry->gconf_connection_id = 0; } /** @@ -888,8 +1018,8 @@ preferences_entry_add_callback (PreferencesEntry *entry, * remove a callback from a pref entry. Both the callback and the callback_data must * match in order for a callback to be removed from the entry. * @preferences_entry: The hash entry. - * @callback: The user supplied callback. - * @callback_data: The user supplied closure. + * @callback: The user-supplied callback. + * @callback_data: The user-supplied closure. **/ static void preferences_entry_remove_callback (PreferencesEntry *entry, @@ -920,22 +1050,57 @@ preferences_entry_remove_callback (PreferencesEntry *entry, } g_list_free (new_list); - - /* - * If there are no callbacks left in the entry, remove the gconf - * notification as well. - */ - if (entry->callback_list == NULL) { - GConfClient *client; - client = preferences_global_client_get (); + preferences_entry_check_remove_connection (entry); +} + +/** + * preferences_entry_remove_auto_storage + * + * remove an auto-storage variable from a pref entry. + * @preferences_entry: The hash entry. + * @storage: The user-supplied location. + **/ +static void +preferences_entry_remove_auto_storage (PreferencesEntry *entry, + gpointer storage) +{ + GList *new_list; + GList *iterator; + gpointer storage_in_entry; + + g_return_if_fail (entry != NULL); + g_return_if_fail (storage != NULL); + g_return_if_fail (entry->auto_storage_list != NULL); + + new_list = g_list_copy (entry->auto_storage_list); + + for (iterator = new_list; iterator != NULL; iterator = iterator->next) { + storage_in_entry = iterator->data; - if (entry->gconf_connection_id != 0) { - gconf_client_notify_remove (client, entry->gconf_connection_id); - } + g_return_if_fail (storage_in_entry != NULL); - entry->gconf_connection_id = 0; + if (storage_in_entry == storage) { + entry->auto_storage_list = g_list_remove (entry->auto_storage_list, + storage); + + switch (entry->type) { + case PREFERENCE_STRING: + update_auto_string (storage, NULL); + break; + case PREFERENCE_BOOLEAN: + case PREFERENCE_INTEGER: + update_auto_integer_or_boolean (storage, 0); + break; + default: + g_warning ("unexpected preference type %d in preferences_entry_remove_auto_storage", entry->type); + } + } } + + g_list_free (new_list); + + preferences_entry_check_remove_connection (entry); } /** @@ -975,7 +1140,7 @@ preferences_callback_entry_free_func (gpointer data, /** * preferences_entry_free * - * Free a preference hash node members along with the node itself. + * Free a preference hash node's members along with the node itself. * @preferences_hash_node: The node to free. **/ static void @@ -992,11 +1157,13 @@ preferences_entry_free (PreferencesEntry *entry) gconf_client_notify_remove (client, entry->gconf_connection_id); entry->gconf_connection_id = 0; } - + + g_list_free (entry->auto_storage_list); nautilus_g_list_free_deep_custom (entry->callback_list, preferences_callback_entry_free_func, NULL); + entry->auto_storage_list = NULL; entry->callback_list = NULL; g_free (entry->name); @@ -1112,6 +1279,118 @@ nautilus_preferences_add_callback (const char *name, preferences_entry_add_callback (entry, callback, callback_data); } +void +nautilus_preferences_add_auto_string (const char *name, + const char **storage) +{ + PreferencesEntry *entry; + char *value; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup_or_insert (name); + g_assert (entry != NULL); + + preferences_entry_add_auto_storage (entry, storage, PREFERENCE_STRING); + + value = nautilus_preferences_get (entry->name); + update_auto_string (storage, value); + g_free (value); +} + +void +nautilus_preferences_add_auto_integer (const char *name, + int *storage) +{ + PreferencesEntry *entry; + int value; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup_or_insert (name); + g_assert (entry != NULL); + + preferences_entry_add_auto_storage (entry, storage, PREFERENCE_INTEGER); + + value = nautilus_preferences_get_integer (entry->name); + update_auto_integer_or_boolean (storage, GINT_TO_POINTER (value)); +} + +void +nautilus_preferences_add_auto_boolean (const char *name, + gboolean *storage) +{ + PreferencesEntry *entry; + gboolean value; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup_or_insert (name); + g_assert (entry != NULL); + + preferences_entry_add_auto_storage (entry, storage, PREFERENCE_BOOLEAN); + + value = nautilus_preferences_get_boolean (entry->name); + update_auto_integer_or_boolean (storage, GINT_TO_POINTER (value)); +} + +void +nautilus_preferences_remove_auto_string (const char *name, + const char **storage) +{ + PreferencesEntry *entry; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup (name); + if (entry == NULL) { + g_warning ("Trying to remove auto-string for %s without adding it first.", name); + return; + } + + preferences_entry_remove_auto_storage (entry, storage); +} + +void +nautilus_preferences_remove_auto_integer (const char *name, + int *storage) +{ + PreferencesEntry *entry; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup (name); + if (entry == NULL) { + g_warning ("Trying to remove auto-integer for %s without adding it first.", name); + return; + } + + preferences_entry_remove_auto_storage (entry, storage); +} + +void +nautilus_preferences_remove_auto_boolean (const char *name, + gboolean *storage) +{ + PreferencesEntry *entry; + + g_return_if_fail (name != NULL); + g_return_if_fail (storage != NULL); + + entry = preferences_global_table_lookup (name); + if (entry == NULL) { + g_warning ("Trying to remove auto-boolean for %s without adding it first.", name); + return; + } + + preferences_entry_remove_auto_storage (entry, storage); +} + typedef struct { char *name; @@ -1172,10 +1451,10 @@ nautilus_preferences_remove_callback (const char *name, g_return_if_fail (name != NULL); g_return_if_fail (callback != NULL); - entry = preferences_global_table_lookup_or_insert (name); + entry = preferences_global_table_lookup (name); if (entry == NULL) { - g_warning ("Trying to remove a callback without adding it first."); + g_warning ("Trying to remove a callback for %s without adding it first.", name); return; } diff --git a/libnautilus-private/nautilus-preferences.h b/libnautilus-private/nautilus-preferences.h index 07a1d7ef2..7f6554d8c 100644 --- a/libnautilus-private/nautilus-preferences.h +++ b/libnautilus-private/nautilus-preferences.h @@ -99,6 +99,20 @@ void nautilus_preferences_remove_callback (const char NautilusPreferencesCallback callback, gpointer callback_data); +/* Variables that are automatically updated (lightweight "callbacks") */ +void nautilus_preferences_add_auto_string (const char *name, + const char **storage); +void nautilus_preferences_add_auto_integer (const char *name, + int *storage); +void nautilus_preferences_add_auto_boolean (const char *name, + gboolean *storage); +void nautilus_preferences_remove_auto_string (const char *name, + const char **storage); +void nautilus_preferences_remove_auto_integer (const char *name, + int *storage); +void nautilus_preferences_remove_auto_boolean (const char *name, + int *storage); + /* Preferences attributes */ int nautilus_preferences_get_visible_user_level (const char *name); void nautilus_preferences_set_visible_user_level (const char *name, diff --git a/src/file-manager/fm-icon-text-window.c b/src/file-manager/fm-icon-text-window.c index 11468805c..340b17071 100644 --- a/src/file-manager/fm-icon-text-window.c +++ b/src/file-manager/fm-icon-text-window.c @@ -367,8 +367,8 @@ static void fm_icon_text_window_destroy_callback (GtkObject *object, gpointer user_data) { - nautilus_preferences_remove_callback (NAUTILUS_PREFERENCES_ICON_CAPTIONS, - synch_menus_with_preference, + nautilus_preferences_remove_callback (NAUTILUS_PREFERENCES_ICON_CAPTIONS, + synch_menus_with_preference, NULL); } @@ -394,27 +394,43 @@ fm_icon_text_window_get_or_create (void) return GTK_WINDOW (icon_text_window); } +/* fm_get_text_attribute_names_preference: + * + * Get the preference for which caption text should appear + * beneath icons. This function validates the raw preference + * and returns a default value if the raw preference is + * nonsensical. + */ char * fm_get_text_attribute_names_preference (void) { - /* FIXME: This string leaks at exit, which matters only if you're - * using a leak checker. - */ - static char *icon_captions = NULL; - char *new_icon_captions; - - new_icon_captions = nautilus_preferences_get (NAUTILUS_PREFERENCES_ICON_CAPTIONS); - - if (attribute_names_string_is_good (new_icon_captions)) { - g_free (icon_captions); - icon_captions = g_strdup (new_icon_captions); + static const char *auto_preferences_value; + static char *last_checked_value; + static gboolean auto_preferences_value_is_registered; + static char *captions_as_string; + + /* Register auto-storage value the first time it's asked for */ + if (!auto_preferences_value_is_registered) { + nautilus_preferences_add_auto_string (NAUTILUS_PREFERENCES_ICON_CAPTIONS, + &auto_preferences_value); + auto_preferences_value_is_registered = TRUE; } - g_free (new_icon_captions); + /* Validate preferences value the first time we see it */ + if (last_checked_value == NULL || strcmp (last_checked_value, auto_preferences_value) != 0) { + if (attribute_names_string_is_good (auto_preferences_value)) { + g_free (captions_as_string); + captions_as_string = g_strdup (auto_preferences_value); + } + + g_free (last_checked_value); + last_checked_value = g_strdup (auto_preferences_value); + } - if (icon_captions == NULL) { - icon_captions = g_strdup (DEFAULT_ATTRIBUTE_NAMES); + /* If the preferences value was bad or nonexistent, use default value */ + if (captions_as_string == NULL) { + captions_as_string = g_strdup (DEFAULT_ATTRIBUTE_NAMES); } - return g_strdup (icon_captions); + return g_strdup (captions_as_string); } diff --git a/src/file-manager/fm-icon-view.c b/src/file-manager/fm-icon-view.c index de9ac36b7..c317ef1c3 100644 --- a/src/file-manager/fm-icon-view.c +++ b/src/file-manager/fm-icon-view.c @@ -150,6 +150,8 @@ static void font_changed_callback (gpointer callback_data); static void smooth_font_changed_callback (gpointer callback_data); static void standard_font_size_changed_callback (gpointer callback_data); +static int preview_sound_auto_value; + NAUTILUS_DEFINE_CLASS_BOILERPLATE (FMIconView, fm_icon_view, FM_TYPE_DIRECTORY_VIEW) @@ -1442,11 +1444,7 @@ preview_audio (FMIconView *icon_view, NautilusFile *file, gboolean start_flag) static gboolean should_preview_sound (NautilusFile *file) { - int preview_mode; - - preview_mode = nautilus_preferences_get_integer (NAUTILUS_PREFERENCES_PREVIEW_SOUND); - - if (preview_mode == NAUTILUS_SPEED_TRADEOFF_NEVER) { + if (preview_sound_auto_value == NAUTILUS_SPEED_TRADEOFF_NEVER) { return FALSE; } /* the following is disabled until we can preview remote sounds, which we currently can't do */ @@ -1970,6 +1968,9 @@ fm_icon_view_initialize_class (FMIconViewClass *klass) klass->get_directory_tighter_layout = fm_icon_view_real_get_directory_tighter_layout; klass->set_directory_tighter_layout = fm_icon_view_real_set_directory_tighter_layout; klass->supports_auto_layout = real_supports_auto_layout; + + nautilus_preferences_add_auto_integer (NAUTILUS_PREFERENCES_PREVIEW_SOUND, + &preview_sound_auto_value); } static void |