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