Migrate xmpp-caps.xml to XDG cache dir
[pidgin-git.git] / libpurple / chat.c
blob8424908de839ea9effc8610f36b04aadb041bdc1
1 /*
2 * purple
4 * Purple is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 #include "internal.h"
24 #include "chat.h"
25 #include "dbus-maybe.h"
26 #include "util.h"
28 #define PURPLE_CHAT_GET_PRIVATE(obj) \
29 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CHAT, PurpleChatPrivate))
31 typedef struct _PurpleChatPrivate PurpleChatPrivate;
33 /* Private data for a chat node */
34 struct _PurpleChatPrivate {
35 char *alias; /* The display name of this chat. */
36 PurpleAccount *account; /* The account this chat is attached to */
37 GHashTable *components; /* the stuff the protocol needs to know to
38 join the chat */
40 gboolean is_constructed; /* Indicates if the chat has finished being
41 constructed. */
44 /* Chat property enums */
45 enum
47 PROP_0,
48 PROP_ALIAS,
49 PROP_ACCOUNT,
50 PROP_COMPONENTS,
51 PROP_LAST
54 /******************************************************************************
55 * Globals
56 *****************************************************************************/
57 static PurpleBlistNode *blistnode_parent_class;
58 static GParamSpec *properties[PROP_LAST];
60 /******************************************************************************
61 * API
62 *****************************************************************************/
64 const char *purple_chat_get_name(PurpleChat *chat)
66 PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat);
68 g_return_val_if_fail(priv != NULL, NULL);
70 if ((priv->alias != NULL) && (*priv->alias != '\0'))
71 return priv->alias;
73 return purple_chat_get_name_only(chat);
76 const char *purple_chat_get_name_only(PurpleChat *chat)
78 char *ret = NULL;
79 PurpleProtocol *protocol = NULL;
80 PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat);
82 g_return_val_if_fail(priv != NULL, NULL);
84 protocol = purple_protocols_find(purple_account_get_protocol_id(priv->account));
86 if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, CHAT_IFACE, info)) {
87 PurpleProtocolChatEntry *pce;
88 GList *parts = purple_protocol_chat_iface_info(protocol, purple_account_get_connection(priv->account));
89 pce = parts->data;
90 ret = g_hash_table_lookup(priv->components, pce->identifier);
91 g_list_foreach(parts, (GFunc)g_free, NULL);
92 g_list_free(parts);
95 return ret;
98 void
99 purple_chat_set_alias(PurpleChat *chat, const char *alias)
101 PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
102 char *old_alias;
103 char *new_alias = NULL;
104 PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat);
106 g_return_if_fail(priv != NULL);
108 if ((alias != NULL) && (*alias != '\0'))
109 new_alias = purple_utf8_strip_unprintables(alias);
111 if (!purple_strequal(priv->alias, new_alias)) {
112 g_free(new_alias);
113 return;
116 old_alias = priv->alias;
118 if ((new_alias != NULL) && (*new_alias != '\0'))
119 priv->alias = new_alias;
120 else {
121 priv->alias = NULL;
122 g_free(new_alias); /* could be "\0" */
125 g_object_notify_by_pspec(G_OBJECT(chat), properties[PROP_ALIAS]);
127 if (ops) {
128 if (ops->save_node)
129 ops->save_node(PURPLE_BLIST_NODE(chat));
130 if (ops->update)
131 ops->update(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(chat));
134 purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased",
135 chat, old_alias);
136 g_free(old_alias);
139 PurpleGroup *
140 purple_chat_get_group(PurpleChat *chat)
142 g_return_val_if_fail(PURPLE_IS_CHAT(chat), NULL);
144 return PURPLE_GROUP(PURPLE_BLIST_NODE(chat)->parent);
147 PurpleAccount *
148 purple_chat_get_account(PurpleChat *chat)
150 PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat);
152 g_return_val_if_fail(priv != NULL, NULL);
154 return priv->account;
157 GHashTable *
158 purple_chat_get_components(PurpleChat *chat)
160 PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat);
162 g_return_val_if_fail(priv != NULL, NULL);
164 return priv->components;
167 /******************************************************************************
168 * GObject Stuff
169 *****************************************************************************/
170 static void
171 purple_chat_set_property(GObject *obj, guint param_id, const GValue *value,
172 GParamSpec *pspec)
174 PurpleChat *chat = PURPLE_CHAT(obj);
175 PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat);
177 switch (param_id) {
178 case PROP_ALIAS:
179 if (priv->is_constructed)
180 purple_chat_set_alias(chat, g_value_get_string(value));
181 else
182 priv->alias =
183 purple_utf8_strip_unprintables(g_value_get_string(value));
184 break;
185 case PROP_ACCOUNT:
186 priv->account = g_value_get_object(value);
187 break;
188 case PROP_COMPONENTS:
189 priv->components = g_value_get_pointer(value);
190 break;
191 default:
192 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
193 break;
197 static void
198 purple_chat_get_property(GObject *obj, guint param_id, GValue *value,
199 GParamSpec *pspec)
201 PurpleChat *chat = PURPLE_CHAT(obj);
202 PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat);
204 switch (param_id) {
205 case PROP_ALIAS:
206 g_value_set_string(value, priv->alias);
207 break;
208 case PROP_ACCOUNT:
209 g_value_set_object(value, purple_chat_get_account(chat));
210 break;
211 case PROP_COMPONENTS:
212 g_value_set_pointer(value, purple_chat_get_components(chat));
213 break;
214 default:
215 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
216 break;
220 /* GObject initialization function */
221 static void
222 purple_chat_init(GTypeInstance *instance, gpointer klass)
224 PURPLE_DBUS_REGISTER_POINTER(PURPLE_CHAT(instance), PurpleChat);
227 /* Called when done constructing */
228 static void
229 purple_chat_constructed(GObject *object)
231 PurpleChat *chat = PURPLE_CHAT(object);
232 PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat);
233 PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
235 G_OBJECT_CLASS(blistnode_parent_class)->constructed(object);
237 if (ops != NULL && ops->new_node != NULL)
238 ops->new_node(PURPLE_BLIST_NODE(chat));
240 priv->is_constructed = TRUE;
243 /* GObject finalize function */
244 static void
245 purple_chat_finalize(GObject *object)
247 PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(object);
249 g_free(priv->alias);
250 g_hash_table_destroy(priv->components);
252 PURPLE_DBUS_UNREGISTER_POINTER(object);
254 G_OBJECT_CLASS(blistnode_parent_class)->finalize(object);
257 /* Class initializer function */
258 static void purple_chat_class_init(PurpleChatClass *klass)
260 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
262 blistnode_parent_class = g_type_class_peek_parent(klass);
264 obj_class->finalize = purple_chat_finalize;
266 /* Setup properties */
267 obj_class->get_property = purple_chat_get_property;
268 obj_class->set_property = purple_chat_set_property;
269 obj_class->constructed = purple_chat_constructed;
271 g_type_class_add_private(klass, sizeof(PurpleChatPrivate));
273 properties[PROP_ALIAS] = g_param_spec_string(
274 "alias",
275 "Alias",
276 "The alias for the chat.",
277 NULL,
278 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS
281 properties[PROP_ACCOUNT] = g_param_spec_object(
282 "account",
283 "Account",
284 "The account that the chat belongs to.",
285 PURPLE_TYPE_ACCOUNT,
286 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS
289 properties[PROP_COMPONENTS] = g_param_spec_pointer(
290 "components",
291 "Components",
292 "The protocol components of the chat.",
293 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS
296 g_object_class_install_properties(obj_class, PROP_LAST, properties);
299 GType
300 purple_chat_get_type(void)
302 static GType type = 0;
304 if(type == 0) {
305 static const GTypeInfo info = {
306 sizeof(PurpleChatClass),
307 NULL,
308 NULL,
309 (GClassInitFunc)purple_chat_class_init,
310 NULL,
311 NULL,
312 sizeof(PurpleChat),
314 (GInstanceInitFunc)purple_chat_init,
315 NULL,
318 type = g_type_register_static(PURPLE_TYPE_BLIST_NODE,
319 "PurpleChat",
320 &info, 0);
323 return type;
326 PurpleChat *
327 purple_chat_new(PurpleAccount *account, const char *alias, GHashTable *components)
329 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
330 g_return_val_if_fail(components != NULL, NULL);
332 return g_object_new(PURPLE_TYPE_CHAT,
333 "account", account,
334 "alias", alias,
335 "components", components,
336 NULL);