3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
22 #include "glibcompat.h"
24 #include "buddylist.h"
26 #include "dbus-maybe.h"
32 #define PURPLE_STATUS_GET_PRIVATE(obj) \
33 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_STATUS, PurpleStatusPrivate))
35 typedef struct _PurpleStatusPrivate PurpleStatusPrivate
;
40 struct _PurpleStatusType
44 PurpleStatusPrimitive primitive
;
50 gboolean user_settable
;
59 struct _PurpleStatusAttribute
67 * Private data for PurpleStatus
69 struct _PurpleStatusPrivate
71 PurpleStatusType
*status_type
;
72 PurplePresence
*presence
;
77 * The current values of the attributes for this status. The
78 * key is a string containing the name of the attribute. It is
79 * a borrowed reference from the list of attrs in the
80 * PurpleStatusType. The value is a GValue.
82 GHashTable
*attr_values
;
85 /* GObject property enums */
97 PurpleAccount
*account
;
99 } PurpleStatusBuddyKey
;
101 static GObjectClass
*parent_class
;
102 static GParamSpec
*properties
[PROP_LAST
];
104 static int primitive_scores
[] =
109 -75, /* unavailable */
112 -200, /* extended away */
116 -10, /* idle, special case. */
117 -5, /* idle time, special case. */
118 10 /* Offline messageable */
122 #define SCORE_IDLE_TIME 10
123 #define SCORE_OFFLINE_MESSAGE 11
125 /**************************************************************************
126 * PurpleStatusPrimitive API
127 **************************************************************************/
128 static struct PurpleStatusPrimitiveMap
130 PurpleStatusPrimitive type
;
134 } const status_primitive_map
[] =
136 { PURPLE_STATUS_UNSET
, "unset", N_("Unset") },
137 { PURPLE_STATUS_OFFLINE
, "offline", N_("Offline") },
138 { PURPLE_STATUS_AVAILABLE
, "available", N_("Available") },
139 { PURPLE_STATUS_UNAVAILABLE
, "unavailable", N_("Do not disturb") },
140 { PURPLE_STATUS_INVISIBLE
, "invisible", N_("Invisible") },
141 { PURPLE_STATUS_AWAY
, "away", N_("Away") },
142 { PURPLE_STATUS_EXTENDED_AWAY
, "extended_away", N_("Extended away") },
143 { PURPLE_STATUS_MOBILE
, "mobile", N_("Mobile") },
144 { PURPLE_STATUS_TUNE
, "tune", N_("Listening to music"), },
145 { PURPLE_STATUS_MOOD
, "mood", N_("Feeling") },
149 _purple_statuses_get_primitive_scores(void)
151 return primitive_scores
;
155 purple_primitive_get_id_from_type(PurpleStatusPrimitive type
)
159 for (i
= 0; i
< PURPLE_STATUS_NUM_PRIMITIVES
; i
++)
161 if (type
== status_primitive_map
[i
].type
)
162 return status_primitive_map
[i
].id
;
165 return status_primitive_map
[0].id
;
169 purple_primitive_get_name_from_type(PurpleStatusPrimitive type
)
173 for (i
= 0; i
< PURPLE_STATUS_NUM_PRIMITIVES
; i
++)
175 if (type
== status_primitive_map
[i
].type
)
176 return _(status_primitive_map
[i
].name
);
179 return _(status_primitive_map
[0].name
);
182 PurpleStatusPrimitive
183 purple_primitive_get_type_from_id(const char *id
)
187 g_return_val_if_fail(id
!= NULL
, PURPLE_STATUS_UNSET
);
189 for (i
= 0; i
< PURPLE_STATUS_NUM_PRIMITIVES
; i
++)
191 if (purple_strequal(id
, status_primitive_map
[i
].id
))
192 return status_primitive_map
[i
].type
;
195 return status_primitive_map
[0].type
;
199 /**************************************************************************
200 * PurpleStatusType API
201 **************************************************************************/
203 purple_status_type_new_full(PurpleStatusPrimitive primitive
, const char *id
,
204 const char *name
, gboolean saveable
,
205 gboolean user_settable
, gboolean independent
)
207 PurpleStatusType
*status_type
;
209 g_return_val_if_fail(primitive
!= PURPLE_STATUS_UNSET
, NULL
);
211 status_type
= g_new0(PurpleStatusType
, 1);
212 PURPLE_DBUS_REGISTER_POINTER(status_type
, PurpleStatusType
);
214 status_type
->primitive
= primitive
;
215 status_type
->saveable
= saveable
;
216 status_type
->user_settable
= user_settable
;
217 status_type
->independent
= independent
;
220 status_type
->id
= g_strdup(id
);
222 status_type
->id
= g_strdup(purple_primitive_get_id_from_type(primitive
));
225 status_type
->name
= g_strdup(name
);
227 status_type
->name
= g_strdup(purple_primitive_get_name_from_type(primitive
));
233 purple_status_type_new(PurpleStatusPrimitive primitive
, const char *id
,
234 const char *name
, gboolean user_settable
)
236 g_return_val_if_fail(primitive
!= PURPLE_STATUS_UNSET
, NULL
);
238 return purple_status_type_new_full(primitive
, id
, name
, TRUE
,
239 user_settable
, FALSE
);
243 status_type_add_attr(PurpleStatusType
*status_type
, const char *id
,
244 const char *name
, GValue
*value
)
246 PurpleStatusAttribute
*attr
;
248 g_return_if_fail(status_type
!= NULL
);
249 g_return_if_fail(id
!= NULL
);
250 g_return_if_fail(name
!= NULL
);
251 g_return_if_fail(value
!= NULL
);
253 attr
= purple_status_attribute_new(id
, name
, value
);
255 status_type
->attrs
= g_list_append(status_type
->attrs
, attr
);
259 status_type_add_attrs_vargs(PurpleStatusType
*status_type
, va_list args
)
261 const char *id
, *name
;
264 g_return_if_fail(status_type
!= NULL
);
266 while ((id
= va_arg(args
, const char *)) != NULL
)
268 name
= va_arg(args
, const char *);
269 g_return_if_fail(name
!= NULL
);
271 value
= va_arg(args
, GValue
*);
272 g_return_if_fail(value
!= NULL
);
274 status_type_add_attr(status_type
, id
, name
, value
);
279 purple_status_type_new_with_attrs(PurpleStatusPrimitive primitive
,
280 const char *id
, const char *name
,
281 gboolean saveable
, gboolean user_settable
,
282 gboolean independent
, const char *attr_id
,
283 const char *attr_name
, GValue
*attr_value
,
286 PurpleStatusType
*status_type
;
289 g_return_val_if_fail(primitive
!= PURPLE_STATUS_UNSET
, NULL
);
290 g_return_val_if_fail(attr_id
!= NULL
, NULL
);
291 g_return_val_if_fail(attr_name
!= NULL
, NULL
);
292 g_return_val_if_fail(attr_value
!= NULL
, NULL
);
294 status_type
= purple_status_type_new_full(primitive
, id
, name
, saveable
,
295 user_settable
, independent
);
297 /* Add the first attribute */
298 status_type_add_attr(status_type
, attr_id
, attr_name
, attr_value
);
300 va_start(args
, attr_value
);
301 status_type_add_attrs_vargs(status_type
, args
);
308 purple_status_type_destroy(PurpleStatusType
*status_type
)
310 g_return_if_fail(status_type
!= NULL
);
312 g_free(status_type
->id
);
313 g_free(status_type
->name
);
315 g_list_foreach(status_type
->attrs
, (GFunc
)purple_status_attribute_destroy
, NULL
);
316 g_list_free(status_type
->attrs
);
318 PURPLE_DBUS_UNREGISTER_POINTER(status_type
);
322 PurpleStatusPrimitive
323 purple_status_type_get_primitive(const PurpleStatusType
*status_type
)
325 g_return_val_if_fail(status_type
!= NULL
, PURPLE_STATUS_UNSET
);
327 return status_type
->primitive
;
331 purple_status_type_get_id(const PurpleStatusType
*status_type
)
333 g_return_val_if_fail(status_type
!= NULL
, NULL
);
335 return status_type
->id
;
339 purple_status_type_get_name(const PurpleStatusType
*status_type
)
341 g_return_val_if_fail(status_type
!= NULL
, NULL
);
343 return status_type
->name
;
347 purple_status_type_is_saveable(const PurpleStatusType
*status_type
)
349 g_return_val_if_fail(status_type
!= NULL
, FALSE
);
351 return status_type
->saveable
;
355 purple_status_type_is_user_settable(const PurpleStatusType
*status_type
)
357 g_return_val_if_fail(status_type
!= NULL
, FALSE
);
359 return status_type
->user_settable
;
363 purple_status_type_is_independent(const PurpleStatusType
*status_type
)
365 g_return_val_if_fail(status_type
!= NULL
, FALSE
);
367 return status_type
->independent
;
371 purple_status_type_is_exclusive(const PurpleStatusType
*status_type
)
373 g_return_val_if_fail(status_type
!= NULL
, FALSE
);
375 return !status_type
->independent
;
379 purple_status_type_is_available(const PurpleStatusType
*status_type
)
381 PurpleStatusPrimitive primitive
;
383 g_return_val_if_fail(status_type
!= NULL
, FALSE
);
385 primitive
= purple_status_type_get_primitive(status_type
);
387 return (primitive
== PURPLE_STATUS_AVAILABLE
);
390 PurpleStatusAttribute
*
391 purple_status_type_get_attr(const PurpleStatusType
*status_type
, const char *id
)
395 g_return_val_if_fail(status_type
!= NULL
, NULL
);
396 g_return_val_if_fail(id
!= NULL
, NULL
);
398 for (l
= status_type
->attrs
; l
!= NULL
; l
= l
->next
)
400 PurpleStatusAttribute
*attr
= (PurpleStatusAttribute
*)l
->data
;
402 if (purple_strequal(purple_status_attribute_get_id(attr
), id
))
410 purple_status_type_get_attrs(const PurpleStatusType
*status_type
)
412 g_return_val_if_fail(status_type
!= NULL
, NULL
);
414 return status_type
->attrs
;
417 const PurpleStatusType
*
418 purple_status_type_find_with_id(GList
*status_types
, const char *id
)
420 PurpleStatusType
*status_type
;
422 g_return_val_if_fail(id
!= NULL
, NULL
);
424 while (status_types
!= NULL
)
426 status_type
= status_types
->data
;
428 if (purple_strequal(id
, status_type
->id
))
431 status_types
= status_types
->next
;
438 /**************************************************************************
439 * PurpleStatusAttribute API
440 **************************************************************************/
441 PurpleStatusAttribute
*
442 purple_status_attribute_new(const char *id
, const char *name
, GValue
*value_type
)
444 PurpleStatusAttribute
*attr
;
446 g_return_val_if_fail(id
!= NULL
, NULL
);
447 g_return_val_if_fail(name
!= NULL
, NULL
);
448 g_return_val_if_fail(value_type
!= NULL
, NULL
);
450 attr
= g_new0(PurpleStatusAttribute
, 1);
451 PURPLE_DBUS_REGISTER_POINTER(attr
, PurpleStatusAttribute
);
453 attr
->id
= g_strdup(id
);
454 attr
->name
= g_strdup(name
);
455 attr
->value_type
= value_type
;
461 purple_status_attribute_destroy(PurpleStatusAttribute
*attr
)
463 g_return_if_fail(attr
!= NULL
);
468 purple_value_free(attr
->value_type
);
470 PURPLE_DBUS_UNREGISTER_POINTER(attr
);
475 purple_status_attribute_get_id(const PurpleStatusAttribute
*attr
)
477 g_return_val_if_fail(attr
!= NULL
, NULL
);
483 purple_status_attribute_get_name(const PurpleStatusAttribute
*attr
)
485 g_return_val_if_fail(attr
!= NULL
, NULL
);
491 purple_status_attribute_get_value(const PurpleStatusAttribute
*attr
)
493 g_return_val_if_fail(attr
!= NULL
, NULL
);
495 return attr
->value_type
;
499 /**************************************************************************
501 **************************************************************************/
503 notify_buddy_status_update(PurpleBuddy
*buddy
, PurplePresence
*presence
,
504 PurpleStatus
*old_status
, PurpleStatus
*new_status
)
506 if (purple_prefs_get_bool("/purple/logging/log_system"))
508 time_t current_time
= time(NULL
);
509 const char *buddy_alias
= purple_buddy_get_alias(buddy
);
513 if (old_status
!= NULL
)
515 tmp
= g_strdup_printf(_("%s (%s) changed status from %s to %s"), buddy_alias
,
516 purple_buddy_get_name(buddy
),
517 purple_status_get_name(old_status
),
518 purple_status_get_name(new_status
));
519 logtmp
= g_markup_escape_text(tmp
, -1);
523 /* old_status == NULL when an independent status is toggled. */
525 if (purple_status_is_active(new_status
))
527 tmp
= g_strdup_printf(_("%s (%s) is now %s"), buddy_alias
,
528 purple_buddy_get_name(buddy
),
529 purple_status_get_name(new_status
));
530 logtmp
= g_markup_escape_text(tmp
, -1);
534 tmp
= g_strdup_printf(_("%s (%s) is no longer %s"), buddy_alias
,
535 purple_buddy_get_name(buddy
),
536 purple_status_get_name(new_status
));
537 logtmp
= g_markup_escape_text(tmp
, -1);
541 log
= purple_account_get_log(purple_buddy_get_account(buddy
), FALSE
);
544 purple_log_write(log
, PURPLE_MESSAGE_SYSTEM
, buddy_alias
,
545 current_time
, logtmp
);
554 notify_status_update(PurplePresence
*presence
, PurpleStatus
*old_status
,
555 PurpleStatus
*new_status
)
557 if (PURPLE_IS_ACCOUNT_PRESENCE(presence
))
559 PurpleAccount
*account
= purple_account_presence_get_account(
560 PURPLE_ACCOUNT_PRESENCE(presence
));
561 PurpleAccountUiOps
*ops
= purple_accounts_get_ui_ops();
563 if (purple_account_get_enabled(account
, purple_core_get_ui()))
564 purple_protocol_change_account_status(account
, old_status
, new_status
);
566 if (ops
!= NULL
&& ops
->status_changed
!= NULL
)
568 ops
->status_changed(account
, new_status
);
571 else if (PURPLE_IS_BUDDY_PRESENCE(presence
))
573 notify_buddy_status_update(purple_buddy_presence_get_buddy(
574 PURPLE_BUDDY_PRESENCE(presence
)), presence
, old_status
,
580 status_has_changed(PurpleStatus
*status
)
582 PurplePresence
*presence
;
583 PurpleStatus
*old_status
;
585 presence
= purple_status_get_presence(status
);
588 * If this status is exclusive, then we must be setting it to "active."
589 * Since we are setting it to active, we want to set the currently
590 * active status to "inactive."
592 if (purple_status_is_exclusive(status
))
594 old_status
= purple_presence_get_active_status(presence
);
595 if (old_status
!= NULL
&& (old_status
!= status
)) {
596 PURPLE_STATUS_GET_PRIVATE(old_status
)->active
= FALSE
;
597 g_object_notify_by_pspec(G_OBJECT(old_status
),
598 properties
[PROP_ACTIVE
]);
604 g_object_set(presence
, "active-status", status
, NULL
);
605 g_object_notify_by_pspec(G_OBJECT(status
), properties
[PROP_ACTIVE
]);
607 notify_status_update(presence
, old_status
, status
);
611 status_set_attr_boolean(PurpleStatus
*status
, const char *id
,
616 g_return_if_fail(PURPLE_IS_STATUS(status
));
617 g_return_if_fail(id
!= NULL
);
619 /* Make sure this attribute exists and is the correct type. */
620 attr_value
= purple_status_get_attr_value(status
, id
);
621 g_return_if_fail(attr_value
!= NULL
);
622 g_return_if_fail(G_VALUE_TYPE(attr_value
) == G_TYPE_BOOLEAN
);
624 g_value_set_boolean(attr_value
, value
);
628 status_set_attr_int(PurpleStatus
*status
, const char *id
, int value
)
632 g_return_if_fail(PURPLE_IS_STATUS(status
));
633 g_return_if_fail(id
!= NULL
);
635 /* Make sure this attribute exists and is the correct type. */
636 attr_value
= purple_status_get_attr_value(status
, id
);
637 g_return_if_fail(attr_value
!= NULL
);
638 g_return_if_fail(G_VALUE_TYPE(attr_value
) == G_TYPE_INT
);
640 g_value_set_int(attr_value
, value
);
644 status_set_attr_string(PurpleStatus
*status
, const char *id
,
649 g_return_if_fail(PURPLE_IS_STATUS(status
));
650 g_return_if_fail(id
!= NULL
);
652 /* Make sure this attribute exists and is the correct type. */
653 attr_value
= purple_status_get_attr_value(status
, id
);
654 /* This used to be g_return_if_fail, but it's failing a LOT, so
655 * let's generate a log error for now. */
656 /* g_return_if_fail(attr_value != NULL); */
657 if (attr_value
== NULL
) {
658 purple_debug_error("status",
659 "Attempted to set status attribute '%s' for "
660 "status '%s', which is not legal. Fix "
662 purple_status_type_get_name(purple_status_get_status_type(status
)));
665 g_return_if_fail(G_VALUE_TYPE(attr_value
) == G_TYPE_STRING
);
667 /* XXX: Check if the value has actually changed. If it has, and the status
668 * is active, should this trigger 'status_has_changed'? */
669 g_value_set_string(attr_value
, value
);
673 purple_status_set_active(PurpleStatus
*status
, gboolean active
)
675 purple_status_set_active_with_attrs_list(status
, active
, NULL
);
679 * This used to parse the va_list directly, but now it creates a GList
680 * and passes it to purple_status_set_active_with_attrs_list(). That
681 * function was created because account.c needs to pass a GList of
682 * attributes to the status API.
685 purple_status_set_active_with_attrs(PurpleStatus
*status
, gboolean active
, va_list args
)
691 while ((id
= va_arg(args
, const char *)) != NULL
)
693 attrs
= g_list_append(attrs
, (char *)id
);
694 data
= va_arg(args
, void *);
695 attrs
= g_list_append(attrs
, data
);
697 purple_status_set_active_with_attrs_list(status
, active
, attrs
);
702 purple_status_set_active_with_attrs_list(PurpleStatus
*status
, gboolean active
,
705 gboolean changed
= FALSE
;
707 GList
*specified_attr_ids
= NULL
;
708 PurpleStatusType
*status_type
;
709 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
711 g_return_if_fail(priv
!= NULL
);
713 if (!active
&& purple_status_is_exclusive(status
))
715 purple_debug_error("status",
716 "Cannot deactivate an exclusive status (%s).\n",
717 purple_status_get_id(status
));
721 if (priv
->active
!= active
)
726 priv
->active
= active
;
728 /* Set any attributes */
737 value
= purple_status_get_attr_value(status
, id
);
740 purple_debug_warning("status", "The attribute \"%s\" on the status \"%s\" is "
741 "not supported.\n", id
, priv
->status_type
->name
);
742 /* Skip over the data and move on to the next attribute */
747 specified_attr_ids
= g_list_prepend(specified_attr_ids
, (gpointer
)id
);
749 if (G_VALUE_TYPE(value
) == G_TYPE_STRING
)
751 const gchar
*string_data
= l
->data
;
753 if (purple_strequal(string_data
, g_value_get_string(value
)))
755 status_set_attr_string(status
, id
, string_data
);
758 else if (G_VALUE_TYPE(value
) == G_TYPE_INT
)
760 int int_data
= GPOINTER_TO_INT(l
->data
);
762 if (int_data
== g_value_get_int(value
))
764 status_set_attr_int(status
, id
, int_data
);
767 else if (G_VALUE_TYPE(value
) == G_TYPE_BOOLEAN
)
769 gboolean boolean_data
= GPOINTER_TO_INT(l
->data
);
771 if (boolean_data
== g_value_get_boolean(value
))
773 status_set_attr_boolean(status
, id
, boolean_data
);
778 /* We don't know what the data is--skip over it */
783 /* Reset any unspecified attributes to their default value */
784 status_type
= purple_status_get_status_type(status
);
785 l
= purple_status_type_get_attrs(status_type
);
787 PurpleStatusAttribute
*attr
;
792 if (!g_list_find_custom(specified_attr_ids
, attr
->id
, (GCompareFunc
)strcmp
)) {
793 GValue
*default_value
;
794 default_value
= purple_status_attribute_get_value(attr
);
795 if (G_VALUE_TYPE(default_value
) == G_TYPE_STRING
) {
796 const char *cur
= purple_status_get_attr_string(status
, attr
->id
);
797 const char *def
= g_value_get_string(default_value
);
798 if ((cur
== NULL
&& def
== NULL
)
799 || (cur
!= NULL
&& def
!= NULL
800 && !strcmp(cur
, def
))) {
804 status_set_attr_string(status
, attr
->id
, def
);
805 } else if (G_VALUE_TYPE(default_value
) == G_TYPE_INT
) {
806 int cur
= purple_status_get_attr_int(status
, attr
->id
);
807 int def
= g_value_get_int(default_value
);
811 status_set_attr_int(status
, attr
->id
, def
);
812 } else if (G_VALUE_TYPE(default_value
) == G_TYPE_BOOLEAN
) {
813 gboolean cur
= purple_status_get_attr_boolean(status
, attr
->id
);
814 gboolean def
= g_value_get_boolean(default_value
);
818 status_set_attr_boolean(status
, attr
->id
, def
);
823 g_list_free(specified_attr_ids
);
827 status_has_changed(status
);
831 purple_status_get_status_type(const PurpleStatus
*status
)
833 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
835 g_return_val_if_fail(priv
!= NULL
, NULL
);
837 return priv
->status_type
;
841 purple_status_get_presence(const PurpleStatus
*status
)
843 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
845 g_return_val_if_fail(priv
!= NULL
, NULL
);
847 return priv
->presence
;
851 purple_status_get_id(const PurpleStatus
*status
)
853 g_return_val_if_fail(PURPLE_IS_STATUS(status
), NULL
);
855 return purple_status_type_get_id(purple_status_get_status_type(status
));
859 purple_status_get_name(const PurpleStatus
*status
)
861 g_return_val_if_fail(PURPLE_IS_STATUS(status
), NULL
);
863 return purple_status_type_get_name(purple_status_get_status_type(status
));
867 purple_status_is_independent(const PurpleStatus
*status
)
869 g_return_val_if_fail(PURPLE_IS_STATUS(status
), FALSE
);
871 return purple_status_type_is_independent(purple_status_get_status_type(status
));
875 purple_status_is_exclusive(const PurpleStatus
*status
)
877 g_return_val_if_fail(PURPLE_IS_STATUS(status
), FALSE
);
879 return purple_status_type_is_exclusive(purple_status_get_status_type(status
));
883 purple_status_is_available(const PurpleStatus
*status
)
885 g_return_val_if_fail(PURPLE_IS_STATUS(status
), FALSE
);
887 return purple_status_type_is_available(purple_status_get_status_type(status
));
891 purple_status_is_active(const PurpleStatus
*status
)
893 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
895 g_return_val_if_fail(priv
!= NULL
, FALSE
);
901 purple_status_is_online(const PurpleStatus
*status
)
903 PurpleStatusPrimitive primitive
;
905 g_return_val_if_fail(PURPLE_IS_STATUS(status
), FALSE
);
907 primitive
= purple_status_type_get_primitive(purple_status_get_status_type(status
));
909 return (primitive
!= PURPLE_STATUS_UNSET
&&
910 primitive
!= PURPLE_STATUS_OFFLINE
);
914 purple_status_get_attr_value(const PurpleStatus
*status
, const char *id
)
916 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
918 g_return_val_if_fail(priv
!= NULL
, NULL
);
919 g_return_val_if_fail(id
!= NULL
, NULL
);
921 return (GValue
*)g_hash_table_lookup(priv
->attr_values
, id
);
925 purple_status_get_attr_boolean(const PurpleStatus
*status
, const char *id
)
929 g_return_val_if_fail(PURPLE_IS_STATUS(status
), FALSE
);
930 g_return_val_if_fail(id
!= NULL
, FALSE
);
932 if ((value
= purple_status_get_attr_value(status
, id
)) == NULL
)
935 g_return_val_if_fail(G_VALUE_TYPE(value
) == G_TYPE_BOOLEAN
, FALSE
);
937 return g_value_get_boolean(value
);
941 purple_status_get_attr_int(const PurpleStatus
*status
, const char *id
)
945 g_return_val_if_fail(PURPLE_IS_STATUS(status
), 0);
946 g_return_val_if_fail(id
!= NULL
, 0);
948 if ((value
= purple_status_get_attr_value(status
, id
)) == NULL
)
951 g_return_val_if_fail(G_VALUE_TYPE(value
) == G_TYPE_INT
, 0);
953 return g_value_get_int(value
);
957 purple_status_get_attr_string(const PurpleStatus
*status
, const char *id
)
961 g_return_val_if_fail(PURPLE_IS_STATUS(status
), NULL
);
962 g_return_val_if_fail(id
!= NULL
, NULL
);
964 if ((value
= purple_status_get_attr_value(status
, id
)) == NULL
)
967 g_return_val_if_fail(G_VALUE_TYPE(value
) == G_TYPE_STRING
, NULL
);
969 return g_value_get_string(value
);
973 purple_status_compare(const PurpleStatus
*status1
, const PurpleStatus
*status2
)
975 PurpleStatusType
*type1
, *type2
;
976 int score1
= 0, score2
= 0;
978 if ((status1
== NULL
&& status2
== NULL
) ||
979 (status1
== status2
))
983 else if (status1
== NULL
)
985 else if (status2
== NULL
)
988 type1
= purple_status_get_status_type(status1
);
989 type2
= purple_status_get_status_type(status2
);
991 if (purple_status_is_active(status1
))
992 score1
= primitive_scores
[purple_status_type_get_primitive(type1
)];
994 if (purple_status_is_active(status2
))
995 score2
= primitive_scores
[purple_status_type_get_primitive(type2
)];
999 else if (score1
< score2
)
1006 /**************************************************************************
1007 * GBoxed code for PurpleStatusType
1008 **************************************************************************/
1009 static PurpleStatusType
*
1010 purple_status_type_ref(PurpleStatusType
*status_type
)
1012 g_return_val_if_fail(status_type
!= NULL
, NULL
);
1014 status_type
->box_count
++;
1020 purple_status_type_unref(PurpleStatusType
*status_type
)
1022 g_return_if_fail(status_type
!= NULL
);
1023 g_return_if_fail(status_type
->box_count
>= 0);
1025 if (!status_type
->box_count
--)
1026 purple_status_type_destroy(status_type
);
1030 purple_status_type_get_type(void)
1032 static GType type
= 0;
1035 type
= g_boxed_type_register_static("PurpleStatusType",
1036 (GBoxedCopyFunc
)purple_status_type_ref
,
1037 (GBoxedFreeFunc
)purple_status_type_unref
);
1043 /**************************************************************************
1044 * GBoxed code for PurpleStatusAttribute
1045 **************************************************************************/
1046 static PurpleStatusAttribute
*
1047 purple_status_attribute_copy(PurpleStatusAttribute
*status_attr
)
1049 g_return_val_if_fail(status_attr
!= NULL
, NULL
);
1051 return purple_status_attribute_new(status_attr
->id
,
1053 purple_value_dup(status_attr
->value_type
));
1057 purple_status_attribute_get_type(void)
1059 static GType type
= 0;
1062 type
= g_boxed_type_register_static("PurpleStatusAttribute",
1063 (GBoxedCopyFunc
)purple_status_attribute_copy
,
1064 (GBoxedFreeFunc
)purple_status_attribute_destroy
);
1070 /**************************************************************************
1071 * GBoxed code for PurpleMood
1072 **************************************************************************/
1074 purple_mood_copy(PurpleMood
*mood
)
1076 PurpleMood
*mood_copy
;
1078 g_return_val_if_fail(mood
!= NULL
, NULL
);
1080 mood_copy
= g_new(PurpleMood
, 1);
1082 mood_copy
->mood
= g_strdup(mood
->mood
);
1083 mood_copy
->description
= g_strdup(mood
->description
);
1089 purple_mood_free(PurpleMood
*mood
)
1091 g_free((gchar
*)mood
->mood
);
1092 g_free((gchar
*)mood
->description
);
1098 purple_mood_get_type(void)
1100 static GType type
= 0;
1103 type
= g_boxed_type_register_static("PurpleMood",
1104 (GBoxedCopyFunc
)purple_mood_copy
,
1105 (GBoxedFreeFunc
)purple_mood_free
);
1112 /**************************************************************************
1114 **************************************************************************/
1116 /* Set method for GObject properties */
1118 purple_status_set_property(GObject
*obj
, guint param_id
, const GValue
*value
,
1121 PurpleStatus
*status
= PURPLE_STATUS(obj
);
1122 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
1125 case PROP_STATUS_TYPE
:
1126 priv
->status_type
= g_value_get_pointer(value
);
1129 priv
->presence
= g_value_get_object(value
);
1132 purple_status_set_active(status
, g_value_get_boolean(value
));
1135 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
1140 /* Get method for GObject properties */
1142 purple_status_get_property(GObject
*obj
, guint param_id
, GValue
*value
,
1145 PurpleStatus
*status
= PURPLE_STATUS(obj
);
1148 case PROP_STATUS_TYPE
:
1149 g_value_set_pointer(value
, purple_status_get_status_type(status
));
1152 g_value_set_object(value
, purple_status_get_presence(status
));
1155 g_value_set_boolean(value
, purple_status_is_active(status
));
1158 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
1163 /* GObject initialization function */
1165 purple_status_init(GTypeInstance
*instance
, gpointer klass
)
1167 PurpleStatus
*status
= PURPLE_STATUS(instance
);
1169 PURPLE_DBUS_REGISTER_POINTER(status
, PurpleStatus
);
1171 PURPLE_STATUS_GET_PRIVATE(status
)->attr_values
=
1172 g_hash_table_new_full(g_str_hash
, g_str_equal
, NULL
,
1173 (GDestroyNotify
)purple_value_free
);
1176 /* Called when done constructing */
1178 purple_status_constructed(GObject
*object
)
1181 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(object
);
1183 parent_class
->constructed(object
);
1185 for (l
= purple_status_type_get_attrs(priv
->status_type
); l
!= NULL
; l
= l
->next
)
1187 PurpleStatusAttribute
*attr
= (PurpleStatusAttribute
*)l
->data
;
1188 GValue
*value
= purple_status_attribute_get_value(attr
);
1189 GValue
*new_value
= purple_value_dup(value
);
1191 g_hash_table_insert(priv
->attr_values
,
1192 (char *)purple_status_attribute_get_id(attr
),
1198 * GObject finalize function
1199 * TODO: If the PurpleStatus is in a PurplePresence, then
1200 * remove it from the PurplePresence?
1203 purple_status_finalize(GObject
*object
)
1205 g_hash_table_destroy(PURPLE_STATUS_GET_PRIVATE(object
)->attr_values
);
1207 PURPLE_DBUS_UNREGISTER_POINTER(object
);
1209 parent_class
->finalize(object
);
1212 /* Class initializer function */
1214 purple_status_class_init(PurpleStatusClass
*klass
)
1216 GObjectClass
*obj_class
= G_OBJECT_CLASS(klass
);
1218 parent_class
= g_type_class_peek_parent(klass
);
1220 obj_class
->finalize
= purple_status_finalize
;
1221 obj_class
->constructed
= purple_status_constructed
;
1223 /* Setup properties */
1224 obj_class
->get_property
= purple_status_get_property
;
1225 obj_class
->set_property
= purple_status_set_property
;
1227 g_type_class_add_private(klass
, sizeof(PurpleStatusPrivate
));
1229 properties
[PROP_STATUS_TYPE
] = g_param_spec_pointer("status-type",
1231 "The PurpleStatusType of the status.",
1232 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
|
1233 G_PARAM_STATIC_STRINGS
);
1235 properties
[PROP_PRESENCE
] = g_param_spec_object("presence", "Presence",
1236 "The presence that the status belongs to.",
1237 PURPLE_TYPE_PRESENCE
,
1238 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
|
1239 G_PARAM_STATIC_STRINGS
);
1241 properties
[PROP_ACTIVE
] = g_param_spec_boolean("active", "Active",
1242 "Whether the status is active or not.", FALSE
,
1243 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1245 g_object_class_install_properties(obj_class
, PROP_LAST
, properties
);
1249 purple_status_get_type(void)
1251 static GType type
= 0;
1254 static const GTypeInfo info
= {
1255 sizeof(PurpleStatusClass
),
1258 (GClassInitFunc
)purple_status_class_init
,
1261 sizeof(PurpleStatus
),
1263 (GInstanceInitFunc
)purple_status_init
,
1267 type
= g_type_register_static(G_TYPE_OBJECT
,
1276 purple_status_new(PurpleStatusType
*status_type
, PurplePresence
*presence
)
1278 g_return_val_if_fail(status_type
!= NULL
, NULL
);
1279 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence
), NULL
);
1281 return g_object_new(PURPLE_TYPE_STATUS
,
1282 "status-type", status_type
,
1283 "presence", presence
,
1288 /**************************************************************************
1290 **************************************************************************/
1292 score_pref_changed_cb(const char *name
, PurplePrefType type
,
1293 gconstpointer value
, gpointer data
)
1295 int index
= GPOINTER_TO_INT(data
);
1297 primitive_scores
[index
] = GPOINTER_TO_INT(value
);
1301 purple_statuses_get_handle(void) {
1308 purple_statuses_init(void)
1310 void *handle
= purple_statuses_get_handle();
1312 purple_prefs_add_none("/purple/status");
1313 purple_prefs_add_none("/purple/status/scores");
1315 purple_prefs_add_int("/purple/status/scores/offline",
1316 primitive_scores
[PURPLE_STATUS_OFFLINE
]);
1317 purple_prefs_add_int("/purple/status/scores/available",
1318 primitive_scores
[PURPLE_STATUS_AVAILABLE
]);
1319 purple_prefs_add_int("/purple/status/scores/invisible",
1320 primitive_scores
[PURPLE_STATUS_INVISIBLE
]);
1321 purple_prefs_add_int("/purple/status/scores/away",
1322 primitive_scores
[PURPLE_STATUS_AWAY
]);
1323 purple_prefs_add_int("/purple/status/scores/extended_away",
1324 primitive_scores
[PURPLE_STATUS_EXTENDED_AWAY
]);
1325 purple_prefs_add_int("/purple/status/scores/idle",
1326 primitive_scores
[SCORE_IDLE
]);
1327 purple_prefs_add_int("/purple/status/scores/idle_time",
1328 primitive_scores
[SCORE_IDLE_TIME
]);
1329 purple_prefs_add_int("/purple/status/scores/offline_msg",
1330 primitive_scores
[SCORE_OFFLINE_MESSAGE
]);
1332 purple_prefs_connect_callback(handle
, "/purple/status/scores/offline",
1333 score_pref_changed_cb
,
1334 GINT_TO_POINTER(PURPLE_STATUS_OFFLINE
));
1335 purple_prefs_connect_callback(handle
, "/purple/status/scores/available",
1336 score_pref_changed_cb
,
1337 GINT_TO_POINTER(PURPLE_STATUS_AVAILABLE
));
1338 purple_prefs_connect_callback(handle
, "/purple/status/scores/invisible",
1339 score_pref_changed_cb
,
1340 GINT_TO_POINTER(PURPLE_STATUS_INVISIBLE
));
1341 purple_prefs_connect_callback(handle
, "/purple/status/scores/away",
1342 score_pref_changed_cb
,
1343 GINT_TO_POINTER(PURPLE_STATUS_AWAY
));
1344 purple_prefs_connect_callback(handle
, "/purple/status/scores/extended_away",
1345 score_pref_changed_cb
,
1346 GINT_TO_POINTER(PURPLE_STATUS_EXTENDED_AWAY
));
1347 purple_prefs_connect_callback(handle
, "/purple/status/scores/idle",
1348 score_pref_changed_cb
,
1349 GINT_TO_POINTER(SCORE_IDLE
));
1350 purple_prefs_connect_callback(handle
, "/purple/status/scores/idle_time",
1351 score_pref_changed_cb
,
1352 GINT_TO_POINTER(SCORE_IDLE_TIME
));
1353 purple_prefs_connect_callback(handle
, "/purple/status/scores/offline_msg",
1354 score_pref_changed_cb
,
1355 GINT_TO_POINTER(SCORE_OFFLINE_MESSAGE
));
1357 purple_prefs_trigger_callback("/purple/status/scores/offline");
1358 purple_prefs_trigger_callback("/purple/status/scores/available");
1359 purple_prefs_trigger_callback("/purple/status/scores/invisible");
1360 purple_prefs_trigger_callback("/purple/status/scores/away");
1361 purple_prefs_trigger_callback("/purple/status/scores/extended_away");
1362 purple_prefs_trigger_callback("/purple/status/scores/idle");
1363 purple_prefs_trigger_callback("/purple/status/scores/idle_time");
1364 purple_prefs_trigger_callback("/purple/status/scores/offline_msg");
1368 purple_statuses_uninit(void)
1370 purple_prefs_disconnect_by_handle(purple_prefs_get_handle());