]> Pileus Git - ~andy/gtk/blob - gtk/tests/filechooser.c
filechooserbutton: Add tests for SELECT_FOLDER mode with the dialog active
[~andy/gtk] / gtk / tests / filechooser.c
1 /* GTK - The GIMP Toolkit
2  * autotestfilechooser.c: Automated unit tests for the GtkFileChooser widget
3  * Copyright (C) 2005, Novell, Inc.
4  *
5  * Authors:
6  *   Federico Mena-Quintero <federico@novell.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /* TODO:
23  *
24  * - In test_reload_sequence(), test that the selection is preserved properly
25  *   between unmap/map.
26  *
27  * - More tests!
28  */
29
30 #define SLEEP_DURATION  100
31
32 #include "config.h"
33 #include <string.h>
34 #include <glib/gprintf.h>
35 #include <gtk/gtk.h>
36 #include "gtk/gtkfilechooserprivate.h"
37 #include "gtk/gtkfilechooserdefault.h"
38 #include "gtk/gtkfilechooserentry.h"
39
40 static void
41 log_test (gboolean passed, const char *test_name, ...)
42 {
43   va_list args;
44   char *str;
45
46   va_start (args, test_name);
47   str = g_strdup_vprintf (test_name, args);
48   va_end (args);
49
50   if (g_test_verbose())
51     g_printf ("%s: %s\n", passed ? "PASSED" : "FAILED", str);
52   g_free (str);
53 }
54
55 static const char *get_action_name (GtkFileChooserAction action);
56
57 typedef void (* SetFilenameFn) (GtkFileChooser *chooser, gpointer data);
58 typedef void (* CompareFilenameFn) (GtkFileChooser *chooser, gpointer data);
59
60 struct test_set_filename_closure {
61   GtkWidget *chooser;
62   GtkWidget *accept_button;
63   gboolean focus_button;
64 };
65
66 static gboolean
67 set_filename_timeout_cb (gpointer data)
68 {
69   struct test_set_filename_closure *closure;
70
71   closure = data;
72
73   if (closure->focus_button)
74     gtk_widget_grab_focus (closure->accept_button);
75
76   gtk_button_clicked (GTK_BUTTON (closure->accept_button));
77
78   return FALSE;
79 }
80
81
82 static guint wait_for_idle_id = 0;
83
84 static gboolean
85 wait_for_idle_idle (gpointer data)
86 {
87   wait_for_idle_id = 0;
88
89   return G_SOURCE_REMOVE;
90 }
91
92 static void
93 wait_for_idle (void)
94 {
95   wait_for_idle_id = g_idle_add_full (G_PRIORITY_LOW + 100,
96                                       wait_for_idle_idle,
97                                       NULL, NULL);
98
99   while (wait_for_idle_id)
100     gtk_main_iteration ();
101 }
102
103 static void
104 test_set_filename (GtkFileChooserAction action,
105                    gboolean focus_button,
106                    SetFilenameFn set_filename_fn,const
107                    CompareFilenameFn compare_filename_fn,
108                    gpointer data)
109 {
110   GtkWidget *chooser;
111   struct test_set_filename_closure closure;
112
113   chooser = gtk_file_chooser_dialog_new ("hello", NULL, action,
114                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
115                                          NULL);
116
117   closure.chooser = chooser;
118   closure.accept_button = gtk_dialog_add_button (GTK_DIALOG (chooser), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
119   closure.focus_button = focus_button;
120
121   gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT);
122
123   (* set_filename_fn) (GTK_FILE_CHOOSER (chooser), data);
124
125   gdk_threads_add_timeout_full (G_MAXINT, SLEEP_DURATION, set_filename_timeout_cb, &closure, NULL);
126   gtk_dialog_run (GTK_DIALOG (chooser));
127
128   (* compare_filename_fn) (GTK_FILE_CHOOSER (chooser), data);
129
130   gtk_widget_destroy (chooser);
131 }
132
133 static void
134 set_filename_cb (GtkFileChooser *chooser, gpointer data)
135 {
136   const char *filename;
137
138   filename = data;
139   gtk_file_chooser_set_filename (chooser, filename);
140 }
141
142 static void
143 compare_filename_cb (GtkFileChooser *chooser, gpointer data)
144 {
145   const char *filename;
146   char *out_filename;
147
148   filename = data;
149   out_filename = gtk_file_chooser_get_filename (chooser);
150
151   g_assert_cmpstr (out_filename, ==, filename);
152
153   if (out_filename)
154     g_free (out_filename);
155 }
156
157 typedef struct
158 {
159   const char *test_name;
160   GtkFileChooserAction action;
161   const char *filename;
162   gboolean focus_button;
163 } TestSetFilenameSetup;
164
165 static void
166 test_black_box_set_filename (gconstpointer data)
167 {
168   const TestSetFilenameSetup *setup = data;
169
170   test_set_filename (setup->action, setup->focus_button, set_filename_cb, compare_filename_cb, (char *) setup->filename);
171 }
172
173 struct current_name_closure {
174         const char *path;
175         const char *current_name;
176 };
177
178 static void
179 set_current_name_cb (GtkFileChooser *chooser, gpointer data)
180 {
181   struct current_name_closure *closure;
182
183   closure = data;
184
185   gtk_file_chooser_set_current_folder (chooser, closure->path);
186   gtk_file_chooser_set_current_name (chooser, closure->current_name);
187 }
188
189 static void
190 compare_current_name_cb (GtkFileChooser *chooser, gpointer data)
191 {
192   struct current_name_closure *closure;
193   char *out_filename;
194   char *filename;
195
196   closure = data;
197
198   out_filename = gtk_file_chooser_get_filename (chooser);
199
200   g_assert (out_filename != NULL);
201
202   filename = g_build_filename (closure->path, closure->current_name, NULL);
203   g_assert_cmpstr (filename, ==, out_filename);
204
205   g_free (filename);
206   g_free (out_filename);
207 }
208
209 typedef struct
210 {
211   const char *test_name;
212   GtkFileChooserAction action;
213   const char *current_name;
214   gboolean focus_button;
215 } TestSetCurrentNameSetup;
216
217 static void
218 test_black_box_set_current_name (gconstpointer data)
219 {
220   const TestSetCurrentNameSetup *setup = data;
221   struct current_name_closure closure;
222   char *cwd;
223
224   cwd = g_get_current_dir ();
225
226   closure.path = cwd;
227   closure.current_name = setup->current_name;
228
229   test_set_filename (setup->action, setup->focus_button, set_current_name_cb, compare_current_name_cb, &closure);
230
231   g_free (cwd);
232 }
233
234 /* FIXME: fails in CREATE_FOLDER mode when FOLDER_NAME == "/" */
235
236 #if 0
237 #define FILE_NAME "/nonexistent"
238 #define FILE_NAME_2 "/nonexistent2"
239 #define FOLDER_NAME "/etc"
240 #define FOLDER_NAME_2 "/usr"
241 #else
242 #define FILE_NAME "/etc/passwd"
243 #define FILE_NAME_2 "/etc/group"
244 #define FOLDER_NAME "/etc"
245 #define FOLDER_NAME_2 "/usr"
246 #endif
247
248 #define CURRENT_NAME "parangaricutirimicuaro.txt"
249 #define CURRENT_NAME_FOLDER "parangaricutirimicuaro"
250
251 /* https://bugzilla.novell.com/show_bug.cgi?id=184875
252  * http://bugzilla.gnome.org/show_bug.cgi?id=347066
253  * http://bugzilla.gnome.org/show_bug.cgi?id=346058
254  */
255
256 static void
257 setup_set_filename_tests (void)
258 {
259   static TestSetFilenameSetup tests[] =
260     {
261       { "/GtkFileChooser/black_box/set_filename/open/no_focus",          GTK_FILE_CHOOSER_ACTION_OPEN,          FILE_NAME,  FALSE },
262       { "/GtkFileChooser/black_box/set_filename/open/focus",             GTK_FILE_CHOOSER_ACTION_OPEN,          FILE_NAME,  TRUE  },
263       { "/GtkFileChooser/black_box/set_filename/save/no_focus",          GTK_FILE_CHOOSER_ACTION_SAVE,          FILE_NAME,  FALSE },
264       { "/GtkFileChooser/black_box/set_filename/save/focus",             GTK_FILE_CHOOSER_ACTION_SAVE,          FILE_NAME,  TRUE  },
265       { "/GtkFileChooser/black_box/set_filename/select_folder/no_focus", GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, FOLDER_NAME,FALSE },
266       { "/GtkFileChooser/black_box/set_filename/select_folder/focus",    GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, FOLDER_NAME,TRUE  },
267       { "/GtkFileChooser/black_box/set_filename/create_folder/no_focus", GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, FOLDER_NAME,FALSE },
268       { "/GtkFileChooser/black_box/set_filename/create_folder/focus",    GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, FOLDER_NAME,TRUE  },
269     };
270   int i;
271
272   for (i = 0; i < G_N_ELEMENTS (tests); i++)
273     g_test_add_data_func (tests[i].test_name, &tests[i], test_black_box_set_filename);
274 }
275
276 static void
277 setup_set_current_name_tests (void)
278 {
279   static TestSetCurrentNameSetup tests[] =
280     {
281       { "/GtkFileChooser/black_box/set_current_name/save/no_focus",          GTK_FILE_CHOOSER_ACTION_SAVE,          CURRENT_NAME,        FALSE },
282       { "/GtkFileChooser/black_box/set_current_name/save/focus",             GTK_FILE_CHOOSER_ACTION_SAVE,          CURRENT_NAME,        TRUE  },
283       { "/GtkFileChooser/black_box/set_current_name/create_folder/no_focus", GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, CURRENT_NAME_FOLDER, FALSE },
284       { "/GtkFileChooser/black_box/set_current_name/create_folder/focus",    GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, CURRENT_NAME_FOLDER, TRUE  },
285     };
286   int i;
287
288   for (i = 0; i < G_N_ELEMENTS (tests); i++)
289     g_test_add_data_func (tests[i].test_name, &tests[i], test_black_box_set_current_name);
290 }
291
292 typedef struct
293 {
294   const char *shortname;
295   GtkFileChooserAction action;
296   const char *initial_current_folder;
297   const char *initial_filename;
298   gboolean open_dialog;
299   const char *tweak_current_folder;
300   const char *tweak_filename;
301   gint dialog_response;
302   const char *final_current_folder;
303   const char *final_filename;
304 } FileChooserButtonTest;
305
306 static char *
307 make_button_test_name (FileChooserButtonTest *t)
308 {
309   return g_strdup_printf ("/GtkFileChooserButton/%s", t->shortname);
310 #if 0
311   GString *s = g_string_new ("/GtkFileChooserButton");
312
313   g_string_append_printf (s, "/%s/%s/%s/%s",
314                           get_action_name (t->action),
315                           t->initial_current_folder ? "set_initial_folder" : "no_default_folder",
316                           t->initial_filename ? "set_initial_filename" : "no_initial_filename",
317                           t->open_dialog ? "open_dialog" : "no_dialog");
318
319   if (t->tweak_current_folder)
320     g_string_append (s, "/tweak_current_folder");
321
322   if (t->tweak_filename)
323     g_string_append (s, "/tweak_filename");
324
325   if (t->open_dialog)
326     g_string_append_printf (s, "/%s",
327                             t->dialog_response == GTK_RESPONSE_ACCEPT ? "accept" : "cancel");
328
329   if (t->final_current_folder)
330     g_string_append (s, "/final_current_folder");
331
332   if (t->final_filename)
333     g_string_append (s, "/final_filename");
334
335   return g_string_free (s, FALSE);
336 #endif
337 }
338
339 /* Copied from gtkfilechooserutils.c:_gtk_file_chooser_delegate_get_quark() */
340 static GQuark
341 delegate_get_quark (void)
342 {
343   static GQuark quark = 0;
344
345   if (G_UNLIKELY (quark == 0))
346     quark = g_quark_from_static_string ("gtk-file-chooser-delegate");
347
348   return quark;
349 }
350
351 static gboolean
352 sleep_timeout_cb (gpointer data)
353 {
354   gtk_main_quit ();
355   return FALSE;
356 }
357
358 static void
359 sleep_in_main_loop (void)
360 {
361   /* process all pending idles and events */
362   while (g_main_context_pending (NULL))
363     g_main_context_iteration (NULL, FALSE);
364   /* sleeping probably isn't strictly necessary here */
365   gdk_threads_add_timeout_full (G_MAXINT, 250, sleep_timeout_cb, NULL, NULL);
366   gtk_main ();
367   /* process any pending idles or events that arrived during sleep */
368   while (g_main_context_pending (NULL))
369     g_main_context_iteration (NULL, FALSE);
370 }
371
372 static void
373 test_file_chooser_button (gconstpointer data)
374 {
375   const FileChooserButtonTest *setup = data;
376   GtkWidget *window;
377   GtkWidget *fc_button;
378   GtkWidget *fc_dialog;
379
380   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
381
382   fc_button = gtk_file_chooser_button_new (setup->action == GTK_FILE_CHOOSER_ACTION_OPEN ? "Select a file" : "Select a folder",
383                                            setup->action);
384   gtk_container_add (GTK_CONTAINER (window), fc_button);
385
386   if (setup->initial_current_folder)
387     gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fc_button), setup->initial_current_folder);
388
389   if (setup->initial_filename)
390     gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (fc_button), setup->initial_filename);
391
392   gtk_widget_show_all (window);
393   wait_for_idle ();
394
395   if (setup->open_dialog)
396     {
397       GList *children;
398
399       /* Hack our way into the file chooser button; get its GtkButton child and click it */
400       children = gtk_container_get_children (GTK_CONTAINER (fc_button));
401       g_assert (children && GTK_IS_BUTTON (children->data));
402       gtk_button_clicked (GTK_BUTTON (children->data));
403       g_list_free (children);
404
405       wait_for_idle ();
406
407       /* Give me the internal dialog, damnit */
408       fc_dialog = g_object_get_qdata (G_OBJECT (fc_button), delegate_get_quark ());
409       g_assert (GTK_IS_FILE_CHOOSER (fc_dialog));
410       g_assert (GTK_IS_DIALOG (fc_dialog));
411     }
412
413   /* Okay, now frob the button and its optional dialog */
414
415   if (setup->tweak_current_folder)
416     gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fc_button), setup->tweak_current_folder);
417
418   if (setup->tweak_filename)
419     gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (fc_button), setup->tweak_filename);
420
421   sleep_in_main_loop ();
422
423   if (setup->open_dialog)
424     {
425       gtk_dialog_response (GTK_DIALOG (fc_dialog), setup->dialog_response);
426       wait_for_idle ();
427     }
428
429   if (setup->final_current_folder)
430     {
431       char *folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (fc_button));
432
433       g_assert_cmpstr (folder, ==, setup->final_current_folder);
434       g_free (folder);
435     }
436
437   if (setup->final_filename)
438     {
439       char *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fc_button));
440
441       g_assert_cmpstr (filename, ==, setup->final_filename);
442       g_free (filename);
443     }
444
445   gtk_widget_destroy (window);
446 }
447
448 static FileChooserButtonTest button_tests[] =
449   {
450     /* OPEN tests without dialog */
451
452     {
453       "open-1",
454       GTK_FILE_CHOOSER_ACTION_OPEN,
455       NULL,                     /* initial_current_folder */
456       NULL,                     /* initial_filename */
457       FALSE,                    /* open_dialog */
458       NULL,                     /* tweak_current_folder */
459       NULL,                     /* tweak_filename */
460       0,                        /* dialog_response */
461       NULL,                     /* final_current_folder */
462       NULL                      /* final_filename */
463     },
464     {
465       "open-2",
466       GTK_FILE_CHOOSER_ACTION_OPEN,
467       NULL,                     /* initial_current_folder */
468       FILE_NAME,                /* initial_filename */
469       FALSE,                    /* open_dialog */
470       NULL,                     /* tweak_current_folder */
471       NULL,                     /* tweak_filename */
472       0,                        /* dialog_response */
473       NULL,                     /* final_current_folder */
474       FILE_NAME                 /* final_filename */
475     },
476     {
477       "open-3",
478       GTK_FILE_CHOOSER_ACTION_OPEN,
479       NULL,                     /* initial_current_folder */
480       NULL,                     /* initial_filename */
481       FALSE,                    /* open_dialog */
482       NULL,                     /* tweak_current_folder */
483       FILE_NAME,                /* tweak_filename */
484       0,                        /* dialog_response */
485       NULL,                     /* final_current_folder */
486       FILE_NAME                 /* final_filename */
487     },
488     {
489       "open-4",
490       GTK_FILE_CHOOSER_ACTION_OPEN,
491       NULL,                     /* initial_current_folder */
492       FILE_NAME,                /* initial_filename */
493       FALSE,                    /* open_dialog */
494       NULL,                     /* tweak_current_folder */
495       FILE_NAME_2,              /* tweak_filename */
496       0,                        /* dialog_response */
497       NULL,                     /* final_current_folder */
498       FILE_NAME_2               /* final_filename */
499     },
500     {
501       "open-5",
502       GTK_FILE_CHOOSER_ACTION_OPEN,
503       FOLDER_NAME,              /* initial_current_folder */
504       NULL,                     /* initial_filename */
505       FALSE,                    /* open_dialog */
506       NULL,                     /* tweak_current_folder */
507       NULL,                     /* tweak_filename */
508       0,                        /* dialog_response */
509       FOLDER_NAME,              /* final_current_folder */
510       NULL                      /* final_filename */
511     },
512     {
513       "open-6",
514       GTK_FILE_CHOOSER_ACTION_OPEN,
515       FOLDER_NAME,              /* initial_current_folder */
516       NULL,                     /* initial_filename */
517       FALSE,                    /* open_dialog */
518       FOLDER_NAME_2,            /* tweak_current_folder */
519       NULL,                     /* tweak_filename */
520       0,                        /* dialog_response */
521       FOLDER_NAME_2,            /* final_current_folder */
522       NULL                      /* final_filename */
523     },
524
525     /* SELECT_FOLDER tests without dialog */
526
527     {
528       "select-folder-1",
529       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
530       NULL,                     /* initial_current_folder */
531       NULL,                     /* initial_filename */
532       FALSE,                    /* open_dialog */
533       NULL,                     /* tweak_current_folder */
534       NULL,                     /* tweak_filename */
535       0,                        /* dialog_response */
536       NULL,                     /* final_current_folder */
537       NULL                      /* final_filename */
538     },
539     {
540       "select-folder-2",
541       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
542       NULL,                     /* initial_current_folder */
543       FOLDER_NAME,              /* initial_filename */
544       FALSE,                    /* open_dialog */
545       NULL,                     /* tweak_current_folder */
546       NULL,                     /* tweak_filename */
547       0,                        /* dialog_response */
548       NULL,                     /* final_current_folder */
549       FOLDER_NAME               /* final_filename */
550     },
551     {
552       "select-folder-3",
553       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
554       NULL,                     /* initial_current_folder */
555       FOLDER_NAME,              /* initial_filename */
556       FALSE,                    /* open_dialog */
557       NULL,                     /* tweak_current_folder */
558       FOLDER_NAME_2,            /* tweak_filename */
559       0,                        /* dialog_response */
560       NULL,                     /* final_current_folder */
561       FOLDER_NAME_2             /* final_filename */
562     },
563     {
564       "select-folder-4",
565       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
566       FOLDER_NAME,              /* initial_current_folder */
567       NULL,                     /* initial_filename */
568       FALSE,                    /* open_dialog */
569       NULL,                     /* tweak_current_folder */
570       NULL,                     /* tweak_filename */
571       0,                        /* dialog_response */
572       NULL,                     /* final_current_folder */
573       FOLDER_NAME               /* final_filename */
574     },
575     {
576       "select-folder-5",
577       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
578       FOLDER_NAME,              /* initial_current_folder */
579       NULL,                     /* initial_filename */
580       FALSE,                    /* open_dialog */
581       NULL,                     /* tweak_current_folder */
582       NULL,                     /* tweak_filename */
583       0,                        /* dialog_response */
584       FOLDER_NAME,              /* final_current_folder */
585       NULL                      /* final_filename */
586     },
587     {
588       "select-folder-6",
589       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
590       FOLDER_NAME,              /* initial_current_folder */
591       NULL,                     /* initial_filename */
592       FALSE,                    /* open_dialog */
593       FOLDER_NAME_2,            /* tweak_current_folder */
594       NULL,                     /* tweak_filename */
595       0,                        /* dialog_response */
596       NULL,                     /* final_current_folder */
597       FOLDER_NAME_2             /* final_filename */
598     },
599     {
600       "select-folder-7",
601       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
602       FOLDER_NAME,              /* initial_current_folder */
603       NULL,                     /* initial_filename */
604       FALSE,                    /* open_dialog */
605       FOLDER_NAME_2,            /* tweak_current_folder */
606       NULL,                     /* tweak_filename */
607       0,                        /* dialog_response */
608       FOLDER_NAME_2,            /* final_current_folder */
609       NULL                      /* final_filename */
610     },
611     {
612       "select-folder-8",
613       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
614       FOLDER_NAME,              /* initial_current_folder */
615       NULL,                     /* initial_filename */
616       FALSE,                    /* open_dialog */
617       NULL,                     /* tweak_current_folder */
618       FOLDER_NAME_2,            /* tweak_filename */
619       0,                        /* dialog_response */
620       NULL,                     /* final_current_folder */
621       FOLDER_NAME_2             /* final_filename */
622     },
623
624     /* OPEN tests with dialog, cancelled */
625
626     {
627       "open-dialog-cancel-1",
628       GTK_FILE_CHOOSER_ACTION_OPEN,
629       NULL,                     /* initial_current_folder */
630       NULL,                     /* initial_filename */
631       TRUE,                     /* open_dialog */
632       NULL,                     /* tweak_current_folder */
633       NULL,                     /* tweak_filename */
634       GTK_RESPONSE_CANCEL,      /* dialog_response */
635       NULL,                     /* final_current_folder */
636       NULL                      /* final_filename */
637     },
638     {
639       "open-dialog-cancel-2",
640       GTK_FILE_CHOOSER_ACTION_OPEN,
641       NULL,                     /* initial_current_folder */
642       FILE_NAME,                /* initial_filename */
643       TRUE,                     /* open_dialog */
644       NULL,                     /* tweak_current_folder */
645       NULL,                     /* tweak_filename */
646       GTK_RESPONSE_CANCEL,      /* dialog_response */
647       NULL,                     /* final_current_folder */
648       FILE_NAME                 /* final_filename */
649     },
650     {
651       "open-dialog-cancel-3",
652       GTK_FILE_CHOOSER_ACTION_OPEN,
653       FOLDER_NAME,              /* initial_current_folder */
654       NULL,                     /* initial_filename */
655       TRUE,                     /* open_dialog */
656       NULL,                     /* tweak_current_folder */
657       NULL,                     /* tweak_filename */
658       GTK_RESPONSE_CANCEL,      /* dialog_response */
659       FOLDER_NAME,              /* final_current_folder */
660       NULL                      /* final_filename */
661     },
662     {
663       "open-dialog-cancel-4",
664       GTK_FILE_CHOOSER_ACTION_OPEN,
665       NULL,                     /* initial_current_folder */
666       NULL,                     /* initial_filename */
667       TRUE,                     /* open_dialog */
668       NULL,                     /* tweak_current_folder */
669       FILE_NAME,                /* tweak_filename */
670       GTK_RESPONSE_CANCEL,      /* dialog_response */
671       NULL,                     /* final_current_folder */
672       NULL                      /* final_filename */
673     },
674     {
675       "open-dialog-cancel-5",
676       GTK_FILE_CHOOSER_ACTION_OPEN,
677       NULL,                     /* initial_current_folder */
678       FILE_NAME,                /* initial_filename */
679       TRUE,                     /* open_dialog */
680       NULL,                     /* tweak_current_folder */
681       FILE_NAME_2,              /* tweak_filename */
682       GTK_RESPONSE_CANCEL,      /* dialog_response */
683       NULL,                     /* final_current_folder */
684       FILE_NAME                 /* final_filename */
685     },
686     {
687       "open-dialog-cancel-6",
688       GTK_FILE_CHOOSER_ACTION_OPEN,
689       FOLDER_NAME,              /* initial_current_folder */
690       NULL,                     /* initial_filename */
691       TRUE,                     /* open_dialog */
692       NULL,                     /* tweak_current_folder */
693       FILE_NAME_2,              /* tweak_filename */
694       GTK_RESPONSE_CANCEL,      /* dialog_response */
695       FOLDER_NAME,              /* final_current_folder */
696       NULL                      /* final_filename */
697     },
698
699     /* SELECT_FOLDER tests with dialog, cancelled */
700
701     {
702       "select-folder-dialog-cancel-1",
703       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
704       NULL,                     /* initial_current_folder */
705       NULL,                     /* initial_filename */
706       TRUE,                     /* open_dialog */
707       NULL,                     /* tweak_current_folder */
708       NULL,                     /* tweak_filename */
709       GTK_RESPONSE_CANCEL,      /* dialog_response */
710       NULL,                     /* final_current_folder */
711       NULL                      /* final_filename */
712     },
713     {
714       "select-folder-dialog-cancel-2",
715       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
716       NULL,                     /* initial_current_folder */
717       FOLDER_NAME,              /* initial_filename */
718       TRUE,                     /* open_dialog */
719       NULL,                     /* tweak_current_folder */
720       NULL,                     /* tweak_filename */
721       GTK_RESPONSE_CANCEL,      /* dialog_response */
722       NULL,                     /* final_current_folder */
723       FOLDER_NAME               /* final_filename */
724     },
725     {
726       "select-folder-dialog-cancel-3",
727       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
728       FOLDER_NAME,              /* initial_current_folder */
729       NULL,                     /* initial_filename */
730       TRUE,                     /* open_dialog */
731       NULL,                     /* tweak_current_folder */
732       NULL,                     /* tweak_filename */
733       GTK_RESPONSE_CANCEL,      /* dialog_response */
734       FOLDER_NAME,              /* final_current_folder */
735       NULL                      /* final_filename */
736     },
737     {
738       "select-folder-dialog-cancel-4",
739       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
740       FOLDER_NAME,              /* initial_current_folder */
741       NULL,                     /* initial_filename */
742       TRUE,                     /* open_dialog */
743       NULL,                     /* tweak_current_folder */
744       NULL,                     /* tweak_filename */
745       GTK_RESPONSE_CANCEL,      /* dialog_response */
746       NULL,                     /* final_current_folder */
747       FOLDER_NAME               /* final_filename */
748     },
749     {
750       "select-folder-dialog-cancel-5",
751       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
752       NULL,                     /* initial_current_folder */
753       NULL,                     /* initial_filename */
754       TRUE,                     /* open_dialog */
755       NULL,                     /* tweak_current_folder */
756       FOLDER_NAME,              /* tweak_filename */
757       GTK_RESPONSE_CANCEL,      /* dialog_response */
758       NULL,                     /* final_current_folder */
759       NULL                      /* final_filename */
760     },
761     {
762       "select-folder-dialog-cancel-6",
763       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
764       NULL,                     /* initial_current_folder */
765       FOLDER_NAME,              /* initial_filename */
766       TRUE,                     /* open_dialog */
767       NULL,                     /* tweak_current_folder */
768       FOLDER_NAME_2,            /* tweak_filename */
769       GTK_RESPONSE_CANCEL,      /* dialog_response */
770       NULL,                     /* final_current_folder */
771       FOLDER_NAME                       /* final_filename */
772     },
773     {
774       "select-folder-dialog-cancel-7",
775       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
776       FOLDER_NAME,              /* initial_current_folder */
777       NULL,                     /* initial_filename */
778       TRUE,                     /* open_dialog */
779       NULL,                     /* tweak_current_folder */
780       FOLDER_NAME_2,            /* tweak_filename */
781       GTK_RESPONSE_CANCEL,      /* dialog_response */
782       FOLDER_NAME,              /* final_current_folder */
783       NULL                      /* final_filename */
784     },
785     {
786       "select-folder-dialog-cancel-8",
787       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
788       FOLDER_NAME,              /* initial_current_folder */
789       NULL,                     /* initial_filename */
790       TRUE,                     /* open_dialog */
791       NULL,                     /* tweak_current_folder */
792       FOLDER_NAME_2,            /* tweak_filename */
793       GTK_RESPONSE_CANCEL,      /* dialog_response */
794       NULL,                     /* final_current_folder */
795       FOLDER_NAME               /* final_filename */
796     },
797
798     /* OPEN tests with dialog */
799
800     {
801       "open-dialog-1",
802       GTK_FILE_CHOOSER_ACTION_OPEN,
803       NULL,                     /* initial_current_folder */
804       NULL,                     /* initial_filename */
805       TRUE,                     /* open_dialog */
806       NULL,                     /* tweak_current_folder */
807       FILE_NAME,                /* tweak_filename */
808       GTK_RESPONSE_ACCEPT,      /* dialog_response */
809       NULL,                     /* final_current_folder */
810       FILE_NAME                 /* final_filename */
811     },
812     {
813       "open-dialog-2",
814       GTK_FILE_CHOOSER_ACTION_OPEN,
815       NULL,                     /* initial_current_folder */
816       FILE_NAME,                /* initial_filename */
817       TRUE,                     /* open_dialog */
818       NULL,                     /* tweak_current_folder */
819       NULL,                     /* tweak_filename */
820       GTK_RESPONSE_ACCEPT,      /* dialog_response */
821       NULL,                     /* final_current_folder */
822       FILE_NAME                 /* final_filename */
823     },
824     {
825       "open-dialog-3",
826       GTK_FILE_CHOOSER_ACTION_OPEN,
827       NULL,                     /* initial_current_folder */
828       FILE_NAME,                /* initial_filename */
829       TRUE,                     /* open_dialog */
830       NULL,                     /* tweak_current_folder */
831       FILE_NAME_2,              /* tweak_filename */
832       GTK_RESPONSE_ACCEPT,      /* dialog_response */
833       NULL,                     /* final_current_folder */
834       FILE_NAME_2               /* final_filename */
835     },
836     {
837       "open-dialog-4",
838       GTK_FILE_CHOOSER_ACTION_OPEN,
839       FOLDER_NAME,              /* initial_current_folder */
840       NULL,                     /* initial_filename */
841       TRUE,                     /* open_dialog */
842       NULL,                     /* tweak_current_folder */
843       FILE_NAME,                /* tweak_filename */
844       GTK_RESPONSE_ACCEPT,      /* dialog_response */
845       NULL,                     /* final_current_folder */
846       FILE_NAME                 /* final_filename */
847     },
848
849     /* SELECT_FOLDER tests with dialog */
850
851     {
852       "select-folder-dialog-1",
853       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
854       NULL,                     /* initial_current_folder */
855       FOLDER_NAME,              /* initial_filename */
856       TRUE,                     /* open_dialog */
857       NULL,                     /* tweak_current_folder */
858       NULL,                     /* tweak_filename */
859       GTK_RESPONSE_ACCEPT,      /* dialog_response */
860       NULL,                     /* final_current_folder */
861       FOLDER_NAME               /* final_filename */
862     },
863     {
864       "select-folder-dialog-2",
865       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
866       FOLDER_NAME,              /* initial_current_folder */
867       NULL,                     /* initial_filename */
868       TRUE,                     /* open_dialog */
869       NULL,                     /* tweak_current_folder */
870       NULL,                     /* tweak_filename */
871       GTK_RESPONSE_ACCEPT,      /* dialog_response */
872       NULL,                     /* final_current_folder */
873       FOLDER_NAME               /* final_filename */
874     },
875     {
876       "select-folder-dialog-3",
877       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
878       NULL,                     /* initial_current_folder */
879       FOLDER_NAME,              /* initial_filename */
880       TRUE,                     /* open_dialog */
881       NULL,                     /* tweak_current_folder */
882       FOLDER_NAME_2,            /* tweak_filename */
883       GTK_RESPONSE_ACCEPT,      /* dialog_response */
884       NULL,                     /* final_current_folder */
885       FOLDER_NAME_2             /* final_filename */
886     },
887     {
888       "select-folder-dialog-4",
889       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
890       FOLDER_NAME,              /* initial_current_folder */
891       NULL,                     /* initial_filename */
892       TRUE,                     /* open_dialog */
893       NULL,                     /* tweak_current_folder */
894       FOLDER_NAME_2,            /* tweak_filename */
895       GTK_RESPONSE_ACCEPT,      /* dialog_response */
896       NULL,                     /* final_current_folder */
897       FOLDER_NAME_2             /* final_filename */
898     },
899
900   };
901
902 static void
903 setup_file_chooser_button_tests (void)
904 {
905   int i;
906
907   for (i = 0; i < G_N_ELEMENTS (button_tests); i++)
908     {
909       char *test_name;
910
911       test_name = make_button_test_name (&button_tests[i]);
912       g_test_add_data_func (test_name, &button_tests[i], test_file_chooser_button);
913       g_free (test_name);
914     }
915 }
916
917 struct confirm_overwrite_closure {
918   GtkWidget *chooser;
919   GtkWidget *accept_button;
920   gint confirm_overwrite_signal_emitted;
921   gchar *extension;
922 };
923
924 static GtkFileChooserConfirmation
925 confirm_overwrite_cb (GtkFileChooser *chooser, gpointer data)
926 {
927   struct confirm_overwrite_closure *closure = data;
928
929   if (g_test_verbose())
930     printf ("bling!\n");
931   closure->confirm_overwrite_signal_emitted += 1;
932
933   return GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME;
934 }
935
936 static void
937 overwrite_response_cb (GtkFileChooser *chooser, gint response, gpointer data)
938 {
939   struct confirm_overwrite_closure *closure = data;
940   char *filename;
941
942   if (g_test_verbose())
943     printf ("plong!\n");
944
945   if (response != GTK_RESPONSE_ACCEPT)
946     return;
947
948   filename = gtk_file_chooser_get_filename (chooser);
949
950   if (!g_str_has_suffix (filename, closure->extension))
951     {
952       char *basename;
953
954       basename = g_path_get_basename (filename);
955       g_free (filename);
956
957       filename = g_strconcat (basename, closure->extension, NULL);
958       gtk_file_chooser_set_current_name (chooser, filename);
959
960       g_signal_stop_emission_by_name (chooser, "response");
961       gtk_dialog_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT);
962     }
963 }
964
965 static gboolean
966 confirm_overwrite_timeout_cb (gpointer data)
967 {
968   struct confirm_overwrite_closure *closure;
969
970   closure = data;
971   gtk_button_clicked (GTK_BUTTON (closure->accept_button));
972
973   return FALSE;
974 }
975
976 /* http://bugzilla.gnome.org/show_bug.cgi?id=347883 */
977 static gboolean
978 test_confirm_overwrite_for_path (const char *path, gboolean append_extension)
979 {
980   gboolean passed;
981   struct confirm_overwrite_closure closure;
982   char *filename;
983
984   passed = TRUE;
985
986   closure.extension = NULL;
987   closure.confirm_overwrite_signal_emitted = 0;
988   closure.chooser = gtk_file_chooser_dialog_new ("hello", NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
989                                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
990                                                  NULL);
991   closure.accept_button = gtk_dialog_add_button (GTK_DIALOG (closure.chooser),
992                                                  GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT);
993   gtk_dialog_set_default_response (GTK_DIALOG (closure.chooser), GTK_RESPONSE_ACCEPT);
994
995   gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (closure.chooser), TRUE);
996
997   g_signal_connect (closure.chooser, "confirm-overwrite",
998                     G_CALLBACK (confirm_overwrite_cb), &closure);
999
1000   if (append_extension)
1001     {
1002       char *extension;
1003
1004       filename = g_path_get_dirname (path);
1005       gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (closure.chooser), filename);
1006       g_free (filename);
1007
1008       filename = g_path_get_basename (path);
1009       extension = strchr (filename, '.');
1010
1011       if (extension)
1012         {
1013           closure.extension = g_strdup (extension);
1014           *extension = '\0';
1015         }
1016
1017       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (closure.chooser), filename);
1018       g_free (filename);
1019
1020       g_signal_connect (closure.chooser, "response",
1021                         G_CALLBACK (overwrite_response_cb), &closure);
1022     }
1023   else
1024     {
1025       gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (closure.chooser), path);
1026     }
1027
1028   gdk_threads_add_timeout_full (G_MAXINT, SLEEP_DURATION, confirm_overwrite_timeout_cb, &closure, NULL);
1029   gtk_dialog_run (GTK_DIALOG (closure.chooser));
1030
1031   filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (closure.chooser));
1032   passed = passed && filename && (strcmp (filename, path) == 0);
1033   g_free (filename);
1034   
1035   gtk_widget_destroy (closure.chooser);
1036
1037   passed = passed && (1 == closure.confirm_overwrite_signal_emitted);
1038
1039   log_test (passed, "Confirm overwrite for %s", path);
1040
1041   return passed;
1042 }
1043
1044 static void
1045 test_confirm_overwrite (void)
1046 {
1047   gboolean passed = TRUE;
1048
1049   /* first test for a file we know will always exist */
1050   passed = passed && test_confirm_overwrite_for_path ("/etc/passwd", FALSE); 
1051   g_assert (passed);
1052   passed = passed && test_confirm_overwrite_for_path ("/etc/resolv.conf", TRUE); 
1053   g_assert (passed);
1054 }
1055
1056 static const GtkFileChooserAction open_actions[] = {
1057   GTK_FILE_CHOOSER_ACTION_OPEN,
1058   GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
1059 };
1060
1061 static const GtkFileChooserAction save_actions[] = {
1062   GTK_FILE_CHOOSER_ACTION_SAVE,
1063   GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
1064 };
1065
1066
1067 static gboolean
1068 has_action (const GtkFileChooserAction *actions,
1069             int n_actions,
1070             GtkFileChooserAction sought_action)
1071 {
1072   int i;
1073
1074   for (i = 0; i < n_actions; i++)
1075     if (actions[i] == sought_action)
1076       return TRUE;
1077
1078   return FALSE;
1079 }
1080
1081 static const char *
1082 get_action_name (GtkFileChooserAction action)
1083 {
1084   switch (action)
1085     {
1086     case GTK_FILE_CHOOSER_ACTION_OPEN:          return "OPEN";
1087     case GTK_FILE_CHOOSER_ACTION_SAVE:          return "SAVE";
1088     case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: return "SELECT_FOLDER";
1089     case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER: return "CREATE_FOLDER";
1090
1091     default:
1092       g_assert_not_reached ();
1093       return NULL;
1094     }
1095 }
1096
1097 static GtkFileChooserDefault *
1098 get_impl_from_dialog (GtkWidget *dialog)
1099 {
1100   GtkFileChooserDialog *d;
1101   GtkFileChooserDialogPrivate *dialog_priv;
1102   GtkFileChooserWidget *chooser_widget;
1103   GtkFileChooserWidgetPrivate *widget_priv;
1104   GtkFileChooserDefault *impl;
1105
1106   d = GTK_FILE_CHOOSER_DIALOG (dialog);
1107   dialog_priv = d->priv;
1108   chooser_widget = GTK_FILE_CHOOSER_WIDGET (dialog_priv->widget);
1109   if (!chooser_widget)
1110     g_error ("BUG: dialog_priv->widget is not a GtkFileChooserWidget");
1111
1112   widget_priv = chooser_widget->priv;
1113   impl = (GtkFileChooserDefault *) (widget_priv->impl);
1114   if (!impl)
1115     g_error ("BUG: widget_priv->impl is not a GtkFileChooserDefault");
1116
1117   return impl;
1118 }
1119 #ifdef BROKEN_TESTS
1120 static gboolean
1121 test_widgets_for_current_action (GtkFileChooserDialog *dialog,
1122                                  GtkFileChooserAction  expected_action)
1123 {
1124   GtkFileChooserDefault *impl;
1125   gboolean passed;
1126
1127   if (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) != expected_action)
1128     return FALSE;
1129
1130   impl = get_impl_from_dialog (GTK_WIDGET (dialog));
1131
1132   g_assert (impl->action == expected_action);
1133
1134   passed = TRUE;
1135
1136   /* OPEN implies that the "new folder" button is hidden; otherwise it is shown */
1137   if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
1138     passed = passed && !gtk_widget_get_visible (impl->browse_new_folder_button);
1139   else
1140     passed = passed && gtk_widget_get_visible (impl->browse_new_folder_button);
1141
1142   /* Check that the widgets are present/visible or not */
1143   if (has_action (open_actions, G_N_ELEMENTS (open_actions), impl->action))
1144     {
1145       passed = passed && (impl->save_widgets == NULL
1146                           && (impl->location_mode == LOCATION_MODE_PATH_BAR
1147                               ? impl->location_entry == NULL
1148                               : impl->location_entry != NULL)
1149                           && impl->save_folder_label == NULL
1150                           && impl->save_folder_combo == NULL
1151                           && impl->save_expander == NULL
1152                           && GTK_IS_CONTAINER (impl->browse_widgets) && gtk_widget_is_drawable (impl->browse_widgets));
1153     }
1154   else if (has_action (save_actions, G_N_ELEMENTS (save_actions), impl->action))
1155     {
1156       /* FIXME: we can't use GTK_IS_FILE_CHOOSER_ENTRY() because it uses
1157        * _gtk_file_chooser_entry_get_type(), which is a non-exported symbol.
1158        * So, we just test impl->location_entry for being non-NULL
1159        */
1160       passed = passed && (GTK_IS_CONTAINER (impl->save_widgets) && gtk_widget_is_drawable (impl->save_widgets)
1161                           && impl->location_entry != NULL && gtk_widget_is_drawable (impl->location_entry)
1162                           && GTK_IS_LABEL (impl->save_folder_label) && gtk_widget_is_drawable (impl->save_folder_label)
1163                           && GTK_IS_COMBO_BOX (impl->save_folder_combo) && gtk_widget_is_drawable (impl->save_folder_combo)
1164                           && GTK_IS_EXPANDER (impl->save_expander) && gtk_widget_is_drawable (impl->save_expander)
1165                           && GTK_IS_CONTAINER (impl->browse_widgets));
1166
1167       /* FIXME: we are in a SAVE mode; test the visibility and sensitivity of
1168        * the children that change depending on the state of the expander.
1169        */
1170     }
1171   else
1172     {
1173       g_error ("BAD TEST: test_widgets_for_current_action() doesn't know about %s", get_action_name (impl->action));
1174       passed = FALSE;
1175     }
1176
1177   return passed;
1178 }
1179
1180 typedef gboolean (* ForeachActionCallback) (GtkFileChooserDialog *dialog,
1181                                             GtkFileChooserAction  action,
1182                                             gpointer              user_data);
1183
1184 static gboolean
1185 foreach_action (GtkFileChooserDialog *dialog,
1186                 ForeachActionCallback callback,
1187                 gpointer              user_data)
1188 {
1189   GEnumClass *enum_class;
1190   int i;
1191
1192   enum_class = g_type_class_peek (GTK_TYPE_FILE_CHOOSER_ACTION);
1193   if (!enum_class)
1194     g_error ("BUG: get_action_name(): no GEnumClass for GTK_TYPE_FILE_CHOOSER_ACTION");
1195
1196   for (i = 0; i < enum_class->n_values; i++)
1197     {
1198       GEnumValue *enum_value;
1199       GtkFileChooserAction action;
1200       gboolean passed;
1201
1202       enum_value = enum_class->values + i;
1203       action = enum_value->value;
1204
1205       passed = (* callback) (dialog, action, user_data);
1206       if (!passed)
1207         return FALSE;
1208     }
1209
1210   return TRUE;
1211 }
1212
1213 struct action_closure {
1214   GtkFileChooserAction from_action;
1215 };
1216
1217 static gboolean
1218 switch_from_to_action_cb (GtkFileChooserDialog *dialog,
1219                           GtkFileChooserAction  action,
1220                           gpointer              user_data)
1221 {
1222   struct action_closure *closure;
1223   gboolean passed;
1224
1225   closure = user_data;
1226
1227   gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), closure->from_action);
1228
1229   passed = test_widgets_for_current_action (dialog, closure->from_action);
1230   log_test (passed, "switch_from_to_action_cb(): reset to action %s", get_action_name (closure->from_action));
1231   if (!passed)
1232     return FALSE;
1233
1234   gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), action);
1235
1236   passed = test_widgets_for_current_action (dialog, action);
1237   log_test (passed, "switch_from_to_action_cb(): transition from %s to %s",
1238             get_action_name (closure->from_action),
1239             get_action_name (action));
1240   return passed;
1241 }
1242
1243 static gboolean
1244 switch_from_action_cb (GtkFileChooserDialog *dialog,
1245                        GtkFileChooserAction  action,
1246                        gpointer              user_data)
1247 {
1248   struct action_closure closure;
1249
1250   closure.from_action = action;
1251
1252   return foreach_action (dialog, switch_from_to_action_cb, &closure);
1253 }
1254
1255 static void
1256 test_action_widgets (void)
1257 {
1258   GtkWidget *dialog;
1259   GtkFileChooserAction action;
1260   gboolean passed;
1261
1262   dialog = gtk_file_chooser_dialog_new ("Test file chooser",
1263                                         NULL,
1264                                         GTK_FILE_CHOOSER_ACTION_OPEN,
1265                                         GTK_STOCK_CANCEL,
1266                                         GTK_RESPONSE_CANCEL,
1267                                         GTK_STOCK_OK,
1268                                         GTK_RESPONSE_ACCEPT,
1269                                         NULL);
1270   gtk_widget_show_now (dialog);
1271
1272   action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog));
1273
1274   passed = test_widgets_for_current_action (GTK_FILE_CHOOSER_DIALOG (dialog), action);
1275   log_test (passed, "test_action_widgets(): widgets for initial action %s", get_action_name (action));
1276   g_assert (passed);
1277
1278   passed = foreach_action (GTK_FILE_CHOOSER_DIALOG (dialog), switch_from_action_cb, NULL);
1279   log_test (passed, "test_action_widgets(): all transitions through property change");
1280   g_assert (passed);
1281
1282   gtk_widget_destroy (dialog);
1283 }
1284 #endif
1285
1286 #ifdef BROKEN_TESTS
1287 static gboolean
1288 test_reload_sequence (gboolean set_folder_before_map)
1289 {
1290   GtkWidget *dialog;
1291   GtkFileChooserDefault *impl;
1292   gboolean passed;
1293   char *folder;
1294   char *current_working_dir;
1295
1296   passed = TRUE;
1297
1298   current_working_dir = g_get_current_dir ();
1299
1300   dialog = gtk_file_chooser_dialog_new ("Test file chooser",
1301                                         NULL,
1302                                         GTK_FILE_CHOOSER_ACTION_OPEN,
1303                                         GTK_STOCK_CANCEL,
1304                                         GTK_RESPONSE_CANCEL,
1305                                         GTK_STOCK_OK,
1306                                         GTK_RESPONSE_ACCEPT,
1307                                         NULL);
1308   impl = get_impl_from_dialog (dialog);
1309
1310   if (set_folder_before_map)
1311     {
1312       gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_home_dir ());
1313
1314       wait_for_idle ();
1315
1316       passed = passed && (impl->current_folder != NULL
1317                           && impl->browse_files_model != NULL
1318                           && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
1319                           && impl->reload_state == RELOAD_HAS_FOLDER
1320                           && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
1321                           && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
1322                               ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
1323                               : TRUE));
1324
1325       wait_for_idle ();
1326
1327       folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
1328       passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
1329       g_free (folder);
1330     }
1331   else
1332     {
1333       /* Initially, no folder is not loaded or pending */
1334       passed = passed && (impl->current_folder == NULL
1335                           && impl->sort_model == NULL
1336                           && impl->browse_files_model == NULL
1337                           && impl->load_state == LOAD_EMPTY
1338                           && impl->reload_state == RELOAD_EMPTY
1339                           && impl->load_timeout_id == 0);
1340
1341       wait_for_idle ();
1342
1343       folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
1344       passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
1345     }
1346
1347   log_test (passed, "test_reload_sequence(): initial status");
1348
1349   /* After mapping, it is loading some folder, either the one that was explicitly set or the default one */
1350
1351   gtk_widget_show_now (dialog);
1352
1353   wait_for_idle ();
1354
1355   passed = passed && (impl->current_folder != NULL
1356                       && impl->browse_files_model != NULL
1357                       && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
1358                       && impl->reload_state == RELOAD_HAS_FOLDER
1359                       && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
1360                       && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
1361                           ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
1362                           : TRUE));
1363
1364   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
1365   if (set_folder_before_map)
1366     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
1367   else
1368     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
1369
1370   g_free (folder);
1371
1372   log_test (passed, "test_reload_sequence(): status after map");
1373
1374   /* Unmap it; we should still have a folder */
1375
1376   gtk_widget_hide (dialog);
1377
1378   wait_for_idle ();
1379
1380   passed = passed && (impl->current_folder != NULL
1381                       && impl->browse_files_model != NULL
1382                       && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
1383                       && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
1384                       && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
1385                           ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
1386                           : TRUE));
1387
1388   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
1389   if (set_folder_before_map)
1390     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
1391   else
1392     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
1393
1394   g_free (folder);
1395
1396   log_test (passed, "test_reload_sequence(): status after unmap");
1397
1398   /* Map it again! */
1399
1400   gtk_widget_show_now (dialog);
1401
1402   wait_for_idle ();
1403
1404   passed = passed && (impl->current_folder != NULL
1405                       && impl->browse_files_model != NULL
1406                       && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
1407                       && impl->reload_state == RELOAD_HAS_FOLDER
1408                       && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
1409                       && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
1410                           ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
1411                           : TRUE));
1412
1413   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
1414   if (set_folder_before_map)
1415     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
1416   else
1417     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
1418
1419   g_free (folder);
1420
1421   log_test (passed, "test_reload_sequence(): status after re-map");
1422
1423   gtk_widget_destroy (dialog);
1424   g_free (current_working_dir);
1425
1426   return passed;
1427 }
1428
1429 static void
1430 test_reload (void)
1431 {
1432   gboolean passed;
1433
1434   passed = test_reload_sequence (FALSE);
1435   log_test (passed, "test_reload(): create and use the default folder");
1436   g_assert (passed);
1437
1438   passed = test_reload_sequence (TRUE);
1439   log_test (passed, "test_reload(): set a folder explicitly before mapping");
1440   g_assert (passed);
1441 }
1442 #endif
1443
1444 static gboolean
1445 test_button_folder_states_for_action (GtkFileChooserAction action, gboolean use_dialog, gboolean set_folder_on_dialog)
1446 {
1447   gboolean passed;
1448   GtkWidget *window;
1449   GtkWidget *button;
1450   char *folder;
1451   GtkWidget *dialog;
1452   char *current_working_dir;
1453   gboolean must_have_cwd;
1454
1455   passed = TRUE;
1456
1457   current_working_dir = g_get_current_dir ();
1458   must_have_cwd = !(use_dialog && set_folder_on_dialog);
1459
1460   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1461
1462   if (use_dialog)
1463     {
1464       dialog = gtk_file_chooser_dialog_new ("Test", NULL, action,
1465                                             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1466                                             GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1467                                             NULL);
1468       button = gtk_file_chooser_button_new_with_dialog (dialog);
1469
1470       if (set_folder_on_dialog)
1471         gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_home_dir ());
1472     }
1473   else
1474     {
1475       button = gtk_file_chooser_button_new ("Test", action);
1476       dialog = NULL; /* keep gcc happy */
1477     }
1478
1479   gtk_container_add (GTK_CONTAINER (window), button);
1480
1481   /* Pre-map; no folder is set */
1482   wait_for_idle ();
1483
1484   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button));
1485   if (must_have_cwd)
1486     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
1487   else
1488     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
1489
1490   log_test (passed, "test_button_folder_states_for_action(): %s, use_dialog=%d, set_folder_on_dialog=%d, pre-map, %s",
1491             get_action_name (action),
1492             use_dialog,
1493             set_folder_on_dialog,
1494             must_have_cwd ? "must have $cwd" : "must have explicit folder");
1495
1496   /* Map; folder should be set */
1497
1498   gtk_widget_show_all (window);
1499   gtk_widget_show_now (window);
1500
1501   wait_for_idle ();
1502
1503   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button));
1504
1505   if (must_have_cwd)
1506     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
1507   else
1508     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
1509
1510   log_test (passed, "test_button_folder_states_for_action(): %s, use_dialog=%d, set_folder_on_dialog=%d, mapped, %s",
1511             get_action_name (action),
1512             use_dialog,
1513             set_folder_on_dialog,
1514             must_have_cwd ? "must have $cwd" : "must have explicit folder");
1515   g_free (folder);
1516
1517   /* Unmap; folder should be set */
1518
1519   gtk_widget_hide (window);
1520   wait_for_idle ();
1521   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button));
1522
1523   if (must_have_cwd)
1524     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
1525   else
1526     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
1527
1528   log_test (passed, "test_button_folder_states_for_action(): %s, use_dialog=%d, set_folder_on_dialog=%d, unmapped, %s",
1529             get_action_name (action),
1530             use_dialog,
1531             set_folder_on_dialog,
1532             must_have_cwd ? "must have $cwd" : "must have explicit folder");
1533   g_free (folder);
1534
1535   /* Re-map; folder should be set */
1536
1537   gtk_widget_show_now (window);
1538   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button));
1539
1540   if (must_have_cwd)
1541     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
1542   else
1543     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
1544   wait_for_idle ();
1545   log_test (passed, "test_button_folder_states_for_action(): %s, use_dialog=%d, set_folder_on_dialog=%d, re-mapped, %s",
1546             get_action_name (action),
1547             use_dialog,
1548             set_folder_on_dialog,
1549             must_have_cwd ? "must have $cwd" : "must have explicit folder");
1550   g_free (folder);
1551
1552   g_free (current_working_dir);
1553
1554   gtk_widget_destroy (window);
1555
1556   return passed;
1557 }
1558
1559 static void
1560 test_button_folder_states (void)
1561 {
1562   /* GtkFileChooserButton only supports OPEN and SELECT_FOLDER */
1563   static const GtkFileChooserAction actions_to_test[] = {
1564     GTK_FILE_CHOOSER_ACTION_OPEN,
1565     GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
1566   };
1567   gboolean passed;
1568   int i;
1569
1570   passed = TRUE;
1571
1572   for (i = 0; i < G_N_ELEMENTS (actions_to_test); i++)
1573     {
1574       passed = passed && test_button_folder_states_for_action (actions_to_test[i], FALSE, FALSE);
1575       g_assert (passed);
1576       passed = passed && test_button_folder_states_for_action (actions_to_test[i], TRUE, FALSE);
1577       g_assert (passed);
1578       passed = passed && test_button_folder_states_for_action (actions_to_test[i], TRUE, TRUE);
1579       g_assert (passed);
1580       log_test (passed, "test_button_folder_states(): action %s", get_action_name (actions_to_test[i]));
1581     }
1582
1583   log_test (passed, "test_button_folder_states(): all supported actions");
1584 }
1585
1586 static void
1587 test_folder_switch_and_filters (void)
1588 {
1589   gboolean passed;
1590   char *cwd;
1591   char *base_dir;
1592   GFile *cwd_file;
1593   GFile *base_dir_file;
1594   GtkWidget *dialog;
1595   GtkFileFilter *all_filter;
1596   GtkFileFilter *txt_filter;
1597   GtkFileChooserDefault *impl;
1598
1599   passed = TRUE;
1600
1601   cwd = g_get_current_dir ();
1602   base_dir = g_build_filename (cwd, "file-chooser-test-dir", NULL);
1603
1604   dialog = gtk_file_chooser_dialog_new ("Test", NULL, GTK_FILE_CHOOSER_ACTION_OPEN,
1605                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1606                                         GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1607                                         NULL);
1608   impl = get_impl_from_dialog (dialog);
1609
1610   cwd_file = g_file_new_for_path (cwd);
1611   base_dir_file = g_file_new_for_path (base_dir);
1612
1613   passed = passed && gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), base_dir);
1614   g_assert (passed);
1615
1616   /* All files filter */
1617
1618   all_filter = gtk_file_filter_new ();
1619   gtk_file_filter_set_name (all_filter, "All files");
1620   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), all_filter);
1621
1622   /* *.txt filter */
1623
1624   txt_filter = gtk_file_filter_new ();
1625   gtk_file_filter_set_name (all_filter, "*.txt");
1626   gtk_file_filter_add_pattern (txt_filter, "*.txt");
1627   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), txt_filter);
1628
1629   /* Test filter set */
1630
1631   gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), all_filter);
1632   passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == all_filter);
1633   g_assert (passed);
1634
1635   gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), txt_filter);
1636   passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == txt_filter);
1637   log_test (passed, "test_folder_switch_and_filters(): set and get filter");
1638   g_assert (passed);
1639
1640   gtk_widget_show (dialog);
1641
1642   /* Test that filter is unchanged when we switch folders */
1643
1644   gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd);
1645   sleep_in_main_loop ();
1646   passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == txt_filter);
1647   g_assert (passed);
1648
1649   gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), base_dir);
1650   sleep_in_main_loop ();
1651
1652   g_signal_emit_by_name (impl->browse_path_bar, "path-clicked",
1653                          cwd_file,
1654                          base_dir_file,
1655                          FALSE);
1656   sleep_in_main_loop ();
1657   passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == txt_filter);
1658   log_test (passed, "test_folder_switch_and_filters(): filter after changing folder");
1659   g_assert (passed);
1660
1661   /* cleanups */
1662   g_free (cwd);
1663   g_free (base_dir);
1664   g_object_unref (cwd_file);
1665   g_object_unref (base_dir_file);
1666
1667   gtk_widget_destroy (dialog);
1668
1669   log_test (passed, "test_folder_switch_and_filters(): all filter tests");
1670 }
1671
1672 int
1673 main (int    argc,
1674       char **argv)
1675 {
1676   /* initialize test program */
1677   gtk_test_init (&argc, &argv);
1678
1679   /* Register tests */
1680
1681   setup_file_chooser_button_tests ();
1682 #ifdef BROKEN_TESTS
1683   setup_set_filename_tests ();
1684   setup_set_current_name_tests ();
1685
1686   g_test_add_func ("/GtkFileChooser/confirm_overwrite", test_confirm_overwrite);
1687   g_test_add_func ("/GtkFileChooser/action_widgets", test_action_widgets);
1688   g_test_add_func ("/GtkFileChooser/reload", test_reload);
1689   g_test_add_func ("/GtkFileChooser/button_folder_states", test_button_folder_states);
1690   g_test_add_func ("/GtkFileChooser/folder_switch_and_filters", test_folder_switch_and_filters);
1691 #endif
1692
1693   /* run and check selected tests */
1694   return g_test_run();
1695 }