]> Pileus Git - ~andy/gtk/blob - gtk/tests/builder.c
af8b5817dd50c4626c51e08de6b5d2e349e0acb3
[~andy/gtk] / gtk / tests / builder.c
1 /* buildertest.c
2  * Copyright (C) 2006-2007 Async Open Source
3  * Authors: Johan Dahlin
4  *          Henrique Romano
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <string.h>
21 #include <libintl.h>
22 #include <locale.h>
23 #include <math.h>
24
25 #include <gtk/gtk.h>
26 #include <gdk/gdkkeysyms.h>
27
28 /* Copied from gtkiconfactory.c; keep in sync! */
29 struct _GtkIconSet
30 {
31   guint ref_count;
32   GSList *sources;
33   GSList *cache;
34   guint cache_size;
35   guint cache_serial;
36 };
37
38
39 static GtkBuilder *
40 builder_new_from_string (const gchar *buffer,
41                          gsize length,
42                          const gchar *domain)
43 {
44   GtkBuilder *builder;
45   GError *error = NULL;
46
47   builder = gtk_builder_new ();
48   if (domain)
49     gtk_builder_set_translation_domain (builder, domain);
50   gtk_builder_add_from_string (builder, buffer, length, &error);
51   if (error)
52     {
53       g_print ("ERROR: %s", error->message);
54       g_error_free (error);
55     }
56
57   return builder;
58 }
59
60 static void
61 test_parser (void)
62 {
63   GtkBuilder *builder;
64   GError *error;
65   
66   builder = gtk_builder_new ();
67
68   error = NULL;
69   gtk_builder_add_from_string (builder, "<xxx/>", -1, &error);
70   g_assert (g_error_matches (error, 
71                              GTK_BUILDER_ERROR,
72                              GTK_BUILDER_ERROR_UNHANDLED_TAG));
73   g_error_free (error);
74   
75   error = NULL;
76   gtk_builder_add_from_string (builder, "<interface invalid=\"X\"/>", -1, &error);
77   g_assert (g_error_matches (error,
78                              GTK_BUILDER_ERROR,
79                              GTK_BUILDER_ERROR_INVALID_ATTRIBUTE));
80   g_error_free (error);
81
82   error = NULL;
83   gtk_builder_add_from_string (builder, "<interface><child/></interface>", -1, &error);
84   g_assert (g_error_matches (error,
85                              GTK_BUILDER_ERROR, 
86                              GTK_BUILDER_ERROR_INVALID_TAG));
87   g_error_free (error);
88
89   error = NULL;
90   gtk_builder_add_from_string (builder, "<interface><object class=\"GtkVBox\" id=\"a\"><object class=\"GtkHBox\" id=\"b\"/></object></interface>", -1, &error);
91   g_assert (g_error_matches (error,
92                              GTK_BUILDER_ERROR,
93                              GTK_BUILDER_ERROR_INVALID_TAG));
94   g_error_free (error);
95
96   error = NULL;
97   gtk_builder_add_from_string (builder, "<interface><object class=\"Unknown\" id=\"a\"></object></interface>", -1, &error);
98   g_assert (g_error_matches (error,
99                              GTK_BUILDER_ERROR,
100                              GTK_BUILDER_ERROR_INVALID_VALUE));
101   g_error_free (error);
102
103   error = NULL;
104   gtk_builder_add_from_string (builder, "<interface><object class=\"GtkWidget\" id=\"a\" constructor=\"none\"></object></interface>", -1, &error);
105   g_assert (g_error_matches (error,
106                              GTK_BUILDER_ERROR,
107                              GTK_BUILDER_ERROR_INVALID_VALUE));
108   g_error_free (error);
109
110   error = NULL;
111   gtk_builder_add_from_string (builder, "<interface><object class=\"GtkButton\" id=\"a\"><child internal-child=\"foobar\"><object class=\"GtkButton\" id=\"int\"/></child></object></interface>", -1, &error);
112   g_assert (g_error_matches (error,
113                              GTK_BUILDER_ERROR,
114                              GTK_BUILDER_ERROR_INVALID_VALUE));
115   g_error_free (error);
116
117   error = NULL;
118   gtk_builder_add_from_string (builder, "<interface><object class=\"GtkButton\" id=\"a\"></object><object class=\"GtkButton\" id=\"a\"/></object></interface>", -1, &error);
119   g_assert (g_error_matches (error,
120                              GTK_BUILDER_ERROR,
121                              GTK_BUILDER_ERROR_DUPLICATE_ID));
122   g_error_free (error);
123
124   g_object_unref (builder);
125 }
126
127 static int normal = 0;
128 static int after = 0;
129 static int object = 0;
130 static int object_after = 0;
131
132 void /* exported for GtkBuilder */
133 signal_normal (GtkWindow *window, GParamSpec spec)
134 {
135   g_assert (GTK_IS_WINDOW (window));
136   g_assert (normal == 0);
137   g_assert (after == 0);
138
139   normal++;
140 }
141
142 void /* exported for GtkBuilder */
143 signal_after (GtkWindow *window, GParamSpec spec)
144 {
145   g_assert (GTK_IS_WINDOW (window));
146   g_assert (normal == 1);
147   g_assert (after == 0);
148   
149   after++;
150 }
151
152 void /* exported for GtkBuilder */
153 signal_object (GtkButton *button, GParamSpec spec)
154 {
155   g_assert (GTK_IS_BUTTON (button));
156   g_assert (object == 0);
157   g_assert (object_after == 0);
158
159   object++;
160 }
161
162 void /* exported for GtkBuilder */
163 signal_object_after (GtkButton *button, GParamSpec spec)
164 {
165   g_assert (GTK_IS_BUTTON (button));
166   g_assert (object == 1);
167   g_assert (object_after == 0);
168
169   object_after++;
170 }
171
172 void /* exported for GtkBuilder */
173 signal_first (GtkButton *button, GParamSpec spec)
174 {
175   g_assert (normal == 0);
176   normal = 10;
177 }
178
179 void /* exported for GtkBuilder */
180 signal_second (GtkButton *button, GParamSpec spec)
181 {
182   g_assert (normal == 10);
183   normal = 20;
184 }
185
186 void /* exported for GtkBuilder */
187 signal_extra (GtkButton *button, GParamSpec spec)
188 {
189   g_assert (normal == 20);
190   normal = 30;
191 }
192
193 void /* exported for GtkBuilder */
194 signal_extra2 (GtkButton *button, GParamSpec spec)
195 {
196   g_assert (normal == 30);
197   normal = 40;
198 }
199
200 static void
201 test_connect_signals (void)
202 {
203   GtkBuilder *builder;
204   GObject *window;
205   const gchar buffer[] =
206     "<interface>"
207     "  <object class=\"GtkButton\" id=\"button\"/>"
208     "  <object class=\"GtkWindow\" id=\"window1\">"
209     "    <signal name=\"notify::title\" handler=\"signal_normal\"/>"
210     "    <signal name=\"notify::title\" handler=\"signal_after\" after=\"yes\"/>"
211     "    <signal name=\"notify::title\" handler=\"signal_object\""
212     "            object=\"button\"/>"
213     "    <signal name=\"notify::title\" handler=\"signal_object_after\""
214     "            object=\"button\" after=\"yes\"/>"
215     "  </object>"
216     "</interface>";
217   const gchar buffer_order[] =
218     "<interface>"
219     "  <object class=\"GtkWindow\" id=\"window1\">"
220     "    <signal name=\"notify::title\" handler=\"signal_first\"/>"
221     "    <signal name=\"notify::title\" handler=\"signal_second\"/>"
222     "  </object>"
223     "</interface>";
224   const gchar buffer_extra[] =
225     "<interface>"
226     "  <object class=\"GtkWindow\" id=\"window2\">"
227     "    <signal name=\"notify::title\" handler=\"signal_extra\"/>"
228     "  </object>"
229     "</interface>";
230   const gchar buffer_extra2[] =
231     "<interface>"
232     "  <object class=\"GtkWindow\" id=\"window3\">"
233     "    <signal name=\"notify::title\" handler=\"signal_extra2\"/>"
234     "  </object>"
235     "</interface>";
236   const gchar buffer_after_child[] =
237     "<interface>"
238     "  <object class=\"GtkWindow\" id=\"window1\">"
239     "    <child>"
240     "      <object class=\"GtkButton\" id=\"button1\"/>"
241     "    </child>"
242     "    <signal name=\"notify::title\" handler=\"signal_normal\"/>"
243     "  </object>"
244     "</interface>";
245
246   builder = builder_new_from_string (buffer, -1, NULL);
247   gtk_builder_connect_signals (builder, NULL);
248
249   window = gtk_builder_get_object (builder, "window1");
250   gtk_window_set_title (GTK_WINDOW (window), "test");
251
252   g_assert_cmpint (normal, ==, 1);
253   g_assert_cmpint (after, ==, 1);
254   g_assert_cmpint (object, ==, 1);
255   g_assert_cmpint (object_after, ==, 1);
256
257   gtk_widget_destroy (GTK_WIDGET (window));
258   g_object_unref (builder);
259   
260   builder = builder_new_from_string (buffer_order, -1, NULL);
261   gtk_builder_connect_signals (builder, NULL);
262   window = gtk_builder_get_object (builder, "window1");
263   normal = 0;
264   gtk_window_set_title (GTK_WINDOW (window), "test");
265   g_assert (normal == 20);
266
267   gtk_widget_destroy (GTK_WIDGET (window));
268
269   gtk_builder_add_from_string (builder, buffer_extra,
270                                strlen (buffer_extra), NULL);
271   gtk_builder_add_from_string (builder, buffer_extra2,
272                                strlen (buffer_extra2), NULL);
273   gtk_builder_connect_signals (builder, NULL);
274   window = gtk_builder_get_object (builder, "window2");
275   gtk_window_set_title (GTK_WINDOW (window), "test");
276   g_assert (normal == 30);
277
278   gtk_widget_destroy (GTK_WIDGET (window));
279   window = gtk_builder_get_object (builder, "window3");
280   gtk_window_set_title (GTK_WINDOW (window), "test");
281   g_assert (normal == 40);
282   gtk_widget_destroy (GTK_WIDGET (window));
283   
284   g_object_unref (builder);
285
286   /* new test, reset globals */
287   after = 0;
288   normal = 0;
289   
290   builder = builder_new_from_string (buffer_after_child, -1, NULL);
291   window = gtk_builder_get_object (builder, "window1");
292   gtk_builder_connect_signals (builder, NULL);
293   gtk_window_set_title (GTK_WINDOW (window), "test");
294
295   g_assert (normal == 1);
296   gtk_widget_destroy (GTK_WIDGET (window));
297   g_object_unref (builder);
298 }
299
300 static void
301 test_uimanager_simple (void)
302 {
303   GtkBuilder *builder;
304   GObject *window, *uimgr, *menubar;
305   GObject *menu, *label;
306   GList *children;
307   const gchar buffer[] =
308     "<interface>"
309     "  <object class=\"GtkUIManager\" id=\"uimgr1\"/>"
310     "</interface>";
311     
312   const gchar buffer2[] =
313     "<interface>"
314     "  <object class=\"GtkUIManager\" id=\"uimgr1\">"
315     "    <child>"
316     "      <object class=\"GtkActionGroup\" id=\"ag1\">"
317     "        <child>"
318     "          <object class=\"GtkAction\" id=\"file\">"
319     "            <property name=\"label\">_File</property>"
320     "          </object>"
321     "          <accelerator key=\"n\" modifiers=\"GDK_CONTROL_MASK\"/>"
322     "        </child>"
323     "      </object>"
324     "    </child>"
325     "    <ui>"
326     "      <menubar name=\"menubar1\">"
327     "        <menu action=\"file\">"
328     "        </menu>"
329     "      </menubar>"
330     "    </ui>"
331     "  </object>"
332     "  <object class=\"GtkWindow\" id=\"window1\">"
333     "    <child>"
334     "      <object class=\"GtkMenuBar\" id=\"menubar1\" constructor=\"uimgr1\"/>"
335     "    </child>"
336     "  </object>"
337     "</interface>";
338
339   builder = builder_new_from_string (buffer, -1, NULL);
340
341   uimgr = gtk_builder_get_object (builder, "uimgr1");
342   g_assert (GTK_IS_UI_MANAGER (uimgr));
343   g_object_unref (builder);
344   
345   builder = builder_new_from_string (buffer2, -1, NULL);
346
347   menubar = gtk_builder_get_object (builder, "menubar1");
348   g_assert (GTK_IS_MENU_BAR (menubar));
349
350   children = gtk_container_get_children (GTK_CONTAINER (menubar));
351   menu = children->data;
352   g_assert (GTK_IS_MENU_ITEM (menu));
353   g_assert (strcmp (gtk_widget_get_name (GTK_WIDGET (menu)), "file") == 0);
354   g_list_free (children);
355   
356   label = G_OBJECT (gtk_bin_get_child (GTK_BIN (menu)));
357   g_assert (GTK_IS_LABEL (label));
358   g_assert (strcmp (gtk_label_get_text (GTK_LABEL (label)), "File") == 0);
359
360   window = gtk_builder_get_object (builder, "window1");
361   gtk_widget_destroy (GTK_WIDGET (window));
362   g_object_unref (builder);
363 }
364
365 static void
366 test_domain (void)
367 {
368   GtkBuilder *builder;
369   const gchar buffer1[] = "<interface/>";
370   const gchar buffer2[] = "<interface domain=\"domain\"/>";
371   const gchar *domain;
372   
373   builder = builder_new_from_string (buffer1, -1, NULL);
374   domain = gtk_builder_get_translation_domain (builder);
375   g_assert (domain == NULL);
376   g_object_unref (builder);
377   
378   builder = builder_new_from_string (buffer1, -1, "domain-1");
379   domain = gtk_builder_get_translation_domain (builder);
380   g_assert (domain);
381   g_assert (strcmp (domain, "domain-1") == 0);
382   g_object_unref (builder);
383
384   builder = builder_new_from_string (buffer2, -1, NULL);
385   domain = gtk_builder_get_translation_domain (builder);
386   g_assert (domain == NULL);
387   g_object_unref (builder);
388 }
389
390 #if 0
391 static void
392 test_translation (void)
393 {
394   GtkBuilder *builder;
395   const gchar buffer[] =
396     "<interface>"
397     "  <object class=\"GtkWindow\" id=\"window1\">"
398     "    <child>"
399     "      <object class=\"GtkLabel\" id=\"label\">"
400     "        <property name=\"label\" translatable=\"yes\">File</property>"
401     "      </object>"
402     "    </child>"
403     "  </object>"
404     "</interface>";
405   GtkLabel *window, *label;
406
407   setlocale (LC_ALL, "sv_SE");
408   textdomain ("builder");
409   bindtextdomain ("builder", "tests");
410
411   builder = builder_new_from_string (buffer, -1, NULL);
412   label = GTK_LABEL (gtk_builder_get_object (builder, "label"));
413   g_assert (strcmp (gtk_label_get_text (label), "Arkiv") == 0);
414
415   window = gtk_builder_get_object (builder, "window1");
416   gtk_widget_destroy (GTK_WIDGET (window));
417   g_object_unref (builder);
418 }
419 #endif
420
421 static void
422 test_sizegroup (void)
423 {
424   GtkBuilder * builder;
425   const gchar buffer1[] =
426     "<interface domain=\"test\">"
427     "  <object class=\"GtkSizeGroup\" id=\"sizegroup1\">"
428     "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
429     "    <widgets>"
430     "      <widget name=\"radio1\"/>"
431     "      <widget name=\"radio2\"/>"
432     "    </widgets>"
433     "  </object>"
434     "  <object class=\"GtkWindow\" id=\"window1\">"
435     "    <child>"
436     "      <object class=\"GtkVBox\" id=\"vbox1\">"
437     "        <child>"
438     "          <object class=\"GtkRadioButton\" id=\"radio1\"/>"
439     "        </child>"
440     "        <child>"
441     "          <object class=\"GtkRadioButton\" id=\"radio2\"/>"
442     "        </child>"
443     "      </object>"
444     "    </child>"
445     "  </object>"
446     "</interface>";
447   const gchar buffer2[] =
448     "<interface domain=\"test\">"
449     "  <object class=\"GtkSizeGroup\" id=\"sizegroup1\">"
450     "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
451     "    <widgets>"
452     "    </widgets>"
453     "   </object>"
454     "</interface>";
455   const gchar buffer3[] =
456     "<interface domain=\"test\">"
457     "  <object class=\"GtkSizeGroup\" id=\"sizegroup1\">"
458     "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
459     "    <widgets>"
460     "      <widget name=\"radio1\"/>"
461     "      <widget name=\"radio2\"/>"
462     "    </widgets>"
463     "  </object>"
464     "  <object class=\"GtkSizeGroup\" id=\"sizegroup2\">"
465     "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
466     "    <widgets>"
467     "      <widget name=\"radio1\"/>"
468     "      <widget name=\"radio2\"/>"
469     "    </widgets>"
470     "  </object>"
471     "  <object class=\"GtkWindow\" id=\"window1\">"
472     "    <child>"
473     "      <object class=\"GtkVBox\" id=\"vbox1\">"
474     "        <child>"
475     "          <object class=\"GtkRadioButton\" id=\"radio1\"/>"
476     "        </child>"
477     "        <child>"
478     "          <object class=\"GtkRadioButton\" id=\"radio2\"/>"
479     "        </child>"
480     "      </object>"
481     "    </child>"
482     "  </object>"
483     "</interface>";
484   GObject *sizegroup;
485   GSList *widgets;
486
487   builder = builder_new_from_string (buffer1, -1, NULL);
488   sizegroup = gtk_builder_get_object (builder, "sizegroup1");
489   widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
490   g_assert (g_slist_length (widgets) == 2);
491   g_slist_free (widgets);
492   g_object_unref (builder);
493
494   builder = builder_new_from_string (buffer2, -1, NULL);
495   sizegroup = gtk_builder_get_object (builder, "sizegroup1");
496   widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
497   g_assert (g_slist_length (widgets) == 0);
498   g_slist_free (widgets);
499   g_object_unref (builder);
500
501   builder = builder_new_from_string (buffer3, -1, NULL);
502   sizegroup = gtk_builder_get_object (builder, "sizegroup1");
503   widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
504   g_assert (g_slist_length (widgets) == 2);
505   g_slist_free (widgets);
506   sizegroup = gtk_builder_get_object (builder, "sizegroup2");
507   widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
508   g_assert (g_slist_length (widgets) == 2);
509   g_slist_free (widgets);
510
511 #if 0
512   {
513     GObject *window;
514     window = gtk_builder_get_object (builder, "window1");
515     gtk_widget_destroy (GTK_WIDGET (window));
516   }
517 #endif  
518   g_object_unref (builder);
519 }
520
521 static void
522 test_list_store (void)
523 {
524   const gchar buffer1[] =
525     "<interface>"
526     "  <object class=\"GtkListStore\" id=\"liststore1\">"
527     "    <columns>"
528     "      <column type=\"gchararray\"/>"
529     "      <column type=\"guint\"/>"
530     "    </columns>"
531     "  </object>"
532     "</interface>";
533   const char buffer2[] = 
534     "<interface>"
535     "  <object class=\"GtkListStore\" id=\"liststore1\">"
536     "    <columns>"
537     "      <column type=\"gchararray\"/>"
538     "      <column type=\"gchararray\"/>"
539     "      <column type=\"gint\"/>"
540     "    </columns>"
541     "    <data>"
542     "      <row>"
543     "        <col id=\"0\" translatable=\"yes\">John</col>"
544     "        <col id=\"1\" context=\"foo\">Doe</col>"
545     "        <col id=\"2\" comment=\"foobar\">25</col>"
546     "      </row>"
547     "      <row>"
548     "        <col id=\"0\">Johan</col>"
549     "        <col id=\"1\">Dole</col>"
550     "        <col id=\"2\">50</col>"
551     "      </row>"
552     "    </data>"
553     "  </object>"
554     "</interface>";
555   const char buffer3[] = 
556     "<interface>"
557     "  <object class=\"GtkListStore\" id=\"liststore1\">"
558     "    <columns>"
559     "      <column type=\"gchararray\"/>"
560     "      <column type=\"gchararray\"/>"
561     "      <column type=\"gint\"/>"
562     "    </columns>"
563     "    <data>"
564     "      <row>"
565     "        <col id=\"1\" context=\"foo\">Doe</col>"
566     "        <col id=\"0\" translatable=\"yes\">John</col>"
567     "        <col id=\"2\" comment=\"foobar\">25</col>"
568     "      </row>"
569     "      <row>"
570     "        <col id=\"2\">50</col>"
571     "        <col id=\"1\">Dole</col>"
572     "        <col id=\"0\">Johan</col>"
573     "      </row>"
574     "      <row>"
575     "        <col id=\"2\">19</col>"
576     "      </row>"
577     "    </data>"
578     "  </object>"
579     "</interface>";
580   GtkBuilder *builder;
581   GObject *store;
582   GtkTreeIter iter;
583   gchar *surname, *lastname;
584   int age;
585   
586   builder = builder_new_from_string (buffer1, -1, NULL);
587   store = gtk_builder_get_object (builder, "liststore1");
588   g_assert (gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)) == 2);
589   g_assert (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 0) == G_TYPE_STRING);
590   g_assert (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 1) == G_TYPE_UINT);
591   g_object_unref (builder);
592   
593   builder = builder_new_from_string (buffer2, -1, NULL);
594   store = gtk_builder_get_object (builder, "liststore1");
595   g_assert (gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)) == 3);
596   g_assert (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 0) == G_TYPE_STRING);
597   g_assert (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 1) == G_TYPE_STRING);
598   g_assert (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 2) == G_TYPE_INT);
599   
600   g_assert (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter) == TRUE);
601   gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
602                       0, &surname,
603                       1, &lastname,
604                       2, &age,
605                       -1);
606   g_assert (surname != NULL);
607   g_assert (strcmp (surname, "John") == 0);
608   g_free (surname);
609   g_assert (lastname != NULL);
610   g_assert (strcmp (lastname, "Doe") == 0);
611   g_free (lastname);
612   g_assert (age == 25);
613   g_assert (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter) == TRUE);
614   
615   gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
616                       0, &surname,
617                       1, &lastname,
618                       2, &age,
619                       -1);
620   g_assert (surname != NULL);
621   g_assert (strcmp (surname, "Johan") == 0);
622   g_free (surname);
623   g_assert (lastname != NULL);
624   g_assert (strcmp (lastname, "Dole") == 0);
625   g_free (lastname);
626   g_assert (age == 50);
627   g_assert (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter) == FALSE);
628
629   g_object_unref (builder);  
630
631   builder = builder_new_from_string (buffer3, -1, NULL);
632   store = gtk_builder_get_object (builder, "liststore1");
633   g_assert (gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)) == 3);
634   g_assert (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 0) == G_TYPE_STRING);
635   g_assert (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 1) == G_TYPE_STRING);
636   g_assert (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 2) == G_TYPE_INT);
637   
638   g_assert (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter) == TRUE);
639   gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
640                       0, &surname,
641                       1, &lastname,
642                       2, &age,
643                       -1);
644   g_assert (surname != NULL);
645   g_assert (strcmp (surname, "John") == 0);
646   g_free (surname);
647   g_assert (lastname != NULL);
648   g_assert (strcmp (lastname, "Doe") == 0);
649   g_free (lastname);
650   g_assert (age == 25);
651   g_assert (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter) == TRUE);
652   
653   gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
654                       0, &surname,
655                       1, &lastname,
656                       2, &age,
657                       -1);
658   g_assert (surname != NULL);
659   g_assert (strcmp (surname, "Johan") == 0);
660   g_free (surname);
661   g_assert (lastname != NULL);
662   g_assert (strcmp (lastname, "Dole") == 0);
663   g_free (lastname);
664   g_assert (age == 50);
665   g_assert (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter) == TRUE);
666   
667   gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
668                       0, &surname,
669                       1, &lastname,
670                       2, &age,
671                       -1);
672   g_assert (surname == NULL);
673   g_assert (lastname == NULL);
674   g_assert (age == 19);
675   g_assert (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter) == FALSE);
676
677   g_object_unref (builder);
678 }
679
680 static void
681 test_tree_store (void)
682 {
683   const gchar buffer[] =
684     "<interface domain=\"test\">"
685     "  <object class=\"GtkTreeStore\" id=\"treestore1\">"
686     "    <columns>"
687     "      <column type=\"gchararray\"/>"
688     "      <column type=\"guint\"/>"
689     "    </columns>"
690     "  </object>"
691     "</interface>";
692   GtkBuilder *builder;
693   GObject *store;
694   
695   builder = builder_new_from_string (buffer, -1, NULL);
696   store = gtk_builder_get_object (builder, "treestore1");
697   g_assert (gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)) == 2);
698   g_assert (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 0) == G_TYPE_STRING);
699   g_assert (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 1) == G_TYPE_UINT);
700   
701   g_object_unref (builder);
702 }
703
704 static void
705 test_types (void)
706 {
707   const gchar buffer[] = 
708     "<interface>"
709     "  <object class=\"GtkAction\" id=\"action\"/>"
710     "  <object class=\"GtkActionGroup\" id=\"actiongroup\"/>"
711     "  <object class=\"GtkAlignment\" id=\"alignment\"/>"
712     "  <object class=\"GtkArrow\" id=\"arrow\"/>"
713     "  <object class=\"GtkButton\" id=\"button\"/>"
714     "  <object class=\"GtkCheckButton\" id=\"checkbutton\"/>"
715     "  <object class=\"GtkDialog\" id=\"dialog\"/>"
716     "  <object class=\"GtkDrawingArea\" id=\"drawingarea\"/>"
717     "  <object class=\"GtkEventBox\" id=\"eventbox\"/>"
718     "  <object class=\"GtkEntry\" id=\"entry\"/>"
719     "  <object class=\"GtkFontButton\" id=\"fontbutton\"/>"
720     "  <object class=\"GtkHButtonBox\" id=\"hbuttonbox\"/>"
721     "  <object class=\"GtkHBox\" id=\"hbox\"/>"
722     "  <object class=\"GtkHPaned\" id=\"hpaned\"/>"
723     "  <object class=\"GtkHScale\" id=\"hscale\"/>"
724     "  <object class=\"GtkHScrollbar\" id=\"hscrollbar\"/>"
725     "  <object class=\"GtkHSeparator\" id=\"hseparator\"/>"
726     "  <object class=\"GtkImage\" id=\"image\"/>"
727     "  <object class=\"GtkLabel\" id=\"label\"/>"
728     "  <object class=\"GtkListStore\" id=\"liststore\"/>"
729     "  <object class=\"GtkMenuBar\" id=\"menubar\"/>"
730     "  <object class=\"GtkNotebook\" id=\"notebook\"/>"
731     "  <object class=\"GtkProgressBar\" id=\"progressbar\"/>"
732     "  <object class=\"GtkRadioButton\" id=\"radiobutton\"/>"
733     "  <object class=\"GtkSizeGroup\" id=\"sizegroup\"/>"
734     "  <object class=\"GtkScrolledWindow\" id=\"scrolledwindow\"/>"
735     "  <object class=\"GtkSpinButton\" id=\"spinbutton\"/>"
736     "  <object class=\"GtkStatusbar\" id=\"statusbar\"/>"
737     "  <object class=\"GtkTextView\" id=\"textview\"/>"
738     "  <object class=\"GtkToggleAction\" id=\"toggleaction\"/>"
739     "  <object class=\"GtkToggleButton\" id=\"togglebutton\"/>"
740     "  <object class=\"GtkToolbar\" id=\"toolbar\"/>"
741     "  <object class=\"GtkTreeStore\" id=\"treestore\"/>"
742     "  <object class=\"GtkTreeView\" id=\"treeview\"/>"
743     "  <object class=\"GtkTable\" id=\"table\"/>"
744     "  <object class=\"GtkVBox\" id=\"vbox\"/>"
745     "  <object class=\"GtkVButtonBox\" id=\"vbuttonbox\"/>"
746     "  <object class=\"GtkVScrollbar\" id=\"vscrollbar\"/>"
747     "  <object class=\"GtkVSeparator\" id=\"vseparator\"/>"
748     "  <object class=\"GtkViewport\" id=\"viewport\"/>"
749     "  <object class=\"GtkVPaned\" id=\"vpaned\"/>"
750     "  <object class=\"GtkVScale\" id=\"vscale\"/>"
751     "  <object class=\"GtkWindow\" id=\"window\"/>"
752     "  <object class=\"GtkUIManager\" id=\"uimanager\"/>"
753     "</interface>";
754   const gchar buffer2[] = 
755     "<interface>"
756     "  <object type-func=\"gtk_window_get_type\" id=\"window\"/>"
757     "</interface>";
758   const gchar buffer3[] = 
759     "<interface>"
760     "  <object type-func=\"xxx_invalid_get_type_function\" id=\"window\"/>"
761     "</interface>";
762   GtkBuilder *builder;
763   GObject *window;
764   GError *error;
765
766   builder = builder_new_from_string (buffer, -1, NULL);
767   gtk_widget_destroy (GTK_WIDGET (gtk_builder_get_object (builder, "dialog")));
768   gtk_widget_destroy (GTK_WIDGET (gtk_builder_get_object (builder, "window")));
769   g_object_unref (builder);
770
771   builder = builder_new_from_string (buffer2, -1, NULL);
772   window = gtk_builder_get_object (builder, "window");
773   g_assert (GTK_IS_WINDOW (window));
774   gtk_widget_destroy (GTK_WIDGET (window));
775   g_object_unref (builder);
776   
777   error = NULL;
778   builder = gtk_builder_new ();
779   gtk_builder_add_from_string (builder, buffer3, -1, &error);
780   g_assert (g_error_matches (error,
781                              GTK_BUILDER_ERROR,
782                              GTK_BUILDER_ERROR_INVALID_TYPE_FUNCTION));
783   g_error_free (error);
784   g_object_unref (builder);
785 }
786
787 static void
788 test_spin_button (void)
789 {
790   GtkBuilder *builder;
791   const gchar buffer[] =
792     "<interface>"
793     "<object class=\"GtkAdjustment\" id=\"adjustment1\">"
794     "<property name=\"lower\">0</property>"
795     "<property name=\"upper\">10</property>"
796     "<property name=\"step-increment\">2</property>"
797     "<property name=\"page-increment\">3</property>"
798     "<property name=\"page-size\">0</property>"
799     "<property name=\"value\">1</property>"
800     "</object>"
801     "<object class=\"GtkSpinButton\" id=\"spinbutton1\">"
802     "<property name=\"visible\">True</property>"
803     "<property name=\"adjustment\">adjustment1</property>"
804     "</object>"
805     "</interface>";
806   GObject *obj;
807   GtkAdjustment *adjustment;
808   gdouble value;
809   
810   builder = builder_new_from_string (buffer, -1, NULL);
811   obj = gtk_builder_get_object (builder, "spinbutton1");
812   g_assert (GTK_IS_SPIN_BUTTON (obj));
813   adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (obj));
814   g_assert (GTK_IS_ADJUSTMENT (adjustment));
815   g_object_get (adjustment, "value", &value, NULL);
816   g_assert (value == 1);
817   g_object_get (adjustment, "lower", &value, NULL);
818   g_assert (value == 0);
819   g_object_get (adjustment, "upper", &value, NULL);
820   g_assert (value == 10);
821   g_object_get (adjustment, "step-increment", &value, NULL);
822   g_assert (value == 2);
823   g_object_get (adjustment, "page-increment", &value, NULL);
824   g_assert (value == 3);
825   g_object_get (adjustment, "page-size", &value, NULL);
826   g_assert (value == 0);
827   
828   g_object_unref (builder);
829 }
830
831 static void
832 test_notebook (void)
833 {
834   GtkBuilder *builder;
835   const gchar buffer[] =
836     "<interface>"
837     "  <object class=\"GtkNotebook\" id=\"notebook1\">"
838     "    <child>"
839     "      <object class=\"GtkLabel\" id=\"label1\">"
840     "        <property name=\"label\">label1</property>"
841     "      </object>"
842     "    </child>"
843     "    <child type=\"tab\">"
844     "      <object class=\"GtkLabel\" id=\"tablabel1\">"
845     "        <property name=\"label\">tab_label1</property>"
846     "      </object>"
847     "    </child>"
848     "    <child>"
849     "      <object class=\"GtkLabel\" id=\"label2\">"
850     "        <property name=\"label\">label2</property>"
851     "      </object>"
852     "    </child>"
853     "    <child type=\"tab\">"
854     "      <object class=\"GtkLabel\" id=\"tablabel2\">"
855     "        <property name=\"label\">tab_label2</property>"
856     "      </object>"
857     "    </child>"
858     "  </object>"
859     "</interface>";
860   GObject *notebook;
861   GtkWidget *label;
862
863   builder = builder_new_from_string (buffer, -1, NULL);
864   notebook = gtk_builder_get_object (builder, "notebook1");
865   g_assert (notebook != NULL);
866   g_assert (gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) == 2);
867
868   label = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 0);
869   g_assert (GTK_IS_LABEL (label));
870   g_assert (strcmp (gtk_label_get_label (GTK_LABEL (label)), "label1") == 0);
871   label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook), label);
872   g_assert (GTK_IS_LABEL (label));
873   g_assert (strcmp (gtk_label_get_label (GTK_LABEL (label)), "tab_label1") == 0);
874
875   label = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 1);
876   g_assert (GTK_IS_LABEL (label));
877   g_assert (strcmp (gtk_label_get_label (GTK_LABEL (label)), "label2") == 0);
878   label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook), label);
879   g_assert (GTK_IS_LABEL (label));
880   g_assert (strcmp (gtk_label_get_label (GTK_LABEL (label)), "tab_label2") == 0);
881
882   g_object_unref (builder);
883 }
884
885 static void
886 test_construct_only_property (void)
887 {
888   GtkBuilder *builder;
889   const gchar buffer[] =
890     "<interface>"
891     "  <object class=\"GtkWindow\" id=\"window1\">"
892     "    <property name=\"type\">GTK_WINDOW_POPUP</property>"
893     "  </object>"
894     "</interface>";
895   const gchar buffer2[] =
896     "<interface>"
897     "  <object class=\"GtkTextTagTable\" id=\"tagtable1\"/>"
898     "  <object class=\"GtkTextBuffer\" id=\"textbuffer1\">"
899     "    <property name=\"tag-table\">tagtable1</property>"
900     "  </object>"
901     "</interface>";
902   GObject *widget, *tagtable, *textbuffer;
903   GtkWindowType type;
904   
905   builder = builder_new_from_string (buffer, -1, NULL);
906   widget = gtk_builder_get_object (builder, "window1");
907   g_object_get (widget, "type", &type, NULL);
908   g_assert (type == GTK_WINDOW_POPUP);
909
910   gtk_widget_destroy (GTK_WIDGET (widget));
911   g_object_unref (builder);
912
913   builder = builder_new_from_string (buffer2, -1, NULL);
914   textbuffer = gtk_builder_get_object (builder, "textbuffer1");
915   g_assert (textbuffer != NULL);
916   g_object_get (textbuffer, "tag-table", &tagtable, NULL);
917   g_assert (tagtable == gtk_builder_get_object (builder, "tagtable1"));
918   g_object_unref (tagtable);
919   g_object_unref (builder);
920 }
921
922 static void
923 test_object_properties (void)
924 {
925   GtkBuilder *builder;
926   const gchar buffer[] =
927     "<interface>"
928     "  <object class=\"GtkWindow\" id=\"window1\">"
929     "    <child>"
930     "      <object class=\"GtkVBox\" id=\"vbox\">"
931     "        <property name=\"border-width\">10</property>"
932     "        <child>"
933     "          <object class=\"GtkLabel\" id=\"label1\">"
934     "            <property name=\"mnemonic-widget\">spinbutton1</property>"
935     "          </object>"
936     "        </child>"
937     "        <child>"
938     "          <object class=\"GtkSpinButton\" id=\"spinbutton1\"/>"
939     "        </child>"
940     "      </object>"
941     "    </child>"
942     "  </object>"
943     "</interface>";
944   const gchar buffer2[] =
945     "<interface>"
946     "  <object class=\"GtkWindow\" id=\"window2\"/>"
947     "</interface>";
948   GObject *label, *spinbutton, *window;
949   
950   builder = builder_new_from_string (buffer, -1, NULL);
951   label = gtk_builder_get_object (builder, "label1");
952   g_assert (label != NULL);
953   spinbutton = gtk_builder_get_object (builder, "spinbutton1");
954   g_assert (spinbutton != NULL);
955   g_assert (spinbutton == (GObject*)gtk_label_get_mnemonic_widget (GTK_LABEL (label)));
956
957   gtk_builder_add_from_string (builder, buffer2, -1, NULL);
958   window = gtk_builder_get_object (builder, "window2");
959   g_assert (window != NULL);
960   gtk_widget_destroy (GTK_WIDGET (window));
961
962   g_object_unref (builder);
963 }
964
965 static void
966 test_children (void)
967 {
968   GtkBuilder * builder;
969   GtkWidget *content_area, *dialog_action_area;
970   GList *children;
971   const gchar buffer1[] =
972     "<interface>"
973     "  <object class=\"GtkWindow\" id=\"window1\">"
974     "    <child>"
975     "      <object class=\"GtkButton\" id=\"button1\">"
976     "        <property name=\"label\">Hello</property>"
977     "      </object>"
978     "    </child>"
979     "  </object>"
980     "</interface>";
981   const gchar buffer2[] =
982     "<interface>"
983     "  <object class=\"GtkDialog\" id=\"dialog1\">"
984     "    <child internal-child=\"vbox\">"
985     "      <object class=\"GtkVBox\" id=\"dialog1-vbox\">"
986     "        <property name=\"border-width\">10</property>"
987     "          <child internal-child=\"action_area\">"
988     "            <object class=\"GtkHButtonBox\" id=\"dialog1-action_area\">"
989     "              <property name=\"border-width\">20</property>"
990     "            </object>"
991     "          </child>"
992     "      </object>"
993     "    </child>"
994     "  </object>"
995     "</interface>";
996
997   GObject *window, *button;
998   GObject *dialog, *vbox, *action_area;
999   
1000   builder = builder_new_from_string (buffer1, -1, NULL);
1001   window = gtk_builder_get_object (builder, "window1");
1002   g_assert (window != NULL);
1003   g_assert (GTK_IS_WINDOW (window));
1004
1005   button = gtk_builder_get_object (builder, "button1");
1006   g_assert (button != NULL);
1007   g_assert (GTK_IS_BUTTON (button));
1008   g_assert (gtk_widget_get_parent (GTK_WIDGET(button)) != NULL);
1009   g_assert (strcmp (gtk_buildable_get_name (GTK_BUILDABLE (gtk_widget_get_parent (GTK_WIDGET (button)))), "window1") == 0);
1010
1011   gtk_widget_destroy (GTK_WIDGET (window));
1012   g_object_unref (builder);
1013   
1014   builder = builder_new_from_string (buffer2, -1, NULL);
1015   dialog = gtk_builder_get_object (builder, "dialog1");
1016   g_assert (dialog != NULL);
1017   g_assert (GTK_IS_DIALOG (dialog));
1018   children = gtk_container_get_children (GTK_CONTAINER (dialog));
1019   g_assert (g_list_length (children) == 1);
1020   g_list_free (children);
1021   
1022   vbox = gtk_builder_get_object (builder, "dialog1-vbox");
1023   content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
1024   g_assert (vbox != NULL);
1025   g_assert (GTK_IS_BOX (vbox));
1026   g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (vbox)) == GTK_ORIENTATION_VERTICAL);
1027   g_assert (strcmp (gtk_buildable_get_name (GTK_BUILDABLE (gtk_widget_get_parent (GTK_WIDGET (vbox)))), "dialog1") == 0);
1028   g_assert (gtk_container_get_border_width (GTK_CONTAINER (vbox)) == 10);
1029   g_assert (strcmp (gtk_buildable_get_name (GTK_BUILDABLE (content_area)), "dialog1-vbox") == 0);
1030
1031   action_area = gtk_builder_get_object (builder, "dialog1-action_area");
1032   dialog_action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
1033   g_assert (action_area != NULL);
1034   g_assert (GTK_IS_BUTTON_BOX (action_area));
1035   g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (action_area)) == GTK_ORIENTATION_HORIZONTAL);
1036   g_assert (gtk_widget_get_parent (GTK_WIDGET (action_area)) != NULL);
1037   g_assert (gtk_container_get_border_width (GTK_CONTAINER (action_area)) == 20);
1038   g_assert (dialog_action_area != NULL);
1039   g_assert (gtk_buildable_get_name (GTK_BUILDABLE (action_area)) != NULL);
1040   g_assert (strcmp (gtk_buildable_get_name (GTK_BUILDABLE (dialog_action_area)), "dialog1-action_area") == 0);
1041   gtk_widget_destroy (GTK_WIDGET (dialog));
1042   g_object_unref (builder);
1043 }
1044
1045 static void
1046 test_child_properties (void)
1047 {
1048   GtkBuilder * builder;
1049   const gchar buffer1[] =
1050     "<interface>"
1051     "  <object class=\"GtkBox\" id=\"vbox1\">"
1052     "    <child>"
1053     "      <object class=\"GtkLabel\" id=\"label1\"/>"
1054     "      <packing>"
1055     "        <property name=\"pack-type\">start</property>"
1056     "      </packing>"
1057     "    </child>"
1058     "    <child>"
1059     "      <object class=\"GtkLabel\" id=\"label2\"/>"
1060     "      <packing>"
1061     "        <property name=\"pack-type\">end</property>"
1062     "      </packing>"
1063     "    </child>"
1064     "  </object>"
1065     "</interface>";
1066
1067   GObject *label, *vbox;
1068   GtkPackType pack_type;
1069   
1070   builder = builder_new_from_string (buffer1, -1, NULL);
1071   vbox = gtk_builder_get_object (builder, "vbox1");
1072   g_assert (GTK_IS_BOX (vbox));
1073
1074   label = gtk_builder_get_object (builder, "label1");
1075   g_assert (GTK_IS_LABEL (label));
1076   gtk_container_child_get (GTK_CONTAINER (vbox),
1077                            GTK_WIDGET (label),
1078                            "pack-type",
1079                            &pack_type,
1080                            NULL);
1081   g_assert (pack_type == GTK_PACK_START);
1082   
1083   label = gtk_builder_get_object (builder, "label2");
1084   g_assert (GTK_IS_LABEL (label));
1085   gtk_container_child_get (GTK_CONTAINER (vbox),
1086                            GTK_WIDGET (label),
1087                            "pack-type",
1088                            &pack_type,
1089                            NULL);
1090   g_assert (pack_type == GTK_PACK_END);
1091
1092   g_object_unref (builder);
1093 }
1094
1095 static void
1096 test_treeview_column (void)
1097 {
1098   GtkBuilder *builder;
1099   const gchar buffer[] =
1100     "<interface>"
1101     "<object class=\"GtkListStore\" id=\"liststore1\">"
1102     "  <columns>"
1103     "    <column type=\"gchararray\"/>"
1104     "    <column type=\"guint\"/>"
1105     "  </columns>"
1106     "  <data>"
1107     "    <row>"
1108     "      <col id=\"0\">John</col>"
1109     "      <col id=\"1\">25</col>"
1110     "    </row>"
1111     "  </data>"
1112     "</object>"
1113     "<object class=\"GtkWindow\" id=\"window1\">"
1114     "  <child>"
1115     "    <object class=\"GtkTreeView\" id=\"treeview1\">"
1116     "      <property name=\"visible\">True</property>"
1117     "      <property name=\"model\">liststore1</property>"
1118     "      <child>"
1119     "        <object class=\"GtkTreeViewColumn\" id=\"column1\">"
1120     "          <property name=\"title\">Test</property>"
1121     "          <child>"
1122     "            <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
1123     "            <attributes>"
1124     "              <attribute name=\"text\">1</attribute>"
1125     "            </attributes>"
1126     "          </child>"
1127     "        </object>"
1128     "      </child>"
1129     "      <child>"
1130     "        <object class=\"GtkTreeViewColumn\" id=\"column2\">"
1131     "          <property name=\"title\">Number</property>"
1132     "          <child>"
1133     "            <object class=\"GtkCellRendererText\" id=\"renderer2\"/>"
1134     "            <attributes>"
1135     "              <attribute name=\"text\">0</attribute>"
1136     "            </attributes>"
1137     "          </child>"
1138     "        </object>"
1139     "      </child>"
1140     "    </object>"
1141     "  </child>"
1142     "</object>"
1143     "</interface>";
1144   GObject *window, *treeview;
1145   GtkTreeViewColumn *column;
1146   GList *renderers;
1147   GObject *renderer;
1148   gchar *text;
1149
1150   builder = builder_new_from_string (buffer, -1, NULL);
1151   treeview = gtk_builder_get_object (builder, "treeview1");
1152   g_assert (treeview);
1153   g_assert (GTK_IS_TREE_VIEW (treeview));
1154   column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), 0);
1155   g_assert (GTK_IS_TREE_VIEW_COLUMN (column));
1156   g_assert (strcmp (gtk_tree_view_column_get_title (column), "Test") == 0);
1157
1158   renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
1159   g_assert (g_list_length (renderers) == 1);
1160   renderer = g_list_nth_data (renderers, 0);
1161   g_assert (renderer);
1162   g_assert (GTK_IS_CELL_RENDERER_TEXT (renderer));
1163   g_list_free (renderers);
1164
1165   gtk_widget_realize (GTK_WIDGET (treeview));
1166
1167   renderer = gtk_builder_get_object (builder, "renderer1");
1168   g_object_get (renderer, "text", &text, NULL);
1169   g_assert (text);
1170   g_assert (strcmp (text, "25") == 0);
1171   g_free (text);
1172   
1173   renderer = gtk_builder_get_object (builder, "renderer2");
1174   g_object_get (renderer, "text", &text, NULL);
1175   g_assert (text);
1176   g_assert (strcmp (text, "John") == 0);
1177   g_free (text);
1178
1179   gtk_widget_unrealize (GTK_WIDGET (treeview));
1180
1181   window = gtk_builder_get_object (builder, "window1");
1182   gtk_widget_destroy (GTK_WIDGET (window));
1183   
1184   g_object_unref (builder);
1185 }
1186
1187 static void
1188 test_icon_view (void)
1189 {
1190   GtkBuilder *builder;
1191   const gchar buffer[] =
1192     "<interface>"
1193     "  <object class=\"GtkListStore\" id=\"liststore1\">"
1194     "    <columns>"
1195     "      <column type=\"gchararray\"/>"
1196     "      <column type=\"GdkPixbuf\"/>"
1197     "    </columns>"
1198     "    <data>"
1199     "      <row>"
1200     "        <col id=\"0\">test</col>"
1201     "      </row>"
1202     "    </data>"
1203     "  </object>"
1204     "  <object class=\"GtkWindow\" id=\"window1\">"
1205     "    <child>"
1206     "      <object class=\"GtkIconView\" id=\"iconview1\">"
1207     "        <property name=\"model\">liststore1</property>"
1208     "        <property name=\"text-column\">0</property>"
1209     "        <property name=\"pixbuf-column\">1</property>"
1210     "        <property name=\"visible\">True</property>"
1211     "        <child>"
1212     "          <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
1213     "          <attributes>"
1214     "            <attribute name=\"text\">0</attribute>"
1215     "          </attributes>"
1216     "        </child>"
1217     "      </object>"
1218     "    </child>"
1219     "  </object>"
1220     "</interface>";
1221   GObject *window, *iconview;
1222   
1223   builder = builder_new_from_string (buffer, -1, NULL);
1224   iconview = gtk_builder_get_object (builder, "iconview1");
1225   g_assert (iconview);
1226   g_assert (GTK_IS_ICON_VIEW (iconview));
1227
1228   window = gtk_builder_get_object (builder, "window1");
1229   gtk_widget_destroy (GTK_WIDGET (window));
1230   g_object_unref (builder);
1231 }
1232
1233 static void
1234 test_combo_box (void)
1235 {
1236   GtkBuilder *builder;
1237   const gchar buffer[] =
1238     "<interface>"
1239     "  <object class=\"GtkListStore\" id=\"liststore1\">"
1240     "    <columns>"
1241     "      <column type=\"guint\"/>"
1242     "      <column type=\"gchararray\"/>"
1243     "    </columns>"
1244     "    <data>"
1245     "      <row>"
1246     "        <col id=\"0\">1</col>"
1247     "        <col id=\"1\">Foo</col>"
1248     "      </row>"
1249     "      <row>"
1250     "        <col id=\"0\">2</col>"
1251     "        <col id=\"1\">Bar</col>"
1252     "      </row>"
1253     "    </data>"
1254     "  </object>"
1255     "  <object class=\"GtkWindow\" id=\"window1\">"
1256     "    <child>"
1257     "      <object class=\"GtkComboBox\" id=\"combobox1\">"
1258     "        <property name=\"model\">liststore1</property>"
1259     "        <property name=\"visible\">True</property>"
1260     "        <child>"
1261     "          <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
1262     "          <attributes>"
1263     "            <attribute name=\"text\">0</attribute>"
1264     "          </attributes>"
1265     "        </child>"
1266     "        <child>"
1267     "          <object class=\"GtkCellRendererText\" id=\"renderer2\"/>"
1268     "          <attributes>"
1269     "            <attribute name=\"text\">1</attribute>"
1270     "          </attributes>"
1271     "        </child>"
1272     "      </object>"
1273     "    </child>"
1274     "  </object>"
1275     "</interface>";
1276   GObject *window, *combobox, *renderer;
1277   gchar *text;
1278
1279   builder = builder_new_from_string (buffer, -1, NULL);
1280   combobox = gtk_builder_get_object (builder, "combobox1");
1281   g_assert (combobox);
1282   gtk_widget_realize (GTK_WIDGET (combobox));
1283
1284   renderer = gtk_builder_get_object (builder, "renderer2");
1285   g_assert (renderer);
1286   g_object_get (renderer, "text", &text, NULL);
1287   g_assert (text);
1288   g_assert (strcmp (text, "Bar") == 0);
1289   g_free (text);
1290
1291   renderer = gtk_builder_get_object (builder, "renderer1");
1292   g_assert (renderer);
1293   g_object_get (renderer, "text", &text, NULL);
1294   g_assert (text);
1295   g_assert (strcmp (text, "2") == 0);
1296   g_free (text);
1297
1298   window = gtk_builder_get_object (builder, "window1");
1299   gtk_widget_destroy (GTK_WIDGET (window));
1300
1301   g_object_unref (builder);
1302 }
1303
1304 #if 0
1305 static void
1306 test_combo_box_entry (void)
1307 {
1308   GtkBuilder *builder;
1309   const gchar buffer[] =
1310     "<interface>"
1311     "  <object class=\"GtkListStore\" id=\"liststore1\">"
1312     "    <columns>"
1313     "      <column type=\"guint\"/>"
1314     "      <column type=\"gchararray\"/>"
1315     "    </columns>"
1316     "    <data>"
1317     "      <row>"
1318     "        <col id=\"0\">1</col>"
1319     "        <col id=\"1\">Foo</col>"
1320     "      </row>"
1321     "      <row>"
1322     "        <col id=\"0\">2</col>"
1323     "        <col id=\"1\">Bar</col>"
1324     "      </row>"
1325     "    </data>"
1326     "  </object>"
1327     "  <object class=\"GtkWindow\" id=\"window1\">"
1328     "    <child>"
1329     "      <object class=\"GtkComboBox\" id=\"comboboxentry1\">"
1330     "        <property name=\"model\">liststore1</property>"
1331     "        <property name=\"has-entry\">True</property>"
1332     "        <property name=\"visible\">True</property>"
1333     "        <child>"
1334     "          <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
1335     "            <attributes>"
1336     "              <attribute name=\"text\">0</attribute>"
1337     "            </attributes>"
1338     "        </child>"
1339     "        <child>"
1340     "          <object class=\"GtkCellRendererText\" id=\"renderer2\"/>"
1341     "            <attributes>"
1342     "              <attribute name=\"text\">1</attribute>"
1343     "            </attributes>"
1344     "        </child>"
1345     "      </object>"
1346     "    </child>"
1347     "  </object>"
1348     "</interface>";
1349   GObject *window, *combobox, *renderer;
1350   gchar *text;
1351
1352   builder = builder_new_from_string (buffer, -1, NULL);
1353   combobox = gtk_builder_get_object (builder, "comboboxentry1");
1354   g_assert (combobox);
1355
1356   renderer = gtk_builder_get_object (builder, "renderer2");
1357   g_assert (renderer);
1358   g_object_get (renderer, "text", &text, NULL);
1359   g_assert (text);
1360   g_assert (strcmp (text, "Bar") == 0);
1361   g_free (text);
1362
1363   renderer = gtk_builder_get_object (builder, "renderer1");
1364   g_assert (renderer);
1365   g_object_get (renderer, "text", &text, NULL);
1366   g_assert (text);
1367   g_assert (strcmp (text, "2") == 0);
1368   g_free (text);
1369
1370   window = gtk_builder_get_object (builder, "window1");
1371   gtk_widget_destroy (GTK_WIDGET (window));
1372
1373   g_object_unref (builder);
1374 }
1375 #endif
1376
1377 static void
1378 test_cell_view (void)
1379 {
1380   GtkBuilder *builder;
1381   const gchar *buffer =
1382     "<interface>"
1383     "  <object class=\"GtkListStore\" id=\"liststore1\">"
1384     "    <columns>"
1385     "      <column type=\"gchararray\"/>"
1386     "    </columns>"
1387     "    <data>"
1388     "      <row>"
1389     "        <col id=\"0\">test</col>"
1390     "      </row>"
1391     "    </data>"
1392     "  </object>"
1393     "  <object class=\"GtkWindow\" id=\"window1\">"
1394     "    <child>"
1395     "      <object class=\"GtkCellView\" id=\"cellview1\">"
1396     "        <property name=\"visible\">True</property>"
1397     "        <property name=\"model\">liststore1</property>"
1398     "        <accelerator key=\"f\" modifiers=\"GDK_CONTROL_MASK\" signal=\"grab_focus\"/>"
1399     "        <child>"
1400     "          <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
1401     "          <attributes>"
1402     "            <attribute name=\"text\">0</attribute>"
1403     "          </attributes>"
1404     "        </child>"
1405     "      </object>"
1406     "    </child>"
1407     "  </object>"
1408     "</interface>";
1409   GObject *cellview;
1410   GObject *model, *window;
1411   GtkTreePath *path;
1412   GList *renderers;
1413   GObject *renderer;
1414   gchar *text;
1415   
1416   builder = builder_new_from_string (buffer, -1, NULL);
1417   cellview = gtk_builder_get_object (builder, "cellview1");
1418   g_assert (builder);
1419   g_assert (cellview);
1420   g_assert (GTK_IS_CELL_VIEW (cellview));
1421   g_object_get (cellview, "model", &model, NULL);
1422   g_assert (model);
1423   g_assert (GTK_IS_TREE_MODEL (model));
1424   g_object_unref (model);
1425   path = gtk_tree_path_new_first ();
1426   gtk_cell_view_set_displayed_row (GTK_CELL_VIEW (cellview), path);
1427   
1428   renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cellview));
1429   g_assert (renderers);
1430   g_assert (g_list_length (renderers) == 1);
1431   
1432   gtk_widget_realize (GTK_WIDGET (cellview));
1433
1434   renderer = g_list_nth_data (renderers, 0);
1435   g_list_free (renderers);
1436   g_assert (renderer);
1437   g_object_get (renderer, "text", &text, NULL);
1438   g_assert (strcmp (text, "test") == 0);
1439   g_free (text);
1440   gtk_tree_path_free (path);
1441
1442   window = gtk_builder_get_object (builder, "window1");
1443   gtk_widget_destroy (GTK_WIDGET (window));
1444   
1445   g_object_unref (builder);
1446 }
1447
1448 static void
1449 test_dialog (void)
1450 {
1451   GtkBuilder * builder;
1452   const gchar buffer1[] =
1453     "<interface>"
1454     "  <object class=\"GtkDialog\" id=\"dialog1\">"
1455     "    <child internal-child=\"vbox\">"
1456     "      <object class=\"GtkVBox\" id=\"dialog1-vbox\">"
1457     "          <child internal-child=\"action_area\">"
1458     "            <object class=\"GtkHButtonBox\" id=\"dialog1-action_area\">"
1459     "              <child>"
1460     "                <object class=\"GtkButton\" id=\"button_cancel\"/>"
1461     "              </child>"
1462     "              <child>"
1463     "                <object class=\"GtkButton\" id=\"button_ok\"/>"
1464     "              </child>"
1465     "            </object>"
1466     "          </child>"
1467     "      </object>"
1468     "    </child>"
1469     "    <action-widgets>"
1470     "      <action-widget response=\"3\">button_ok</action-widget>"
1471     "      <action-widget response=\"-5\">button_cancel</action-widget>"
1472     "    </action-widgets>"
1473     "  </object>"
1474     "</interface>";
1475
1476   GObject *dialog1;
1477   GObject *button_ok;
1478   GObject *button_cancel;
1479   
1480   builder = builder_new_from_string (buffer1, -1, NULL);
1481   dialog1 = gtk_builder_get_object (builder, "dialog1");
1482   button_ok = gtk_builder_get_object (builder, "button_ok");
1483   g_assert (gtk_dialog_get_response_for_widget (GTK_DIALOG (dialog1), GTK_WIDGET (button_ok)) == 3);
1484   button_cancel = gtk_builder_get_object (builder, "button_cancel");
1485   g_assert (gtk_dialog_get_response_for_widget (GTK_DIALOG (dialog1), GTK_WIDGET (button_cancel)) == -5);
1486   
1487   gtk_widget_destroy (GTK_WIDGET (dialog1));
1488   g_object_unref (builder);
1489 }
1490
1491 static void
1492 test_message_dialog (void)
1493 {
1494   GtkBuilder * builder;
1495   const gchar buffer1[] =
1496     "<interface>"
1497     "  <object class=\"GtkMessageDialog\" id=\"dialog1\">"
1498     "    <child internal-child=\"message_area\">"
1499     "      <object class=\"GtkVBox\" id=\"dialog-message-area\">"
1500     "        <child>"
1501     "          <object class=\"GtkExpander\" id=\"expander\"/>"
1502     "        </child>"
1503     "      </object>"
1504     "    </child>"
1505     "  </object>"
1506     "</interface>";
1507
1508   GObject *dialog1;
1509   GObject *expander;
1510
1511   builder = builder_new_from_string (buffer1, -1, NULL);
1512   dialog1 = gtk_builder_get_object (builder, "dialog1");
1513   expander = gtk_builder_get_object (builder, "expander");
1514   g_assert (GTK_IS_EXPANDER (expander));
1515   g_assert (gtk_widget_get_parent (GTK_WIDGET (expander)) == gtk_message_dialog_get_message_area (GTK_MESSAGE_DIALOG (dialog1)));
1516
1517   gtk_widget_destroy (GTK_WIDGET (dialog1));
1518   g_object_unref (builder);
1519 }
1520
1521 static void
1522 test_accelerators (void)
1523 {
1524   GtkBuilder *builder;
1525   const gchar *buffer =
1526     "<interface>"
1527     "  <object class=\"GtkWindow\" id=\"window1\">"
1528     "    <child>"
1529     "      <object class=\"GtkButton\" id=\"button1\">"
1530     "        <accelerator key=\"q\" modifiers=\"GDK_CONTROL_MASK\" signal=\"clicked\"/>"
1531     "      </object>"
1532     "    </child>"
1533     "  </object>"
1534     "</interface>";
1535   const gchar *buffer2 =
1536     "<interface>"
1537     "  <object class=\"GtkWindow\" id=\"window1\">"
1538     "    <child>"
1539     "      <object class=\"GtkTreeView\" id=\"treeview1\">"
1540     "        <signal name=\"cursor-changed\" handler=\"gtk_main_quit\"/>"
1541     "        <accelerator key=\"f\" modifiers=\"GDK_CONTROL_MASK\" signal=\"grab_focus\"/>"
1542     "      </object>"
1543     "    </child>"
1544     "  </object>"
1545     "</interface>";
1546   GObject *window1;
1547   GSList *accel_groups;
1548   GObject *accel_group;
1549   
1550   builder = builder_new_from_string (buffer, -1, NULL);
1551   window1 = gtk_builder_get_object (builder, "window1");
1552   g_assert (window1);
1553   g_assert (GTK_IS_WINDOW (window1));
1554
1555   accel_groups = gtk_accel_groups_from_object (window1);
1556   g_assert (g_slist_length (accel_groups) == 1);
1557   accel_group = g_slist_nth_data (accel_groups, 0);
1558   g_assert (accel_group);
1559
1560   gtk_widget_destroy (GTK_WIDGET (window1));
1561   g_object_unref (builder);
1562
1563   builder = builder_new_from_string (buffer2, -1, NULL);
1564   window1 = gtk_builder_get_object (builder, "window1");
1565   g_assert (window1);
1566   g_assert (GTK_IS_WINDOW (window1));
1567
1568   accel_groups = gtk_accel_groups_from_object (window1);
1569   g_assert (g_slist_length (accel_groups) == 1);
1570   accel_group = g_slist_nth_data (accel_groups, 0);
1571   g_assert (accel_group);
1572
1573   gtk_widget_destroy (GTK_WIDGET (window1));
1574   g_object_unref (builder);
1575 }
1576
1577 static void
1578 test_widget (void)
1579 {
1580   const gchar *buffer =
1581     "<interface>"
1582     "  <object class=\"GtkWindow\" id=\"window1\">"
1583     "    <child>"
1584     "      <object class=\"GtkButton\" id=\"button1\">"
1585     "         <property name=\"can-focus\">True</property>"
1586     "         <property name=\"has-focus\">True</property>"
1587     "      </object>"
1588     "    </child>"
1589     "  </object>"
1590    "</interface>";
1591   const gchar *buffer2 =
1592     "<interface>"
1593     "  <object class=\"GtkWindow\" id=\"window1\">"
1594     "    <child>"
1595     "      <object class=\"GtkButton\" id=\"button1\">"
1596     "         <property name=\"can-default\">True</property>"
1597     "         <property name=\"has-default\">True</property>"
1598     "      </object>"
1599     "    </child>"
1600     "  </object>"
1601    "</interface>";
1602   const gchar *buffer3 =
1603     "<interface>"
1604     "  <object class=\"GtkWindow\" id=\"window1\">"
1605     "    <child>"
1606     "      <object class=\"GtkVBox\" id=\"vbox1\">"
1607     "        <child>"
1608     "          <object class=\"GtkLabel\" id=\"label1\">"
1609     "            <child internal-child=\"accessible\">"
1610     "              <object class=\"AtkObject\" id=\"a11y-label1\">"
1611     "                <property name=\"AtkObject::accessible-name\">A Label</property>"
1612     "              </object>"
1613     "            </child>"
1614     "            <accessibility>"
1615     "              <relation target=\"button1\" type=\"label-for\"/>"
1616     "            </accessibility>"
1617     "          </object>"
1618     "        </child>"
1619     "        <child>"
1620     "          <object class=\"GtkButton\" id=\"button1\">"
1621     "            <accessibility>"
1622     "              <action action_name=\"click\" description=\"Sliff\"/>"
1623     "              <action action_name=\"clack\" translatable=\"yes\">Sniff</action>"
1624     "            </accessibility>"
1625     "          </object>"
1626     "        </child>"
1627     "      </object>"
1628     "    </child>"
1629     "  </object>"
1630     "</interface>";
1631   GtkBuilder *builder;
1632   GObject *window1, *button1, *label1;
1633   AtkObject *accessible;
1634   AtkRelationSet *relation_set;
1635   AtkRelation *relation;
1636   char *name;
1637   
1638   builder = builder_new_from_string (buffer, -1, NULL);
1639   button1 = gtk_builder_get_object (builder, "button1");
1640
1641 #if 0
1642   g_assert (gtk_widget_has_focus (GTK_WIDGET (button1)));
1643 #endif
1644   window1 = gtk_builder_get_object (builder, "window1");
1645   gtk_widget_destroy (GTK_WIDGET (window1));
1646   
1647   g_object_unref (builder);
1648   
1649   builder = builder_new_from_string (buffer2, -1, NULL);
1650   button1 = gtk_builder_get_object (builder, "button1");
1651
1652   g_assert (gtk_widget_get_receives_default (GTK_WIDGET (button1)));
1653   
1654   g_object_unref (builder);
1655   
1656   builder = builder_new_from_string (buffer3, -1, NULL);
1657
1658   window1 = gtk_builder_get_object (builder, "window1");
1659   label1 = gtk_builder_get_object (builder, "label1");
1660
1661   accessible = gtk_widget_get_accessible (GTK_WIDGET (label1));
1662   relation_set = atk_object_ref_relation_set (accessible);
1663   g_return_if_fail (atk_relation_set_get_n_relations (relation_set) == 1);
1664   relation = atk_relation_set_get_relation (relation_set, 0);
1665   g_return_if_fail (relation != NULL);
1666   g_return_if_fail (ATK_IS_RELATION (relation));
1667   g_return_if_fail (atk_relation_get_relation_type (relation) != ATK_RELATION_LABELLED_BY);
1668   g_object_unref (relation_set);
1669
1670   g_object_get (G_OBJECT (accessible), "accessible-name", &name, NULL);
1671   g_return_if_fail (strcmp (name, "A Label") == 0);
1672   g_free (name);
1673   
1674   gtk_widget_destroy (GTK_WIDGET (window1));
1675   g_object_unref (builder);
1676 }
1677
1678 static void
1679 test_window (void)
1680 {
1681   const gchar *buffer1 =
1682     "<interface>"
1683     "  <object class=\"GtkWindow\" id=\"window1\">"
1684     "     <property name=\"title\"></property>"
1685     "  </object>"
1686    "</interface>";
1687   const gchar *buffer2 =
1688     "<interface>"
1689     "  <object class=\"GtkWindow\" id=\"window1\">"
1690     "  </object>"
1691    "</interface>";
1692   GtkBuilder *builder;
1693   GObject *window1;
1694   gchar *title;
1695   
1696   builder = builder_new_from_string (buffer1, -1, NULL);
1697   window1 = gtk_builder_get_object (builder, "window1");
1698   g_object_get (window1, "title", &title, NULL);
1699   g_assert (strcmp (title, "") == 0);
1700   g_free (title);
1701   gtk_widget_destroy (GTK_WIDGET (window1));
1702   g_object_unref (builder);
1703
1704   builder = builder_new_from_string (buffer2, -1, NULL);
1705   window1 = gtk_builder_get_object (builder, "window1");
1706   gtk_widget_destroy (GTK_WIDGET (window1));
1707   g_object_unref (builder);
1708 }
1709
1710 static void
1711 test_value_from_string (void)
1712 {
1713   GValue value = G_VALUE_INIT;
1714   GError *error = NULL;
1715   GtkBuilder *builder;
1716
1717   builder = gtk_builder_new ();
1718   
1719   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_STRING, "test", &value, &error));
1720   g_assert (G_VALUE_HOLDS_STRING (&value));
1721   g_assert (strcmp (g_value_get_string (&value), "test") == 0);
1722   g_value_unset (&value);
1723
1724   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, "true", &value, &error));
1725   g_assert (G_VALUE_HOLDS_BOOLEAN (&value));
1726   g_assert (g_value_get_boolean (&value) == TRUE);
1727   g_value_unset (&value);
1728
1729   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, "false", &value, &error));
1730   g_assert (G_VALUE_HOLDS_BOOLEAN (&value));
1731   g_assert (g_value_get_boolean (&value) == FALSE);
1732   g_value_unset (&value);
1733
1734   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, "yes", &value, &error));
1735   g_assert (G_VALUE_HOLDS_BOOLEAN (&value));
1736   g_assert (g_value_get_boolean (&value) == TRUE);
1737   g_value_unset (&value);
1738
1739   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, "no", &value, &error));
1740   g_assert (G_VALUE_HOLDS_BOOLEAN (&value));
1741   g_assert (g_value_get_boolean (&value) == FALSE);
1742   g_value_unset (&value);
1743
1744   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, "0", &value, &error));
1745   g_assert (G_VALUE_HOLDS_BOOLEAN (&value));
1746   g_assert (g_value_get_boolean (&value) == FALSE);
1747   g_value_unset (&value);
1748
1749   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, "1", &value, &error));
1750   g_assert (G_VALUE_HOLDS_BOOLEAN (&value));
1751   g_assert (g_value_get_boolean (&value) == TRUE);
1752   g_value_unset (&value);
1753
1754   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, "tRuE", &value, &error));
1755   g_assert (G_VALUE_HOLDS_BOOLEAN (&value));
1756   g_assert (g_value_get_boolean (&value) == TRUE);
1757   g_value_unset (&value);
1758   
1759   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, "blaurgh", &value, &error) == FALSE);
1760   g_value_unset (&value);
1761   g_assert (g_error_matches (error,
1762                              GTK_BUILDER_ERROR,
1763                              GTK_BUILDER_ERROR_INVALID_VALUE));
1764   g_error_free (error);
1765   error = NULL;
1766
1767   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, "yess", &value, &error) == FALSE);
1768   g_value_unset (&value);
1769   g_assert (g_error_matches (error,
1770                              GTK_BUILDER_ERROR,
1771                              GTK_BUILDER_ERROR_INVALID_VALUE));
1772   g_error_free (error);
1773   error = NULL;
1774   
1775   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, "trueee", &value, &error) == FALSE);
1776   g_value_unset (&value);
1777   g_assert (g_error_matches (error,
1778                              GTK_BUILDER_ERROR,
1779                              GTK_BUILDER_ERROR_INVALID_VALUE));
1780   g_error_free (error);
1781   error = NULL;
1782   
1783   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, "", &value, &error) == FALSE);
1784   g_value_unset (&value);
1785   g_assert (g_error_matches (error,
1786                              GTK_BUILDER_ERROR,
1787                              GTK_BUILDER_ERROR_INVALID_VALUE));
1788   g_error_free (error);
1789   error = NULL;
1790   
1791   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_INT, "12345", &value, &error));
1792   g_assert (G_VALUE_HOLDS_INT (&value));
1793   g_assert (g_value_get_int (&value) == 12345);
1794   g_value_unset (&value);
1795
1796   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_LONG, "9912345", &value, &error));
1797   g_assert (G_VALUE_HOLDS_LONG (&value));
1798   g_assert (g_value_get_long (&value) == 9912345);
1799   g_value_unset (&value);
1800
1801   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_UINT, "2345", &value, &error));
1802   g_assert (G_VALUE_HOLDS_UINT (&value));
1803   g_assert (g_value_get_uint (&value) == 2345);
1804   g_value_unset (&value);
1805
1806   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_FLOAT, "1.454", &value, &error));
1807   g_assert (G_VALUE_HOLDS_FLOAT (&value));
1808   g_assert (fabs (g_value_get_float (&value) - 1.454) < 0.00001);
1809   g_value_unset (&value);
1810
1811   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_FLOAT, "abc", &value, &error) == FALSE);
1812   g_value_unset (&value);
1813   g_assert (g_error_matches (error,
1814                              GTK_BUILDER_ERROR,
1815                              GTK_BUILDER_ERROR_INVALID_VALUE));
1816   g_error_free (error);
1817   error = NULL;
1818
1819   g_assert (gtk_builder_value_from_string_type (builder, G_TYPE_INT, "/-+,abc", &value, &error) == FALSE);
1820   g_value_unset (&value);
1821   g_assert (g_error_matches (error,
1822                              GTK_BUILDER_ERROR,
1823                              GTK_BUILDER_ERROR_INVALID_VALUE));
1824   g_error_free (error);
1825   error = NULL;
1826
1827   g_assert (gtk_builder_value_from_string_type (builder, GTK_TYPE_WINDOW_TYPE, "toplevel", &value, &error) == TRUE);
1828   g_assert (G_VALUE_HOLDS_ENUM (&value));
1829   g_assert (g_value_get_enum (&value) == GTK_WINDOW_TOPLEVEL);
1830   g_value_unset (&value);
1831
1832   g_assert (gtk_builder_value_from_string_type (builder, GTK_TYPE_WINDOW_TYPE, "sliff", &value, &error) == FALSE);
1833   g_value_unset (&value);
1834   g_assert (g_error_matches (error,
1835                              GTK_BUILDER_ERROR,
1836                              GTK_BUILDER_ERROR_INVALID_VALUE));
1837   g_error_free (error);
1838   error = NULL;
1839
1840   g_assert (gtk_builder_value_from_string_type (builder, GTK_TYPE_WINDOW_TYPE, "foobar", &value, &error) == FALSE);
1841   g_value_unset (&value);
1842   g_assert (g_error_matches (error,
1843                              GTK_BUILDER_ERROR,
1844                              GTK_BUILDER_ERROR_INVALID_VALUE));
1845   g_error_free (error);
1846   error = NULL;
1847   
1848   g_object_unref (builder);
1849 }
1850
1851 static gboolean model_freed = FALSE;
1852
1853 static void
1854 model_weakref (gpointer data,
1855                GObject *model)
1856 {
1857   model_freed = TRUE;
1858 }
1859
1860 static void
1861 test_reference_counting (void)
1862 {
1863   GtkBuilder *builder;
1864   const gchar buffer1[] =
1865     "<interface>"
1866     "  <object class=\"GtkListStore\" id=\"liststore1\"/>"
1867     "  <object class=\"GtkListStore\" id=\"liststore2\"/>"
1868     "  <object class=\"GtkWindow\" id=\"window1\">"
1869     "    <child>"
1870     "      <object class=\"GtkTreeView\" id=\"treeview1\">"
1871     "        <property name=\"model\">liststore1</property>"
1872     "      </object>"
1873     "    </child>"
1874     "  </object>"
1875     "</interface>";
1876   const gchar buffer2[] =
1877     "<interface>"
1878     "  <object class=\"GtkVBox\" id=\"vbox1\">"
1879     "    <child>"
1880     "      <object class=\"GtkLabel\" id=\"label1\"/>"
1881     "      <packing>"
1882     "        <property name=\"pack-type\">start</property>"
1883     "      </packing>"
1884     "    </child>"
1885     "  </object>"
1886     "</interface>";
1887   GObject *window, *treeview, *model;
1888   
1889   builder = builder_new_from_string (buffer1, -1, NULL);
1890   window = gtk_builder_get_object (builder, "window1");
1891   treeview = gtk_builder_get_object (builder, "treeview1");
1892   model = gtk_builder_get_object (builder, "liststore1");
1893   g_object_unref (builder);
1894
1895   g_object_weak_ref (model, (GWeakNotify)model_weakref, NULL);
1896
1897   g_assert (model_freed == FALSE);
1898   gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), NULL);
1899   g_assert (model_freed == TRUE);
1900   
1901   gtk_widget_destroy (GTK_WIDGET (window));
1902
1903   builder = builder_new_from_string (buffer2, -1, NULL);
1904   g_object_unref (builder);
1905 }
1906
1907 static void
1908 test_icon_factory (void)
1909 {
1910   GtkBuilder *builder;
1911   const gchar buffer1[] =
1912     "<interface>"
1913     "  <object class=\"GtkIconFactory\" id=\"iconfactory1\">"
1914     "    <sources>"
1915     "      <source stock-id=\"apple-red\" filename=\"apple-red.png\"/>"
1916     "    </sources>"
1917     "  </object>"
1918     "</interface>";
1919   const gchar buffer2[] =
1920     "<interface>"
1921     "  <object class=\"GtkIconFactory\" id=\"iconfactory1\">"
1922     "    <sources>"
1923     "      <source stock-id=\"sliff\" direction=\"rtl\" state=\"active\""
1924     "              size=\"menu\" filename=\"sloff.png\"/>"
1925     "      <source stock-id=\"sliff\" direction=\"ltr\" state=\"selected\""
1926     "              size=\"dnd\" filename=\"slurf.png\"/>"
1927     "    </sources>"
1928     "  </object>"
1929     "</interface>";
1930 #if 0
1931   const gchar buffer3[] =
1932     "<interface>"
1933     "  <object class=\"GtkIconFactory\" id=\"iconfactory1\">"
1934     "    <invalid/>"
1935     "  </object>"
1936     "</interface>";
1937   const gchar buffer4[] =
1938     "<interface>"
1939     "  <object class=\"GtkIconFactory\" id=\"iconfactory1\">"
1940     "    <sources>"
1941     "      <invalid/>"
1942     "    </sources>"
1943     "  </object>"
1944     "</interface>";
1945   const gchar buffer5[] =
1946     "<interface>"
1947     "  <object class=\"GtkIconFactory\" id=\"iconfactory1\">"
1948     "    <sources>"
1949     "      <source/>"
1950     "    </sources>"
1951     "  </object>"
1952     "</interface>";
1953   GError *error = NULL;
1954 #endif  
1955   GObject *factory;
1956   GtkIconSet *icon_set;
1957   GtkIconSource *icon_source;
1958   GtkWidget *image;
1959   
1960   builder = builder_new_from_string (buffer1, -1, NULL);
1961   factory = gtk_builder_get_object (builder, "iconfactory1");
1962   g_assert (factory != NULL);
1963
1964   icon_set = gtk_icon_factory_lookup (GTK_ICON_FACTORY (factory), "apple-red");
1965   g_assert (icon_set != NULL);
1966   gtk_icon_factory_add_default (GTK_ICON_FACTORY (factory));
1967   image = gtk_image_new_from_stock ("apple-red", GTK_ICON_SIZE_BUTTON);
1968   g_assert (image != NULL);
1969   g_object_ref_sink (image);
1970   g_object_unref (image);
1971
1972   g_object_unref (builder);
1973
1974   builder = builder_new_from_string (buffer2, -1, NULL);
1975   factory = gtk_builder_get_object (builder, "iconfactory1");
1976   g_assert (factory != NULL);
1977
1978   icon_set = gtk_icon_factory_lookup (GTK_ICON_FACTORY (factory), "sliff");
1979   g_assert (icon_set != NULL);
1980   g_assert (g_slist_length (icon_set->sources) == 2);
1981
1982   icon_source = icon_set->sources->data;
1983   g_assert (gtk_icon_source_get_direction (icon_source) == GTK_TEXT_DIR_RTL);
1984   g_assert (gtk_icon_source_get_state (icon_source) == GTK_STATE_ACTIVE);
1985   g_assert (gtk_icon_source_get_size (icon_source) == GTK_ICON_SIZE_MENU);
1986   g_assert (g_str_has_suffix (gtk_icon_source_get_filename (icon_source), "sloff.png"));
1987   
1988   icon_source = icon_set->sources->next->data;
1989   g_assert (gtk_icon_source_get_direction (icon_source) == GTK_TEXT_DIR_LTR);
1990   g_assert (gtk_icon_source_get_state (icon_source) == GTK_STATE_SELECTED);
1991   g_assert (gtk_icon_source_get_size (icon_source) == GTK_ICON_SIZE_DND);
1992   g_assert (g_str_has_suffix (gtk_icon_source_get_filename (icon_source), "slurf.png"));
1993
1994   g_object_unref (builder);
1995
1996 #if 0
1997   error = NULL;
1998   gtk_builder_add_from_string (builder, buffer3, -1, &error);
1999   g_assert (g_error_matches (error,
2000                              GTK_BUILDER_ERROR,
2001                              GTK_BUILDER_ERROR_INVALID_TAG));
2002   g_error_free (error);
2003
2004   error = NULL;
2005   gtk_builder_add_from_string (builder, buffer4, -1, &error);
2006   g_assert (g_error_matches (error,
2007                              GTK_BUILDER_ERROR,
2008                              GTK_BUILDER_ERROR_INVALID_TAG));
2009   g_error_free (error);
2010
2011   error = NULL;
2012   gtk_builder_add_from_string (builder, buffer5, -1, &error);
2013   g_assert (g_error_matches (error,
2014                              GTK_BUILDER_ERROR,
2015                              GTK_BUILDER_ERROR_INVALID_ATTRIBUTE));
2016   g_error_free (error);
2017 #endif
2018
2019 }
2020
2021 typedef struct {
2022   gboolean weight;
2023   gboolean foreground;
2024   gboolean underline;
2025   gboolean size;
2026   gboolean font_desc;
2027   gboolean language;
2028 } FoundAttrs;
2029
2030 static gboolean 
2031 filter_pango_attrs (PangoAttribute *attr, 
2032                     gpointer        data)
2033 {
2034   FoundAttrs *found = (FoundAttrs *)data;
2035
2036   if (attr->klass->type == PANGO_ATTR_WEIGHT)
2037     found->weight = TRUE;
2038   else if (attr->klass->type == PANGO_ATTR_FOREGROUND)
2039     found->foreground = TRUE;
2040   else if (attr->klass->type == PANGO_ATTR_UNDERLINE)
2041     found->underline = TRUE;
2042   /* Make sure optional start/end properties are working */
2043   else if (attr->klass->type == PANGO_ATTR_SIZE && 
2044            attr->start_index == 5 &&
2045            attr->end_index   == 10)
2046     found->size = TRUE;
2047   else if (attr->klass->type == PANGO_ATTR_FONT_DESC)
2048     found->font_desc = TRUE;
2049   else if (attr->klass->type == PANGO_ATTR_LANGUAGE)
2050     found->language = TRUE;
2051
2052   return TRUE;
2053 }
2054
2055 static void
2056 test_pango_attributes (void)
2057 {
2058   GtkBuilder *builder;
2059   FoundAttrs found = { 0, };
2060   const gchar buffer[] =
2061     "<interface>"
2062     "  <object class=\"GtkLabel\" id=\"label1\">"
2063     "    <attributes>"
2064     "      <attribute name=\"weight\" value=\"PANGO_WEIGHT_BOLD\"/>"
2065     "      <attribute name=\"foreground\" value=\"DarkSlateGray\"/>"
2066     "      <attribute name=\"underline\" value=\"True\"/>"
2067     "      <attribute name=\"size\" value=\"4\" start=\"5\" end=\"10\"/>"
2068     "      <attribute name=\"font-desc\" value=\"Sans Italic 22\"/>"
2069     "      <attribute name=\"language\" value=\"pt_BR\"/>"
2070     "    </attributes>"
2071     "  </object>"
2072     "</interface>";
2073   const gchar err_buffer1[] =
2074     "<interface>"
2075     "  <object class=\"GtkLabel\" id=\"label1\">"
2076     "    <attributes>"
2077     "      <attribute name=\"weight\"/>"
2078     "    </attributes>"
2079     "  </object>"
2080     "</interface>";
2081   const gchar err_buffer2[] =
2082     "<interface>"
2083     "  <object class=\"GtkLabel\" id=\"label1\">"
2084     "    <attributes>"
2085     "      <attribute name=\"weight\" value=\"PANGO_WEIGHT_BOLD\" unrecognized=\"True\"/>"
2086     "    </attributes>"
2087     "  </object>"
2088     "</interface>";
2089
2090   GObject *label;
2091   GError  *error = NULL;
2092   PangoAttrList *attrs, *filtered;
2093   
2094   /* Test attributes are set */
2095   builder = builder_new_from_string (buffer, -1, NULL);
2096   label = gtk_builder_get_object (builder, "label1");
2097   g_assert (label != NULL);
2098
2099   attrs = gtk_label_get_attributes (GTK_LABEL (label));
2100   g_assert (attrs != NULL);
2101
2102   filtered = pango_attr_list_filter (attrs, filter_pango_attrs, &found);
2103   g_assert (filtered);
2104   pango_attr_list_unref (filtered);
2105
2106   g_assert (found.weight);
2107   g_assert (found.foreground);
2108   g_assert (found.underline);
2109   g_assert (found.size);
2110   g_assert (found.language);
2111   g_assert (found.font_desc);
2112
2113   g_object_unref (builder);
2114
2115   /* Test errors are set */
2116   builder = gtk_builder_new ();
2117   gtk_builder_add_from_string (builder, err_buffer1, -1, &error);
2118   label = gtk_builder_get_object (builder, "label1");
2119   g_assert (g_error_matches (error,
2120                              GTK_BUILDER_ERROR,
2121                              GTK_BUILDER_ERROR_MISSING_ATTRIBUTE));
2122   g_object_unref (builder);
2123   g_error_free (error);
2124   error = NULL;
2125
2126   builder = gtk_builder_new ();
2127   gtk_builder_add_from_string (builder, err_buffer2, -1, &error);
2128   label = gtk_builder_get_object (builder, "label1");
2129
2130   g_assert (g_error_matches (error,
2131                              GTK_BUILDER_ERROR,
2132                              GTK_BUILDER_ERROR_INVALID_ATTRIBUTE));
2133   g_object_unref (builder);
2134   g_error_free (error);
2135 }
2136
2137 static void
2138 test_requires (void)
2139 {
2140   GtkBuilder *builder;
2141   GError     *error = NULL;
2142   gchar      *buffer;
2143   const gchar buffer_fmt[] =
2144     "<interface>"
2145     "  <requires lib=\"gtk+\" version=\"%d.%d\"/>"
2146     "</interface>";
2147
2148   buffer = g_strdup_printf (buffer_fmt, GTK_MAJOR_VERSION, GTK_MINOR_VERSION + 1);
2149   builder = gtk_builder_new ();
2150   gtk_builder_add_from_string (builder, buffer, -1, &error);
2151   g_assert (g_error_matches (error,
2152                              GTK_BUILDER_ERROR,
2153                              GTK_BUILDER_ERROR_VERSION_MISMATCH));
2154   g_object_unref (builder);
2155   g_error_free (error);
2156   g_free (buffer);
2157 }
2158
2159 static void
2160 test_add_objects (void)
2161 {
2162   GtkBuilder *builder;
2163   GError *error;
2164   gint ret;
2165   GObject *obj;
2166   GtkUIManager *manager;
2167   GtkWidget *menubar;
2168   GObject *menu, *label;
2169   GList *children;
2170   gchar *objects[2] = {"mainbox", NULL};
2171   gchar *objects2[3] = {"mainbox", "window2", NULL};
2172   gchar *objects3[3] = {"uimgr1", "menubar1"};
2173   gchar *objects4[2] = {"uimgr1", NULL};
2174   const gchar buffer[] =
2175     "<interface>"
2176     "  <object class=\"GtkWindow\" id=\"window\">"
2177     "    <child>"
2178     "      <object class=\"GtkVBox\" id=\"mainbox\">"
2179     "        <property name=\"visible\">True</property>"
2180     "        <child>"
2181     "          <object class=\"GtkLabel\" id=\"label1\">"
2182     "            <property name=\"visible\">True</property>"
2183     "            <property name=\"label\" translatable=\"no\">first label</property>"
2184     "          </object>"
2185     "        </child>"
2186     "        <child>"
2187     "          <object class=\"GtkLabel\" id=\"label2\">"
2188     "            <property name=\"visible\">True</property>"
2189     "            <property name=\"label\" translatable=\"no\">second label</property>"
2190     "          </object>"
2191     "          <packing>"
2192     "            <property name=\"position\">1</property>"
2193     "          </packing>"
2194     "        </child>"
2195     "      </object>"
2196     "    </child>"
2197     "  </object>"
2198     "  <object class=\"GtkWindow\" id=\"window2\">"
2199     "    <child>"
2200     "      <object class=\"GtkLabel\" id=\"label3\">"
2201     "        <property name=\"label\" translatable=\"no\">second label</property>"
2202     "      </object>"
2203     "    </child>"
2204     "  </object>"
2205     "<interface/>";
2206   const gchar buffer2[] =
2207     "<interface>"
2208     "  <object class=\"GtkUIManager\" id=\"uimgr1\">"
2209     "    <child>"
2210     "      <object class=\"GtkActionGroup\" id=\"ag1\">"
2211     "        <child>"
2212     "          <object class=\"GtkAction\" id=\"file\">"
2213     "            <property name=\"label\">_File</property>"
2214     "          </object>"
2215     "          <accelerator key=\"n\" modifiers=\"GDK_CONTROL_MASK\"/>"
2216     "        </child>"
2217     "      </object>"
2218     "    </child>"
2219     "    <ui>"
2220     "      <menubar name=\"menubar1\">"
2221     "        <menu action=\"file\">"
2222     "        </menu>"
2223     "      </menubar>"
2224     "    </ui>"
2225     "  </object>"
2226     "  <object class=\"GtkWindow\" id=\"window1\">"
2227     "    <child>"
2228     "      <object class=\"GtkMenuBar\" id=\"menubar1\" constructor=\"uimgr1\"/>"
2229     "    </child>"
2230     "  </object>"
2231     "</interface>";
2232
2233   error = NULL;
2234   builder = gtk_builder_new ();
2235   ret = gtk_builder_add_objects_from_string (builder, buffer, -1, objects, &error);
2236   g_assert (ret);
2237   g_assert (error == NULL);
2238   obj = gtk_builder_get_object (builder, "window");
2239   g_assert (obj == NULL);
2240   obj = gtk_builder_get_object (builder, "window2");
2241   g_assert (obj == NULL);
2242   obj = gtk_builder_get_object (builder, "mainbox");  
2243   g_assert (GTK_IS_WIDGET (obj));
2244   g_object_unref (builder);
2245
2246   error = NULL;
2247   builder = gtk_builder_new ();
2248   ret = gtk_builder_add_objects_from_string (builder, buffer, -1, objects2, &error);
2249   g_assert (ret);
2250   g_assert (error == NULL);
2251   obj = gtk_builder_get_object (builder, "window");
2252   g_assert (obj == NULL);
2253   obj = gtk_builder_get_object (builder, "window2");
2254   g_assert (GTK_IS_WINDOW (obj));
2255   gtk_widget_destroy (GTK_WIDGET (obj));
2256   obj = gtk_builder_get_object (builder, "mainbox");  
2257   g_assert (GTK_IS_WIDGET (obj));
2258   g_object_unref (builder);
2259
2260   /* test cherry picking a ui manager and menubar that depends on it */
2261   error = NULL;
2262   builder = gtk_builder_new ();
2263   ret = gtk_builder_add_objects_from_string (builder, buffer2, -1, objects3, &error);
2264   g_assert (ret);
2265   obj = gtk_builder_get_object (builder, "uimgr1");
2266   g_assert (GTK_IS_UI_MANAGER (obj));
2267   obj = gtk_builder_get_object (builder, "file");
2268   g_assert (GTK_IS_ACTION (obj));
2269   obj = gtk_builder_get_object (builder, "menubar1");
2270   g_assert (GTK_IS_MENU_BAR (obj));
2271   menubar = GTK_WIDGET (obj);
2272
2273   children = gtk_container_get_children (GTK_CONTAINER (menubar));
2274   menu = children->data;
2275   g_assert (menu != NULL);
2276   g_assert (GTK_IS_MENU_ITEM (menu));
2277   g_assert (strcmp (gtk_widget_get_name (GTK_WIDGET (menu)), "file") == 0);
2278   g_list_free (children);
2279  
2280   label = G_OBJECT (gtk_bin_get_child (GTK_BIN (menu)));
2281   g_assert (label != NULL);
2282   g_assert (GTK_IS_LABEL (label));
2283   g_assert (strcmp (gtk_label_get_text (GTK_LABEL (label)), "File") == 0);
2284
2285   g_object_unref (builder);
2286
2287   /* test cherry picking just the ui manager */
2288   error = NULL;
2289   builder = gtk_builder_new ();
2290   ret = gtk_builder_add_objects_from_string (builder, buffer2, -1, objects4, &error);
2291   g_assert (ret);
2292   obj = gtk_builder_get_object (builder, "uimgr1");
2293   g_assert (GTK_IS_UI_MANAGER (obj));
2294   manager = GTK_UI_MANAGER (obj);
2295   obj = gtk_builder_get_object (builder, "file");
2296   g_assert (GTK_IS_ACTION (obj));
2297   menubar = gtk_ui_manager_get_widget (manager, "/menubar1");
2298   g_assert (GTK_IS_MENU_BAR (menubar));
2299
2300   children = gtk_container_get_children (GTK_CONTAINER (menubar));
2301   menu = children->data;
2302   g_assert (menu != NULL);
2303   g_assert (GTK_IS_MENU_ITEM (menu));
2304   g_assert (strcmp (gtk_widget_get_name (GTK_WIDGET (menu)), "file") == 0);
2305   g_list_free (children);
2306  
2307   label = G_OBJECT (gtk_bin_get_child (GTK_BIN (menu)));
2308   g_assert (label != NULL);
2309   g_assert (GTK_IS_LABEL (label));
2310   g_assert (strcmp (gtk_label_get_text (GTK_LABEL (label)), "File") == 0);
2311
2312   g_object_unref (builder);
2313 }
2314
2315 static GtkWidget *
2316 get_parent_menubar (GtkWidget *menuitem)
2317 {
2318   GtkMenuShell *menu_shell;
2319   GtkWidget *attach = NULL;
2320
2321   menu_shell = GTK_MENU_SHELL (gtk_widget_get_parent (menuitem));
2322
2323   g_assert (GTK_IS_MENU_SHELL (menu_shell));
2324
2325   while (menu_shell && !GTK_IS_MENU_BAR (menu_shell))
2326     {
2327       if (GTK_IS_MENU (menu_shell) && 
2328           (attach = gtk_menu_get_attach_widget (GTK_MENU (menu_shell))) != NULL)
2329         menu_shell = GTK_MENU_SHELL (gtk_widget_get_parent (attach));
2330       else
2331         menu_shell = NULL;
2332     }
2333
2334   return menu_shell ? GTK_WIDGET (menu_shell) : NULL;
2335 }
2336
2337 static void
2338 test_menus (void)
2339 {
2340   const gchar *buffer =
2341     "<interface>"
2342     "  <object class=\"GtkWindow\" id=\"window1\">"
2343     "    <accel-groups>"
2344     "      <group name=\"accelgroup1\"/>"
2345     "    </accel-groups>"
2346     "    <child>"
2347     "      <object class=\"GtkVBox\" id=\"vbox1\">"
2348     "        <property name=\"visible\">True</property>"
2349     "        <property name=\"orientation\">vertical</property>"
2350     "        <child>"
2351     "          <object class=\"GtkMenuBar\" id=\"menubar1\">"
2352     "            <property name=\"visible\">True</property>"
2353     "            <child>"
2354     "              <object class=\"GtkMenuItem\" id=\"menuitem1\">"
2355     "                <property name=\"visible\">True</property>"
2356     "                <property name=\"label\" translatable=\"yes\">_File</property>"
2357     "                <property name=\"use_underline\">True</property>"
2358     "                <child type=\"submenu\">"
2359     "                  <object class=\"GtkMenu\" id=\"menu1\">"
2360     "                    <property name=\"visible\">True</property>"
2361     "                    <child>"
2362     "                      <object class=\"GtkImageMenuItem\" id=\"imagemenuitem1\">"
2363     "                        <property name=\"label\">gtk-new</property>"
2364     "                        <property name=\"visible\">True</property>"
2365     "                        <property name=\"use_stock\">True</property>"
2366     "                        <property name=\"accel_group\">accelgroup1</property>"
2367     "                      </object>"
2368     "                    </child>"
2369     "                  </object>"
2370     "                </child>"
2371     "              </object>"
2372     "            </child>"
2373     "          </object>"
2374     "        </child>"
2375     "      </object>"
2376     "    </child>"
2377     "  </object>"
2378     "<object class=\"GtkAccelGroup\" id=\"accelgroup1\"/>"
2379     "</interface>";
2380
2381   const gchar *buffer1 =
2382     "<interface>"
2383     "  <object class=\"GtkWindow\" id=\"window1\">"
2384     "    <accel-groups>"
2385     "      <group name=\"accelgroup1\"/>"
2386     "    </accel-groups>"
2387     "    <child>"
2388     "      <object class=\"GtkVBox\" id=\"vbox1\">"
2389     "        <property name=\"visible\">True</property>"
2390     "        <property name=\"orientation\">vertical</property>"
2391     "        <child>"
2392     "          <object class=\"GtkMenuBar\" id=\"menubar1\">"
2393     "            <property name=\"visible\">True</property>"
2394     "            <child>"
2395     "              <object class=\"GtkImageMenuItem\" id=\"imagemenuitem1\">"
2396     "                <property name=\"visible\">True</property>"
2397     "                <child>"
2398     "                  <object class=\"GtkLabel\" id=\"custom1\">"
2399     "                    <property name=\"visible\">True</property>"
2400     "                    <property name=\"label\">a label</property>"
2401     "                  </object>"
2402     "                </child>"
2403     "              </object>"
2404     "            </child>"
2405     "          </object>"
2406     "        </child>"
2407     "      </object>"
2408     "    </child>"
2409     "  </object>"
2410     "<object class=\"GtkAccelGroup\" id=\"accelgroup1\"/>"
2411     "</interface>";
2412   GtkBuilder *builder;
2413   GtkWidget *child;
2414   GtkWidget *window, *item;
2415   GtkAccelGroup *accel_group;
2416   GtkWidget *item_accel_label, *sample_accel_label, *sample_menu_item, *custom;
2417
2418   /* Check that the item has the correct accel label string set
2419    */
2420   builder = builder_new_from_string (buffer, -1, NULL);
2421   window = (GtkWidget *)gtk_builder_get_object (builder, "window1");
2422   item = (GtkWidget *)gtk_builder_get_object (builder, "imagemenuitem1");
2423   accel_group = (GtkAccelGroup *)gtk_builder_get_object (builder, "accelgroup1");
2424
2425   gtk_widget_show_all (window);
2426
2427   sample_menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_NEW, accel_group);
2428
2429   child = gtk_bin_get_child (GTK_BIN (sample_menu_item));
2430   g_assert (child);
2431   g_assert (GTK_IS_ACCEL_LABEL (child));
2432   sample_accel_label = child;
2433   gtk_widget_show (sample_accel_label);
2434
2435   child = gtk_bin_get_child (GTK_BIN (item));
2436   g_assert (child);
2437   g_assert (GTK_IS_ACCEL_LABEL (child));
2438   item_accel_label = child;
2439
2440   gtk_accel_label_refetch (GTK_ACCEL_LABEL (sample_accel_label));
2441   gtk_accel_label_refetch (GTK_ACCEL_LABEL (item_accel_label));
2442
2443   g_assert (gtk_label_get_text (GTK_LABEL (sample_accel_label)) != NULL);
2444   g_assert (gtk_label_get_text (GTK_LABEL (item_accel_label)) != NULL);
2445   g_assert (strcmp (gtk_label_get_text (GTK_LABEL (item_accel_label)),
2446                     gtk_label_get_text (GTK_LABEL (sample_accel_label))) == 0);
2447
2448   /* Check the menu hierarchy worked here  */
2449   g_assert (get_parent_menubar (item));
2450
2451   gtk_widget_destroy (GTK_WIDGET (window));
2452   gtk_widget_destroy (sample_menu_item);
2453   g_object_unref (builder);
2454
2455
2456   /* Check that we can add alien children to menu items via normal
2457    * GtkContainer apis.
2458    */
2459   builder = builder_new_from_string (buffer1, -1, NULL);
2460   window = (GtkWidget *)gtk_builder_get_object (builder, "window1");
2461   item = (GtkWidget *)gtk_builder_get_object (builder, "imagemenuitem1");
2462   custom = (GtkWidget *)gtk_builder_get_object (builder, "custom1");
2463
2464   g_assert (gtk_widget_get_parent (custom) == item);
2465
2466   gtk_widget_destroy (GTK_WIDGET (window));
2467   g_object_unref (builder);
2468
2469 }
2470
2471
2472 static void 
2473 test_file (const gchar *filename)
2474 {
2475   GtkBuilder *builder;
2476   GError *error = NULL;
2477   GSList *l, *objects;
2478
2479   builder = gtk_builder_new ();
2480
2481   if (!gtk_builder_add_from_file (builder, filename, &error))
2482     {
2483       g_error ("%s", error->message);
2484       g_error_free (error);
2485       return;
2486     }
2487
2488   objects = gtk_builder_get_objects (builder);
2489   for (l = objects; l; l = l->next)
2490     {
2491       GObject *obj = (GObject*)l->data;
2492
2493       if (GTK_IS_DIALOG (obj))
2494         {
2495           g_print ("Running dialog %s.\n",
2496                    gtk_widget_get_name (GTK_WIDGET (obj)));
2497           gtk_dialog_run (GTK_DIALOG (obj));
2498         }
2499       else if (GTK_IS_WINDOW (obj))
2500         {
2501           g_signal_connect (obj, "destroy", G_CALLBACK (gtk_main_quit), NULL);
2502           g_print ("Showing %s.\n",
2503                    gtk_widget_get_name (GTK_WIDGET (obj)));
2504           gtk_widget_show_all (GTK_WIDGET (obj));
2505         }
2506     }
2507
2508   gtk_main ();
2509
2510   g_object_unref (builder);
2511   builder = NULL;
2512 }
2513
2514 static void
2515 test_message_area (void)
2516 {
2517   GtkBuilder *builder;
2518   GObject *obj, *obj1;
2519   const gchar buffer[] =
2520     "<interface>"
2521     "  <object class=\"GtkInfoBar\" id=\"infobar1\">"
2522     "    <child internal-child=\"content_area\">"
2523     "      <object class=\"GtkHBox\" id=\"contentarea1\">"
2524     "        <child>"
2525     "          <object class=\"GtkLabel\" id=\"content\">"
2526     "            <property name=\"label\" translatable=\"yes\">Message</property>"
2527     "          </object>"
2528     "          <packing>"
2529     "            <property name='expand'>False</property>"
2530     "          </packing>"
2531     "        </child>"
2532     "      </object>"
2533     "    </child>"
2534     "    <child internal-child=\"action_area\">"
2535     "      <object class=\"GtkVButtonBox\" id=\"actionarea1\">"
2536     "        <child>"
2537     "          <object class=\"GtkButton\" id=\"button_ok\">"
2538     "            <property name=\"label\">gtk-ok</property>"
2539     "            <property name=\"use-stock\">yes</property>"
2540     "          </object>"
2541     "        </child>"
2542     "      </object>"
2543     "    </child>"
2544     "    <action-widgets>"
2545     "      <action-widget response=\"1\">button_ok</action-widget>"
2546     "    </action-widgets>"
2547     "  </object>"
2548     "</interface>";
2549
2550   builder = builder_new_from_string (buffer, -1, NULL);
2551   obj = gtk_builder_get_object (builder, "infobar1");
2552   g_assert (GTK_IS_INFO_BAR (obj));
2553   obj1 = gtk_builder_get_object (builder, "content");
2554   g_assert (GTK_IS_LABEL (obj1));
2555   g_assert (gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (obj1))) == GTK_WIDGET (obj));
2556
2557   obj1 = gtk_builder_get_object (builder, "button_ok");
2558   g_assert (GTK_IS_BUTTON (obj1));
2559   g_assert (gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (obj1))) == GTK_WIDGET (obj));
2560
2561   g_object_unref (builder);
2562 }
2563
2564 static void
2565 test_gmenu (void)
2566 {
2567   GtkBuilder *builder;
2568   GObject *obj, *obj1;
2569   const gchar buffer[] =
2570     "<interface>"
2571     "  <object class=\"GtkWindow\" id=\"window\">"
2572     "  </object>"
2573     "  <menu id='edit-menu'>"
2574     "    <section>"
2575     "      <item>"
2576     "        <attribute name='label'>Undo</attribute>"
2577     "        <attribute name='action'>undo</attribute>"
2578     "      </item>"
2579     "      <item>"
2580     "        <attribute name='label'>Redo</attribute>"
2581     "        <attribute name='action'>redo</attribute>"
2582     "      </item>"
2583     "    </section>"
2584     "    <section></section>"
2585     "    <section>"
2586     "      <attribute name='label'>Copy &amp; Paste</attribute>"
2587     "      <item>"
2588     "        <attribute name='label'>Cut</attribute>"
2589     "        <attribute name='action'>cut</attribute>"
2590     "      </item>"
2591     "      <item>"
2592     "        <attribute name='label'>Copy</attribute>"
2593     "        <attribute name='action'>copy</attribute>"
2594     "      </item>"
2595     "      <item>"
2596     "        <attribute name='label'>Paste</attribute>"
2597     "        <attribute name='action'>paste</attribute>"
2598     "      </item>"
2599     "    </section>"
2600     "    <item><link name='section' id='blargh'>"
2601     "      <item>"
2602     "        <attribute name='label'>Bold</attribute>"
2603     "        <attribute name='action'>bold</attribute>"
2604     "      </item>"
2605     "      <submenu>"
2606     "        <attribute name='label'>Language</attribute>"
2607     "        <item>"
2608     "          <attribute name='label'>Latin</attribute>"
2609     "          <attribute name='action'>lang</attribute>"
2610     "          <attribute name='target'>'latin'</attribute>"
2611     "        </item>"
2612     "        <item>"
2613     "          <attribute name='label'>Greek</attribute>"
2614     "          <attribute name='action'>lang</attribute>"
2615     "          <attribute name='target'>'greek'</attribute>"
2616     "        </item>"
2617     "        <item>"
2618     "          <attribute name='label'>Urdu</attribute>"
2619     "          <attribute name='action'>lang</attribute>"
2620     "          <attribute name='target'>'urdu'</attribute>"
2621     "        </item>"
2622     "      </submenu>"
2623     "    </link></item>"
2624     "  </menu>"
2625     "</interface>";
2626
2627   builder = builder_new_from_string (buffer, -1, NULL);
2628   obj = gtk_builder_get_object (builder, "window");
2629   g_assert (GTK_IS_WINDOW (obj));
2630   obj1 = gtk_builder_get_object (builder, "edit-menu");
2631   g_assert (G_IS_MENU_MODEL (obj1));
2632   obj1 = gtk_builder_get_object (builder, "blargh");
2633   g_assert (G_IS_MENU_MODEL (obj1));
2634   g_object_unref (builder);
2635 }
2636
2637 int
2638 main (int argc, char **argv)
2639 {
2640   /* initialize test program */
2641   gtk_test_init (&argc, &argv);
2642
2643   if (argc > 1)
2644     {
2645       test_file (argv[1]);
2646       return 0;
2647     }
2648
2649   g_test_add_func ("/Builder/Parser", test_parser);
2650   g_test_add_func ("/Builder/Types", test_types);
2651   g_test_add_func ("/Builder/Construct-Only Properties", test_construct_only_property);
2652   g_test_add_func ("/Builder/Children", test_children);
2653   g_test_add_func ("/Builder/Child Properties", test_child_properties);
2654   g_test_add_func ("/Builder/Object Properties", test_object_properties);
2655   g_test_add_func ("/Builder/Notebook", test_notebook);
2656   g_test_add_func ("/Builder/Domain", test_domain);
2657   g_test_add_func ("/Builder/Signal Autoconnect", test_connect_signals);
2658   g_test_add_func ("/Builder/UIManager Simple", test_uimanager_simple);
2659   g_test_add_func ("/Builder/Spin Button", test_spin_button);
2660   g_test_add_func ("/Builder/SizeGroup", test_sizegroup);
2661   g_test_add_func ("/Builder/ListStore", test_list_store);
2662   g_test_add_func ("/Builder/TreeStore", test_tree_store);
2663   g_test_add_func ("/Builder/TreeView Column", test_treeview_column);
2664   g_test_add_func ("/Builder/IconView", test_icon_view);
2665   g_test_add_func ("/Builder/ComboBox", test_combo_box);
2666 #if 0
2667   g_test_add_func ("/Builder/ComboBox Entry", test_combo_box_entry);
2668 #endif
2669   g_test_add_func ("/Builder/CellView", test_cell_view);
2670   g_test_add_func ("/Builder/Dialog", test_dialog);
2671   g_test_add_func ("/Builder/Accelerators", test_accelerators);
2672   g_test_add_func ("/Builder/Widget", test_widget);
2673   g_test_add_func ("/Builder/Value From String", test_value_from_string);
2674   g_test_add_func ("/Builder/Reference Counting", test_reference_counting);
2675   g_test_add_func ("/Builder/Window", test_window);
2676   g_test_add_func ("/Builder/IconFactory", test_icon_factory);
2677   g_test_add_func ("/Builder/PangoAttributes", test_pango_attributes);
2678   g_test_add_func ("/Builder/Requires", test_requires);
2679   g_test_add_func ("/Builder/AddObjects", test_add_objects);
2680   g_test_add_func ("/Builder/Menus", test_menus);
2681   g_test_add_func ("/Builder/MessageArea", test_message_area);
2682   g_test_add_func ("/Builder/MessageDialog", test_message_dialog);
2683   g_test_add_func ("/Builder/GMenu", test_gmenu);
2684
2685   return g_test_run();
2686 }
2687