1 /* Basic GtkTreeView unit tests.
2  * Copyright (C) 2009  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 static void
test_bug_546005(void)21 test_bug_546005 (void)
22 {
23   GtkTreeIter iter;
24   GtkTreePath *path;
25   GtkTreePath *cursor_path;
26   GtkListStore *list_store;
27   GtkWidget *view;
28 
29   /*http://bugzilla.gnome.org/show_bug.cgi?id=546005 */
30 
31   /* Tests provided by Bjorn Lindqvist, Paul Pogonyshev */
32   view = gtk_tree_view_new ();
33 
34   /* Invalid path on tree view without model */
35   path = gtk_tree_path_new_from_indices (1, -1);
36   gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path,
37                             NULL, FALSE);
38   gtk_tree_path_free (path);
39 
40   list_store = gtk_list_store_new (1, G_TYPE_STRING);
41   gtk_tree_view_set_model (GTK_TREE_VIEW (view),
42                            GTK_TREE_MODEL (list_store));
43 
44   /* Invalid path on tree view with empty model */
45   path = gtk_tree_path_new_from_indices (1, -1);
46   gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path,
47                             NULL, FALSE);
48   gtk_tree_path_free (path);
49 
50   /* Valid path */
51   gtk_list_store_insert_with_values (list_store, &iter, 0,
52                                      0, "hi",
53                                      -1);
54 
55   path = gtk_tree_path_new_from_indices (0, -1);
56   gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path,
57                             NULL, FALSE);
58 
59   gtk_tree_view_get_cursor (GTK_TREE_VIEW (view), &cursor_path, NULL);
60   //gtk_assert_cmptreepath (cursor_path, ==, path);
61 
62   gtk_tree_path_free (path);
63   gtk_tree_path_free (cursor_path);
64 
65   /* Invalid path on tree view with model */
66   path = gtk_tree_path_new_from_indices (1, -1);
67   gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path,
68                             NULL, FALSE);
69   gtk_tree_path_free (path);
70 
71   g_object_unref (g_object_ref_sink (view));
72 }
73 
74 static void
test_bug_539377(void)75 test_bug_539377 (void)
76 {
77   GtkWidget *view;
78   GtkTreePath *path;
79   GtkListStore *list_store;
80   gboolean ret;
81 
82   /*http://bugzilla.gnome.org/show_bug.cgi?id=539377 */
83 
84   /* Test provided by Bjorn Lindqvist */
85 
86   /* Non-realized view, no model */
87   view = gtk_tree_view_new ();
88   ret = gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (view), 10, 10, &path,
89                                        NULL, NULL, NULL);
90   g_assert_false (ret);
91   ret = gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (view), 10, 10,
92                                            &path, NULL);
93   g_assert_false (ret);
94 
95   /* Non-realized view, with model */
96   list_store = gtk_list_store_new (1, G_TYPE_STRING);
97   gtk_tree_view_set_model (GTK_TREE_VIEW (view),
98                            GTK_TREE_MODEL (list_store));
99 
100   ret = gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (view), 10, 10, &path,
101                                        NULL, NULL, NULL);
102   g_assert_false (ret);
103   ret = gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (view), 10, 10,
104                                            &path, NULL);
105   g_assert_false (ret);
106 
107   g_object_unref (g_object_ref_sink (view));
108 }
109 
110 static void
test_select_collapsed_row(void)111 test_select_collapsed_row (void)
112 {
113   GtkTreeIter child, parent;
114   GtkTreePath *path;
115   GtkTreeStore *tree_store;
116   GtkTreeSelection *selection;
117   GtkWidget *view;
118 
119   /* Reported by Michael Natterer */
120   tree_store = gtk_tree_store_new (1, G_TYPE_STRING);
121   view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (tree_store));
122 
123   gtk_tree_store_insert_with_values (tree_store, &parent, NULL, 0,
124                                      0, "Parent",
125                                      -1);
126 
127   gtk_tree_store_insert_with_values (tree_store, &child, &parent, 0,
128                                      0, "Child",
129                                      -1);
130   gtk_tree_store_insert_with_values (tree_store, &child, &parent, 0,
131                                      0, "Child",
132                                      -1);
133 
134 
135   /* Try to select a child path. */
136   path = gtk_tree_path_new_from_indices (0, 1, -1);
137   gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path, NULL, FALSE);
138 
139   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
140 
141   /* Check that the parent is not selected. */
142   gtk_tree_path_up (path);
143   g_assert_false (gtk_tree_selection_path_is_selected (selection, path));
144 
145   /* Nothing should be selected at this point. */
146   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
147 
148   /* Check that selection really still works. */
149   gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path, NULL, FALSE);
150   g_assert_true (gtk_tree_selection_path_is_selected (selection, path));
151   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 1);
152 
153   /* Expand and select child node now. */
154   gtk_tree_path_append_index (path, 1);
155   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
156 
157   gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path, NULL, FALSE);
158   g_assert_true (gtk_tree_selection_path_is_selected (selection, path));
159   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 1);
160 
161   gtk_tree_path_free (path);
162 
163   g_object_unref (g_object_ref_sink (view));
164 }
165 
166 static gboolean
test_row_separator_height_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)167 test_row_separator_height_func (GtkTreeModel *model,
168                                 GtkTreeIter  *iter,
169                                 gpointer      data)
170 {
171   gboolean ret = FALSE;
172   GtkTreePath *path;
173 
174   path = gtk_tree_model_get_path (model, iter);
175   if (gtk_tree_path_get_indices (path)[0] == 2)
176     ret = TRUE;
177   gtk_tree_path_free (path);
178 
179   return ret;
180 }
181 
182 static void
test_row_separator_height(void)183 test_row_separator_height (void)
184 {
185   int height;
186   GtkTreeIter iter;
187   GtkTreePath *path;
188   GtkListStore *store;
189   GtkWidget *window;
190   GtkWidget *tree_view;
191   GdkRectangle rect = { 0, }, cell_rect = { 0, };
192 
193   store = gtk_list_store_new (1, G_TYPE_STRING);
194   gtk_list_store_insert_with_values (store, &iter, 0, 0, "Row content", -1);
195   gtk_list_store_insert_with_values (store, &iter, 1, 0, "Row content", -1);
196   gtk_list_store_insert_with_values (store, &iter, 2, 0, "Row content", -1);
197   gtk_list_store_insert_with_values (store, &iter, 3, 0, "Row content", -1);
198   gtk_list_store_insert_with_values (store, &iter, 4, 0, "Row content", -1);
199 
200   window = gtk_window_new ();
201 
202   tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
203   gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (tree_view),
204                                         test_row_separator_height_func,
205                                         NULL,
206                                         NULL);
207 
208   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
209                                                0,
210                                                "Test",
211                                                gtk_cell_renderer_text_new (),
212                                                "text", 0,
213                                                NULL);
214 
215   gtk_window_set_child (GTK_WINDOW (window), tree_view);
216   gtk_widget_show (window);
217 
218   gtk_test_widget_wait_for_draw (window);
219 
220   path = gtk_tree_path_new_from_indices (2, -1);
221   gtk_tree_view_get_background_area (GTK_TREE_VIEW (tree_view),
222                                      path, NULL, &rect);
223   gtk_tree_view_get_cell_area (GTK_TREE_VIEW (tree_view),
224                                path, NULL, &cell_rect);
225   gtk_tree_path_free (path);
226 
227   height = 2;
228 
229   g_assert_cmpint (rect.height, ==, height);
230   g_assert_cmpint (cell_rect.height, ==, height);
231 
232   gtk_window_destroy (GTK_WINDOW (window));
233 }
234 
235 static void
test_selection_count(void)236 test_selection_count (void)
237 {
238   GtkTreePath *path;
239   GtkListStore *list_store;
240   GtkTreeSelection *selection;
241   GtkWidget *view;
242 
243   /*http://bugzilla.gnome.org/show_bug.cgi?id=702957 */
244 
245   list_store = gtk_list_store_new (1, G_TYPE_STRING);
246   view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
247 
248   gtk_list_store_insert_with_values (list_store, NULL, 0, 0, "One", -1);
249   gtk_list_store_insert_with_values (list_store, NULL, 1, 0, "Two", -1);
250   gtk_list_store_insert_with_values (list_store, NULL, 2, 0, "Tree", -1);
251 
252   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
253   gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
254 
255   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
256 
257   path = gtk_tree_path_new_from_indices (0, -1);
258   gtk_tree_selection_select_path (selection, path);
259   gtk_tree_path_free (path);
260 
261   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 1);
262 
263   path = gtk_tree_path_new_from_indices (2, -1);
264   gtk_tree_selection_select_path (selection, path);
265   gtk_tree_path_free (path);
266 
267   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 2);
268 
269   path = gtk_tree_path_new_from_indices (2, -1);
270   gtk_tree_selection_select_path (selection, path);
271   gtk_tree_path_free (path);
272 
273   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 2);
274 
275   path = gtk_tree_path_new_from_indices (1, -1);
276   gtk_tree_selection_select_path (selection, path);
277   gtk_tree_path_free (path);
278 
279   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 3);
280 
281   gtk_tree_selection_unselect_all (selection);
282 
283   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
284 
285   g_object_unref (g_object_ref_sink (view));
286 }
287 
288 static void G_GNUC_NORETURN
abort_cb(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)289 abort_cb (GtkTreeModel *model,
290           GtkTreePath  *path,
291           GtkTreeIter  *iter,
292           gpointer      data)
293 {
294   g_assert_not_reached ();
295 }
296 
297 static void
test_selection_empty(void)298 test_selection_empty (void)
299 {
300   GtkTreePath *path;
301   GtkListStore *list_store;
302   GtkTreeSelection *selection;
303   GtkWidget *view;
304   GtkTreeIter iter;
305 
306   /*http://bugzilla.gnome.org/show_bug.cgi?id=712760 */
307 
308   list_store = gtk_list_store_new (1, G_TYPE_STRING);
309   view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
310   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
311 
312   g_assert_false (gtk_tree_selection_get_selected (selection, NULL, &iter));
313   gtk_tree_selection_selected_foreach (selection, abort_cb, NULL);
314   g_assert_null (gtk_tree_selection_get_selected_rows (selection, NULL));
315   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
316 
317   path = gtk_tree_path_new_from_indices (0, -1);
318 
319   gtk_tree_selection_select_path (selection, path);
320   gtk_tree_selection_unselect_path (selection, path);
321   g_assert_false (gtk_tree_selection_path_is_selected (selection, path));
322 
323   gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
324 
325   gtk_tree_selection_select_all (selection);
326   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
327 
328   gtk_tree_selection_unselect_all (selection);
329   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
330 
331   gtk_tree_selection_select_range (selection, path, path);
332   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
333 
334   gtk_tree_selection_unselect_range (selection, path, path);
335   g_assert_cmpint (gtk_tree_selection_count_selected_rows (selection), ==, 0);
336 
337   gtk_tree_path_free (path);
338 
339   g_object_unref (g_object_ref_sink (view));
340 }
341 
342 int
main(int argc,char ** argv)343 main (int    argc,
344       char **argv)
345 {
346   gtk_test_init (&argc, &argv, NULL);
347 
348   g_test_add_func ("/TreeView/cursor/bug-546005", test_bug_546005);
349   g_test_add_func ("/TreeView/cursor/bug-539377", test_bug_539377);
350   g_test_add_func ("/TreeView/cursor/select-collapsed_row",
351                    test_select_collapsed_row);
352   g_test_add_func ("/TreeView/sizing/row-separator-height",
353                    test_row_separator_height);
354   g_test_add_func ("/TreeView/selection/count", test_selection_count);
355   g_test_add_func ("/TreeView/selection/empty", test_selection_empty);
356 
357   return g_test_run ();
358 }
359