--- a/libpurple/meson.build Mon Dec 12 04:23:17 2022 -0600
+++ b/libpurple/meson.build Mon Dec 12 23:38:47 2022 -0600
@@ -41,6 +41,7 @@
'purpleaddcontactrequest.c',
'purpleauthorizationrequest.c',
'purplechatconversation.c',
@@ -145,6 +146,7 @@
'purpleaccountusersplit.h',
'purpleaddcontactrequest.h',
'purpleauthorizationrequest.h',
'purplechatconversation.h',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purpleavatar.c Mon Dec 12 23:38:47 2022 -0600
@@ -0,0 +1,228 @@
+ * Purple - Internet Messaging Library + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * 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 "purpleavatar.h" +static GParamSpec *properties[N_PROPERTIES] = {NULL, }; +G_DEFINE_TYPE(PurpleAvatar, purple_avatar, G_TYPE_OBJECT) +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +purple_avatar_get_property(GObject *obj, guint param_id, GValue *value, + PurpleAvatar *avatar = PURPLE_AVATAR(obj); + g_value_set_string(value, purple_avatar_get_filename(avatar)); + g_value_set_object(value, purple_avatar_get_pixbuf(avatar)); + g_value_set_object(value, purple_avatar_get_tags(avatar)); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +purple_avatar_set_property(GObject *obj, guint param_id, const GValue *value, + PurpleAvatar *avatar = PURPLE_AVATAR(obj); + purple_avatar_set_filename(avatar, g_value_get_string(value)); + purple_avatar_set_pixbuf(avatar, g_value_get_object(value)); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +purple_avatar_finalize(GObject *obj) { + PurpleAvatar *avatar = PURPLE_AVATAR(obj); + g_clear_pointer(&avatar->filename, g_free); + g_clear_object(&avatar->pixbuf); + g_clear_object(&avatar->tags); + G_OBJECT_CLASS(purple_avatar_parent_class)->finalize(obj); +purple_avatar_init(PurpleAvatar *avatar) { + avatar->tags = purple_tags_new(); +purple_avatar_class_init(PurpleAvatarClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + obj_class->finalize = purple_avatar_finalize; + obj_class->get_property = purple_avatar_get_property; + obj_class->set_property = purple_avatar_set_property; + * PurpleAvatar:filename: + * The filename to save/load the avatar to/from. + properties[PROP_FILENAME] = g_param_spec_string( + "filename", "filename", + "The filename to save/load the avatar from.", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + * The [class@GdkPixbuf.Pixbuf]. This may be %NULL if + * [method@Purple.Avatar.load] has not yet been called. + properties[PROP_PIXBUF] = g_param_spec_object( + "The pixbuf of the avatar.", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + * The [class@Purple.Tags] for the avatar. + properties[PROP_TAGS] = g_param_spec_object( + "The tags for the avatar.", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties(obj_class, N_PROPERTIES, properties); +/****************************************************************************** + *****************************************************************************/ +purple_avatar_new(const char *filename, GdkPixbuf *pixbuf) { +purple_avatar_get_filename(PurpleAvatar *avatar) { + g_return_val_if_fail(PURPLE_IS_AVATAR(avatar), NULL); + return avatar->filename; +purple_avatar_set_filename(PurpleAvatar *avatar, const char *filename) { + g_return_if_fail(PURPLE_IS_AVATAR(avatar)); + g_free(avatar->filename); + avatar->filename = g_strdup(filename); + g_object_notify_by_pspec(G_OBJECT(avatar), properties[PROP_FILENAME]); +purple_avatar_get_pixbuf(PurpleAvatar *avatar) { + g_return_val_if_fail(PURPLE_IS_AVATAR(avatar), NULL); +purple_avatar_set_pixbuf(PurpleAvatar *avatar, GdkPixbuf *pixbuf) { + g_return_if_fail(PURPLE_IS_AVATAR(avatar)); + if(g_set_object(&avatar->pixbuf, pixbuf)) { + g_object_notify_by_pspec(G_OBJECT(avatar), properties[PROP_PIXBUF]); +purple_avatar_get_tags(PurpleAvatar *avatar) { + g_return_val_if_fail(PURPLE_IS_AVATAR(avatar), NULL); +purple_avatar_load(PurpleAvatar *avatar, GError **error) { + GError *local_error = NULL; + g_return_val_if_fail(PURPLE_IS_AVATAR(avatar), FALSE); + g_clear_object(&avatar->pixbuf); + avatar->pixbuf = gdk_pixbuf_new_from_file(avatar->filename, &local_error); + if(avatar->pixbuf == NULL) { + g_propagate_error(error, local_error); +purple_avatar_save(PurpleAvatar *avatar, GError **error) { + g_return_val_if_fail(PURPLE_IS_AVATAR(avatar), FALSE); + return gdk_pixbuf_save(avatar->pixbuf, avatar->filename, "png", error, + "quality", "100", NULL); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purpleavatar.h Mon Dec 12 23:38:47 2022 -0600
@@ -0,0 +1,151 @@
+ * Purple - Internet Messaging Library + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * 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 <pidgin.h> may be included directly" +#include <glib-object.h> +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <libpurple/purpletags.h> +#define PURPLE_TYPE_AVATAR (purple_avatar_get_type()) +G_DECLARE_FINAL_TYPE(PurpleAvatar, purple_avatar, PURPLE, AVATAR, GObject) + * A representation of an Avatar that is used for accounts, contacts, and + * @filename: (nullable): The filename for the avatar. + * @pixbuf: (nullable): The [class@GdkPixbuf.Pixbuf] to use. + * Creates a new avatar with @filename and @pixbuf. + * Returns: (transfer full): The new instance. +PurpleAvatar *purple_avatar_new(const char *filename, GdkPixbuf *pixbuf); + * purple_avatar_get_filename: + * @avatar: The instance. + * Gets the base filename of @avatar. + * Returns: The base filename of @avatar. +const char *purple_avatar_get_filename(PurpleAvatar *avatar); + * purple_avatar_set_filename: + * @avatar: The instance. + * @filename: The new filename. + * Sets the filename of @avatar to @filename. +void purple_avatar_set_filename(PurpleAvatar *avatar, const char *filename); + * purple_avatar_get_pixbuf: + * @avatar: The instance. + * Gets the [class@GdkPixbuf.Pixbuf] of @avatar. + * Returns: The pixbuf of the avatar which could be %NULL. +GdkPixbuf *purple_avatar_get_pixbuf(PurpleAvatar *avatar); + * purple_avatar_set_pixbuf: + * @avatar: The instance. + * @pixbuf: (nullable): The new [class@GdkPixbuf.Pixbuf]. + * Sets the [class@GdkPixbuf.Pixbuf] for @avatar to @pixbuf. If @pixbuf is + * %NULL, the pixbuf will be cleared. +void purple_avatar_set_pixbuf(PurpleAvatar *avatar, GdkPixbuf *pixbuf); + * purple_avatar_get_tags: + * @avatar: The instance. + * Gets the [class@Purple.Tags] for @avatar. + * Returns: (transfer none): The [class@Purple.Tags] for @avatar. +PurpleTags *purple_avatar_get_tags(PurpleAvatar *avatar); + * @avatar: The instance. + * @error: Return address for a #GError, or %NULL. + * Attempts to load @avatar from disk from [property@Purple.Avatar:filename]. + * If successful, %TRUE is returned, otherwise %FALSE will be returned with + * @error potentially set. + * Returns: %TRUE on success or %FALSE on error with @error potentialy set. +gboolean purple_avatar_load(PurpleAvatar *avatar, GError **error); + * @avatar: The instance. + * @error: Return address for a #GError, or %NULL. + * Attempts to save @avatar to disk using [property@Purple.Avatar:filename]. + * If successful, %TRUE is returned, otherwise %FALSE will be returned with + * @error potentially set. + * Returns: %TRUE on success or %FALSE on error with @error potentialy set. +gboolean purple_avatar_save(PurpleAvatar *avatar, GError **error); +#endif /* PURPLE_AVATAR_H */ --- a/libpurple/tests/meson.build Mon Dec 12 04:23:17 2022 -0600
+++ b/libpurple/tests/meson.build Mon Dec 12 23:38:47 2022 -0600
@@ -2,6 +2,7 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/tests/test_avatar.c Mon Dec 12 23:38:47 2022 -0600
@@ -0,0 +1,97 @@
+ * 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/>. +/****************************************************************************** + *****************************************************************************/ +test_purple_avatar_new(void) { + PurpleAvatar *avatar = NULL; + GdkPixbuf *pixbuf = NULL; + pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 1, 1); + avatar = purple_avatar_new("filename", pixbuf); + g_assert_true(PURPLE_IS_AVATAR(avatar)); + g_assert_cmpstr(purple_avatar_get_filename(avatar), ==, "filename"); + g_assert_true(purple_avatar_get_pixbuf(avatar) == pixbuf); + g_clear_object(&avatar); + g_clear_object(&pixbuf); +test_purple_avatar_properties(void) { + PurpleAvatar *avatar = NULL; + PurpleTags *tags = NULL; + GdkPixbuf *pixbuf = NULL; + GdkPixbuf *pixbuf1 = NULL; + gchar *filename = NULL; + pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 1, 1); + /* 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 + "filename", "filename", + /* Now use g_object_get to read all of the properties. */ + /* Compare all the things. */ + g_assert_cmpstr(filename, ==, "filename"); + g_assert_true(pixbuf1 == pixbuf); + g_assert_nonnull(tags); + /* Free/unref all the things. */ + g_clear_pointer(&filename, g_free); + g_clear_object(&pixbuf1); + g_clear_object(&avatar); + g_clear_object(&pixbuf); +/****************************************************************************** + *****************************************************************************/ +main(gint argc, gchar *argv[]) { + g_test_init(&argc, &argv, NULL); + g_test_add_func("/avatar/new", + test_purple_avatar_new); + g_test_add_func("/avatar/properties", + test_purple_avatar_properties); --- a/po/POTFILES.in Mon Dec 12 04:23:17 2022 -0600
+++ b/po/POTFILES.in Mon Dec 12 23:38:47 2022 -0600
@@ -167,6 +167,7 @@
libpurple/purpleaccountusersplit.c
libpurple/purpleaddcontactrequest.c
libpurple/purpleattachment.c
+libpurple/purpleavatar.c libpurple/purplebuddypresence.c
libpurple/purplechatconversation.c
libpurple/purplechatuser.c