/pidgin/main: c3548438b3a8: Implement PurplePrefsUiOps.(dis)conn...

dx <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: c3548438b3a816033e66723479569bb16e918eab
Author:	 dx <[email protected]>
Date:	 2016-06-16 02:10 -0300
Branch:	 release-2.x.y
URL: https://hg.pidgin.im/pidgin/main/rev/c3548438b3a8

Description:

Implement PurplePrefsUiOps.(dis)connect_callback from instantbird

They were called observers in instantbird, but since that's a mozilla specific
term, I made it generic. Most of the code checks if connect_callback is defined
to call the functions that implement callback handling for the UI.

The main difference is that when the UI overrides the handling of the
preferences, find_pref() won't work, and the callbacks have to be stored
elsewhere.

diffstat:

 libpurple/prefs.c |  196 +++++++++++++++++++++++++++++++++++++++++++++++++----
 libpurple/prefs.h |   16 +++-
 2 files changed, 195 insertions(+), 17 deletions(-)

diffs (truncated from 336 to 300 lines):

diff --git a/libpurple/prefs.c b/libpurple/prefs.c
--- a/libpurple/prefs.c
+++ b/libpurple/prefs.c
@@ -42,11 +42,13 @@
 
 static PurplePrefsUiOps *prefs_ui_ops = NULL;
 
-struct pref_cb {
+struct _PurplePrefCallbackData {
 	PurplePrefCallback func;
 	gpointer data;
 	guint id;
 	void *handle;
+	void *ui_data;
+	char *name;
 };
 
 /* TODO: This should use PurpleValues? */
@@ -80,6 +82,7 @@ static struct purple_pref prefs = {
 static GHashTable *prefs_hash = NULL;
 static guint       save_timer = 0;
 static gboolean    prefs_loaded = FALSE;
+static GSList     *ui_callbacks = NULL;
 
 #define PURPLE_PREFS_UI_OP_CALL(member, ...) \
 	{ \
@@ -823,16 +826,51 @@ do_callbacks(const char* name, struct pu
 	struct purple_pref *cb_pref;
 	for(cb_pref = pref; cb_pref; cb_pref = cb_pref->parent) {
 		for(cbs = cb_pref->callbacks; cbs; cbs = cbs->next) {
-			struct pref_cb *cb = cbs->data;
+			PurplePrefCallbackData *cb = cbs->data;
 			cb->func(name, pref->type, pref->value.generic, cb->data);
 		}
 	}
 }
 
+static void
+do_ui_callbacks(const char *name)
+{
+	GSList *cbs;
+
+	purple_debug_misc("prefs", "trigger callback %s\n", name);
+
+	for (cbs = ui_callbacks; cbs; cbs = cbs->next) {
+		PurplePrefCallbackData *cb = cbs->data;
+		const char *cb_name = cb->name;
+		size_t len = strlen(cb_name);
+		if (!strncmp(cb_name, name, len) &&
+		    (name[len] == 0 || name[len] == '/' ||
+		     (len && name[len - 1] == '/'))) {
+			/* This test should behave like this:
+			 * name    = /toto/tata
+			 * cb_name = /toto/tata --> true
+			 * cb_name = /toto/tatatiti --> false
+			 * cb_name = / --> true
+			 * cb_name = /toto --> true
+			 * cb_name = /toto/ --> true
+			 */
+			purple_prefs_trigger_callback_object(cbs->data);
+		}
+	}
+}
+
 void
 purple_prefs_trigger_callback(const char *name)
 {
-	struct purple_pref *pref = find_pref(name);
+	struct purple_pref *pref;
+	PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
+	if (uiop && uiop->connect_callback) {
+		do_ui_callbacks(name);
+		return;
+	}
+
+	pref = find_pref(name);
 
 	if(!pref) {
 		purple_debug_error("prefs",
@@ -1355,31 +1393,103 @@ purple_prefs_rename_boolean_toggle(const
 guint
 purple_prefs_connect_callback(void *handle, const char *name, PurplePrefCallback func, gpointer data)
 {
-	struct purple_pref *pref;
-	struct pref_cb *cb;
+	struct purple_pref *pref = NULL;
+	PurplePrefCallbackData *cb;
 	static guint cb_id = 0;
+	PurplePrefsUiOps *uiop = NULL;
 
 	g_return_val_if_fail(name != NULL, 0);
 	g_return_val_if_fail(func != NULL, 0);
 
-	pref = find_pref(name);
-	if (pref == NULL) {
-		purple_debug_error("prefs", "purple_prefs_connect_callback: Unknown pref %s\n", name);
-		return 0;
+	uiop = purple_prefs_get_ui_ops();
+
+	if (!(uiop && uiop->connect_callback)) {
+		pref = find_pref(name);
+		if (pref == NULL) {
+			purple_debug_error("prefs", "purple_prefs_connect_callback: Unknown pref %s\n", name);
+			return 0;
+		}
 	}
 
-	cb = g_new0(struct pref_cb, 1);
+	cb = g_new0(PurplePrefCallbackData, 1);
 
 	cb->func = func;
 	cb->data = data;
 	cb->id = ++cb_id;
 	cb->handle = handle;
+	cb->name = g_strdup(name);
 
-	pref->callbacks = g_slist_append(pref->callbacks, cb);
+	if (uiop && uiop->connect_callback) {
+		cb->ui_data = uiop->connect_callback(name, cb);
+
+		if (cb->ui_data == NULL) {
+			purple_debug_error("prefs", "purple_prefs_connect_callback: connect failed for %s\n", name);
+			g_free(cb->name);
+			g_free(cb);
+			return 0;
+		}
+
+		ui_callbacks = g_slist_append(ui_callbacks, cb);
+	} else {
+		pref->callbacks = g_slist_append(pref->callbacks, cb);
+	}
 
 	return cb->id;
 }
 
+static void
+purple_prefs_trigger_ui_callback_object(PurplePrefCallbackData *cb)
+{
+	PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+	gconstpointer value = NULL;
+	PurplePrefType type = PURPLE_PREF_NONE;
+
+	type = uiop->get_type(cb->name);
+
+	switch (type) {
+		case PURPLE_PREF_INT:
+			if (uiop->get_int) {
+				value = GINT_TO_POINTER(uiop->get_int(cb->name));
+			}
+			break;
+		case PURPLE_PREF_BOOLEAN:
+			if (uiop->get_bool) {
+				value = GINT_TO_POINTER(uiop->get_bool(cb->name));
+			}
+			break;
+		case PURPLE_PREF_STRING:
+		case PURPLE_PREF_PATH:
+			if (uiop->get_string) {
+				value = uiop->get_string(cb->name);
+			}
+			break;
+		case PURPLE_PREF_STRING_LIST:
+		case PURPLE_PREF_PATH_LIST:
+			if (uiop->get_string_list) {
+				value = uiop->get_string_list(cb->name);
+			}
+			break;
+		case PURPLE_PREF_NONE:
+			break;
+		default:
+			purple_debug_error("prefs", "Unexpected type = %i\n", type);
+	}
+
+	cb->func(cb->name, type, value, cb->data);
+}
+
+void
+purple_prefs_trigger_callback_object(PurplePrefCallbackData *cb)
+{
+	PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
+	if (uiop && uiop->connect_callback && uiop->get_type) {
+		purple_prefs_trigger_ui_callback_object(cb);
+	} else {
+		purple_prefs_trigger_callback(cb->name);
+	}
+}
+
 static gboolean
 disco_callback_helper(struct purple_pref *pref, guint callback_id)
 {
@@ -1390,9 +1500,10 @@ disco_callback_helper(struct purple_pref
 		return FALSE;
 
 	for(cbs = pref->callbacks; cbs; cbs = cbs->next) {
-		struct pref_cb *cb = cbs->data;
+		PurplePrefCallbackData *cb = cbs->data;
 		if(cb->id == callback_id) {
 			pref->callbacks = g_slist_delete_link(pref->callbacks, cbs);
+			g_free(cb->name);
 			g_free(cb);
 			return TRUE;
 		}
@@ -1406,10 +1517,35 @@ disco_callback_helper(struct purple_pref
 	return FALSE;
 }
 
+static void
+disco_ui_callback_helper(guint callback_id)
+{
+	GSList *cbs;
+	PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
+	for (cbs = ui_callbacks; cbs; cbs = cbs->next) {
+		PurplePrefCallbackData *cb = cbs->data;
+		if (cb->id == callback_id) {
+			uiop->disconnect_callback(cb->name, cb->ui_data);
+
+			ui_callbacks = g_slist_delete_link(ui_callbacks, cbs);
+			g_free(cb->name);
+			g_free(cb);
+			return;
+		}
+	}
+}
+
 void
 purple_prefs_disconnect_callback(guint callback_id)
 {
-	disco_callback_helper(&prefs, callback_id);
+	PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
+	if (uiop && uiop->disconnect_callback) {
+		disco_ui_callback_helper(callback_id);
+	} else {
+		disco_callback_helper(&prefs, callback_id);
+	}
 }
 
 static void
@@ -1423,9 +1559,10 @@ disco_callback_helper_handle(struct purp
 
 	cbs = pref->callbacks;
 	while (cbs != NULL) {
-		struct pref_cb *cb = cbs->data;
+		PurplePrefCallbackData *cb = cbs->data;
 		if(cb->handle == handle) {
 			pref->callbacks = g_slist_delete_link(pref->callbacks, cbs);
+			g_free(cb->name);
 			g_free(cb);
 			cbs = pref->callbacks;
 		} else
@@ -1436,12 +1573,41 @@ disco_callback_helper_handle(struct purp
 		disco_callback_helper_handle(child, handle);
 }
 
+static void
+disco_ui_callback_helper_handle(void *handle)
+{
+	GSList *cbs;
+	PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
+	cbs = ui_callbacks;
+	for (cbs = ui_callbacks; cbs; cbs = cbs->next) {
+		PurplePrefCallbackData *cb = cbs->data;
+		if (cb->handle != handle) {
+			cbs = cbs->next;
+			continue;
+		}
+
+		uiop->disconnect_callback(cb->name, cb->ui_data);
+
+		ui_callbacks = g_slist_delete_link(ui_callbacks, cbs);
+		g_free(cb->name);
+		g_free(cb);
+		cbs = ui_callbacks;
+	}
+}
+
 void
 purple_prefs_disconnect_by_handle(void *handle)
 {
+	PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
 	g_return_if_fail(handle != NULL);
 
-	disco_callback_helper_handle(&prefs, handle);
+	if (uiop && uiop->disconnect_callback) {
+		disco_ui_callback_helper_handle(handle);
+	} else {
+		disco_callback_helper_handle(&prefs, handle);
+	}
 }
 
 GList *
diff --git a/libpurple/prefs.h b/libpurple/prefs.h
--- a/libpurple/prefs.h
+++ b/libpurple/prefs.h
@@ -62,6 +62,11 @@ typedef enum _PurplePrefType

_______________________________________________
Commits mailing list
[email protected]
https://pidgin.im/cgi-bin/mailman/listinfo/commits
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.