/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