File: | ctk/ctkbuilder.c |
Warning: | line 783, column 43 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* CTK - The GIMP Toolkit |
2 | * Copyright (C) 1998-2002 James Henstridge <james@daa.com.au> |
3 | * Copyright (C) 2006-2007 Async Open Source, |
4 | * Johan Dahlin <jdahlin@async.com.br>, |
5 | * Henrique Romano <henrique@async.com.br> |
6 | * |
7 | * This library is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Library General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2 of the License, or (at your option) any later version. |
11 | * |
12 | * This library is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Library General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Library General Public |
18 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
19 | */ |
20 | |
21 | /** |
22 | * SECTION:ctkbuilder |
23 | * @Short_description: Build an interface from an XML UI definition |
24 | * @Title: CtkBuilder |
25 | * |
26 | * A CtkBuilder is an auxiliary object that reads textual descriptions |
27 | * of a user interface and instantiates the described objects. To create |
28 | * a CtkBuilder from a user interface description, call |
29 | * ctk_builder_new_from_file(), ctk_builder_new_from_resource() or |
30 | * ctk_builder_new_from_string(). |
31 | * |
32 | * In the (unusual) case that you want to add user interface |
33 | * descriptions from multiple sources to the same CtkBuilder you can |
34 | * call ctk_builder_new() to get an empty builder and populate it by |
35 | * (multiple) calls to ctk_builder_add_from_file(), |
36 | * ctk_builder_add_from_resource() or ctk_builder_add_from_string(). |
37 | * |
38 | * A CtkBuilder holds a reference to all objects that it has constructed |
39 | * and drops these references when it is finalized. This finalization can |
40 | * cause the destruction of non-widget objects or widgets which are not |
41 | * contained in a toplevel window. For toplevel windows constructed by a |
42 | * builder, it is the responsibility of the user to call ctk_widget_destroy() |
43 | * to get rid of them and all the widgets they contain. |
44 | * |
45 | * The functions ctk_builder_get_object() and ctk_builder_get_objects() |
46 | * can be used to access the widgets in the interface by the names assigned |
47 | * to them inside the UI description. Toplevel windows returned by these |
48 | * functions will stay around until the user explicitly destroys them |
49 | * with ctk_widget_destroy(). Other widgets will either be part of a |
50 | * larger hierarchy constructed by the builder (in which case you should |
51 | * not have to worry about their lifecycle), or without a parent, in which |
52 | * case they have to be added to some container to make use of them. |
53 | * Non-widget objects need to be reffed with g_object_ref() to keep them |
54 | * beyond the lifespan of the builder. |
55 | * |
56 | * The function ctk_builder_connect_signals() and variants thereof can be |
57 | * used to connect handlers to the named signals in the description. |
58 | * |
59 | * # CtkBuilder UI Definitions # {#BUILDER-UI} |
60 | * |
61 | * CtkBuilder parses textual descriptions of user interfaces which are |
62 | * specified in an XML format which can be roughly described by the |
63 | * RELAX NG schema below. We refer to these descriptions as “CtkBuilder |
64 | * UI definitions” or just “UI definitions” if the context is clear. |
65 | * Do not confuse CtkBuilder UI Definitions with |
66 | * [CtkUIManager UI Definitions][XML-UI], which are more limited in scope. |
67 | * It is common to use `.ui` as the filename extension for files containing |
68 | * CtkBuilder UI definitions. |
69 | * |
70 | * [RELAX NG Compact Syntax](https://gitlab.gnome.org/GNOME/ctk/-/blob/ctk-3-24/ctk/ctkbuilder.rnc) |
71 | * |
72 | * The toplevel element is <interface>. It optionally takes a “domain” |
73 | * attribute, which will make the builder look for translated strings |
74 | * using dgettext() in the domain specified. This can also be done by |
75 | * calling ctk_builder_set_translation_domain() on the builder. |
76 | * Objects are described by <object> elements, which can contain |
77 | * <property> elements to set properties, <signal> elements which |
78 | * connect signals to handlers, and <child> elements, which describe |
79 | * child objects (most often widgets inside a container, but also e.g. |
80 | * actions in an action group, or columns in a tree model). A <child> |
81 | * element contains an <object> element which describes the child object. |
82 | * The target toolkit version(s) are described by <requires> elements, |
83 | * the “lib” attribute specifies the widget library in question (currently |
84 | * the only supported value is “ctk+”) and the “version” attribute specifies |
85 | * the target version in the form “<major>.<minor>”. The builder will error |
86 | * out if the version requirements are not met. |
87 | * |
88 | * Typically, the specific kind of object represented by an <object> |
89 | * element is specified by the “class” attribute. If the type has not |
90 | * been loaded yet, CTK+ tries to find the get_type() function from the |
91 | * class name by applying heuristics. This works in most cases, but if |
92 | * necessary, it is possible to specify the name of the get_type() function |
93 | * explictly with the "type-func" attribute. As a special case, CtkBuilder |
94 | * allows to use an object that has been constructed by a #CtkUIManager in |
95 | * another part of the UI definition by specifying the id of the #CtkUIManager |
96 | * in the “constructor” attribute and the name of the object in the “id” |
97 | * attribute. |
98 | * |
99 | * Objects may be given a name with the “id” attribute, which allows the |
100 | * application to retrieve them from the builder with ctk_builder_get_object(). |
101 | * An id is also necessary to use the object as property value in other |
102 | * parts of the UI definition. CTK+ reserves ids starting and ending |
103 | * with ___ (3 underscores) for its own purposes. |
104 | * |
105 | * Setting properties of objects is pretty straightforward with the |
106 | * <property> element: the “name” attribute specifies the name of the |
107 | * property, and the content of the element specifies the value. |
108 | * If the “translatable” attribute is set to a true value, CTK+ uses |
109 | * gettext() (or dgettext() if the builder has a translation domain set) |
110 | * to find a translation for the value. This happens before the value |
111 | * is parsed, so it can be used for properties of any type, but it is |
112 | * probably most useful for string properties. It is also possible to |
113 | * specify a context to disambiguate short strings, and comments which |
114 | * may help the translators. |
115 | * |
116 | * CtkBuilder can parse textual representations for the most common |
117 | * property types: characters, strings, integers, floating-point numbers, |
118 | * booleans (strings like “TRUE”, “t”, “yes”, “y”, “1” are interpreted |
119 | * as %TRUE, strings like “FALSE”, “f”, “no”, “n”, “0” are interpreted |
120 | * as %FALSE), enumerations (can be specified by their name, nick or |
121 | * integer value), flags (can be specified by their name, nick, integer |
122 | * value, optionally combined with “|”, e.g. “CTK_VISIBLE|CTK_REALIZED”) |
123 | * and colors (in a format understood by cdk_rgba_parse()). |
124 | * |
125 | * GVariants can be specified in the format understood by g_variant_parse(), |
126 | * and pixbufs can be specified as a filename of an image file to load. |
127 | * |
128 | * Objects can be referred to by their name and by default refer to |
129 | * objects declared in the local xml fragment and objects exposed via |
130 | * ctk_builder_expose_object(). In general, CtkBuilder allows forward |
131 | * references to objects — declared in the local xml; an object doesn’t |
132 | * have to be constructed before it can be referred to. The exception |
133 | * to this rule is that an object has to be constructed before it can |
134 | * be used as the value of a construct-only property. |
135 | * |
136 | * It is also possible to bind a property value to another object's |
137 | * property value using the attributes |
138 | * "bind-source" to specify the source object of the binding, |
139 | * "bind-property" to specify the source property and optionally |
140 | * "bind-flags" to specify the binding flags. |
141 | * Internally builder implements this using GBinding objects. |
142 | * For more information see g_object_bind_property() |
143 | * |
144 | * Signal handlers are set up with the <signal> element. The “name” |
145 | * attribute specifies the name of the signal, and the “handler” attribute |
146 | * specifies the function to connect to the signal. By default, CTK+ tries |
147 | * to find the handler using g_module_symbol(), but this can be changed by |
148 | * passing a custom #CtkBuilderConnectFunc to |
149 | * ctk_builder_connect_signals_full(). The remaining attributes, “after”, |
150 | * “swapped” and “object”, have the same meaning as the corresponding |
151 | * parameters of the g_signal_connect_object() or |
152 | * g_signal_connect_data() functions. A “last_modification_time” |
153 | * attribute is also allowed, but it does not have a meaning to the |
154 | * builder. |
155 | * |
156 | * Sometimes it is necessary to refer to widgets which have implicitly |
157 | * been constructed by CTK+ as part of a composite widget, to set |
158 | * properties on them or to add further children (e.g. the @vbox of |
159 | * a #CtkDialog). This can be achieved by setting the “internal-child” |
160 | * property of the <child> element to a true value. Note that CtkBuilder |
161 | * still requires an <object> element for the internal child, even if it |
162 | * has already been constructed. |
163 | * |
164 | * A number of widgets have different places where a child can be added |
165 | * (e.g. tabs vs. page content in notebooks). This can be reflected in |
166 | * a UI definition by specifying the “type” attribute on a <child> |
167 | * The possible values for the “type” attribute are described in the |
168 | * sections describing the widget-specific portions of UI definitions. |
169 | * |
170 | * # A CtkBuilder UI Definition |
171 | * |
172 | * |[ |
173 | * <interface> |
174 | * <object class="CtkDialog" id="dialog1"> |
175 | * <child internal-child="vbox"> |
176 | * <object class="CtkBox" id="vbox1"> |
177 | * <property name="border-width">10</property> |
178 | * <child internal-child="action_area"> |
179 | * <object class="CtkButtonBox" id="hbuttonbox1"> |
180 | * <property name="border-width">20</property> |
181 | * <child> |
182 | * <object class="CtkButton" id="ok_button"> |
183 | * <property name="label">ctk-ok</property> |
184 | * <property name="use-stock">TRUE</property> |
185 | * <signal name="clicked" handler="ok_button_clicked"/> |
186 | * </object> |
187 | * </child> |
188 | * </object> |
189 | * </child> |
190 | * </object> |
191 | * </child> |
192 | * </object> |
193 | * </interface> |
194 | * ]| |
195 | * |
196 | * Beyond this general structure, several object classes define their |
197 | * own XML DTD fragments for filling in the ANY placeholders in the DTD |
198 | * above. Note that a custom element in a <child> element gets parsed by |
199 | * the custom tag handler of the parent object, while a custom element in |
200 | * an <object> element gets parsed by the custom tag handler of the object. |
201 | * |
202 | * These XML fragments are explained in the documentation of the |
203 | * respective objects. |
204 | * |
205 | * Additionally, since 3.10 a special <template> tag has been added |
206 | * to the format allowing one to define a widget class’s components. |
207 | * See the [CtkWidget documentation][composite-templates] for details. |
208 | */ |
209 | |
210 | #include "config.h" |
211 | #include <errno(*__errno_location ()).h> /* errno */ |
212 | #include <stdlib.h> |
213 | #include <string.h> /* strlen */ |
214 | |
215 | #include "ctkbuilder.h" |
216 | #include "ctkbuildable.h" |
217 | #include "ctkbuilderprivate.h" |
218 | #include "ctkdebug.h" |
219 | #include "ctkmain.h" |
220 | #include "ctkintl.h" |
221 | #include "ctkprivate.h" |
222 | #include "ctktypebuiltins.h" |
223 | #include "ctkwindow.h" |
224 | #include "ctkicontheme.h" |
225 | #include "ctktestutils.h" |
226 | #include "ctkstock.h" |
227 | |
228 | |
229 | static void ctk_builder_class_init (CtkBuilderClass *klass); |
230 | static void ctk_builder_init (CtkBuilder *builder); |
231 | static void ctk_builder_finalize (GObject *object); |
232 | static void ctk_builder_set_property (GObject *object, |
233 | guint prop_id, |
234 | const GValue *value, |
235 | GParamSpec *pspec); |
236 | static void ctk_builder_get_property (GObject *object, |
237 | guint prop_id, |
238 | GValue *value, |
239 | GParamSpec *pspec); |
240 | static GType ctk_builder_real_get_type_from_name (CtkBuilder *builder, |
241 | const gchar *type_name); |
242 | |
243 | enum { |
244 | PROP_0, |
245 | PROP_TRANSLATION_DOMAIN, |
246 | LAST_PROP |
247 | }; |
248 | |
249 | static GParamSpec *builder_props[LAST_PROP]; |
250 | |
251 | struct _CtkBuilderPrivate |
252 | { |
253 | gchar *domain; |
254 | GHashTable *objects; |
255 | GHashTable *callbacks; |
256 | GSList *delayed_properties; |
257 | GSList *signals; |
258 | GSList *bindings; |
259 | gchar *filename; |
260 | gchar *resource_prefix; |
261 | GType template_type; |
262 | CtkApplication *application; |
263 | }; |
264 | |
265 | G_DEFINE_TYPE_WITH_PRIVATE (CtkBuilder, ctk_builder, G_TYPE_OBJECT)static void ctk_builder_init (CtkBuilder *self); static void ctk_builder_class_init (CtkBuilderClass *klass); static GType ctk_builder_get_type_once (void); static gpointer ctk_builder_parent_class = ((void*)0 ); static gint CtkBuilder_private_offset; static void ctk_builder_class_intern_init (gpointer klass) { ctk_builder_parent_class = g_type_class_peek_parent (klass); if (CtkBuilder_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkBuilder_private_offset); ctk_builder_class_init ((CtkBuilderClass*) klass); } __attribute__ ((__unused__)) static inline gpointer ctk_builder_get_instance_private (CtkBuilder *self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkBuilder_private_offset )))); } GType ctk_builder_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); (void ) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*) 0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = ctk_builder_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id ) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id )); })) ; } return static_g_define_type_id; } __attribute__ ( (__noinline__)) static GType ctk_builder_get_type_once (void) { GType g_define_type_id = g_type_register_static_simple ((( GType) ((20) << (2))), g_intern_static_string ("CtkBuilder" ), sizeof (CtkBuilderClass), (GClassInitFunc)(void (*)(void)) ctk_builder_class_intern_init, sizeof (CtkBuilder), (GInstanceInitFunc )(void (*)(void)) ctk_builder_init, (GTypeFlags) 0); { {{ CtkBuilder_private_offset = g_type_add_instance_private (g_define_type_id, sizeof (CtkBuilderPrivate )); };} } return g_define_type_id; } |
266 | |
267 | static void |
268 | ctk_builder_class_init (CtkBuilderClass *klass) |
269 | { |
270 | GObjectClass *gobject_class; |
271 | |
272 | gobject_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); |
273 | |
274 | gobject_class->finalize = ctk_builder_finalize; |
275 | gobject_class->set_property = ctk_builder_set_property; |
276 | gobject_class->get_property = ctk_builder_get_property; |
277 | |
278 | klass->get_type_from_name = ctk_builder_real_get_type_from_name; |
279 | |
280 | /** |
281 | * CtkBuilder:translation-domain: |
282 | * |
283 | * The translation domain used when translating property values that |
284 | * have been marked as translatable in interface descriptions. |
285 | * If the translation domain is %NULL, #CtkBuilder uses gettext(), |
286 | * otherwise g_dgettext(). |
287 | * |
288 | * Since: 2.12 |
289 | */ |
290 | builder_props[PROP_TRANSLATION_DOMAIN] = |
291 | g_param_spec_string ("translation-domain", |
292 | P_("Translation Domain")g_dgettext("ctk30" "-properties","Translation Domain"), |
293 | P_("The translation domain used by gettext")g_dgettext("ctk30" "-properties","The translation domain used by gettext" ), |
294 | NULL((void*)0), |
295 | CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB); |
296 | |
297 | g_object_class_install_properties (gobject_class, LAST_PROP, builder_props); |
298 | } |
299 | |
300 | static void |
301 | ctk_builder_init (CtkBuilder *builder) |
302 | { |
303 | builder->priv = ctk_builder_get_instance_private (builder); |
304 | builder->priv->domain = NULL((void*)0); |
305 | builder->priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal, |
306 | g_free, g_object_unref); |
307 | } |
308 | |
309 | |
310 | /* |
311 | * GObject virtual methods |
312 | */ |
313 | |
314 | static void |
315 | ctk_builder_finalize (GObject *object) |
316 | { |
317 | CtkBuilderPrivate *priv = CTK_BUILDER (object)((((CtkBuilder*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_builder_get_type ()))))))->priv; |
318 | |
319 | g_free (priv->domain); |
320 | g_free (priv->filename); |
321 | g_free (priv->resource_prefix); |
322 | |
323 | g_hash_table_destroy (priv->objects); |
324 | if (priv->callbacks) |
325 | g_hash_table_destroy (priv->callbacks); |
326 | |
327 | g_slist_free_full (priv->signals, (GDestroyNotify)_free_signal_info); |
328 | |
329 | G_OBJECT_CLASS (ctk_builder_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_builder_parent_class)), (((GType) ((20) << (2) )))))))->finalize (object); |
330 | } |
331 | |
332 | static void |
333 | ctk_builder_set_property (GObject *object, |
334 | guint prop_id, |
335 | const GValue *value, |
336 | GParamSpec *pspec) |
337 | { |
338 | CtkBuilder *builder = CTK_BUILDER (object)((((CtkBuilder*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_builder_get_type ())))))); |
339 | |
340 | switch (prop_id) |
341 | { |
342 | case PROP_TRANSLATION_DOMAIN: |
343 | ctk_builder_set_translation_domain (builder, g_value_get_string (value)); |
344 | break; |
345 | default: |
346 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec *_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id = ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'" , "ctkbuilder.c", 346, ("property"), _glib__property_id, _glib__pspec ->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) ( _glib__pspec))->g_class))->g_type)))), (g_type_name ((( (((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class ))->g_type)))))); } while (0); |
347 | break; |
348 | } |
349 | } |
350 | |
351 | static void |
352 | ctk_builder_get_property (GObject *object, |
353 | guint prop_id, |
354 | GValue *value, |
355 | GParamSpec *pspec) |
356 | { |
357 | CtkBuilder *builder = CTK_BUILDER (object)((((CtkBuilder*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_builder_get_type ())))))); |
358 | |
359 | switch (prop_id) |
360 | { |
361 | case PROP_TRANSLATION_DOMAIN: |
362 | g_value_set_string (value, builder->priv->domain); |
363 | break; |
364 | default: |
365 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec *_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id = ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'" , "ctkbuilder.c", 365, ("property"), _glib__property_id, _glib__pspec ->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) ( _glib__pspec))->g_class))->g_type)))), (g_type_name ((( (((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class ))->g_type)))))); } while (0); |
366 | break; |
367 | } |
368 | } |
369 | |
370 | |
371 | /* |
372 | * Try to map a type name to a _get_type function |
373 | * and call it, eg: |
374 | * |
375 | * CtkWindow -> ctk_window_get_type |
376 | * CtkHBox -> ctk_hbox_get_type |
377 | * CtkUIManager -> ctk_ui_manager_get_type |
378 | * GWeatherLocation -> gweather_location_get_type |
379 | * |
380 | * Keep in sync with testsuite/ctk/typename.c ! |
381 | */ |
382 | static gchar * |
383 | type_name_mangle (const gchar *name) |
384 | { |
385 | GString *symbol_name = g_string_new (""); |
386 | gint i; |
387 | |
388 | for (i = 0; name[i] != '\0'; i++) |
389 | { |
390 | /* skip if uppercase, first or previous is uppercase */ |
391 | if ((name[i] == g_ascii_toupper (name[i]) && |
392 | i > 0 && name[i-1] != g_ascii_toupper (name[i-1])) || |
393 | (i > 2 && name[i] == g_ascii_toupper (name[i]) && |
394 | name[i-1] == g_ascii_toupper (name[i-1]) && |
395 | name[i-2] == g_ascii_toupper (name[i-2]))) |
396 | g_string_append_c (symbol_name, '_')g_string_append_c_inline (symbol_name, '_'); |
397 | g_string_append_c (symbol_name, g_ascii_tolower (name[i]))g_string_append_c_inline (symbol_name, g_ascii_tolower (name[ i])); |
398 | } |
399 | g_string_append (symbol_name, "_get_type")(__builtin_constant_p ("_get_type") ? __extension__ ({ const char * const __val = ("_get_type"); g_string_append_len_inline (symbol_name , __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + ! (__val))) : (gssize) -1); }) : g_string_append_len_inline (symbol_name , "_get_type", (gssize) -1)); |
400 | |
401 | return g_string_free (symbol_name, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((symbol_name ), ((0))) : g_string_free_and_steal (symbol_name)) : (g_string_free ) ((symbol_name), ((0)))); |
402 | } |
403 | |
404 | static GType |
405 | _ctk_builder_resolve_type_lazily (const gchar *name) |
406 | { |
407 | static GModule *module = NULL((void*)0); |
408 | GTypeGetFunc func; |
409 | gchar *symbol; |
410 | GType gtype = G_TYPE_INVALID((GType) ((0) << (2))); |
411 | |
412 | if (!module) |
413 | module = g_module_open (NULL((void*)0), 0); |
414 | |
415 | symbol = type_name_mangle (name); |
416 | |
417 | if (g_module_symbol (module, symbol, (gpointer)&func)) |
418 | gtype = func (); |
419 | |
420 | g_free (symbol); |
421 | |
422 | return gtype; |
423 | } |
424 | |
425 | /* |
426 | * CtkBuilder virtual methods |
427 | */ |
428 | |
429 | static GType |
430 | ctk_builder_real_get_type_from_name (CtkBuilder *builder G_GNUC_UNUSED__attribute__ ((__unused__)), |
431 | const gchar *type_name) |
432 | { |
433 | GType gtype; |
434 | |
435 | gtype = g_type_from_name (type_name); |
436 | if (gtype != G_TYPE_INVALID((GType) ((0) << (2)))) |
437 | return gtype; |
438 | |
439 | gtype = _ctk_builder_resolve_type_lazily (type_name); |
440 | if (gtype != G_TYPE_INVALID((GType) ((0) << (2)))) |
441 | return gtype; |
442 | |
443 | ctk_test_register_all_types (); |
444 | return g_type_from_name (type_name); |
445 | } |
446 | |
447 | typedef struct |
448 | { |
449 | gchar *object; |
450 | GParamSpec *pspec; |
451 | gchar *value; |
452 | gint line; |
453 | gint col; |
454 | } DelayedProperty; |
455 | |
456 | typedef struct |
457 | { |
458 | GPtrArray *names; |
459 | GArray *values; |
460 | guint len; |
461 | } ObjectProperties; |
462 | |
463 | static ObjectProperties * |
464 | object_properties_new (void) |
465 | { |
466 | ObjectProperties *res = g_new (ObjectProperties, 1)((ObjectProperties *) g_malloc_n ((1), sizeof (ObjectProperties ))); |
467 | |
468 | res->names = g_ptr_array_new (); |
469 | |
470 | res->values = g_array_new (FALSE(0), FALSE(0), sizeof (GValue)); |
471 | g_array_set_clear_func (res->values, (GDestroyNotify) g_value_unset); |
472 | |
473 | res->len = 0; |
474 | |
475 | return res; |
476 | } |
477 | |
478 | static void |
479 | object_properties_free (ObjectProperties *properties) |
480 | { |
481 | if (properties == NULL((void*)0)) |
482 | return; |
483 | |
484 | g_ptr_array_unref (properties->names); |
485 | g_array_unref (properties->values); |
486 | |
487 | g_free (properties); |
488 | } |
489 | |
490 | static void |
491 | object_properties_add (ObjectProperties *properties, |
492 | const char *name, |
493 | const GValue *value) |
494 | { |
495 | g_ptr_array_add (properties->names, (char *) name); |
496 | g_array_append_vals (properties->values, value, 1); |
497 | |
498 | g_assert (properties->names->len == properties->values->len)do { if (properties->names->len == properties->values ->len) ; else g_assertion_message_expr ("Ctk", "ctkbuilder.c" , 498, ((const char*) (__func__)), "properties->names->len == properties->values->len" ); } while (0); |
499 | |
500 | properties->len += 1; |
501 | } |
502 | |
503 | static const char * |
504 | object_properties_get_name (ObjectProperties *properties, |
505 | guint idx) |
506 | { |
507 | return g_ptr_array_index (properties->names, idx)((properties->names)->pdata)[idx]; |
508 | } |
509 | |
510 | static GValue * |
511 | object_properties_get_value (ObjectProperties *properties, |
512 | guint idx) |
513 | { |
514 | return &g_array_index (properties->values, GValue, idx)(((GValue*) (void *) (properties->values)->data) [(idx) ]); |
515 | } |
516 | |
517 | static void |
518 | ctk_builder_get_parameters (CtkBuilder *builder, |
519 | GType object_type, |
520 | const gchar *object_name, |
521 | GSList *properties, |
522 | GParamFlags filter_flags, |
523 | ObjectProperties **parameters, |
524 | ObjectProperties **filtered_parameters) |
525 | { |
526 | GSList *l; |
527 | DelayedProperty *property; |
528 | GError *error = NULL((void*)0); |
529 | |
530 | if (parameters) |
531 | *parameters = object_properties_new (); |
532 | if (filtered_parameters) |
533 | *filtered_parameters = object_properties_new (); |
534 | |
535 | for (l = properties; l; l = l->next) |
536 | { |
537 | PropertyInfo *prop = (PropertyInfo*)l->data; |
538 | const char *property_name = g_intern_string (prop->pspec->name); |
539 | GValue property_value = G_VALUE_INIT{ 0, { { 0 } } }; |
540 | |
541 | if (G_IS_PARAM_SPEC_OBJECT (prop->pspec)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (prop->pspec)); GType __t = ((g_param_spec_types[19])); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))) && |
542 | (G_PARAM_SPEC_VALUE_TYPE (prop->pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((prop->pspec)), (((GType) ((19) << (2))))))))-> value_type) != GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ())) && |
543 | (G_PARAM_SPEC_VALUE_TYPE (prop->pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((prop->pspec)), (((GType) ((19) << (2))))))))-> value_type) != G_TYPE_FILE(g_file_get_type ()))) |
544 | { |
545 | GObject *object = g_hash_table_lookup (builder->priv->objects, |
546 | prop->text->str); |
547 | |
548 | if (object) |
549 | { |
550 | g_value_init (&property_value, G_OBJECT_TYPE (object)(((((GTypeClass*) (((GTypeInstance*) (object))->g_class))-> g_type)))); |
551 | g_value_set_object (&property_value, object); |
552 | } |
553 | else |
554 | { |
555 | if (prop->pspec->flags & G_PARAM_CONSTRUCT_ONLY) |
556 | { |
557 | g_warning ("Failed to get construct only property " |
558 | "%s of %s with value '%s'", |
559 | prop->pspec->name, object_name, prop->text->str); |
560 | continue; |
561 | } |
562 | /* Delay setting property */ |
563 | property = g_slice_new (DelayedProperty)((DelayedProperty*) g_slice_alloc (sizeof (DelayedProperty))); |
564 | property->pspec = prop->pspec; |
565 | property->object = g_strdup (object_name)g_strdup_inline (object_name); |
566 | property->value = g_strdup (prop->text->str)g_strdup_inline (prop->text->str); |
567 | property->line = prop->line; |
568 | property->col = prop->col; |
569 | builder->priv->delayed_properties = |
570 | g_slist_prepend (builder->priv->delayed_properties, property); |
571 | continue; |
572 | } |
573 | } |
574 | else if (prop->bound && (!prop->text || prop->text->len == 0)) |
575 | { |
576 | /* Ignore properties with a binding and no value since they are |
577 | * only there for to express the binding. |
578 | */ |
579 | continue; |
580 | } |
581 | else if (!ctk_builder_value_from_string (builder, prop->pspec, |
582 | prop->text->str, |
583 | &property_value, |
584 | &error)) |
585 | { |
586 | g_warning ("Failed to set property %s.%s to %s: %s", |
587 | g_type_name (object_type), prop->pspec->name, prop->text->str, |
588 | error->message); |
589 | g_error_free (error); |
590 | error = NULL((void*)0); |
591 | continue; |
592 | } |
593 | |
594 | if (prop->pspec->flags & filter_flags) |
595 | { |
596 | if (filtered_parameters) |
597 | object_properties_add (*filtered_parameters, property_name, &property_value); |
598 | } |
599 | else |
600 | { |
601 | if (parameters) |
602 | object_properties_add (*parameters, property_name, &property_value); |
603 | } |
604 | } |
605 | } |
606 | |
607 | static const gchar * |
608 | object_get_name (GObject *object) |
609 | { |
610 | if (CTK_IS_BUILDABLE (object)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (object)); GType __t = ((ctk_buildable_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
611 | return ctk_buildable_get_name (CTK_BUILDABLE (object)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_buildable_get_type ()))))))); |
612 | else |
613 | return g_object_get_data (object, "ctk-builder-name"); |
614 | } |
615 | |
616 | static GObject * |
617 | ctk_builder_get_internal_child (CtkBuilder *builder, |
618 | ObjectInfo *info, |
619 | const gchar *childname, |
620 | GError **error) |
621 | { |
622 | GObject *obj = NULL((void*)0); |
623 | |
624 | while (!obj) |
625 | { |
626 | if (!info->parent) |
627 | break; |
628 | |
629 | info = (ObjectInfo*)((ChildInfo*)info->parent)->parent; |
630 | if (!info) |
631 | break; |
632 | |
633 | CTK_NOTE (BUILDER,do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message ("Trying to get internal child %s from %s", childname, object_get_name (info->object)); }; } while (0) |
634 | g_message ("Trying to get internal child %s from %s",do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message ("Trying to get internal child %s from %s", childname, object_get_name (info->object)); }; } while (0) |
635 | childname, object_get_name (info->object)))do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message ("Trying to get internal child %s from %s", childname, object_get_name (info->object)); }; } while (0); |
636 | |
637 | if (CTK_IS_BUILDABLE (info->object)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (info->object)); GType __t = ((ctk_buildable_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } ))))) |
638 | obj = ctk_buildable_get_internal_child (CTK_BUILDABLE (info->object)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((info->object)), ((ctk_buildable_get_type ())))))), |
639 | builder, |
640 | childname); |
641 | }; |
642 | |
643 | if (!obj) |
644 | { |
645 | g_set_error (error, |
646 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
647 | CTK_BUILDER_ERROR_INVALID_VALUE, |
648 | "Unknown internal child: %s", childname); |
649 | } |
650 | return obj; |
651 | } |
652 | |
653 | static inline void |
654 | object_set_name (GObject *object, |
655 | const gchar *name) |
656 | { |
657 | if (CTK_IS_BUILDABLE (object)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (object)); GType __t = ((ctk_buildable_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
658 | ctk_buildable_set_name (CTK_BUILDABLE (object)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_buildable_get_type ())))))), name); |
659 | else |
660 | g_object_set_data_full (object, "ctk-builder-name", g_strdup (name)g_strdup_inline (name), g_free); |
661 | } |
662 | |
663 | void |
664 | _ctk_builder_add_object (CtkBuilder *builder, |
665 | const gchar *id, |
666 | GObject *object) |
667 | { |
668 | object_set_name (object, id); |
669 | g_hash_table_insert (builder->priv->objects, g_strdup (id)g_strdup_inline (id), g_object_ref (object)((__typeof__ (object)) (g_object_ref) (object))); |
670 | } |
671 | |
672 | static void |
673 | ctk_builder_take_bindings (CtkBuilder *builder, |
674 | GObject *target, |
675 | GSList *bindings) |
676 | { |
677 | GSList *l; |
678 | |
679 | for (l = bindings; l; l = l->next) |
680 | { |
681 | BindingInfo *info = l->data; |
682 | info->target = target; |
683 | } |
684 | |
685 | builder->priv->bindings = g_slist_concat (builder->priv->bindings, bindings); |
686 | } |
687 | |
688 | GObject * |
689 | _ctk_builder_construct (CtkBuilder *builder, |
690 | ObjectInfo *info, |
691 | GError **error) |
692 | { |
693 | ObjectProperties *parameters, *construct_parameters; |
694 | GObject *obj; |
695 | int i; |
696 | CtkBuildableIface *iface; |
697 | gboolean custom_set_property; |
698 | CtkBuildable *buildable; |
699 | GParamFlags param_filter_flags; |
700 | |
701 | g_assert (info->type != G_TYPE_INVALID)do { if (info->type != ((GType) ((0) << (2)))) ; else g_assertion_message_expr ("Ctk", "ctkbuilder.c", 701, ((const char*) (__func__)), "info->type != G_TYPE_INVALID"); } while (0); |
702 | |
703 | if (builder->priv->template_type != 0 && |
704 | g_type_is_a (info->type, builder->priv->template_type)((info->type) == (builder->priv->template_type) || ( g_type_is_a) ((info->type), (builder->priv->template_type )))) |
705 | { |
706 | g_set_error (error, |
707 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
708 | CTK_BUILDER_ERROR_OBJECT_TYPE_REFUSED, |
709 | "Refused to build object of type '%s' because it " |
710 | "conforms to the template type '%s', avoiding infinite recursion.", |
711 | g_type_name (info->type), g_type_name (builder->priv->template_type)); |
712 | return NULL((void*)0); |
713 | } |
714 | |
715 | /* If there is a manual constructor (like UIManager), or if this is a |
716 | * reference to an internal child, then we filter out construct-only |
717 | * and warn that they cannot be set. |
718 | * |
719 | * Otherwise if we are calling g_object_new_with_properties(), we want |
720 | * to pass both G_PARAM_CONSTRUCT and G_PARAM_CONSTRUCT_ONLY to the |
721 | * object's constructor. |
722 | * |
723 | * Passing all construct properties to g_object_new_with_properties() |
724 | * slightly improves performance as the construct properties will only |
725 | * be set once. |
726 | */ |
727 | if (info->constructor || |
728 | (info->parent && ((ChildInfo*)info->parent)->internal_child != NULL((void*)0))) |
729 | param_filter_flags = G_PARAM_CONSTRUCT_ONLY; |
730 | else |
731 | param_filter_flags = G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY; |
732 | |
733 | ctk_builder_get_parameters (builder, info->type, |
734 | info->id, |
735 | info->properties, |
736 | param_filter_flags, |
737 | ¶meters, |
738 | &construct_parameters); |
739 | |
740 | if (info->constructor) |
741 | { |
742 | GObject *constructor; |
743 | |
744 | constructor = g_hash_table_lookup (builder->priv->objects, info->constructor); |
745 | if (constructor == NULL((void*)0)) |
746 | { |
747 | g_set_error (error, |
748 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
749 | CTK_BUILDER_ERROR_INVALID_VALUE, |
750 | "Unknown object constructor for %s: %s", |
751 | info->id, |
752 | info->constructor); |
753 | object_properties_free (parameters); |
754 | object_properties_free (construct_parameters); |
755 | return NULL((void*)0); |
756 | } |
757 | obj = ctk_buildable_construct_child (CTK_BUILDABLE (constructor)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((constructor)), ((ctk_buildable_get_type ())))))), |
758 | builder, |
759 | info->id); |
760 | g_assert (obj != NULL)do { if (obj != ((void*)0)) ; else g_assertion_message_expr ( "Ctk", "ctkbuilder.c", 760, ((const char*) (__func__)), "obj != NULL" ); } while (0); |
761 | if (construct_parameters->len) |
762 | g_warning ("Can't pass in construct-only parameters to %s", info->id); |
763 | } |
764 | else if (info->parent && ((ChildInfo*)info->parent)->internal_child != NULL((void*)0)) |
765 | { |
766 | gchar *childname = ((ChildInfo*)info->parent)->internal_child; |
767 | obj = ctk_builder_get_internal_child (builder, info, childname, error); |
768 | if (!obj) |
769 | { |
770 | object_properties_free (parameters); |
771 | object_properties_free (construct_parameters); |
772 | return NULL((void*)0); |
773 | } |
774 | if (construct_parameters->len) |
775 | g_warning ("Can't pass in construct-only parameters to %s", childname); |
776 | g_object_ref (obj)((__typeof__ (obj)) (g_object_ref) (obj)); |
777 | } |
778 | else |
779 | { |
780 | obj = g_object_new_with_properties (info->type, |
781 | construct_parameters->len, |
782 | (const char **) construct_parameters->names->pdata, |
783 | (GValue *) construct_parameters->values->data); |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
784 | |
785 | /* No matter what, make sure we have a reference. |
786 | * |
787 | * If it's an initially unowned object, sink it. |
788 | * If it's not initially unowned then we have the reference already. |
789 | * |
790 | * In the case that this is a window it will be sunk already and |
791 | * this is effectively a call to g_object_ref(). That's what |
792 | * we want. |
793 | */ |
794 | if (G_IS_INITIALLY_UNOWNED (obj)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (obj)); GType __t = ((g_initially_unowned_get_type())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
795 | g_object_ref_sink (obj)((__typeof__ (obj)) (g_object_ref_sink) (obj)); |
796 | |
797 | CTK_NOTE (BUILDER,do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message ("created %s of type %s", info->id, g_type_name (info-> type)); }; } while (0) |
798 | g_message ("created %s of type %s", info->id, g_type_name (info->type)))do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message ("created %s of type %s", info->id, g_type_name (info-> type)); }; } while (0); |
799 | } |
800 | |
801 | object_properties_free (construct_parameters); |
802 | |
803 | custom_set_property = FALSE(0); |
804 | buildable = NULL((void*)0); |
805 | iface = NULL((void*)0); |
806 | if (CTK_IS_BUILDABLE (obj)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (obj)); GType __t = ((ctk_buildable_get_type ())); gboolean __r ; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
807 | { |
808 | buildable = CTK_BUILDABLE (obj)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((obj)), ((ctk_buildable_get_type ())))))); |
809 | iface = CTK_BUILDABLE_GET_IFACE (obj)((((CtkBuildableIface*) g_type_interface_peek (((GTypeInstance *) ((obj)))->g_class, ((ctk_buildable_get_type ())))))); |
810 | if (iface->set_buildable_property) |
811 | custom_set_property = TRUE(!(0)); |
812 | } |
813 | |
814 | /* We're going to set multiple properties in one go, so it's better |
815 | * to notify changes at the end |
816 | */ |
817 | g_object_freeze_notify (obj); |
818 | |
819 | for (i = 0; i < parameters->len; i++) |
820 | { |
821 | const char *name = object_properties_get_name (parameters, i); |
822 | const GValue *value = object_properties_get_value (parameters, i); |
823 | |
824 | if (custom_set_property) |
825 | iface->set_buildable_property (buildable, builder, name, value); |
826 | else |
827 | g_object_set_property (obj, name, value); |
828 | |
829 | #ifdef G_ENABLE_DEBUG1 |
830 | if (CTK_DEBUG_CHECK (BUILDER)(ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) |
831 | { |
832 | gchar *str = g_strdup_value_contents (value); |
833 | g_message ("set %s: %s = %s", info->id, name, str); |
834 | g_free (str); |
835 | } |
836 | #endif |
837 | } |
838 | |
839 | g_object_thaw_notify (obj); |
840 | |
841 | object_properties_free (parameters); |
842 | |
843 | if (info->bindings) |
844 | ctk_builder_take_bindings (builder, obj, info->bindings); |
845 | |
846 | /* put it in the hash table. */ |
847 | _ctk_builder_add_object (builder, info->id, obj); |
848 | |
849 | /* we already own a reference to obj. */ |
850 | g_object_unref (obj); |
851 | |
852 | return obj; |
853 | } |
854 | |
855 | void |
856 | _ctk_builder_apply_properties (CtkBuilder *builder, |
857 | ObjectInfo *info, |
858 | GError **error G_GNUC_UNUSED__attribute__ ((__unused__))) |
859 | { |
860 | ObjectProperties *parameters; |
861 | CtkBuildableIface *iface; |
862 | CtkBuildable *buildable; |
863 | gboolean custom_set_property; |
864 | gint i; |
865 | |
866 | g_assert (info->object != NULL)do { if (info->object != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkbuilder.c", 866, ((const char*) (__func__)), "info->object != NULL" ); } while (0); |
867 | g_assert (info->type != G_TYPE_INVALID)do { if (info->type != ((GType) ((0) << (2)))) ; else g_assertion_message_expr ("Ctk", "ctkbuilder.c", 867, ((const char*) (__func__)), "info->type != G_TYPE_INVALID"); } while (0); |
868 | |
869 | /* Fetch all properties that are not construct-only */ |
870 | ctk_builder_get_parameters (builder, info->type, |
871 | info->id, |
872 | info->properties, |
873 | G_PARAM_CONSTRUCT_ONLY, |
874 | ¶meters, NULL((void*)0)); |
875 | |
876 | custom_set_property = FALSE(0); |
877 | buildable = NULL((void*)0); |
878 | iface = NULL((void*)0); |
879 | if (CTK_IS_BUILDABLE (info->object)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (info->object)); GType __t = ((ctk_buildable_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } ))))) |
880 | { |
881 | buildable = CTK_BUILDABLE (info->object)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((info->object)), ((ctk_buildable_get_type ())))))); |
882 | iface = CTK_BUILDABLE_GET_IFACE (info->object)((((CtkBuildableIface*) g_type_interface_peek (((GTypeInstance *) ((info->object)))->g_class, ((ctk_buildable_get_type ())))))); |
883 | if (iface->set_buildable_property) |
884 | custom_set_property = TRUE(!(0)); |
885 | } |
886 | |
887 | g_object_freeze_notify (info->object); |
888 | |
889 | for (i = 0; i < parameters->len; i++) |
890 | { |
891 | const char *name = object_properties_get_name (parameters, i); |
892 | const GValue *value = object_properties_get_value (parameters, i); |
893 | if (custom_set_property) |
894 | iface->set_buildable_property (buildable, builder, name, value); |
895 | else |
896 | g_object_set_property (info->object, name, value); |
897 | |
898 | #ifdef G_ENABLE_DEBUG1 |
899 | if (CTK_DEBUG_CHECK (BUILDER)(ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) |
900 | { |
901 | gchar *str = g_strdup_value_contents (value); |
902 | g_message ("set %s: %s = %s", info->id, name, str); |
903 | g_free (str); |
904 | } |
905 | #endif |
906 | } |
907 | |
908 | g_object_thaw_notify (info->object); |
909 | |
910 | object_properties_free (parameters); |
911 | } |
912 | |
913 | void |
914 | _ctk_builder_add (CtkBuilder *builder, |
915 | ChildInfo *child_info) |
916 | { |
917 | GObject *object; |
918 | GObject *parent; |
919 | |
920 | /* Internal children are already added |
921 | * Also prevent us from being called twice. |
922 | */ |
923 | if (!child_info || |
924 | child_info->internal_child || |
925 | child_info->added) |
926 | return; |
927 | |
928 | object = child_info->object; |
929 | if (!object) |
930 | return; |
931 | |
932 | if (!child_info->parent) |
933 | { |
934 | g_warning ("%s: Not adding, No parent", object_get_name (object)); |
935 | return; |
936 | } |
937 | |
938 | g_assert (object != NULL)do { if (object != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkbuilder.c", 938, ((const char*) (__func__)), "object != NULL" ); } while (0); |
939 | |
940 | parent = ((ObjectInfo*)child_info->parent)->object; |
941 | g_assert (CTK_IS_BUILDABLE (parent))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((parent)); GType __t = ((ctk_buildable_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else g_assertion_message_expr ("Ctk", "ctkbuilder.c", 941, ((const char*) (__func__)), "CTK_IS_BUILDABLE (parent)"); } while (0 ); |
942 | |
943 | CTK_NOTE (BUILDER,do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message ("adding %s to %s", object_get_name (object), object_get_name (parent)); }; } while (0) |
944 | g_message ("adding %s to %s", object_get_name (object), object_get_name (parent)))do { if ((ctk_get_debug_flags () & CTK_DEBUG_BUILDER)) { g_message ("adding %s to %s", object_get_name (object), object_get_name (parent)); }; } while (0); |
945 | |
946 | ctk_buildable_add_child (CTK_BUILDABLE (parent)((((CtkBuildable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((parent)), ((ctk_buildable_get_type ())))))), builder, object, |
947 | child_info->type); |
948 | |
949 | child_info->added = TRUE(!(0)); |
950 | } |
951 | |
952 | void |
953 | _ctk_builder_add_signals (CtkBuilder *builder, |
954 | GSList *signals) |
955 | { |
956 | builder->priv->signals = g_slist_concat (builder->priv->signals, |
957 | g_slist_copy (signals)); |
958 | } |
959 | |
960 | static void |
961 | ctk_builder_apply_delayed_properties (CtkBuilder *builder) |
962 | { |
963 | GSList *l, *props; |
964 | |
965 | /* take the list over from the builder->priv. |
966 | * |
967 | * g_slist_reverse does not copy the list, so the list now |
968 | * belongs to us (and we free it at the end of this function). |
969 | */ |
970 | props = g_slist_reverse (builder->priv->delayed_properties); |
971 | builder->priv->delayed_properties = NULL((void*)0); |
972 | |
973 | for (l = props; l; l = l->next) |
974 | { |
975 | DelayedProperty *property = l->data; |
976 | GObject *object, *obj; |
977 | |
978 | object = g_hash_table_lookup (builder->priv->objects, property->object); |
979 | g_assert (object != NULL)do { if (object != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkbuilder.c", 979, ((const char*) (__func__)), "object != NULL" ); } while (0); |
980 | |
981 | obj = _ctk_builder_lookup_object (builder, property->value, property->line, property->col); |
982 | if (obj) |
983 | g_object_set (object, property->pspec->name, obj, NULL((void*)0)); |
984 | |
985 | g_free (property->value); |
986 | g_free (property->object); |
987 | g_slice_free (DelayedProperty, property)do { if (1) g_slice_free1 (sizeof (DelayedProperty), (property )); else (void) ((DelayedProperty*) 0 == (property)); } while (0); |
988 | } |
989 | g_slist_free (props); |
990 | } |
991 | |
992 | static inline void |
993 | free_binding_info (gpointer data, |
994 | gpointer user G_GNUC_UNUSED__attribute__ ((__unused__))) |
995 | { |
996 | BindingInfo *info = data; |
997 | |
998 | g_free (info->source); |
999 | g_free (info->source_property); |
1000 | g_slice_free (BindingInfo, data)do { if (1) g_slice_free1 (sizeof (BindingInfo), (data)); else (void) ((BindingInfo*) 0 == (data)); } while (0); |
1001 | } |
1002 | |
1003 | static inline void |
1004 | ctk_builder_create_bindings (CtkBuilder *builder) |
1005 | { |
1006 | GSList *l; |
1007 | |
1008 | for (l = builder->priv->bindings; l; l = l->next) |
1009 | { |
1010 | BindingInfo *info = l->data; |
1011 | GObject *source; |
1012 | |
1013 | source = _ctk_builder_lookup_object (builder, info->source, info->line, info->col); |
1014 | if (source) |
1015 | g_object_bind_property (source, info->source_property, |
1016 | info->target, info->target_pspec->name, |
1017 | info->flags); |
1018 | |
1019 | free_binding_info (info, NULL((void*)0)); |
1020 | } |
1021 | |
1022 | g_slist_free (builder->priv->bindings); |
1023 | builder->priv->bindings = NULL((void*)0); |
1024 | } |
1025 | |
1026 | void |
1027 | _ctk_builder_finish (CtkBuilder *builder) |
1028 | { |
1029 | ctk_builder_apply_delayed_properties (builder); |
1030 | ctk_builder_create_bindings (builder); |
1031 | } |
1032 | |
1033 | /** |
1034 | * ctk_builder_new: |
1035 | * |
1036 | * Creates a new empty builder object. |
1037 | * |
1038 | * This function is only useful if you intend to make multiple calls |
1039 | * to ctk_builder_add_from_file(), ctk_builder_add_from_resource() |
1040 | * or ctk_builder_add_from_string() in order to merge multiple UI |
1041 | * descriptions into a single builder. |
1042 | * |
1043 | * Most users will probably want to use ctk_builder_new_from_file(), |
1044 | * ctk_builder_new_from_resource() or ctk_builder_new_from_string(). |
1045 | * |
1046 | * Returns: a new (empty) #CtkBuilder object |
1047 | * |
1048 | * Since: 2.12 |
1049 | **/ |
1050 | CtkBuilder * |
1051 | ctk_builder_new (void) |
1052 | { |
1053 | return g_object_new (CTK_TYPE_BUILDER(ctk_builder_get_type ()), NULL((void*)0)); |
1054 | } |
1055 | |
1056 | /** |
1057 | * ctk_builder_add_from_file: |
1058 | * @builder: a #CtkBuilder |
1059 | * @filename: the name of the file to parse |
1060 | * @error: (allow-none): return location for an error, or %NULL |
1061 | * |
1062 | * Parses a file containing a [CtkBuilder UI definition][BUILDER-UI] |
1063 | * and merges it with the current contents of @builder. |
1064 | * |
1065 | * Most users will probably want to use ctk_builder_new_from_file(). |
1066 | * |
1067 | * If an error occurs, 0 will be returned and @error will be assigned a |
1068 | * #GError from the #CTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR |
1069 | * domain. |
1070 | * |
1071 | * It’s not really reasonable to attempt to handle failures of this |
1072 | * call. You should not use this function with untrusted files (ie: |
1073 | * files that are not part of your application). Broken #CtkBuilder |
1074 | * files can easily crash your program, and it’s possible that memory |
1075 | * was leaked leading up to the reported failure. The only reasonable |
1076 | * thing to do when an error is detected is to call g_error(). |
1077 | * |
1078 | * Returns: A positive value on success, 0 if an error occurred |
1079 | * |
1080 | * Since: 2.12 |
1081 | **/ |
1082 | guint |
1083 | ctk_builder_add_from_file (CtkBuilder *builder, |
1084 | const gchar *filename, |
1085 | GError **error) |
1086 | { |
1087 | gchar *buffer; |
1088 | gsize length; |
1089 | GError *tmp_error; |
1090 | |
1091 | g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (0); } } while (0); |
1092 | g_return_val_if_fail (filename != NULL, 0)do { if ((filename != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "filename != NULL"); return (0); } } while (0); |
1093 | g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return (0); } } while ( 0); |
1094 | |
1095 | tmp_error = NULL((void*)0); |
1096 | |
1097 | if (!g_file_get_contents (filename, &buffer, &length, &tmp_error)) |
1098 | { |
1099 | g_propagate_error (error, tmp_error); |
1100 | return 0; |
1101 | } |
1102 | |
1103 | g_free (builder->priv->filename); |
1104 | g_free (builder->priv->resource_prefix); |
1105 | builder->priv->filename = g_strdup (filename)g_strdup_inline (filename); |
1106 | builder->priv->resource_prefix = NULL((void*)0); |
1107 | |
1108 | _ctk_builder_parser_parse_buffer (builder, filename, |
1109 | buffer, length, |
1110 | NULL((void*)0), |
1111 | &tmp_error); |
1112 | |
1113 | g_free (buffer); |
1114 | |
1115 | if (tmp_error != NULL((void*)0)) |
1116 | { |
1117 | g_propagate_error (error, tmp_error); |
1118 | return 0; |
1119 | } |
1120 | |
1121 | return 1; |
1122 | } |
1123 | |
1124 | /** |
1125 | * ctk_builder_add_objects_from_file: |
1126 | * @builder: a #CtkBuilder |
1127 | * @filename: the name of the file to parse |
1128 | * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build |
1129 | * @error: (allow-none): return location for an error, or %NULL |
1130 | * |
1131 | * Parses a file containing a [CtkBuilder UI definition][BUILDER-UI] |
1132 | * building only the requested objects and merges |
1133 | * them with the current contents of @builder. |
1134 | * |
1135 | * Upon errors 0 will be returned and @error will be assigned a |
1136 | * #GError from the #CTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR |
1137 | * domain. |
1138 | * |
1139 | * If you are adding an object that depends on an object that is not |
1140 | * its child (for instance a #CtkTreeView that depends on its |
1141 | * #CtkTreeModel), you have to explicitly list all of them in @object_ids. |
1142 | * |
1143 | * Returns: A positive value on success, 0 if an error occurred |
1144 | * |
1145 | * Since: 2.14 |
1146 | **/ |
1147 | guint |
1148 | ctk_builder_add_objects_from_file (CtkBuilder *builder, |
1149 | const gchar *filename, |
1150 | gchar **object_ids, |
1151 | GError **error) |
1152 | { |
1153 | gchar *buffer; |
1154 | gsize length; |
1155 | GError *tmp_error; |
1156 | |
1157 | g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (0); } } while (0); |
1158 | g_return_val_if_fail (filename != NULL, 0)do { if ((filename != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "filename != NULL"); return (0); } } while (0); |
1159 | g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0)do { if ((object_ids != ((void*)0) && object_ids[0] != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "object_ids != NULL && object_ids[0] != NULL" ); return (0); } } while (0); |
1160 | g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return (0); } } while ( 0); |
1161 | |
1162 | tmp_error = NULL((void*)0); |
1163 | |
1164 | if (!g_file_get_contents (filename, &buffer, &length, &tmp_error)) |
1165 | { |
1166 | g_propagate_error (error, tmp_error); |
1167 | return 0; |
1168 | } |
1169 | |
1170 | g_free (builder->priv->filename); |
1171 | g_free (builder->priv->resource_prefix); |
1172 | builder->priv->filename = g_strdup (filename)g_strdup_inline (filename); |
1173 | builder->priv->resource_prefix = NULL((void*)0); |
1174 | |
1175 | _ctk_builder_parser_parse_buffer (builder, filename, |
1176 | buffer, length, |
1177 | object_ids, |
1178 | &tmp_error); |
1179 | |
1180 | g_free (buffer); |
1181 | |
1182 | if (tmp_error != NULL((void*)0)) |
1183 | { |
1184 | g_propagate_error (error, tmp_error); |
1185 | return 0; |
1186 | } |
1187 | |
1188 | return 1; |
1189 | } |
1190 | |
1191 | |
1192 | /** |
1193 | * ctk_builder_extend_with_template: |
1194 | * @builder: a #CtkBuilder |
1195 | * @widget: the widget that is being extended |
1196 | * @template_type: the type that the template is for |
1197 | * @buffer: the string to parse |
1198 | * @length: the length of @buffer (may be -1 if @buffer is nul-terminated) |
1199 | * @error: (allow-none): return location for an error, or %NULL |
1200 | * |
1201 | * Main private entry point for building composite container |
1202 | * components from template XML. |
1203 | * |
1204 | * This is exported purely to let ctk-builder-tool validate |
1205 | * templates, applications have no need to call this function. |
1206 | * |
1207 | * Returns: A positive value on success, 0 if an error occurred |
1208 | */ |
1209 | guint |
1210 | ctk_builder_extend_with_template (CtkBuilder *builder, |
1211 | CtkWidget *widget, |
1212 | GType template_type, |
1213 | const gchar *buffer, |
1214 | gsize length, |
1215 | GError **error) |
1216 | { |
1217 | GError *tmp_error; |
1218 | |
1219 | g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (0); } } while (0); |
1220 | g_return_val_if_fail (CTK_IS_WIDGET (widget), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((widget)); GType __t = ((ctk_widget_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_WIDGET (widget)"); return (0); } } while (0); |
1221 | g_return_val_if_fail (g_type_name (template_type) != NULL, 0)do { if ((g_type_name (template_type) != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "g_type_name (template_type) != NULL"); return (0); } } while (0); |
1222 | g_return_val_if_fail (g_type_is_a (G_OBJECT_TYPE (widget), template_type), 0)do { if (((((((((GTypeClass*) (((GTypeInstance*) (widget))-> g_class))->g_type)))) == (template_type) || (g_type_is_a) ( ((((((GTypeClass*) (((GTypeInstance*) (widget))->g_class)) ->g_type)))), (template_type))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "g_type_is_a (G_OBJECT_TYPE (widget), template_type)" ); return (0); } } while (0); |
1223 | g_return_val_if_fail (buffer && buffer[0], 0)do { if ((buffer && buffer[0])) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "buffer && buffer[0]" ); return (0); } } while (0); |
1224 | |
1225 | tmp_error = NULL((void*)0); |
1226 | |
1227 | g_free (builder->priv->filename); |
1228 | g_free (builder->priv->resource_prefix); |
1229 | builder->priv->filename = g_strdup (".")g_strdup_inline ("."); |
1230 | builder->priv->resource_prefix = NULL((void*)0); |
1231 | builder->priv->template_type = template_type; |
1232 | |
1233 | ctk_builder_expose_object (builder, g_type_name (template_type), G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), (((GType) ((20) << (2))))))))); |
1234 | _ctk_builder_parser_parse_buffer (builder, "<input>", |
1235 | buffer, length, |
1236 | NULL((void*)0), |
1237 | &tmp_error); |
1238 | |
1239 | if (tmp_error != NULL((void*)0)) |
1240 | { |
1241 | g_propagate_error (error, tmp_error); |
1242 | return 0; |
1243 | } |
1244 | |
1245 | return 1; |
1246 | } |
1247 | |
1248 | /** |
1249 | * ctk_builder_add_from_resource: |
1250 | * @builder: a #CtkBuilder |
1251 | * @resource_path: the path of the resource file to parse |
1252 | * @error: (allow-none): return location for an error, or %NULL |
1253 | * |
1254 | * Parses a resource file containing a [CtkBuilder UI definition][BUILDER-UI] |
1255 | * and merges it with the current contents of @builder. |
1256 | * |
1257 | * Most users will probably want to use ctk_builder_new_from_resource(). |
1258 | * |
1259 | * If an error occurs, 0 will be returned and @error will be assigned a |
1260 | * #GError from the #CTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR |
1261 | * domain. |
1262 | * |
1263 | * It’s not really reasonable to attempt to handle failures of this |
1264 | * call. The only reasonable thing to do when an error is detected is |
1265 | * to call g_error(). |
1266 | * |
1267 | * Returns: A positive value on success, 0 if an error occurred |
1268 | * |
1269 | * Since: 3.4 |
1270 | **/ |
1271 | guint |
1272 | ctk_builder_add_from_resource (CtkBuilder *builder, |
1273 | const gchar *resource_path, |
1274 | GError **error) |
1275 | { |
1276 | GError *tmp_error; |
1277 | GBytes *data; |
1278 | char *filename_for_errors; |
1279 | char *slash; |
1280 | |
1281 | g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (0); } } while (0); |
1282 | g_return_val_if_fail (resource_path != NULL, 0)do { if ((resource_path != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "resource_path != NULL") ; return (0); } } while (0); |
1283 | g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return (0); } } while ( 0); |
1284 | |
1285 | tmp_error = NULL((void*)0); |
1286 | |
1287 | data = g_resources_lookup_data (resource_path, 0, &tmp_error); |
1288 | if (data == NULL((void*)0)) |
1289 | { |
1290 | g_propagate_error (error, tmp_error); |
1291 | return 0; |
1292 | } |
1293 | |
1294 | g_free (builder->priv->filename); |
1295 | g_free (builder->priv->resource_prefix); |
1296 | builder->priv->filename = g_strdup (".")g_strdup_inline ("."); |
1297 | |
1298 | slash = strrchr (resource_path, '/'); |
1299 | if (slash != NULL((void*)0)) |
1300 | builder->priv->resource_prefix = |
1301 | g_strndup (resource_path, slash - resource_path + 1); |
1302 | else |
1303 | builder->priv->resource_prefix = |
1304 | g_strdup ("/")g_strdup_inline ("/"); |
1305 | |
1306 | filename_for_errors = g_strconcat ("<resource>", resource_path, NULL((void*)0)); |
1307 | |
1308 | _ctk_builder_parser_parse_buffer (builder, filename_for_errors, |
1309 | g_bytes_get_data (data, NULL((void*)0)), g_bytes_get_size (data), |
1310 | NULL((void*)0), |
1311 | &tmp_error); |
1312 | |
1313 | g_free (filename_for_errors); |
1314 | g_bytes_unref (data); |
1315 | |
1316 | if (tmp_error != NULL((void*)0)) |
1317 | { |
1318 | g_propagate_error (error, tmp_error); |
1319 | return 0; |
1320 | } |
1321 | |
1322 | return 1; |
1323 | } |
1324 | |
1325 | /** |
1326 | * ctk_builder_add_objects_from_resource: |
1327 | * @builder: a #CtkBuilder |
1328 | * @resource_path: the path of the resource file to parse |
1329 | * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build |
1330 | * @error: (allow-none): return location for an error, or %NULL |
1331 | * |
1332 | * Parses a resource file containing a [CtkBuilder UI definition][BUILDER-UI] |
1333 | * building only the requested objects and merges |
1334 | * them with the current contents of @builder. |
1335 | * |
1336 | * Upon errors 0 will be returned and @error will be assigned a |
1337 | * #GError from the #CTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR |
1338 | * domain. |
1339 | * |
1340 | * If you are adding an object that depends on an object that is not |
1341 | * its child (for instance a #CtkTreeView that depends on its |
1342 | * #CtkTreeModel), you have to explicitly list all of them in @object_ids. |
1343 | * |
1344 | * Returns: A positive value on success, 0 if an error occurred |
1345 | * |
1346 | * Since: 3.4 |
1347 | **/ |
1348 | guint |
1349 | ctk_builder_add_objects_from_resource (CtkBuilder *builder, |
1350 | const gchar *resource_path, |
1351 | gchar **object_ids, |
1352 | GError **error) |
1353 | { |
1354 | GError *tmp_error; |
1355 | GBytes *data; |
1356 | char *filename_for_errors; |
1357 | char *slash; |
1358 | |
1359 | g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (0); } } while (0); |
1360 | g_return_val_if_fail (resource_path != NULL, 0)do { if ((resource_path != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "resource_path != NULL") ; return (0); } } while (0); |
1361 | g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0)do { if ((object_ids != ((void*)0) && object_ids[0] != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "object_ids != NULL && object_ids[0] != NULL" ); return (0); } } while (0); |
1362 | g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return (0); } } while ( 0); |
1363 | |
1364 | tmp_error = NULL((void*)0); |
1365 | |
1366 | data = g_resources_lookup_data (resource_path, 0, &tmp_error); |
1367 | if (data == NULL((void*)0)) |
1368 | { |
1369 | g_propagate_error (error, tmp_error); |
1370 | return 0; |
1371 | } |
1372 | |
1373 | g_free (builder->priv->filename); |
1374 | g_free (builder->priv->resource_prefix); |
1375 | builder->priv->filename = g_strdup (".")g_strdup_inline ("."); |
1376 | |
1377 | slash = strrchr (resource_path, '/'); |
1378 | if (slash != NULL((void*)0)) |
1379 | builder->priv->resource_prefix = |
1380 | g_strndup (resource_path, slash - resource_path + 1); |
1381 | else |
1382 | builder->priv->resource_prefix = |
1383 | g_strdup ("/")g_strdup_inline ("/"); |
1384 | |
1385 | filename_for_errors = g_strconcat ("<resource>", resource_path, NULL((void*)0)); |
1386 | |
1387 | _ctk_builder_parser_parse_buffer (builder, filename_for_errors, |
1388 | g_bytes_get_data (data, NULL((void*)0)), g_bytes_get_size (data), |
1389 | object_ids, |
1390 | &tmp_error); |
1391 | g_free (filename_for_errors); |
1392 | g_bytes_unref (data); |
1393 | |
1394 | if (tmp_error != NULL((void*)0)) |
1395 | { |
1396 | g_propagate_error (error, tmp_error); |
1397 | return 0; |
1398 | } |
1399 | |
1400 | return 1; |
1401 | } |
1402 | |
1403 | /** |
1404 | * ctk_builder_add_from_string: |
1405 | * @builder: a #CtkBuilder |
1406 | * @buffer: the string to parse |
1407 | * @length: the length of @buffer (may be -1 if @buffer is nul-terminated) |
1408 | * @error: (allow-none): return location for an error, or %NULL |
1409 | * |
1410 | * Parses a string containing a [CtkBuilder UI definition][BUILDER-UI] |
1411 | * and merges it with the current contents of @builder. |
1412 | * |
1413 | * Most users will probably want to use ctk_builder_new_from_string(). |
1414 | * |
1415 | * Upon errors 0 will be returned and @error will be assigned a |
1416 | * #GError from the #CTK_BUILDER_ERROR, #G_MARKUP_ERROR or |
1417 | * #G_VARIANT_PARSE_ERROR domain. |
1418 | * |
1419 | * It’s not really reasonable to attempt to handle failures of this |
1420 | * call. The only reasonable thing to do when an error is detected is |
1421 | * to call g_error(). |
1422 | * |
1423 | * Returns: A positive value on success, 0 if an error occurred |
1424 | * |
1425 | * Since: 2.12 |
1426 | **/ |
1427 | guint |
1428 | ctk_builder_add_from_string (CtkBuilder *builder, |
1429 | const gchar *buffer, |
1430 | gsize length, |
1431 | GError **error) |
1432 | { |
1433 | GError *tmp_error; |
1434 | |
1435 | g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (0); } } while (0); |
1436 | g_return_val_if_fail (buffer != NULL, 0)do { if ((buffer != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "buffer != NULL"); return (0); } } while (0); |
1437 | g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return (0); } } while ( 0); |
1438 | |
1439 | tmp_error = NULL((void*)0); |
1440 | |
1441 | g_free (builder->priv->filename); |
1442 | g_free (builder->priv->resource_prefix); |
1443 | builder->priv->filename = g_strdup (".")g_strdup_inline ("."); |
1444 | builder->priv->resource_prefix = NULL((void*)0); |
1445 | |
1446 | _ctk_builder_parser_parse_buffer (builder, "<input>", |
1447 | buffer, length, |
1448 | NULL((void*)0), |
1449 | &tmp_error); |
1450 | if (tmp_error != NULL((void*)0)) |
1451 | { |
1452 | g_propagate_error (error, tmp_error); |
1453 | return 0; |
1454 | } |
1455 | |
1456 | return 1; |
1457 | } |
1458 | |
1459 | /** |
1460 | * ctk_builder_add_objects_from_string: |
1461 | * @builder: a #CtkBuilder |
1462 | * @buffer: the string to parse |
1463 | * @length: the length of @buffer (may be -1 if @buffer is nul-terminated) |
1464 | * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build |
1465 | * @error: (allow-none): return location for an error, or %NULL |
1466 | * |
1467 | * Parses a string containing a [CtkBuilder UI definition][BUILDER-UI] |
1468 | * building only the requested objects and merges |
1469 | * them with the current contents of @builder. |
1470 | * |
1471 | * Upon errors 0 will be returned and @error will be assigned a |
1472 | * #GError from the #CTK_BUILDER_ERROR or #G_MARKUP_ERROR domain. |
1473 | * |
1474 | * If you are adding an object that depends on an object that is not |
1475 | * its child (for instance a #CtkTreeView that depends on its |
1476 | * #CtkTreeModel), you have to explicitly list all of them in @object_ids. |
1477 | * |
1478 | * Returns: A positive value on success, 0 if an error occurred |
1479 | * |
1480 | * Since: 2.14 |
1481 | **/ |
1482 | guint |
1483 | ctk_builder_add_objects_from_string (CtkBuilder *builder, |
1484 | const gchar *buffer, |
1485 | gsize length, |
1486 | gchar **object_ids, |
1487 | GError **error) |
1488 | { |
1489 | GError *tmp_error; |
1490 | |
1491 | g_return_val_if_fail (CTK_IS_BUILDER (builder), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (0); } } while (0); |
1492 | g_return_val_if_fail (buffer != NULL, 0)do { if ((buffer != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "buffer != NULL"); return (0); } } while (0); |
1493 | g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0)do { if ((object_ids != ((void*)0) && object_ids[0] != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "object_ids != NULL && object_ids[0] != NULL" ); return (0); } } while (0); |
1494 | g_return_val_if_fail (error == NULL || *error == NULL, 0)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return (0); } } while ( 0); |
1495 | |
1496 | tmp_error = NULL((void*)0); |
1497 | |
1498 | g_free (builder->priv->filename); |
1499 | g_free (builder->priv->resource_prefix); |
1500 | builder->priv->filename = g_strdup (".")g_strdup_inline ("."); |
1501 | builder->priv->resource_prefix = NULL((void*)0); |
1502 | |
1503 | _ctk_builder_parser_parse_buffer (builder, "<input>", |
1504 | buffer, length, |
1505 | object_ids, |
1506 | &tmp_error); |
1507 | |
1508 | if (tmp_error != NULL((void*)0)) |
1509 | { |
1510 | g_propagate_error (error, tmp_error); |
1511 | return 0; |
1512 | } |
1513 | |
1514 | return 1; |
1515 | } |
1516 | |
1517 | /** |
1518 | * ctk_builder_get_object: |
1519 | * @builder: a #CtkBuilder |
1520 | * @name: name of object to get |
1521 | * |
1522 | * Gets the object named @name. Note that this function does not |
1523 | * increment the reference count of the returned object. |
1524 | * |
1525 | * Returns: (nullable) (transfer none): the object named @name or %NULL if |
1526 | * it could not be found in the object tree. |
1527 | * |
1528 | * Since: 2.12 |
1529 | **/ |
1530 | GObject * |
1531 | ctk_builder_get_object (CtkBuilder *builder, |
1532 | const gchar *name) |
1533 | { |
1534 | g_return_val_if_fail (CTK_IS_BUILDER (builder), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (((void*)0)); } } while (0); |
1535 | g_return_val_if_fail (name != NULL, NULL)do { if ((name != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "name != NULL"); return ( ((void*)0)); } } while (0); |
1536 | |
1537 | return g_hash_table_lookup (builder->priv->objects, name); |
1538 | } |
1539 | |
1540 | /** |
1541 | * ctk_builder_get_objects: |
1542 | * @builder: a #CtkBuilder |
1543 | * |
1544 | * Gets all objects that have been constructed by @builder. Note that |
1545 | * this function does not increment the reference counts of the returned |
1546 | * objects. |
1547 | * |
1548 | * Returns: (element-type GObject) (transfer container): a newly-allocated #GSList containing all the objects |
1549 | * constructed by the #CtkBuilder instance. It should be freed by |
1550 | * g_slist_free() |
1551 | * |
1552 | * Since: 2.12 |
1553 | **/ |
1554 | GSList * |
1555 | ctk_builder_get_objects (CtkBuilder *builder) |
1556 | { |
1557 | GSList *objects = NULL((void*)0); |
1558 | GObject *object; |
1559 | GHashTableIter iter; |
1560 | |
1561 | g_return_val_if_fail (CTK_IS_BUILDER (builder), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (((void*)0)); } } while (0); |
1562 | |
1563 | g_hash_table_iter_init (&iter, builder->priv->objects); |
1564 | while (g_hash_table_iter_next (&iter, NULL((void*)0), (gpointer *)&object)) |
1565 | objects = g_slist_prepend (objects, object); |
1566 | |
1567 | return g_slist_reverse (objects); |
1568 | } |
1569 | |
1570 | /** |
1571 | * ctk_builder_set_translation_domain: |
1572 | * @builder: a #CtkBuilder |
1573 | * @domain: (allow-none): the translation domain or %NULL |
1574 | * |
1575 | * Sets the translation domain of @builder. |
1576 | * See #CtkBuilder:translation-domain. |
1577 | * |
1578 | * Since: 2.12 |
1579 | **/ |
1580 | void |
1581 | ctk_builder_set_translation_domain (CtkBuilder *builder, |
1582 | const gchar *domain) |
1583 | { |
1584 | gchar *new_domain; |
1585 | |
1586 | g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return; } } while (0); |
1587 | |
1588 | new_domain = g_strdup (domain)g_strdup_inline (domain); |
1589 | g_free (builder->priv->domain); |
1590 | builder->priv->domain = new_domain; |
1591 | |
1592 | g_object_notify_by_pspec (G_OBJECT (builder)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((builder)), (((GType) ((20) << (2)))))))), builder_props[PROP_TRANSLATION_DOMAIN]); |
1593 | } |
1594 | |
1595 | /** |
1596 | * ctk_builder_get_translation_domain: |
1597 | * @builder: a #CtkBuilder |
1598 | * |
1599 | * Gets the translation domain of @builder. |
1600 | * |
1601 | * Returns: the translation domain. This string is owned |
1602 | * by the builder object and must not be modified or freed. |
1603 | * |
1604 | * Since: 2.12 |
1605 | **/ |
1606 | const gchar * |
1607 | ctk_builder_get_translation_domain (CtkBuilder *builder) |
1608 | { |
1609 | g_return_val_if_fail (CTK_IS_BUILDER (builder), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (((void*)0)); } } while (0); |
1610 | |
1611 | return builder->priv->domain; |
1612 | } |
1613 | |
1614 | /** |
1615 | * ctk_builder_expose_object: |
1616 | * @builder: a #CtkBuilder |
1617 | * @name: the name of the object exposed to the builder |
1618 | * @object: the object to expose |
1619 | * |
1620 | * Add @object to the @builder object pool so it can be referenced just like any |
1621 | * other object built by builder. |
1622 | * |
1623 | * Since: 3.8 |
1624 | **/ |
1625 | void |
1626 | ctk_builder_expose_object (CtkBuilder *builder, |
1627 | const gchar *name, |
1628 | GObject *object) |
1629 | { |
1630 | g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return; } } while (0); |
1631 | g_return_if_fail (name && name[0])do { if ((name && name[0])) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "name && name[0]" ); return; } } while (0); |
1632 | g_return_if_fail (!g_hash_table_contains (builder->priv->objects, name))do { if ((!g_hash_table_contains (builder->priv->objects , name))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "!g_hash_table_contains (builder->priv->objects, name)" ); return; } } while (0); |
1633 | |
1634 | object_set_name (object, name); |
1635 | g_hash_table_insert (builder->priv->objects, |
1636 | g_strdup (name)g_strdup_inline (name), |
1637 | g_object_ref (object)((__typeof__ (object)) (g_object_ref) (object))); |
1638 | } |
1639 | |
1640 | |
1641 | typedef struct { |
1642 | GModule *module; |
1643 | gpointer data; |
1644 | } ConnectArgs; |
1645 | |
1646 | static void |
1647 | ctk_builder_connect_signals_default (CtkBuilder *builder, |
1648 | GObject *object, |
1649 | const gchar *signal_name, |
1650 | const gchar *handler_name, |
1651 | GObject *connect_object, |
1652 | GConnectFlags flags, |
1653 | gpointer user_data) |
1654 | { |
1655 | GCallback func; |
1656 | ConnectArgs *args = (ConnectArgs*) user_data; |
1657 | |
1658 | func = ctk_builder_lookup_callback_symbol (builder, handler_name); |
1659 | |
1660 | if (!func) |
1661 | { |
1662 | /* Only error out for missing GModule support if we've not |
1663 | * found the symbols explicitly added with ctk_builder_add_callback_symbol() |
1664 | */ |
1665 | if (args->module == NULL((void*)0)) |
1666 | g_error ("ctk_builder_connect_signals() requires working GModule"); |
1667 | |
1668 | if (!g_module_symbol (args->module, handler_name, (gpointer)&func)) |
1669 | { |
1670 | g_warning ("Could not find signal handler '%s'. Did you compile with -rdynamic?", handler_name); |
1671 | return; |
1672 | } |
1673 | } |
1674 | |
1675 | if (connect_object) |
1676 | g_signal_connect_object (object, signal_name, func, connect_object, flags); |
1677 | else |
1678 | g_signal_connect_data (object, signal_name, func, args->data, NULL((void*)0), flags); |
1679 | } |
1680 | |
1681 | |
1682 | /** |
1683 | * ctk_builder_connect_signals: |
1684 | * @builder: a #CtkBuilder |
1685 | * @user_data: user data to pass back with all signals |
1686 | * |
1687 | * This method is a simpler variation of ctk_builder_connect_signals_full(). |
1688 | * It uses symbols explicitly added to @builder with prior calls to |
1689 | * ctk_builder_add_callback_symbol(). In the case that symbols are not |
1690 | * explicitly added; it uses #GModule’s introspective features (by opening the module %NULL) |
1691 | * to look at the application’s symbol table. From here it tries to match |
1692 | * the signal handler names given in the interface description with |
1693 | * symbols in the application and connects the signals. Note that this |
1694 | * function can only be called once, subsequent calls will do nothing. |
1695 | * |
1696 | * Note that unless ctk_builder_add_callback_symbol() is called for |
1697 | * all signal callbacks which are referenced by the loaded XML, this |
1698 | * function will require that #GModule be supported on the platform. |
1699 | * |
1700 | * If you rely on #GModule support to lookup callbacks in the symbol table, |
1701 | * the following details should be noted: |
1702 | * |
1703 | * When compiling applications for Windows, you must declare signal callbacks |
1704 | * with #G_MODULE_EXPORT, or they will not be put in the symbol table. |
1705 | * On Linux and Unices, this is not necessary; applications should instead |
1706 | * be compiled with the -Wl,--export-dynamic CFLAGS, and linked against |
1707 | * gmodule-export-2.0. |
1708 | * |
1709 | * Since: 2.12 |
1710 | **/ |
1711 | void |
1712 | ctk_builder_connect_signals (CtkBuilder *builder, |
1713 | gpointer user_data) |
1714 | { |
1715 | ConnectArgs args; |
1716 | |
1717 | g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return; } } while (0); |
1718 | |
1719 | args.data = user_data; |
1720 | |
1721 | if (g_module_supported ()) |
1722 | args.module = g_module_open (NULL((void*)0), G_MODULE_BIND_LAZY); |
1723 | else |
1724 | args.module = NULL((void*)0); |
1725 | |
1726 | ctk_builder_connect_signals_full (builder, |
1727 | ctk_builder_connect_signals_default, |
1728 | &args); |
1729 | if (args.module) |
1730 | g_module_close (args.module); |
1731 | } |
1732 | |
1733 | /** |
1734 | * CtkBuilderConnectFunc: |
1735 | * @builder: a #CtkBuilder |
1736 | * @object: object to connect a signal to |
1737 | * @signal_name: name of the signal |
1738 | * @handler_name: name of the handler |
1739 | * @connect_object: (nullable): a #GObject, if non-%NULL, use g_signal_connect_object() |
1740 | * @flags: #GConnectFlags to use |
1741 | * @user_data: user data |
1742 | * |
1743 | * This is the signature of a function used to connect signals. It is used |
1744 | * by the ctk_builder_connect_signals() and ctk_builder_connect_signals_full() |
1745 | * methods. It is mainly intended for interpreted language bindings, but |
1746 | * could be useful where the programmer wants more control over the signal |
1747 | * connection process. Note that this function can only be called once, |
1748 | * subsequent calls will do nothing. |
1749 | * |
1750 | * Since: 2.12 |
1751 | */ |
1752 | |
1753 | /** |
1754 | * ctk_builder_connect_signals_full: |
1755 | * @builder: a #CtkBuilder |
1756 | * @func: (scope call): the function used to connect the signals |
1757 | * @user_data: arbitrary data that will be passed to the connection function |
1758 | * |
1759 | * This function can be thought of the interpreted language binding |
1760 | * version of ctk_builder_connect_signals(), except that it does not |
1761 | * require GModule to function correctly. |
1762 | * |
1763 | * Since: 2.12 |
1764 | */ |
1765 | void |
1766 | ctk_builder_connect_signals_full (CtkBuilder *builder, |
1767 | CtkBuilderConnectFunc func, |
1768 | gpointer user_data) |
1769 | { |
1770 | GSList *l; |
1771 | GObject *object; |
1772 | GObject *connect_object; |
1773 | GString *detailed_id = NULL((void*)0); |
1774 | |
1775 | g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return; } } while (0); |
1776 | g_return_if_fail (func != NULL)do { if ((func != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "func != NULL"); return; } } while (0); |
1777 | |
1778 | if (!builder->priv->signals) |
1779 | return; |
1780 | |
1781 | builder->priv->signals = g_slist_reverse (builder->priv->signals); |
1782 | for (l = builder->priv->signals; l; l = l->next) |
1783 | { |
1784 | SignalInfo *signal = (SignalInfo*)l->data; |
1785 | const gchar *signal_name; |
1786 | |
1787 | g_assert (signal != NULL)do { if (signal != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkbuilder.c", 1787, ((const char*) (__func__)), "signal != NULL" ); } while (0); |
1788 | g_assert (signal->id != 0)do { if (signal->id != 0) ; else g_assertion_message_expr ( "Ctk", "ctkbuilder.c", 1788, ((const char*) (__func__)), "signal->id != 0" ); } while (0); |
1789 | |
1790 | signal_name = g_signal_name (signal->id); |
1791 | |
1792 | object = g_hash_table_lookup (builder->priv->objects, |
1793 | signal->object_name); |
1794 | g_assert (object != NULL)do { if (object != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkbuilder.c", 1794, ((const char*) (__func__)), "object != NULL" ); } while (0); |
1795 | |
1796 | connect_object = NULL((void*)0); |
1797 | |
1798 | if (signal->connect_object_name) |
1799 | { |
1800 | connect_object = g_hash_table_lookup (builder->priv->objects, |
1801 | signal->connect_object_name); |
1802 | if (!connect_object) |
1803 | g_warning ("Could not lookup object %s on signal %s of object %s", |
1804 | signal->connect_object_name, signal_name, |
1805 | signal->object_name); |
1806 | } |
1807 | |
1808 | if (signal->detail) |
1809 | { |
1810 | if (detailed_id == NULL((void*)0)) |
1811 | detailed_id = g_string_new (""); |
1812 | |
1813 | g_string_printf (detailed_id, "%s::%s", signal_name, |
1814 | g_quark_to_string (signal->detail)); |
1815 | signal_name = detailed_id->str; |
1816 | } |
1817 | |
1818 | func (builder, object, signal_name, signal->handler, |
1819 | connect_object, signal->flags, user_data); |
1820 | } |
1821 | |
1822 | g_slist_free_full (builder->priv->signals, (GDestroyNotify)_free_signal_info); |
1823 | builder->priv->signals = NULL((void*)0); |
1824 | |
1825 | if (detailed_id) |
1826 | g_string_free (detailed_id, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (detailed_id), ((!(0)))) : g_string_free_and_steal (detailed_id )) : (g_string_free) ((detailed_id), ((!(0))))); |
1827 | } |
1828 | |
1829 | /** |
1830 | * ctk_builder_value_from_string: |
1831 | * @builder: a #CtkBuilder |
1832 | * @pspec: the #GParamSpec for the property |
1833 | * @string: the string representation of the value |
1834 | * @value: (out): the #GValue to store the result in |
1835 | * @error: (allow-none): return location for an error, or %NULL |
1836 | * |
1837 | * This function demarshals a value from a string. This function |
1838 | * calls g_value_init() on the @value argument, so it need not be |
1839 | * initialised beforehand. |
1840 | * |
1841 | * This function can handle char, uchar, boolean, int, uint, long, |
1842 | * ulong, enum, flags, float, double, string, #CdkColor, #CdkRGBA and |
1843 | * #CtkAdjustment type values. Support for #CtkWidget type values is |
1844 | * still to come. |
1845 | * |
1846 | * Upon errors %FALSE will be returned and @error will be assigned a |
1847 | * #GError from the #CTK_BUILDER_ERROR domain. |
1848 | * |
1849 | * Returns: %TRUE on success |
1850 | * |
1851 | * Since: 2.12 |
1852 | */ |
1853 | gboolean |
1854 | ctk_builder_value_from_string (CtkBuilder *builder, |
1855 | GParamSpec *pspec, |
1856 | const gchar *string, |
1857 | GValue *value, |
1858 | GError **error) |
1859 | { |
1860 | g_return_val_if_fail (CTK_IS_BUILDER (builder), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return ((0)); } } while (0); |
1861 | g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE)do { if (((((g_type_check_instance_is_fundamentally_a ((GTypeInstance *) ((pspec)), (((GType) ((19) << (2)))))))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "G_IS_PARAM_SPEC (pspec)"); return ((0)); } } while (0); |
1862 | g_return_val_if_fail (string != NULL, FALSE)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "string != NULL"); return ((0)); } } while (0); |
1863 | g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "value != NULL"); return ((0)); } } while (0); |
1864 | g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return ((0)); } } while (0); |
1865 | |
1866 | /* |
1867 | * GParamSpecUnichar has the internal type G_TYPE_UINT, |
1868 | * so we cannot handle this in the switch, do it separately |
1869 | */ |
1870 | if (G_IS_PARAM_SPEC_UNICHAR (pspec)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (pspec)); GType __t = ((g_param_spec_types[9])); gboolean __r ; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
1871 | { |
1872 | gunichar c; |
1873 | g_value_init (value, G_TYPE_UINT((GType) ((7) << (2)))); |
1874 | c = g_utf8_get_char_validated (string, strlen (string)); |
1875 | if (c != 0 && c != (gunichar)-1 && c != (gunichar)-2) |
1876 | g_value_set_uint (value, c); |
1877 | return TRUE(!(0)); |
1878 | } |
1879 | |
1880 | /* |
1881 | * GParamSpecVariant can specify a GVariantType which can help with |
1882 | * parsing, so we need to take care of that here. |
1883 | */ |
1884 | if (G_IS_PARAM_SPEC_VARIANT (pspec)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (pspec)); GType __t = ((g_param_spec_types[22])); gboolean __r ; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
1885 | { |
1886 | GParamSpecVariant *variant_pspec = G_PARAM_SPEC_VARIANT (pspec)((((GParamSpecVariant*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((pspec)), ((g_param_spec_types[22])))))); |
1887 | const GVariantType *type; |
1888 | GVariant *variant; |
1889 | |
1890 | g_value_init (value, G_TYPE_VARIANT((GType) ((21) << (2)))); |
1891 | |
1892 | /* The GVariant parser doesn't deal with indefinite types */ |
1893 | if (g_variant_type_is_definite (variant_pspec->type)) |
1894 | type = variant_pspec->type; |
1895 | else |
1896 | type = NULL((void*)0); |
1897 | |
1898 | variant = g_variant_parse (type, string, NULL((void*)0), NULL((void*)0), error); |
1899 | if (variant == NULL((void*)0)) |
1900 | return FALSE(0); |
1901 | g_value_take_variant (value, variant); |
1902 | return TRUE(!(0)); |
1903 | } |
1904 | |
1905 | return ctk_builder_value_from_string_type (builder, |
1906 | G_PARAM_SPEC_VALUE_TYPE (pspec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((pspec)), (((GType) ((19) << (2))))))))->value_type ), |
1907 | string, value, error); |
1908 | } |
1909 | |
1910 | /** |
1911 | * ctk_builder_value_from_string_type: |
1912 | * @builder: a #CtkBuilder |
1913 | * @type: the #GType of the value |
1914 | * @string: the string representation of the value |
1915 | * @value: (out): the #GValue to store the result in |
1916 | * @error: (allow-none): return location for an error, or %NULL |
1917 | * |
1918 | * Like ctk_builder_value_from_string(), this function demarshals |
1919 | * a value from a string, but takes a #GType instead of #GParamSpec. |
1920 | * This function calls g_value_init() on the @value argument, so it |
1921 | * need not be initialised beforehand. |
1922 | * |
1923 | * Upon errors %FALSE will be returned and @error will be assigned a |
1924 | * #GError from the #CTK_BUILDER_ERROR domain. |
1925 | * |
1926 | * Returns: %TRUE on success |
1927 | * |
1928 | * Since: 2.12 |
1929 | */ |
1930 | gboolean |
1931 | ctk_builder_value_from_string_type (CtkBuilder *builder, |
1932 | GType type, |
1933 | const gchar *string, |
1934 | GValue *value, |
1935 | GError **error) |
1936 | { |
1937 | gboolean ret = TRUE(!(0)); |
1938 | |
1939 | g_return_val_if_fail (string != NULL, FALSE)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "string != NULL"); return ((0)); } } while (0); |
1940 | g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return ((0)); } } while (0); |
1941 | |
1942 | g_value_init (value, type); |
1943 | |
1944 | switch (G_TYPE_FUNDAMENTAL (type)(g_type_fundamental (type))) |
1945 | { |
1946 | case G_TYPE_CHAR((GType) ((3) << (2))): |
1947 | g_value_set_schar (value, string[0]); |
1948 | break; |
1949 | case G_TYPE_UCHAR((GType) ((4) << (2))): |
1950 | g_value_set_uchar (value, (guchar)string[0]); |
1951 | break; |
1952 | case G_TYPE_BOOLEAN((GType) ((5) << (2))): |
1953 | { |
1954 | gboolean b; |
1955 | |
1956 | if (!_ctk_builder_boolean_from_string (string, &b, error)) |
1957 | { |
1958 | ret = FALSE(0); |
1959 | break; |
1960 | } |
1961 | g_value_set_boolean (value, b); |
1962 | break; |
1963 | } |
1964 | case G_TYPE_INT((GType) ((6) << (2))): |
1965 | case G_TYPE_LONG((GType) ((8) << (2))): |
1966 | case G_TYPE_INT64((GType) ((10) << (2))): |
1967 | { |
1968 | gint64 l; |
1969 | gchar *endptr = NULL((void*)0); |
1970 | |
1971 | errno(*__errno_location ()) = 0; |
1972 | l = g_ascii_strtoll (string, &endptr, 0); |
1973 | if (errno(*__errno_location ()) || endptr == string) |
1974 | { |
1975 | g_set_error (error, |
1976 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
1977 | CTK_BUILDER_ERROR_INVALID_VALUE, |
1978 | "Could not parse integer '%s'", |
1979 | string); |
1980 | ret = FALSE(0); |
1981 | break; |
1982 | } |
1983 | if (G_VALUE_HOLDS_INT (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value )); GType __t = (((GType) ((6) << (2)))); gboolean __r; if (!__val) __r = (0); else if (__val->g_type == __t) __r = (!(0)); else __r = g_type_check_value_holds (__val, __t); __r ; }))))) |
1984 | g_value_set_int (value, l); |
1985 | else if (G_VALUE_HOLDS_LONG (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value )); GType __t = (((GType) ((8) << (2)))); gboolean __r; if (!__val) __r = (0); else if (__val->g_type == __t) __r = (!(0)); else __r = g_type_check_value_holds (__val, __t); __r ; }))))) |
1986 | g_value_set_long (value, l); |
1987 | else |
1988 | g_value_set_int64 (value, l); |
1989 | break; |
1990 | } |
1991 | case G_TYPE_UINT((GType) ((7) << (2))): |
1992 | case G_TYPE_ULONG((GType) ((9) << (2))): |
1993 | case G_TYPE_UINT64((GType) ((11) << (2))): |
1994 | { |
1995 | guint64 ul; |
1996 | gchar *endptr = NULL((void*)0); |
1997 | errno(*__errno_location ()) = 0; |
1998 | ul = g_ascii_strtoull (string, &endptr, 0); |
1999 | if (errno(*__errno_location ()) || endptr == string) |
2000 | { |
2001 | g_set_error (error, |
2002 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2003 | CTK_BUILDER_ERROR_INVALID_VALUE, |
2004 | "Could not parse unsigned integer '%s'", |
2005 | string); |
2006 | ret = FALSE(0); |
2007 | break; |
2008 | } |
2009 | if (G_VALUE_HOLDS_UINT (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value )); GType __t = (((GType) ((7) << (2)))); gboolean __r; if (!__val) __r = (0); else if (__val->g_type == __t) __r = (!(0)); else __r = g_type_check_value_holds (__val, __t); __r ; }))))) |
2010 | g_value_set_uint (value, ul); |
2011 | else if (G_VALUE_HOLDS_ULONG (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value )); GType __t = (((GType) ((9) << (2)))); gboolean __r; if (!__val) __r = (0); else if (__val->g_type == __t) __r = (!(0)); else __r = g_type_check_value_holds (__val, __t); __r ; }))))) |
2012 | g_value_set_ulong (value, ul); |
2013 | else |
2014 | g_value_set_uint64 (value, ul); |
2015 | break; |
2016 | } |
2017 | case G_TYPE_ENUM((GType) ((12) << (2))): |
2018 | { |
2019 | gint enum_value; |
2020 | if (!_ctk_builder_enum_from_string (type, string, &enum_value, error)) |
2021 | { |
2022 | ret = FALSE(0); |
2023 | break; |
2024 | } |
2025 | g_value_set_enum (value, enum_value); |
2026 | break; |
2027 | } |
2028 | case G_TYPE_FLAGS((GType) ((13) << (2))): |
2029 | { |
2030 | guint flags_value; |
2031 | |
2032 | if (!_ctk_builder_flags_from_string (type, NULL((void*)0), string, &flags_value, error)) |
2033 | { |
2034 | ret = FALSE(0); |
2035 | break; |
2036 | } |
2037 | g_value_set_flags (value, flags_value); |
2038 | break; |
2039 | } |
2040 | case G_TYPE_FLOAT((GType) ((14) << (2))): |
2041 | case G_TYPE_DOUBLE((GType) ((15) << (2))): |
2042 | { |
2043 | gdouble d; |
2044 | gchar *endptr = NULL((void*)0); |
2045 | errno(*__errno_location ()) = 0; |
2046 | d = g_ascii_strtod (string, &endptr); |
2047 | if (errno(*__errno_location ()) || endptr == string) |
2048 | { |
2049 | g_set_error (error, |
2050 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2051 | CTK_BUILDER_ERROR_INVALID_VALUE, |
2052 | "Could not parse double '%s'", |
2053 | string); |
2054 | ret = FALSE(0); |
2055 | break; |
2056 | } |
2057 | if (G_VALUE_HOLDS_FLOAT (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value )); GType __t = (((GType) ((14) << (2)))); gboolean __r ; if (!__val) __r = (0); else if (__val->g_type == __t) __r = (!(0)); else __r = g_type_check_value_holds (__val, __t); __r ; }))))) |
2058 | g_value_set_float (value, d); |
2059 | else |
2060 | g_value_set_double (value, d); |
2061 | break; |
2062 | } |
2063 | case G_TYPE_STRING((GType) ((16) << (2))): |
2064 | g_value_set_string (value, string); |
2065 | break; |
2066 | case G_TYPE_VARIANT((GType) ((21) << (2))): |
2067 | { |
2068 | GVariant *variant; |
2069 | |
2070 | variant = g_variant_parse (NULL((void*)0), string, NULL((void*)0), NULL((void*)0), error); |
2071 | if (value != NULL((void*)0)) |
2072 | g_value_take_variant (value, variant); |
2073 | else |
2074 | ret = FALSE(0); |
2075 | } |
2076 | break; |
2077 | case G_TYPE_BOXED((GType) ((18) << (2))): |
2078 | if (G_VALUE_HOLDS (value, g_type_from_name ("CdkColor"))(((__extension__ ({ const GValue *__val = (const GValue*) ((value )); GType __t = ((g_type_from_name ("CdkColor"))); gboolean __r ; if (!__val) __r = (0); else if (__val->g_type == __t) __r = (!(0)); else __r = g_type_check_value_holds (__val, __t); __r ; }))))) |
2079 | { |
2080 | CdkColor color = { 0, }; |
2081 | |
2082 | if (cdk_color_parse (string, &color)) |
2083 | g_value_set_boxed (value, &color); |
2084 | else |
2085 | { |
2086 | g_set_error (error, |
2087 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2088 | CTK_BUILDER_ERROR_INVALID_VALUE, |
2089 | "Could not parse color '%s'", |
2090 | string); |
2091 | ret = FALSE(0); |
2092 | } |
2093 | } |
2094 | else if (G_VALUE_HOLDS (value, CDK_TYPE_RGBA)(((__extension__ ({ const GValue *__val = (const GValue*) ((value )); GType __t = (((cdk_rgba_get_type ()))); gboolean __r; if ( !__val) __r = (0); else if (__val->g_type == __t) __r = (! (0)); else __r = g_type_check_value_holds (__val, __t); __r; } ))))) |
2095 | { |
2096 | CdkRGBA rgba = { 0 }; |
2097 | |
2098 | if (cdk_rgba_parse (&rgba, string)) |
2099 | g_value_set_boxed (value, &rgba); |
2100 | else |
2101 | { |
2102 | g_set_error (error, |
2103 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2104 | CTK_BUILDER_ERROR_INVALID_VALUE, |
2105 | "Could not parse RGBA color '%s'", |
2106 | string); |
2107 | ret = FALSE(0); |
2108 | } |
2109 | } |
2110 | else if (G_VALUE_HOLDS (value, G_TYPE_STRV)(((__extension__ ({ const GValue *__val = (const GValue*) ((value )); GType __t = (((g_strv_get_type ()))); gboolean __r; if (! __val) __r = (0); else if (__val->g_type == __t) __r = (!( 0)); else __r = g_type_check_value_holds (__val, __t); __r; } ))))) |
2111 | { |
2112 | gchar **vector = g_strsplit (string, "\n", 0); |
2113 | g_value_take_boxed (value, vector); |
2114 | } |
2115 | else |
2116 | { |
2117 | g_set_error (error, |
2118 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2119 | CTK_BUILDER_ERROR_INVALID_VALUE, |
2120 | "Could not parse '%s' as a %s", |
2121 | string, G_VALUE_TYPE_NAME (value)(g_type_name ((((GValue*) (value))->g_type)))); |
2122 | ret = FALSE(0); |
2123 | } |
2124 | break; |
2125 | case G_TYPE_OBJECT((GType) ((20) << (2))): |
2126 | case G_TYPE_INTERFACE((GType) ((2) << (2))): |
2127 | if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF)(((__extension__ ({ const GValue *__val = (const GValue*) ((value )); GType __t = (((gdk_pixbuf_get_type ()))); gboolean __r; if (!__val) __r = (0); else if (__val->g_type == __t) __r = ( !(0)); else __r = g_type_check_value_holds (__val, __t); __r; }))))) |
2128 | { |
2129 | gchar *filename; |
2130 | GError *tmp_error = NULL((void*)0); |
2131 | GdkPixbuf *pixbuf = NULL((void*)0); |
2132 | |
2133 | if (g_hash_table_contains (builder->priv->objects, string)) |
2134 | { |
2135 | g_set_error (error, |
2136 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2137 | CTK_BUILDER_ERROR_INVALID_VALUE, |
2138 | "Could not load image '%s': " |
2139 | " '%s' is already used as object id", |
2140 | string, string); |
2141 | return FALSE(0); |
2142 | } |
2143 | |
2144 | filename = _ctk_builder_get_resource_path (builder, string); |
2145 | if (filename != NULL((void*)0)) |
2146 | { |
2147 | GInputStream *stream = g_resources_open_stream (filename, 0, &tmp_error); |
2148 | if (stream != NULL((void*)0)) |
2149 | { |
2150 | pixbuf = gdk_pixbuf_new_from_stream (stream, NULL((void*)0), &tmp_error); |
2151 | g_object_unref (stream); |
2152 | } |
2153 | } |
2154 | else |
2155 | { |
2156 | filename = _ctk_builder_get_absolute_filename (builder, string); |
2157 | pixbuf = gdk_pixbuf_new_from_file (filename, &tmp_error); |
2158 | } |
2159 | |
2160 | if (pixbuf == NULL((void*)0)) |
2161 | { |
2162 | CtkIconTheme *theme; |
2163 | |
2164 | g_warning ("Could not load image '%s': %s", |
2165 | string, tmp_error->message); |
2166 | g_error_free (tmp_error); |
2167 | |
2168 | /* fall back to a missing image */ |
2169 | theme = ctk_icon_theme_get_default (); |
2170 | pixbuf = ctk_icon_theme_load_icon (theme, |
2171 | "image-missing", |
2172 | 16, |
2173 | CTK_ICON_LOOKUP_USE_BUILTIN, |
2174 | NULL((void*)0)); |
2175 | } |
2176 | |
2177 | if (pixbuf) |
2178 | { |
2179 | g_value_set_object (value, pixbuf); |
2180 | g_object_unref (G_OBJECT (pixbuf)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((pixbuf)), (((GType) ((20) << (2))))))))); |
2181 | } |
2182 | |
2183 | g_free (filename); |
2184 | |
2185 | ret = TRUE(!(0)); |
2186 | } |
2187 | else if (G_VALUE_HOLDS (value, G_TYPE_FILE)(((__extension__ ({ const GValue *__val = (const GValue*) ((value )); GType __t = (((g_file_get_type ()))); gboolean __r; if (! __val) __r = (0); else if (__val->g_type == __t) __r = (!( 0)); else __r = g_type_check_value_holds (__val, __t); __r; } ))))) |
2188 | { |
2189 | GFile *file; |
2190 | |
2191 | if (g_hash_table_contains (builder->priv->objects, string)) |
2192 | { |
2193 | g_set_error (error, |
2194 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2195 | CTK_BUILDER_ERROR_INVALID_VALUE, |
2196 | "Could not create file '%s': " |
2197 | " '%s' is already used as object id", |
2198 | string, string); |
2199 | return FALSE(0); |
2200 | } |
2201 | |
2202 | file = g_file_new_for_uri (string); |
2203 | g_value_set_object (value, file); |
2204 | g_object_unref (G_OBJECT (file)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((file)), (((GType) ((20) << (2))))))))); |
2205 | |
2206 | ret = TRUE(!(0)); |
2207 | } |
2208 | else |
2209 | ret = FALSE(0); |
2210 | break; |
2211 | default: |
2212 | ret = FALSE(0); |
2213 | break; |
2214 | } |
2215 | |
2216 | /* Catch unassigned error for object types as well as any unsupported types. |
2217 | * While parsing CtkBuilder; object types are deserialized |
2218 | * without calling ctk_builder_value_from_string_type(). |
2219 | */ |
2220 | if (!ret && error && *error == NULL((void*)0)) |
2221 | g_set_error (error, |
2222 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2223 | CTK_BUILDER_ERROR_INVALID_VALUE, |
2224 | "Unsupported GType '%s'", g_type_name (type)); |
2225 | |
2226 | return ret; |
2227 | } |
2228 | |
2229 | gboolean |
2230 | _ctk_builder_enum_from_string (GType type, |
2231 | const gchar *string, |
2232 | gint *enum_value, |
2233 | GError **error) |
2234 | { |
2235 | GEnumClass *eclass; |
2236 | GEnumValue *ev; |
2237 | gchar *endptr; |
2238 | gint value; |
2239 | gboolean ret; |
2240 | |
2241 | g_return_val_if_fail (G_TYPE_IS_ENUM (type), FALSE)do { if ((((g_type_fundamental (type)) == ((GType) ((12) << (2)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "G_TYPE_IS_ENUM (type)"); return ((0)); } } while (0); |
2242 | g_return_val_if_fail (string != NULL, FALSE)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "string != NULL"); return ((0)); } } while (0); |
2243 | |
2244 | ret = TRUE(!(0)); |
2245 | |
2246 | endptr = NULL((void*)0); |
2247 | errno(*__errno_location ()) = 0; |
2248 | value = g_ascii_strtoull (string, &endptr, 0); |
2249 | if (errno(*__errno_location ()) == 0 && endptr != string) /* parsed a number */ |
2250 | *enum_value = value; |
2251 | else |
2252 | { |
2253 | eclass = g_type_class_ref (type); |
2254 | ev = g_enum_get_value_by_name (eclass, string); |
2255 | if (!ev) |
2256 | ev = g_enum_get_value_by_nick (eclass, string); |
2257 | |
2258 | if (ev) |
2259 | *enum_value = ev->value; |
2260 | else |
2261 | { |
2262 | g_set_error (error, |
2263 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2264 | CTK_BUILDER_ERROR_INVALID_VALUE, |
2265 | "Could not parse enum: '%s'", |
2266 | string); |
2267 | ret = FALSE(0); |
2268 | } |
2269 | |
2270 | g_type_class_unref (eclass); |
2271 | } |
2272 | |
2273 | return ret; |
2274 | } |
2275 | |
2276 | gboolean |
2277 | _ctk_builder_flags_from_string (GType type, |
2278 | GFlagsValue *aliases, |
2279 | const gchar *string, |
2280 | guint *flags_value, |
2281 | GError **error) |
2282 | { |
2283 | GFlagsClass *fclass; |
2284 | gchar *endptr, *prevptr; |
2285 | guint i, j, k, value; |
2286 | gchar *flagstr; |
2287 | GFlagsValue *fv; |
2288 | const gchar *flag; |
2289 | gunichar ch; |
2290 | gboolean eos, ret; |
2291 | |
2292 | g_return_val_if_fail (G_TYPE_IS_FLAGS (type), FALSE)do { if ((((g_type_fundamental (type)) == ((GType) ((13) << (2)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "G_TYPE_IS_FLAGS (type)"); return ((0)); } } while (0); |
2293 | g_return_val_if_fail (string != 0, FALSE)do { if ((string != 0)) { } else { g_return_if_fail_warning ( "Ctk", ((const char*) (__func__)), "string != 0"); return ((0 )); } } while (0); |
2294 | |
2295 | ret = TRUE(!(0)); |
2296 | |
2297 | endptr = NULL((void*)0); |
2298 | errno(*__errno_location ()) = 0; |
2299 | value = g_ascii_strtoull (string, &endptr, 0); |
2300 | if (errno(*__errno_location ()) == 0 && endptr != string) /* parsed a number */ |
2301 | *flags_value = value; |
2302 | else |
2303 | { |
2304 | fclass = g_type_class_ref (type); |
2305 | |
2306 | flagstr = g_strdup (string)g_strdup_inline (string); |
2307 | for (value = i = j = 0; ; i++) |
2308 | { |
2309 | |
2310 | eos = flagstr[i] == '\0'; |
2311 | |
2312 | if (!eos && flagstr[i] != '|') |
2313 | continue; |
2314 | |
2315 | flag = &flagstr[j]; |
2316 | endptr = &flagstr[i]; |
2317 | |
2318 | if (!eos) |
2319 | { |
2320 | flagstr[i++] = '\0'; |
2321 | j = i; |
2322 | } |
2323 | |
2324 | /* trim spaces */ |
2325 | for (;;) |
2326 | { |
2327 | ch = g_utf8_get_char (flag); |
2328 | if (!g_unichar_isspace (ch)) |
2329 | break; |
2330 | flag = g_utf8_next_char (flag)((flag) + g_utf8_skip[*(const guchar *)(flag)]); |
2331 | } |
2332 | |
2333 | while (endptr > flag) |
2334 | { |
2335 | prevptr = g_utf8_prev_char (endptr); |
2336 | ch = g_utf8_get_char (prevptr); |
2337 | if (!g_unichar_isspace (ch)) |
2338 | break; |
2339 | endptr = prevptr; |
2340 | } |
2341 | |
2342 | if (endptr > flag) |
2343 | { |
2344 | *endptr = '\0'; |
2345 | |
2346 | fv = NULL((void*)0); |
2347 | |
2348 | if (aliases) |
2349 | { |
2350 | for (k = 0; aliases[k].value_nick; k++) |
2351 | { |
2352 | if (g_ascii_strcasecmp (aliases[k].value_nick, flag) == 0) |
2353 | { |
2354 | fv = &aliases[k]; |
2355 | break; |
2356 | } |
2357 | } |
2358 | } |
2359 | |
2360 | if (!fv) |
2361 | fv = g_flags_get_value_by_name (fclass, flag); |
2362 | |
2363 | if (!fv) |
2364 | fv = g_flags_get_value_by_nick (fclass, flag); |
2365 | |
2366 | if (fv) |
2367 | value |= fv->value; |
2368 | else |
2369 | { |
2370 | g_set_error (error, |
2371 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2372 | CTK_BUILDER_ERROR_INVALID_VALUE, |
2373 | "Unknown flag: '%s'", |
2374 | flag); |
2375 | ret = FALSE(0); |
2376 | break; |
2377 | } |
2378 | } |
2379 | |
2380 | if (eos) |
2381 | { |
2382 | *flags_value = value; |
2383 | break; |
2384 | } |
2385 | } |
2386 | |
2387 | g_free (flagstr); |
2388 | |
2389 | g_type_class_unref (fclass); |
2390 | } |
2391 | |
2392 | return ret; |
2393 | } |
2394 | |
2395 | gboolean |
2396 | _ctk_builder_boolean_from_string (const gchar *string, |
2397 | gboolean *value, |
2398 | GError **error) |
2399 | { |
2400 | if (string[0] == '\0') |
2401 | goto error; |
2402 | else if (string[1] == '\0') |
2403 | { |
2404 | gchar c; |
2405 | |
2406 | c = string[0]; |
2407 | if (c == '1' || |
2408 | c == 'y' || c == 't' || |
2409 | c == 'Y' || c == 'T') |
2410 | *value = TRUE(!(0)); |
2411 | else if (c == '0' || |
2412 | c == 'n' || c == 'f' || |
2413 | c == 'N' || c == 'F') |
2414 | *value = FALSE(0); |
2415 | else |
2416 | goto error; |
2417 | } |
2418 | else |
2419 | { |
2420 | if (g_ascii_strcasecmp (string, "true") == 0 || |
2421 | g_ascii_strcasecmp (string, "yes") == 0) |
2422 | *value = TRUE(!(0)); |
2423 | else if (g_ascii_strcasecmp (string, "false") == 0 || |
2424 | g_ascii_strcasecmp (string, "no") == 0) |
2425 | *value = FALSE(0); |
2426 | else |
2427 | goto error; |
2428 | } |
2429 | |
2430 | return TRUE(!(0)); |
2431 | |
2432 | error: |
2433 | g_set_error (error, |
2434 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2435 | CTK_BUILDER_ERROR_INVALID_VALUE, |
2436 | "Could not parse boolean '%s'", |
2437 | string); |
2438 | return FALSE(0); |
2439 | } |
2440 | |
2441 | /** |
2442 | * ctk_builder_get_type_from_name: |
2443 | * @builder: a #CtkBuilder |
2444 | * @type_name: type name to lookup |
2445 | * |
2446 | * Looks up a type by name, using the virtual function that |
2447 | * #CtkBuilder has for that purpose. This is mainly used when |
2448 | * implementing the #CtkBuildable interface on a type. |
2449 | * |
2450 | * Returns: the #GType found for @type_name or #G_TYPE_INVALID |
2451 | * if no type was found |
2452 | * |
2453 | * Since: 2.12 |
2454 | */ |
2455 | GType |
2456 | ctk_builder_get_type_from_name (CtkBuilder *builder, |
2457 | const gchar *type_name) |
2458 | { |
2459 | GType type; |
2460 | |
2461 | g_return_val_if_fail (CTK_IS_BUILDER (builder), G_TYPE_INVALID)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (((GType) ((0) << (2)))); } } while (0); |
2462 | g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID)do { if ((type_name != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "type_name != NULL"); return (((GType) ((0) << (2)))); } } while (0); |
2463 | |
2464 | type = CTK_BUILDER_GET_CLASS (builder)((((CtkBuilderClass*) (((GTypeInstance*) ((builder)))->g_class ))))->get_type_from_name (builder, type_name); |
2465 | |
2466 | if (G_TYPE_IS_CLASSED (type)(g_type_test_flags ((type), G_TYPE_FLAG_CLASSED))) |
2467 | g_type_class_unref (g_type_class_ref (type)); |
2468 | |
2469 | return type; |
2470 | } |
2471 | |
2472 | GQuark |
2473 | ctk_builder_error_quark (void) |
2474 | { |
2475 | return g_quark_from_static_string ("ctk-builder-error-quark"); |
2476 | } |
2477 | |
2478 | gchar * |
2479 | _ctk_builder_get_resource_path (CtkBuilder *builder, const gchar *string) |
2480 | { |
2481 | if (g_str_has_prefix (string, "resource:///")(__builtin_constant_p ("resource:///")? __extension__ ({ const char * const __str = (string); const char * const __prefix = ("resource:///"); gboolean __result = (0); if (__str == ((void *)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len = strlen (( (__str) + !(__str))); const size_t __prefix_len = strlen (((__prefix ) + !(__prefix))); if (__str_len >= __prefix_len) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len ) == 0; } __result; }) : (g_str_has_prefix) (string, "resource:///" ) )) |
2482 | return g_uri_unescape_string (string + 11, "/"); |
2483 | |
2484 | if (g_path_is_absolute (string) || |
2485 | builder->priv->resource_prefix == NULL((void*)0)) |
2486 | return NULL((void*)0); |
2487 | |
2488 | return g_build_path ("/", builder->priv->resource_prefix, string, NULL((void*)0)); |
2489 | } |
2490 | |
2491 | gchar * |
2492 | _ctk_builder_get_absolute_filename (CtkBuilder *builder, |
2493 | const gchar *string) |
2494 | { |
2495 | gchar *filename; |
2496 | gchar *dirname = NULL((void*)0); |
2497 | |
2498 | if (g_path_is_absolute (string)) |
2499 | return g_strdup (string)g_strdup_inline (string); |
2500 | |
2501 | if (builder->priv->filename && |
2502 | strcmp (builder->priv->filename, ".") != 0) |
2503 | { |
2504 | dirname = g_path_get_dirname (builder->priv->filename); |
2505 | |
2506 | if (strcmp (dirname, ".") == 0) |
2507 | { |
2508 | g_free (dirname); |
2509 | dirname = g_get_current_dir (); |
2510 | } |
2511 | } |
2512 | else |
2513 | dirname = g_get_current_dir (); |
2514 | |
2515 | filename = g_build_filename (dirname, string, NULL((void*)0)); |
2516 | g_free (dirname); |
2517 | |
2518 | return filename; |
2519 | } |
2520 | |
2521 | GType |
2522 | _ctk_builder_get_template_type (CtkBuilder *builder) |
2523 | { |
2524 | return builder->priv->template_type; |
2525 | } |
2526 | |
2527 | /** |
2528 | * ctk_builder_add_callback_symbol: |
2529 | * @builder: a #CtkBuilder |
2530 | * @callback_name: The name of the callback, as expected in the XML |
2531 | * @callback_symbol: (scope async): The callback pointer |
2532 | * |
2533 | * Adds the @callback_symbol to the scope of @builder under the given @callback_name. |
2534 | * |
2535 | * Using this function overrides the behavior of ctk_builder_connect_signals() |
2536 | * for any callback symbols that are added. Using this method allows for better |
2537 | * encapsulation as it does not require that callback symbols be declared in |
2538 | * the global namespace. |
2539 | * |
2540 | * Since: 3.10 |
2541 | */ |
2542 | void |
2543 | ctk_builder_add_callback_symbol (CtkBuilder *builder, |
2544 | const gchar *callback_name, |
2545 | GCallback callback_symbol) |
2546 | { |
2547 | g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return; } } while (0); |
2548 | g_return_if_fail (callback_name && callback_name[0])do { if ((callback_name && callback_name[0])) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "callback_name && callback_name[0]"); return; } } while (0); |
2549 | g_return_if_fail (callback_symbol != NULL)do { if ((callback_symbol != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "callback_symbol != NULL" ); return; } } while (0); |
2550 | |
2551 | if (!builder->priv->callbacks) |
2552 | builder->priv->callbacks = g_hash_table_new_full (g_str_hash, g_str_equal, |
2553 | g_free, NULL((void*)0)); |
2554 | |
2555 | g_hash_table_insert (builder->priv->callbacks, g_strdup (callback_name)g_strdup_inline (callback_name), callback_symbol); |
2556 | } |
2557 | |
2558 | /** |
2559 | * ctk_builder_add_callback_symbols: |
2560 | * @builder: a #CtkBuilder |
2561 | * @first_callback_name: The name of the callback, as expected in the XML |
2562 | * @first_callback_symbol: (scope async): The callback pointer |
2563 | * @...: A list of callback name and callback symbol pairs terminated with %NULL |
2564 | * |
2565 | * A convenience function to add many callbacks instead of calling |
2566 | * ctk_builder_add_callback_symbol() for each symbol. |
2567 | * |
2568 | * Since: 3.10 |
2569 | */ |
2570 | void |
2571 | ctk_builder_add_callback_symbols (CtkBuilder *builder, |
2572 | const gchar *first_callback_name, |
2573 | GCallback first_callback_symbol, |
2574 | ...) |
2575 | { |
2576 | va_list var_args; |
2577 | const gchar *callback_name; |
2578 | GCallback callback_symbol; |
2579 | |
2580 | g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return; } } while (0); |
2581 | g_return_if_fail (first_callback_name && first_callback_name[0])do { if ((first_callback_name && first_callback_name[ 0])) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "first_callback_name && first_callback_name[0]" ); return; } } while (0); |
2582 | g_return_if_fail (first_callback_symbol != NULL)do { if ((first_callback_symbol != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "first_callback_symbol != NULL" ); return; } } while (0); |
2583 | |
2584 | callback_name = first_callback_name; |
2585 | callback_symbol = first_callback_symbol; |
2586 | |
2587 | va_start (var_args, first_callback_symbol)__builtin_va_start(var_args, first_callback_symbol); |
2588 | |
2589 | do { |
2590 | |
2591 | ctk_builder_add_callback_symbol (builder, callback_name, callback_symbol); |
2592 | |
2593 | callback_name = va_arg (var_args, const gchar*)__builtin_va_arg(var_args, const gchar*); |
2594 | |
2595 | if (callback_name) |
2596 | callback_symbol = va_arg (var_args, GCallback)__builtin_va_arg(var_args, GCallback); |
2597 | |
2598 | } while (callback_name != NULL((void*)0)); |
2599 | |
2600 | va_end (var_args)__builtin_va_end(var_args); |
2601 | } |
2602 | |
2603 | /** |
2604 | * ctk_builder_lookup_callback_symbol: (skip) |
2605 | * @builder: a #CtkBuilder |
2606 | * @callback_name: The name of the callback |
2607 | * |
2608 | * Fetches a symbol previously added to @builder |
2609 | * with ctk_builder_add_callback_symbols() |
2610 | * |
2611 | * This function is intended for possible use in language bindings |
2612 | * or for any case that one might be cusomizing signal connections |
2613 | * using ctk_builder_connect_signals_full() |
2614 | * |
2615 | * Returns: (nullable): The callback symbol in @builder for @callback_name, or %NULL |
2616 | * |
2617 | * Since: 3.10 |
2618 | */ |
2619 | GCallback |
2620 | ctk_builder_lookup_callback_symbol (CtkBuilder *builder, |
2621 | const gchar *callback_name) |
2622 | { |
2623 | g_return_val_if_fail (CTK_IS_BUILDER (builder), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (((void*)0)); } } while (0); |
2624 | g_return_val_if_fail (callback_name && callback_name[0], NULL)do { if ((callback_name && callback_name[0])) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "callback_name && callback_name[0]"); return (((void *)0)); } } while (0); |
2625 | |
2626 | if (!builder->priv->callbacks) |
2627 | return NULL((void*)0); |
2628 | |
2629 | return g_hash_table_lookup (builder->priv->callbacks, callback_name); |
2630 | } |
2631 | |
2632 | /** |
2633 | * ctk_builder_new_from_file: |
2634 | * @filename: filename of user interface description file |
2635 | * |
2636 | * Builds the [CtkBuilder UI definition][BUILDER-UI] |
2637 | * in the file @filename. |
2638 | * |
2639 | * If there is an error opening the file or parsing the description then |
2640 | * the program will be aborted. You should only ever attempt to parse |
2641 | * user interface descriptions that are shipped as part of your program. |
2642 | * |
2643 | * Returns: a #CtkBuilder containing the described interface |
2644 | * |
2645 | * Since: 3.10 |
2646 | **/ |
2647 | CtkBuilder * |
2648 | ctk_builder_new_from_file (const gchar *filename) |
2649 | { |
2650 | GError *error = NULL((void*)0); |
2651 | CtkBuilder *builder; |
2652 | |
2653 | builder = ctk_builder_new (); |
2654 | if (!ctk_builder_add_from_file (builder, filename, &error)) |
2655 | g_error ("failed to add UI: %s", error->message); |
2656 | |
2657 | return builder; |
2658 | } |
2659 | |
2660 | /** |
2661 | * ctk_builder_new_from_resource: |
2662 | * @resource_path: a #GResource resource path |
2663 | * |
2664 | * Builds the [CtkBuilder UI definition][BUILDER-UI] |
2665 | * at @resource_path. |
2666 | * |
2667 | * If there is an error locating the resource or parsing the |
2668 | * description, then the program will be aborted. |
2669 | * |
2670 | * Returns: a #CtkBuilder containing the described interface |
2671 | * |
2672 | * Since: 3.10 |
2673 | **/ |
2674 | CtkBuilder * |
2675 | ctk_builder_new_from_resource (const gchar *resource_path) |
2676 | { |
2677 | GError *error = NULL((void*)0); |
2678 | CtkBuilder *builder; |
2679 | |
2680 | builder = ctk_builder_new (); |
2681 | if (!ctk_builder_add_from_resource (builder, resource_path, &error)) |
2682 | g_error ("failed to add UI: %s", error->message); |
2683 | |
2684 | return builder; |
2685 | } |
2686 | |
2687 | /** |
2688 | * ctk_builder_new_from_string: |
2689 | * @string: a user interface (XML) description |
2690 | * @length: the length of @string, or -1 |
2691 | * |
2692 | * Builds the user interface described by @string (in the |
2693 | * [CtkBuilder UI definition][BUILDER-UI] format). |
2694 | * |
2695 | * If @string is %NULL-terminated, then @length should be -1. |
2696 | * If @length is not -1, then it is the length of @string. |
2697 | * |
2698 | * If there is an error parsing @string then the program will be |
2699 | * aborted. You should not attempt to parse user interface description |
2700 | * from untrusted sources. |
2701 | * |
2702 | * Returns: a #CtkBuilder containing the interface described by @string |
2703 | * |
2704 | * Since: 3.10 |
2705 | **/ |
2706 | CtkBuilder * |
2707 | ctk_builder_new_from_string (const gchar *string, |
2708 | gssize length) |
2709 | { |
2710 | GError *error = NULL((void*)0); |
2711 | CtkBuilder *builder; |
2712 | |
2713 | builder = ctk_builder_new (); |
2714 | if (!ctk_builder_add_from_string (builder, string, length, &error)) |
2715 | g_error ("failed to add UI: %s", error->message); |
2716 | |
2717 | return builder; |
2718 | } |
2719 | |
2720 | /** |
2721 | * ctk_builder_set_application: |
2722 | * @builder: a #CtkBuilder |
2723 | * @application: a #CtkApplication |
2724 | * |
2725 | * Sets the application associated with @builder. |
2726 | * |
2727 | * You only need this function if there is more than one #GApplication |
2728 | * in your process. @application cannot be %NULL. |
2729 | * |
2730 | * Since: 3.10 |
2731 | **/ |
2732 | void |
2733 | ctk_builder_set_application (CtkBuilder *builder, |
2734 | CtkApplication *application) |
2735 | { |
2736 | g_return_if_fail (CTK_IS_BUILDER (builder))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return; } } while (0); |
2737 | g_return_if_fail (CTK_IS_APPLICATION (application))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((application)); GType __t = ((ctk_application_get_type () )); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_APPLICATION (application)"); return ; } } while (0); |
2738 | |
2739 | if (builder->priv->application) |
2740 | g_object_unref (builder->priv->application); |
2741 | |
2742 | builder->priv->application = g_object_ref (application)((__typeof__ (application)) (g_object_ref) (application)); |
2743 | } |
2744 | |
2745 | /** |
2746 | * ctk_builder_get_application: |
2747 | * @builder: a #CtkBuilder |
2748 | * |
2749 | * Gets the #CtkApplication associated with the builder. |
2750 | * |
2751 | * The #CtkApplication is used for creating action proxies as requested |
2752 | * from XML that the builder is loading. |
2753 | * |
2754 | * By default, the builder uses the default application: the one from |
2755 | * g_application_get_default(). If you want to use another application |
2756 | * for constructing proxies, use ctk_builder_set_application(). |
2757 | * |
2758 | * Returns: (nullable) (transfer none): the application being used by the builder, |
2759 | * or %NULL |
2760 | * |
2761 | * Since: 3.10 |
2762 | **/ |
2763 | CtkApplication * |
2764 | ctk_builder_get_application (CtkBuilder *builder) |
2765 | { |
2766 | g_return_val_if_fail (CTK_IS_BUILDER (builder), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((builder)); GType __t = ((ctk_builder_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_BUILDER (builder)"); return (((void*)0)); } } while (0); |
2767 | |
2768 | if (!builder->priv->application) |
2769 | { |
2770 | GApplication *application; |
2771 | |
2772 | application = g_application_get_default (); |
2773 | if (application && CTK_IS_APPLICATION (application)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (application)); GType __t = ((ctk_application_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
2774 | builder->priv->application = g_object_ref (CTK_APPLICATION (application))((__typeof__ (((((CtkApplication*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((application)), ((ctk_application_get_type ())))))))) (g_object_ref) (((((CtkApplication*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((application)), ((ctk_application_get_type ())))))))); |
2775 | } |
2776 | |
2777 | return builder->priv->application; |
2778 | } |
2779 | |
2780 | /*< private > |
2781 | * _ctk_builder_prefix_error: |
2782 | * @builder: a #CtkBuilder |
2783 | * @context: the #GMarkupParseContext |
2784 | * @error: an error |
2785 | * |
2786 | * Calls g_prefix_error() to prepend a filename:line:column marker |
2787 | * to the given error. The filename is taken from @builder, and |
2788 | * the line and column are obtained by calling |
2789 | * g_markup_parse_context_get_position(). |
2790 | * |
2791 | * This is intended to be called on errors returned by |
2792 | * g_markup_collect_attributes() in a start_element vfunc. |
2793 | */ |
2794 | void |
2795 | _ctk_builder_prefix_error (CtkBuilder *builder, |
2796 | GMarkupParseContext *context, |
2797 | GError **error) |
2798 | { |
2799 | gint line, col; |
2800 | |
2801 | g_markup_parse_context_get_position (context, &line, &col); |
2802 | g_prefix_error (error, "%s:%d:%d ", builder->priv->filename, line, col); |
2803 | } |
2804 | |
2805 | /*< private > |
2806 | * _ctk_builder_error_unhandled_tag: |
2807 | * @builder: a #CtkBuilder |
2808 | * @context: the #GMarkupParseContext |
2809 | * @object: name of the object that is being handled |
2810 | * @element_name: name of the element whose start tag is being handled |
2811 | * @error: return location for the error |
2812 | * |
2813 | * Sets @error to a suitable error indicating that an @element_name |
2814 | * tag is not expected in the custom markup for @object. |
2815 | * |
2816 | * This is intended to be called in a start_element vfunc. |
2817 | */ |
2818 | void |
2819 | _ctk_builder_error_unhandled_tag (CtkBuilder *builder, |
2820 | GMarkupParseContext *context, |
2821 | const gchar *object, |
2822 | const gchar *element_name, |
2823 | GError **error) |
2824 | { |
2825 | gint line, col; |
2826 | |
2827 | g_markup_parse_context_get_position (context, &line, &col); |
2828 | g_set_error (error, |
2829 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2830 | CTK_BUILDER_ERROR_UNHANDLED_TAG, |
2831 | "%s:%d:%d Unsupported tag for %s: <%s>", |
2832 | builder->priv->filename, line, col, |
2833 | object, element_name); |
2834 | } |
2835 | |
2836 | /*< private > |
2837 | * @builder: a #CtkBuilder |
2838 | * @context: the #GMarkupParseContext |
2839 | * @parent_name: the name of the expected parent element |
2840 | * @error: return location for an error |
2841 | * |
2842 | * Checks that the parent element of the currently handled |
2843 | * start tag is @parent_name and set @error if it isn't. |
2844 | * |
2845 | * This is intended to be called in start_element vfuncs to |
2846 | * ensure that element nesting is as intended. |
2847 | * |
2848 | * Returns: %TRUE if @parent_name is the parent element |
2849 | */ |
2850 | gboolean |
2851 | _ctk_builder_check_parent (CtkBuilder *builder, |
2852 | GMarkupParseContext *context, |
2853 | const gchar *parent_name, |
2854 | GError **error) |
2855 | { |
2856 | const GSList *stack; |
2857 | gint line, col; |
2858 | const gchar *parent; |
2859 | const gchar *element; |
2860 | |
2861 | stack = g_markup_parse_context_get_element_stack (context); |
2862 | |
2863 | element = (const gchar *)stack->data; |
2864 | parent = stack->next ? (const gchar *)stack->next->data : ""; |
2865 | |
2866 | if (g_str_equal (parent_name, parent)(strcmp ((const char *) (parent_name), (const char *) (parent )) == 0) || |
2867 | (g_str_equal (parent_name, "object")(strcmp ((const char *) (parent_name), (const char *) ("object" )) == 0) && g_str_equal (parent, "template")(strcmp ((const char *) (parent), (const char *) ("template") ) == 0))) |
2868 | return TRUE(!(0)); |
2869 | |
2870 | g_markup_parse_context_get_position (context, &line, &col); |
2871 | g_set_error (error, |
2872 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), |
2873 | CTK_BUILDER_ERROR_INVALID_TAG, |
2874 | "%s:%d:%d Can't use <%s> here", |
2875 | builder->priv->filename, line, col, element); |
2876 | |
2877 | return FALSE(0); |
2878 | } |
2879 | |
2880 | /*< private > |
2881 | * @builder: a #CtkBuilder |
2882 | * @name: object name to look up |
2883 | * @line: line number where @name was encountered |
2884 | * @col: column number where @name was encountered |
2885 | * |
2886 | * Looks up an object by name. Similar to ctk_builder_get_object(), |
2887 | * but sets an error if lookup fails during custom_tag_end, |
2888 | * custom_finished or parser_finished vfuncs. |
2889 | * |
2890 | * The reason for doing things this way is that these vfuncs don't |
2891 | * take a GError** parameter to return an error. |
2892 | * |
2893 | * Returns: the found object |
2894 | */ |
2895 | GObject * |
2896 | _ctk_builder_lookup_object (CtkBuilder *builder, |
2897 | const gchar *name, |
2898 | gint line, |
2899 | gint col) |
2900 | { |
2901 | GObject *obj; |
2902 | GError *error = NULL((void*)0); |
2903 | |
2904 | obj = g_hash_table_lookup (builder->priv->objects, name); |
2905 | error = (GError *) g_object_get_data (G_OBJECT (builder)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((builder)), (((GType) ((20) << (2)))))))), "lookup-error"); |
2906 | |
2907 | if (!obj && !error) |
2908 | { |
2909 | g_set_error (&error, |
2910 | CTK_BUILDER_ERROR(ctk_builder_error_quark ()), CTK_BUILDER_ERROR_INVALID_ID, |
2911 | "%s:%d:%d Object with ID %s not found", |
2912 | builder->priv->filename, line, col, name); |
2913 | g_object_set_data_full (G_OBJECT (builder)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((builder)), (((GType) ((20) << (2)))))))), "lookup-error", |
2914 | error, (GDestroyNotify)g_error_free); |
2915 | } |
2916 | |
2917 | return obj; |
2918 | } |
2919 | |
2920 | /*< private > |
2921 | * _ctk_builder_lookup_failed: |
2922 | * @CtkBuilder: a #CtkBuilder |
2923 | * @error: return location for error |
2924 | * |
2925 | * Finds whether any object lookups have failed. |
2926 | * |
2927 | * Returns: %TRUE if @error has been set |
2928 | */ |
2929 | gboolean |
2930 | _ctk_builder_lookup_failed (CtkBuilder *builder, |
2931 | GError **error) |
2932 | { |
2933 | GError *lookup_error; |
2934 | |
2935 | lookup_error = (GError*) g_object_steal_data (G_OBJECT (builder)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((builder)), (((GType) ((20) << (2)))))))), "lookup-error"); |
2936 | if (lookup_error) |
2937 | { |
2938 | g_propagate_error (error, lookup_error); |
2939 | return TRUE(!(0)); |
2940 | } |
2941 | |
2942 | return FALSE(0); |
2943 | } |