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
25 #include "dbus-maybe.h"
26 #include "internal.h" /* TODO: this needs to die */
29 #define PURPLE_CONTACT_GET_PRIVATE(obj) \
30 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CONTACT, PurpleContactPrivate))
32 typedef struct _PurpleContactPrivate PurpleContactPrivate
;
34 struct _PurpleContactPrivate
{
35 char *alias
; /* The user-set alias of the contact */
36 PurpleBuddy
*priority_buddy
; /* The "top" buddy for this contact */
37 gboolean priority_valid
; /* Is priority valid? */
48 /******************************************************************************
50 *****************************************************************************/
51 static GObjectClass
*parent_class
= NULL
;
52 static GParamSpec
*properties
[PROP_LAST
];
54 /******************************************************************************
56 *****************************************************************************/
58 purple_contact_compute_priority_buddy(PurpleContact
*contact
) {
59 PurpleBlistNode
*bnode
;
60 PurpleBuddy
*new_priority
= NULL
;
61 PurpleContactPrivate
*priv
= PURPLE_CONTACT_GET_PRIVATE(contact
);
63 g_return_if_fail(priv
!= NULL
);
65 priv
->priority_buddy
= NULL
;
66 for (bnode
= PURPLE_BLIST_NODE(contact
)->child
;
72 if (!PURPLE_IS_BUDDY(bnode
))
75 buddy
= PURPLE_BUDDY(bnode
);
76 if (new_priority
== NULL
)
82 if (purple_account_is_connected(purple_buddy_get_account(buddy
)))
85 if (purple_account_is_connected(purple_buddy_get_account(new_priority
)))
86 cmp
= purple_buddy_presence_compare(
87 PURPLE_BUDDY_PRESENCE(purple_buddy_get_presence(new_priority
)),
88 PURPLE_BUDDY_PRESENCE(purple_buddy_get_presence(buddy
)));
90 if (cmp
> 0 || (cmp
== 0 &&
91 purple_prefs_get_bool("/purple/contact/last_match")))
98 priv
->priority_buddy
= new_priority
;
99 priv
->priority_valid
= TRUE
;
101 g_object_notify_by_pspec(G_OBJECT(contact
),
102 properties
[PROP_PRIORITY_BUDDY
]);
106 purple_contact_get_group(const PurpleContact
*contact
)
108 g_return_val_if_fail(PURPLE_IS_CONTACT(contact
), NULL
);
110 return PURPLE_GROUP(PURPLE_BLIST_NODE(contact
)->parent
);
114 purple_contact_set_alias(PurpleContact
*contact
, const char *alias
)
116 PurpleBlistUiOps
*ops
= purple_blist_get_ui_ops();
117 PurpleIMConversation
*im
;
118 PurpleBlistNode
*bnode
;
120 char *new_alias
= NULL
;
121 PurpleContactPrivate
*priv
= PURPLE_CONTACT_GET_PRIVATE(contact
);
123 g_return_if_fail(priv
!= NULL
);
125 if ((alias
!= NULL
) && (*alias
!= '\0'))
126 new_alias
= purple_utf8_strip_unprintables(alias
);
128 if (!purple_strequal(priv
->alias
, new_alias
)) {
133 old_alias
= priv
->alias
;
135 if ((new_alias
!= NULL
) && (*new_alias
!= '\0'))
136 priv
->alias
= new_alias
;
139 g_free(new_alias
); /* could be "\0" */
142 g_object_notify_by_pspec(G_OBJECT(contact
),
143 properties
[PROP_ALIAS
]);
147 ops
->save_node(PURPLE_BLIST_NODE(contact
));
149 ops
->update(purple_blist_get_buddy_list(), PURPLE_BLIST_NODE(contact
));
152 for(bnode
= PURPLE_BLIST_NODE(contact
)->child
; bnode
!= NULL
; bnode
= bnode
->next
)
154 PurpleBuddy
*buddy
= PURPLE_BUDDY(bnode
);
156 im
= purple_conversations_find_im_with_account(purple_buddy_get_name(buddy
),
157 purple_buddy_get_account(buddy
));
159 purple_conversation_autoset_title(PURPLE_CONVERSATION(im
));
162 purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased",
167 const char *purple_contact_get_alias(PurpleContact
* contact
)
169 PurpleContactPrivate
*priv
= PURPLE_CONTACT_GET_PRIVATE(contact
);
171 g_return_val_if_fail(priv
!= NULL
, NULL
);
176 return purple_buddy_get_alias(purple_contact_get_priority_buddy(contact
));
179 gboolean
purple_contact_on_account(PurpleContact
*c
, PurpleAccount
*account
)
181 PurpleBlistNode
*bnode
, *cnode
= (PurpleBlistNode
*) c
;
183 g_return_val_if_fail(PURPLE_IS_CONTACT(c
), FALSE
);
184 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account
), FALSE
);
186 for (bnode
= cnode
->child
; bnode
; bnode
= bnode
->next
) {
189 if (! PURPLE_IS_BUDDY(bnode
))
192 buddy
= (PurpleBuddy
*)bnode
;
193 if (purple_buddy_get_account(buddy
) == account
)
199 void purple_contact_invalidate_priority_buddy(PurpleContact
*contact
)
201 PurpleContactPrivate
*priv
= PURPLE_CONTACT_GET_PRIVATE(contact
);
203 g_return_if_fail(priv
!= NULL
);
205 priv
->priority_valid
= FALSE
;
208 PurpleBuddy
*purple_contact_get_priority_buddy(PurpleContact
*contact
)
210 PurpleContactPrivate
*priv
= PURPLE_CONTACT_GET_PRIVATE(contact
);
212 g_return_val_if_fail(priv
!= NULL
, NULL
);
214 if (!priv
->priority_valid
)
215 purple_contact_compute_priority_buddy(contact
);
217 return priv
->priority_buddy
;
220 void purple_contact_merge(PurpleContact
*source
, PurpleBlistNode
*node
)
222 PurpleBlistNode
*sourcenode
= (PurpleBlistNode
*)source
;
223 PurpleBlistNode
*prev
, *cur
, *next
;
224 PurpleContact
*target
;
226 g_return_if_fail(PURPLE_IS_CONTACT(source
));
227 g_return_if_fail(PURPLE_IS_BLIST_NODE(node
));
229 if (PURPLE_IS_CONTACT(node
)) {
230 target
= (PurpleContact
*)node
;
231 prev
= _purple_blist_get_last_child(node
);
232 } else if (PURPLE_IS_BUDDY(node
)) {
233 target
= (PurpleContact
*)node
->parent
;
239 if (source
== target
|| !target
)
242 next
= sourcenode
->child
;
247 if (PURPLE_IS_BUDDY(cur
)) {
248 purple_blist_add_buddy((PurpleBuddy
*)cur
, target
, NULL
, prev
);
254 /**************************************************************************
256 **************************************************************************/
257 /* Set method for GObject properties */
259 purple_contact_set_property(GObject
*obj
, guint param_id
, const GValue
*value
,
262 PurpleContact
*contact
= PURPLE_CONTACT(obj
);
266 purple_contact_set_alias(contact
, g_value_get_string(value
));
269 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
274 /* Get method for GObject properties */
276 purple_contact_get_property(GObject
*obj
, guint param_id
, GValue
*value
,
279 PurpleContact
*contact
= PURPLE_CONTACT(obj
);
280 PurpleContactPrivate
*priv
= PURPLE_CONTACT_GET_PRIVATE(contact
);
284 g_value_set_string(value
, priv
->alias
);
286 case PROP_PRIORITY_BUDDY
:
287 g_value_set_object(value
, purple_contact_get_priority_buddy(contact
));
290 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
295 /* GObject initialization function */
297 purple_contact_init(GTypeInstance
*instance
, gpointer klass
)
299 PurpleContact
*contact
= PURPLE_CONTACT(instance
);
300 PurpleBlistUiOps
*ops
= purple_blist_get_ui_ops();
302 if (ops
&& ops
->new_node
)
303 ops
->new_node(PURPLE_BLIST_NODE(contact
));
305 PURPLE_DBUS_REGISTER_POINTER(contact
, PurpleContact
);
308 /* GObject finalize function */
310 purple_contact_finalize(GObject
*object
)
312 g_free(PURPLE_CONTACT_GET_PRIVATE(object
)->alias
);
314 PURPLE_DBUS_UNREGISTER_POINTER(object
);
316 G_OBJECT_CLASS(parent_class
)->finalize(object
);
319 /* Class initializer function */
320 static void purple_contact_class_init(PurpleContactClass
*klass
)
322 GObjectClass
*obj_class
= G_OBJECT_CLASS(klass
);
324 parent_class
= g_type_class_peek_parent(klass
);
326 obj_class
->finalize
= purple_contact_finalize
;
328 /* Setup properties */
329 obj_class
->get_property
= purple_contact_get_property
;
330 obj_class
->set_property
= purple_contact_set_property
;
332 g_type_class_add_private(klass
, sizeof(PurpleContactPrivate
));
334 properties
[PROP_ALIAS
] = g_param_spec_string(
337 "The alias for the contact.",
339 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
342 properties
[PROP_PRIORITY_BUDDY
] = g_param_spec_object(
345 "The priority buddy of the contact.",
347 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
350 g_object_class_install_properties(obj_class
, PROP_LAST
, properties
);
354 purple_contact_get_type(void)
356 static GType type
= 0;
359 static const GTypeInfo info
= {
360 sizeof(PurpleContactClass
),
363 (GClassInitFunc
)purple_contact_class_init
,
366 sizeof(PurpleContact
),
368 (GInstanceInitFunc
)purple_contact_init
,
372 type
= g_type_register_static(
373 PURPLE_TYPE_COUNTING_NODE
,
384 purple_contact_new(void)
386 return g_object_new(PURPLE_TYPE_CONTACT
, NULL
);