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