After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 338024 - Add g_object_set_properties
Add g_object_set_properties
Status: RESOLVED DUPLICATE of bug 709865
Product: glib
Classification: Platform
Component: gobject
unspecified
Other Linux
: Normal enhancement
: ---
Assigned To: Johan (not receiving bugmail) Dahlin
gtkdev
Depends on:
Blocks:
 
 
Reported: 2006-04-10 20:28 UTC by Johan (not receiving bugmail) Dahlin
Modified: 2017-11-17 12:08 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
patch (1.86 KB, patch)
2006-04-10 20:32 UTC, Johan (not receiving bugmail) Dahlin
none Details | Review
v2: header and exported symbol included (2.87 KB, patch)
2006-04-10 20:41 UTC, Johan (not receiving bugmail) Dahlin
none Details | Review
v2: header and exported symbol included (3.22 KB, patch)
2006-04-10 20:53 UTC, Johan (not receiving bugmail) Dahlin
none Details | Review
v3: updated for head, with test and documentation included (10.36 KB, patch)
2006-10-25 14:16 UTC, Johan (not receiving bugmail) Dahlin
none Details | Review
v4: Update to trunk, add g_object_get_properties, extends test to all g_gobject_set/get functions (14.68 KB, patch)
2007-05-04 21:47 UTC, Johan (not receiving bugmail) Dahlin
needs-work Details | Review

Description Johan (not receiving bugmail) Dahlin 2006-04-10 20:28:14 UTC
It'd would be nice to have a method which takes a list of GParameters, which is useful to set many parameters at once, without having to send notifications for each property.
Comment 1 Johan (not receiving bugmail) Dahlin 2006-04-10 20:32:48 UTC
Created attachment 63200 [details] [review]
patch

Note, this patch is leaving the GValue creation and destruction to the caller, following the behavior of g_object_set_property.
Comment 2 Johan (not receiving bugmail) Dahlin 2006-04-10 20:41:48 UTC
Created attachment 63201 [details] [review]
v2: header and exported symbol included
Comment 3 Johan (not receiving bugmail) Dahlin 2006-04-10 20:53:45 UTC
Created attachment 63205 [details] [review]
v2: header and exported symbol included

Correct one attached now, I have too many patches in my home directory...
Comment 4 Tim Janik 2006-08-23 08:49:29 UTC
thanks Johan.
would you mind also writing a test program for this function, so we can get it properly covered by the test suite?
Comment 5 Johan (not receiving bugmail) Dahlin 2006-10-25 14:16:07 UTC
Created attachment 75371 [details] [review]
v3: updated for head, with test and documentation included
Comment 6 Tim Janik 2007-05-03 13:39:06 UTC
Comment on attachment 75371 [details] [review]
v3: updated for head, with test and documentation included

>diff -u -d -r1.47 objects.sgml
>--- docs/reference/gobject/tmpl/objects.sgml	5 Jun 2006 17:34:49 -0000	1.47
>+++ docs/reference/gobject/tmpl/objects.sgml	25 Oct 2006 14:14:50 -0000
>@@ -999,6 +999,19 @@
> @value: return location for the property value
> 
> 
>+<!-- ##### FUNCTION g_object_set_properties ##### -->
>+<para>
>+Sets properties on an object.
>+</para>
>+<para>
>+Note that g_object_set_properties() is really intended for language
>+bindings, g_object_set() is much more convenient for C programming.

i don't think that disclaimer is accurate, the interface is nice and good to use for generic code beyond language bindings (in know that gimp in particular deals with arrays of GParameter for instance). there can conceivably be a disclaimer here that says that g_object_set() is easier to use for most C programmers, but that's about it.

>+</para>
>+
>+@object: a #GObject
>+@n_parameters: number of parameters to set
>+@parameters: parameters
>+
> <!-- ##### FUNCTION g_object_new_valist ##### -->
> <para>
> Creates a new instance of a #GObject subtype and sets its properties.
>Index: gobject/gobject.c
>===================================================================
>RCS file: /cvs/gnome/glib/gobject/gobject.c,v
>retrieving revision 1.82
>diff -u -d -r1.82 gobject.c
>--- gobject/gobject.c	30 Sep 2006 13:59:01 -0000	1.82
>+++ gobject/gobject.c	25 Oct 2006 14:14:52 -0000
>@@ -1325,6 +1325,59 @@
>   g_object_unref (object);
> }
> 
>+void
>+g_object_set_properties (GObject    *object,
>+                         guint       n_parameters,
>+                         GParameter *parameters)
>+{
>+  GObjectNotifyQueue *nqueue;
>+  int i;
>+
>+  g_return_if_fail (G_IS_OBJECT (object));
>+  
>+  g_object_ref (object);
>+  nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
>+  
>+  for (i = 0; i < n_parameters; i++)
>+    {
>+      GValue *value = &parameters[i].value;
>+      const gchar *name = parameters[i].name;
>+      GParamSpec *pspec;
>+      
>+      pspec = g_param_spec_pool_lookup (pspec_pool,
>+                                        name,
>+                                        G_OBJECT_TYPE (object),
>+                                        TRUE);
>+      if (!pspec)
>+        {
>+          g_warning ("%s: object class `%s' has no property named `%s'",
>+                     G_STRFUNC,
>+                     G_OBJECT_TYPE_NAME (object),
>+                     name);
>+          break;
>+        }
>+      if (!(pspec->flags & G_PARAM_WRITABLE))
>+        {
>+          g_warning ("%s: property `%s' of object class `%s' is not writable",
>+                     G_STRFUNC,
>+                     pspec->name,
>+                     G_OBJECT_TYPE_NAME (object));
>+          break;
>+        }
>+      if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))

this condition was fixed in g_object_set_valist(), please update your patch accordingly.

>+        {
>+          g_warning ("%s: construct property \"%s\" for object `%s' can't be set after construction",
>+                     G_STRFUNC, pspec->name, G_OBJECT_TYPE_NAME (object));
>+          break;
>+        }
>+
>+      object_set_property (object, pspec, value, nqueue);
>+    }
>+
>+  g_object_notify_queue_thaw (object, nqueue);
>+  g_object_unref (object);
>+}
>+
> gpointer
> g_object_connect (gpointer     _object,
> 		  const gchar *signal_spec,
>Index: gobject/gobject.h
>===================================================================
>RCS file: /cvs/gnome/glib/gobject/gobject.h,v
>retrieving revision 1.38
>diff -u -d -r1.38 gobject.h
>--- gobject/gobject.h	23 Aug 2006 08:46:21 -0000	1.38
>+++ gobject/gobject.h	25 Oct 2006 14:14:52 -0000
>@@ -174,6 +174,9 @@
> void        g_object_get_property             (GObject        *object,
> 					       const gchar    *property_name,
> 					       GValue         *value);
>+void        g_object_set_properties           (GObject        *object,
>+					       guint	       n_parameters,
>+					       GParameter     *properties);


hm, the patch mostly looks good, but why is there only a _set_ variant and not also a _get_ variant of this function?

> void        g_object_freeze_notify            (GObject        *object);
> void        g_object_notify                   (GObject        *object,
> 					       const gchar    *property_name);
>Index: tests/gobject/properties.c
>===================================================================
>RCS file: tests/gobject/properties.c
>diff -N tests/gobject/properties.c
>--- /dev/null	1 Jan 1970 00:00:00 -0000
>+++ tests/gobject/properties.c	25 Oct 2006 14:14:52 -0000
>@@ -0,0 +1,185 @@
>+/* GObject - GLib Type, Object, Parameter and Signal Library
>+ * Copyright (C) 2006 Johan Dahlin
>+ *
>+ * 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, write to the
>+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
>+ * Boston, MA 02111-1307, USA.
>+ */
>+
>+#include <string.h>
>+
>+#include <glib-object.h>
>+
>+#define TEST_TYPE_OBJECT          (test_object_get_type ())
>+typedef struct _TestObject        TestObject;
>+typedef struct _TestObjectClass   TestObjectClass;
>+
>+enum {
>+  PROP_0,
>+  PROP_STRING,
>+  PROP_INT,
>+};
>+
>+struct _TestObject
>+{
>+  GObject parent_instance;
>+  gchar * prop_string;
>+  int prop_int;
>+};
>+
>+struct _TestObjectClass
>+{
>+  GObjectClass parent_class;
>+};
>+
>+G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT);
>+
>+static void
>+test_set_property (GObject         *object,
>+                   guint            prop_id,
>+                   const GValue    *value,
>+                   GParamSpec      *pspec)
>+{
>+  TestObject *test = (TestObject*)object;
>+
>+  switch (prop_id)
>+    {
>+    case PROP_STRING:
>+      test->prop_string = g_strdup (g_value_get_string (value));
>+      break;
>+    case PROP_INT:
>+      test->prop_int = g_value_get_int (value);
>+      break;
>+    default:
>+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
>+      break;
>+    }
>+}
>+
>+static void
>+test_get_property (GObject         *object,
>+                   guint            prop_id,
>+                   GValue          *value,
>+                   GParamSpec      *pspec)
>+{
>+  TestObject *test = (TestObject*)object;
>+  
>+  switch (prop_id)
>+    {
>+    case PROP_STRING:
>+      g_value_set_string (value, test->prop_string);
>+      break;
>+    case PROP_INT:
>+      g_value_set_int (value, test->prop_int);
>+      break;
>+    default:
>+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
>+      break;
>+    }
>+}
>+
>+static void
>+test_finalize (GObject *object)
>+{
>+  TestObject *test = (TestObject*)object;
>+
>+  g_free (test->prop_string);
>+  
>+  G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
>+}
>+
>+static void
>+test_object_class_init (TestObjectClass *class)
>+{
>+  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
>+
>+  gobject_class->finalize = test_finalize;
>+  gobject_class->set_property = test_set_property;
>+  gobject_class->get_property = test_get_property;
>+
>+  g_object_class_install_property (gobject_class,
>+                                   PROP_STRING,
>+                                   g_param_spec_string ("string", NULL, NULL, NULL,
>+                                                        G_PARAM_READWRITE));
>+
>+  g_object_class_install_property (gobject_class,
>+                                   PROP_INT,
>+                                   g_param_spec_int ("int", NULL, NULL,
>+                                                     G_MININT, G_MAXINT, 0,
>+                                                     G_PARAM_READWRITE));
>+}
>+
>+static void
>+test_object_init (TestObject *test_object)
>+{
>+}
>+
>+static void
>+test_set_properties (GObject *test)
>+{
>+  GParameter *parameters;
>+  GValue *values;
>+
>+  parameters = g_new0 (GParameter, 2);
>+  values = g_new0 (GValue, 2);
>+
>+  g_value_init (&values[0], G_TYPE_STRING);
>+  g_value_set_static_string (&values[0], "foobar");
>+  parameters[0].name = "string";
>+  parameters[0].value = values[0];
>+    
>+  g_value_init (&values[1], G_TYPE_INT);
>+  g_value_set_int (&values[1], 42);
>+  parameters[1].name = "int";
>+  parameters[1].value = values[1];
>+
>+  g_object_set_properties (test, 2, parameters);

since you wrote a fairly generic proeprty test program here, what about extending it at this point to also run the same tests for the varargs variants and a _get_properties version?

>+
>+  g_value_unset (&values[0]);
>+  g_value_unset (&values[1]);
>+  g_free (values);
>+  g_free (parameters);
>+  
>+  g_assert (((TestObject*)test)->prop_int == 42);
>+  g_assert (!strcmp (((TestObject*)test)->prop_string, "foobar"));
>+}
>+
>+int
>+main (int   argc,
>+      char *argv[])
>+{
>+  GObject *obj;
>+  char *s;
>+  int i;
>+  
>+  g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
>+                          G_LOG_LEVEL_WARNING |
>+                          G_LOG_LEVEL_CRITICAL);
>+  g_type_init ();
>+
>+  obj = g_object_new (TEST_TYPE_OBJECT, NULL);
>+
>+  /* Default values */
>+  g_object_get (obj, "int", &i, NULL);
>+  g_assert (i == 0);
>+  
>+  g_object_get (obj, "string", &s, NULL);
>+  g_assert (s == NULL);
>+
>+  test_set_properties (obj);
>+  
>+  g_object_unref (obj);
>+  
>+  return 0;
>+}

thanks for the new patch, looks fairly good to go in already, except for the CONSTRUCT properties logic fix and that we really should have a _Get_variant as well.
Comment 7 Johan (not receiving bugmail) Dahlin 2007-05-04 21:46:48 UTC
(In reply to comment #6)

> >+<!-- ##### FUNCTION g_object_set_properties ##### -->
> >+<para>
> >+Sets properties on an object.
> >+</para>
> >+<para>
> >+Note that g_object_set_properties() is really intended for language
> >+bindings, g_object_set() is much more convenient for C programming.
> 
> i don't think that disclaimer is accurate, the interface is nice and good to
> use for generic code beyond language bindings (in know that gimp in particular
> deals with arrays of GParameter for instance). there can conceivably be a
> disclaimer here that says that g_object_set() is easier to use for most C
> programmers, but that's about it.

This was just copied from documentation of set/get_property. I think it's better to keep it consistent. Sure I agree that the language might be a bit strong, they're actually useful for C programming as well.
Comment 8 Johan (not receiving bugmail) Dahlin 2007-05-04 21:47:20 UTC
Created attachment 87574 [details] [review]
v4: Update to trunk, add g_object_get_properties, extends test to all g_gobject_set/get functions
Comment 9 Tim Janik 2007-05-22 13:28:03 UTC
Comment on attachment 87574 [details] [review]
v4: Update to trunk, add g_object_get_properties, extends test to all g_gobject_set/get functions

>--- docs/reference/gobject/tmpl/objects.sgml	(revisão 5484)
>+++ docs/reference/gobject/tmpl/objects.sgml	(cópia de trabalho)

can you please fix the wording here then to be less strong, and fix it consistently?


>--- tests/gobject/properties.c	(revisão 0)
>+++ tests/gobject/properties.c	(revisão 0)

thanks. nice extensive property set/get test case now ;)

>--- gobject/gobject.c	(revisão 5484)
>+++ gobject/gobject.c	(cópia de trabalho)
>@@ -1330,6 +1330,104 @@ g_object_get_property (GObject	   *objec
>   g_object_unref (object);
> }
> 
>+void
>+g_object_get_properties (GObject    *object,
>+                         guint       n_parameters,
>+                         GParameter *parameters)
>+{
>+  int i;
>+
>+  g_return_if_fail (G_IS_OBJECT (object));
>+  
>+  g_object_ref (object);
>+  
>+  for (i = 0; i < n_parameters; i++)
>+    {
>+      GValue *value = &parameters[i].value;
>+      const gchar *name = parameters[i].name;
>+      GParamSpec *pspec;
>+      
>+      pspec = g_param_spec_pool_lookup (pspec_pool,
>+                                        name,
>+                                        G_OBJECT_TYPE (object),
>+                                        TRUE);
>+      if (!pspec)
>+	{
>+	  g_warning ("%s: object class `%s' has no property named `%s'",
>+		     G_STRFUNC,
>+		     G_OBJECT_TYPE_NAME (object),
>+		     name);
>+	  break;

this can be s/break/continue/

>+	}
>+      if (!(pspec->flags & G_PARAM_READABLE))
>+	{
>+	  g_warning ("%s: property `%s' of object class `%s' is not readable",
>+		     G_STRFUNC,
>+		     pspec->name,
>+		     G_OBJECT_TYPE_NAME (object));
>+	  break;

this can be s/break/continue/

the reason we have "break" in the get_valist variant is that we can't continue to parse the property arguments once an individual property wasn't recognized.
with the array at hand though, we implement best effort and continue to get properties.

>+	}
>+      
>+      object_get_property (object, pspec, value);
>+
>+    }
>+
>+  g_object_unref (object);
>+}
>+
>+void
>+g_object_set_properties (GObject    *object,
>+                         guint       n_parameters,
>+                         GParameter *parameters)
>+{
>+  GObjectNotifyQueue *nqueue;
>+  int i;
>+
>+  g_return_if_fail (G_IS_OBJECT (object));
>+  
>+  g_object_ref (object);
>+  nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
>+  
>+  for (i = 0; i < n_parameters; i++)
>+    {
>+      GValue *value = &parameters[i].value;
>+      const gchar *name = parameters[i].name;
>+      GParamSpec *pspec;
>+      
>+      pspec = g_param_spec_pool_lookup (pspec_pool,
>+                                        name,
>+                                        G_OBJECT_TYPE (object),
>+                                        TRUE);
>+      if (!pspec)
>+        {
>+          g_warning ("%s: object class `%s' has no property named `%s'",
>+                     G_STRFUNC,
>+                     G_OBJECT_TYPE_NAME (object),
>+                     name);
>+          break;

this should stay "break" btw, because the settable properties in the array may have a certain dependency, so continuing to set properties could be possibly harmfull.

>+        }
>+      if (!(pspec->flags & G_PARAM_WRITABLE))
>+        {
>+          g_warning ("%s: property `%s' of object class `%s' is not writable",
>+                     G_STRFUNC,
>+                     pspec->name,
>+                     G_OBJECT_TYPE_NAME (object));
>+          break;
>+        }
[...]

the rest looks good. please apply and attach a new patch for objects.sgml.
Comment 10 Philip Withnall 2017-11-17 12:08:29 UTC
This was fixed in bug #709865, which introduced the g_object_getv() and g_object_setv() methods, as well as a new g_object_new_with_properties() constructor.

*** This bug has been marked as a duplicate of bug 709865 ***