diff options
author | Gary Kramlich <grim@reaperworld.com> | 2023-04-25 00:46:17 -0500 |
---|---|---|
committer | Gary Kramlich <grim@reaperworld.com> | 2023-04-25 00:46:17 -0500 |
commit | 4c706c2b0b728e39c977672a8f9ca1b034fbd3eb (patch) | |
tree | 1bfc8aebbaa2a449ffb54cfaa20adf450616a496 | |
parent | e0528d1cf31b55507d2fbfce27128fd6284708bc (diff) | |
download | pidgin-4c706c2b0b728e39c977672a8f9ca1b034fbd3eb.tar.gz |
Create PurpleSavedPresence for saving the users presences
Testing Done:
Ran the unit tests.
Bugs closed: PIDGIN-17795
Reviewed at https://reviews.imfreedom.org/r/2440/
-rw-r--r-- | libpurple/meson.build | 2 | ||||
-rw-r--r-- | libpurple/purplesavedpresence.c | 376 | ||||
-rw-r--r-- | libpurple/purplesavedpresence.h | 197 | ||||
-rw-r--r-- | libpurple/tests/meson.build | 1 | ||||
-rw-r--r-- | libpurple/tests/test_saved_presence.c | 111 |
5 files changed, 687 insertions, 0 deletions
diff --git a/libpurple/meson.build b/libpurple/meson.build index 8921fb04ac..ce6cf33cd2 100644 --- a/libpurple/meson.build +++ b/libpurple/meson.build @@ -88,6 +88,7 @@ purple_coresources = [ 'purplerequestgroup.c', 'purplerequestpage.c', 'purpleroomlistroom.c', + 'purplesavedpresence.c', 'purplesqlite3.c', 'purplesqlitehistoryadapter.c', 'purpletags.c', @@ -205,6 +206,7 @@ purple_coreheaders = [ 'purplerequestgroup.h', 'purplerequestpage.h', 'purpleroomlistroom.h', + 'purplesavedpresence.h', 'purplesqlite3.h', 'purplesqlitehistoryadapter.h', 'purpletags.h', diff --git a/libpurple/purplesavedpresence.c b/libpurple/purplesavedpresence.c new file mode 100644 index 0000000000..604896c362 --- /dev/null +++ b/libpurple/purplesavedpresence.c @@ -0,0 +1,376 @@ +/* + * purple + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#include <glib/gi18n-lib.h> + +#include "purpleenums.h" +#include "purplesavedpresence.h" +#include "util.h" + +struct _PurpleSavedPresence { + GObject parent; + + GDateTime *last_used; + guint use_count; + + char *name; + + PurplePresencePrimitive primitive; + char *message; + char *emoji; +}; + +enum { + PROP_0, + PROP_LAST_USED, + PROP_USE_COUNT, + PROP_NAME, + PROP_PRIMITIVE, + PROP_MESSAGE, + PROP_EMOJI, + N_PROPERTIES +}; +static GParamSpec *properties[N_PROPERTIES]; + +G_DEFINE_TYPE(PurpleSavedPresence, purple_saved_presence, G_TYPE_OBJECT) + +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +static void +purple_saved_presence_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleSavedPresence *presence = PURPLE_SAVED_PRESENCE(obj); + + switch(param_id) { + case PROP_LAST_USED: + purple_saved_presence_set_last_used(presence, + g_value_get_boxed(value)); + break; + case PROP_USE_COUNT: + purple_saved_presence_set_use_count(presence, + g_value_get_uint(value)); + break; + case PROP_NAME: + purple_saved_presence_set_name(presence, + g_value_get_string(value)); + break; + case PROP_PRIMITIVE: + purple_saved_presence_set_primitive(presence, + g_value_get_enum(value)); + break; + case PROP_MESSAGE: + purple_saved_presence_set_message(presence, + g_value_get_string(value)); + break; + case PROP_EMOJI: + purple_saved_presence_set_emoji(presence, + g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_saved_presence_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleSavedPresence *presence = PURPLE_SAVED_PRESENCE(obj); + + switch(param_id) { + case PROP_LAST_USED: + g_value_set_boxed(value, + purple_saved_presence_get_last_used(presence)); + break; + case PROP_USE_COUNT: + g_value_set_uint(value, + purple_saved_presence_get_use_count(presence)); + break; + case PROP_NAME: + g_value_set_string(value, + purple_saved_presence_get_name(presence)); + break; + case PROP_PRIMITIVE: + g_value_set_enum(value, + purple_saved_presence_get_primitive(presence)); + break; + case PROP_MESSAGE: + g_value_set_string(value, + purple_saved_presence_get_message(presence)); + break; + case PROP_EMOJI: + g_value_set_string(value, + purple_saved_presence_get_emoji(presence)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_saved_presence_init(G_GNUC_UNUSED PurpleSavedPresence *presence) { +} + +static void +purple_saved_presence_finalize(GObject *obj) { + PurpleSavedPresence *presence = PURPLE_SAVED_PRESENCE(obj); + + g_clear_pointer(&presence->last_used, g_date_time_unref); + + g_clear_pointer(&presence->name, g_free); + g_clear_pointer(&presence->message, g_free); + g_clear_pointer(&presence->emoji, g_free); + + G_OBJECT_CLASS(purple_saved_presence_parent_class)->finalize(obj); +} + +static void +purple_saved_presence_class_init(PurpleSavedPresenceClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + obj_class->get_property = purple_saved_presence_get_property; + obj_class->set_property = purple_saved_presence_set_property; + obj_class->finalize = purple_saved_presence_finalize; + + /** + * PurpleSavedPresence:last-used: + * + * The [struct@GLib.DateTime] when this saved presence was last used. + * + * Since: 3.0.0 + */ + properties[PROP_LAST_USED] = g_param_spec_boxed( + "last-used", "last-used", + "The time this presence was last used.", + G_TYPE_DATE_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * PurpleSavedPresence:use-count: + * + * The number of times this saved presence has been used. + * + * Since: 3.0.0 + */ + properties[PROP_USE_COUNT] = g_param_spec_uint( + "use-count", "use-count", + "The number of times this saved presence has been used.", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * PurpleSavedPresence:name: + * + * The name of the saved presence. + * + * Since: 3.0.0 + */ + properties[PROP_NAME] = g_param_spec_string( + "name", "name", + "The name of this saved presence.", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * PurpleSavedPresence:primitive: + * + * The [enum@Purple.StatusPrimitive] for this saved presence. + * + * Since: 3.0.0 + */ + properties[PROP_PRIMITIVE] = g_param_spec_enum( + "primitive", "primitive", + "The primitive for this saved presence.", + PURPLE_TYPE_PRESENCE_PRIMITIVE, + PURPLE_PRESENCE_PRIMITIVE_OFFLINE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * PurpleSavedPresence:message: + * + * The status message of this saved presence. + * + * Since: 3.0.0 + */ + properties[PROP_MESSAGE] = g_param_spec_string( + "message", "message", + "The status message of this saved presence.", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * PurpleSavedPresence:emoji: + * + * The emoji or mood of the presence. + * + * Since: 3.0.0 + */ + properties[PROP_EMOJI] = g_param_spec_string( + "emoji", "emoji", + "The emoji for this saved presence.", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(obj_class, N_PROPERTIES, properties); +} + +/****************************************************************************** + * Public API + *****************************************************************************/ +PurpleSavedPresence * +purple_saved_presence_new(void) { + return g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL); +} + +GDateTime * +purple_saved_presence_get_last_used(PurpleSavedPresence *presence) { + g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), NULL); + + return presence->last_used; +} + +void +purple_saved_presence_set_last_used(PurpleSavedPresence *presence, + GDateTime *last_used) +{ + g_return_if_fail(PURPLE_IS_SAVED_PRESENCE(presence)); + + if(presence->last_used != last_used) { + g_clear_pointer(&presence->last_used, g_date_time_unref); + if(last_used != NULL) { + presence->last_used = g_date_time_ref(last_used); + } + + g_object_notify_by_pspec(G_OBJECT(presence), + properties[PROP_LAST_USED]); + } +} + +guint +purple_saved_presence_get_use_count(PurpleSavedPresence *presence) { + g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), 0); + + return presence->use_count; +} + +void +purple_saved_presence_set_use_count(PurpleSavedPresence *presence, + guint use_count) +{ + g_return_if_fail(PURPLE_IS_SAVED_PRESENCE(presence)); + + if(presence->use_count != use_count) { + presence->use_count = use_count; + + g_object_notify_by_pspec(G_OBJECT(presence), + properties[PROP_USE_COUNT]); + } +} + +const char * +purple_saved_presence_get_name(PurpleSavedPresence *presence) { + g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), NULL); + + return presence->name; +} + +void +purple_saved_presence_set_name(PurpleSavedPresence *presence, + const char *name) +{ + g_return_if_fail(PURPLE_IS_SAVED_PRESENCE(presence)); + + if(!purple_strequal(presence->name, name)) { + g_free(presence->name); + presence->name = g_strdup(name); + + g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_NAME]); + } +} + +PurplePresencePrimitive +purple_saved_presence_get_primitive(PurpleSavedPresence *presence) { + g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), + PURPLE_PRESENCE_PRIMITIVE_OFFLINE); + + return presence->primitive; +} + +void +purple_saved_presence_set_primitive(PurpleSavedPresence *presence, + PurplePresencePrimitive primitive) +{ + g_return_if_fail(PURPLE_IS_SAVED_PRESENCE(presence)); + + if(presence->primitive != primitive) { + presence->primitive = primitive; + + g_object_notify_by_pspec(G_OBJECT(presence), + properties[PROP_PRIMITIVE]); + } +} + +const char * +purple_saved_presence_get_message(PurpleSavedPresence *presence) { + g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), NULL); + + return presence->message; +} + +void +purple_saved_presence_set_message(PurpleSavedPresence *presence, + const char *message) +{ + g_return_if_fail(PURPLE_IS_SAVED_PRESENCE(presence)); + + if(!purple_strequal(presence->message, message)) { + g_free(presence->message); + presence->message = g_strdup(message); + + g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_MESSAGE]); + } +} + +const char * +purple_saved_presence_get_emoji(PurpleSavedPresence *presence) { + g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), NULL); + + return presence->emoji; +} + +void +purple_saved_presence_set_emoji(PurpleSavedPresence *presence, + const char *emoji) +{ + g_return_if_fail(PURPLE_IS_SAVED_PRESENCE(presence)); + + if(!purple_strequal(presence->emoji, emoji)) { + g_free(presence->emoji); + presence->emoji = g_strdup(emoji); + + g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_EMOJI]); + } +} diff --git a/libpurple/purplesavedpresence.h b/libpurple/purplesavedpresence.h new file mode 100644 index 0000000000..c9f7bcaba1 --- /dev/null +++ b/libpurple/purplesavedpresence.h @@ -0,0 +1,197 @@ +/* + * Purple - Internet Messaging Library + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION) +# error "only <purple.h> may be included directly" +#endif + +#ifndef PURPLE_SAVED_PRESENCE_H +#define PURPLE_SAVED_PRESENCE_H + +#include <glib.h> +#include <glib-object.h> + +#include <libpurple/purplepresence.h> + +G_BEGIN_DECLS + +#define PURPLE_TYPE_SAVED_PRESENCE purple_saved_presence_get_type() +G_DECLARE_FINAL_TYPE(PurpleSavedPresence, purple_saved_presence, PURPLE, + SAVED_PRESENCE, GObject) + +/** + * purple_saved_presence_new: + * + * Creates a new saved_presence instance. + * + * Returns: (transfer full): The new instance. + * + * Since: 3.0.0 + */ +PurpleSavedPresence *purple_saved_presence_new(void); + +/** + * purple_saved_presence_get_last_used: + * @presence: The instance. + * + * Gets the [struct@GLib.DateTime] that @presence was last used. + * + * Returns: (transfer none) (nullable): The time @presence was last used or + * %NULL. + * + * Since: 3.0.0 + */ +GDateTime *purple_saved_presence_get_last_used(PurpleSavedPresence *presence); + +/** + * purple_saved_presence_set_last_used: + * @presence: The instance. + * @last_used: (nullable): The time this was last used. + * + * Sets the last time @presence was used to @last_used. If @last_used is %NULL, + * the time will be cleared. + * + * Since: 3.0.0 + */ +void purple_saved_presence_set_last_used(PurpleSavedPresence *presence, GDateTime *last_used); + +/** + * purple_saved_presence_get_use_count: + * @presence: The instance. + * + * Gets the number of times @presence has been used. + * + * Returns: The number of times @presence has been used. + * + * Since: 3.0.0 + */ +guint purple_saved_presence_get_use_count(PurpleSavedPresence *presence); + +/** + * purple_saved_presence_set_use_count: + * @presence: The instance. + * @use_count: The new use count. + * + * Sets the number of times @presence has been used to @use_count. + * + * Since: 3.0.0 + */ +void purple_saved_presence_set_use_count(PurpleSavedPresence *presence, guint use_count); + +/** + * purple_saved_presence_get_name: + * @presence: The instance. + * + * Gets the name of @presence. + * + * Returns: (nullable): The name of @presence. + * + * Since: 3.0.0 + */ +const char *purple_saved_presence_get_name(PurpleSavedPresence *presence); + +/** + * purple_saved_presence_set_name: + * @presence: The instance. + * @name: (nullable): The new name. + * + * Sets the name of @presence to @name. If @name is %NULL the name will be + * cleared. + * + * Since: 3.0.0 + */ +void purple_saved_presence_set_name(PurpleSavedPresence *presence, const char *name); + +/** + * purple_saved_presence_get_primitive: + * @presence: The instance. + * + * Gets the [enum@PresencePrimitive] for @presence. + * + * Returns: The [enum@PresencePrimitive] for @presence. + * + * Since: 3.0.0 + */ +PurplePresencePrimitive purple_saved_presence_get_primitive(PurpleSavedPresence *presence); + +/** + * purple_saved_presence_set_primitive: + * @presence: The instance. + * @primitive: The new primitive. + * + * Sets the [enum@PresencePrimitive] of @presence to @primitive. + * + * Since: 3.0.0 + */ +void purple_saved_presence_set_primitive(PurpleSavedPresence *presence, PurplePresencePrimitive primitive); + +/** + * purple_saved_presence_get_message: + * @presence: The instance. + * + * Gets the message of @presence. + * + * Returns: (nullable): The message from @presence. + * + * Since: 3.0.0 + */ +const char *purple_saved_presence_get_message(PurpleSavedPresence *presence); + +/** + * purple_saved_presence_set_message: + * @presence: The instance. + * @message: (nullable): The new message. + * + * Sets the message of @presence to @message. If @message is %NULL the message + * is cleared. + * + * Since: 3.0.0 + */ +void purple_saved_presence_set_message(PurpleSavedPresence *presence, const char *message); + +/** + * purple_saved_presence_get_emoji: + * @presence: The instance. + * + * Gets the emoji for @presence. + * + * Returns: (nullable): The emoji for @presence. + * + * Since: 3.0.0 + */ +const char *purple_saved_presence_get_emoji(PurpleSavedPresence *presence); + +/** + * purple_saved_presence_set_emoji: + * @presence: The instance. + * @emoji: (nullable): The new emoji. + * + * Sets the emoji of @presence to @emoji. If @emoji is %NULL, the emoji will be + * cleared. + * + * Since: 3.0.0 + */ +void purple_saved_presence_set_emoji(PurpleSavedPresence *presence, const char *emoji); + +G_END_DECLS + +#endif /* PURPLE_SAVED_PRESENCE_H */ diff --git a/libpurple/tests/meson.build b/libpurple/tests/meson.build index 146ae25fd0..826216cae5 100644 --- a/libpurple/tests/meson.build +++ b/libpurple/tests/meson.build @@ -29,6 +29,7 @@ PROGS = [ 'request_field', 'request_group', 'request_page', + 'saved_presence', 'str', 'tags', 'util', diff --git a/libpurple/tests/test_saved_presence.c b/libpurple/tests/test_saved_presence.c new file mode 100644 index 0000000000..bc55e5b92d --- /dev/null +++ b/libpurple/tests/test_saved_presence.c @@ -0,0 +1,111 @@ +/* + * Purple - Internet Messaging Library + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <https://www.gnu.org/licenses/>. + */ + +#include <glib.h> + +#include <purple.h> + +/****************************************************************************** + * Tests + *****************************************************************************/ +static void +test_purple_saved_presence_new(void) { + PurpleSavedPresence *presence = NULL; + + presence = purple_saved_presence_new(); + g_assert_true(PURPLE_IS_SAVED_PRESENCE(presence)); + + g_clear_object(&presence); +} + +static void +test_purple_saved_presence_properties(void) { + PurpleSavedPresence *presence = NULL; + PurplePresencePrimitive primitive; + GDateTime *last_used = NULL; + GDateTime *last_used1 = NULL; + guint use_count; + char *name; + char *message; + char *emoji; + + last_used = g_date_time_new_now_local(); + + /* Use g_object_new so we can test setting properties by name. All of them + * call the setter methods, so by doing it this way we exercise more of the + * code. + */ + presence = g_object_new( + PURPLE_TYPE_SAVED_PRESENCE, + "last-used", last_used, + "use-count", 123, + "name", "my saved status", + "primitive", PURPLE_PRESENCE_PRIMITIVE_STREAMING, + "message", "I'm live on twitch at https://twitch.tv/rw_grim/", + "emoji", "💀", + NULL); + + /* Now use g_object_get to read all of the properties. */ + g_object_get( + presence, + "last-used", &last_used1, + "use-count", &use_count, + "name", &name, + "primitive", &primitive, + "message", &message, + "emoji", &emoji, + NULL); + + /* Compare all the things. */ + g_assert_nonnull(last_used1); + g_assert_true(g_date_time_equal(last_used, last_used1)); + g_clear_pointer(&last_used1, g_date_time_unref); + + g_assert_cmpuint(use_count, ==, 123); + + g_assert_cmpstr(name, ==, "my saved status"); + g_clear_pointer(&name, g_free); + + g_assert_cmpint(primitive, ==, PURPLE_PRESENCE_PRIMITIVE_STREAMING); + + g_assert_cmpstr(message, ==, + "I'm live on twitch at https://twitch.tv/rw_grim/"); + g_clear_pointer(&message, g_free); + + g_assert_cmpstr(emoji, ==, "💀"); + g_clear_pointer(&emoji, g_free); + + g_clear_pointer(&last_used, g_date_time_unref); + g_clear_object(&presence); +} + +/****************************************************************************** + * Main + *****************************************************************************/ +gint +main(gint argc, gchar *argv[]) { + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/saved-presence/new", + test_purple_saved_presence_new); + g_test_add_func("/saved-presence/properties", + test_purple_saved_presence_properties); + + + return g_test_run(); +} |