pidgin/pidgin

Make PurpleRequestFieldImage into a GObject

14 months ago, Elliott Sales de Andrade
809019093568
Parents 7ecf7a18e627
Children f4538cc1cb27
Make PurpleRequestFieldImage into a GObject

I'm not sure taking a `char*` and `gsize` is the best constructor; we can probably move this to `GdkPixbuf` or something now. Plus the properties would be nicer, and then it could change images on the fly. But that can happen later.

Testing Done:
Compiled and opened Request Fields from the Demo protocol

Reviewed at https://reviews.imfreedom.org/r/2339/
--- a/libpurple/meson.build Fri Mar 10 17:25:22 2023 -0600
+++ b/libpurple/meson.build Fri Mar 10 17:37:15 2023 -0600
@@ -100,6 +100,7 @@
'request/purplerequestfieldaccount.c',
'request/purplerequestfieldbool.c',
'request/purplerequestfieldchoice.c',
+ 'request/purplerequestfieldimage.c',
'request/purplerequestfieldint.c',
'request/purplerequestfieldlabel.c',
'request/purplerequestfieldlist.c',
@@ -230,6 +231,7 @@
'request/purplerequestfieldaccount.h',
'request/purplerequestfieldbool.h',
'request/purplerequestfieldchoice.h',
+ 'request/purplerequestfieldimage.h',
'request/purplerequestfieldint.h',
'request/purplerequestfieldlabel.h',
'request/purplerequestfieldlist.h',
--- a/libpurple/purplerequestfield.c Fri Mar 10 17:25:22 2023 -0600
+++ b/libpurple/purplerequestfield.c Fri Mar 10 17:37:15 2023 -0600
@@ -42,13 +42,6 @@
union {
struct {
- unsigned int scale_x;
- unsigned int scale_y;
- char *buffer;
- gsize size;
- } image;
-
- struct {
PurpleRequestDatasheet *sheet;
} datasheet;
} u;
@@ -198,8 +191,6 @@
if(priv->type == PURPLE_REQUEST_FIELD_DATASHEET) {
purple_request_datasheet_free(priv->u.datasheet.sheet);
- } else if(priv->type == PURPLE_REQUEST_FIELD_IMAGE) {
- g_free(priv->u.image.buffer);
}
G_OBJECT_CLASS(purple_request_field_parent_class)->finalize(obj);
@@ -635,95 +626,6 @@
}
PurpleRequestField *
-purple_request_field_image_new(const char *id, const char *text, const char *buf, gsize size)
-{
- PurpleRequestField *field;
-
- PurpleRequestFieldPrivate *priv = NULL;
-
- g_return_val_if_fail(id != NULL, NULL);
- g_return_val_if_fail(text != NULL, NULL);
- g_return_val_if_fail(buf != NULL, NULL);
- g_return_val_if_fail(size > 0, NULL);
-
- field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_IMAGE);
- priv = purple_request_field_get_instance_private(field);
-
- priv->u.image.buffer = g_memdup2(buf, size);
- priv->u.image.size = size;
- priv->u.image.scale_x = 1;
- priv->u.image.scale_y = 1;
-
- return field;
-}
-
-void
-purple_request_field_image_set_scale(PurpleRequestField *field, unsigned int x, unsigned int y)
-{
- PurpleRequestFieldPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field));
-
- priv = purple_request_field_get_instance_private(field);
- g_return_if_fail(priv->type == PURPLE_REQUEST_FIELD_IMAGE);
-
- priv->u.image.scale_x = x;
- priv->u.image.scale_y = y;
-}
-
-const char *
-purple_request_field_image_get_buffer(PurpleRequestField *field)
-{
- PurpleRequestFieldPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL);
-
- priv = purple_request_field_get_instance_private(field);
- g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_IMAGE, NULL);
-
- return priv->u.image.buffer;
-}
-
-gsize
-purple_request_field_image_get_size(PurpleRequestField *field)
-{
- PurpleRequestFieldPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), 0);
-
- priv = purple_request_field_get_instance_private(field);
- g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
-
- return priv->u.image.size;
-}
-
-unsigned int
-purple_request_field_image_get_scale_x(PurpleRequestField *field)
-{
- PurpleRequestFieldPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), 0);
-
- priv = purple_request_field_get_instance_private(field);
- g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
-
- return priv->u.image.scale_x;
-}
-
-unsigned int
-purple_request_field_image_get_scale_y(PurpleRequestField *field)
-{
- PurpleRequestFieldPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), 0);
-
- priv = purple_request_field_get_instance_private(field);
- g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_IMAGE, 0);
-
- return priv->u.image.scale_y;
-}
-
-PurpleRequestField *
purple_request_field_datasheet_new(const char *id,
const gchar *text, PurpleRequestDatasheet *sheet)
{
--- a/libpurple/purplerequestfield.h Fri Mar 10 17:25:22 2023 -0600
+++ b/libpurple/purplerequestfield.h Fri Mar 10 17:37:15 2023 -0600
@@ -64,7 +64,6 @@
/**
* PurpleRequestFieldType:
* @PURPLE_REQUEST_FIELD_NONE: No field.
- * @PURPLE_REQUEST_FIELD_IMAGE: Image field.
* @PURPLE_REQUEST_FIELD_DATASHEET: Datasheet field.
*
* A type of field.
@@ -72,7 +71,6 @@
typedef enum
{
PURPLE_REQUEST_FIELD_NONE,
- PURPLE_REQUEST_FIELD_IMAGE,
PURPLE_REQUEST_FIELD_DATASHEET
} PurpleRequestFieldType;
@@ -307,74 +305,6 @@
gboolean purple_request_field_is_sensitive(PurpleRequestField *field);
/**************************************************************************/
-/* Image Field API */
-/**************************************************************************/
-
-/**
- * purple_request_field_image_new:
- * @id: The field ID.
- * @text: The label of the field.
- * @buf: The image data.
- * @size: The size of the data in @buf.
- *
- * Creates an image field.
- *
- * Returns: (transfer full): The new field.
- */
-PurpleRequestField *purple_request_field_image_new(const char *id, const char *text,
- const char *buf, gsize size);
-
-/**
- * purple_request_field_image_set_scale:
- * @field: The image field.
- * @x: The x scale factor.
- * @y: The y scale factor.
- *
- * Sets the scale factors of an image field.
- */
-void purple_request_field_image_set_scale(PurpleRequestField *field, unsigned int x, unsigned int y);
-
-/**
- * purple_request_field_image_get_buffer:
- * @field: The image field.
- *
- * Returns pointer to the image.
- *
- * Returns: Pointer to the image.
- */
-const char *purple_request_field_image_get_buffer(PurpleRequestField *field);
-
-/**
- * purple_request_field_image_get_size:
- * @field: The image field.
- *
- * Returns size (in bytes) of the image.
- *
- * Returns: Size of the image.
- */
-gsize purple_request_field_image_get_size(PurpleRequestField *field);
-
-/**
- * purple_request_field_image_get_scale_x:
- * @field: The image field.
- *
- * Returns X scale coefficient of the image.
- *
- * Returns: X scale coefficient of the image.
- */
-unsigned int purple_request_field_image_get_scale_x(PurpleRequestField *field);
-
-/**
- * purple_request_field_image_get_scale_y:
- * @field: The image field.
- *
- * Returns Y scale coefficient of the image.
- *
- * Returns: Y scale coefficient of the image.
- */
-unsigned int purple_request_field_image_get_scale_y(PurpleRequestField *field);
-
-/**************************************************************************/
/* Datasheet Field API */
/**************************************************************************/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/request/purplerequestfieldimage.c Fri Mar 10 17:37:15 2023 -0600
@@ -0,0 +1,255 @@
+/* purple
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#include <glib/gi18n-lib.h>
+
+#include "glibcompat.h"
+#include "purplerequestfield.h"
+#include "purplerequestfieldimage.h"
+
+struct _PurpleRequestFieldImage {
+ PurpleRequestField parent;
+
+ unsigned int scale_x;
+ unsigned int scale_y;
+ char *buffer;
+ gsize size;
+};
+
+enum {
+ PROP_0,
+ PROP_SCALE_X,
+ PROP_SCALE_Y,
+ PROP_BUFFER,
+ PROP_SIZE,
+ N_PROPERTIES,
+};
+static GParamSpec *properties[N_PROPERTIES] = {NULL, };
+
+G_DEFINE_TYPE(PurpleRequestFieldImage, purple_request_field_image,
+ PURPLE_TYPE_REQUEST_FIELD)
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+static void
+purple_request_field_image_get_property(GObject *obj, guint param_id,
+ GValue *value, GParamSpec *pspec)
+{
+ PurpleRequestFieldImage *field = PURPLE_REQUEST_FIELD_IMAGE(obj);
+
+ switch(param_id) {
+ case PROP_SCALE_X:
+ g_value_set_uint(value,
+ purple_request_field_image_get_scale_x(field));
+ break;
+ case PROP_SCALE_Y:
+ g_value_set_uint(value,
+ purple_request_field_image_get_scale_y(field));
+ break;
+ case PROP_BUFFER:
+ g_value_set_pointer(value,
+ (gpointer)purple_request_field_image_get_buffer(field));
+ break;
+ case PROP_SIZE:
+ g_value_set_uint64(value,
+ purple_request_field_image_get_size(field));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+purple_request_field_image_set_property(GObject *obj, guint param_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ PurpleRequestFieldImage *field = PURPLE_REQUEST_FIELD_IMAGE(obj);
+
+ switch(param_id) {
+ case PROP_SCALE_X:
+ purple_request_field_image_set_scale(field,
+ g_value_get_uint(value),
+ field->scale_y);
+ break;
+ case PROP_SCALE_Y:
+ purple_request_field_image_set_scale(field, field->scale_x,
+ g_value_get_uint(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+purple_request_field_image_finalize(GObject *obj) {
+ PurpleRequestFieldImage *field = PURPLE_REQUEST_FIELD_IMAGE(obj);
+
+ g_free(field->buffer);
+
+ G_OBJECT_CLASS(purple_request_field_image_parent_class)->finalize(obj);
+}
+
+static void
+purple_request_field_image_init(PurpleRequestFieldImage *field) {
+ field->scale_x = 1;
+ field->scale_y = 1;
+}
+
+static void
+purple_request_field_image_class_init(PurpleRequestFieldImageClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ obj_class->finalize = purple_request_field_image_finalize;
+ obj_class->get_property = purple_request_field_image_get_property;
+ obj_class->set_property = purple_request_field_image_set_property;
+
+ /**
+ * PurpleRequestFieldImage:scale-x:
+ *
+ * The X scale coefficient of the image.
+ *
+ * Since: 3.0.0
+ */
+ properties[PROP_SCALE_X] = g_param_spec_uint(
+ "scale-x", "scale-x",
+ "The X scale coefficient of the image.",
+ 1, G_MAXUINT, 1,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurpleRequestFieldImage:scale-y:
+ *
+ * The Y scale coefficient of the image.
+ *
+ * Since: 3.0.0
+ */
+ properties[PROP_SCALE_Y] = g_param_spec_uint(
+ "scale-y", "scale-y",
+ "The Y scale coefficient of the image.",
+ 1, G_MAXUINT, 1,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurpleRequestFieldImage:buffer:
+ *
+ * The contents of the image.
+ *
+ * Since: 3.0.0
+ */
+ properties[PROP_BUFFER] = g_param_spec_pointer(
+ "buffer", "buffer",
+ "The contents of the image.",
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurpleRequestFieldImage:size:
+ *
+ * The size in bytes of the image.
+ *
+ * Since: 3.0.0
+ */
+ properties[PROP_SIZE] = g_param_spec_uint64(
+ "size", "size",
+ "The size in bytes of the image.",
+ 0, G_MAXSIZE, 0,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+PurpleRequestField *
+purple_request_field_image_new(const char *id, const char *text,
+ const char *buf, gsize size)
+{
+ PurpleRequestFieldImage *field;
+
+ g_return_val_if_fail(id != NULL, NULL);
+ g_return_val_if_fail(text != NULL, NULL);
+ g_return_val_if_fail(buf != NULL, NULL);
+ g_return_val_if_fail(size > 0, NULL);
+
+ field = g_object_new(PURPLE_TYPE_REQUEST_FIELD_IMAGE,
+ "id", id,
+ "label", text,
+ NULL);
+
+ field->buffer = g_memdup2(buf, size);
+ field->size = size;
+
+ return PURPLE_REQUEST_FIELD(field);
+}
+
+void
+purple_request_field_image_set_scale(PurpleRequestFieldImage *field,
+ unsigned int x, unsigned int y)
+{
+ g_return_if_fail(PURPLE_IS_REQUEST_FIELD_IMAGE(field));
+
+ if(field->scale_x == x && field->scale_y == y) {
+ return;
+ }
+
+ field->scale_x = x;
+ field->scale_y = y;
+
+ g_object_freeze_notify(G_OBJECT(field));
+ g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_SCALE_X]);
+ g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_SCALE_Y]);
+ g_object_thaw_notify(G_OBJECT(field));
+}
+
+const char *
+purple_request_field_image_get_buffer(PurpleRequestFieldImage *field)
+{
+ g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_IMAGE(field), NULL);
+
+ return field->buffer;
+}
+
+gsize
+purple_request_field_image_get_size(PurpleRequestFieldImage *field)
+{
+ g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_IMAGE(field), 0);
+
+ return field->size;
+}
+
+unsigned int
+purple_request_field_image_get_scale_x(PurpleRequestFieldImage *field)
+{
+ g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_IMAGE(field), 0);
+
+ return field->scale_x;
+}
+
+unsigned int
+purple_request_field_image_get_scale_y(PurpleRequestFieldImage *field)
+{
+ g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_IMAGE(field), 0);
+
+ return field->scale_y;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/request/purplerequestfieldimage.h Fri Mar 10 17:37:15 2023 -0600
@@ -0,0 +1,115 @@
+/*
+ * 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_REQUEST_FIELD_IMAGE_H
+#define PURPLE_REQUEST_FIELD_IMAGE_H
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+/**
+ * PurpleRequestFieldImage:
+ *
+ * An image request field.
+ */
+typedef struct _PurpleRequestFieldImage PurpleRequestFieldImage;
+
+#include "purplerequestfield.h"
+
+G_BEGIN_DECLS
+
+#define PURPLE_TYPE_REQUEST_FIELD_IMAGE (purple_request_field_image_get_type())
+G_DECLARE_FINAL_TYPE(PurpleRequestFieldImage, purple_request_field_image,
+ PURPLE, REQUEST_FIELD_IMAGE, PurpleRequestField)
+
+/**
+ * purple_request_field_image_new:
+ * @id: The field ID.
+ * @text: The label of the field.
+ * @buf: The image data.
+ * @size: The size of the data in @buf.
+ *
+ * Creates an image field.
+ *
+ * Returns: (transfer full): The new field.
+ */
+PurpleRequestField *purple_request_field_image_new(const char *id, const char *text, const char *buf, gsize size);
+
+/**
+ * purple_request_field_image_set_scale:
+ * @field: The image field.
+ * @x: The x scale factor.
+ * @y: The y scale factor.
+ *
+ * Sets the scale factors of an image field.
+ */
+void purple_request_field_image_set_scale(PurpleRequestFieldImage *field, unsigned int x, unsigned int y);
+
+/**
+ * purple_request_field_image_get_buffer:
+ * @field: The image field.
+ *
+ * Returns pointer to the image.
+ *
+ * Returns: Pointer to the image.
+ */
+const char *purple_request_field_image_get_buffer(PurpleRequestFieldImage *field);
+
+/**
+ * purple_request_field_image_get_size:
+ * @field: The image field.
+ *
+ * Returns size (in bytes) of the image.
+ *
+ * Returns: Size of the image.
+ */
+gsize purple_request_field_image_get_size(PurpleRequestFieldImage *field);
+
+/**
+ * purple_request_field_image_get_scale_x:
+ * @field: The image field.
+ *
+ * Returns X scale coefficient of the image.
+ *
+ * Returns: X scale coefficient of the image.
+ */
+unsigned int purple_request_field_image_get_scale_x(PurpleRequestFieldImage *field);
+
+/**
+ * purple_request_field_image_get_scale_y:
+ * @field: The image field.
+ *
+ * Returns Y scale coefficient of the image.
+ *
+ * Returns: Y scale coefficient of the image.
+ */
+unsigned int purple_request_field_image_get_scale_y(PurpleRequestFieldImage *field);
+
+G_END_DECLS
+
+#endif /* PURPLE_REQUEST_FIELD_IMAGE_H */
--- a/pidgin/gtkrequest.c Fri Mar 10 17:25:22 2023 -0600
+++ b/pidgin/gtkrequest.c Fri Mar 10 17:37:15 2023 -0600
@@ -1293,16 +1293,17 @@
static GtkWidget *
create_image_field(PurpleRequestField *field)
{
+ PurpleRequestFieldImage *ifield = PURPLE_REQUEST_FIELD_IMAGE(field);
GtkWidget *widget;
GdkPixbuf *buf, *scale;
buf = purple_gdk_pixbuf_from_data(
- (const guchar *)purple_request_field_image_get_buffer(field),
- purple_request_field_image_get_size(field));
+ (const guchar *)purple_request_field_image_get_buffer(ifield),
+ purple_request_field_image_get_size(ifield));
scale = gdk_pixbuf_scale_simple(buf,
- purple_request_field_image_get_scale_x(field) * gdk_pixbuf_get_width(buf),
- purple_request_field_image_get_scale_y(field) * gdk_pixbuf_get_height(buf),
+ purple_request_field_image_get_scale_x(ifield) * gdk_pixbuf_get_width(buf),
+ purple_request_field_image_get_scale_y(ifield) * gdk_pixbuf_get_height(buf),
GDK_INTERP_BILINEAR);
widget = gtk_image_new_from_pixbuf(scale);
g_object_unref(G_OBJECT(buf));
@@ -2155,9 +2156,9 @@
widget = create_choice_field(field);
} else if(PURPLE_IS_REQUEST_FIELD_LIST(field)) {
widget = create_list_field(field);
- } else if (type == PURPLE_REQUEST_FIELD_IMAGE)
+ } else if(PURPLE_IS_REQUEST_FIELD_IMAGE(field)) {
widget = create_image_field(field);
- else if(PURPLE_IS_REQUEST_FIELD_ACCOUNT(field)) {
+ } else if(PURPLE_IS_REQUEST_FIELD_ACCOUNT(field)) {
widget = create_account_field(field);
} else if (type == PURPLE_REQUEST_FIELD_DATASHEET)
widget = create_datasheet_field(field, datasheet_buttons_sg);