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 GDateTime
*current_time
= g_date_time_new_now_utc();
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
);
548 g_date_time_unref(current_time
);
555 notify_status_update(PurplePresence
*presence
, PurpleStatus
*old_status
,
556 PurpleStatus
*new_status
)
558 if (PURPLE_IS_ACCOUNT_PRESENCE(presence
))
560 PurpleAccount
*account
= purple_account_presence_get_account(
561 PURPLE_ACCOUNT_PRESENCE(presence
));
562 PurpleAccountUiOps
*ops
= purple_accounts_get_ui_ops();
564 if (purple_account_get_enabled(account
, purple_core_get_ui()))
565 purple_protocol_change_account_status(account
, old_status
, new_status
);
567 if (ops
!= NULL
&& ops
->status_changed
!= NULL
)
569 ops
->status_changed(account
, new_status
);
572 else if (PURPLE_IS_BUDDY_PRESENCE(presence
))
574 notify_buddy_status_update(purple_buddy_presence_get_buddy(
575 PURPLE_BUDDY_PRESENCE(presence
)), presence
, old_status
,
581 status_has_changed(PurpleStatus
*status
)
583 PurplePresence
*presence
;
584 PurpleStatus
*old_status
;
586 presence
= purple_status_get_presence(status
);
589 * If this status is exclusive, then we must be setting it to "active."
590 * Since we are setting it to active, we want to set the currently
591 * active status to "inactive."
593 if (purple_status_is_exclusive(status
))
595 old_status
= purple_presence_get_active_status(presence
);
596 if (old_status
!= NULL
&& (old_status
!= status
)) {
597 PURPLE_STATUS_GET_PRIVATE(old_status
)->active
= FALSE
;
598 g_object_notify_by_pspec(G_OBJECT(old_status
),
599 properties
[PROP_ACTIVE
]);
605 g_object_set(presence
, "active-status", status
, NULL
);
606 g_object_notify_by_pspec(G_OBJECT(status
), properties
[PROP_ACTIVE
]);
608 notify_status_update(presence
, old_status
, status
);
612 status_set_attr_boolean(PurpleStatus
*status
, const char *id
,
617 g_return_if_fail(PURPLE_IS_STATUS(status
));
618 g_return_if_fail(id
!= NULL
);
620 /* Make sure this attribute exists and is the correct type. */
621 attr_value
= purple_status_get_attr_value(status
, id
);
622 g_return_if_fail(attr_value
!= NULL
);
623 g_return_if_fail(G_VALUE_TYPE(attr_value
) == G_TYPE_BOOLEAN
);
625 g_value_set_boolean(attr_value
, value
);
629 status_set_attr_int(PurpleStatus
*status
, const char *id
, int value
)
633 g_return_if_fail(PURPLE_IS_STATUS(status
));
634 g_return_if_fail(id
!= NULL
);
636 /* Make sure this attribute exists and is the correct type. */
637 attr_value
= purple_status_get_attr_value(status
, id
);
638 g_return_if_fail(attr_value
!= NULL
);
639 g_return_if_fail(G_VALUE_TYPE(attr_value
) == G_TYPE_INT
);
641 g_value_set_int(attr_value
, value
);
645 status_set_attr_string(PurpleStatus
*status
, const char *id
,
650 g_return_if_fail(PURPLE_IS_STATUS(status
));
651 g_return_if_fail(id
!= NULL
);
653 /* Make sure this attribute exists and is the correct type. */
654 attr_value
= purple_status_get_attr_value(status
, id
);
655 /* This used to be g_return_if_fail, but it's failing a LOT, so
656 * let's generate a log error for now. */
657 /* g_return_if_fail(attr_value != NULL); */
658 if (attr_value
== NULL
) {
659 purple_debug_error("status",
660 "Attempted to set status attribute '%s' for "
661 "status '%s', which is not legal. Fix "
663 purple_status_type_get_name(purple_status_get_status_type(status
)));
666 g_return_if_fail(G_VALUE_TYPE(attr_value
) == G_TYPE_STRING
);
668 /* XXX: Check if the value has actually changed. If it has, and the status
669 * is active, should this trigger 'status_has_changed'? */
670 g_value_set_string(attr_value
, value
);
674 purple_status_set_active(PurpleStatus
*status
, gboolean active
)
676 purple_status_set_active_with_attrs_list(status
, active
, NULL
);
680 * This used to parse the va_list directly, but now it creates a GList
681 * and passes it to purple_status_set_active_with_attrs_list(). That
682 * function was created because account.c needs to pass a GList of
683 * attributes to the status API.
686 purple_status_set_active_with_attrs(PurpleStatus
*status
, gboolean active
, va_list args
)
692 while ((id
= va_arg(args
, const char *)) != NULL
)
694 attrs
= g_list_append(attrs
, (char *)id
);
695 data
= va_arg(args
, void *);
696 attrs
= g_list_append(attrs
, data
);
698 purple_status_set_active_with_attrs_list(status
, active
, attrs
);
703 purple_status_set_active_with_attrs_list(PurpleStatus
*status
, gboolean active
,
706 gboolean changed
= FALSE
;
708 GList
*specified_attr_ids
= NULL
;
709 PurpleStatusType
*status_type
;
710 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
712 g_return_if_fail(priv
!= NULL
);
714 if (!active
&& purple_status_is_exclusive(status
))
716 purple_debug_error("status",
717 "Cannot deactivate an exclusive status (%s).\n",
718 purple_status_get_id(status
));
722 if (priv
->active
!= active
)
727 priv
->active
= active
;
729 /* Set any attributes */
738 value
= purple_status_get_attr_value(status
, id
);
741 purple_debug_warning("status", "The attribute \"%s\" on the status \"%s\" is "
742 "not supported.\n", id
, priv
->status_type
->name
);
743 /* Skip over the data and move on to the next attribute */
748 specified_attr_ids
= g_list_prepend(specified_attr_ids
, (gpointer
)id
);
750 if (G_VALUE_TYPE(value
) == G_TYPE_STRING
)
752 const gchar
*string_data
= l
->data
;
754 if (purple_strequal(string_data
, g_value_get_string(value
)))
756 status_set_attr_string(status
, id
, string_data
);
759 else if (G_VALUE_TYPE(value
) == G_TYPE_INT
)
761 int int_data
= GPOINTER_TO_INT(l
->data
);
763 if (int_data
== g_value_get_int(value
))
765 status_set_attr_int(status
, id
, int_data
);
768 else if (G_VALUE_TYPE(value
) == G_TYPE_BOOLEAN
)
770 gboolean boolean_data
= GPOINTER_TO_INT(l
->data
);
772 if (boolean_data
== g_value_get_boolean(value
))
774 status_set_attr_boolean(status
, id
, boolean_data
);
779 /* We don't know what the data is--skip over it */
784 /* Reset any unspecified attributes to their default value */
785 status_type
= purple_status_get_status_type(status
);
786 l
= purple_status_type_get_attrs(status_type
);
788 PurpleStatusAttribute
*attr
;
793 if (!g_list_find_custom(specified_attr_ids
, attr
->id
, (GCompareFunc
)strcmp
)) {
794 GValue
*default_value
;
795 default_value
= purple_status_attribute_get_value(attr
);
796 if (G_VALUE_TYPE(default_value
) == G_TYPE_STRING
) {
797 const char *cur
= purple_status_get_attr_string(status
, attr
->id
);
798 const char *def
= g_value_get_string(default_value
);
799 if (purple_strequal(cur
, def
)) {
803 status_set_attr_string(status
, attr
->id
, def
);
804 } else if (G_VALUE_TYPE(default_value
) == G_TYPE_INT
) {
805 int cur
= purple_status_get_attr_int(status
, attr
->id
);
806 int def
= g_value_get_int(default_value
);
810 status_set_attr_int(status
, attr
->id
, def
);
811 } else if (G_VALUE_TYPE(default_value
) == G_TYPE_BOOLEAN
) {
812 gboolean cur
= purple_status_get_attr_boolean(status
, attr
->id
);
813 gboolean def
= g_value_get_boolean(default_value
);
817 status_set_attr_boolean(status
, attr
->id
, def
);
822 g_list_free(specified_attr_ids
);
826 status_has_changed(status
);
830 purple_status_get_status_type(const PurpleStatus
*status
)
832 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
834 g_return_val_if_fail(priv
!= NULL
, NULL
);
836 return priv
->status_type
;
840 purple_status_get_presence(const PurpleStatus
*status
)
842 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
844 g_return_val_if_fail(priv
!= NULL
, NULL
);
846 return priv
->presence
;
850 purple_status_get_id(const PurpleStatus
*status
)
852 g_return_val_if_fail(PURPLE_IS_STATUS(status
), NULL
);
854 return purple_status_type_get_id(purple_status_get_status_type(status
));
858 purple_status_get_name(const PurpleStatus
*status
)
860 g_return_val_if_fail(PURPLE_IS_STATUS(status
), NULL
);
862 return purple_status_type_get_name(purple_status_get_status_type(status
));
866 purple_status_is_independent(const PurpleStatus
*status
)
868 g_return_val_if_fail(PURPLE_IS_STATUS(status
), FALSE
);
870 return purple_status_type_is_independent(purple_status_get_status_type(status
));
874 purple_status_is_exclusive(const PurpleStatus
*status
)
876 g_return_val_if_fail(PURPLE_IS_STATUS(status
), FALSE
);
878 return purple_status_type_is_exclusive(purple_status_get_status_type(status
));
882 purple_status_is_available(const PurpleStatus
*status
)
884 g_return_val_if_fail(PURPLE_IS_STATUS(status
), FALSE
);
886 return purple_status_type_is_available(purple_status_get_status_type(status
));
890 purple_status_is_active(const PurpleStatus
*status
)
892 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
894 g_return_val_if_fail(priv
!= NULL
, FALSE
);
900 purple_status_is_online(const PurpleStatus
*status
)
902 PurpleStatusPrimitive primitive
;
904 g_return_val_if_fail(PURPLE_IS_STATUS(status
), FALSE
);
906 primitive
= purple_status_type_get_primitive(purple_status_get_status_type(status
));
908 return (primitive
!= PURPLE_STATUS_UNSET
&&
909 primitive
!= PURPLE_STATUS_OFFLINE
);
913 purple_status_get_attr_value(const PurpleStatus
*status
, const char *id
)
915 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
917 g_return_val_if_fail(priv
!= NULL
, NULL
);
918 g_return_val_if_fail(id
!= NULL
, NULL
);
920 return (GValue
*)g_hash_table_lookup(priv
->attr_values
, id
);
924 purple_status_get_attr_boolean(const PurpleStatus
*status
, const char *id
)
928 g_return_val_if_fail(PURPLE_IS_STATUS(status
), FALSE
);
929 g_return_val_if_fail(id
!= NULL
, FALSE
);
931 if ((value
= purple_status_get_attr_value(status
, id
)) == NULL
)
934 g_return_val_if_fail(G_VALUE_TYPE(value
) == G_TYPE_BOOLEAN
, FALSE
);
936 return g_value_get_boolean(value
);
940 purple_status_get_attr_int(const PurpleStatus
*status
, const char *id
)
944 g_return_val_if_fail(PURPLE_IS_STATUS(status
), 0);
945 g_return_val_if_fail(id
!= NULL
, 0);
947 if ((value
= purple_status_get_attr_value(status
, id
)) == NULL
)
950 g_return_val_if_fail(G_VALUE_TYPE(value
) == G_TYPE_INT
, 0);
952 return g_value_get_int(value
);
956 purple_status_get_attr_string(const PurpleStatus
*status
, const char *id
)
960 g_return_val_if_fail(PURPLE_IS_STATUS(status
), NULL
);
961 g_return_val_if_fail(id
!= NULL
, NULL
);
963 if ((value
= purple_status_get_attr_value(status
, id
)) == NULL
)
966 g_return_val_if_fail(G_VALUE_TYPE(value
) == G_TYPE_STRING
, NULL
);
968 return g_value_get_string(value
);
972 purple_status_compare(const PurpleStatus
*status1
, const PurpleStatus
*status2
)
974 PurpleStatusType
*type1
, *type2
;
975 int score1
= 0, score2
= 0;
977 if ((status1
== NULL
&& status2
== NULL
) ||
978 (status1
== status2
))
982 else if (status1
== NULL
)
984 else if (status2
== NULL
)
987 type1
= purple_status_get_status_type(status1
);
988 type2
= purple_status_get_status_type(status2
);
990 if (purple_status_is_active(status1
))
991 score1
= primitive_scores
[purple_status_type_get_primitive(type1
)];
993 if (purple_status_is_active(status2
))
994 score2
= primitive_scores
[purple_status_type_get_primitive(type2
)];
998 else if (score1
< score2
)
1005 /**************************************************************************
1006 * GBoxed code for PurpleStatusType
1007 **************************************************************************/
1008 static PurpleStatusType
*
1009 purple_status_type_ref(PurpleStatusType
*status_type
)
1011 g_return_val_if_fail(status_type
!= NULL
, NULL
);
1013 status_type
->box_count
++;
1019 purple_status_type_unref(PurpleStatusType
*status_type
)
1021 g_return_if_fail(status_type
!= NULL
);
1022 g_return_if_fail(status_type
->box_count
>= 0);
1024 if (!status_type
->box_count
--)
1025 purple_status_type_destroy(status_type
);
1029 purple_status_type_get_type(void)
1031 static GType type
= 0;
1034 type
= g_boxed_type_register_static("PurpleStatusType",
1035 (GBoxedCopyFunc
)purple_status_type_ref
,
1036 (GBoxedFreeFunc
)purple_status_type_unref
);
1042 /**************************************************************************
1043 * GBoxed code for PurpleStatusAttribute
1044 **************************************************************************/
1045 static PurpleStatusAttribute
*
1046 purple_status_attribute_copy(PurpleStatusAttribute
*status_attr
)
1048 g_return_val_if_fail(status_attr
!= NULL
, NULL
);
1050 return purple_status_attribute_new(status_attr
->id
,
1052 purple_value_dup(status_attr
->value_type
));
1056 purple_status_attribute_get_type(void)
1058 static GType type
= 0;
1061 type
= g_boxed_type_register_static("PurpleStatusAttribute",
1062 (GBoxedCopyFunc
)purple_status_attribute_copy
,
1063 (GBoxedFreeFunc
)purple_status_attribute_destroy
);
1069 /**************************************************************************
1070 * GBoxed code for PurpleMood
1071 **************************************************************************/
1073 purple_mood_copy(PurpleMood
*mood
)
1075 PurpleMood
*mood_copy
;
1077 g_return_val_if_fail(mood
!= NULL
, NULL
);
1079 mood_copy
= g_new(PurpleMood
, 1);
1081 mood_copy
->mood
= g_strdup(mood
->mood
);
1082 mood_copy
->description
= g_strdup(mood
->description
);
1088 purple_mood_free(PurpleMood
*mood
)
1090 g_free((gchar
*)mood
->mood
);
1091 g_free((gchar
*)mood
->description
);
1097 purple_mood_get_type(void)
1099 static GType type
= 0;
1102 type
= g_boxed_type_register_static("PurpleMood",
1103 (GBoxedCopyFunc
)purple_mood_copy
,
1104 (GBoxedFreeFunc
)purple_mood_free
);
1111 /**************************************************************************
1113 **************************************************************************/
1115 /* Set method for GObject properties */
1117 purple_status_set_property(GObject
*obj
, guint param_id
, const GValue
*value
,
1120 PurpleStatus
*status
= PURPLE_STATUS(obj
);
1121 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(status
);
1124 case PROP_STATUS_TYPE
:
1125 priv
->status_type
= g_value_get_pointer(value
);
1128 priv
->presence
= g_value_get_object(value
);
1131 purple_status_set_active(status
, g_value_get_boolean(value
));
1134 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
1139 /* Get method for GObject properties */
1141 purple_status_get_property(GObject
*obj
, guint param_id
, GValue
*value
,
1144 PurpleStatus
*status
= PURPLE_STATUS(obj
);
1147 case PROP_STATUS_TYPE
:
1148 g_value_set_pointer(value
, purple_status_get_status_type(status
));
1151 g_value_set_object(value
, purple_status_get_presence(status
));
1154 g_value_set_boolean(value
, purple_status_is_active(status
));
1157 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj
, param_id
, pspec
);
1162 /* GObject initialization function */
1164 purple_status_init(GTypeInstance
*instance
, gpointer klass
)
1166 PurpleStatus
*status
= PURPLE_STATUS(instance
);
1168 PURPLE_DBUS_REGISTER_POINTER(status
, PurpleStatus
);
1170 PURPLE_STATUS_GET_PRIVATE(status
)->attr_values
=
1171 g_hash_table_new_full(g_str_hash
, g_str_equal
, NULL
,
1172 (GDestroyNotify
)purple_value_free
);
1175 /* Called when done constructing */
1177 purple_status_constructed(GObject
*object
)
1180 PurpleStatusPrivate
*priv
= PURPLE_STATUS_GET_PRIVATE(object
);
1182 parent_class
->constructed(object
);
1184 for (l
= purple_status_type_get_attrs(priv
->status_type
); l
!= NULL
; l
= l
->next
)
1186 PurpleStatusAttribute
*attr
= (PurpleStatusAttribute
*)l
->data
;
1187 GValue
*value
= purple_status_attribute_get_value(attr
);
1188 GValue
*new_value
= purple_value_dup(value
);
1190 g_hash_table_insert(priv
->attr_values
,
1191 (char *)purple_status_attribute_get_id(attr
),
1197 * GObject finalize function
1198 * TODO: If the PurpleStatus is in a PurplePresence, then
1199 * remove it from the PurplePresence?
1202 purple_status_finalize(GObject
*object
)
1204 g_hash_table_destroy(PURPLE_STATUS_GET_PRIVATE(object
)->attr_values
);
1206 PURPLE_DBUS_UNREGISTER_POINTER(object
);
1208 parent_class
->finalize(object
);
1211 /* Class initializer function */
1213 purple_status_class_init(PurpleStatusClass
*klass
)
1215 GObjectClass
*obj_class
= G_OBJECT_CLASS(klass
);
1217 parent_class
= g_type_class_peek_parent(klass
);
1219 obj_class
->finalize
= purple_status_finalize
;
1220 obj_class
->constructed
= purple_status_constructed
;
1222 /* Setup properties */
1223 obj_class
->get_property
= purple_status_get_property
;
1224 obj_class
->set_property
= purple_status_set_property
;
1226 g_type_class_add_private(klass
, sizeof(PurpleStatusPrivate
));
1228 properties
[PROP_STATUS_TYPE
] = g_param_spec_pointer("status-type",
1230 "The PurpleStatusType of the status.",
1231 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
|
1232 G_PARAM_STATIC_STRINGS
);
1234 properties
[PROP_PRESENCE
] = g_param_spec_object("presence", "Presence",
1235 "The presence that the status belongs to.",
1236 PURPLE_TYPE_PRESENCE
,
1237 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
|
1238 G_PARAM_STATIC_STRINGS
);
1240 properties
[PROP_ACTIVE
] = g_param_spec_boolean("active", "Active",
1241 "Whether the status is active or not.", FALSE
,
1242 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
1244 g_object_class_install_properties(obj_class
, PROP_LAST
, properties
);
1248 purple_status_get_type(void)
1250 static GType type
= 0;
1253 static const GTypeInfo info
= {
1254 sizeof(PurpleStatusClass
),
1257 (GClassInitFunc
)purple_status_class_init
,
1260 sizeof(PurpleStatus
),
1262 (GInstanceInitFunc
)purple_status_init
,
1266 type
= g_type_register_static(G_TYPE_OBJECT
,
1275 purple_status_new(PurpleStatusType
*status_type
, PurplePresence
*presence
)
1277 g_return_val_if_fail(status_type
!= NULL
, NULL
);
1278 g_return_val_if_fail(PURPLE_IS_PRESENCE(presence
), NULL
);
1280 return g_object_new(PURPLE_TYPE_STATUS
,
1281 "status-type", status_type
,
1282 "presence", presence
,
1287 /**************************************************************************
1289 **************************************************************************/
1291 score_pref_changed_cb(const char *name
, PurplePrefType type
,
1292 gconstpointer value
, gpointer data
)
1294 int index
= GPOINTER_TO_INT(data
);
1296 primitive_scores
[index
] = GPOINTER_TO_INT(value
);
1300 purple_statuses_get_handle(void) {
1307 purple_statuses_init(void)
1309 void *handle
= purple_statuses_get_handle();
1311 purple_prefs_add_none("/purple/status");
1312 purple_prefs_add_none("/purple/status/scores");
1314 purple_prefs_add_int("/purple/status/scores/offline",
1315 primitive_scores
[PURPLE_STATUS_OFFLINE
]);
1316 purple_prefs_add_int("/purple/status/scores/available",
1317 primitive_scores
[PURPLE_STATUS_AVAILABLE
]);
1318 purple_prefs_add_int("/purple/status/scores/invisible",
1319 primitive_scores
[PURPLE_STATUS_INVISIBLE
]);
1320 purple_prefs_add_int("/purple/status/scores/away",
1321 primitive_scores
[PURPLE_STATUS_AWAY
]);
1322 purple_prefs_add_int("/purple/status/scores/extended_away",
1323 primitive_scores
[PURPLE_STATUS_EXTENDED_AWAY
]);
1324 purple_prefs_add_int("/purple/status/scores/idle",
1325 primitive_scores
[SCORE_IDLE
]);
1326 purple_prefs_add_int("/purple/status/scores/idle_time",
1327 primitive_scores
[SCORE_IDLE_TIME
]);
1328 purple_prefs_add_int("/purple/status/scores/offline_msg",
1329 primitive_scores
[SCORE_OFFLINE_MESSAGE
]);
1331 purple_prefs_connect_callback(handle
, "/purple/status/scores/offline",
1332 score_pref_changed_cb
,
1333 GINT_TO_POINTER(PURPLE_STATUS_OFFLINE
));
1334 purple_prefs_connect_callback(handle
, "/purple/status/scores/available",
1335 score_pref_changed_cb
,
1336 GINT_TO_POINTER(PURPLE_STATUS_AVAILABLE
));
1337 purple_prefs_connect_callback(handle
, "/purple/status/scores/invisible",
1338 score_pref_changed_cb
,
1339 GINT_TO_POINTER(PURPLE_STATUS_INVISIBLE
));
1340 purple_prefs_connect_callback(handle
, "/purple/status/scores/away",
1341 score_pref_changed_cb
,
1342 GINT_TO_POINTER(PURPLE_STATUS_AWAY
));
1343 purple_prefs_connect_callback(handle
, "/purple/status/scores/extended_away",
1344 score_pref_changed_cb
,
1345 GINT_TO_POINTER(PURPLE_STATUS_EXTENDED_AWAY
));
1346 purple_prefs_connect_callback(handle
, "/purple/status/scores/idle",
1347 score_pref_changed_cb
,
1348 GINT_TO_POINTER(SCORE_IDLE
));
1349 purple_prefs_connect_callback(handle
, "/purple/status/scores/idle_time",
1350 score_pref_changed_cb
,
1351 GINT_TO_POINTER(SCORE_IDLE_TIME
));
1352 purple_prefs_connect_callback(handle
, "/purple/status/scores/offline_msg",
1353 score_pref_changed_cb
,
1354 GINT_TO_POINTER(SCORE_OFFLINE_MESSAGE
));
1356 purple_prefs_trigger_callback("/purple/status/scores/offline");
1357 purple_prefs_trigger_callback("/purple/status/scores/available");
1358 purple_prefs_trigger_callback("/purple/status/scores/invisible");
1359 purple_prefs_trigger_callback("/purple/status/scores/away");
1360 purple_prefs_trigger_callback("/purple/status/scores/extended_away");
1361 purple_prefs_trigger_callback("/purple/status/scores/idle");
1362 purple_prefs_trigger_callback("/purple/status/scores/idle_time");
1363 purple_prefs_trigger_callback("/purple/status/scores/offline_msg");
1367 purple_statuses_uninit(void)
1369 purple_prefs_disconnect_by_handle(purple_prefs_get_handle());