[PATCH] Improve eel and nautilus preferences (de)registration



The Nautilus/EEL preferences interaction used to be quite buggy.
Identical callbacks were deregistered in different places, and EEL
didn't catch bogus calls properly (i.e. double (de)registrations, and
calls after shutdown).

Proposed patch attached.

-- 
Christian Neumair <chris gnome-de org>
Index: eel/eel-preferences.c
===================================================================
RCS file: /cvs/gnome/eel/eel/eel-preferences.c,v
retrieving revision 1.17
diff -u -p -r1.17 eel-preferences.c
--- eel/eel-preferences.c	10 Jun 2005 00:49:54 -0000	1.17
+++ eel/eel-preferences.c	6 Oct 2006 22:38:03 -0000
@@ -251,6 +251,32 @@ preferences_get_default_value (const cha
         return result;
 }
 
+static int
+preferences_callback_entry_compare (gconstpointer a,
+				    gconstpointer b)
+{
+	const PreferencesCallbackEntry *a_entry = a;
+	const PreferencesCallbackEntry *b_entry = b;
+
+	if (a_entry->callback < b_entry->callback) {
+		return -1;
+	}
+
+	if (a_entry->callback > b_entry->callback) {
+		return +1;
+	}
+
+	if (a_entry->callback_data < b_entry->callback_data) {
+		return -1;
+	}
+
+	if (a_entry->callback_data > b_entry->callback_data) {
+		return +1;
+	}
+
+	return 0;
+}
+
 /* Public preferences functions */
 
 gboolean
@@ -793,6 +819,7 @@ preferences_entry_add_callback (Preferen
 				gpointer callback_data)
 {
 	PreferencesCallbackEntry *callback_entry;
+	GList *l;
 
 	g_return_if_fail (entry != NULL);
 	g_return_if_fail (callback != NULL);
@@ -800,12 +827,14 @@ preferences_entry_add_callback (Preferen
 	callback_entry = g_new0 (PreferencesCallbackEntry, 1);
 	callback_entry->callback = callback;
 	callback_entry->callback_data = callback_data;
-	
-	g_return_if_fail (callback_entry != NULL);
-	
-	entry->callback_list = g_list_append (entry->callback_list, callback_entry);
 
-	preferences_entry_ensure_gconf_connection (entry);
+	l = g_list_find_custom (entry->callback_list, callback_entry, preferences_callback_entry_compare);
+	if (l == NULL) {
+		entry->callback_list = g_list_append (entry->callback_list, callback_entry);
+		preferences_entry_ensure_gconf_connection (entry);
+	} else {
+		g_warning ("Trying to add a callback for %s that already exists.", entry->name);
+	}
 }
 
 /**
@@ -826,7 +855,10 @@ preferences_entry_add_auto_storage (Pref
 	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);
+	if (g_list_find (entry->auto_storage_list, storage) != NULL) {
+		g_warning ("Trying to add an auto storage for %s that already exists.", entry->name);
+		return;
+	}
 
 	entry->type = type;
 	
@@ -864,32 +896,25 @@ preferences_entry_remove_callback (Prefe
 				   EelPreferencesCallback callback,
 				   gpointer callback_data)
 {
-	GList *new_list;
-	const GList *node;
+	PreferencesCallbackEntry cb_entry;
+	GList *l;
 
 	g_return_if_fail (entry != NULL);
 	g_return_if_fail (callback != NULL);
-	g_return_if_fail (entry->callback_list != NULL);
-	
-	new_list = g_list_copy (entry->callback_list);
-	
-	for (node = new_list; node != NULL; node = node->next) {
-		PreferencesCallbackEntry *callback_entry = node->data;
-		
-		g_return_if_fail (callback_entry != NULL);
-		
-		if (callback_entry->callback == callback &&
-		    callback_entry->callback_data == callback_data) {
-			entry->callback_list = g_list_remove (entry->callback_list, 
-							      callback_entry);
-			
-			preferences_callback_entry_free (callback_entry);
-		}
-	}
 
-	g_list_free (new_list);
+	cb_entry.callback = callback;
+	cb_entry.callback_data = callback_data;
 
-	preferences_entry_check_remove_connection (entry);
+	l = g_list_find_custom (entry->callback_list, &cb_entry, preferences_callback_entry_compare);
+	if (l != NULL) {
+		preferences_callback_entry_free (l->data);
+		entry->callback_list = g_list_delete_link (entry->callback_list, l);
+		preferences_entry_check_remove_connection (entry);
+	} else {
+		g_warning ("Trying to remove a callback for %s without adding it first.", entry->name);
+	}
+
+	g_assert (g_list_find_custom (entry->callback_list, &cb_entry, preferences_callback_entry_compare) == NULL);
 }
 
 /**
@@ -1043,6 +1068,12 @@ preferences_global_table_free (void)
 	storage_path = NULL;
 }
 
+static void
+preferences_uninitialize (void)
+{
+	initialized = FALSE;
+}
+
 static GHashTable *
 preferences_global_table_get_global (void)
 {
@@ -1054,6 +1085,8 @@ preferences_global_table_get_global (voi
 		if (!at_exit_handler_added) {
 			at_exit_handler_added = TRUE;
 			eel_debug_call_at_shutdown (preferences_global_table_free);
+			/* ensure that we catch calls to preferences functions after eel shutdown */
+			eel_debug_call_at_shutdown (preferences_uninitialize);
 		}
 	}
 	
@@ -1341,9 +1374,13 @@ preferences_while_alive_disconnector (gp
 
 	data = callback_data;
 
-	eel_preferences_remove_callback (data->name,
-					 data->callback,
-					 data->callback_data);
+	/* we might have survived an eel shutdown, which
+	 * already cleared all the callbacks */
+	if (preferences_is_initialized ()) {
+		eel_preferences_remove_callback (data->name,
+						 data->callback,
+						 data->callback_data);
+	}
 
 	g_free (data->name);
 	g_free (data);
Index: src/file-manager/fm-directory-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-directory-view.c,v
retrieving revision 1.750
diff -u -p -r1.750 fm-directory-view.c
--- src/file-manager/fm-directory-view.c	8 Aug 2006 14:43:25 -0000	1.750
+++ src/file-manager/fm-directory-view.c	6 Oct 2006 22:33:58 -0000
@@ -2062,8 +2062,6 @@ fm_directory_view_destroy (GtkObject *ob
 		view->details->directory_as_file = NULL;
 	}
 
-	fm_directory_view_ignore_hidden_file_preferences (view);
-
 	EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
 }
 
@@ -2074,10 +2072,15 @@ fm_directory_view_finalize (GObject *obj
 
 	view = FM_DIRECTORY_VIEW (object);
 
-	eel_preferences_remove_callback (NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES,
-					 filtering_changed_callback, view);
-	eel_preferences_remove_callback (NAUTILUS_PREFERENCES_SHOW_BACKUP_FILES,
-					 filtering_changed_callback, view);
+	if (!view->details->ignore_hidden_file_preferences) {
+		/* fm_directory_view_ignore_hidden_file_preferences is a one-way switch,
+		 * and may have removed these callbacks already.
+		 */
+		eel_preferences_remove_callback (NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES,
+						 filtering_changed_callback, view);
+		eel_preferences_remove_callback (NAUTILUS_PREFERENCES_SHOW_BACKUP_FILES,
+						 filtering_changed_callback, view);
+	}
 	eel_preferences_remove_callback (NAUTILUS_PREFERENCES_CONFIRM_TRASH,
 					 schedule_update_menus_callback, view);
 	eel_preferences_remove_callback (NAUTILUS_PREFERENCES_ENABLE_DELETE,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]