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