]> Pileus Git - ~andy/gtk/blob - gtk/tests/treemodel.c
Merge branch 'bgo593793-filechooser-recent-folders-master'
[~andy/gtk] / gtk / tests / treemodel.c
1 /* Main wrapper for TreeModel test suite.
2  * Copyright (C) 2011  Kristian Rietveld  <kris@gtk.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <gtk/gtk.h>
21
22 #include "treemodel.h"
23
24 int
25 main (int    argc,
26       char **argv)
27 {
28   gtk_test_init (&argc, &argv, NULL);
29
30   g_test_bug_base ("http://bugzilla.gnome.org/");
31
32   register_list_store_tests ();
33   register_tree_store_tests ();
34   register_model_ref_count_tests ();
35   register_sort_model_tests ();
36   register_filter_model_tests ();
37
38   return g_test_run ();
39 }
40
41 /*
42  * Signal monitor
43  */
44
45 static const char *
46 signal_name_to_string (SignalName signal)
47 {
48   switch (signal)
49     {
50       case ROW_INSERTED:
51           return "row-inserted";
52
53       case ROW_DELETED:
54           return "row-deleted";
55
56       case ROW_CHANGED:
57           return "row-changed";
58
59       case ROW_HAS_CHILD_TOGGLED:
60           return "row-has-child-toggled";
61
62       case ROWS_REORDERED:
63           return "rows-reordered";
64
65       default:
66           /* Fall through */
67           break;
68     }
69
70   return "(unknown)";
71 }
72
73 typedef struct
74 {
75   SignalName signal;
76   GtkTreePath *path;
77
78   /* For rows-reordered */
79   int *new_order;
80   int len;
81 }
82 Signal;
83
84
85 static Signal *
86 signal_new (SignalName signal, GtkTreePath *path)
87 {
88   Signal *s;
89
90   s = g_new0 (Signal, 1);
91   s->signal = signal;
92   s->path = gtk_tree_path_copy (path);
93   s->new_order = NULL;
94
95   return s;
96 }
97
98 static Signal *
99 signal_new_with_order (SignalName signal, GtkTreePath *path,
100                        int *new_order, int len)
101 {
102   Signal *s = signal_new (signal, path);
103
104   s->new_order = new_order;
105   s->len = len;
106
107   return s;
108 }
109
110 static void
111 signal_free (Signal *s)
112 {
113   if (s->path)
114     gtk_tree_path_free (s->path);
115
116   g_free (s);
117 }
118
119
120 struct _SignalMonitor
121 {
122   GQueue *queue;
123   GtkTreeModel *client;
124   gulong signal_ids[LAST_SIGNAL];
125 };
126
127
128 static void
129 signal_monitor_generic_handler (SignalMonitor *m,
130                                 SignalName     signal,
131                                 GtkTreeModel  *model,
132                                 GtkTreeIter   *iter,
133                                 GtkTreePath   *path,
134                                 int           *new_order)
135 {
136   Signal *s;
137
138   if (g_queue_is_empty (m->queue))
139     {
140       gchar *path_str;
141
142       path_str = gtk_tree_path_to_string (path);
143       g_error ("Signal queue empty, got signal %s path %s\n",
144                signal_name_to_string (signal), path_str);
145       g_free (path_str);
146
147       g_assert_not_reached ();
148     }
149
150   if (m->client != model)
151     {
152       g_error ("Model mismatch; expected %p, got %p\n",
153                m->client, model);
154       g_assert_not_reached ();
155     }
156
157   s = g_queue_peek_tail (m->queue);
158
159 #if 0
160   /* For debugging: output signals that are coming in.  Leaks memory. */
161   g_print ("signal=%s path=%s\n", signal_name_to_string (signal),
162            gtk_tree_path_to_string (path));
163 #endif
164
165   if (s->signal != signal ||
166       (gtk_tree_path_get_depth (s->path) == 0 &&
167        gtk_tree_path_get_depth (path) != 0) ||
168       (gtk_tree_path_get_depth (s->path) != 0 &&
169        gtk_tree_path_compare (s->path, path) != 0))
170     {
171       gchar *path_str, *s_path_str;
172
173       s_path_str = gtk_tree_path_to_string (s->path);
174       path_str = gtk_tree_path_to_string (path);
175
176       g_error ("Signals don't match; expected signal %s path %s, got signal %s path %s\n",
177                signal_name_to_string (s->signal), s_path_str,
178                signal_name_to_string (signal), path_str);
179
180       g_free (s_path_str);
181       g_free (path_str);
182
183       g_assert_not_reached ();
184     }
185
186   if (signal == ROWS_REORDERED && s->new_order != NULL)
187     {
188       int i, len;
189
190       g_assert (new_order != NULL);
191
192       len = gtk_tree_model_iter_n_children (model, iter);
193       g_assert (s->len == len);
194
195       for (i = 0; i < len; i++)
196         g_assert (s->new_order[i] == new_order[i]);
197     }
198
199   s = g_queue_pop_tail (m->queue);
200
201   signal_free (s);
202 }
203
204 static void
205 signal_monitor_row_inserted (GtkTreeModel *model,
206                              GtkTreePath  *path,
207                              GtkTreeIter  *iter,
208                              gpointer      data)
209 {
210   signal_monitor_generic_handler (data, ROW_INSERTED,
211                                   model, iter, path, NULL);
212 }
213
214 static void
215 signal_monitor_row_deleted (GtkTreeModel *model,
216                             GtkTreePath  *path,
217                             gpointer      data)
218 {
219   signal_monitor_generic_handler (data, ROW_DELETED,
220                                   model, NULL, path, NULL);
221 }
222
223 static void
224 signal_monitor_row_changed (GtkTreeModel *model,
225                             GtkTreePath  *path,
226                             GtkTreeIter  *iter,
227                             gpointer      data)
228 {
229   signal_monitor_generic_handler (data, ROW_CHANGED,
230                                   model, iter, path, NULL);
231 }
232
233 static void
234 signal_monitor_row_has_child_toggled (GtkTreeModel *model,
235                                       GtkTreePath  *path,
236                                       GtkTreeIter  *iter,
237                                       gpointer      data)
238 {
239   signal_monitor_generic_handler (data, ROW_HAS_CHILD_TOGGLED,
240                                   model, iter, path, NULL);
241 }
242
243 static void
244 signal_monitor_rows_reordered (GtkTreeModel *model,
245                                GtkTreePath  *path,
246                                GtkTreeIter  *iter,
247                                gint         *new_order,
248                                gpointer      data)
249 {
250   signal_monitor_generic_handler (data, ROWS_REORDERED,
251                                   model, iter, path, new_order);
252 }
253
254 SignalMonitor *
255 signal_monitor_new (GtkTreeModel *client)
256 {
257   SignalMonitor *m;
258
259   m = g_new0 (SignalMonitor, 1);
260   m->client = g_object_ref (client);
261   m->queue = g_queue_new ();
262
263   m->signal_ids[ROW_INSERTED] = g_signal_connect (client,
264                                                   "row-inserted",
265                                                   G_CALLBACK (signal_monitor_row_inserted),
266                                                   m);
267   m->signal_ids[ROW_DELETED] = g_signal_connect (client,
268                                                  "row-deleted",
269                                                  G_CALLBACK (signal_monitor_row_deleted),
270                                                  m);
271   m->signal_ids[ROW_CHANGED] = g_signal_connect (client,
272                                                  "row-changed",
273                                                  G_CALLBACK (signal_monitor_row_changed),
274                                                  m);
275   m->signal_ids[ROW_HAS_CHILD_TOGGLED] = g_signal_connect (client,
276                                                            "row-has-child-toggled",
277                                                            G_CALLBACK (signal_monitor_row_has_child_toggled),
278                                                            m);
279   m->signal_ids[ROWS_REORDERED] = g_signal_connect (client,
280                                                     "rows-reordered",
281                                                     G_CALLBACK (signal_monitor_rows_reordered),
282                                                     m);
283
284   return m;
285 }
286
287 void
288 signal_monitor_free (SignalMonitor *m)
289 {
290   int i;
291
292   for (i = 0; i < LAST_SIGNAL; i++)
293     g_signal_handler_disconnect (m->client, m->signal_ids[i]);
294
295   g_object_unref (m->client);
296
297   if (m->queue)
298     g_queue_free (m->queue);
299
300   g_free (m);
301 }
302
303 void
304 signal_monitor_assert_is_empty (SignalMonitor *m)
305 {
306   g_assert (g_queue_is_empty (m->queue));
307 }
308
309 void
310 signal_monitor_append_signal_path (SignalMonitor *m,
311                                    SignalName     signal,
312                                    GtkTreePath   *path)
313 {
314   Signal *s;
315
316   s = signal_new (signal, path);
317   g_queue_push_head (m->queue, s);
318 }
319
320 void
321 signal_monitor_append_signal_reordered (SignalMonitor *m,
322                                         SignalName     signal,
323                                         GtkTreePath   *path,
324                                         int           *new_order,
325                                         int            len)
326 {
327   Signal *s;
328
329   s = signal_new_with_order (signal, path, new_order, len);
330   g_queue_push_head (m->queue, s);
331 }
332
333 void
334 signal_monitor_append_signal (SignalMonitor *m,
335                               SignalName     signal,
336                               const gchar   *path_string)
337 {
338   Signal *s;
339   GtkTreePath *path;
340
341   path = gtk_tree_path_new_from_string (path_string);
342
343   s = signal_new (signal, path);
344   g_queue_push_head (m->queue, s);
345
346   gtk_tree_path_free (path);
347 }