]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkbuilder.c
More documentation reshuffling
[~andy/gtk] / gtk / gtkbuilder.c
index 9dff20e38a03eea0baa3c2d9f28eeb6a53ca4e21..97b0053da3c3f127561d8fa67ac24202a00f4972 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+/**
+ * SECTION:gtkbuilder
+ * @Short_description: Build an interface from an XML UI definition
+ * @Title: GtkBuilder
+ *
+ * A GtkBuilder is an auxiliary object that reads textual descriptions
+ * of a user interface and instantiates the described objects. To pass a
+ * description to a GtkBuilder, call gtk_builder_add_from_file() or
+ * gtk_builder_add_from_string(). These functions can be called multiple
+ * times; the builder merges the content of all descriptions.
+ *
+ * A GtkBuilder holds a reference to all objects that it has constructed
+ * and drops these references when it is finalized. This finalization can
+ * cause the destruction of non-widget objects or widgets which are not
+ * contained in a toplevel window. For toplevel windows constructed by a
+ * builder, it is the responsibility of the user to call gtk_widget_destroy()
+ * to get rid of them and all the widgets they contain.
+ *
+ * The functions gtk_builder_get_object() and gtk_builder_get_objects()
+ * can be used to access the widgets in the interface by the names assigned
+ * to them inside the UI description. Toplevel windows returned by these
+ * functions will stay around until the user explicitly destroys them
+ * with gtk_widget_destroy(). Other widgets will either be part of a
+ * larger hierarchy constructed by the builder (in which case you should
+ * not have to worry about their lifecycle), or without a parent, in which
+ * case they have to be added to some container to make use of them.
+ * Non-widget objects need to be reffed with g_object_ref() to keep them
+ * beyond the lifespan of the builder.
+ *
+ * The function gtk_builder_connect_signals() and variants thereof can be
+ * used to connect handlers to the named signals in the description.
+ *
+ * <refsect2 id="BUILDER-UI">
+ * <title>GtkBuilder UI Definitions</title>
+ * <para>
+ * GtkBuilder parses textual descriptions of user interfaces which are specified
+ * in an XML format which can be roughly described by the DTD below. We refer to
+ * these descriptions as <firstterm>GtkBuilder UI definitions</firstterm> or
+ * just <firstterm>UI definitions</firstterm> if the context is clear. Do not
+ * confuse GtkBuilder UI Definitions with
+ * <link linkend="XML-UI">GtkUIManager UI Definitions</link>, which are more
+ * limited in scope.
+ * </para>
+ * <programlisting><![CDATA[
+ * <!ELEMENT interface (requires|object)* >
+ * <!ELEMENT object    (property|signal|child|ANY)* >
+ * <!ELEMENT property  PCDATA >
+ * <!ELEMENT signal    EMPTY >
+ * <!ELEMENT requires  EMPTY >
+ * <!ELEMENT child     (object|ANY*) >
+ *
+ * <!ATTLIST interface  domain                     #IMPLIED >
+ * <!ATTLIST object     id                         #REQUIRED
+ *                      class                      #REQUIRED
+ *                      type-func                  #IMPLIED
+ *                      constructor                #IMPLIED >
+ * <!ATTLIST requires   lib                        #REQUIRED
+ *                      version                    #REQUIRED >
+ * <!ATTLIST property   name                       #REQUIRED
+ *                      translatable               #IMPLIED
+ *                      comments               #IMPLIED
+ *                      context                #IMPLIED >
+ * <!ATTLIST signal     name                       #REQUIRED
+ *                      handler                    #REQUIRED
+ *                      after                      #IMPLIED
+ *                      swapped                    #IMPLIED
+ *                      object                     #IMPLIED
+ *                      last_modification_time #IMPLIED >
+ * <!ATTLIST child      type                       #IMPLIED
+ *                      internal-child             #IMPLIED >
+ * ]]></programlisting>
+ * <para>
+ * The toplevel element is &lt;interface&gt;. It optionally takes a "domain"
+ * attribute, which will make the builder look for translated strings using
+ * dgettext() in the domain specified. This can also be done by calling
+ * gtk_builder_set_translation_domain() on the builder. Objects are described by
+ * &lt;object&gt; elements, which can contain &lt;property&gt; elements to set
+ * properties, &lt;signal&gt; elements which connect signals to handlers, and
+ * &lt;child&gt; elements, which describe child objects (most often widgets
+ * inside a container, but also e.g. actions in an action group, or columns in a
+ * tree model). A &lt;child&gt; element contains an &lt;object&gt; element which
+ * describes the child object. The target toolkit version(s) are described by
+ * &lt;requires&gt; elements, the "lib" attribute specifies the widget library
+ * in question (currently the only supported value is "gtk+") and the "version"
+ * attribute specifies the target version in the form
+ * "&lt;major&gt;.&lt;minor&gt;". The builder will error out if the version
+ * requirements are not met.
+ *
+ * Typically, the specific kind of object represented by an &lt;object&gt;
+ * element is specified by the "class" attribute. If the type has not been
+ * loaded yet, GTK+ tries to find the <function>_get_type()</function> from the
+ * class name by applying heuristics. This works in most cases, but if
+ * necessary, it is possible to specify the name of the
+ * <function>_get_type()</function> explictly with the "type-func" attribute.
+ * As a special case, GtkBuilder allows to use an object that has been
+ * constructed by a #GtkUIManager in another part of the UI definition by
+ * specifying the id of the #GtkUIManager in the "constructor" attribute and the
+ * name of the object in the "id" attribute.
+ *
+ * Objects must be given a name with the "id" attribute, which allows the
+ * application to retrieve them from the builder with gtk_builder_get_object().
+ * An id is also necessary to use the object as property value in other parts of
+ * the UI definition.
+ * </para>
+ * <note><para>
+ * Prior to 2.20, GtkBuilder was setting the "name" property of constructed widgets to the
+ * "id" attribute. In GTK+ 2.20 or newer, you have to use gtk_buildable_get_name() instead
+ * of gtk_widget_get_name() to obtain the "id", or set the "name" property in your UI
+ * definition.
+ * </para></note>
+ * <para>
+ * Setting properties of objects is pretty straightforward with the
+ * &lt;property&gt; element: the "name" attribute specifies the name of the
+ * property, and the content of the element specifies the value. If the
+ * "translatable" attribute is set to a true value, GTK+ uses gettext() (or
+ * dgettext() if the builder has a translation domain set) to find a translation
+ * for the value. This happens before the value is parsed, so it can be used for
+ * properties of any type, but it is probably most useful for string properties.
+ * It is also possible to specify a context to disambiguate short strings, and
+ * comments which may help the translators.
+ *
+ * GtkBuilder can parse textual representations for the most common property
+ * types: characters, strings, integers, floating-point numbers, booleans
+ * (strings like "TRUE", "t", "yes", "y", "1" are interpreted as %TRUE, strings
+ * like "FALSE, "f", "no", "n", "0" are interpreted as %FALSE), enumerations
+ * (can be specified by their name, nick or integer value), flags (can be
+ * specified by their name, nick, integer value, optionally combined with "|",
+ * e.g. "GTK_VISIBLE|GTK_REALIZED")  and colors (in a format understood by
+ * gdk_color_parse()). Objects can be referred to by their name. Pixbufs can be
+ * specified as a filename of an image file to load. In general, GtkBuilder
+ * allows forward references to objects &mdash; an object doesn't have to be
+ * constructed before it can be referred to. The exception to this rule is that
+ * an object has to be constructed before it can be used as the value of a
+ * construct-only property.
+ *
+ * Signal handlers are set up with the &lt;signal&gt; element. The "name"
+ * attribute specifies the name of the signal, and the "handler" attribute
+ * specifies the function to connect to the signal. By default, GTK+ tries to
+ * find the handler using g_module_symbol(), but this can be changed by passing
+ * a custom #GtkBuilderConnectFunc to gtk_builder_connect_signals_full(). The
+ * remaining attributes, "after", "swapped" and "object", have the same meaning
+ * as the corresponding parameters of the g_signal_connect_object() or
+ * g_signal_connect_data() functions. A "last_modification_time" attribute
+ * is also allowed, but it does not have a meaning to the builder.
+ *
+ * Sometimes it is necessary to refer to widgets which have implicitly been
+ * constructed by GTK+ as part of a composite widget, to set properties on them
+ * or to add further children (e.g. the @vbox of a #GtkDialog). This can be
+ * achieved by setting the "internal-child" propery of the &lt;child&gt; element
+ * to a true value. Note that GtkBuilder still requires an &lt;object&gt;
+ * element for the internal child, even if it has already been constructed.
+ *
+ * A number of widgets have different places where a child can be added (e.g.
+ * tabs vs. page content in notebooks). This can be reflected in a UI definition
+ * by specifying the "type" attribute on a &lt;child&gt;. The possible values
+ * for the "type" attribute are described in the sections describing the
+ * widget-specific portions of UI definitions.
+ * </para>
+ * <example>
+ * <title>A GtkBuilder UI Definition</title>
+ * <programlisting><![CDATA[
+ * <interface>
+ *   <object class="GtkDialog" id="dialog1">
+ *     <child internal-child="vbox">
+ *       <object class="GtkVBox" id="vbox1">
+ *         <property name="border-width">10</property>
+ *         <child internal-child="action_area">
+ *           <object class="GtkHButtonBox" id="hbuttonbox1">
+ *             <property name="border-width">20</property>
+ *             <child>
+ *               <object class="GtkButton" id="ok_button">
+ *                 <property name="label">gtk-ok</property>
+ *                 <property name="use-stock">TRUE</property>
+ *                 <signal name="clicked" handler="ok_button_clicked"/>
+ *               </object>
+ *             </child>
+ *           </object>
+ *         </child>
+ *       </object>
+ *     </child>
+ *   </object>
+ * </interface>
+ * ]]></programlisting>
+ * </example>
+ * <para>
+ * Beyond this general structure, several object classes define their own XML
+ * DTD fragments for filling in the ANY placeholders in the DTD above. Note that
+ * a custom element in a &lt;child&gt; element gets parsed by the custom tag
+ * handler of the parent object, while a custom element in an &lt;object&gt;
+ * element gets parsed by the custom tag handler of the object.
+ *
+ * These XML fragments are explained in the documentation of the respective
+ * objects, see
+ * <link linkend="GtkWidget-BUILDER-UI">GtkWidget</link>,
+ * <link linkend="GtkLabel-BUILDER-UI">GtkLabel</link>,
+ * <link linkend="GtkWindow-BUILDER-UI">GtkWindow</link>,
+ * <link linkend="GtkContainer-BUILDER-UI">GtkContainer</link>,
+ * <link linkend="GtkDialog-BUILDER-UI">GtkDialog</link>,
+ * <link linkend="GtkCellLayout-BUILDER-UI">GtkCellLayout</link>,
+ * <link linkend="GtkColorSelectionDialog-BUILDER-UI">GtkColorSelectionDialog</link>,
+ * <link linkend="GtkFontSelectionDialog-BUILDER-UI">GtkFontSelectionDialog</link>,
+ * <link linkend="GtkExpander-BUILDER-UI">GtkExpander</link>,
+ * <link linkend="GtkFrame-BUILDER-UI">GtkFrame</link>,
+ * <link linkend="GtkListStore-BUILDER-UI">GtkListStore</link>,
+ * <link linkend="GtkTreeStore-BUILDER-UI">GtkTreeStore</link>,
+ * <link linkend="GtkNotebook-BUILDER-UI">GtkNotebook</link>,
+ * <link linkend="GtkSizeGroup-BUILDER-UI">GtkSizeGroup</link>,
+ * <link linkend="GtkTreeView-BUILDER-UI">GtkTreeView</link>,
+ * <link linkend="GtkUIManager-BUILDER-UI">GtkUIManager</link>,
+ * <link linkend="GtkActionGroup-BUILDER-UI">GtkActionGroup</link>.
+ * <link linkend="GtkMenuItem-BUILDER-UI">GtkMenuItem</link>,
+ * <link linkend="GtkAssistant-BUILDER-UI">GtkAssistant</link>,
+ * <link linkend="GtkScale-BUILDER-UI">GtkScale</link>.
+ * </para>
+ * </refsect2>
+ */
+
 #include "config.h"
 #include <errno.h> /* errno */
-#include <stdlib.h> /* strtol, strtoul */
+#include <stdlib.h>
 #include <string.h> /* strlen */
 
 #include "gtkbuilder.h"
 #include "gtkbuildable.h"
 #include "gtkbuilderprivate.h"
+#include "gtkdebug.h"
 #include "gtkmain.h"
 #include "gtkintl.h"
 #include "gtkprivate.h"
 #include "gtkwindow.h"
 #include "gtkicontheme.h"
 #include "gtkstock.h"
-#include "gtkalias.h"
+
 
 static void gtk_builder_class_init     (GtkBuilderClass *klass);
 static void gtk_builder_init           (GtkBuilder      *builder);
@@ -483,7 +701,7 @@ _gtk_builder_construct (GtkBuilder *builder,
         g_object_set_property (obj, param->name, &param->value);
 
 #if G_ENABLE_DEBUG
-      if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+      if (gtk_get_debug_flags () & GTK_DEBUG_BUILDER)
         {
           gchar *str = g_strdup_value_contents ((const GValue*)&param->value);
           g_print ("set %s: %s = %s\n", info->id, param->name, str);
@@ -638,11 +856,15 @@ gtk_builder_new (void)
  * gtk_builder_add_from_file:
  * @builder: a #GtkBuilder
  * @filename: the name of the file to parse
- * @error: return location for an error, or %NULL
+ * @error: (allow-none): return location for an error, or %NULL
  *
  * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder 
  * UI definition</link> and merges it with the current contents of @builder. 
  * 
+ * Upon errors 0 will be returned and @error will be assigned a
+ * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR 
+ * domain.
+ *
  * Returns: A positive value on success, 0 if an error occurred
  *
  * Since: 2.12
@@ -692,12 +914,16 @@ gtk_builder_add_from_file (GtkBuilder   *builder,
  * @builder: a #GtkBuilder
  * @filename: the name of the file to parse
  * @object_ids: nul-terminated array of objects to build
- * @error: return location for an error, or %NULL
+ * @error: (allow-none): return location for an error, or %NULL
  *
  * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder 
  * UI definition</link> building only the requested objects and merges
  * them with the current contents of @builder. 
  *
+ * Upon errors 0 will be returned and @error will be assigned a
+ * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR 
+ * domain.
+ *
  * <note><para>
  * If you are adding an object that depends on an object that is not 
  * its child (for instance a #GtkTreeView that depends on its
@@ -755,11 +981,14 @@ gtk_builder_add_objects_from_file (GtkBuilder   *builder,
  * @builder: a #GtkBuilder
  * @buffer: the string to parse
  * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
- * @error: return location for an error, or %NULL
+ * @error: (allow-none): return location for an error, or %NULL
  *
  * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder 
  * UI definition</link> and merges it with the current contents of @builder. 
  *
+ * Upon errors 0 will be returned and @error will be assigned a
+ * #GError from the #GTK_BUILDER_ERROR or #G_MARKUP_ERROR domain.
+ *
  * Returns: A positive value on success, 0 if an error occurred
  *
  * Since: 2.12
@@ -799,12 +1028,15 @@ gtk_builder_add_from_string (GtkBuilder   *builder,
  * @builder: a #GtkBuilder
  * @buffer: the string to parse
  * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
- * @object_ids: nul-terminated array of objects to build
- * @error: return location for an error, or %NULL
+ * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
+ * @error: (allow-none): return location for an error, or %NULL
  *
  * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder 
  * UI definition</link> building only the requested objects and merges
  * them with the current contents of @builder. 
+ *
+ * Upon errors 0 will be returned and @error will be assigned a
+ * #GError from the #GTK_BUILDER_ERROR or #G_MARKUP_ERROR domain.
  * 
  * <note><para>
  * If you are adding an object that depends on an object that is not 
@@ -857,8 +1089,8 @@ gtk_builder_add_objects_from_string (GtkBuilder   *builder,
  * Gets the object named @name. Note that this function does not
  * increment the reference count of the returned object. 
  *
- * Return value: the object named @name or %NULL if it could not be 
- *    found in the object tree. 
+ * Return value: (transfer none): the object named @name or %NULL if
+ *    it could not be found in the object tree.
  *
  * Since: 2.12
  **/
@@ -888,7 +1120,7 @@ object_add_to_list (gchar    *object_id,
  * this function does not increment the reference counts of the returned
  * objects.
  *
- * Return value: a newly-allocated #GSList containing all the objects
+ * Return value: (element-type GObject) (transfer container): a newly-allocated #GSList containing all the objects
  *   constructed by the #GtkBuilder instance. It should be freed by
  *   g_slist_free()
  *
@@ -909,7 +1141,7 @@ gtk_builder_get_objects (GtkBuilder *builder)
 /**
  * gtk_builder_set_translation_domain:
  * @builder: a #GtkBuilder
- * @domain: the translation domain or %NULL
+ * @domain: (allow-none): the translation domain or %NULL
  *
  * Sets the translation domain of @builder. 
  * See #GtkBuilder:translation-domain.
@@ -1047,7 +1279,7 @@ gtk_builder_connect_signals (GtkBuilder *builder,
 /**
  * gtk_builder_connect_signals_full:
  * @builder: a #GtkBuilder
- * @func: the function used to connect the signals
+ * @func: (scope call): the function used to connect the signals
  * @user_data: arbitrary data that will be passed to the connection function
  *
  * This function can be thought of the interpreted language binding
@@ -1110,7 +1342,7 @@ gtk_builder_connect_signals_full (GtkBuilder            *builder,
  * @pspec: the #GParamSpec for the property
  * @string: the string representation of the value
  * @value: the #GValue to store the result in
- * @error: return location for an error, or %NULL
+ * @error: (allow-none): return location for an error, or %NULL
  *
  * This function demarshals a value from a string. This function
  * calls g_value_init() on the @value argument, so it need not be
@@ -1121,6 +1353,9 @@ gtk_builder_connect_signals_full (GtkBuilder            *builder,
  * #GtkAdjustment type values. Support for #GtkWidget type values is
  * still to come.
  *
+ * Upon errors %FALSE will be returned and @error will be assigned a
+ * #GError from the #GTK_BUILDER_ERROR domain.
+ *
  * Returns: %TRUE on success
  *
  * Since: 2.12
@@ -1163,13 +1398,16 @@ gtk_builder_value_from_string (GtkBuilder   *builder,
  * @type: the #GType of the value
  * @string: the string representation of the value
  * @value: the #GValue to store the result in
- * @error: return location for an error, or %NULL
+ * @error: (allow-none): return location for an error, or %NULL
  *
  * Like gtk_builder_value_from_string(), this function demarshals 
  * a value from a string, but takes a #GType instead of #GParamSpec.
  * This function calls g_value_init() on the @value argument, so it 
  * need not be initialised beforehand.
  *
+ * Upon errors %FALSE will be returned and @error will be assigned a
+ * #GError from the #GTK_BUILDER_ERROR domain.
+ *
  * Returns: %TRUE on success
  *
  * Since: 2.12
@@ -1213,9 +1451,9 @@ gtk_builder_value_from_string_type (GtkBuilder   *builder,
     case G_TYPE_LONG:
       {
         long l;
-        gchar *endptr;
+        gchar *endptr = NULL;
         errno = 0;
-        l = strtol (string, &endptr, 0);
+        l = g_ascii_strtoll (string, &endptr, 0);
         if (errno || endptr == string)
           {
            g_set_error (error,
@@ -1236,9 +1474,9 @@ gtk_builder_value_from_string_type (GtkBuilder   *builder,
     case G_TYPE_ULONG:
       {
         gulong ul;
-        gchar *endptr;
+        gchar *endptr = NULL;
         errno = 0;
-        ul = strtoul (string, &endptr, 0);
+        ul = g_ascii_strtoull (string, &endptr, 0);
         if (errno || endptr == string)
           {
            g_set_error (error,
@@ -1282,7 +1520,7 @@ gtk_builder_value_from_string_type (GtkBuilder   *builder,
     case G_TYPE_DOUBLE:
       {
         gdouble d;
-        gchar *endptr;
+        gchar *endptr = NULL;
         errno = 0;
         d = g_ascii_strtod (string, &endptr);
         if (errno || endptr == string)
@@ -1307,12 +1545,10 @@ gtk_builder_value_from_string_type (GtkBuilder   *builder,
     case G_TYPE_BOXED:
       if (G_VALUE_HOLDS (value, GDK_TYPE_COLOR))
         {
-          GdkColor colour = { 0, };
+          GdkColor color = { 0, };
 
-          if (gdk_color_parse (string, &colour) &&
-              gdk_colormap_alloc_color (gtk_widget_get_default_colormap (),
-                                        &colour, FALSE, TRUE))
-            g_value_set_boxed (value, &colour);
+          if (gdk_color_parse (string, &color))
+            g_value_set_boxed (value, &color);
           else
             {
              g_set_error (error,
@@ -1323,6 +1559,22 @@ gtk_builder_value_from_string_type (GtkBuilder   *builder,
               ret = FALSE;
             }
         }
+      else if (G_VALUE_HOLDS (value, GDK_TYPE_RGBA))
+        {
+          GdkRGBA rgba = { 0 };
+
+          if (gdk_rgba_parse (&rgba, string))
+            g_value_set_boxed (value, &rgba);
+          else
+            {
+              g_set_error (error,
+                           GTK_BUILDER_ERROR,
+                           GTK_BUILDER_ERROR_INVALID_VALUE,
+                           "Could not parse RGBA color '%s'",
+                           string);
+              ret = FALSE;
+            }
+        }
       else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
         {
           gchar **vector = g_strsplit (string, "\n", 0);
@@ -1390,14 +1642,19 @@ gtk_builder_value_from_string_type (GtkBuilder   *builder,
         ret = FALSE;
       break;
     default:
-      g_set_error (error,
-                  GTK_BUILDER_ERROR,
-                  GTK_BUILDER_ERROR_INVALID_VALUE,
-                  "Unsupported GType `%s'",
-                  g_type_name (type));
       ret = FALSE;
       break;
     }
+  /* Catch unassigned error for object types as well as any unsupported types.
+   * While parsing GtkBuilder; object types are deserialized
+   * without calling gtk_builder_value_from_string_type().
+   */
+  if (!ret && error && *error == NULL) 
+    g_set_error (error,
+                GTK_BUILDER_ERROR,
+                GTK_BUILDER_ERROR_INVALID_VALUE,
+                "Unsupported GType `%s'", g_type_name (type));
 
   return ret;
 }
@@ -1419,8 +1676,10 @@ _gtk_builder_enum_from_string (GType         type,
   
   ret = TRUE;
 
-  value = strtoul (string, &endptr, 0);
-  if (endptr != string) /* parsed a number */
+  endptr = NULL;
+  errno = 0;
+  value = g_ascii_strtoull (string, &endptr, 0);
+  if (errno == 0 && endptr != string) /* parsed a number */
     *enum_value = value;
   else
     {
@@ -1466,9 +1725,11 @@ _gtk_builder_flags_from_string (GType         type,
   g_return_val_if_fail (string != 0, FALSE);
 
   ret = TRUE;
-  
-  value = strtoul (string, &endptr, 0);
-  if (endptr != string) /* parsed a number */
+
+  endptr = NULL;
+  errno = 0;
+  value = g_ascii_strtoull (string, &endptr, 0);
+  if (errno == 0 && endptr != string) /* parsed a number */
     *flags_value = value;
   else
     {
@@ -1605,6 +1866,3 @@ _gtk_builder_get_absolute_filename (GtkBuilder *builder, const gchar *string)
   
   return filename;
 }
-
-#define __GTK_BUILDER_C__
-#include "gtkaliasdef.c"