diff options
author | Gary Kramlich <grim@reaperworld.com> | 2021-09-02 21:28:40 -0500 |
---|---|---|
committer | Gary Kramlich <grim@reaperworld.com> | 2021-09-02 21:28:40 -0500 |
commit | 2a03afa2b0a7ec79b2e34a762597b7415865e061 (patch) | |
tree | 1ab0ca3c17bf6a5732c4eed0e8ff2a3b2cb1c33e | |
parent | 99ac18ff794e4a412d8cc1cc7068c98cf0b5120c (diff) | |
download | pidgin-2a03afa2b0a7ec79b2e34a762597b7415865e061.tar.gz |
Create PurpleWhiteboardManager for managing whiteboards
Testing Done:
Compiled only. Tried to create a silc account, but it dies deep in libsilc.
Reviewed at https://reviews.imfreedom.org/r/886/
-rw-r--r-- | doc/reference/libpurple/libpurple-docs.xml | 1 | ||||
-rw-r--r-- | libpurple/core.c | 2 | ||||
-rw-r--r-- | libpurple/meson.build | 2 | ||||
-rw-r--r-- | libpurple/protocols/silc/wb.c | 77 | ||||
-rw-r--r-- | libpurple/purpleprivate.h | 19 | ||||
-rw-r--r-- | libpurple/purplewhiteboard.c | 87 | ||||
-rw-r--r-- | libpurple/purplewhiteboard.h | 40 | ||||
-rw-r--r-- | libpurple/purplewhiteboardmanager.c | 269 | ||||
-rw-r--r-- | libpurple/purplewhiteboardmanager.h | 193 | ||||
-rw-r--r-- | libpurple/tests/meson.build | 3 | ||||
-rw-r--r-- | libpurple/tests/test_whiteboard_manager.c | 54 | ||||
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | pidgin/gtkwhiteboard.c | 6 | ||||
-rw-r--r-- | po/POTFILES.in | 1 |
14 files changed, 661 insertions, 95 deletions
diff --git a/doc/reference/libpurple/libpurple-docs.xml b/doc/reference/libpurple/libpurple-docs.xml index 535f7f9643..54fea6abb2 100644 --- a/doc/reference/libpurple/libpurple-docs.xml +++ b/doc/reference/libpurple/libpurple-docs.xml @@ -80,6 +80,7 @@ <xi:include href="xml/purpleplugininfo.xml" /> <xi:include href="xml/purplepresence.xml" /> <xi:include href="xml/purplewhiteboard.xml" /> + <xi:include href="xml/purplewhiteboardmanager.xml" /> <xi:include href="xml/purplewhiteboardops.xml" /> <xi:include href="xml/purplewhiteboarduiops.xml" /> <xi:include href="xml/purpleuiinfo.xml" /> diff --git a/libpurple/core.c b/libpurple/core.c index 963cefa004..a093409137 100644 --- a/libpurple/core.c +++ b/libpurple/core.c @@ -170,6 +170,7 @@ purple_core_init(const char *ui) purple_notify_init(); purple_conversations_init(); purple_conversation_manager_startup(); + purple_whiteboard_manager_startup(); purple_blist_init(); purple_log_init(); purple_network_init(); @@ -219,6 +220,7 @@ purple_core_quit(void) /* Save .xml files, remove signals, etc. */ purple_idle_uninit(); + purple_whiteboard_manager_shutdown(); purple_conversation_manager_shutdown(); purple_conversations_uninit(); purple_blist_uninit(); diff --git a/libpurple/meson.build b/libpurple/meson.build index cfc51a235a..562a4ab07d 100644 --- a/libpurple/meson.build +++ b/libpurple/meson.build @@ -73,6 +73,7 @@ purple_coresources = [ 'purpleprotocolserver.c', 'purpleuiinfo.c', 'purplewhiteboard.c', + 'purplewhiteboardmanager.c', 'purplewhiteboarduiops.c', 'queuedoutputstream.c', 'request.c', @@ -164,6 +165,7 @@ purple_coreheaders = [ 'purpleprotocolserver.h', 'purpleuiinfo.h', 'purplewhiteboard.h', + 'purplewhiteboardmanager.h', 'purplewhiteboardops.h', 'purplewhiteboarduiops.h', 'queuedoutputstream.h', diff --git a/libpurple/protocols/silc/wb.c b/libpurple/protocols/silc/wb.c index f687e69ef6..80577acfd1 100644 --- a/libpurple/protocols/silc/wb.c +++ b/libpurple/protocols/silc/wb.c @@ -105,13 +105,24 @@ typedef struct { PurpleWhiteboard *silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry) { PurpleWhiteboard *wb; + PurpleWhiteboardManager *manager; SilcPurpleWb wbs; + gchar *id = NULL; - wb = purple_whiteboard_get_session(sg->account, client_entry->nickname); - if (!wb) - wb = purple_whiteboard_new(sg->account, client_entry->nickname, 0); - if (!wb) + manager = purple_whiteboard_manager_get_default(); + + id = g_strdup_printf("silc-client-%s", client_entry->nickname); + wb = purple_whiteboard_manager_find(manager, id); + if(!PURPLE_IS_WHITEBOARD(wb)) { + wb = purple_whiteboard_new(sg->account, id, 0); + purple_whiteboard_manager_register(manager, wb, NULL); + } + + g_free(id); + + if(!PURPLE_IS_WHITEBOARD(wb)) { return NULL; + } if (!purple_whiteboard_get_protocol_data(wb)) { wbs = silc_calloc(1, sizeof(*wbs)); @@ -135,14 +146,24 @@ PurpleWhiteboard *silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry PurpleWhiteboard *silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel) { + PurpleWhiteboardManager *manager = NULL; PurpleWhiteboard *wb; SilcPurpleWb wbs; + gchar *id; + + manager = purple_whiteboard_manager_get_default(); - wb = purple_whiteboard_get_session(sg->account, channel->channel_name); - if (!wb) - wb = purple_whiteboard_new(sg->account, channel->channel_name, 0); - if (!wb) + id = g_strdup_printf("silc-channel-%s", channel->channel_name); + wb = purple_whiteboard_manager_find(manager, id); + if(!PURPLE_IS_WHITEBOARD(wb)) { + wb = purple_whiteboard_new(sg->account, id, 0); + } + + g_free(id); + + if(!PURPLE_IS_WHITEBOARD(wb)) { return NULL; + } if (!purple_whiteboard_get_protocol_data(wb)) { wbs = silc_calloc(1, sizeof(*wbs)); @@ -315,18 +336,19 @@ void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn, SilcMessageFlags flags, const unsigned char *message, SilcUInt32 message_len) { - SilcPurple sg; - PurpleConnection *gc; PurpleWhiteboard *wb; + PurpleWhiteboardManager *manager; + gchar *id = NULL; - gc = client->application; - sg = purple_connection_get_protocol_data(gc); + manager = purple_whiteboard_manager_get_default(); + + id = g_strdup_printf("silc-client-%s", sender->nickname); + wb = purple_whiteboard_manager_find(manager, id); + g_free(id); - wb = purple_whiteboard_get_session(sg->account, sender->nickname); - if (!wb) { + if(!PURPLE_IS_WHITEBOARD(wb)) { /* Ask user if they want to open the whiteboard */ - silcpurple_wb_request(client, message, message_len, - sender, NULL); + silcpurple_wb_request(client, message, message_len, sender, NULL); return; } @@ -342,18 +364,20 @@ void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn, const unsigned char *message, SilcUInt32 message_len) { - SilcPurple sg; - PurpleConnection *gc; PurpleWhiteboard *wb; + PurpleWhiteboardManager *manager; + gchar *id; - gc = client->application; - sg = purple_connection_get_protocol_data(gc); + manager = purple_whiteboard_manager_get_default(); + + id = g_strdup_printf("silc-channel-%s", channel->channel_name); + wb = purple_whiteboard_manager_find(manager, id); + g_free(id); - wb = purple_whiteboard_get_session(sg->account, channel->channel_name); - if (!wb) { + if(!PURPLE_IS_WHITEBOARD(wb)) { /* Ask user if they want to open the whiteboard */ - silcpurple_wb_request(client, message, message_len, - sender, channel); + silcpurple_wb_request(client, message, message_len, sender, channel); + return; } @@ -430,9 +454,14 @@ void silcpurple_wb_start(PurpleWhiteboard *wb) void silcpurple_wb_end(PurpleWhiteboard *wb) { SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); + PurpleWhiteboardManager *manager; + + manager = purple_whiteboard_manager_get_default(); silc_free(wbs); purple_whiteboard_set_protocol_data(wb, NULL); + + purple_whiteboard_manager_unregister(manager, wb, NULL); } void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height) diff --git a/libpurple/purpleprivate.h b/libpurple/purpleprivate.h index 414e5c8351..82499ad149 100644 --- a/libpurple/purpleprivate.h +++ b/libpurple/purpleprivate.h @@ -255,6 +255,25 @@ void purple_credential_provider_activate(PurpleCredentialProvider *provider); */ void purple_credential_provider_deactivate(PurpleCredentialProvider *provider); +/** + * purple_whiteboard_manager_startup: + * + * Starts up the whiteboard manager by creating the default instance. + * + * Since: 3.0.0 + */ +void purple_whiteboard_manager_startup(void); + +/** + * purple_whiteboard_manager_shutdown: + * + * Shuts down the whiteboard manager by destroying the default instance. + * + * Since: 3.0.0 + */ +void purple_whiteboard_manager_shutdown(void); + + G_END_DECLS #endif /* PURPLE_PRIVATE_H */ diff --git a/libpurple/purplewhiteboard.c b/libpurple/purplewhiteboard.c index f2db319bb0..8d97c200bb 100644 --- a/libpurple/purplewhiteboard.c +++ b/libpurple/purplewhiteboard.c @@ -27,12 +27,13 @@ #include "purpleprotocolfactory.h" #include "purplewhiteboarduiops.h" #include "protocol.h" +#include "util.h" typedef struct { int state; PurpleAccount *account; - char *who; + gchar *id; /* TODO Remove this and use protocol-specific subclasses. */ void *proto_data; @@ -47,7 +48,7 @@ enum { PROP_0, PROP_STATE, PROP_ACCOUNT, - PROP_WHO, + PROP_ID, PROP_DRAW_LIST, N_PROPERTIES, }; @@ -56,11 +57,6 @@ static GParamSpec *properties[N_PROPERTIES] = { NULL, }; G_DEFINE_TYPE_WITH_PRIVATE(PurpleWhiteboard, purple_whiteboard, G_TYPE_OBJECT) /****************************************************************************** - * Globals - *****************************************************************************/ -static GList *wb_list = NULL; - -/****************************************************************************** * Helpers *****************************************************************************/ static void @@ -78,15 +74,15 @@ purple_whiteboard_set_account(PurpleWhiteboard *whiteboard, } static void -purple_whiteboard_set_who(PurpleWhiteboard *whiteboard, const gchar *who) { +purple_whiteboard_set_id(PurpleWhiteboard *whiteboard, const gchar *id) { PurpleWhiteboardPrivate *priv = NULL; priv = purple_whiteboard_get_instance_private(whiteboard); - g_clear_pointer(&priv->who, g_free); - priv->who = g_strdup(who); + g_free(priv->id); + priv->id = g_strdup(id); - g_object_notify_by_pspec(G_OBJECT(whiteboard), properties[PROP_WHO]); + g_object_notify_by_pspec(G_OBJECT(whiteboard), properties[PROP_ID]); } /****************************************************************************** @@ -106,8 +102,8 @@ purple_whiteboard_set_property(GObject *obj, guint param_id, purple_whiteboard_set_account(whiteboard, g_value_get_object(value)); break; - case PROP_WHO: - purple_whiteboard_set_who(whiteboard, g_value_get_string(value)); + case PROP_ID: + purple_whiteboard_set_id(whiteboard, g_value_get_string(value)); break; case PROP_DRAW_LIST: purple_whiteboard_set_draw_list(whiteboard, @@ -133,9 +129,9 @@ purple_whiteboard_get_property(GObject *obj, guint param_id, GValue *value, g_value_set_object(value, purple_whiteboard_get_account(whiteboard)); break; - case PROP_WHO: + case PROP_ID: g_value_set_string(value, - purple_whiteboard_get_who(whiteboard)); + purple_whiteboard_get_id(whiteboard)); break; case PROP_DRAW_LIST: g_value_set_pointer(value, @@ -170,8 +166,6 @@ purple_whiteboard_constructed(GObject *object) { if(priv->protocol_ops != NULL && priv->protocol_ops->start != NULL) { priv->protocol_ops->start(whiteboard); } - - wb_list = g_list_append(wb_list, whiteboard); } static void @@ -186,10 +180,8 @@ purple_whiteboard_finalize(GObject *object) { priv->protocol_ops->end(whiteboard); } - wb_list = g_list_remove(wb_list, whiteboard); - g_clear_object(&priv->account); - g_clear_pointer(&priv->who, g_free); + g_clear_pointer(&priv->id, g_free); /* TODO: figure out how we need to clean up the drawlist */ @@ -216,9 +208,9 @@ purple_whiteboard_class_init(PurpleWhiteboardClass *klass) { "The whiteboard's account.", PURPLE_TYPE_ACCOUNT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - properties[PROP_WHO] = g_param_spec_string( - "who", "Who", - "Who you're drawing with.", NULL, + properties[PROP_ID] = g_param_spec_string( + "id", "id", + "The ID of the whiteboard.", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); properties[PROP_DRAW_LIST] = g_param_spec_pointer( @@ -257,14 +249,14 @@ purple_whiteboard_get_account(PurpleWhiteboard *whiteboard) { } const gchar * -purple_whiteboard_get_who(PurpleWhiteboard *whiteboard) { +purple_whiteboard_get_id(PurpleWhiteboard *whiteboard) { PurpleWhiteboardPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_WHITEBOARD(whiteboard), NULL); priv = purple_whiteboard_get_instance_private(whiteboard); - return priv->who; + return priv->id; } void @@ -296,24 +288,6 @@ purple_whiteboard_start(PurpleWhiteboard *whiteboard) { purple_whiteboard_ui_ops_create(whiteboard); } -PurpleWhiteboard * -purple_whiteboard_get_session(PurpleAccount *account, const gchar *who) { - PurpleWhiteboard *whiteboard = NULL; - PurpleWhiteboardPrivate *priv = NULL; - GList *l = NULL; - - for(l = wb_list; l != NULL; l = l->next) { - whiteboard = PURPLE_WHITEBOARD(l->data); - priv = purple_whiteboard_get_instance_private(whiteboard); - - if(priv->account == account && purple_strequal(priv->who, who)) { - return whiteboard; - } - } - - return NULL; -} - void purple_whiteboard_draw_list_destroy(GList *draw_list) { g_list_free(draw_list); @@ -491,12 +465,12 @@ purple_whiteboard_get_protocol_data(PurpleWhiteboard *whiteboard) { } PurpleWhiteboard * -purple_whiteboard_new(PurpleAccount *account, const gchar *who, gint state) { +purple_whiteboard_new(PurpleAccount *account, const gchar *id, gint state) { PurpleWhiteboard *whiteboard = NULL; PurpleProtocol *protocol = NULL; g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL); - g_return_val_if_fail(who != NULL, NULL); + g_return_val_if_fail(id != NULL, NULL); protocol = purple_account_get_protocol(account); @@ -504,12 +478,12 @@ purple_whiteboard_new(PurpleAccount *account, const gchar *who, gint state) { if(PURPLE_IS_PROTOCOL_FACTORY(protocol)) { whiteboard = purple_protocol_factory_whiteboard_new( - PURPLE_PROTOCOL_FACTORY(protocol), account, who, state); + PURPLE_PROTOCOL_FACTORY(protocol), account, id, state); } else { whiteboard = g_object_new(PURPLE_TYPE_WHITEBOARD, "account", account, - "who", who, - "state", state, + "id", id, + "state", state, NULL ); } @@ -517,3 +491,20 @@ purple_whiteboard_new(PurpleAccount *account, const gchar *who, gint state) { return whiteboard; } +gboolean +purple_whiteboard_equal(PurpleWhiteboard *whiteboard1, + PurpleWhiteboard *whiteboard2) +{ + PurpleWhiteboardPrivate *priv1 = NULL, *priv2 = NULL; + + if(whiteboard1 == NULL) { + return (whiteboard2 == NULL); + } else if(whiteboard2 == NULL) { + return FALSE; + } + + priv1 = purple_whiteboard_get_instance_private(whiteboard1); + priv2 = purple_whiteboard_get_instance_private(whiteboard2); + + return purple_strequal(priv1->id, priv2->id); +} diff --git a/libpurple/purplewhiteboard.h b/libpurple/purplewhiteboard.h index 3548a8d9fe..2a23e7f87b 100644 --- a/libpurple/purplewhiteboard.h +++ b/libpurple/purplewhiteboard.h @@ -94,14 +94,14 @@ void purple_whiteboard_set_protocol_ops(PurpleWhiteboard *whiteboard, PurpleWhit /** * purple_whiteboard_new: * @account: A #PurpleAccount instance. - * @who: Who you're drawing with. + * @id: The identifier of the whiteboard. * @state: The state. * * Creates a new whiteboard. * * Returns: (transfer full): The new #PurpleWhiteboard instance. */ -PurpleWhiteboard *purple_whiteboard_new(PurpleAccount *account, const gchar *who, gint state); +PurpleWhiteboard *purple_whiteboard_new(PurpleAccount *account, const gchar *id, gint state); /** * purple_whiteboard_get_account: @@ -114,14 +114,16 @@ PurpleWhiteboard *purple_whiteboard_new(PurpleAccount *account, const gchar *who PurpleAccount *purple_whiteboard_get_account(PurpleWhiteboard *whiteboard); /** - * purple_whiteboard_get_who: + * purple_whiteboard_get_id: * @whiteboard: The #PurpleWhiteboard instance. * - * Gets the name of who you're drawing with. + * Gets the id of @whiteboard. * - * Returns: The name of who you're drawing with. + * Returns: The id of @whiteboard. + * + * Since: 3.0.0 */ -const gchar *purple_whiteboard_get_who(PurpleWhiteboard *whiteboard); +const gchar *purple_whiteboard_get_id(PurpleWhiteboard *whiteboard); /** * purple_whiteboard_set_state: @@ -151,18 +153,6 @@ gint purple_whiteboard_get_state(PurpleWhiteboard *whiteboard); void purple_whiteboard_start(PurpleWhiteboard *whiteboard); /** - * purple_whiteboard_get_session: - * @account: A #PurpleAccount instance. - * @who: The name of the user you're drawing with. - * - * Finds a whiteboard from @account and @who. - * - * Returns: (transfer none): The #PurpleWhiteboard instance if found, otherwise - * %NULL. - */ -PurpleWhiteboard *purple_whiteboard_get_session(PurpleAccount *account, const gchar *who); - -/** * purple_whiteboard_draw_list_destroy: * @draw_list: (element-type gint): The drawing list. * @@ -313,6 +303,20 @@ void purple_whiteboard_set_protocol_data(PurpleWhiteboard *whiteboard, gpointer */ gpointer purple_whiteboard_get_protocol_data(PurpleWhiteboard *whiteboard); +/** + * purple_whiteboard_equal: + * @whiteboard1: The first #PurpleWhiteboard instance to check. + * @whiteboard2: The second #PurpleWhiteboard instance to check. + * + * Checks the id's for @whiteboard1 and @whiteboard2 and return whether or not + * they are equal. + * + * Returns: %TRUE if the id's of @whiteboard1 and @whiteboard2 are equal. + * + * Since: 3.0.0 + */ +gboolean purple_whiteboard_equal(PurpleWhiteboard *whiteboard1, PurpleWhiteboard *whiteboard2); + G_END_DECLS #endif /* PURPLE_WHITEBOARD_H */ diff --git a/libpurple/purplewhiteboardmanager.c b/libpurple/purplewhiteboardmanager.c new file mode 100644 index 0000000000..309b485a47 --- /dev/null +++ b/libpurple/purplewhiteboardmanager.c @@ -0,0 +1,269 @@ +/* + * Purple - Internet Messaging Library + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#include <glib/gi18n-lib.h> + +#include "purplewhiteboardmanager.h" +#include "purpleprivate.h" + +enum { + SIG_REGISTERED, + SIG_UNREGISTERED, + N_SIGNALS, +}; +static guint signals[N_SIGNALS] = {0, }; + +typedef struct { + GListStore *store; +} PurpleWhiteboardManagerPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE(PurpleWhiteboardManager, purple_whiteboard_manager, + G_TYPE_OBJECT); + +static PurpleWhiteboardManager *default_manager = NULL; + +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +static void +purple_whiteboard_manager_finalize(GObject *obj) { + PurpleWhiteboardManager *manager = NULL; + PurpleWhiteboardManagerPrivate *priv = NULL; + + manager = PURPLE_WHITEBOARD_MANAGER(obj); + priv = purple_whiteboard_manager_get_instance_private(manager); + + g_clear_object(&priv->store); + + G_OBJECT_CLASS(purple_whiteboard_manager_parent_class)->finalize(obj); +} + +static void +purple_whiteboard_manager_init(PurpleWhiteboardManager *manager) { + PurpleWhiteboardManagerPrivate *priv = NULL; + + priv = purple_whiteboard_manager_get_instance_private(manager); + + priv->store = g_list_store_new(PURPLE_TYPE_WHITEBOARD); +} + +static void +purple_whiteboard_manager_class_init(PurpleWhiteboardManagerClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + obj_class->finalize = purple_whiteboard_manager_finalize; + + /** + * PurpleWhiteboardManager::registered: + * @manager: The #PurpleWhiteboardManager instance. + * @whiteboard: The #PurpleWhiteboard that was registered. + * + * Emitted after @whiteboard has been registered in @manager. + * + * Since: 3.0.0 + */ + signals[SIG_REGISTERED] = g_signal_new( + "registered", + G_OBJECT_CLASS_TYPE(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(PurpleWhiteboardManagerClass, registered), + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + PURPLE_TYPE_WHITEBOARD); + + /** + * PurpleWhiteboardManager::unregistered: + * @manager: The #PurpleWhiteboardManager instance. + * @whiteboard: The #PurpleWhiteboard that was unregistered. + * + * Emitted after @whiteboard has been unregistered from @manager. + * + * Since: 3.0.0 + */ + signals[SIG_UNREGISTERED] = g_signal_new( + "unregistered", + G_OBJECT_CLASS_TYPE(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(PurpleWhiteboardManagerClass, unregistered), + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + PURPLE_TYPE_WHITEBOARD); +} + +/****************************************************************************** + * Private API + *****************************************************************************/ +void +purple_whiteboard_manager_startup(void) { + if(default_manager == NULL) { + default_manager = g_object_new(PURPLE_TYPE_WHITEBOARD_MANAGER, NULL); + } +} + +void +purple_whiteboard_manager_shutdown(void) { + g_clear_object(&default_manager); +} + +/****************************************************************************** + * Public API + *****************************************************************************/ +PurpleWhiteboardManager * +purple_whiteboard_manager_get_default(void) { + return default_manager; +} + +gboolean +purple_whiteboard_manager_register(PurpleWhiteboardManager *manager, + PurpleWhiteboard *whiteboard, + GError **error) +{ + PurpleWhiteboardManagerPrivate *priv = NULL; + gboolean found = FALSE; + + g_return_val_if_fail(PURPLE_IS_WHITEBOARD_MANAGER(manager), FALSE); + g_return_val_if_fail(PURPLE_IS_WHITEBOARD(whiteboard), FALSE); + + priv = purple_whiteboard_manager_get_instance_private(manager); + + found = g_list_store_find_with_equal_func(priv->store, whiteboard, + (GEqualFunc)purple_whiteboard_equal, + NULL); + + if(found) { + g_set_error(error, PURPLE_WHITEBOARD_MANAGER_DOMAIN, 0, + _("whiteboard %s is already registered"), + purple_whiteboard_get_id(whiteboard)); + + return FALSE; + } + + g_list_store_insert(priv->store, 0, whiteboard); + + g_signal_emit(G_OBJECT(manager), signals[SIG_REGISTERED], 0, whiteboard); + + return TRUE; +} + +gboolean +purple_whiteboard_manager_unregister(PurpleWhiteboardManager *manager, + PurpleWhiteboard *whiteboard, + GError **error) +{ + PurpleWhiteboardManagerPrivate *priv = NULL; + guint position = 0; + gboolean found = FALSE; + + g_return_val_if_fail(PURPLE_IS_WHITEBOARD_MANAGER(manager), FALSE); + g_return_val_if_fail(PURPLE_IS_WHITEBOARD(whiteboard), FALSE); + + priv = purple_whiteboard_manager_get_instance_private(manager); + + found = g_list_store_find_with_equal_func(priv->store, whiteboard, + (GEqualFunc)purple_whiteboard_equal, + &position); + + if(!found) { + g_set_error(error, PURPLE_WHITEBOARD_MANAGER_DOMAIN, 0, + _("whiteboard %s is not registered"), + purple_whiteboard_get_id(whiteboard)); + + return FALSE; + } + + /* Temporarily ref whiteboard so we can pass it along to the signal + * callbacks. + */ + g_object_ref(G_OBJECT(whiteboard)); + + g_list_store_remove(priv->store, position); + + g_signal_emit(G_OBJECT(manager), signals[SIG_UNREGISTERED], 0, whiteboard); + + g_object_unref(G_OBJECT(whiteboard)); + + return TRUE; +} + +PurpleWhiteboard * +purple_whiteboard_manager_find(PurpleWhiteboardManager *manager, + const gchar *id) +{ + PurpleWhiteboardManagerPrivate *priv = NULL; + guint idx, n; + + g_return_val_if_fail(PURPLE_IS_WHITEBOARD_MANAGER(manager), NULL); + g_return_val_if_fail(id != NULL, NULL); + + priv = purple_whiteboard_manager_get_instance_private(manager); + + n = g_list_model_get_n_items(G_LIST_MODEL(priv->store)); + for(idx = 0; idx < n; idx++) { + GObject *obj = NULL; + + obj = g_list_model_get_object(G_LIST_MODEL(priv->store), idx); + if(PURPLE_IS_WHITEBOARD(obj)) { + PurpleWhiteboard *whiteboard = PURPLE_WHITEBOARD(obj); + + if(purple_strequal(id, purple_whiteboard_get_id(whiteboard))) { + return whiteboard; + } + } + g_clear_object(&obj); + } + + return NULL; +} + +void +purple_whiteboard_manager_foreach(PurpleWhiteboardManager *manager, + PurpleWhiteboardManagerForeachFunc func, + gpointer data) +{ + PurpleWhiteboardManagerPrivate *priv = NULL; + guint idx, n; + + g_return_if_fail(PURPLE_IS_WHITEBOARD_MANAGER(manager)); + g_return_if_fail(func != NULL); + + priv = purple_whiteboard_manager_get_instance_private(manager); + + n = g_list_model_get_n_items(G_LIST_MODEL(priv->store)); + for(idx = 0; idx < n; idx++) { + gpointer item = g_list_model_get_item(G_LIST_MODEL(priv->store), idx); + func(item, data); + g_object_unref(item); + } +} + +GListModel * +purple_whiteboard_manager_get_model(PurpleWhiteboardManager *manager) { + PurpleWhiteboardManagerPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_WHITEBOARD_MANAGER(manager), NULL); + + priv = purple_whiteboard_manager_get_instance_private(manager); + + return G_LIST_MODEL(priv->store); +} diff --git a/libpurple/purplewhiteboardmanager.h b/libpurple/purplewhiteboardmanager.h new file mode 100644 index 0000000000..c2ebe89363 --- /dev/null +++ b/libpurple/purplewhiteboardmanager.h @@ -0,0 +1,193 @@ +/* + * Purple - Internet Messaging Library + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION) +# error "only <pidgin.h> may be included directly" +#endif + +#ifndef PURPLE_WHITEBOARD_MANAGER_H +#define PURPLE_WHITEBOARD_MANAGER_H + +#include <glib.h> +#include <glib-object.h> + +#include <libpurple/purplewhiteboard.h> + +G_BEGIN_DECLS + +/** + * SECTION:purplewhiteboardmanager + * @section_id: libpurple-purplewhiteboardmanager + * @title: Purple Whiteboard Manager + * @short_description: Management of whiteboards. + * + * #PurpleWhiteboardManager keeps track of all whiteboards and emits signals + * when whiteboards are registered and unregistered. + */ + +/** + * PURPLE_WHITEBOARD_MANAGER_DOMAIN: + * + * A #GError domain for errors from #PurpleWhiteboardManager. + * + * Since: 3.0.0 + */ +#define PURPLE_WHITEBOARD_MANAGER_DOMAIN (g_quark_from_static_string("purple-whiteboard-manager")) + +/** + * PURPLE_TYPE_WHITEBOARD_MANAGER: + * + * The standard _TYPE_ macro for #PurpleWhiteboardManager. + * + * Since: 3.0.0 + */ +#define PURPLE_TYPE_WHITEBOARD_MANAGER (purple_whiteboard_manager_get_type()) + +/** + * purple_whiteboard_manager_get_type: + * + * The standard _get_type macro for #PurpleWhiteboardManager. + * + * Since: 3.0.0 + */ + +/** + * PurpleWhiteboardManager: + * + * An opaque data structure that manages whiteboards. + * + * Since: 3.0.0 + */ +G_DECLARE_DERIVABLE_TYPE(PurpleWhiteboardManager, purple_whiteboard_manager, + PURPLE, WHITEBOARD_MANAGER, GObject) + +/** + * PurpleWhiteboardManagerClass: + * @registered: The default signal handler for when a whiteboard is registered. + * @unregistered: The default signal handler for when a whiteboard is + * unregistered. + * + * The class structure for #PurpleWhiteboardManager. + * + * Since: 3.0.0 + */ +struct _PurpleWhiteboardManagerClass { + /*< private >*/ + GObjectClass parent; + + /*< public >*/ + void (*registered)(PurpleWhiteboardManager *manager, PurpleWhiteboard *whiteboard); + void (*unregistered)(PurpleWhiteboardManager *manager, PurpleWhiteboard *whiteboard); + + /*< private >*/ + gpointer reserved[4]; +}; + +/** + * PurpleWhiteboardManagerForeachFunc: + * @whiteboard: The #PurpleWhiteboard instance. + * @data: User supplied data. + * + * A function to be used as a callback with purple_whiteboard_manager_foreach(). + * + * Since: 3.0.0 + */ +typedef void (*PurpleWhiteboardManagerForeachFunc)(PurpleWhiteboard *whiteboard, gpointer data); + +/** + * purple_whiteboard_manager_get_default: + * + * Gets the default #PurpleWhiteboardManager instance. + * + * Returns: (transfer none): The default #PurpleWhiteboardManager instance. + * + * Since: 3.0.0 + */ +PurpleWhiteboardManager *purple_whiteboard_manager_get_default(void); + +/** + * purple_whiteboard_manager_register: + * @manager: The #PurpleWhiteboardManager instance. + * @whiteboard: The #PurpleWhiteboard to register. + * @error: (out) (optional) (nullable): A return address for a #GError. + * + * Registers @whiteboard with @manager. + * + * Returns: %TRUE if @whiteboard was successfully registered with @manager, + * %FALSE otherwise. + * + * Since: 3.0.0 + */ +gboolean purple_whiteboard_manager_register(PurpleWhiteboardManager *manager, PurpleWhiteboard *whiteboard, GError **error); + +/** + * purple_whiteboard_manager_unregister: + * @manager: The #PurpleWhiteboardManager instance. + * @whiteboard: The #PurpleWhiteboard to unregister. + * @error: (out) (optional) (nullable): A return address for a #GError. + * + * Unregisters @whiteboard from @manager. + * + * Returns: %TRUE if @whiteboard was successfully unregistered from @manager, + * %FALSE otherwise. + * + * Since: 3.0.0 + */ +gboolean purple_whiteboard_manager_unregister(PurpleWhiteboardManager *manager, PurpleWhiteboard *whiteboard, GError **error); + +/** + * purple_whiteboard_manager_find: + * @manager: The #PurpleWhiteboardManager instance. + * @id: The id of the #PurpleWhiteboard to find. + * + * Gets the #PurpleWhiteboard identified by @id if found, otherwise %NULL. + * + * Returns: (transfer full): The #PurpleWhiteboard identified by @id or %NULL. + * + * Since: 3.0.0 + */ +PurpleWhiteboard *purple_whiteboard_manager_find(PurpleWhiteboardManager *manager, const gchar *id); + +/** + * purple_whiteboard_manager_foreach: + * @manager: The #PurpleWhiteboardManager instance. + * @func: (scope call): The #PurpleWhiteboardManagerForeachFunc to call. + * @data: User data to pass to @func. + * + * Calls @func for each #PurpleWhiteboard that @manager knows about. + * + * Since: 3.0.0 + */ +void purple_whiteboard_manager_foreach(PurpleWhiteboardManager *manager, PurpleWhiteboardManagerForeachFunc func, gpointer data); + +/** + * purple_whiteboard_manager_get_model: + * @manager: The #PurpleWhiteboardManager instance. + * + * Gets the backing model of @manager as a #GListModel. + * + * Returns: (transfer none) (element-type PurpleWhiteboard): The #GListModel + * containing all of the #PurpleWhiteboards registered with @manager. + * + * Since: 3.0.0 + */ +GListModel *purple_whiteboard_manager_get_model(PurpleWhiteboardManager *manager); + +G_END_DECLS + +#endif /* PURPLE_WHITEBOARD_MANAGER_H */ diff --git a/libpurple/tests/meson.build b/libpurple/tests/meson.build index 98ec189030..7757242cc1 100644 --- a/libpurple/tests/meson.build +++ b/libpurple/tests/meson.build @@ -13,7 +13,8 @@ PROGS = [ 'queued_output_stream', 'trie', 'util', - 'xmlnode' + 'whiteboard_manager', + 'xmlnode', ] test_ui = static_library( diff --git a/libpurple/tests/test_whiteboard_manager.c b/libpurple/tests/test_whiteboard_manager.c new file mode 100644 index 0000000000..3a6ddb19d6 --- /dev/null +++ b/libpurple/tests/test_whiteboard_manager.c @@ -0,0 +1,54 @@ +/* + * Purple - Internet Messaging Library + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <https://www.gnu.org/licenses/>. + */ + +#include <glib.h> + +#include <purple.h> + +#include "test_ui.h" + +/****************************************************************************** + * Tests + *****************************************************************************/ +static void +test_purple_whiteboard_manager_get_default(void) { + PurpleWhiteboardManager *manager1 = NULL, *manager2 = NULL; + + manager1 = purple_whiteboard_manager_get_default(); + g_assert_true(PURPLE_IS_WHITEBOARD_MANAGER(manager1)); + + manager2 = purple_whiteboard_manager_get_default(); + g_assert_true(PURPLE_IS_WHITEBOARD_MANAGER(manager2)); + + g_assert_true(manager1 == manager2); +} + +/****************************************************************************** + * Main + *****************************************************************************/ +gint +main(gint argc, gchar *argv[]) { + g_test_init(&argc, &argv, NULL); + + test_ui_purple_init(); + + g_test_add_func("/whiteboard-manager/get-default", + test_purple_whiteboard_manager_get_default); + + return g_test_run(); +} diff --git a/meson.build b/meson.build index 99d3137b3b..3e3ea58aff 100644 --- a/meson.build +++ b/meson.build @@ -230,7 +230,7 @@ endif # ####################################################################### # # Check for GLib 2.44 (required) # ####################################################################### -glib = dependency('glib-2.0', version : '>= 2.52.0') +glib = dependency('glib-2.0', version : '>= 2.64.0') gio = dependency('gio-2.0') gobject = dependency('gobject-2.0') gthread = dependency('gthread-2.0') diff --git a/pidgin/gtkwhiteboard.c b/pidgin/gtkwhiteboard.c index 169f6e27e0..8450cfaac5 100644 --- a/pidgin/gtkwhiteboard.c +++ b/pidgin/gtkwhiteboard.c @@ -588,13 +588,13 @@ pidgin_whiteboard_create(PurpleWhiteboard *wb) * their username */ buddy = purple_blist_find_buddy(purple_whiteboard_get_account(wb), - purple_whiteboard_get_who(wb)); + purple_whiteboard_get_id(wb)); gtk_window_set_title(GTK_WINDOW(gtkwb), buddy != NULL ? purple_buddy_get_contact_alias(buddy) - : purple_whiteboard_get_who(wb)); - gtk_widget_set_name(GTK_WIDGET(gtkwb), purple_whiteboard_get_who(wb)); + : purple_whiteboard_get_id(wb)); + gtk_widget_set_name(GTK_WIDGET(gtkwb), purple_whiteboard_get_id(wb)); gtk_widget_set_size_request(GTK_WIDGET(gtkwb->drawing_area), gtkwb->width, gtkwb->height); diff --git a/po/POTFILES.in b/po/POTFILES.in index caeda38cd3..ccf3545fa9 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -268,6 +268,7 @@ libpurple/purpleprotocolroomlist.c libpurple/purpleprotocolserver.c libpurple/purpleuiinfo.c libpurple/purplewhiteboard.c +libpurple/purplewhiteboardmanager.c libpurple/purplewhiteboarduiops.c libpurple/queuedoutputstream.c libpurple/request.c |