commit 542c9e333748831b6f3cb4a18b0e9c81b14c41bf Author: dequis Date: Mon Jun 13 01:41:01 2016 -0300 instantbird: prefs: observe, callback stuff diff --git a/libpurple/prefs.c b/libpurple/prefs.c index 4e2de2b..9adf4ab 100644 --- a/libpurple/prefs.c +++ b/libpurple/prefs.c @@ -45,10 +45,13 @@ struct pref_cb { gpointer data; guint id; void *handle; + void *observer; + char *name; }; static guint save_timer = 0; static gboolean prefs_loaded = FALSE; +static GSList *callbacks = NULL; static gboolean save_cb(gpointer data) @@ -158,15 +161,27 @@ purple_prefs_destroy() void purple_prefs_trigger_callback(const char *name) { - struct purple_pref *pref = find_pref(name); - - if(!pref) { - purple_debug_error("prefs", - "purple_prefs_trigger_callback: Unknown pref %s\n", name); - return; + GSList *cbs; + + purple_debug_misc("prefs", "trigger callback %s\n", name); + + for (cbs = callbacks; cbs; cbs = cbs->next) { + const char *cb_name = ((struct pref_cb *)cbs->data)->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_observe(cbs->data); + } } - - do_callbacks(name, pref); } void @@ -334,18 +349,15 @@ purple_prefs_get_string(const char *name) guint purple_prefs_connect_callback(void *handle, const char *name, PurplePrefCallback func, gpointer data) { - struct purple_pref *pref; struct pref_cb *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(); + g_return_val_if_fail(uiop, 0); cb = g_new0(struct pref_cb, 1); @@ -353,26 +365,92 @@ purple_prefs_connect_callback(void *handle, const char *name, PurplePrefCallback cb->data = data; cb->id = ++cb_id; cb->handle = handle; + cb->name = g_strdup(name); - pref->callbacks = g_slist_append(pref->callbacks, cb); + cb->observer = uiop->add_observer(name, cb); + + if (cb->observer == NULL) { + purple_debug_error("prefs", "purple_prefs_connect_callback: add observer failed for %s\n", name); + g_free(cb->name); + g_free(cb); + return 0; + } + callbacks = g_slist_append(callbacks, cb); return cb->id; } +void purple_prefs_observe(gpointer data) +{ + struct pref_cb *cb = data; + PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops(); + gconstpointer value = NULL; + PurplePrefType type = PURPLE_PREF_NONE; + type = uiop->get_type(cb->name); + + purple_debug_misc("prefs", "observe name = %s\n", cb->name); + + switch (type) { + case PURPLE_PREF_INT: + value = GINT_TO_POINTER(uiop->get_int(cb->name)); + break; + case PURPLE_PREF_BOOLEAN: + value = GINT_TO_POINTER(uiop->get_bool(cb->name)); + break; + case PURPLE_PREF_STRING: + value = uiop->get_string(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_disconnect_callback(guint callback_id) { - disco_callback_helper(&prefs, callback_id); -} + GSList *cbs; + for (cbs = callbacks; cbs; cbs = cbs->next) { + struct pref_cb *cb = cbs->data; + if (cb->id == callback_id) { + PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops(); + uiop->remove_observer(cb->name, cb->observer); + + callbacks = g_slist_delete_link(callbacks, cbs); + g_free(cb->name); + g_free(cb); + return; + } + } +} void purple_prefs_disconnect_by_handle(void *handle) { + GSList *cbs; + g_return_if_fail(handle != NULL); - disco_callback_helper_handle(&prefs, handle); + cbs = callbacks; + while (cbs != NULL) { + PurplePrefsUiOps *uiop; + struct pref_cb *cb = cbs->data; + if (cb->handle != handle) { + cbs = cbs->next; + continue; + } + + uiop = purple_prefs_get_ui_ops(); + uiop->remove_observer(cb->name, cb->observer); + + callbacks = g_slist_delete_link(callbacks, cbs); + g_free(cb->name); + g_free(cb); + cbs = callbacks; + } } GList *