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