Index: gtk/gtkbuilderprivate.h
===================================================================
--- gtk/gtkbuilderprivate.h	(revisione 20262)
+++ gtk/gtkbuilderprivate.h	(copia locale)
@@ -91,12 +91,18 @@ typedef struct {
   const gchar *last_element;
   GtkBuilder *builder;
   gchar *domain;
+  gchar *root_object;
   GSList *stack;
   SubParser *subparser;
   GMarkupParseContext *ctx;
   const gchar *filename;
   GSList *finalizers;
   GSList *custom_finalizers;
+
+  gboolean root_object_found;
+  gboolean root_object_end_found;
+  gint root_object_level;
+  gint cur_object_level;
 } ParserData;
 
 typedef GType (*GTypeGetFunc) (void);
@@ -106,6 +112,7 @@ void _gtk_builder_parser_parse_buffer (G
                                        const gchar *filename,
                                        const gchar *buffer,
                                        gsize length,
+                                       const gchar *root_object,
                                        GError **error);
 GObject * _gtk_builder_construct (GtkBuilder *builder,
                                   ObjectInfo *info,
Index: gtk/gtkbuilder.c
===================================================================
--- gtk/gtkbuilder.c	(revisione 20262)
+++ gtk/gtkbuilder.c	(copia locale)
@@ -635,22 +635,28 @@ gtk_builder_new (void)
 }
 
 /**
- * gtk_builder_add_from_file:
+ * gtk_builder_add_from_file_with_root:
  * @builder: a #GtkBuilder
  * @filename: the name of the file to parse
+ * @root_object: id of the object to use as root
  * @error: 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. 
+ * UI definition</link> and merges it with the current contents of @builder
+ * including only objects starting from @root_object.
+ * This is usually useful to construct the containts of a composed
+ * widget, while still having the toplevel saved in the file
+ * for easier editing with a GUI builder.
  * 
  * Returns: A positive value on success, 0 if an error occurred
  *
- * Since: 2.12
+ * Since: 2.14
  **/
 guint
-gtk_builder_add_from_file (GtkBuilder   *builder,
-                           const gchar  *filename,
-                           GError      **error)
+gtk_builder_add_from_file_with_root (GtkBuilder   *builder,
+                                     const gchar  *filename,
+                                     const gchar  *root_object,
+                                     GError      **error)
 {
   gchar *buffer;
   gsize length;
@@ -673,6 +679,7 @@ gtk_builder_add_from_file (GtkBuilder   
 
   _gtk_builder_parser_parse_buffer (builder, filename,
                                     buffer, length,
+                                    root_object,
                                     &tmp_error);
 
   g_free (buffer);
@@ -687,6 +694,27 @@ gtk_builder_add_from_file (GtkBuilder   
 }
 
 /**
+ * gtk_builder_add_from_file:
+ * @builder: a #GtkBuilder
+ * @filename: the name of the file to parse
+ * @error: 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. 
+ * 
+ * Returns: A positive value on success, 0 if an error occurred
+ *
+ * Since: 2.12
+ **/
+guint
+gtk_builder_add_from_file (GtkBuilder   *builder,
+                           const gchar  *filename,
+                           GError      **error)
+{
+  return gtk_builder_add_from_file_with_root (builder, filename, NULL, error);
+}
+
+/**
  * gtk_builder_add_from_string:
  * @builder: a #GtkBuilder
  * @buffer: the string to parse
@@ -719,6 +747,7 @@ gtk_builder_add_from_string (GtkBuilder 
 
   _gtk_builder_parser_parse_buffer (builder, "<input>",
                                     buffer, length,
+                                    NULL,
                                     &tmp_error);
   if (tmp_error != NULL)
     {
Index: gtk/gtkbuilder.h
===================================================================
--- gtk/gtkbuilder.h	(revisione 20262)
+++ gtk/gtkbuilder.h	(copia locale)
@@ -95,6 +95,10 @@ GtkBuilder*  gtk_builder_new            
 guint        gtk_builder_add_from_file           (GtkBuilder    *builder,
                                                   const gchar   *filename,
                                                   GError       **error);
+guint        gtk_builder_add_from_file_with_root (GtkBuilder    *builder,
+                                                  const gchar   *filename,
+                                                  const gchar   *root_object,
+                                                  GError       **error);
 guint        gtk_builder_add_from_string         (GtkBuilder    *builder,
                                                   const gchar   *buffer,
                                                   gsize          length,
Index: gtk/gtk.symbols
===================================================================
--- gtk/gtk.symbols	(revisione 20262)
+++ gtk/gtk.symbols	(copia locale)
@@ -440,6 +440,7 @@ gtk_buildable_set_buildable_property
 #if IN_HEADER(__GTK_BUILDER_H__)
 #if IN_FILE(__GTK_BUILDER_C__)
 gtk_builder_add_from_file
+gtk_builder_add_from_file_with_root
 gtk_builder_add_from_string
 gtk_builder_error_quark
 gtk_builder_get_object
Index: gtk/gtkbuilderparser.c
===================================================================
--- gtk/gtkbuilderparser.c	(revisione 20262)
+++ gtk/gtkbuilderparser.c	(copia locale)
@@ -346,6 +346,23 @@ parse_object (ParserData   *data,
       return;
     }
 
+  ++data->cur_object_level;
+
+  /* check if we reached the root object (if it is specified) */
+  if (data->root_object && !data->root_object_found)
+    {
+      if (strcmp (data->root_object, object_id) == 0)
+        {
+          data->root_object_level = data->cur_object_level;
+
+          GTK_NOTE (BUILDER, g_print ("root object found at level %d\n", data->root_object_level));
+
+          data->root_object_found = TRUE;
+        }
+      else
+        return;
+    }
+
   object_info = g_slice_new0 (ObjectInfo);
   object_info->class_name = object_class;
   object_info->id = object_id;
@@ -800,6 +817,12 @@ start_element (GMarkupParseContext *cont
     parse_requires (data, element_name, names, values, error);
   else if (strcmp (element_name, "object") == 0)
     parse_object (data, element_name, names, values, error);
+  else if (data->root_object && !data->root_object_found)
+    {
+      /* If a root object was specified and it was not yet reached,
+       * simply ignore this tag */
+      return;
+    }
   else if (strcmp (element_name, "child") == 0)
     parse_child (data, element_name, names, values, error);
   else if (strcmp (element_name, "property") == 0)
@@ -909,11 +932,33 @@ end_element (GMarkupParseContext *contex
 			 GTK_MAJOR_VERSION, GTK_MINOR_VERSION);
 	}
     }
+  else if (strcmp (element_name, "interface") == 0)
+    {
+    }
+  else if (data->root_object &&
+           (!data->root_object_found || data->root_object_end_found))
+    {
+      /* If a root object was specified and we are outside it,
+       * simply ignore this tag */
+      return;
+    }
   else if (strcmp (element_name, "object") == 0)
     {
       ObjectInfo *object_info = state_pop_info (data, ObjectInfo);
       ChildInfo* child_info = state_peek_info (data, ChildInfo);
 
+      if (data->root_object &&
+          (data->cur_object_level == data->root_object_level))
+        {
+          GTK_NOTE (BUILDER, g_print ("root object end found at level %d\n", data->root_object_level));
+
+          data->root_object_end_found = TRUE;
+        }
+
+      --data->cur_object_level;
+
+      g_assert (data->cur_object_level >= 0);
+
       object_info->object = builder_construct (data, object_info, error);
       if (!object_info->object)
 	{
@@ -975,9 +1020,6 @@ end_element (GMarkupParseContext *contex
       object_info->signals =
         g_slist_prepend (object_info->signals, signal_info);
     }
-  else if (strcmp (element_name, "interface") == 0)
-    {
-    }
   else if (strcmp (element_name, "placeholder") == 0)
     {
     }
@@ -1055,6 +1097,7 @@ _gtk_builder_parser_parse_buffer (GtkBui
                                   const gchar  *filename,
                                   const gchar  *buffer,
                                   gsize         length,
+                                  const gchar  *root_object,  
                                   GError      **error)
 {
   ParserData *data;
@@ -1064,6 +1107,7 @@ _gtk_builder_parser_parse_buffer (GtkBui
   data->builder = builder;
   data->filename = filename;
   data->domain = g_strdup (gtk_builder_get_translation_domain (builder));
+  data->root_object = g_strdup (root_object);
 
   data->ctx = g_markup_parse_context_new (&parser, 
                                           G_MARKUP_TREAT_CDATA_AS_TEXT, 
@@ -1071,7 +1115,16 @@ _gtk_builder_parser_parse_buffer (GtkBui
 
   if (!g_markup_parse_context_parse (data->ctx, buffer, length, error))
     goto out;
-  
+
+  if (data->root_object && !data->root_object_found)
+    {
+      g_set_error (error, GTK_BUILDER_ERROR, 
+                   GTK_BUILDER_ERROR_INVALID_VALUE,
+                   _("Root object not found: '%s'"),
+		   root_object);    
+      goto out;
+    }
+
   _gtk_builder_finish (builder);
 
   /* Custom parser_finished */
@@ -1102,6 +1155,7 @@ _gtk_builder_parser_parse_buffer (GtkBui
   g_slist_foreach (data->custom_finalizers, (GFunc)free_subparser, NULL);
   g_slist_free (data->custom_finalizers);
   g_slist_free (data->finalizers);
+  g_free (data->root_object);
   g_free (data->domain);
   g_markup_parse_context_free (data->ctx);
   g_free (data);
Index: docs/reference/gtk/gtk-sections.txt
===================================================================
--- docs/reference/gtk/gtk-sections.txt	(revisione 20262)
+++ docs/reference/gtk/gtk-sections.txt	(copia locale)
@@ -477,6 +477,7 @@ GtkBuilderConnectFunc
 GtkBuilderError
 gtk_builder_new
 gtk_builder_add_from_file
+gtk_builder_add_from_file_with_root
 gtk_builder_add_from_string
 gtk_builder_get_object
 gtk_builder_get_objects
Index: tests/buildertest.c
===================================================================
--- tests/buildertest.c	(revisione 20262)
+++ tests/buildertest.c	(copia locale)
@@ -2123,6 +2123,49 @@ test_requires (void)
   g_error_free (error);
 }
 
+#define TEST_UI_FILE "buildertest.ui"
+#define TEST_UI_ROOT "mainbox"
+
+static void
+test_add_from_file (void)
+{
+  GtkBuilder *builder;
+  GError     *error;
+  gint        ret;
+  GObject    *w;
+
+  builder = gtk_builder_new ();
+  error = NULL;
+  ret = gtk_builder_add_from_file (builder, "not_existing.ui", &error);
+  g_assert (!ret);
+  g_assert (error != NULL);
+  g_assert (error->domain == G_FILE_ERROR);
+  g_assert (error->code == G_FILE_ERROR_NOENT);
+  g_object_unref (builder);
+  g_error_free (error);
+
+  builder = gtk_builder_new ();
+  error = NULL;
+  ret = gtk_builder_add_from_file_with_root (builder, TEST_UI_FILE, "wrong_root", &error);
+  g_assert (!ret);
+  g_assert (error != NULL);
+  g_assert (error->domain == GTK_BUILDER_ERROR);
+  g_assert (error->code == GTK_BUILDER_ERROR_INVALID_VALUE);
+  g_object_unref (builder);
+  g_error_free (error);
+
+  builder = gtk_builder_new ();
+  error = NULL;
+  ret = gtk_builder_add_from_file_with_root (builder, TEST_UI_FILE, TEST_UI_ROOT, &error);
+  g_assert (ret);
+  g_assert (error == NULL);
+  w = gtk_builder_get_object (builder, "window");  
+  g_assert (!w);
+  w = gtk_builder_get_object (builder, TEST_UI_ROOT);  
+  g_assert (GTK_IS_WIDGET (w));
+  g_object_unref (builder);
+}
+
 
 static void 
 test_file (const gchar *filename)
@@ -2168,17 +2211,59 @@ test_file (const gchar *filename)
   builder = NULL;
 }
 
+static void 
+test_file_with_root (const gchar *filename, const gchar *root)
+{
+  GtkBuilder *builder;
+  GError *error = NULL;
+  GtkWidget *dialog;
+  GObject *contents;
+
+  builder = gtk_builder_new ();
+
+  if (!gtk_builder_add_from_file_with_root (builder, filename, root, &error))
+    {
+      g_error (error->message);
+      g_error_free (error);
+      return;
+    }
+
+  dialog = gtk_dialog_new_with_buttons ("Test Builder",
+                                        NULL,
+                                        GTK_DIALOG_MODAL,
+                                        GTK_STOCK_OK,
+                                        GTK_RESPONSE_ACCEPT,
+                                        GTK_STOCK_CANCEL,
+                                        GTK_RESPONSE_REJECT,
+                                        NULL);
+
+  contents = gtk_builder_get_object (builder, root);
+  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
+                     GTK_WIDGET (contents));
+
+  gtk_widget_show_all (dialog);
+  gtk_dialog_run (GTK_DIALOG (dialog));
+
+  g_object_unref (builder);
+  builder = NULL;
+}
+
 int
 main (int argc, char **argv)
 {
   /* initialize test program */
   gtk_test_init (&argc, &argv);
 
-  if (argc > 1)
+  if (argc == 2)
     {
       test_file (argv[1]);
       return 0;
     }
+  else if (argc == 3)
+    {
+      test_file_with_root (argv[1], argv[2]);
+      return 0;
+    }
 
   g_test_add_func ("/Builder/Parser", test_parser);
   g_test_add_func ("/Builder/Types", test_types);
@@ -2208,6 +2293,7 @@ main (int argc, char **argv)
   g_test_add_func ("/Builder/IconFactory", test_icon_factory);
   g_test_add_func ("/Builder/PangoAttributes", test_pango_attributes);
   g_test_add_func ("/Builder/Requires", test_requires);
+  g_test_add_func ("/Builder/Add From File", test_add_from_file);
 
   return g_test_run();
 }
