1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
3 * Copyright (c) 2010 Collabora Ltd. <http://www.collabora.co.uk/>
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #include "pygi-private.h"
26 #include <girepository.h>
28 static GIPropertyInfo *
29 lookup_property_from_object_info (GIObjectInfo *info, const gchar *attr_name)
34 n_infos = g_object_info_get_n_properties (info);
35 for (i = 0; i < n_infos; i++) {
36 GIPropertyInfo *property_info;
38 property_info = g_object_info_get_property (info, i);
39 g_assert (info != NULL);
41 if (strcmp (attr_name, g_base_info_get_name (property_info)) == 0) {
45 g_base_info_unref (property_info);
51 static GIPropertyInfo *
52 lookup_property_from_interface_info (GIInterfaceInfo *info,
53 const gchar *attr_name)
58 n_infos = g_interface_info_get_n_properties (info);
59 for (i = 0; i < n_infos; i++) {
60 GIPropertyInfo *property_info;
62 property_info = g_interface_info_get_property (info, i);
63 g_assert (info != NULL);
65 if (strcmp (attr_name, g_base_info_get_name (property_info)) == 0) {
69 g_base_info_unref (property_info);
75 static GIPropertyInfo *
76 _pygi_lookup_property_from_g_type (GType g_type, const gchar *attr_name)
78 GIPropertyInfo *ret = NULL;
79 GIRepository *repository;
82 repository = g_irepository_get_default();
83 info = g_irepository_find_by_gtype (repository, g_type);
87 if (GI_IS_OBJECT_INFO (info))
88 ret = lookup_property_from_object_info ((GIObjectInfo *) info,
90 else if (GI_IS_INTERFACE_INFO (info))
91 ret = lookup_property_from_interface_info ((GIInterfaceInfo *) info,
94 g_base_info_unref (info);
99 pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec)
101 GIPropertyInfo *property_info = NULL;
102 GValue value = { 0, };
103 GIArgument arg = { 0, };
104 PyObject *py_value = NULL;
105 GITypeInfo *type_info = NULL;
108 /* The owner_type of the pspec gives us the exact type that introduced the
109 * property, even if it is a parent class of the instance in question. */
110 property_info = _pygi_lookup_property_from_g_type (pspec->owner_type, pspec->name);
112 if (property_info == NULL)
115 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
116 g_object_get_property (instance->obj, pspec->name, &value);
118 type_info = g_property_info_get_type (property_info);
119 transfer = g_property_info_get_ownership_transfer (property_info);
121 GITypeTag type_tag = g_type_info_get_tag (type_info);
123 case GI_TYPE_TAG_BOOLEAN:
124 arg.v_boolean = g_value_get_boolean (&value);
126 case GI_TYPE_TAG_INT8:
127 arg.v_int8 = g_value_get_schar (&value);
129 case GI_TYPE_TAG_INT16:
130 case GI_TYPE_TAG_INT32:
131 if (G_VALUE_HOLDS_LONG (&value))
132 arg.v_long = g_value_get_long (&value);
134 arg.v_int = g_value_get_int (&value);
136 case GI_TYPE_TAG_INT64:
137 if (G_VALUE_HOLDS_LONG (&value))
138 arg.v_long = g_value_get_long (&value);
140 arg.v_int64 = g_value_get_int64 (&value);
142 case GI_TYPE_TAG_UINT8:
143 arg.v_uint8 = g_value_get_uchar (&value);
145 case GI_TYPE_TAG_UINT16:
146 case GI_TYPE_TAG_UINT32:
147 if (G_VALUE_HOLDS_ULONG (&value))
148 arg.v_ulong = g_value_get_ulong (&value);
150 arg.v_uint = g_value_get_uint (&value);
152 case GI_TYPE_TAG_UINT64:
153 if (G_VALUE_HOLDS_ULONG (&value))
154 arg.v_ulong = g_value_get_ulong (&value);
156 arg.v_uint64 = g_value_get_uint64 (&value);
158 case GI_TYPE_TAG_FLOAT:
159 arg.v_float = g_value_get_float (&value);
161 case GI_TYPE_TAG_DOUBLE:
162 arg.v_double = g_value_get_double (&value);
164 case GI_TYPE_TAG_GTYPE:
165 arg.v_size = g_value_get_gtype (&value);
167 case GI_TYPE_TAG_UTF8:
168 case GI_TYPE_TAG_FILENAME:
169 arg.v_string = g_value_dup_string (&value);
171 case GI_TYPE_TAG_INTERFACE:
174 GIInfoType info_type;
177 info = g_type_info_get_interface (type_info);
178 type = g_registered_type_info_get_g_type (info);
179 info_type = g_base_info_get_type (info);
181 g_base_info_unref (info);
184 case GI_INFO_TYPE_ENUM:
185 arg.v_int32 = g_value_get_enum (&value);
187 case GI_INFO_TYPE_INTERFACE:
188 case GI_INFO_TYPE_OBJECT:
189 arg.v_pointer = g_value_get_object (&value);
191 case GI_INFO_TYPE_BOXED:
192 case GI_INFO_TYPE_STRUCT:
193 case GI_INFO_TYPE_UNION:
195 if (g_type_is_a (type, G_TYPE_BOXED)) {
196 arg.v_pointer = g_value_get_boxed (&value);
197 } else if (g_type_is_a (type, G_TYPE_POINTER)) {
198 arg.v_pointer = g_value_get_pointer (&value);
199 } else if (g_type_is_a (type, G_TYPE_VARIANT)) {
200 arg.v_pointer = g_value_get_variant (&value);
202 PyErr_Format (PyExc_NotImplementedError,
203 "Retrieving properties of type '%s' is not implemented",
208 PyErr_Format (PyExc_NotImplementedError,
209 "Retrieving properties of type '%s' is not implemented",
215 case GI_TYPE_TAG_GHASH:
216 arg.v_pointer = g_value_get_boxed (&value);
218 case GI_TYPE_TAG_GLIST:
219 case GI_TYPE_TAG_GSLIST:
220 arg.v_pointer = g_value_get_pointer (&value);
222 case GI_TYPE_TAG_ARRAY:
228 strings = g_value_get_boxed (&value);
230 arg.v_pointer = NULL;
232 arg_items = g_array_sized_new (TRUE, TRUE, sizeof (GIArgument), g_strv_length (strings));
233 g_array_set_size (arg_items, g_strv_length (strings));
234 for (i = 0; strings[i] != NULL; ++i) {
235 g_array_index (arg_items, GIArgument, i).v_string = strings[i];
237 arg.v_pointer = arg_items;
242 PyErr_Format (PyExc_NotImplementedError,
243 "Retrieving properties of type %s is not implemented",
244 g_type_tag_to_string (g_type_info_get_tag (type_info)));
248 py_value = _pygi_argument_to_object (&arg, type_info, transfer);
251 if (property_info != NULL)
252 g_base_info_unref (property_info);
253 if (type_info != NULL)
254 g_base_info_unref (type_info);
260 pygi_set_property_value_real (PyGObject *instance,
264 GIPropertyInfo *property_info = NULL;
265 GITypeInfo *type_info = NULL;
268 GValue value = { 0, };
269 GIArgument arg = { 0, };
272 /* The owner_type of the pspec gives us the exact type that introduced the
273 * property, even if it is a parent class of the instance in question. */
274 property_info = _pygi_lookup_property_from_g_type (pspec->owner_type,
276 if (property_info == NULL)
279 if (! (pspec->flags & G_PARAM_WRITABLE))
282 type_info = g_property_info_get_type (property_info);
283 transfer = g_property_info_get_ownership_transfer (property_info);
284 arg = _pygi_argument_from_object (py_value, type_info, transfer);
286 if (PyErr_Occurred())
289 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
291 // FIXME: Lots of types still unhandled
292 type_tag = g_type_info_get_tag (type_info);
294 case GI_TYPE_TAG_INTERFACE:
297 GIInfoType info_type;
300 info = g_type_info_get_interface (type_info);
301 type = g_registered_type_info_get_g_type (info);
302 info_type = g_base_info_get_type (info);
304 g_base_info_unref (info);
307 case GI_INFO_TYPE_ENUM:
308 g_value_set_enum (&value, arg.v_int32);
310 case GI_INFO_TYPE_INTERFACE:
311 case GI_INFO_TYPE_OBJECT:
312 g_value_set_object (&value, arg.v_pointer);
314 case GI_INFO_TYPE_BOXED:
315 case GI_INFO_TYPE_STRUCT:
316 case GI_INFO_TYPE_UNION:
317 if (g_type_is_a (type, G_TYPE_BOXED)) {
318 g_value_set_boxed (&value, arg.v_pointer);
319 } else if (g_type_is_a (type, G_TYPE_VARIANT)) {
320 g_value_set_variant (&value, arg.v_pointer);
322 PyErr_Format (PyExc_NotImplementedError,
323 "Setting properties of type '%s' is not implemented",
328 PyErr_Format (PyExc_NotImplementedError,
329 "Setting properties of type '%s' is not implemented",
335 case GI_TYPE_TAG_BOOLEAN:
336 g_value_set_boolean (&value, arg.v_boolean);
338 case GI_TYPE_TAG_INT8:
339 g_value_set_schar (&value, arg.v_int8);
341 case GI_TYPE_TAG_INT16:
342 case GI_TYPE_TAG_INT32:
343 if (G_VALUE_HOLDS_LONG (&value))
344 g_value_set_long (&value, arg.v_long);
346 g_value_set_int (&value, arg.v_int);
348 case GI_TYPE_TAG_INT64:
349 if (G_VALUE_HOLDS_LONG (&value))
350 g_value_set_long (&value, arg.v_long);
352 g_value_set_int64 (&value, arg.v_int64);
354 case GI_TYPE_TAG_UINT8:
355 g_value_set_uchar (&value, arg.v_uint8);
357 case GI_TYPE_TAG_UINT16:
358 case GI_TYPE_TAG_UINT32:
359 if (G_VALUE_HOLDS_ULONG (&value))
360 g_value_set_ulong (&value, arg.v_ulong);
362 g_value_set_uint (&value, arg.v_uint);
364 case GI_TYPE_TAG_UINT64:
365 if (G_VALUE_HOLDS_ULONG (&value))
366 g_value_set_ulong (&value, arg.v_ulong);
368 g_value_set_uint64 (&value, arg.v_uint64);
370 case GI_TYPE_TAG_FLOAT:
371 g_value_set_float (&value, arg.v_float);
373 case GI_TYPE_TAG_DOUBLE:
374 g_value_set_double (&value, arg.v_double);
376 case GI_TYPE_TAG_GTYPE:
377 g_value_set_gtype (&value, arg.v_size);
379 case GI_TYPE_TAG_UTF8:
380 case GI_TYPE_TAG_FILENAME:
381 g_value_set_string (&value, arg.v_string);
383 case GI_TYPE_TAG_GHASH:
384 g_value_set_boxed (&value, arg.v_pointer);
386 case GI_TYPE_TAG_GLIST:
387 g_value_set_pointer (&value, arg.v_pointer);
389 case GI_TYPE_TAG_ARRAY:
391 /* This is assumes GI_TYPE_TAG_ARRAY is always a GStrv
392 * https://bugzilla.gnome.org/show_bug.cgi?id=688232
394 GArray *arg_items = (GArray*) arg.v_pointer;
398 if (arg_items == NULL)
401 strings = g_new0 (char*, arg_items->len + 1);
402 for (i = 0; i < arg_items->len; ++i) {
403 strings[i] = g_array_index (arg_items, GIArgument, i).v_string;
405 strings[arg_items->len] = NULL;
406 g_value_set_boxed (&value, strings);
407 g_array_free (arg_items, TRUE);
411 PyErr_Format (PyExc_NotImplementedError,
412 "Setting properties of type %s is not implemented",
413 g_type_tag_to_string (g_type_info_get_tag (type_info)));
417 g_object_set_property (instance->obj, pspec->name, &value);
422 if (property_info != NULL)
423 g_base_info_unref (property_info);
424 if (type_info != NULL)
425 g_base_info_unref (type_info);