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
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
24 #include "glibcompat.h"
26 typedef struct _PurpleBlistNodePrivate PurpleBlistNodePrivate
;
28 /* Private data of a buddy list node */
29 struct _PurpleBlistNodePrivate
{
30 GHashTable
*settings
; /* per-node settings */
31 gboolean transient
; /* node should not be saved with the buddy list */
34 /* Blist node property enums */
38 BLNODE_PROP_TRANSIENT
,
42 static GParamSpec
*bn_properties
[BLNODE_PROP_LAST
];
44 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(PurpleBlistNode
, purple_blist_node
,
47 /**************************************************************************/
48 /* Buddy list node API */
49 /**************************************************************************/
51 static PurpleBlistNode
*get_next_node(PurpleBlistNode
*node
, gboolean godeep
)
56 if (godeep
&& node
->child
)
62 return get_next_node(node
->parent
, FALSE
);
65 PurpleBlistNode
*purple_blist_node_next(PurpleBlistNode
*node
, gboolean offline
)
67 PurpleBlistNode
*ret
= node
;
70 return get_next_node(ret
, TRUE
);
73 ret
= get_next_node(ret
, TRUE
);
74 } while (ret
&& PURPLE_IS_BUDDY(ret
) &&
75 !purple_account_is_connected(purple_buddy_get_account((PurpleBuddy
*)ret
)));
80 PurpleBlistNode
*purple_blist_node_get_parent(PurpleBlistNode
*node
)
82 return node
? node
->parent
: NULL
;
85 PurpleBlistNode
*purple_blist_node_get_first_child(PurpleBlistNode
*node
)
87 return node
? node
->child
: NULL
;
90 PurpleBlistNode
*purple_blist_node_get_sibling_next(PurpleBlistNode
*node
)
92 return node
? node
->next
: NULL
;
95 PurpleBlistNode
*purple_blist_node_get_sibling_prev(PurpleBlistNode
*node
)
97 return node
? node
->prev
: NULL
;
101 purple_blist_node_get_ui_data(const PurpleBlistNode
*node
)
103 g_return_val_if_fail(PURPLE_IS_BLIST_NODE(node
), NULL
);
105 return node
->ui_data
;
109 purple_blist_node_set_ui_data(PurpleBlistNode
*node
, void *ui_data
) {
110 g_return_if_fail(PURPLE_IS_BLIST_NODE(node
));
112 node
->ui_data
= ui_data
;
115 void purple_blist_node_remove_setting(PurpleBlistNode
*node
, const char *key
)
117 PurpleBlistNodePrivate
*priv
= NULL
;
119 g_return_if_fail(PURPLE_IS_BLIST_NODE(node
));
120 g_return_if_fail(key
!= NULL
);
122 priv
= purple_blist_node_get_instance_private(node
);
123 g_return_if_fail(priv
->settings
!= NULL
);
125 g_hash_table_remove(priv
->settings
, key
);
127 purple_blist_save_node(purple_blist_get_default(), node
);
131 purple_blist_node_set_transient(PurpleBlistNode
*node
, gboolean transient
)
133 PurpleBlistNodePrivate
*priv
= NULL
;
135 g_return_if_fail(PURPLE_IS_BLIST_NODE(node
));
137 priv
= purple_blist_node_get_instance_private(node
);
138 priv
->transient
= transient
;
140 g_object_notify_by_pspec(G_OBJECT(node
),
141 bn_properties
[BLNODE_PROP_TRANSIENT
]);
145 purple_blist_node_is_transient(PurpleBlistNode
*node
)
147 PurpleBlistNodePrivate
*priv
= NULL
;
149 g_return_val_if_fail(PURPLE_IS_BLIST_NODE(node
), 0);
151 priv
= purple_blist_node_get_instance_private(node
);
152 return priv
->transient
;
156 purple_blist_node_get_settings(PurpleBlistNode
*node
)
158 PurpleBlistNodePrivate
*priv
= NULL
;
160 g_return_val_if_fail(PURPLE_IS_BLIST_NODE(node
), NULL
);
162 priv
= purple_blist_node_get_instance_private(node
);
163 return priv
->settings
;
167 purple_blist_node_has_setting(PurpleBlistNode
* node
, const char *key
)
169 PurpleBlistNodePrivate
*priv
= NULL
;
171 g_return_val_if_fail(PURPLE_IS_BLIST_NODE(node
), FALSE
);
172 g_return_val_if_fail(key
!= NULL
, FALSE
);
174 priv
= purple_blist_node_get_instance_private(node
);
175 g_return_val_if_fail(priv
->settings
!= NULL
, FALSE
);
177 /* Boxed type, so it won't ever be NULL, so no need for _extended */
178 return (g_hash_table_lookup(priv
->settings
, key
) != NULL
);
182 purple_blist_node_set_bool(PurpleBlistNode
* node
, const char *key
, gboolean data
)
184 PurpleBlistNodePrivate
*priv
= NULL
;
187 g_return_if_fail(PURPLE_IS_BLIST_NODE(node
));
188 g_return_if_fail(key
!= NULL
);
190 priv
= purple_blist_node_get_instance_private(node
);
191 g_return_if_fail(priv
->settings
!= NULL
);
193 value
= purple_value_new(G_TYPE_BOOLEAN
);
194 g_value_set_boolean(value
, data
);
196 g_hash_table_replace(priv
->settings
, g_strdup(key
), value
);
198 purple_blist_save_node(purple_blist_get_default(), node
);
202 purple_blist_node_get_bool(PurpleBlistNode
* node
, const char *key
)
204 PurpleBlistNodePrivate
*priv
= NULL
;
207 g_return_val_if_fail(PURPLE_IS_BLIST_NODE(node
), FALSE
);
208 g_return_val_if_fail(key
!= NULL
, FALSE
);
210 priv
= purple_blist_node_get_instance_private(node
);
211 g_return_val_if_fail(priv
->settings
!= NULL
, FALSE
);
213 value
= g_hash_table_lookup(priv
->settings
, key
);
218 g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(value
), FALSE
);
220 return g_value_get_boolean(value
);
224 purple_blist_node_set_int(PurpleBlistNode
* node
, const char *key
, int data
)
226 PurpleBlistNodePrivate
*priv
= NULL
;
229 g_return_if_fail(PURPLE_IS_BLIST_NODE(node
));
230 g_return_if_fail(key
!= NULL
);
232 priv
= purple_blist_node_get_instance_private(node
);
233 g_return_if_fail(priv
->settings
!= NULL
);
235 value
= purple_value_new(G_TYPE_INT
);
236 g_value_set_int(value
, data
);
238 g_hash_table_replace(priv
->settings
, g_strdup(key
), value
);
240 purple_blist_save_node(purple_blist_get_default(), node
);
244 purple_blist_node_get_int(PurpleBlistNode
* node
, const char *key
)
246 PurpleBlistNodePrivate
*priv
= NULL
;
249 g_return_val_if_fail(PURPLE_IS_BLIST_NODE(node
), 0);
250 g_return_val_if_fail(key
!= NULL
, 0);
252 priv
= purple_blist_node_get_instance_private(node
);
253 g_return_val_if_fail(priv
->settings
!= NULL
, 0);
255 value
= g_hash_table_lookup(priv
->settings
, key
);
260 g_return_val_if_fail(G_VALUE_HOLDS_INT(value
), 0);
262 return g_value_get_int(value
);
266 purple_blist_node_set_string(PurpleBlistNode
* node
, const char *key
, const char *data
)
268 PurpleBlistNodePrivate
*priv
= NULL
;
271 g_return_if_fail(PURPLE_IS_BLIST_NODE(node
));
272 g_return_if_fail(key
!= NULL
);
274 priv
= purple_blist_node_get_instance_private(node
);
275 g_return_if_fail(priv
->settings
!= NULL
);
277 value
= purple_value_new(G_TYPE_STRING
);
278 g_value_set_string(value
, data
);
280 g_hash_table_replace(priv
->settings
, g_strdup(key
), value
);
282 purple_blist_save_node(purple_blist_get_default(), node
);
286 purple_blist_node_get_string(PurpleBlistNode
* node
, const char *key
)
288 PurpleBlistNodePrivate
*priv
= NULL
;
291 g_return_val_if_fail(PURPLE_IS_BLIST_NODE(node
), NULL
);
292 g_return_val_if_fail(key
!= NULL
, NULL
);
294 priv
= purple_blist_node_get_instance_private(node
);
295 g_return_val_if_fail(priv
->settings
!= NULL
, NULL
);
297 value
= g_hash_table_lookup(priv
->settings
, key
);
302 g_return_val_if_fail(G_VALUE_HOLDS_STRING(value
), NULL
);
304 return g_value_get_string(value
);
308 purple_blist_node_get_extended_menu(PurpleBlistNode
*n
)
312 g_return_val_if_fail(n
!= NULL
, NULL
);
314 purple_signal_emit(purple_blist_get_handle(), "blist-node-extended-menu",
319 /**************************************************************************
320 * GObject code for PurpleBlistNode
321 **************************************************************************/
323 /* Set method for GObject properties */
325 purple_blist_node_set_property(GObject
*obj
, guint param_id
, const GValue
*value
,
328 PurpleBlistNode
*node
= PURPLE_BLIST_NODE(obj
);
331 case BLNODE_PROP_TRANSIENT
:
332 purple_blist_node_set_transient(node
, g_value_get_boolean(value
));
335 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
340 /* Get method for GObject properties */
342 purple_blist_node_get_property(GObject
*obj
, guint param_id
, GValue
*value
,
345 PurpleBlistNode
*node
= PURPLE_BLIST_NODE(obj
);
348 case BLNODE_PROP_TRANSIENT
:
349 g_value_set_boolean(value
, purple_blist_node_is_transient(node
));
352 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
357 /* GObject initialization function */
359 purple_blist_node_init(PurpleBlistNode
*node
)
361 PurpleBlistNodePrivate
*priv
=
362 purple_blist_node_get_instance_private(node
);
364 priv
->settings
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
,
365 (GDestroyNotify
)purple_value_free
);
368 /* GObject finalize function */
370 purple_blist_node_finalize(GObject
*object
)
372 PurpleBlistNodePrivate
*priv
= purple_blist_node_get_instance_private(
373 PURPLE_BLIST_NODE(object
));
375 g_hash_table_destroy(priv
->settings
);
377 G_OBJECT_CLASS(purple_blist_node_parent_class
)->finalize(object
);
380 /* Class initializer function */
382 purple_blist_node_class_init(PurpleBlistNodeClass
*klass
)
384 GObjectClass
*obj_class
= G_OBJECT_CLASS(klass
);
386 obj_class
->finalize
= purple_blist_node_finalize
;
388 /* Setup properties */
389 obj_class
->get_property
= purple_blist_node_get_property
;
390 obj_class
->set_property
= purple_blist_node_set_property
;
392 bn_properties
[BLNODE_PROP_TRANSIENT
] = g_param_spec_boolean("transient",
394 "Whether node should not be saved with the buddy list.",
395 FALSE
, G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
397 g_object_class_install_properties(obj_class
, BLNODE_PROP_LAST
,