]> Pileus Git - ~andy/gtk/blob - gtk/gtkbuilder.c
Require XInput2.h in X11 backend
[~andy/gtk] / gtk / gtkbuilder.c
1 /* GTK - 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:gtkbuilder
23  * @Short_description: Build an interface from an XML UI definition
24  * @Title: GtkBuilder
25  *
26  * A GtkBuilder is an auxiliary object that reads textual descriptions
27  * of a user interface and instantiates the described objects. To pass a
28  * description to a GtkBuilder, call gtk_builder_add_from_file() or
29  * gtk_builder_add_from_string(). These functions can be called multiple
30  * times; the builder merges the content of all descriptions.
31  *
32  * A GtkBuilder holds a reference to all objects that it has constructed
33  * and drops these references when it is finalized. This finalization can
34  * cause the destruction of non-widget objects or widgets which are not
35  * contained in a toplevel window. For toplevel windows constructed by a
36  * builder, it is the responsibility of the user to call gtk_widget_destroy()
37  * to get rid of them and all the widgets they contain.
38  *
39  * The functions gtk_builder_get_object() and gtk_builder_get_objects()
40  * can be used to access the widgets in the interface by the names assigned
41  * to them inside the UI description. Toplevel windows returned by these
42  * functions will stay around until the user explicitly destroys them
43  * with gtk_widget_destroy(). Other widgets will either be part of a
44  * larger hierarchy constructed by the builder (in which case you should
45  * not have to worry about their lifecycle), or without a parent, in which
46  * case they have to be added to some container to make use of them.
47  * Non-widget objects need to be reffed with g_object_ref() to keep them
48  * beyond the lifespan of the builder.
49  *
50  * The function gtk_builder_connect_signals() and variants thereof can be
51  * used to connect handlers to the named signals in the description.
52  *
53  * <refsect2 id="BUILDER-UI">
54  * <title>GtkBuilder UI Definitions</title>
55  * <para>
56  * GtkBuilder parses textual descriptions of user interfaces which are specified
57  * in an XML format which can be roughly described by the RELAX NG schema below.
58  * We refer to these descriptions as <firstterm>GtkBuilder UI definitions</firstterm>
59  * or just <firstterm>UI definitions</firstterm> if the context is clear. Do not
60  * confuse GtkBuilder UI Definitions with
61  * <link linkend="XML-UI">GtkUIManager UI Definitions</link>, which are more
62  * limited in scope.
63  * </para>
64  * <programlisting>
65  * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gtk/gtkbuilder.rnc">
66  *   <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
67  * </xi:include>
68  * </programlisting>
69  * <para>
70  * The toplevel element is &lt;interface&gt;. It optionally takes a "domain"
71  * attribute, which will make the builder look for translated strings using
72  * dgettext() in the domain specified. This can also be done by calling
73  * gtk_builder_set_translation_domain() on the builder. Objects are described by
74  * &lt;object&gt; elements, which can contain &lt;property&gt; elements to set
75  * properties, &lt;signal&gt; elements which connect signals to handlers, and
76  * &lt;child&gt; elements, which describe child objects (most often widgets
77  * inside a container, but also e.g. actions in an action group, or columns in a
78  * tree model). A &lt;child&gt; element contains an &lt;object&gt; element which
79  * describes the child object. The target toolkit version(s) are described by
80  * &lt;requires&gt; elements, the "lib" attribute specifies the widget library
81  * in question (currently the only supported value is "gtk+") and the "version"
82  * attribute specifies the target version in the form
83  * "&lt;major&gt;.&lt;minor&gt;". The builder will error out if the version
84  * requirements are not met.
85  *
86  * Typically, the specific kind of object represented by an &lt;object&gt;
87  * element is specified by the "class" attribute. If the type has not been
88  * loaded yet, GTK+ tries to find the <function>_get_type()</function> from the
89  * class name by applying heuristics. This works in most cases, but if
90  * necessary, it is possible to specify the name of the
91  * <function>_get_type()</function> explictly with the "type-func" attribute.
92  * As a special case, GtkBuilder allows to use an object that has been
93  * constructed by a #GtkUIManager in another part of the UI definition by
94  * specifying the id of the #GtkUIManager in the "constructor" attribute and the
95  * name of the object in the "id" attribute.
96  *
97  * Objects must be given a name with the "id" attribute, which allows the
98  * application to retrieve them from the builder with gtk_builder_get_object().
99  * An id is also necessary to use the object as property value in other parts of
100  * the UI definition.
101  * </para>
102  * <note><para>
103  * Prior to 2.20, GtkBuilder was setting the "name" property of constructed widgets to the
104  * "id" attribute. In GTK+ 2.20 or newer, you have to use gtk_buildable_get_name() instead
105  * of gtk_widget_get_name() to obtain the "id", or set the "name" property in your UI
106  * definition.
107  * </para></note>
108  * <para>
109  * Setting properties of objects is pretty straightforward with the
110  * &lt;property&gt; element: the "name" attribute specifies the name of the
111  * property, and the content of the element specifies the value. If the
112  * "translatable" attribute is set to a true value, GTK+ uses gettext() (or
113  * dgettext() if the builder has a translation domain set) to find a translation
114  * for the value. This happens before the value is parsed, so it can be used for
115  * properties of any type, but it is probably most useful for string properties.
116  * It is also possible to specify a context to disambiguate short strings, and
117  * comments which may help the translators.
118  *
119  * GtkBuilder can parse textual representations for the most common property
120  * types: characters, strings, integers, floating-point numbers, booleans
121  * (strings like "TRUE", "t", "yes", "y", "1" are interpreted as %TRUE, strings
122  * like "FALSE, "f", "no", "n", "0" are interpreted as %FALSE), enumerations
123  * (can be specified by their name, nick or integer value), flags (can be
124  * specified by their name, nick, integer value, optionally combined with "|",
125  * e.g. "GTK_VISIBLE|GTK_REALIZED")  and colors (in a format understood by
126  * gdk_color_parse()). Objects can be referred to by their name. Pixbufs can be
127  * specified as a filename of an image file to load. In general, GtkBuilder
128  * allows forward references to objects &mdash; an object doesn't have to be
129  * constructed before it can be referred to. The exception to this rule is that
130  * an object has to be constructed before it can be used as the value of a
131  * construct-only property.
132  *
133  * Signal handlers are set up with the &lt;signal&gt; element. The "name"
134  * attribute specifies the name of the signal, and the "handler" attribute
135  * specifies the function to connect to the signal. By default, GTK+ tries to
136  * find the handler using g_module_symbol(), but this can be changed by passing
137  * a custom #GtkBuilderConnectFunc to gtk_builder_connect_signals_full(). The
138  * remaining attributes, "after", "swapped" and "object", have the same meaning
139  * as the corresponding parameters of the g_signal_connect_object() or
140  * g_signal_connect_data() functions. A "last_modification_time" attribute
141  * is also allowed, but it does not have a meaning to the builder.
142  *
143  * Sometimes it is necessary to refer to widgets which have implicitly been
144  * constructed by GTK+ as part of a composite widget, to set properties on them
145  * or to add further children (e.g. the @vbox of a #GtkDialog). This can be
146  * achieved by setting the "internal-child" propery of the &lt;child&gt; element
147  * to a true value. Note that GtkBuilder still requires an &lt;object&gt;
148  * element for the internal child, even if it has already been constructed.
149  *
150  * A number of widgets have different places where a child can be added (e.g.
151  * tabs vs. page content in notebooks). This can be reflected in a UI definition
152  * by specifying the "type" attribute on a &lt;child&gt;. The possible values
153  * for the "type" attribute are described in the sections describing the
154  * widget-specific portions of UI definitions.
155  * </para>
156  * <example>
157  * <title>A GtkBuilder UI Definition</title>
158  * <programlisting><![CDATA[
159  * <interface>
160  *   <object class="GtkDialog" id="dialog1">
161  *     <child internal-child="vbox">
162  *       <object class="GtkVBox" id="vbox1">
163  *         <property name="border-width">10</property>
164  *         <child internal-child="action_area">
165  *           <object class="GtkHButtonBox" id="hbuttonbox1">
166  *             <property name="border-width">20</property>
167  *             <child>
168  *               <object class="GtkButton" id="ok_button">
169  *                 <property name="label">gtk-ok</property>
170  *                 <property name="use-stock">TRUE</property>
171  *                 <signal name="clicked" handler="ok_button_clicked"/>
172  *               </object>
173  *             </child>
174  *           </object>
175  *         </child>
176  *       </object>
177  *     </child>
178  *   </object>
179  * </interface>
180  * ]]></programlisting>
181  * </example>
182  * <para>
183  * Beyond this general structure, several object classes define their own XML
184  * DTD fragments for filling in the ANY placeholders in the DTD above. Note that
185  * a custom element in a &lt;child&gt; element gets parsed by the custom tag
186  * handler of the parent object, while a custom element in an &lt;object&gt;
187  * element gets parsed by the custom tag handler of the object.
188  *
189  * These XML fragments are explained in the documentation of the respective
190  * objects, see
191  * <link linkend="GtkWidget-BUILDER-UI">GtkWidget</link>,
192  * <link linkend="GtkLabel-BUILDER-UI">GtkLabel</link>,
193  * <link linkend="GtkWindow-BUILDER-UI">GtkWindow</link>,
194  * <link linkend="GtkContainer-BUILDER-UI">GtkContainer</link>,
195  * <link linkend="GtkDialog-BUILDER-UI">GtkDialog</link>,
196  * <link linkend="GtkCellLayout-BUILDER-UI">GtkCellLayout</link>,
197  * <link linkend="GtkColorSelectionDialog-BUILDER-UI">GtkColorSelectionDialog</link>,
198  * <link linkend="GtkFontSelectionDialog-BUILDER-UI">GtkFontSelectionDialog</link>,
199  * <link linkend="GtkExpander-BUILDER-UI">GtkExpander</link>,
200  * <link linkend="GtkFrame-BUILDER-UI">GtkFrame</link>,
201  * <link linkend="GtkListStore-BUILDER-UI">GtkListStore</link>,
202  * <link linkend="GtkTreeStore-BUILDER-UI">GtkTreeStore</link>,
203  * <link linkend="GtkNotebook-BUILDER-UI">GtkNotebook</link>,
204  * <link linkend="GtkSizeGroup-BUILDER-UI">GtkSizeGroup</link>,
205  * <link linkend="GtkTreeView-BUILDER-UI">GtkTreeView</link>,
206  * <link linkend="GtkUIManager-BUILDER-UI">GtkUIManager</link>,
207  * <link linkend="GtkActionGroup-BUILDER-UI">GtkActionGroup</link>.
208  * <link linkend="GtkMenuItem-BUILDER-UI">GtkMenuItem</link>,
209  * <link linkend="GtkMenuToolButton-BUILDER-UI">GtkMenuToolButton</link>,
210  * <link linkend="GtkAssistant-BUILDER-UI">GtkAssistant</link>,
211  * <link linkend="GtkScale-BUILDER-UI">GtkScale</link>,
212  * <link linkend="GtkComboBoxText-BUILDER-UI">GtkComboBoxText</link>,
213  * <link linkend="GtkRecentFilter-BUILDER-UI">GtkRecentFilter</link>,
214  * <link linkend="GtkFileFilter-BUILDER-UI">GtkFileFilter</link>,
215  * <link linkend="GtkTextTagTable-BUILDER-UI">GtkTextTagTable</link>.
216  * </para>
217  * </refsect2>
218  * <refsect2>
219  * <title>Embedding other XML</title>
220  * <para>
221  * Apart from the language for UI descriptions that has been explained
222  * in the previous section, GtkBuilder can also parse XML fragments
223  * of <link linkend="gio-GMenu-Markup">GMenu markup</link>. The resulting
224  * #GMenu object and its named submenus are available via
225  * gtk_builder_get_object() like other constructed objects.
226  * </para>
227  * </refsect2>
228  */
229
230 #include "config.h"
231 #include <errno.h> /* errno */
232 #include <stdlib.h>
233 #include <string.h> /* strlen */
234
235 #include "gtkbuilder.h"
236 #include "gtkbuildable.h"
237 #include "gtkbuilderprivate.h"
238 #include "gtkdebug.h"
239 #include "gtkmain.h"
240 #include "gtkintl.h"
241 #include "gtkprivate.h"
242 #include "gtktypebuiltins.h"
243 #include "gtkwindow.h"
244 #include "gtkicontheme.h"
245 #include "gtkstock.h"
246
247
248 static void gtk_builder_class_init     (GtkBuilderClass *klass);
249 static void gtk_builder_init           (GtkBuilder      *builder);
250 static void gtk_builder_finalize       (GObject         *object);
251 static void gtk_builder_set_property   (GObject         *object,
252                                         guint            prop_id,
253                                         const GValue    *value,
254                                         GParamSpec      *pspec);
255 static void gtk_builder_get_property   (GObject         *object,
256                                         guint            prop_id,
257                                         GValue          *value,
258                                         GParamSpec      *pspec);
259 static GType gtk_builder_real_get_type_from_name (GtkBuilder  *builder,
260                                                   const gchar *type_name);
261
262 enum {
263   PROP_0,
264   PROP_TRANSLATION_DOMAIN,
265 };
266
267 struct _GtkBuilderPrivate
268 {
269   gchar *domain;
270   GHashTable *objects;
271   GSList *delayed_properties;
272   GSList *signals;
273   gchar *filename;
274   gchar *resource_prefix;
275 };
276
277 G_DEFINE_TYPE (GtkBuilder, gtk_builder, G_TYPE_OBJECT)
278
279 static void
280 gtk_builder_class_init (GtkBuilderClass *klass)
281 {
282   GObjectClass *gobject_class;
283
284   gobject_class = G_OBJECT_CLASS (klass);
285
286   gobject_class->finalize = gtk_builder_finalize;
287   gobject_class->set_property = gtk_builder_set_property;
288   gobject_class->get_property = gtk_builder_get_property;
289
290   klass->get_type_from_name = gtk_builder_real_get_type_from_name;
291
292  /** 
293   * GtkBuilder:translation-domain:
294   *
295   * The translation domain used when translating property values that
296   * have been marked as translatable in interface descriptions.
297   * If the translation domain is %NULL, #GtkBuilder uses gettext(),
298   * otherwise g_dgettext().
299   *
300   * Since: 2.12
301   */
302   g_object_class_install_property (gobject_class,
303                                    PROP_TRANSLATION_DOMAIN,
304                                    g_param_spec_string ("translation-domain",
305                                                         P_("Translation Domain"),
306                                                         P_("The translation domain used by gettext"),
307                                                         NULL,
308                                                         GTK_PARAM_READWRITE));
309
310   g_type_class_add_private (gobject_class, sizeof (GtkBuilderPrivate));
311 }
312
313 static void
314 gtk_builder_init (GtkBuilder *builder)
315 {
316   builder->priv = G_TYPE_INSTANCE_GET_PRIVATE (builder, GTK_TYPE_BUILDER,
317                                                GtkBuilderPrivate);
318   builder->priv->domain = NULL;
319   builder->priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
320                                                   g_free, g_object_unref);
321 }
322
323
324 /*
325  * GObject virtual methods
326  */
327
328 static void
329 gtk_builder_finalize (GObject *object)
330 {
331   GtkBuilderPrivate *priv = GTK_BUILDER (object)->priv;
332   
333   g_free (priv->domain);
334   g_free (priv->filename);
335   g_free (priv->resource_prefix);
336   
337   g_hash_table_destroy (priv->objects);
338
339   g_slist_foreach (priv->signals, (GFunc) _free_signal_info, NULL);
340   g_slist_free (priv->signals);
341   
342   G_OBJECT_CLASS (gtk_builder_parent_class)->finalize (object);
343 }
344
345 static void
346 gtk_builder_set_property (GObject      *object,
347                           guint         prop_id,
348                           const GValue *value,
349                           GParamSpec   *pspec)
350 {
351   GtkBuilder *builder = GTK_BUILDER (object);
352
353   switch (prop_id)
354     {
355     case PROP_TRANSLATION_DOMAIN:
356       gtk_builder_set_translation_domain (builder, g_value_get_string (value));
357       break;
358     default:
359       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
360       break;
361     }
362 }
363
364 static void
365 gtk_builder_get_property (GObject    *object,
366                           guint       prop_id,
367                           GValue     *value,
368                           GParamSpec *pspec)
369 {
370   GtkBuilder *builder = GTK_BUILDER (object);
371
372   switch (prop_id)
373     {
374     case PROP_TRANSLATION_DOMAIN:
375       g_value_set_string (value, builder->priv->domain);
376       break;
377     default:
378       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
379       break;
380     }
381 }
382
383
384 /*
385  * Try to map a type name to a _get_type function
386  * and call it, eg:
387  *
388  * GtkWindow -> gtk_window_get_type
389  * GtkHBox -> gtk_hbox_get_type
390  * GtkUIManager -> gtk_ui_manager_get_type
391  *
392  */
393 static GType
394 _gtk_builder_resolve_type_lazily (const gchar *name)
395 {
396   static GModule *module = NULL;
397   GTypeGetFunc func;
398   GString *symbol_name = g_string_new ("");
399   char c, *symbol;
400   int i;
401   GType gtype = G_TYPE_INVALID;
402
403   if (!module)
404     module = g_module_open (NULL, 0);
405   
406   for (i = 0; name[i] != '\0'; i++)
407     {
408       c = name[i];
409       /* skip if uppercase, first or previous is uppercase */
410       if ((c == g_ascii_toupper (c) &&
411            i > 0 && name[i-1] != g_ascii_toupper (name[i-1])) ||
412           (i > 2 && name[i]   == g_ascii_toupper (name[i]) &&
413            name[i-1] == g_ascii_toupper (name[i-1]) &&
414            name[i-2] == g_ascii_toupper (name[i-2])))
415         g_string_append_c (symbol_name, '_');
416       g_string_append_c (symbol_name, g_ascii_tolower (c));
417     }
418   g_string_append (symbol_name, "_get_type");
419   
420   symbol = g_string_free (symbol_name, FALSE);
421
422   if (g_module_symbol (module, symbol, (gpointer)&func))
423     gtype = func ();
424   
425   g_free (symbol);
426
427   return gtype;
428 }
429
430 /*
431  * GtkBuilder virtual methods
432  */
433
434 static GType
435 gtk_builder_real_get_type_from_name (GtkBuilder  *builder, 
436                                      const gchar *type_name)
437 {
438   GType gtype;
439
440   gtype = g_type_from_name (type_name);
441   if (gtype != G_TYPE_INVALID)
442     return gtype;
443
444   return _gtk_builder_resolve_type_lazily (type_name);
445 }
446
447 typedef struct
448 {
449   gchar *object;
450   gchar *name;
451   gchar *value;
452 } DelayedProperty;
453
454 static void
455 gtk_builder_get_parameters (GtkBuilder  *builder,
456                             GType        object_type,
457                             const gchar *object_name,
458                             GSList      *properties,
459                             GArray      **parameters,
460                             GArray      **construct_parameters)
461 {
462   GSList *l;
463   GParamSpec *pspec;
464   GObjectClass *oclass;
465   DelayedProperty *property;
466   GError *error = NULL;
467   
468   oclass = g_type_class_ref (object_type);
469   g_assert (oclass != NULL);
470
471   *parameters = g_array_new (FALSE, FALSE, sizeof (GParameter));
472   *construct_parameters = g_array_new (FALSE, FALSE, sizeof (GParameter));
473
474   for (l = properties; l; l = l->next)
475     {
476       PropertyInfo *prop = (PropertyInfo*)l->data;
477       GParameter parameter = { NULL };
478
479       pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass),
480                                             prop->name);
481       if (!pspec)
482         {
483           g_warning ("Unknown property: %s.%s",
484                      g_type_name (object_type), prop->name);
485           continue;
486         }
487
488       parameter.name = prop->name;
489
490       if (G_IS_PARAM_SPEC_OBJECT (pspec) &&
491           (G_PARAM_SPEC_VALUE_TYPE (pspec) != GDK_TYPE_PIXBUF))
492         {
493           GObject *object = gtk_builder_get_object (builder, prop->data);
494
495           if (object)
496             {
497               g_value_init (&parameter.value, G_OBJECT_TYPE (object));
498               g_value_set_object (&parameter.value, object);
499             }
500           else 
501             {
502               if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
503                 {
504                   g_warning ("Failed to get constuct only property "
505                              "%s of %s with value `%s'",
506                              prop->name, object_name, prop->data);
507                   continue;
508                 }
509               /* Delay setting property */
510               property = g_slice_new (DelayedProperty);
511               property->object = g_strdup (object_name);
512               property->name = g_strdup (prop->name);
513               property->value = g_strdup (prop->data);
514               builder->priv->delayed_properties =
515                 g_slist_prepend (builder->priv->delayed_properties, property);
516               continue;
517             }
518         }
519       else if (!gtk_builder_value_from_string (builder, pspec,
520                                                prop->data, &parameter.value, &error))
521         {
522           g_warning ("Failed to set property %s.%s to %s: %s",
523                      g_type_name (object_type), prop->name, prop->data,
524                      error->message);
525           g_error_free (error);
526           error = NULL;
527           continue;
528         }
529
530       if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
531         g_array_append_val (*construct_parameters, parameter);
532       else
533         g_array_append_val (*parameters, parameter);
534     }
535
536   g_type_class_unref (oclass);
537 }
538
539 static GObject *
540 gtk_builder_get_internal_child (GtkBuilder  *builder,
541                                 ObjectInfo  *info,
542                                 const gchar *childname,
543                                 GError      **error)
544 {
545   GObject *obj = NULL;
546
547   while (!obj)
548     {
549       if (!info->parent)
550         break;
551
552       info = (ObjectInfo*)((ChildInfo*)info->parent)->parent;
553       if (!info)
554         break;
555
556       GTK_NOTE (BUILDER,
557                 g_print ("Trying to get internal child %s from %s\n",
558                          childname,
559                          gtk_buildable_get_name (GTK_BUILDABLE (info->object))));
560
561       if (GTK_IS_BUILDABLE (info->object))
562           obj = gtk_buildable_get_internal_child (GTK_BUILDABLE (info->object),
563                                                   builder,
564                                                   childname);
565     };
566
567   if (!obj)
568     {
569       g_set_error (error,
570                    GTK_BUILDER_ERROR,
571                    GTK_BUILDER_ERROR_INVALID_VALUE,
572                    "Unknown internal child: %s", childname);
573     }
574   return obj;
575 }
576
577 GObject *
578 _gtk_builder_construct (GtkBuilder *builder,
579                         ObjectInfo *info,
580                         GError **error)
581 {
582   GArray *parameters, *construct_parameters;
583   GType object_type;
584   GObject *obj;
585   int i;
586   GtkBuildableIface *iface;
587   gboolean custom_set_property;
588   GtkBuildable *buildable;
589
590   g_assert (info->class_name != NULL);
591   object_type = gtk_builder_get_type_from_name (builder, info->class_name);
592   if (object_type == G_TYPE_INVALID)
593     {
594       g_set_error (error,
595                    GTK_BUILDER_ERROR,
596                    GTK_BUILDER_ERROR_INVALID_VALUE,
597                    "Invalid object type `%s'",
598                    info->class_name);
599       return NULL;
600     }
601
602   gtk_builder_get_parameters (builder, object_type,
603                               info->id,
604                               info->properties,
605                               &parameters,
606                               &construct_parameters);
607
608   if (info->constructor)
609     {
610       GObject *constructor;
611
612       constructor = gtk_builder_get_object (builder, info->constructor);
613       if (constructor == NULL)
614         {
615           g_set_error (error,
616                        GTK_BUILDER_ERROR,
617                        GTK_BUILDER_ERROR_INVALID_VALUE,
618                        "Unknown object constructor for %s: %s",
619                        info->id,
620                        info->constructor);
621           g_array_free (parameters, TRUE);
622           g_array_free (construct_parameters, TRUE);
623           return NULL;
624         }
625       obj = gtk_buildable_construct_child (GTK_BUILDABLE (constructor),
626                                            builder,
627                                            info->id);
628       g_assert (obj != NULL);
629       if (construct_parameters->len)
630         g_warning ("Can't pass in construct-only parameters to %s", info->id);
631     }
632   else if (info->parent && ((ChildInfo*)info->parent)->internal_child != NULL)
633     {
634       gchar *childname = ((ChildInfo*)info->parent)->internal_child;
635       obj = gtk_builder_get_internal_child (builder, info, childname, error);
636       if (!obj)
637         {
638           g_array_free (parameters, TRUE);
639           g_array_free (construct_parameters, TRUE);
640           return NULL;
641         }
642       if (construct_parameters->len)
643         g_warning ("Can't pass in construct-only parameters to %s", childname);
644       g_object_ref (obj);
645     }
646   else
647     {
648       obj = g_object_newv (object_type,
649                            construct_parameters->len,
650                            (GParameter *)construct_parameters->data);
651
652       /* No matter what, make sure we have a reference.
653        *
654        * If it's an initially unowned object, sink it.
655        * If it's not initially unowned then we have the reference already.
656        *
657        * In the case that this is a window it will be sunk already and
658        * this is effectively a call to g_object_ref().  That's what
659        * we want.
660        */
661       if (G_IS_INITIALLY_UNOWNED (obj))
662         g_object_ref_sink (obj);
663
664       GTK_NOTE (BUILDER,
665                 g_print ("created %s of type %s\n", info->id, info->class_name));
666
667       for (i = 0; i < construct_parameters->len; i++)
668         {
669           GParameter *param = &g_array_index (construct_parameters,
670                                               GParameter, i);
671           g_value_unset (&param->value);
672         }
673     }
674   g_array_free (construct_parameters, TRUE);
675
676   custom_set_property = FALSE;
677   buildable = NULL;
678   iface = NULL;
679   if (GTK_IS_BUILDABLE (obj))
680     {
681       buildable = GTK_BUILDABLE (obj);
682       iface = GTK_BUILDABLE_GET_IFACE (obj);
683       if (iface->set_buildable_property)
684         custom_set_property = TRUE;
685     }
686
687   for (i = 0; i < parameters->len; i++)
688     {
689       GParameter *param = &g_array_index (parameters, GParameter, i);
690       if (custom_set_property)
691         iface->set_buildable_property (buildable, builder, param->name, &param->value);
692       else
693         g_object_set_property (obj, param->name, &param->value);
694
695 #if G_ENABLE_DEBUG
696       if (gtk_get_debug_flags () & GTK_DEBUG_BUILDER)
697         {
698           gchar *str = g_strdup_value_contents ((const GValue*)&param->value);
699           g_print ("set %s: %s = %s\n", info->id, param->name, str);
700           g_free (str);
701         }
702 #endif      
703       g_value_unset (&param->value);
704     }
705   g_array_free (parameters, TRUE);
706   
707   if (GTK_IS_BUILDABLE (obj))
708     gtk_buildable_set_name (buildable, info->id);
709   else
710     g_object_set_data_full (obj,
711                             "gtk-builder-name",
712                             g_strdup (info->id),
713                             g_free);
714
715   /* we already own a reference to obj.  put it in the hash table. */
716   g_hash_table_insert (builder->priv->objects, g_strdup (info->id), obj);
717   
718   return obj;
719 }
720
721 void
722 _gtk_builder_add_object (GtkBuilder  *builder,
723                          const gchar *id,
724                          GObject     *object)
725 {
726   g_hash_table_insert (builder->priv->objects, g_strdup (id), g_object_ref (object));
727 }
728
729 void
730 _gtk_builder_add (GtkBuilder *builder,
731                   ChildInfo  *child_info)
732 {
733   GObject *object;
734   GObject *parent;
735
736   /* Internal children are already added
737    * Also prevent us from being called twice.
738    */
739   if (!child_info ||
740       child_info->internal_child ||
741       child_info->added)
742     return;
743
744   object = child_info->object;
745   if (!object)
746     return;
747
748   if (!child_info->parent)
749     {
750       g_warning ("%s: Not adding, No parent",
751                  gtk_buildable_get_name (GTK_BUILDABLE (object)));
752       return;
753     }
754
755   g_assert (object != NULL);
756
757   parent = ((ObjectInfo*)child_info->parent)->object;
758   g_assert (GTK_IS_BUILDABLE (parent));
759
760   GTK_NOTE (BUILDER,
761             g_print ("adding %s to %s\n",
762                      gtk_buildable_get_name (GTK_BUILDABLE (object)),
763                      gtk_buildable_get_name (GTK_BUILDABLE (parent))));
764   
765   gtk_buildable_add_child (GTK_BUILDABLE (parent), builder, object,
766                            child_info->type);
767
768   child_info->added = TRUE;
769 }
770
771 void
772 _gtk_builder_add_signals (GtkBuilder *builder,
773                           GSList     *signals)
774 {
775   builder->priv->signals = g_slist_concat (builder->priv->signals,
776                                            g_slist_copy (signals));
777 }
778
779 static void
780 gtk_builder_apply_delayed_properties (GtkBuilder *builder)
781 {
782   GSList *l, *props;
783   DelayedProperty *property;
784   GObject *object;
785   GType object_type;
786   GObjectClass *oclass;
787   GParamSpec *pspec;
788
789   /* take the list over from the builder->priv.
790    *
791    * g_slist_reverse does not copy the list, so the list now
792    * belongs to us (and we free it at the end of this function).
793    */
794   props = g_slist_reverse (builder->priv->delayed_properties);
795   builder->priv->delayed_properties = NULL;
796
797   for (l = props; l; l = l->next)
798     {
799       property = (DelayedProperty*)l->data;
800       object = g_hash_table_lookup (builder->priv->objects, property->object);
801       g_assert (object != NULL);
802
803       object_type = G_OBJECT_TYPE (object);
804       g_assert (object_type != G_TYPE_INVALID);
805
806       oclass = g_type_class_ref (object_type);
807       g_assert (oclass != NULL);
808
809       pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass),
810                                             property->name);
811       if (!pspec)
812         g_warning ("Unknown property: %s.%s", g_type_name (object_type),
813                    property->name);
814       else
815         {
816           GObject *obj;
817
818           obj = g_hash_table_lookup (builder->priv->objects, property->value);
819           if (!obj)
820             g_warning ("No object called: %s", property->value);
821           else
822             g_object_set (object, property->name, obj, NULL);
823         }
824       g_free (property->value);
825       g_free (property->object);
826       g_free (property->name);
827       g_slice_free (DelayedProperty, property);
828       g_type_class_unref (oclass);
829     }
830   g_slist_free (props);
831 }
832
833 void
834 _gtk_builder_finish (GtkBuilder *builder)
835 {
836   gtk_builder_apply_delayed_properties (builder);
837 }
838
839 /**
840  * gtk_builder_new:
841  *
842  * Creates a new builder object.
843  *
844  * Return value: a new #GtkBuilder object
845  *
846  * Since: 2.12
847  **/
848 GtkBuilder *
849 gtk_builder_new (void)
850 {
851   return g_object_new (GTK_TYPE_BUILDER, NULL);
852 }
853
854 /**
855  * gtk_builder_add_from_file:
856  * @builder: a #GtkBuilder
857  * @filename: the name of the file to parse
858  * @error: (allow-none): return location for an error, or %NULL
859  *
860  * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder 
861  * UI definition</link> and merges it with the current contents of @builder. 
862  * 
863  * Upon errors 0 will be returned and @error will be assigned a
864  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR 
865  * domain.
866  *
867  * Returns: A positive value on success, 0 if an error occurred
868  *
869  * Since: 2.12
870  **/
871 guint
872 gtk_builder_add_from_file (GtkBuilder   *builder,
873                            const gchar  *filename,
874                            GError      **error)
875 {
876   gchar *buffer;
877   gsize length;
878   GError *tmp_error;
879
880   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
881   g_return_val_if_fail (filename != NULL, 0);
882   g_return_val_if_fail (error == NULL || *error == NULL, 0);
883
884   tmp_error = NULL;
885
886   if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
887     {
888       g_propagate_error (error, tmp_error);
889       return 0;
890     }
891   
892   g_free (builder->priv->filename);
893   g_free (builder->priv->resource_prefix);
894   builder->priv->filename = g_strdup (filename);
895   builder->priv->resource_prefix = NULL;
896
897   _gtk_builder_parser_parse_buffer (builder, filename,
898                                     buffer, length,
899                                     NULL,
900                                     &tmp_error);
901
902   g_free (buffer);
903
904   if (tmp_error != NULL)
905     {
906       g_propagate_error (error, tmp_error);
907       return 0;
908     }
909
910   return 1;
911 }
912
913 /**
914  * gtk_builder_add_objects_from_file:
915  * @builder: a #GtkBuilder
916  * @filename: the name of the file to parse
917  * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
918  * @error: (allow-none): return location for an error, or %NULL
919  *
920  * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder 
921  * UI definition</link> building only the requested objects and merges
922  * them with the current contents of @builder. 
923  *
924  * Upon errors 0 will be returned and @error will be assigned a
925  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR 
926  * domain.
927  *
928  * <note><para>
929  * If you are adding an object that depends on an object that is not 
930  * its child (for instance a #GtkTreeView that depends on its
931  * #GtkTreeModel), you have to explicitely list all of them in @object_ids. 
932  * </para></note>
933  *
934  * Returns: A positive value on success, 0 if an error occurred
935  *
936  * Since: 2.14
937  **/
938 guint
939 gtk_builder_add_objects_from_file (GtkBuilder   *builder,
940                                    const gchar  *filename,
941                                    gchar       **object_ids,
942                                    GError      **error)
943 {
944   gchar *buffer;
945   gsize length;
946   GError *tmp_error;
947
948   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
949   g_return_val_if_fail (filename != NULL, 0);
950   g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0);
951   g_return_val_if_fail (error == NULL || *error == NULL, 0);
952
953   tmp_error = NULL;
954
955   if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
956     {
957       g_propagate_error (error, tmp_error);
958       return 0;
959     }
960   
961   g_free (builder->priv->filename);
962   g_free (builder->priv->resource_prefix);
963   builder->priv->filename = g_strdup (filename);
964   builder->priv->resource_prefix = NULL;
965
966   _gtk_builder_parser_parse_buffer (builder, filename,
967                                     buffer, length,
968                                     object_ids,
969                                     &tmp_error);
970
971   g_free (buffer);
972
973   if (tmp_error != NULL)
974     {
975       g_propagate_error (error, tmp_error);
976       return 0;
977     }
978
979   return 1;
980 }
981
982 /**
983  * gtk_builder_add_from_resource:
984  * @builder: a #GtkBuilder
985  * @resource_path: the path of the resource file to parse
986  * @error: (allow-none): return location for an error, or %NULL
987  *
988  * Parses a resource file containing a <link linkend="BUILDER-UI">GtkBuilder
989  * UI definition</link> and merges it with the current contents of @builder.
990  *
991  * Upon errors 0 will be returned and @error will be assigned a
992  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR
993  * domain.
994  *
995  * Returns: A positive value on success, 0 if an error occurred
996  *
997  * Since: 3.4
998  **/
999 guint
1000 gtk_builder_add_from_resource (GtkBuilder   *builder,
1001                                const gchar  *resource_path,
1002                                GError      **error)
1003 {
1004   GError *tmp_error;
1005   GBytes *data;
1006   char *filename_for_errors;
1007   char *slash;
1008
1009   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1010   g_return_val_if_fail (resource_path != NULL, 0);
1011   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1012
1013   tmp_error = NULL;
1014
1015   data = g_resources_lookup_data (resource_path, 0, &tmp_error);
1016   if (data == NULL)
1017     {
1018       g_propagate_error (error, tmp_error);
1019       return 0;
1020     }
1021
1022   g_free (builder->priv->filename);
1023   g_free (builder->priv->resource_prefix);
1024   builder->priv->filename = g_strdup (".");
1025
1026   slash = strrchr (resource_path, '/');
1027   if (slash != NULL)
1028     builder->priv->resource_prefix =
1029       g_strndup (resource_path, slash - resource_path + 1);
1030   else
1031     builder->priv->resource_prefix =
1032       g_strdup ("/");
1033
1034   filename_for_errors = g_strconcat ("<resource>", resource_path, NULL);
1035
1036   _gtk_builder_parser_parse_buffer (builder, filename_for_errors,
1037                                     g_bytes_get_data (data, NULL), g_bytes_get_size (data),
1038                                     NULL,
1039                                     &tmp_error);
1040
1041   g_free (filename_for_errors);
1042   g_bytes_unref (data);
1043
1044   if (tmp_error != NULL)
1045     {
1046       g_propagate_error (error, tmp_error);
1047       return 0;
1048     }
1049
1050   return 1;
1051 }
1052
1053 /**
1054  * gtk_builder_add_objects_from_resource:
1055  * @builder: a #GtkBuilder
1056  * @resource_path: the path of the resource file to parse
1057  * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
1058  * @error: (allow-none): return location for an error, or %NULL
1059  *
1060  * Parses a resource file containing a <link linkend="BUILDER-UI">GtkBuilder
1061  * UI definition</link> building only the requested objects and merges
1062  * them with the current contents of @builder.
1063  *
1064  * Upon errors 0 will be returned and @error will be assigned a
1065  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR
1066  * domain.
1067  *
1068  * <note><para>
1069  * If you are adding an object that depends on an object that is not
1070  * its child (for instance a #GtkTreeView that depends on its
1071  * #GtkTreeModel), you have to explicitely list all of them in @object_ids.
1072  * </para></note>
1073  *
1074  * Returns: A positive value on success, 0 if an error occurred
1075  *
1076  * Since: 3.4
1077  **/
1078 guint
1079 gtk_builder_add_objects_from_resource (GtkBuilder   *builder,
1080                                        const gchar  *resource_path,
1081                                        gchar       **object_ids,
1082                                        GError      **error)
1083 {
1084   GError *tmp_error;
1085   GBytes *data;
1086   char *filename_for_errors;
1087   char *slash;
1088
1089   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1090   g_return_val_if_fail (resource_path != NULL, 0);
1091   g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0);
1092   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1093
1094   tmp_error = NULL;
1095
1096   data = g_resources_lookup_data (resource_path, 0, &tmp_error);
1097   if (data == NULL)
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 (".");
1106
1107   slash = strrchr (resource_path, '/');
1108   if (slash != NULL)
1109     builder->priv->resource_prefix =
1110       g_strndup (resource_path, slash - resource_path + 1);
1111   else
1112     builder->priv->resource_prefix =
1113       g_strdup ("/");
1114
1115   filename_for_errors = g_strconcat ("<resource>", resource_path, NULL);
1116
1117   _gtk_builder_parser_parse_buffer (builder, filename_for_errors,
1118                                     g_bytes_get_data (data, NULL), g_bytes_get_size (data),
1119                                     object_ids,
1120                                     &tmp_error);
1121   g_free (filename_for_errors);
1122   g_bytes_unref (data);
1123
1124   if (tmp_error != NULL)
1125     {
1126       g_propagate_error (error, tmp_error);
1127       return 0;
1128     }
1129
1130   return 1;
1131 }
1132
1133 /**
1134  * gtk_builder_add_from_string:
1135  * @builder: a #GtkBuilder
1136  * @buffer: the string to parse
1137  * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
1138  * @error: (allow-none): return location for an error, or %NULL
1139  *
1140  * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder 
1141  * UI definition</link> and merges it with the current contents of @builder. 
1142  *
1143  * Upon errors 0 will be returned and @error will be assigned a
1144  * #GError from the #GTK_BUILDER_ERROR or #G_MARKUP_ERROR domain.
1145  *
1146  * Returns: A positive value on success, 0 if an error occurred
1147  *
1148  * Since: 2.12
1149  **/
1150 guint
1151 gtk_builder_add_from_string (GtkBuilder   *builder,
1152                              const gchar  *buffer,
1153                              gsize         length,
1154                              GError      **error)
1155 {
1156   GError *tmp_error;
1157
1158   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1159   g_return_val_if_fail (buffer != NULL, 0);
1160   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1161
1162   tmp_error = NULL;
1163
1164   g_free (builder->priv->filename);
1165   g_free (builder->priv->resource_prefix);
1166   builder->priv->filename = g_strdup (".");
1167   builder->priv->resource_prefix = NULL;
1168
1169   _gtk_builder_parser_parse_buffer (builder, "<input>",
1170                                     buffer, length,
1171                                     NULL,
1172                                     &tmp_error);
1173   if (tmp_error != NULL)
1174     {
1175       g_propagate_error (error, tmp_error);
1176       return 0;
1177     }
1178
1179   return 1;
1180 }
1181
1182 /**
1183  * gtk_builder_add_objects_from_string:
1184  * @builder: a #GtkBuilder
1185  * @buffer: the string to parse
1186  * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
1187  * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
1188  * @error: (allow-none): return location for an error, or %NULL
1189  *
1190  * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder 
1191  * UI definition</link> building only the requested objects and merges
1192  * them with the current contents of @builder. 
1193  *
1194  * Upon errors 0 will be returned and @error will be assigned a
1195  * #GError from the #GTK_BUILDER_ERROR or #G_MARKUP_ERROR domain.
1196  * 
1197  * <note><para>
1198  * If you are adding an object that depends on an object that is not 
1199  * its child (for instance a #GtkTreeView that depends on its
1200  * #GtkTreeModel), you have to explicitely list all of them in @object_ids. 
1201  * </para></note>
1202  *
1203  * Returns: A positive value on success, 0 if an error occurred
1204  *
1205  * Since: 2.14
1206  **/
1207 guint
1208 gtk_builder_add_objects_from_string (GtkBuilder   *builder,
1209                                      const gchar  *buffer,
1210                                      gsize         length,
1211                                      gchar       **object_ids,
1212                                      GError      **error)
1213 {
1214   GError *tmp_error;
1215
1216   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1217   g_return_val_if_fail (buffer != NULL, 0);
1218   g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0);
1219   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1220
1221   tmp_error = NULL;
1222
1223   g_free (builder->priv->filename);
1224   g_free (builder->priv->resource_prefix);
1225   builder->priv->filename = g_strdup (".");
1226   builder->priv->resource_prefix = NULL;
1227
1228   _gtk_builder_parser_parse_buffer (builder, "<input>",
1229                                     buffer, length,
1230                                     object_ids,
1231                                     &tmp_error);
1232
1233   if (tmp_error != NULL)
1234     {
1235       g_propagate_error (error, tmp_error);
1236       return 0;
1237     }
1238
1239   return 1;
1240 }
1241
1242 /**
1243  * gtk_builder_get_object:
1244  * @builder: a #GtkBuilder
1245  * @name: name of object to get
1246  *
1247  * Gets the object named @name. Note that this function does not
1248  * increment the reference count of the returned object. 
1249  *
1250  * Return value: (transfer none): the object named @name or %NULL if
1251  *    it could not be found in the object tree.
1252  *
1253  * Since: 2.12
1254  **/
1255 GObject *
1256 gtk_builder_get_object (GtkBuilder  *builder,
1257                         const gchar *name)
1258 {
1259   g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
1260   g_return_val_if_fail (name != NULL, NULL);
1261
1262   return g_hash_table_lookup (builder->priv->objects, name);
1263 }
1264
1265 static void
1266 object_add_to_list (gchar    *object_id,
1267                     GObject  *object,
1268                     GSList  **list)
1269 {
1270   *list = g_slist_prepend (*list, object);
1271 }
1272
1273 /**
1274  * gtk_builder_get_objects:
1275  * @builder: a #GtkBuilder
1276  *
1277  * Gets all objects that have been constructed by @builder. Note that 
1278  * this function does not increment the reference counts of the returned
1279  * objects.
1280  *
1281  * Return value: (element-type GObject) (transfer container): a newly-allocated #GSList containing all the objects
1282  *   constructed by the #GtkBuilder instance. It should be freed by
1283  *   g_slist_free()
1284  *
1285  * Since: 2.12
1286  **/
1287 GSList *
1288 gtk_builder_get_objects (GtkBuilder *builder)
1289 {
1290   GSList *objects = NULL;
1291
1292   g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
1293
1294   g_hash_table_foreach (builder->priv->objects, (GHFunc)object_add_to_list, &objects);
1295
1296   return g_slist_reverse (objects);
1297 }
1298
1299 /**
1300  * gtk_builder_set_translation_domain:
1301  * @builder: a #GtkBuilder
1302  * @domain: (allow-none): the translation domain or %NULL
1303  *
1304  * Sets the translation domain of @builder. 
1305  * See #GtkBuilder:translation-domain.
1306  *
1307  * Since: 2.12
1308  **/
1309 void
1310 gtk_builder_set_translation_domain (GtkBuilder  *builder,
1311                                     const gchar *domain)
1312 {
1313   gchar *new_domain;
1314     
1315   g_return_if_fail (GTK_IS_BUILDER (builder));
1316
1317   new_domain = g_strdup (domain);
1318   g_free (builder->priv->domain);
1319   builder->priv->domain = new_domain;
1320
1321   g_object_notify (G_OBJECT (builder), "translation-domain");
1322 }
1323
1324 /**
1325  * gtk_builder_get_translation_domain:
1326  * @builder: a #GtkBuilder
1327  *
1328  * Gets the translation domain of @builder.
1329  *
1330  * Return value: the translation domain. This string is owned
1331  * by the builder object and must not be modified or freed.
1332  *
1333  * Since: 2.12
1334  **/
1335 const gchar *
1336 gtk_builder_get_translation_domain (GtkBuilder *builder)
1337 {
1338   g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
1339
1340   return builder->priv->domain;
1341 }
1342
1343 typedef struct {
1344   GModule *module;
1345   gpointer data;
1346 } connect_args;
1347
1348 static void
1349 gtk_builder_connect_signals_default (GtkBuilder    *builder,
1350                                      GObject       *object,
1351                                      const gchar   *signal_name,
1352                                      const gchar   *handler_name,
1353                                      GObject       *connect_object,
1354                                      GConnectFlags  flags,
1355                                      gpointer       user_data)
1356 {
1357   GCallback func;
1358   connect_args *args = (connect_args*)user_data;
1359   
1360   if (!g_module_symbol (args->module, handler_name, (gpointer)&func))
1361     {
1362       g_warning ("Could not find signal handler '%s'", handler_name);
1363       return;
1364     }
1365
1366   if (connect_object)
1367     g_signal_connect_object (object, signal_name, func, connect_object, flags);
1368   else
1369     g_signal_connect_data (object, signal_name, func, args->data, NULL, flags);
1370 }
1371
1372
1373 /**
1374  * gtk_builder_connect_signals:
1375  * @builder: a #GtkBuilder
1376  * @user_data: a pointer to a structure sent in as user data to all signals
1377  *
1378  * This method is a simpler variation of gtk_builder_connect_signals_full().
1379  * It uses #GModule's introspective features (by opening the module %NULL) 
1380  * to look at the application's symbol table. From here it tries to match
1381  * the signal handler names given in the interface description with
1382  * symbols in the application and connects the signals. Note that this
1383  * function can only be called once, subsequent calls will do nothing.
1384  * 
1385  * Note that this function will not work correctly if #GModule is not
1386  * supported on the platform.
1387  *
1388  * When compiling applications for Windows, you must declare signal callbacks
1389  * with #G_MODULE_EXPORT, or they will not be put in the symbol table.
1390  * On Linux and Unices, this is not necessary; applications should instead
1391  * be compiled with the -Wl,--export-dynamic CFLAGS, and linked against
1392  * gmodule-export-2.0.
1393  *
1394  * Since: 2.12
1395  **/
1396 void
1397 gtk_builder_connect_signals (GtkBuilder *builder,
1398                              gpointer    user_data)
1399 {
1400   connect_args *args;
1401   
1402   g_return_if_fail (GTK_IS_BUILDER (builder));
1403   
1404   if (!g_module_supported ())
1405     g_error ("gtk_builder_connect_signals() requires working GModule");
1406
1407   args = g_slice_new0 (connect_args);
1408   args->module = g_module_open (NULL, G_MODULE_BIND_LAZY);
1409   args->data = user_data;
1410   
1411   gtk_builder_connect_signals_full (builder,
1412                                     gtk_builder_connect_signals_default,
1413                                     args);
1414   g_module_close (args->module);
1415
1416   g_slice_free (connect_args, args);
1417 }
1418
1419 /**
1420  * GtkBuilderConnectFunc:
1421  * @builder: a #GtkBuilder
1422  * @object: object to connect a signal to
1423  * @signal_name: name of the signal
1424  * @handler_name: name of the handler
1425  * @connect_object: a #GObject, if non-%NULL, use g_signal_connect_object()
1426  * @flags: #GConnectFlags to use
1427  * @user_data: user data
1428  *
1429  * This is the signature of a function used to connect signals.  It is used
1430  * by the gtk_builder_connect_signals() and gtk_builder_connect_signals_full()
1431  * methods.  It is mainly intended for interpreted language bindings, but
1432  * could be useful where the programmer wants more control over the signal
1433  * connection process. Note that this function can only be called once,
1434  * subsequent calls will do nothing.
1435  *
1436  * Since: 2.12
1437  */
1438
1439 /**
1440  * gtk_builder_connect_signals_full:
1441  * @builder: a #GtkBuilder
1442  * @func: (scope call): the function used to connect the signals
1443  * @user_data: arbitrary data that will be passed to the connection function
1444  *
1445  * This function can be thought of the interpreted language binding
1446  * version of gtk_builder_connect_signals(), except that it does not
1447  * require GModule to function correctly.
1448  *
1449  * Since: 2.12
1450  */
1451 void
1452 gtk_builder_connect_signals_full (GtkBuilder            *builder,
1453                                   GtkBuilderConnectFunc  func,
1454                                   gpointer               user_data)
1455 {
1456   GSList *l;
1457   GObject *object;
1458   GObject *connect_object;
1459   
1460   g_return_if_fail (GTK_IS_BUILDER (builder));
1461   g_return_if_fail (func != NULL);
1462   
1463   if (!builder->priv->signals)
1464     return;
1465
1466   builder->priv->signals = g_slist_reverse (builder->priv->signals);
1467   for (l = builder->priv->signals; l; l = l->next)
1468     {
1469       SignalInfo *signal = (SignalInfo*)l->data;
1470
1471       g_assert (signal != NULL);
1472       g_assert (signal->name != NULL);
1473
1474       object = g_hash_table_lookup (builder->priv->objects,
1475                                     signal->object_name);
1476       g_assert (object != NULL);
1477
1478       connect_object = NULL;
1479       
1480       if (signal->connect_object_name)
1481         {
1482           connect_object = g_hash_table_lookup (builder->priv->objects,
1483                                                 signal->connect_object_name);
1484           if (!connect_object)
1485               g_warning ("Could not lookup object %s on signal %s of object %s",
1486                          signal->connect_object_name, signal->name,
1487                          signal->object_name);
1488         }
1489                                                   
1490       func (builder, object, signal->name, signal->handler, 
1491             connect_object, signal->flags, user_data);
1492     }
1493
1494   g_slist_foreach (builder->priv->signals, (GFunc)_free_signal_info, NULL);
1495   g_slist_free (builder->priv->signals);
1496   builder->priv->signals = NULL;
1497 }
1498
1499 /**
1500  * gtk_builder_value_from_string:
1501  * @builder: a #GtkBuilder
1502  * @pspec: the #GParamSpec for the property
1503  * @string: the string representation of the value
1504  * @value: (out): the #GValue to store the result in
1505  * @error: (allow-none): return location for an error, or %NULL
1506  *
1507  * This function demarshals a value from a string. This function
1508  * calls g_value_init() on the @value argument, so it need not be
1509  * initialised beforehand.
1510  *
1511  * This function can handle char, uchar, boolean, int, uint, long,
1512  * ulong, enum, flags, float, double, string, #GdkColor, #GdkRGBA and
1513  * #GtkAdjustment type values. Support for #GtkWidget type values is
1514  * still to come.
1515  *
1516  * Upon errors %FALSE will be returned and @error will be assigned a
1517  * #GError from the #GTK_BUILDER_ERROR domain.
1518  *
1519  * Returns: %TRUE on success
1520  *
1521  * Since: 2.12
1522  */
1523 gboolean
1524 gtk_builder_value_from_string (GtkBuilder   *builder,
1525                                GParamSpec   *pspec,
1526                                const gchar  *string,
1527                                GValue       *value,
1528                                GError      **error)
1529 {
1530   g_return_val_if_fail (GTK_IS_BUILDER (builder), FALSE);
1531   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
1532   g_return_val_if_fail (string != NULL, FALSE);
1533   g_return_val_if_fail (value != NULL, FALSE);
1534   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1535
1536   /*
1537    * GParamSpecUnichar has the internal type G_TYPE_UINT,
1538    * so we cannot handle this in the switch, do it separately
1539    */
1540   if (G_IS_PARAM_SPEC_UNICHAR (pspec))
1541     {
1542       gunichar c;
1543       g_value_init (value, G_TYPE_UINT);
1544       c = g_utf8_get_char_validated (string, strlen (string));
1545       if (c > 0)
1546         g_value_set_uint (value, c);
1547       return TRUE;
1548     }
1549
1550   /*
1551    * GParamSpecVariant can specify a GVariantType which can help with
1552    * parsing, so we need to take care of that here.
1553    */
1554   if (G_IS_PARAM_SPEC_VARIANT (pspec))
1555     {
1556       GParamSpecVariant *variant_pspec = G_PARAM_SPEC_VARIANT (pspec);
1557       const GVariantType *type;
1558       GVariant *variant;
1559
1560       g_value_init (value, G_TYPE_VARIANT);
1561
1562       /* The GVariant parser doesn't deal with indefinite types */
1563       if (g_variant_type_is_definite (variant_pspec->type))
1564         type = variant_pspec->type;
1565       else
1566         type = NULL;
1567
1568       variant = g_variant_parse (type, string, NULL, NULL, error);
1569       if (variant == NULL)
1570         return FALSE;
1571       g_value_take_variant (value, variant);
1572       return TRUE;
1573     }
1574
1575   return gtk_builder_value_from_string_type (builder,
1576                                              G_PARAM_SPEC_VALUE_TYPE (pspec),
1577                                              string, value, error);
1578 }
1579
1580 /**
1581  * gtk_builder_value_from_string_type:
1582  * @builder: a #GtkBuilder
1583  * @type: the #GType of the value
1584  * @string: the string representation of the value
1585  * @value: (out): the #GValue to store the result in
1586  * @error: (allow-none): return location for an error, or %NULL
1587  *
1588  * Like gtk_builder_value_from_string(), this function demarshals 
1589  * a value from a string, but takes a #GType instead of #GParamSpec.
1590  * This function calls g_value_init() on the @value argument, so it 
1591  * need not be initialised beforehand.
1592  *
1593  * Upon errors %FALSE will be returned and @error will be assigned a
1594  * #GError from the #GTK_BUILDER_ERROR domain.
1595  *
1596  * Returns: %TRUE on success
1597  *
1598  * Since: 2.12
1599  */
1600 gboolean
1601 gtk_builder_value_from_string_type (GtkBuilder   *builder,
1602                                     GType         type,
1603                                     const gchar  *string,
1604                                     GValue       *value,
1605                                     GError      **error)
1606 {
1607   gboolean ret = TRUE;
1608
1609   g_return_val_if_fail (type != G_TYPE_INVALID, FALSE);
1610   g_return_val_if_fail (string != NULL, FALSE);
1611   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1612
1613   g_value_init (value, type);
1614
1615   switch (G_TYPE_FUNDAMENTAL (type))
1616     {
1617     case G_TYPE_CHAR:
1618       g_value_set_schar (value, string[0]);
1619       break;
1620     case G_TYPE_UCHAR:
1621       g_value_set_uchar (value, (guchar)string[0]);
1622       break;
1623     case G_TYPE_BOOLEAN:
1624       {
1625         gboolean b;
1626
1627         if (!_gtk_builder_boolean_from_string (string, &b, error))
1628           {
1629             ret = FALSE;
1630             break;
1631           }
1632         g_value_set_boolean (value, b);
1633         break;
1634       }
1635     case G_TYPE_INT:
1636     case G_TYPE_LONG:
1637       {
1638         long l;
1639         gchar *endptr = NULL;
1640         errno = 0;
1641         l = g_ascii_strtoll (string, &endptr, 0);
1642         if (errno || endptr == string)
1643           {
1644             g_set_error (error,
1645                          GTK_BUILDER_ERROR,
1646                          GTK_BUILDER_ERROR_INVALID_VALUE,
1647                          "Could not parse integer `%s'",
1648                          string);
1649             ret = FALSE;
1650             break;
1651           }
1652         if (G_VALUE_HOLDS_INT (value))
1653           g_value_set_int (value, l);
1654         else
1655           g_value_set_long (value, l);
1656         break;
1657       }
1658     case G_TYPE_UINT:
1659     case G_TYPE_ULONG:
1660       {
1661         gulong ul;
1662         gchar *endptr = NULL;
1663         errno = 0;
1664         ul = g_ascii_strtoull (string, &endptr, 0);
1665         if (errno || endptr == string)
1666           {
1667             g_set_error (error,
1668                          GTK_BUILDER_ERROR,
1669                          GTK_BUILDER_ERROR_INVALID_VALUE,
1670                          "Could not parse unsigned integer `%s'",
1671                          string);
1672             ret = FALSE;
1673             break;
1674           }
1675         if (G_VALUE_HOLDS_UINT (value))
1676           g_value_set_uint (value, ul);
1677         else 
1678           g_value_set_ulong (value, ul);
1679         break;
1680       }
1681     case G_TYPE_ENUM:
1682       {
1683         gint enum_value;
1684         if (!_gtk_builder_enum_from_string (type, string, &enum_value, error))
1685           {
1686             ret = FALSE;
1687             break;
1688           }
1689         g_value_set_enum (value, enum_value);
1690         break;
1691       }
1692     case G_TYPE_FLAGS:
1693       {
1694         guint flags_value;
1695
1696         if (!_gtk_builder_flags_from_string (type, string, &flags_value, error))
1697           {
1698             ret = FALSE;
1699             break;
1700           }
1701         g_value_set_flags (value, flags_value);
1702         break;
1703       }
1704     case G_TYPE_FLOAT:
1705     case G_TYPE_DOUBLE:
1706       {
1707         gdouble d;
1708         gchar *endptr = NULL;
1709         errno = 0;
1710         d = g_ascii_strtod (string, &endptr);
1711         if (errno || endptr == string)
1712           {
1713             g_set_error (error,
1714                          GTK_BUILDER_ERROR,
1715                          GTK_BUILDER_ERROR_INVALID_VALUE,
1716                          "Could not parse double `%s'",
1717                          string);
1718             ret = FALSE;
1719             break;
1720           }
1721         if (G_VALUE_HOLDS_FLOAT (value))
1722           g_value_set_float (value, d);
1723         else
1724           g_value_set_double (value, d);
1725         break;
1726       }
1727     case G_TYPE_STRING:
1728       g_value_set_string (value, string);
1729       break;
1730     case G_TYPE_VARIANT:
1731       {
1732         GVariant *variant;
1733
1734         variant = g_variant_parse (NULL, string, NULL, NULL, error);
1735         if (value != NULL)
1736           g_value_take_variant (value, variant);
1737         else
1738           ret = FALSE;
1739       }
1740       break;
1741     case G_TYPE_BOXED:
1742       if (G_VALUE_HOLDS (value, GDK_TYPE_COLOR))
1743         {
1744           GdkColor color = { 0, };
1745
1746           if (gdk_color_parse (string, &color))
1747             g_value_set_boxed (value, &color);
1748           else
1749             {
1750               g_set_error (error,
1751                            GTK_BUILDER_ERROR,
1752                            GTK_BUILDER_ERROR_INVALID_VALUE,
1753                            "Could not parse color `%s'",
1754                            string);
1755               ret = FALSE;
1756             }
1757         }
1758       else if (G_VALUE_HOLDS (value, GDK_TYPE_RGBA))
1759         {
1760           GdkRGBA rgba = { 0 };
1761
1762           if (gdk_rgba_parse (&rgba, string))
1763             g_value_set_boxed (value, &rgba);
1764           else
1765             {
1766               g_set_error (error,
1767                            GTK_BUILDER_ERROR,
1768                            GTK_BUILDER_ERROR_INVALID_VALUE,
1769                            "Could not parse RGBA color '%s'",
1770                            string);
1771               ret = FALSE;
1772             }
1773         }
1774       else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
1775         {
1776           gchar **vector = g_strsplit (string, "\n", 0);
1777           g_value_take_boxed (value, vector);
1778         }
1779       else
1780         {
1781           g_set_error (error,
1782                        GTK_BUILDER_ERROR,
1783                        GTK_BUILDER_ERROR_INVALID_VALUE,
1784                        "Could not parse '%s' as a %s",
1785                        string, G_VALUE_TYPE_NAME (value));
1786           ret = FALSE;
1787         }
1788       break;
1789     case G_TYPE_OBJECT:
1790       if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF))
1791         {
1792           gchar *filename;
1793           GError *tmp_error = NULL;
1794           GdkPixbuf *pixbuf = NULL;
1795        
1796           if (gtk_builder_get_object (builder, string))
1797             {
1798               g_set_error (error,
1799                            GTK_BUILDER_ERROR,
1800                            GTK_BUILDER_ERROR_INVALID_VALUE,
1801                            "Could not load image '%s': "
1802                            " '%s' is already used as object id",
1803                            string, string);
1804               return FALSE;
1805             }
1806
1807           filename = _gtk_builder_get_resource_path (builder, string);
1808           if (filename != NULL)
1809             {
1810               GInputStream *stream = g_resources_open_stream (filename, 0, &tmp_error);
1811               if (stream != NULL)
1812                 {
1813                   pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &tmp_error);
1814                   g_object_unref (stream);
1815                 }
1816             }
1817           else
1818             {
1819               filename = _gtk_builder_get_absolute_filename (builder, string);
1820               pixbuf = gdk_pixbuf_new_from_file (filename, &tmp_error);
1821             }
1822
1823           if (pixbuf == NULL)
1824             {
1825               GtkIconTheme *theme;
1826
1827               g_warning ("Could not load image '%s': %s", 
1828                          string, tmp_error->message);
1829               g_error_free (tmp_error);
1830
1831               /* fall back to a missing image */
1832               theme = gtk_icon_theme_get_default ();
1833               pixbuf = gtk_icon_theme_load_icon (theme, 
1834                                                  GTK_STOCK_MISSING_IMAGE,
1835                                                  16,
1836                                                  GTK_ICON_LOOKUP_USE_BUILTIN,
1837                                                  NULL);
1838             }
1839  
1840           if (pixbuf)
1841             {
1842               g_value_set_object (value, pixbuf);
1843               g_object_unref (G_OBJECT (pixbuf));
1844             }
1845
1846           g_free (filename);
1847
1848           ret = TRUE;
1849         }
1850       else
1851         ret = FALSE;
1852       break;
1853     default:
1854       ret = FALSE;
1855       break;
1856     }
1857  
1858   /* Catch unassigned error for object types as well as any unsupported types.
1859    * While parsing GtkBuilder; object types are deserialized
1860    * without calling gtk_builder_value_from_string_type().
1861    */
1862   if (!ret && error && *error == NULL) 
1863     g_set_error (error,
1864                  GTK_BUILDER_ERROR,
1865                  GTK_BUILDER_ERROR_INVALID_VALUE,
1866                  "Unsupported GType `%s'", g_type_name (type));
1867
1868   return ret;
1869 }
1870
1871 gboolean
1872 _gtk_builder_enum_from_string (GType         type, 
1873                                const gchar  *string,
1874                                gint         *enum_value,
1875                                GError      **error)
1876 {
1877   GEnumClass *eclass;
1878   GEnumValue *ev;
1879   gchar *endptr;
1880   gint value;
1881   gboolean ret;
1882   
1883   g_return_val_if_fail (G_TYPE_IS_ENUM (type), FALSE);
1884   g_return_val_if_fail (string != NULL, FALSE);
1885   
1886   ret = TRUE;
1887
1888   endptr = NULL;
1889   errno = 0;
1890   value = g_ascii_strtoull (string, &endptr, 0);
1891   if (errno == 0 && endptr != string) /* parsed a number */
1892     *enum_value = value;
1893   else
1894     {
1895       eclass = g_type_class_ref (type);
1896       ev = g_enum_get_value_by_name (eclass, string);
1897       if (!ev)
1898         ev = g_enum_get_value_by_nick (eclass, string);
1899
1900       if (ev)
1901         *enum_value = ev->value;
1902       else
1903         {
1904           g_set_error (error,
1905                        GTK_BUILDER_ERROR,
1906                        GTK_BUILDER_ERROR_INVALID_VALUE,
1907                        "Could not parse enum: `%s'",
1908                        string);
1909           ret = FALSE;
1910         }
1911       
1912       g_type_class_unref (eclass);
1913     }
1914   
1915   return ret;
1916 }
1917
1918 gboolean
1919 _gtk_builder_flags_from_string (GType         type, 
1920                                 const gchar  *string,
1921                                 guint        *flags_value,
1922                                 GError      **error)
1923 {
1924   GFlagsClass *fclass;
1925   gchar *endptr, *prevptr;
1926   guint i, j, value;
1927   gchar *flagstr;
1928   GFlagsValue *fv;
1929   const gchar *flag;
1930   gunichar ch;
1931   gboolean eos, ret;
1932
1933   g_return_val_if_fail (G_TYPE_IS_FLAGS (type), FALSE);
1934   g_return_val_if_fail (string != 0, FALSE);
1935
1936   ret = TRUE;
1937
1938   endptr = NULL;
1939   errno = 0;
1940   value = g_ascii_strtoull (string, &endptr, 0);
1941   if (errno == 0 && endptr != string) /* parsed a number */
1942     *flags_value = value;
1943   else
1944     {
1945       fclass = g_type_class_ref (type);
1946
1947       flagstr = g_strdup (string);
1948       for (value = i = j = 0; ; i++)
1949         {
1950           
1951           eos = flagstr[i] == '\0';
1952           
1953           if (!eos && flagstr[i] != '|')
1954             continue;
1955           
1956           flag = &flagstr[j];
1957           endptr = &flagstr[i];
1958           
1959           if (!eos)
1960             {
1961               flagstr[i++] = '\0';
1962               j = i;
1963             }
1964           
1965           /* trim spaces */
1966           for (;;)
1967             {
1968               ch = g_utf8_get_char (flag);
1969               if (!g_unichar_isspace (ch))
1970                 break;
1971               flag = g_utf8_next_char (flag);
1972             }
1973           
1974           while (endptr > flag)
1975             {
1976               prevptr = g_utf8_prev_char (endptr);
1977               ch = g_utf8_get_char (prevptr);
1978               if (!g_unichar_isspace (ch))
1979                 break;
1980               endptr = prevptr;
1981             }
1982           
1983           if (endptr > flag)
1984             {
1985               *endptr = '\0';
1986               fv = g_flags_get_value_by_name (fclass, flag);
1987               
1988               if (!fv)
1989                 fv = g_flags_get_value_by_nick (fclass, flag);
1990               
1991               if (fv)
1992                 value |= fv->value;
1993               else
1994                 {
1995                   g_set_error (error,
1996                                GTK_BUILDER_ERROR,
1997                                GTK_BUILDER_ERROR_INVALID_VALUE,
1998                                "Unknown flag: `%s'",
1999                                flag);
2000                   ret = FALSE;
2001                   break;
2002                 }
2003             }
2004           
2005           if (eos)
2006             {
2007               *flags_value = value;
2008               break;
2009             }
2010         }
2011       
2012       g_free (flagstr);
2013       
2014       g_type_class_unref (fclass);
2015     }
2016
2017   return ret;
2018 }
2019
2020 /**
2021  * gtk_builder_get_type_from_name:
2022  * @builder: a #GtkBuilder
2023  * @type_name: type name to lookup
2024  *
2025  * Looks up a type by name, using the virtual function that 
2026  * #GtkBuilder has for that purpose. This is mainly used when
2027  * implementing the #GtkBuildable interface on a type.
2028  *
2029  * Returns: the #GType found for @type_name or #G_TYPE_INVALID 
2030  *   if no type was found
2031  *
2032  * Since: 2.12
2033  */
2034 GType
2035 gtk_builder_get_type_from_name (GtkBuilder  *builder, 
2036                                 const gchar *type_name)
2037 {
2038   g_return_val_if_fail (GTK_IS_BUILDER (builder), G_TYPE_INVALID);
2039   g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
2040
2041   return GTK_BUILDER_GET_CLASS (builder)->get_type_from_name (builder, type_name);
2042 }
2043
2044 GQuark
2045 gtk_builder_error_quark (void)
2046 {
2047   return g_quark_from_static_string ("gtk-builder-error-quark");
2048 }
2049
2050 gchar *
2051 _gtk_builder_get_resource_path (GtkBuilder *builder, const gchar *string)
2052 {
2053   if (g_str_has_prefix (string, "resource:///"))
2054     return g_uri_unescape_string (string + 11, "/");
2055
2056   if (g_path_is_absolute (string) ||
2057       builder->priv->resource_prefix == NULL)
2058     return NULL;
2059
2060   return g_build_path ("/", builder->priv->resource_prefix, string, NULL);
2061 }
2062
2063 gchar *
2064 _gtk_builder_get_absolute_filename (GtkBuilder *builder, const gchar *string)
2065 {
2066   gchar *filename;
2067   gchar *dirname = NULL;
2068   
2069   if (g_path_is_absolute (string))
2070     return g_strdup (string);
2071
2072   if (builder->priv->filename &&
2073       strcmp (builder->priv->filename, ".") != 0) 
2074     {
2075       dirname = g_path_get_dirname (builder->priv->filename);
2076
2077       if (strcmp (dirname, ".") == 0)
2078         {
2079           g_free (dirname);
2080           dirname = g_get_current_dir ();
2081         }
2082     }
2083   else
2084     dirname = g_get_current_dir ();
2085     
2086   filename = g_build_filename (dirname, string, NULL);
2087   g_free (dirname);
2088   
2089   return filename;
2090 }