pidgin/pidgin

Convert XmppDiscoService into a GObject

15 months ago, Elliott Sales de Andrade
af20db93f2c2
Parents 941734e74261
Children ecb08d1c66eb
Convert XmppDiscoService into a GObject

This will enable porting things to binding/expression lookup.

I probably didn't _really_ need to make everything properties, but that was easier to do than figure out which ones would really be needed.

Testing Done:
Ran discovery on `pidgin.im`; saw `conference.pidgin.im` show up, then expanded it and the various rooms appeared, as they should. Clicked Add on a few and verified that the Add Chat dialog appeared with the correct values.

Reviewed at https://reviews.imfreedom.org/r/2210/
--- a/pidgin/plugins/disco/gtkdisco.c Mon Jan 23 23:27:47 2023 -0600
+++ b/pidgin/plugins/disco/gtkdisco.c Tue Jan 24 15:40:35 2023 -0600
@@ -103,26 +103,6 @@
}
}
-static char *
-pidgin_disco_get_icon_name(XmppDiscoService *service)
-{
- char *icon_name = NULL;
-
- g_return_val_if_fail(service != NULL, NULL);
-
- if (service->type == XMPP_DISCO_SERVICE_TYPE_GATEWAY && service->gateway_type) {
- icon_name = g_strconcat("im-", service->gateway_type, NULL);
-#if 0
- } else if (service->type == XMPP_DISCO_SERVICE_TYPE_USER) {
- icon_name = g_strdup("person");
-#endif
- } else if (service->type == XMPP_DISCO_SERVICE_TYPE_CHAT) {
- icon_name = g_strdup("chat");
- }
-
- return icon_name;
-}
-
static void
dialog_select_account_cb(GObject *obj, G_GNUC_UNUSED GParamSpec *pspec,
gpointer data)
@@ -146,9 +126,9 @@
PidginDiscoDialog *dialog = data;
XmppDiscoService *service = dialog->selected;
- g_return_if_fail(service != NULL);
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
- xmpp_disco_service_register(service);
+ xmpp_disco_register_service(service);
}
static void discolist_cancel_cb(PidginDiscoList *pdl, const char *server)
@@ -248,15 +228,17 @@
{
PidginDiscoDialog *dialog = data;
XmppDiscoService *service = dialog->selected;
+ PidginDiscoList *list = NULL;
PurpleAccount *account;
const char *jid;
- g_return_if_fail(service != NULL);
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
- account = purple_connection_get_account(service->list->pc);
- jid = service->jid;
+ list = xmpp_disco_service_get_list(service);
+ account = purple_connection_get_account(list->pc);
+ jid = xmpp_disco_service_get_jid(service);
- if (service->type == XMPP_DISCO_SERVICE_TYPE_CHAT) {
+ if(xmpp_disco_service_get_service_type(service) == XMPP_DISCO_SERVICE_TYPE_CHAT) {
purple_blist_request_add_chat(account, NULL, NULL, jid);
} else {
purple_blist_request_add_buddy(account, jid, NULL, NULL);
@@ -318,8 +300,9 @@
SERVICE_COLUMN, &val);
dialog->selected = g_value_get_pointer(&val);
if (dialog->selected != NULL) {
- allow_add = (dialog->selected->flags & XMPP_DISCO_ADD);
- allow_register = (dialog->selected->flags & XMPP_DISCO_REGISTER);
+ XmppDiscoServiceFlags flags = xmpp_disco_service_get_flags(dialog->selected);
+ allow_add = (flags & XMPP_DISCO_ADD) != 0;
+ allow_register = (flags & XMPP_DISCO_REGISTER) != 0;
}
}
@@ -351,6 +334,7 @@
PidginDiscoDialog *dialog = user_data;
GtkTreeIter iter;
XmppDiscoService *service;
+ XmppDiscoServiceFlags flags;
GValue val;
if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter, path)) {
@@ -362,15 +346,16 @@
SERVICE_COLUMN, &val);
service = g_value_get_pointer(&val);
- if (service->flags & XMPP_DISCO_BROWSE) {
+ flags = xmpp_disco_service_get_flags(service);
+ if((flags & XMPP_DISCO_BROWSE) != 0) {
if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(dialog->tree), path)) {
gtk_tree_view_collapse_row(GTK_TREE_VIEW(dialog->tree), path);
} else {
gtk_tree_view_expand_row(GTK_TREE_VIEW(dialog->tree), path, FALSE);
}
- } else if (service->flags & XMPP_DISCO_REGISTER) {
+ } else if((flags & XMPP_DISCO_REGISTER) != 0) {
g_action_activate(G_ACTION(dialog->register_action), NULL);
- } else if (service->flags & XMPP_DISCO_ADD) {
+ } else if((flags & XMPP_DISCO_ADD) != 0) {
g_action_activate(G_ACTION(dialog->add_action), NULL);
}
}
@@ -452,7 +437,7 @@
return FALSE;
}
- switch (service->type) {
+ switch(xmpp_disco_service_get_service_type(service)) {
case XMPP_DISCO_SERVICE_TYPE_UNSET:
type = _("Unknown");
break;
@@ -482,16 +467,17 @@
break;
}
- name = g_markup_escape_text(service->name, -1);
- jid = g_markup_escape_text(service->jid, -1);
- if (service->description != NULL) {
- desc = g_markup_escape_text(service->description, -1);
+ name = g_markup_escape_text(xmpp_disco_service_get_name(service), -1);
+ jid = g_markup_escape_text(xmpp_disco_service_get_jid(service), -1);
+ if(xmpp_disco_service_get_description(service) != NULL) {
+ desc = g_markup_escape_text(xmpp_disco_service_get_description(service),
+ -1);
}
markup = g_strdup_printf("<span size='x-large' weight='bold'>%s</span>\n<b>%s:</b> %s%s%s",
name, type, jid,
- service->description ? _("\n<b>Description:</b> ") : "",
- service->description ? desc : "");
+ desc != NULL ? _("\n<b>Description:</b> ") : "",
+ desc != NULL ? desc : "");
gtk_tooltip_set_markup(tooltip, markup);
gtk_tree_view_set_tooltip_row(GTK_TREE_VIEW(widget), tooltip, path);
@@ -663,10 +649,11 @@
g_return_if_fail(dialog != NULL);
if (service != NULL) {
- purple_debug_info("xmppdisco", "Adding service \"%s\"", service->name);
+ purple_debug_info("xmppdisco", "Adding service \"%s\"",
+ xmpp_disco_service_get_name(service));
} else {
purple_debug_info("xmppdisco", "Service \"%s\" has no children",
- parent->name);
+ xmpp_disco_service_get_name(parent));
}
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(dialog->progress));
@@ -710,7 +697,7 @@
iter = child;
}
- if (service->flags & XMPP_DISCO_BROWSE) {
+ if((xmpp_disco_service_get_flags(service) & XMPP_DISCO_BROWSE) != 0) {
GtkTreeRowReference *rr;
GtkTreePath *path;
@@ -724,11 +711,12 @@
gtk_tree_path_free(path);
}
- icon_name = pidgin_disco_get_icon_name(service);
+ icon_name = xmpp_disco_service_get_icon_name(service);
gtk_tree_store_set(dialog->model, &iter, ICON_NAME_COLUMN, icon_name,
- NAME_COLUMN, service->name, DESCRIPTION_COLUMN,
- service->description, SERVICE_COLUMN, service, -1);
+ NAME_COLUMN, xmpp_disco_service_get_name(service),
+ DESCRIPTION_COLUMN, xmpp_disco_service_get_description(service),
+ SERVICE_COLUMN, service, -1);
g_free(icon_name);
}
--- a/pidgin/plugins/disco/meson.build Mon Jan 23 23:27:47 2023 -0600
+++ b/pidgin/plugins/disco/meson.build Tue Jan 24 15:40:35 2023 -0600
@@ -1,17 +1,28 @@
xmppdisco_SOURCES = [
'gtkdisco.c',
+ 'xmppdisco.c',
+ 'xmppdiscoservice.c',
+]
+
+xmppdisco_HEADERS = [
'gtkdisco.h',
- 'xmppdisco.c',
- 'xmppdisco.h'
+ 'xmppdisco.h',
+ 'xmppdiscoservice.h',
]
+xmppdisco_enums = gnome.mkenums_simple('xmppdiscoenums',
+ sources: xmppdisco_HEADERS,
+ identifier_prefix: 'XmppDisco',
+ symbol_prefix: 'xmpp_disco')
+xmppdisco_SOURCES += xmppdisco_enums
+
xmppdisco_resource = gnome.compile_resources('xmppdiscoresources',
'resources/xmppdisco.gresource.xml',
source_dir : 'resources',
c_name : 'xmppdisco')
xmppdisco_SOURCES += xmppdisco_resource
-xmppdisco = library('xmppdisco', xmppdisco_SOURCES,
+xmppdisco = library('xmppdisco', xmppdisco_SOURCES, xmppdisco_HEADERS,
c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PidginPlugin-XMPPDisco"'],
dependencies : [libpurple_dep, libpidgin_dep, glib],
name_prefix : '',
--- a/pidgin/plugins/disco/xmppdisco.c Mon Jan 23 23:27:47 2023 -0600
+++ b/pidgin/plugins/disco/xmppdisco.c Tue Jan 24 15:40:35 2023 -0600
@@ -297,48 +297,47 @@
if (purple_strequal(type, "result") &&
(query = purple_xmlnode_get_child(iq, "query"))) {
PurpleXmlNode *identity = purple_xmlnode_get_child(query, "identity");
- XmppDiscoService *service;
+ XmppDiscoService *service = NULL;
PurpleXmlNode *feature;
- service = g_new0(XmppDiscoService, 1);
- service->list = item_data->list;
- purple_debug_info("xmppdisco", "parent for %s is %p\n", from, item_data->parent);
- service->parent = item_data->parent;
- service->flags = 0;
- service->type = disco_service_type_from_identity(identity);
+ service = xmpp_disco_service_new(item_data->list);
+ purple_debug_info("xmppdisco", "parent for %s is %p", from, item_data->parent);
+ xmpp_disco_service_set_service_type(service,
+ disco_service_type_from_identity(identity));
if (item_data->node) {
if (item_data->name) {
- service->name = item_data->name;
- item_data->name = NULL;
+ xmpp_disco_service_set_name(service, item_data->name);
+ g_clear_pointer(&item_data->name, g_free);
} else {
- service->name = g_strdup(item_data->node);
+ xmpp_disco_service_set_name(service, item_data->node);
}
- service->node = item_data->node;
- item_data->node = NULL;
+ xmpp_disco_service_set_node(service, item_data->node);
+ g_clear_pointer(&item_data->node, g_free);
- if (service->type == XMPP_DISCO_SERVICE_TYPE_PUBSUB_COLLECTION) {
- service->flags |= XMPP_DISCO_BROWSE;
+ if(xmpp_disco_service_get_service_type(service) == XMPP_DISCO_SERVICE_TYPE_PUBSUB_COLLECTION) {
+ xmpp_disco_service_add_flags(service, XMPP_DISCO_BROWSE);
}
} else {
- service->name = g_strdup(from);
+ xmpp_disco_service_set_name(service, from);
}
- if (!service->node) {
+ if(!xmpp_disco_service_get_node(service)) {
/* Only support adding JIDs, not JID+node combos */
- service->flags |= XMPP_DISCO_ADD;
+ xmpp_disco_service_add_flags(service, XMPP_DISCO_ADD);
}
if (item_data->name) {
- service->description = item_data->name;
- item_data->name = NULL;
+ xmpp_disco_service_set_description(service, item_data->name);
+ g_clear_pointer(&item_data->name, g_free);
} else if (identity) {
- service->description = g_strdup(purple_xmlnode_get_attrib(identity, "name"));
+ xmpp_disco_service_set_description(service,
+ purple_xmlnode_get_attrib(identity, "name"));
}
/* TODO: Overlap with service->name a bit */
- service->jid = g_strdup(from);
+ xmpp_disco_service_set_jid(service, from);
for (feature = purple_xmlnode_get_child(query, "feature"); feature;
feature = purple_xmlnode_get_next_twin(feature)) {
@@ -348,21 +347,23 @@
}
if (purple_strequal(var, NS_REGISTER)) {
- service->flags |= XMPP_DISCO_REGISTER;
+ xmpp_disco_service_add_flags(service, XMPP_DISCO_REGISTER);
} else if (purple_strequal(var, NS_DISCO_ITEMS)) {
- service->flags |= XMPP_DISCO_BROWSE;
+ xmpp_disco_service_add_flags(service, XMPP_DISCO_BROWSE);
} else if (purple_strequal(var, NS_MUC)) {
- service->flags |= XMPP_DISCO_BROWSE;
- service->type = XMPP_DISCO_SERVICE_TYPE_CHAT;
+ xmpp_disco_service_add_flags(service, XMPP_DISCO_BROWSE);
+ xmpp_disco_service_set_service_type(service,
+ XMPP_DISCO_SERVICE_TYPE_CHAT);
}
}
- if (service->type == XMPP_DISCO_SERVICE_TYPE_GATEWAY) {
- service->gateway_type = g_strdup(disco_type_from_string(
+ if(xmpp_disco_service_get_service_type(service) == XMPP_DISCO_SERVICE_TYPE_GATEWAY) {
+ xmpp_disco_service_set_gateway_type(service,
+ disco_type_from_string(
purple_xmlnode_get_attrib(identity, "type")));
}
- pidgin_disco_add_service(list, service, service->parent);
+ pidgin_disco_add_service(list, service, item_data->parent);
}
out:
@@ -403,7 +404,7 @@
has_items = TRUE;
- if (item_data->parent->type == XMPP_DISCO_SERVICE_TYPE_CHAT) {
+ if(xmpp_disco_service_get_service_type(item_data->parent) == XMPP_DISCO_SERVICE_TYPE_CHAT) {
/* This is a hacky first-order approximation. Any MUC
* component that has a >1 level hierarchy (a Yahoo MUC
* transport component probably does) will violate this.
@@ -411,18 +412,18 @@
* On the other hand, this is better than querying all the
* chats at conference.jabber.org to enumerate them.
*/
- XmppDiscoService *service = g_new0(XmppDiscoService, 1);
- service->list = item_data->list;
- service->parent = item_data->parent;
- service->flags = XMPP_DISCO_ADD;
- service->type = XMPP_DISCO_SERVICE_TYPE_CHAT;
+ XmppDiscoService *service = xmpp_disco_service_new(item_data->list);
+ xmpp_disco_service_set_flags(service, XMPP_DISCO_ADD);
+ xmpp_disco_service_set_service_type(service,
+ XMPP_DISCO_SERVICE_TYPE_CHAT);
- service->name = g_strdup(name);
- service->jid = g_strdup(jid);
- service->node = g_strdup(node);
- if (service->name == NULL) {
- service->name = g_strdup(jid);
+ if(name != NULL) {
+ xmpp_disco_service_set_name(service, name);
+ } else {
+ xmpp_disco_service_set_name(service, jid);
}
+ xmpp_disco_service_set_jid(service, jid);
+ xmpp_disco_service_set_node(service, node);
pidgin_disco_add_service(list, service, item_data->parent);
} else {
struct item_data *item_data2 = g_new0(struct item_data, 1);
@@ -567,43 +568,51 @@
void xmpp_disco_service_expand(XmppDiscoService *service)
{
+ PidginDiscoList *list = NULL;
struct item_data *item_data;
- g_return_if_fail(service != NULL);
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
- if (service->expanded) {
+ if(xmpp_disco_service_get_expanded(service)) {
return;
}
+ list = xmpp_disco_service_get_list(service);
+
item_data = g_new0(struct item_data, 1);
- item_data->list = service->list;
+ item_data->list = list;
item_data->parent = service;
- ++service->list->fetch_count;
- pidgin_disco_list_ref(service->list);
+ ++list->fetch_count;
+ pidgin_disco_list_ref(list);
+
+ pidgin_disco_list_set_in_progress(list, TRUE);
- pidgin_disco_list_set_in_progress(service->list, TRUE);
-
- xmpp_disco_items_do(service->list->pc, item_data, service->jid, service->node,
+ xmpp_disco_items_do(list->pc, item_data,
+ xmpp_disco_service_get_jid(service),
+ xmpp_disco_service_get_node(service),
got_items_cb);
- service->expanded = TRUE;
+ xmpp_disco_service_set_expanded(service, TRUE);
}
-void xmpp_disco_service_register(XmppDiscoService *service)
+void
+xmpp_disco_register_service(XmppDiscoService *service)
{
+ PidginDiscoList *list = NULL;
PurpleXmlNode *iq, *query;
char *id = generate_next_id();
iq = purple_xmlnode_new("iq");
purple_xmlnode_set_attrib(iq, "type", "get");
- purple_xmlnode_set_attrib(iq, "to", service->jid);
+ purple_xmlnode_set_attrib(iq, "to", xmpp_disco_service_get_jid(service));
purple_xmlnode_set_attrib(iq, "id", id);
query = purple_xmlnode_new_child(iq, "query");
purple_xmlnode_set_namespace(query, NS_REGISTER);
- purple_signal_emit(purple_connection_get_protocol(service->list->pc),
- "jabber-sending-xmlnode", service->list->pc, &iq);
+ list = xmpp_disco_service_get_list(service);
+ purple_signal_emit(purple_connection_get_protocol(list->pc),
+ "jabber-sending-xmlnode", list->pc, &iq);
if (iq != NULL) {
purple_xmlnode_free(iq);
}
@@ -684,6 +693,7 @@
return FALSE;
}
+ xmpp_disco_service_register(plugin);
pidgin_disco_dialog_register(plugin);
purple_signal_connect(purple_connections_get_handle(), "signing-off",
--- a/pidgin/plugins/disco/xmppdisco.h Mon Jan 23 23:27:47 2023 -0600
+++ b/pidgin/plugins/disco/xmppdisco.h Tue Jan 24 15:40:35 2023 -0600
@@ -22,8 +22,7 @@
#ifndef PIDGIN_XMPP_DISCO_H
#define PIDGIN_XMPP_DISCO_H
-typedef struct _XmppDiscoService XmppDiscoService;
-
+#include "xmppdiscoservice.h"
#include "gtkdisco.h"
#define XMPP_PROTOCOL_ID "prpl-jabber"
@@ -38,73 +37,9 @@
#include <purple.h>
extern PurplePlugin *my_plugin;
-/**
- * The types of services.
- */
-typedef enum
-{
- XMPP_DISCO_SERVICE_TYPE_UNSET,
- /**
- * A registerable gateway to another protocol. An example would be
- * XMPP legacy transports.
- */
- XMPP_DISCO_SERVICE_TYPE_GATEWAY,
-
- /**
- * A directory (e.g. allows the user to search for other users).
- */
- XMPP_DISCO_SERVICE_TYPE_DIRECTORY,
-
- /**
- * A chat (multi-user conversation).
- */
- XMPP_DISCO_SERVICE_TYPE_CHAT,
-
- /**
- * A pubsub collection (contains nodes)
- */
- XMPP_DISCO_SERVICE_TYPE_PUBSUB_COLLECTION,
-
- /**
- * A pubsub leaf (contains stuff, not nodes).
- */
- XMPP_DISCO_SERVICE_TYPE_PUBSUB_LEAF,
-
- /**
- * Something else. Do we need more categories?
- */
- XMPP_DISCO_SERVICE_TYPE_OTHER
-} XmppDiscoServiceType;
-
-/**
- * The flags of services.
- */
-typedef enum
-{
- XMPP_DISCO_NONE = 0x0000,
- XMPP_DISCO_ADD = 0x0001, /**< Supports an 'add' operation */
- XMPP_DISCO_BROWSE = 0x0002, /**< Supports browsing */
- XMPP_DISCO_REGISTER = 0x0004 /**< Supports a 'register' operation */
-} XmppDiscoServiceFlags;
-
-struct _XmppDiscoService {
- PidginDiscoList *list;
- gchar *name;
- gchar *description;
-
- gchar *gateway_type;
- XmppDiscoServiceType type;
- XmppDiscoServiceFlags flags;
-
- XmppDiscoService *parent;
- gchar *jid;
- gchar *node;
- gboolean expanded;
-};
-
void xmpp_disco_start(PidginDiscoList *list);
void xmpp_disco_service_expand(XmppDiscoService *service);
-void xmpp_disco_service_register(XmppDiscoService *service);
+void xmpp_disco_register_service(XmppDiscoService *service);
#endif /* PIDGIN_XMPP_DISCO_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/disco/xmppdiscoservice.c Tue Jan 24 15:40:35 2023 -0600
@@ -0,0 +1,467 @@
+/*
+ * Purple - XMPP Service Disco Browser
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * 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 "xmppdiscoservice.h"
+#include "xmppdiscoenums.h"
+
+struct _XmppDiscoService {
+ GObject parent;
+
+ PidginDiscoList *list;
+ char *name;
+ char *description;
+
+ char *gateway_type;
+ XmppDiscoServiceType type;
+ XmppDiscoServiceFlags flags;
+
+ char *jid;
+ char *node;
+ gboolean expanded;
+};
+
+enum {
+ PROP_0,
+ PROP_LIST,
+ PROP_NAME,
+ PROP_DESCRIPTION,
+ PROP_SERVICE_TYPE,
+ PROP_GATEWAY_TYPE,
+ PROP_FLAGS,
+ PROP_JID,
+ PROP_NODE,
+ PROP_EXPANDED,
+ PROP_ICON_NAME,
+ PROP_LAST
+};
+
+static GParamSpec *properties[PROP_LAST] = {NULL};
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+xmpp_disco_service_set_list(XmppDiscoService *service, PidginDiscoList *list) {
+ service->list = list;
+
+ g_object_notify_by_pspec(G_OBJECT(service), properties[PROP_LIST]);
+}
+
+/******************************************************************************
+ * GObject implementation
+ *****************************************************************************/
+G_DEFINE_DYNAMIC_TYPE(XmppDiscoService, xmpp_disco_service, G_TYPE_OBJECT)
+
+static void
+xmpp_disco_service_get_property(GObject *object, guint prop_id, GValue *value,
+ GParamSpec *pspec)
+{
+ XmppDiscoService *service = XMPP_DISCO_SERVICE(object);
+
+ switch(prop_id) {
+ case PROP_LIST:
+ g_value_set_pointer(value, xmpp_disco_service_get_list(service));
+ break;
+ case PROP_NAME:
+ g_value_set_string(value, xmpp_disco_service_get_name(service));
+ break;
+ case PROP_DESCRIPTION:
+ g_value_set_string(value,
+ xmpp_disco_service_get_description(service));
+ break;
+ case PROP_SERVICE_TYPE:
+ g_value_set_enum(value,
+ xmpp_disco_service_get_service_type(service));
+ break;
+ case PROP_GATEWAY_TYPE:
+ g_value_set_string(value,
+ xmpp_disco_service_get_gateway_type(service));
+ break;
+ case PROP_FLAGS:
+ g_value_set_flags(value, xmpp_disco_service_get_flags(service));
+ break;
+ case PROP_JID:
+ g_value_set_string(value, xmpp_disco_service_get_jid(service));
+ break;
+ case PROP_NODE:
+ g_value_set_string(value, xmpp_disco_service_get_node(service));
+ break;
+ case PROP_EXPANDED:
+ g_value_set_boolean(value,
+ xmpp_disco_service_get_expanded(service));
+ break;
+ case PROP_ICON_NAME:
+ g_value_take_string(value,
+ xmpp_disco_service_get_icon_name(service));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+xmpp_disco_service_set_property(GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ XmppDiscoService *service = XMPP_DISCO_SERVICE(object);
+
+ switch(prop_id) {
+ case PROP_LIST:
+ xmpp_disco_service_set_list(service, g_value_get_pointer(value));
+ break;
+ case PROP_NAME:
+ xmpp_disco_service_set_name(service, g_value_get_string(value));
+ break;
+ case PROP_DESCRIPTION:
+ xmpp_disco_service_set_description(service,
+ g_value_get_string(value));
+ break;
+ case PROP_SERVICE_TYPE:
+ xmpp_disco_service_set_service_type(service,
+ g_value_get_enum(value));
+ break;
+ case PROP_GATEWAY_TYPE:
+ xmpp_disco_service_set_gateway_type(service,
+ g_value_get_string(value));
+ break;
+ case PROP_FLAGS:
+ xmpp_disco_service_set_flags(service, g_value_get_flags(value));
+ break;
+ case PROP_JID:
+ xmpp_disco_service_set_jid(service, g_value_get_string(value));
+ break;
+ case PROP_NODE:
+ xmpp_disco_service_set_node(service, g_value_get_string(value));
+ break;
+ case PROP_EXPANDED:
+ xmpp_disco_service_set_expanded(service,
+ g_value_get_boolean(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+xmpp_disco_service_finalize(GObject *obj) {
+ XmppDiscoService *service = XMPP_DISCO_SERVICE(obj);
+
+ g_clear_pointer(&service->name, g_free);
+ g_clear_pointer(&service->description, g_free);
+ g_clear_pointer(&service->gateway_type, g_free);
+ g_clear_pointer(&service->jid, g_free);
+ g_clear_pointer(&service->node, g_free);
+
+ G_OBJECT_CLASS(xmpp_disco_service_parent_class)->finalize(obj);
+}
+
+static void
+xmpp_disco_service_class_init(XmppDiscoServiceClass *klass)
+{
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ /* Properties */
+ obj_class->get_property = xmpp_disco_service_get_property;
+ obj_class->set_property = xmpp_disco_service_set_property;
+ obj_class->finalize = xmpp_disco_service_finalize;
+
+ properties[PROP_LIST] = g_param_spec_pointer(
+ "list", "list", "The list displaying this service.",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_NAME] = g_param_spec_string(
+ "name", "name", "The name of this service.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_DESCRIPTION] = g_param_spec_string(
+ "description", "description", "The description of this service.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_SERVICE_TYPE] = g_param_spec_enum(
+ "service-type", "service-type", "The service type of this service.",
+ XMPP_DISCO_TYPE_SERVICE_TYPE, XMPP_DISCO_SERVICE_TYPE_UNSET,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_GATEWAY_TYPE] = g_param_spec_string(
+ "gateway-type", "gateway-type", "The gateway type of this service.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_FLAGS] = g_param_spec_flags(
+ "flags", "flags", "The flags of this service.",
+ XMPP_DISCO_TYPE_SERVICE_FLAGS, XMPP_DISCO_NONE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_JID] = g_param_spec_string(
+ "jid", "jid", "The jid of this service.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_NODE] = g_param_spec_string(
+ "node", "node", "The node of this service.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_EXPANDED] = g_param_spec_boolean(
+ "expanded", "expanded", "Whether this service expanded.",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_ICON_NAME] = g_param_spec_string(
+ "icon-name", "icon-name", "The icon name of this service.",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(obj_class, PROP_LAST, properties);
+}
+
+static void
+xmpp_disco_service_class_finalize(G_GNUC_UNUSED XmppDiscoServiceClass *klass) {
+}
+
+static void
+xmpp_disco_service_init(G_GNUC_UNUSED XmppDiscoService *service) {
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+
+void
+xmpp_disco_service_register(PurplePlugin *plugin) {
+ xmpp_disco_service_register_type(G_TYPE_MODULE(plugin));
+}
+
+XmppDiscoService *
+xmpp_disco_service_new(PidginDiscoList *list) {
+ return g_object_new(
+ XMPP_DISCO_TYPE_SERVICE,
+ "list", list,
+ NULL);
+}
+
+PidginDiscoList *
+xmpp_disco_service_get_list(XmppDiscoService *service) {
+ g_return_val_if_fail(XMPP_DISCO_IS_SERVICE(service), NULL);
+
+ return service->list;
+}
+
+const char *
+xmpp_disco_service_get_name(XmppDiscoService *service) {
+ g_return_val_if_fail(XMPP_DISCO_IS_SERVICE(service), NULL);
+
+ return service->name;
+}
+
+void
+xmpp_disco_service_set_name(XmppDiscoService *service, const char *name) {
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
+
+ g_free(service->name);
+ service->name = g_strdup(name);
+
+ g_object_notify_by_pspec(G_OBJECT(service), properties[PROP_NAME]);
+}
+
+const char *
+xmpp_disco_service_get_description(XmppDiscoService *service) {
+ g_return_val_if_fail(XMPP_DISCO_IS_SERVICE(service), NULL);
+
+ return service->description;
+}
+
+void
+xmpp_disco_service_set_description(XmppDiscoService *service,
+ const char *description)
+{
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
+
+ g_free(service->description);
+ service->description = g_strdup(description);
+
+ g_object_notify_by_pspec(G_OBJECT(service), properties[PROP_DESCRIPTION]);
+}
+
+XmppDiscoServiceType
+xmpp_disco_service_get_service_type(XmppDiscoService *service) {
+ g_return_val_if_fail(XMPP_DISCO_IS_SERVICE(service),
+ XMPP_DISCO_SERVICE_TYPE_UNSET);
+
+ return service->type;
+}
+
+void
+xmpp_disco_service_set_service_type(XmppDiscoService *service,
+ XmppDiscoServiceType type)
+{
+ GObject *obj = NULL;
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
+
+ service->type = type;
+
+ obj = G_OBJECT(service);
+ g_object_freeze_notify(obj);
+ g_object_notify_by_pspec(obj, properties[PROP_SERVICE_TYPE]);
+ g_object_notify_by_pspec(obj, properties[PROP_ICON_NAME]);
+ g_object_thaw_notify(obj);
+}
+
+const char *
+xmpp_disco_service_get_gateway_type(XmppDiscoService *service) {
+ g_return_val_if_fail(XMPP_DISCO_IS_SERVICE(service), NULL);
+
+ return service->gateway_type;
+}
+
+void
+xmpp_disco_service_set_gateway_type(XmppDiscoService *service,
+ const char *gateway_type)
+{
+ GObject *obj = NULL;
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
+
+ g_free(service->gateway_type);
+ service->gateway_type = g_strdup(gateway_type);
+
+ obj = G_OBJECT(service);
+ g_object_freeze_notify(obj);
+ g_object_notify_by_pspec(obj, properties[PROP_GATEWAY_TYPE]);
+ g_object_notify_by_pspec(obj, properties[PROP_ICON_NAME]);
+ g_object_thaw_notify(obj);
+}
+
+XmppDiscoServiceFlags
+xmpp_disco_service_get_flags(XmppDiscoService *service) {
+ g_return_val_if_fail(XMPP_DISCO_IS_SERVICE(service), XMPP_DISCO_NONE);
+
+ return service->flags;
+}
+
+void
+xmpp_disco_service_set_flags(XmppDiscoService *service,
+ XmppDiscoServiceFlags flags)
+{
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
+
+ service->flags = flags;
+
+ g_object_notify_by_pspec(G_OBJECT(service), properties[PROP_FLAGS]);
+}
+
+void
+xmpp_disco_service_add_flags(XmppDiscoService *service,
+ XmppDiscoServiceFlags flags)
+{
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
+
+ service->flags |= flags;
+
+ g_object_notify_by_pspec(G_OBJECT(service), properties[PROP_FLAGS]);
+}
+
+void
+xmpp_disco_service_remove_flags(XmppDiscoService *service,
+ XmppDiscoServiceFlags flags)
+{
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
+
+ service->flags &= ~flags;
+
+ g_object_notify_by_pspec(G_OBJECT(service), properties[PROP_FLAGS]);
+}
+
+const char *
+xmpp_disco_service_get_jid(XmppDiscoService *service) {
+ g_return_val_if_fail(XMPP_DISCO_IS_SERVICE(service), NULL);
+
+ return service->jid;
+}
+
+void
+xmpp_disco_service_set_jid(XmppDiscoService *service, const char *jid) {
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
+
+ g_free(service->jid);
+ service->jid = g_strdup(jid);
+
+ g_object_notify_by_pspec(G_OBJECT(service), properties[PROP_JID]);
+}
+
+const char *
+xmpp_disco_service_get_node(XmppDiscoService *service) {
+ g_return_val_if_fail(XMPP_DISCO_IS_SERVICE(service), NULL);
+
+ return service->node;
+}
+
+void
+xmpp_disco_service_set_node(XmppDiscoService *service, const char *node) {
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
+
+ g_free(service->node);
+ service->node = g_strdup(node);
+
+ g_object_notify_by_pspec(G_OBJECT(service), properties[PROP_NODE]);
+}
+
+gboolean
+xmpp_disco_service_get_expanded(XmppDiscoService *service) {
+ g_return_val_if_fail(XMPP_DISCO_IS_SERVICE(service), FALSE);
+
+ return service->expanded;
+}
+
+void
+xmpp_disco_service_set_expanded(XmppDiscoService *service, gboolean expanded) {
+ g_return_if_fail(XMPP_DISCO_IS_SERVICE(service));
+
+ service->expanded = expanded;
+
+ g_object_notify_by_pspec(G_OBJECT(service), properties[PROP_EXPANDED]);
+}
+
+char *
+xmpp_disco_service_get_icon_name(XmppDiscoService *service)
+{
+ char *icon_name = NULL;
+
+ g_return_val_if_fail(XMPP_DISCO_IS_SERVICE(service), NULL);
+
+ if(service->type == XMPP_DISCO_SERVICE_TYPE_GATEWAY && service->gateway_type != NULL) {
+ icon_name = g_strconcat("im-", service->gateway_type, NULL);
+#if 0
+ } else if(service->type == XMPP_DISCO_SERVICE_TYPE_USER) {
+ icon_name = g_strdup("person");
+#endif
+ } else if(service->type == XMPP_DISCO_SERVICE_TYPE_CHAT) {
+ icon_name = g_strdup("chat");
+ }
+
+ return icon_name;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/disco/xmppdiscoservice.h Tue Jan 24 15:40:35 2023 -0600
@@ -0,0 +1,111 @@
+/* pidgin
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * 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/>.
+ */
+
+#ifndef PIDGIN_XMPP_DISCO_SERVICE_H
+#define PIDGIN_XMPP_DISCO_SERVICE_H
+
+#include <glib-object.h>
+
+#include <purple.h>
+
+#define XMPP_DISCO_TYPE_SERVICE (xmpp_disco_service_get_type())
+G_DECLARE_FINAL_TYPE(XmppDiscoService, xmpp_disco_service, XMPP_DISCO, SERVICE,
+ GObject)
+
+#include "gtkdisco.h"
+
+/**
+ * XmppDiscoServiceType:
+ * @XMPP_DISCO_SERVICE_TYPE_UNSET: An unset service type.
+ * @XMPP_DISCO_SERVICE_TYPE_GATEWAY: A registerable gateway to another
+ * protocol. An example would be XMPP legacy
+ * transports.
+ * @XMPP_DISCO_SERVICE_TYPE_DIRECTORY: A directory (e.g. allows the user to
+ * search for other users).
+ * @XMPP_DISCO_SERVICE_TYPE_CHAT: A chat (multi-user conversation).
+ * @XMPP_DISCO_SERVICE_TYPE_PUBSUB_COLLECTION: A pubsub collection (contains
+ * nodes).
+ * @XMPP_DISCO_SERVICE_TYPE_PUBSUB_LEAF: A pubsub leaf (contains stuff, not
+ * nodes).
+ * @XMPP_DISCO_SERVICE_TYPE_OTHER: Something else. Do we need more categories?
+ *
+ * The types of services.
+ */
+typedef enum {
+ XMPP_DISCO_SERVICE_TYPE_UNSET,
+ XMPP_DISCO_SERVICE_TYPE_GATEWAY,
+ XMPP_DISCO_SERVICE_TYPE_DIRECTORY,
+ XMPP_DISCO_SERVICE_TYPE_CHAT,
+ XMPP_DISCO_SERVICE_TYPE_PUBSUB_COLLECTION,
+ XMPP_DISCO_SERVICE_TYPE_PUBSUB_LEAF,
+ XMPP_DISCO_SERVICE_TYPE_OTHER
+} XmppDiscoServiceType;
+
+/**
+ * XmppDiscoServiceFlags:
+ * @XMPP_DISCO_NONE: No flags.
+ * @XMPP_DISCO_ADD: Supports an 'add' operation.
+ * @XMPP_DISCO_BROWSE: Supports browsing.
+ * @XMPP_DISCO_REGISTER: Supports a 'register' operation.
+ *
+ * The flags of services.
+ */
+typedef enum { /*< flags >*/
+ XMPP_DISCO_NONE = 0x0000,
+ XMPP_DISCO_ADD = 0x0001,
+ XMPP_DISCO_BROWSE = 0x0002,
+ XMPP_DISCO_REGISTER = 0x0004,
+} XmppDiscoServiceFlags;
+
+void xmpp_disco_service_register(PurplePlugin *plugin);
+
+XmppDiscoService *xmpp_disco_service_new(PidginDiscoList *list);
+
+PidginDiscoList *xmpp_disco_service_get_list(XmppDiscoService *service);
+
+const char *xmpp_disco_service_get_name(XmppDiscoService *service);
+void xmpp_disco_service_set_name(XmppDiscoService *service, const char *name);
+
+const char *xmpp_disco_service_get_description(XmppDiscoService *service);
+void xmpp_disco_service_set_description(XmppDiscoService *service, const char *description);
+
+XmppDiscoServiceType xmpp_disco_service_get_service_type(XmppDiscoService *service);
+void xmpp_disco_service_set_service_type(XmppDiscoService *service, XmppDiscoServiceType type);
+
+const char *xmpp_disco_service_get_gateway_type(XmppDiscoService *service);
+void xmpp_disco_service_set_gateway_type(XmppDiscoService *service, const char *gateway_type);
+
+XmppDiscoServiceFlags xmpp_disco_service_get_flags(XmppDiscoService *service);
+void xmpp_disco_service_set_flags(XmppDiscoService *service, XmppDiscoServiceFlags flags);
+void xmpp_disco_service_add_flags(XmppDiscoService *service, XmppDiscoServiceFlags flags);
+void xmpp_disco_service_remove_flags(XmppDiscoService *service, XmppDiscoServiceFlags flags);
+
+const char *xmpp_disco_service_get_jid(XmppDiscoService *service);
+void xmpp_disco_service_set_jid(XmppDiscoService *service, const char *jid);
+
+const char *xmpp_disco_service_get_node(XmppDiscoService *service);
+void xmpp_disco_service_set_node(XmppDiscoService *service, const char *node);
+
+gboolean xmpp_disco_service_get_expanded(XmppDiscoService *service);
+void xmpp_disco_service_set_expanded(XmppDiscoService *service, gboolean expanded);
+
+char *xmpp_disco_service_get_icon_name(XmppDiscoService *service);
+
+#endif /* PIDGIN_XMPP_DISCO_SERVICE_H */