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