~canonical-dx-team/ubuntu/maverick/gtk+2.0/menuproxy

« back to all changes in this revision

Viewing changes to tests/testtreeview.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-05-04 12:24:25 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20070504122425-0m8midgzrp40y8w2
Tags: 2.10.12-1ubuntu1
* Sync with Debian
* New upstream version:
  Fixed bugs:
  - 379414 file chooser warnings when changing path in the entry
  - 418585 GtkFileChooserDefault sizing code is not DPI independent
  - 419568 Crash in search if start with special letter
  - 435062 build dies with icon cache validation
  - 379399 Segfault to call gtk_print_operation_run twice.
  - 387889 cups backend has problems when there are too many printers
  - 418531 invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon...
  - 423916 crash in color scheme code
  - 424042 Segmentation fault while quickly pressing Alt+arrows
  - 415260 Protect against negative indices when setting values in G...
  - 419171 XGetVisualInfo() may not set nxvisuals
  - 128852 Gdk cursors don't look good on win32
  - 344657 Ctrl-H doesn't toggle "Show Hidden Files" setting
  - 345345 PrintOperation::paginate is not emitted for class handler
  - 347567 GtkPrintOperation::end-print is not emitted if it's cance...
  - 369112 gtk_ui_manager_add_ui should accept unnamed separator
  - 392015 Selected menu item invisible on Windows Vista
  - 399253 MS-Windows Theme Bottom Tab placement rendering glitches
  - 399425 gtk_input_dialog_fill_axes() adds child to gtkscrolledwin...
  - 403251 [patch] little memory leak in GtkPrintJob
  - 403267 [patch] memory leak in GtkPageSetupUnixDialog
  - 403470 MS-Windows Theme tab placement other than on top leaks a ...
  - 404506 Windows system fonts that have multi-byte font names cann...
  - 405089 Incorrect window placement for GtkEventBox private window
  - 405515 Minor leak in gtkfilesystemmodel.c
  - 405539 gdk_pixbuf_save() for PNG saver can return FALSE without ...
  - 415681 gdk_window_clear_area includes an extra line and column o...
  - 418219 GtkRecentChooser should apply filter before sorting and c...
  - 418403 Scroll to printer after selecting it from settings
  - 421985 _gtk_print_operation_platform_backend_launch_preview
  - 421990 gtk_print_job_get_surface
  - 421993 gtk_print_operation_init
  - 423064 Conditional jump or move depends on uninitialised value(s...
  - 423722 Fix printing header in gtk-demo
  - 424168 gtk_print_operation_run on async preview
  - 425655 Don't install gtk+-unix-print-2.0.pc on non-UNIX platforms
  - 425786 GDK segfaults if XineramaQueryScreens fails
  - 428665 Lpr Backend gets stuck in infinite loop during gtk_enumer...
  - 429902 GtkPrintOperation leaks cairo contextes
  - 431997 First delay of GdkPixbufAnimationIter is wrong
  - 433242 Inconsistent scroll arrow position calculations
  - 433972 Placing gtk.Expander inside a gtk.TextView() changes gtk....
  - 434261 _gtk_toolbar_elide_underscores incorrectly handles some s...
  - 383354 ctrl-L should make 'Location' entry disappear
  - 418673 gtk_recent_manager_add_item
  - 429732 gtk_accel_group_finalize accesses invalid memory
  - 435028 WM_CLIENT_LEADER is wrong on the leader_window
  - 431067 Background of the header window is not updated
  - 338843 add recent files support inside the ui manager
  - 148535 add drop shadow to menus, tooltips, etc. under Windows XP
* debian/control.in:
  - Conflicts on ubuntulooks (<= 0.9.11-1)
* debian/patches/15_default-fallback-icon-theme.patch:
  - patch from Debian, fallback on gnome icon theme

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* testtreeview.c
 
2
 * Copyright (C) 2001 Red Hat, Inc
 
3
 * Author: Jonathan Blandford
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Library General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Library General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Library General Public
 
16
 * License along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
#undef GTK_DISABLE_DEPRECATED
 
22
#include <string.h>
 
23
#include "prop-editor.h"
 
24
#include <gtk/gtk.h>
 
25
#include <stdlib.h>
 
26
 
 
27
/* Don't copy this bad example; inline RGB data is always a better
 
28
 * idea than inline XPMs.
 
29
 */
 
30
static char  *book_closed_xpm[] = {
 
31
"16 16 6 1",
 
32
"       c None s None",
 
33
".      c black",
 
34
"X      c red",
 
35
"o      c yellow",
 
36
"O      c #808080",
 
37
"#      c white",
 
38
"                ",
 
39
"       ..       ",
 
40
"     ..XX.      ",
 
41
"   ..XXXXX.     ",
 
42
" ..XXXXXXXX.    ",
 
43
".ooXXXXXXXXX.   ",
 
44
"..ooXXXXXXXXX.  ",
 
45
".X.ooXXXXXXXXX. ",
 
46
".XX.ooXXXXXX..  ",
 
47
" .XX.ooXXX..#O  ",
 
48
"  .XX.oo..##OO. ",
 
49
"   .XX..##OO..  ",
 
50
"    .X.#OO..    ",
 
51
"     ..O..      ",
 
52
"      ..        ",
 
53
"                "
 
54
};
 
55
 
 
56
static void run_automated_tests (void);
 
57
 
 
58
/* This custom model is to test custom model use. */
 
59
 
 
60
#define GTK_TYPE_MODEL_TYPES                            (gtk_tree_model_types_get_type ())
 
61
#define GTK_TREE_MODEL_TYPES(obj)                       (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_MODEL_TYPES, GtkTreeModelTypes))
 
62
#define GTK_TREE_MODEL_TYPES_CLASS(klass)               (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_MODEL_TYPES, GtkTreeModelTypesClass))
 
63
#define GTK_IS_TREE_MODEL_TYPES(obj)                    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_MODEL_TYPES))
 
64
#define GTK_IS_TREE_MODEL_TYPES_GET_CLASS(klass)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_MODEL_TYPES))
 
65
 
 
66
typedef struct _GtkTreeModelTypes       GtkTreeModelTypes;
 
67
typedef struct _GtkTreeModelTypesClass  GtkTreeModelTypesClass;
 
68
 
 
69
struct _GtkTreeModelTypes
 
70
{
 
71
  GObject parent;
 
72
 
 
73
  gint stamp;
 
74
};
 
75
 
 
76
struct _GtkTreeModelTypesClass
 
77
{
 
78
  GObjectClass parent_class;
 
79
 
 
80
  guint        (* get_flags)       (GtkTreeModel *tree_model);   
 
81
  gint         (* get_n_columns)   (GtkTreeModel *tree_model);
 
82
  GType        (* get_column_type) (GtkTreeModel *tree_model,
 
83
                                    gint          index);
 
84
  gboolean     (* get_iter)        (GtkTreeModel *tree_model,
 
85
                                    GtkTreeIter  *iter,
 
86
                                    GtkTreePath  *path);
 
87
  GtkTreePath *(* get_path)        (GtkTreeModel *tree_model,
 
88
                                    GtkTreeIter  *iter);
 
89
  void         (* get_value)       (GtkTreeModel *tree_model,
 
90
                                    GtkTreeIter  *iter,
 
91
                                    gint          column,
 
92
                                    GValue       *value);
 
93
  gboolean     (* iter_next)       (GtkTreeModel *tree_model,
 
94
                                    GtkTreeIter  *iter);
 
95
  gboolean     (* iter_children)   (GtkTreeModel *tree_model,
 
96
                                    GtkTreeIter  *iter,
 
97
                                    GtkTreeIter  *parent);
 
98
  gboolean     (* iter_has_child)  (GtkTreeModel *tree_model,
 
99
                                    GtkTreeIter  *iter);
 
100
  gint         (* iter_n_children) (GtkTreeModel *tree_model,
 
101
                                    GtkTreeIter  *iter);
 
102
  gboolean     (* iter_nth_child)  (GtkTreeModel *tree_model,
 
103
                                    GtkTreeIter  *iter,
 
104
                                    GtkTreeIter  *parent,
 
105
                                    gint          n);
 
106
  gboolean     (* iter_parent)     (GtkTreeModel *tree_model,
 
107
                                    GtkTreeIter  *iter,
 
108
                                    GtkTreeIter  *child);
 
109
  void         (* ref_iter)        (GtkTreeModel *tree_model,
 
110
                                    GtkTreeIter  *iter);
 
111
  void         (* unref_iter)      (GtkTreeModel *tree_model,
 
112
                                    GtkTreeIter  *iter);
 
113
 
 
114
  /* These will be moved into the GtkTreeModelIface eventually */
 
115
  void         (* changed)         (GtkTreeModel *tree_model,
 
116
                                    GtkTreePath  *path,
 
117
                                    GtkTreeIter  *iter);
 
118
  void         (* inserted)        (GtkTreeModel *tree_model,
 
119
                                    GtkTreePath  *path,
 
120
                                    GtkTreeIter  *iter);
 
121
  void         (* child_toggled)   (GtkTreeModel *tree_model,
 
122
                                    GtkTreePath  *path,
 
123
                                    GtkTreeIter  *iter);
 
124
  void         (* deleted)         (GtkTreeModel *tree_model,
 
125
                                    GtkTreePath  *path);
 
126
};
 
127
 
 
128
GType              gtk_tree_model_types_get_type      (void) G_GNUC_CONST;
 
129
GtkTreeModelTypes *gtk_tree_model_types_new           (void);
 
130
 
 
131
typedef enum
 
132
{
 
133
  COLUMNS_NONE,
 
134
  COLUMNS_ONE,
 
135
  COLUMNS_LOTS,
 
136
  COLUMNS_LAST
 
137
} ColumnsType;
 
138
 
 
139
static gchar *column_type_names[] = {
 
140
  "No columns",
 
141
  "One column",
 
142
  "Many columns"
 
143
};
 
144
 
 
145
#define N_COLUMNS 9
 
146
 
 
147
static GType*
 
148
get_model_types (void)
 
149
{
 
150
  static GType column_types[N_COLUMNS] = { 0 };
 
151
  
 
152
  if (column_types[0] == 0)
 
153
    {
 
154
      column_types[0] = G_TYPE_STRING;
 
155
      column_types[1] = G_TYPE_STRING;
 
156
      column_types[2] = GDK_TYPE_PIXBUF;
 
157
      column_types[3] = G_TYPE_FLOAT;
 
158
      column_types[4] = G_TYPE_UINT;
 
159
      column_types[5] = G_TYPE_UCHAR;
 
160
      column_types[6] = G_TYPE_CHAR;
 
161
#define BOOL_COLUMN 7
 
162
      column_types[BOOL_COLUMN] = G_TYPE_BOOLEAN;
 
163
      column_types[8] = G_TYPE_INT;
 
164
    }
 
165
 
 
166
  return column_types;
 
167
}
 
168
 
 
169
static void
 
170
col_clicked_cb (GtkTreeViewColumn *col, gpointer data)
 
171
{
 
172
  GtkWindow *win;
 
173
 
 
174
  win = GTK_WINDOW (create_prop_editor (G_OBJECT (col), GTK_TYPE_TREE_VIEW_COLUMN));
 
175
 
 
176
  gtk_window_set_title (win, gtk_tree_view_column_get_title (col));
 
177
}
 
178
 
 
179
static void
 
180
setup_column (GtkTreeViewColumn *col)
 
181
{
 
182
  gtk_tree_view_column_set_clickable (col, TRUE);
 
183
  g_signal_connect (col,
 
184
                    "clicked",
 
185
                    G_CALLBACK (col_clicked_cb),
 
186
                    NULL);
 
187
}
 
188
 
 
189
static void
 
190
toggled_callback (GtkCellRendererToggle *celltoggle,
 
191
                  gchar                 *path_string,
 
192
                  GtkTreeView           *tree_view)
 
193
{
 
194
  GtkTreeModel *model = NULL;
 
195
  GtkTreeModelSort *sort_model = NULL;
 
196
  GtkTreePath *path;
 
197
  GtkTreeIter iter;
 
198
  gboolean active = FALSE;
 
199
  
 
200
  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
201
 
 
202
  model = gtk_tree_view_get_model (tree_view);
 
203
  
 
204
  if (GTK_IS_TREE_MODEL_SORT (model))
 
205
    {
 
206
      sort_model = GTK_TREE_MODEL_SORT (model);
 
207
      model = gtk_tree_model_sort_get_model (sort_model);
 
208
    }
 
209
 
 
210
  if (model == NULL)
 
211
    return;
 
212
 
 
213
  if (sort_model)
 
214
    {
 
215
      g_warning ("FIXME implement conversion from TreeModelSort iter to child model iter");
 
216
      return;
 
217
    }
 
218
      
 
219
  path = gtk_tree_path_new_from_string (path_string);
 
220
  if (!gtk_tree_model_get_iter (model,
 
221
                                &iter, path))
 
222
    {
 
223
      g_warning ("%s: bad path?", G_STRLOC);
 
224
      return;
 
225
    }
 
226
  gtk_tree_path_free (path);
 
227
  
 
228
  if (GTK_IS_LIST_STORE (model))
 
229
    {
 
230
      gtk_tree_model_get (GTK_TREE_MODEL (model),
 
231
                          &iter,
 
232
                          BOOL_COLUMN,
 
233
                          &active,
 
234
                          -1);
 
235
      
 
236
      gtk_list_store_set (GTK_LIST_STORE (model),
 
237
                          &iter,
 
238
                          BOOL_COLUMN,
 
239
                          !active,
 
240
                          -1);
 
241
    }
 
242
  else if (GTK_IS_TREE_STORE (model))
 
243
    {
 
244
      gtk_tree_model_get (GTK_TREE_MODEL (model),
 
245
                          &iter,
 
246
                          BOOL_COLUMN,
 
247
                          &active,
 
248
                          -1);
 
249
            
 
250
      gtk_tree_store_set (GTK_TREE_STORE (model),
 
251
                          &iter,
 
252
                          BOOL_COLUMN,
 
253
                          !active,
 
254
                          -1);
 
255
    }
 
256
  else
 
257
    g_warning ("don't know how to actually toggle value for model type %s",
 
258
               g_type_name (G_TYPE_FROM_INSTANCE (model)));
 
259
}
 
260
 
 
261
static void
 
262
edited_callback (GtkCellRendererText *renderer,
 
263
                 const gchar   *path_string,
 
264
                 const gchar   *new_text,
 
265
                 GtkTreeView  *tree_view)
 
266
{
 
267
  GtkTreeModel *model = NULL;
 
268
  GtkTreeModelSort *sort_model = NULL;
 
269
  GtkTreePath *path;
 
270
  GtkTreeIter iter;
 
271
  guint value = atoi (new_text);
 
272
  
 
273
  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
274
 
 
275
  model = gtk_tree_view_get_model (tree_view);
 
276
  
 
277
  if (GTK_IS_TREE_MODEL_SORT (model))
 
278
    {
 
279
      sort_model = GTK_TREE_MODEL_SORT (model);
 
280
      model = gtk_tree_model_sort_get_model (sort_model);
 
281
    }
 
282
 
 
283
  if (model == NULL)
 
284
    return;
 
285
 
 
286
  if (sort_model)
 
287
    {
 
288
      g_warning ("FIXME implement conversion from TreeModelSort iter to child model iter");
 
289
      return;
 
290
    }
 
291
      
 
292
  path = gtk_tree_path_new_from_string (path_string);
 
293
  if (!gtk_tree_model_get_iter (model,
 
294
                                &iter, path))
 
295
    {
 
296
      g_warning ("%s: bad path?", G_STRLOC);
 
297
      return;
 
298
    }
 
299
  gtk_tree_path_free (path);
 
300
 
 
301
  if (GTK_IS_LIST_STORE (model))
 
302
    {
 
303
      gtk_list_store_set (GTK_LIST_STORE (model),
 
304
                          &iter,
 
305
                          4,
 
306
                          value,
 
307
                          -1);
 
308
    }
 
309
  else if (GTK_IS_TREE_STORE (model))
 
310
    {
 
311
      gtk_tree_store_set (GTK_TREE_STORE (model),
 
312
                          &iter,
 
313
                          4,
 
314
                          value,
 
315
                          -1);
 
316
    }
 
317
  else
 
318
    g_warning ("don't know how to actually toggle value for model type %s",
 
319
               g_type_name (G_TYPE_FROM_INSTANCE (model)));
 
320
}
 
321
 
 
322
static ColumnsType current_column_type = COLUMNS_LOTS;
 
323
 
 
324
static void
 
325
set_columns_type (GtkTreeView *tree_view, ColumnsType type)
 
326
{
 
327
  GtkTreeViewColumn *col;
 
328
  GtkCellRenderer *rend;
 
329
  GdkPixbuf *pixbuf;
 
330
  GtkWidget *image;
 
331
  GtkObject *adjustment;
 
332
    
 
333
  current_column_type = type;
 
334
  
 
335
  col = gtk_tree_view_get_column (tree_view, 0);
 
336
  while (col)
 
337
    {
 
338
      gtk_tree_view_remove_column (tree_view, col);
 
339
 
 
340
      col = gtk_tree_view_get_column (tree_view, 0);
 
341
    }
 
342
 
 
343
  gtk_tree_view_set_rules_hint (tree_view, FALSE);
 
344
  
 
345
  switch (type)
 
346
    {
 
347
    case COLUMNS_NONE:
 
348
      break;
 
349
 
 
350
    case COLUMNS_LOTS:
 
351
      /* with lots of columns we need to turn on rules */
 
352
      gtk_tree_view_set_rules_hint (tree_view, TRUE);
 
353
      
 
354
      rend = gtk_cell_renderer_text_new ();
 
355
      
 
356
      col = gtk_tree_view_column_new_with_attributes ("Column 1",
 
357
                                                      rend,
 
358
                                                      "text", 1,
 
359
                                                      NULL);
 
360
      setup_column (col);
 
361
      
 
362
      gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
 
363
      
 
364
      col = gtk_tree_view_column_new();
 
365
      gtk_tree_view_column_set_title (col, "Column 2");
 
366
      
 
367
      rend = gtk_cell_renderer_pixbuf_new ();
 
368
      gtk_tree_view_column_pack_start (col, rend, FALSE);
 
369
      gtk_tree_view_column_add_attribute (col, rend, "pixbuf", 2);
 
370
      rend = gtk_cell_renderer_text_new ();
 
371
      gtk_tree_view_column_pack_start (col, rend, TRUE);
 
372
      gtk_tree_view_column_add_attribute (col, rend, "text", 0);
 
373
 
 
374
      setup_column (col);
 
375
      
 
376
      
 
377
      gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
 
378
      gtk_tree_view_set_expander_column (tree_view, col);
 
379
      
 
380
      rend = gtk_cell_renderer_toggle_new ();
 
381
 
 
382
      g_signal_connect (rend, "toggled",
 
383
                        G_CALLBACK (toggled_callback), tree_view);
 
384
      
 
385
      col = gtk_tree_view_column_new_with_attributes ("Column 3",
 
386
                                                      rend,
 
387
                                                      "active", BOOL_COLUMN,
 
388
                                                      NULL);
 
389
 
 
390
      setup_column (col);
 
391
      
 
392
      gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
 
393
 
 
394
      pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
 
395
 
 
396
      image = gtk_image_new_from_pixbuf (pixbuf);
 
397
 
 
398
      g_object_unref (pixbuf);
 
399
      
 
400
      gtk_widget_show (image);
 
401
      
 
402
      gtk_tree_view_column_set_widget (col, image);
 
403
      
 
404
      rend = gtk_cell_renderer_toggle_new ();
 
405
 
 
406
      /* you could also set this per-row by tying it to a column
 
407
       * in the model of course.
 
408
       */
 
409
      g_object_set (rend, "radio", TRUE, NULL);
 
410
      
 
411
      g_signal_connect (rend, "toggled",
 
412
                        G_CALLBACK (toggled_callback), tree_view);
 
413
      
 
414
      col = gtk_tree_view_column_new_with_attributes ("Column 4",
 
415
                                                      rend,
 
416
                                                      "active", BOOL_COLUMN,
 
417
                                                      NULL);
 
418
 
 
419
      setup_column (col);
 
420
      
 
421
      gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
 
422
 
 
423
      rend = gtk_cell_renderer_spin_new ();
 
424
 
 
425
      adjustment = gtk_adjustment_new (0, 0, 10000, 100, 100, 100);
 
426
      g_object_set (rend, "editable", TRUE, NULL);
 
427
      g_object_set (rend, "adjustment", adjustment, NULL);
 
428
 
 
429
      g_signal_connect (rend, "edited",
 
430
                        G_CALLBACK (edited_callback), tree_view);
 
431
 
 
432
      col = gtk_tree_view_column_new_with_attributes ("Column 5",
 
433
                                                      rend,
 
434
                                                      "text", 4,
 
435
                                                      NULL);
 
436
 
 
437
      setup_column (col);
 
438
      
 
439
      gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
 
440
#if 0
 
441
      
 
442
      rend = gtk_cell_renderer_text_new ();
 
443
      
 
444
      col = gtk_tree_view_column_new_with_attributes ("Column 6",
 
445
                                                      rend,
 
446
                                                      "text", 4,
 
447
                                                      NULL);
 
448
 
 
449
      setup_column (col);
 
450
      
 
451
      gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
 
452
      
 
453
      rend = gtk_cell_renderer_text_new ();
 
454
      
 
455
      col = gtk_tree_view_column_new_with_attributes ("Column 7",
 
456
                                                      rend,
 
457
                                                      "text", 5,
 
458
                                                      NULL);
 
459
 
 
460
      setup_column (col);
 
461
      
 
462
      gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
 
463
      
 
464
      rend = gtk_cell_renderer_text_new ();
 
465
      
 
466
      col = gtk_tree_view_column_new_with_attributes ("Column 8",
 
467
                                                      rend,
 
468
                                                      "text", 6,
 
469
                                                      NULL);
 
470
 
 
471
      setup_column (col);
 
472
      
 
473
      gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
 
474
      
 
475
      rend = gtk_cell_renderer_text_new ();
 
476
      
 
477
      col = gtk_tree_view_column_new_with_attributes ("Column 9",
 
478
                                                      rend,
 
479
                                                      "text", 7,
 
480
                                                      NULL);
 
481
 
 
482
      setup_column (col);
 
483
      
 
484
      gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
 
485
      
 
486
      rend = gtk_cell_renderer_text_new ();
 
487
      
 
488
      col = gtk_tree_view_column_new_with_attributes ("Column 10",
 
489
                                                      rend,
 
490
                                                      "text", 8,
 
491
                                                      NULL);
 
492
 
 
493
      setup_column (col);
 
494
      
 
495
      gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
 
496
      
 
497
#endif
 
498
      
 
499
      /* FALL THRU */
 
500
      
 
501
    case COLUMNS_ONE:
 
502
      rend = gtk_cell_renderer_text_new ();
 
503
      
 
504
      col = gtk_tree_view_column_new_with_attributes ("Column 0",
 
505
                                                      rend,
 
506
                                                      "text", 0,
 
507
                                                      NULL);
 
508
 
 
509
      setup_column (col);
 
510
      
 
511
      gtk_tree_view_insert_column (GTK_TREE_VIEW (tree_view), col, 0);
 
512
    default:
 
513
      break;
 
514
    }
 
515
}
 
516
 
 
517
static ColumnsType
 
518
get_columns_type (void)
 
519
{
 
520
  return current_column_type;
 
521
}
 
522
 
 
523
static GdkPixbuf *our_pixbuf;
 
524
  
 
525
typedef enum
 
526
{
 
527
  /*   MODEL_TYPES, */
 
528
  MODEL_TREE,
 
529
  MODEL_LIST,
 
530
  MODEL_SORTED_TREE,
 
531
  MODEL_SORTED_LIST,
 
532
  MODEL_EMPTY_LIST,
 
533
  MODEL_EMPTY_TREE,
 
534
  MODEL_NULL,
 
535
  MODEL_LAST
 
536
} ModelType;
 
537
 
 
538
/* FIXME add a custom model to test */
 
539
static GtkTreeModel *models[MODEL_LAST];
 
540
static const char *model_names[MODEL_LAST] = {
 
541
  "GtkTreeStore",
 
542
  "GtkListStore",
 
543
  "GtkTreeModelSort wrapping GtkTreeStore",
 
544
  "GtkTreeModelSort wrapping GtkListStore",
 
545
  "Empty GtkListStore",
 
546
  "Empty GtkTreeStore",
 
547
  "NULL (no model)"
 
548
};
 
549
 
 
550
static GtkTreeModel*
 
551
create_list_model (void)
 
552
{
 
553
  GtkListStore *store;
 
554
  GtkTreeIter iter;
 
555
  gint i;
 
556
  GType *t;
 
557
 
 
558
  t = get_model_types ();
 
559
  
 
560
  store = gtk_list_store_new (N_COLUMNS,
 
561
                              t[0], t[1], t[2],
 
562
                              t[3], t[4], t[5],
 
563
                              t[6], t[7], t[8]);
 
564
 
 
565
  i = 0;
 
566
  while (i < 200)
 
567
    {
 
568
      char *msg;
 
569
      
 
570
      gtk_list_store_append (store, &iter);
 
571
 
 
572
      msg = g_strdup_printf ("%d", i);
 
573
      
 
574
      gtk_list_store_set (store, &iter, 0, msg, 1, "Foo! Foo! Foo!",
 
575
                          2, our_pixbuf,
 
576
                          3, 7.0, 4, (guint) 9000,
 
577
                          5, 'f', 6, 'g',
 
578
                          7, TRUE, 8, 23245454,
 
579
                          -1);
 
580
 
 
581
      g_free (msg);
 
582
      
 
583
      ++i;
 
584
    }
 
585
 
 
586
  return GTK_TREE_MODEL (store);
 
587
}
 
588
 
 
589
static void
 
590
typesystem_recurse (GType        type,
 
591
                    GtkTreeIter *parent_iter,
 
592
                    GtkTreeStore *store)
 
593
{
 
594
  GType* children;
 
595
  guint n_children = 0;
 
596
  gint i;
 
597
  GtkTreeIter iter;
 
598
  gchar *str;
 
599
  
 
600
  gtk_tree_store_append (store, &iter, parent_iter);
 
601
 
 
602
  str = g_strdup_printf ("%ld", (glong)type);
 
603
  gtk_tree_store_set (store, &iter, 0, str, 1, g_type_name (type),
 
604
                      2, our_pixbuf,
 
605
                      3, 7.0, 4, (guint) 9000,
 
606
                      5, 'f', 6, 'g',
 
607
                      7, TRUE, 8, 23245454,
 
608
                      -1);
 
609
  g_free (str);
 
610
  
 
611
  children = g_type_children (type, &n_children);
 
612
 
 
613
  i = 0;
 
614
  while (i < n_children)
 
615
    {
 
616
      typesystem_recurse (children[i], &iter, store);
 
617
 
 
618
      ++i;
 
619
    }
 
620
  
 
621
  g_free (children);
 
622
}
 
623
 
 
624
static GtkTreeModel*
 
625
create_tree_model (void)
 
626
{
 
627
  GtkTreeStore *store;
 
628
  gint i;
 
629
  GType *t;
 
630
  volatile GType dummy; /* G_GNUC_CONST makes the optimizer remove
 
631
                         * get_type calls if you don't do something
 
632
                         * like this
 
633
                         */
 
634
  
 
635
  /* Make the tree more interesting */
 
636
  dummy = gtk_scrolled_window_get_type ();
 
637
  dummy = gtk_label_get_type ();
 
638
  dummy = gtk_hscrollbar_get_type ();
 
639
  dummy = gtk_vscrollbar_get_type ();
 
640
  dummy = pango_layout_get_type ();
 
641
 
 
642
  t = get_model_types ();
 
643
  
 
644
  store = gtk_tree_store_new (N_COLUMNS,
 
645
                              t[0], t[1], t[2],
 
646
                              t[3], t[4], t[5],
 
647
                              t[6], t[7], t[8]);
 
648
 
 
649
  i = 0;
 
650
  while (i < G_TYPE_FUNDAMENTAL_MAX)
 
651
    {
 
652
      typesystem_recurse (i, NULL, store);
 
653
      
 
654
      ++i;
 
655
    }
 
656
 
 
657
  return GTK_TREE_MODEL (store);
 
658
}
 
659
 
 
660
static void
 
661
model_selected (GtkOptionMenu *om, gpointer data)
 
662
{
 
663
  GtkTreeView *tree_view = GTK_TREE_VIEW (data);
 
664
  gint hist;
 
665
 
 
666
  hist = gtk_option_menu_get_history (om);
 
667
 
 
668
  if (models[hist] != gtk_tree_view_get_model (tree_view))
 
669
    {
 
670
      gtk_tree_view_set_model (tree_view, models[hist]);
 
671
    }
 
672
}
 
673
 
 
674
static void
 
675
columns_selected (GtkOptionMenu *om, gpointer data)
 
676
{
 
677
  GtkTreeView *tree_view = GTK_TREE_VIEW (data);
 
678
  gint hist;
 
679
 
 
680
  hist = gtk_option_menu_get_history (om);
 
681
 
 
682
  if (hist != get_columns_type ())
 
683
    {
 
684
      set_columns_type (tree_view, hist);
 
685
    }
 
686
}
 
687
 
 
688
 
 
689
enum
 
690
{
 
691
  TARGET_GTK_TREE_MODEL_ROW
 
692
};
 
693
 
 
694
static GtkTargetEntry row_targets[] = {
 
695
  { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_APP,
 
696
    TARGET_GTK_TREE_MODEL_ROW }
 
697
};
 
698
 
 
699
int
 
700
main (int    argc,
 
701
      char **argv)
 
702
{
 
703
  GtkWidget *window;
 
704
  GtkWidget *sw;
 
705
  GtkWidget *tv;
 
706
  GtkWidget *table;
 
707
  GtkWidget *om;
 
708
  GtkWidget *menu;
 
709
  GtkTreeModel *model;
 
710
  gint i;
 
711
  
 
712
  gtk_init (&argc, &argv);
 
713
 
 
714
  our_pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) book_closed_xpm);  
 
715
  
 
716
#if 0
 
717
  models[MODEL_TYPES] = GTK_TREE_MODEL (gtk_tree_model_types_new ());
 
718
#endif
 
719
  models[MODEL_LIST] = create_list_model ();
 
720
  models[MODEL_TREE] = create_tree_model ();
 
721
 
 
722
  model = create_list_model ();
 
723
  models[MODEL_SORTED_LIST] = gtk_tree_model_sort_new_with_model (model);
 
724
  g_object_unref (model);
 
725
 
 
726
  model = create_tree_model ();
 
727
  models[MODEL_SORTED_TREE] = gtk_tree_model_sort_new_with_model (model);
 
728
  g_object_unref (model);
 
729
 
 
730
  models[MODEL_EMPTY_LIST] = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_INT));
 
731
  models[MODEL_EMPTY_TREE] = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT));
 
732
  
 
733
  models[MODEL_NULL] = NULL;
 
734
 
 
735
  run_automated_tests ();
 
736
  
 
737
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
738
  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
 
739
  gtk_window_set_default_size (GTK_WINDOW (window), 430, 400);
 
740
 
 
741
  table = gtk_table_new (3, 1, FALSE);
 
742
 
 
743
  gtk_container_add (GTK_CONTAINER (window), table);
 
744
 
 
745
  tv = gtk_tree_view_new_with_model (models[0]);
 
746
  
 
747
  gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (tv),
 
748
                                          GDK_BUTTON1_MASK,
 
749
                                          row_targets,
 
750
                                          G_N_ELEMENTS (row_targets),
 
751
                                          GDK_ACTION_MOVE | GDK_ACTION_COPY);
 
752
 
 
753
  gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (tv),
 
754
                                        row_targets,
 
755
                                        G_N_ELEMENTS (row_targets),
 
756
                                        GDK_ACTION_MOVE | GDK_ACTION_COPY);
 
757
  
 
758
  /* Model menu */
 
759
 
 
760
  menu = gtk_menu_new ();
 
761
  
 
762
  i = 0;
 
763
  while (i < MODEL_LAST)
 
764
    {
 
765
      GtkWidget *mi;
 
766
      const char *name;
 
767
 
 
768
      name = model_names[i];
 
769
      
 
770
      mi = gtk_menu_item_new_with_label (name);
 
771
 
 
772
      gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
 
773
 
 
774
#if 0
 
775
      window = create_prop_editor (G_OBJECT (models[i]));
 
776
 
 
777
      gtk_window_set_title (GTK_WINDOW (window),                            
 
778
                            name);
 
779
#endif
 
780
 
 
781
      ++i;
 
782
    }
 
783
  gtk_widget_show_all (menu);
 
784
  
 
785
  om = gtk_option_menu_new ();
 
786
  gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
 
787
  
 
788
  gtk_table_attach (GTK_TABLE (table), om,
 
789
                    0, 1, 0, 1,
 
790
                    0, 0, 
 
791
                    0, 0);
 
792
 
 
793
  g_signal_connect (om,
 
794
                    "changed",
 
795
                    G_CALLBACK (model_selected),
 
796
                    tv);
 
797
  
 
798
  /* Columns menu */
 
799
 
 
800
  menu = gtk_menu_new ();
 
801
  
 
802
  i = 0;
 
803
  while (i < COLUMNS_LAST)
 
804
    {
 
805
      GtkWidget *mi;
 
806
      const char *name;
 
807
 
 
808
      name = column_type_names[i];
 
809
      
 
810
      mi = gtk_menu_item_new_with_label (name);
 
811
 
 
812
      gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
 
813
 
 
814
      ++i;
 
815
    }
 
816
  gtk_widget_show_all (menu);
 
817
  
 
818
  om = gtk_option_menu_new ();
 
819
  gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
 
820
  
 
821
  gtk_table_attach (GTK_TABLE (table), om,
 
822
                    0, 1, 1, 2,
 
823
                    0, 0, 
 
824
                    0, 0);
 
825
 
 
826
  set_columns_type (GTK_TREE_VIEW (tv), COLUMNS_LOTS);
 
827
  gtk_option_menu_set_history (GTK_OPTION_MENU (om), COLUMNS_LOTS);
 
828
  
 
829
  g_signal_connect (om,
 
830
                    "changed",
 
831
                    G_CALLBACK (columns_selected),
 
832
                    tv);
 
833
  
 
834
  sw = gtk_scrolled_window_new (NULL, NULL);
 
835
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
 
836
                                  GTK_POLICY_AUTOMATIC,
 
837
                                  GTK_POLICY_AUTOMATIC);
 
838
  
 
839
  gtk_table_attach (GTK_TABLE (table), sw,
 
840
                    0, 1, 2, 3,
 
841
                    GTK_EXPAND | GTK_FILL,
 
842
                    GTK_EXPAND | GTK_FILL,
 
843
                    0, 0);
 
844
  
 
845
  gtk_container_add (GTK_CONTAINER (sw), tv);
 
846
  
 
847
  gtk_widget_show_all (window);
 
848
  
 
849
  gtk_main ();
 
850
 
 
851
  return 0;
 
852
}
 
853
 
 
854
/*
 
855
 * GtkTreeModelTypes
 
856
 */
 
857
 
 
858
static void         gtk_tree_model_types_init                 (GtkTreeModelTypes      *model_types);
 
859
static void         gtk_tree_model_types_tree_model_init      (GtkTreeModelIface   *iface);
 
860
static gint         gtk_real_model_types_get_n_columns   (GtkTreeModel        *tree_model);
 
861
static GType        gtk_real_model_types_get_column_type (GtkTreeModel        *tree_model,
 
862
                                                           gint                 index);
 
863
static GtkTreePath *gtk_real_model_types_get_path        (GtkTreeModel        *tree_model,
 
864
                                                           GtkTreeIter         *iter);
 
865
static void         gtk_real_model_types_get_value       (GtkTreeModel        *tree_model,
 
866
                                                           GtkTreeIter         *iter,
 
867
                                                           gint                 column,
 
868
                                                           GValue              *value);
 
869
static gboolean     gtk_real_model_types_iter_next       (GtkTreeModel        *tree_model,
 
870
                                                           GtkTreeIter         *iter);
 
871
static gboolean     gtk_real_model_types_iter_children   (GtkTreeModel        *tree_model,
 
872
                                                           GtkTreeIter         *iter,
 
873
                                                           GtkTreeIter         *parent);
 
874
static gboolean     gtk_real_model_types_iter_has_child  (GtkTreeModel        *tree_model,
 
875
                                                           GtkTreeIter         *iter);
 
876
static gint         gtk_real_model_types_iter_n_children (GtkTreeModel        *tree_model,
 
877
                                                           GtkTreeIter         *iter);
 
878
static gboolean     gtk_real_model_types_iter_nth_child  (GtkTreeModel        *tree_model,
 
879
                                                           GtkTreeIter         *iter,
 
880
                                                           GtkTreeIter         *parent,
 
881
                                                           gint                 n);
 
882
static gboolean     gtk_real_model_types_iter_parent     (GtkTreeModel        *tree_model,
 
883
                                                           GtkTreeIter         *iter,
 
884
                                                           GtkTreeIter         *child);
 
885
 
 
886
 
 
887
GType
 
888
gtk_tree_model_types_get_type (void)
 
889
{
 
890
  static GType model_types_type = 0;
 
891
 
 
892
  if (!model_types_type)
 
893
    {
 
894
      static const GTypeInfo model_types_info =
 
895
      {
 
896
        sizeof (GtkTreeModelTypesClass),
 
897
        NULL,           /* base_init */
 
898
        NULL,           /* base_finalize */
 
899
        NULL,           /* class_init */
 
900
        NULL,           /* class_finalize */
 
901
        NULL,           /* class_data */
 
902
        sizeof (GtkTreeModelTypes),
 
903
        0,
 
904
        (GInstanceInitFunc) gtk_tree_model_types_init
 
905
      };
 
906
 
 
907
      static const GInterfaceInfo tree_model_info =
 
908
      {
 
909
        (GInterfaceInitFunc) gtk_tree_model_types_tree_model_init,
 
910
        NULL,
 
911
        NULL
 
912
      };
 
913
 
 
914
      model_types_type = g_type_register_static (G_TYPE_OBJECT,
 
915
                                                 "GtkTreeModelTypes",
 
916
                                                 &model_types_info, 0);
 
917
      g_type_add_interface_static (model_types_type,
 
918
                                   GTK_TYPE_TREE_MODEL,
 
919
                                   &tree_model_info);
 
920
    }
 
921
 
 
922
  return model_types_type;
 
923
}
 
924
 
 
925
GtkTreeModelTypes *
 
926
gtk_tree_model_types_new (void)
 
927
{
 
928
  GtkTreeModelTypes *retval;
 
929
 
 
930
  retval = g_object_new (GTK_TYPE_MODEL_TYPES, NULL);
 
931
 
 
932
  return retval;
 
933
}
 
934
 
 
935
static void
 
936
gtk_tree_model_types_tree_model_init (GtkTreeModelIface *iface)
 
937
{
 
938
  iface->get_n_columns = gtk_real_model_types_get_n_columns;
 
939
  iface->get_column_type = gtk_real_model_types_get_column_type;
 
940
  iface->get_path = gtk_real_model_types_get_path;
 
941
  iface->get_value = gtk_real_model_types_get_value;
 
942
  iface->iter_next = gtk_real_model_types_iter_next;
 
943
  iface->iter_children = gtk_real_model_types_iter_children;
 
944
  iface->iter_has_child = gtk_real_model_types_iter_has_child;
 
945
  iface->iter_n_children = gtk_real_model_types_iter_n_children;
 
946
  iface->iter_nth_child = gtk_real_model_types_iter_nth_child;
 
947
  iface->iter_parent = gtk_real_model_types_iter_parent;
 
948
}
 
949
 
 
950
static void
 
951
gtk_tree_model_types_init (GtkTreeModelTypes *model_types)
 
952
{
 
953
  model_types->stamp = g_random_int ();
 
954
}
 
955
 
 
956
static GType column_types[] = {
 
957
  G_TYPE_STRING, /* GType */
 
958
  G_TYPE_STRING  /* type name */
 
959
};
 
960
  
 
961
static gint
 
962
gtk_real_model_types_get_n_columns (GtkTreeModel *tree_model)
 
963
{
 
964
  return G_N_ELEMENTS (column_types);
 
965
}
 
966
 
 
967
static GType
 
968
gtk_real_model_types_get_column_type (GtkTreeModel *tree_model,
 
969
                                      gint          index)
 
970
{
 
971
  g_return_val_if_fail (index < G_N_ELEMENTS (column_types), G_TYPE_INVALID);
 
972
  
 
973
  return column_types[index];
 
974
}
 
975
 
 
976
#if 0
 
977
/* Use default implementation of this */
 
978
static gboolean
 
979
gtk_real_model_types_get_iter (GtkTreeModel *tree_model,
 
980
                               GtkTreeIter  *iter,
 
981
                               GtkTreePath  *path)
 
982
{
 
983
  
 
984
}
 
985
#endif
 
986
 
 
987
/* The toplevel nodes of the tree are the reserved types, G_TYPE_NONE through
 
988
 * G_TYPE_RESERVED_FUNDAMENTAL.
 
989
 */
 
990
 
 
991
static GtkTreePath *
 
992
gtk_real_model_types_get_path (GtkTreeModel *tree_model,
 
993
                               GtkTreeIter  *iter)
 
994
{
 
995
  GtkTreePath *retval;
 
996
  GType type;
 
997
  GType parent;
 
998
  
 
999
  g_return_val_if_fail (GTK_IS_TREE_MODEL_TYPES (tree_model), NULL);
 
1000
  g_return_val_if_fail (iter != NULL, NULL);
 
1001
 
 
1002
  type = GPOINTER_TO_INT (iter->user_data);
 
1003
  
 
1004
  retval = gtk_tree_path_new ();
 
1005
  
 
1006
  parent = g_type_parent (type);
 
1007
  while (parent != G_TYPE_INVALID)
 
1008
    {
 
1009
      GType* children = g_type_children (parent, NULL);
 
1010
      gint i = 0;
 
1011
 
 
1012
      if (!children || children[0] == G_TYPE_INVALID)
 
1013
        {
 
1014
          g_warning ("bad iterator?");
 
1015
          return NULL;
 
1016
        }
 
1017
      
 
1018
      while (children[i] != type)
 
1019
        ++i;
 
1020
 
 
1021
      gtk_tree_path_prepend_index (retval, i);
 
1022
 
 
1023
      g_free (children);
 
1024
      
 
1025
      type = parent;
 
1026
      parent = g_type_parent (parent);
 
1027
    }
 
1028
 
 
1029
  /* The fundamental type itself is the index on the toplevel */
 
1030
  gtk_tree_path_prepend_index (retval, type);
 
1031
 
 
1032
  return retval;
 
1033
}
 
1034
 
 
1035
static void
 
1036
gtk_real_model_types_get_value (GtkTreeModel *tree_model,
 
1037
                                GtkTreeIter  *iter,
 
1038
                                gint          column,
 
1039
                                GValue       *value)
 
1040
{
 
1041
  GType type;
 
1042
 
 
1043
  type = GPOINTER_TO_INT (iter->user_data);
 
1044
 
 
1045
  switch (column)
 
1046
    {
 
1047
    case 0:
 
1048
      {
 
1049
        gchar *str;
 
1050
        
 
1051
        g_value_init (value, G_TYPE_STRING);
 
1052
 
 
1053
        str = g_strdup_printf ("%ld", type);
 
1054
        g_value_set_string (value, str);
 
1055
        g_free (str);
 
1056
      }
 
1057
      break;
 
1058
 
 
1059
    case 1:
 
1060
      g_value_init (value, G_TYPE_STRING);
 
1061
      g_value_set_string (value, g_type_name (type));
 
1062
      break;
 
1063
 
 
1064
    default:
 
1065
      g_warning ("Bad column %d requested", column);
 
1066
    }
 
1067
}
 
1068
 
 
1069
static gboolean
 
1070
gtk_real_model_types_iter_next (GtkTreeModel  *tree_model,
 
1071
                                GtkTreeIter   *iter)
 
1072
{
 
1073
  
 
1074
  GType parent;
 
1075
  GType type;
 
1076
 
 
1077
  type = GPOINTER_TO_INT (iter->user_data);
 
1078
 
 
1079
  parent = g_type_parent (type);
 
1080
  
 
1081
  if (parent == G_TYPE_INVALID)
 
1082
    {
 
1083
      /* find next _valid_ fundamental type */
 
1084
      do
 
1085
        type++;
 
1086
      while (!g_type_name (type) && type <= G_TYPE_FUNDAMENTAL_MAX);
 
1087
      if (type <= G_TYPE_FUNDAMENTAL_MAX)
 
1088
        {
 
1089
          /* found one */
 
1090
          iter->user_data = GINT_TO_POINTER (type);
 
1091
          return TRUE;
 
1092
        }
 
1093
      else
 
1094
        return FALSE;
 
1095
    }
 
1096
  else
 
1097
    {
 
1098
      GType* children = g_type_children (parent, NULL);
 
1099
      gint i = 0;
 
1100
 
 
1101
      g_assert (children != NULL);
 
1102
      
 
1103
      while (children[i] != type)
 
1104
        ++i;
 
1105
  
 
1106
      ++i;
 
1107
 
 
1108
      if (children[i] != G_TYPE_INVALID)
 
1109
        {
 
1110
          g_free (children);
 
1111
          iter->user_data = GINT_TO_POINTER (children[i]);
 
1112
          return TRUE;
 
1113
        }
 
1114
      else
 
1115
        {
 
1116
          g_free (children);
 
1117
          return FALSE;
 
1118
        }
 
1119
    }
 
1120
}
 
1121
 
 
1122
static gboolean
 
1123
gtk_real_model_types_iter_children (GtkTreeModel *tree_model,
 
1124
                                    GtkTreeIter  *iter,
 
1125
                                    GtkTreeIter  *parent)
 
1126
{
 
1127
  GType type;
 
1128
  GType* children;
 
1129
  
 
1130
  type = GPOINTER_TO_INT (parent->user_data);
 
1131
 
 
1132
  children = g_type_children (type, NULL);
 
1133
 
 
1134
  if (!children || children[0] == G_TYPE_INVALID)
 
1135
    {
 
1136
      g_free (children);
 
1137
      return FALSE;
 
1138
    }
 
1139
  else
 
1140
    {
 
1141
      iter->user_data = GINT_TO_POINTER (children[0]);
 
1142
      g_free (children);
 
1143
      return TRUE;
 
1144
    }
 
1145
}
 
1146
 
 
1147
static gboolean
 
1148
gtk_real_model_types_iter_has_child (GtkTreeModel *tree_model,
 
1149
                                     GtkTreeIter  *iter)
 
1150
{
 
1151
  GType type;
 
1152
  GType* children;
 
1153
  
 
1154
  type = GPOINTER_TO_INT (iter->user_data);
 
1155
  
 
1156
  children = g_type_children (type, NULL);
 
1157
 
 
1158
  if (!children || children[0] == G_TYPE_INVALID)
 
1159
    {
 
1160
      g_free (children);
 
1161
      return FALSE;
 
1162
    }
 
1163
  else
 
1164
    {
 
1165
      g_free (children);
 
1166
      return TRUE;
 
1167
    }
 
1168
}
 
1169
 
 
1170
static gint
 
1171
gtk_real_model_types_iter_n_children (GtkTreeModel *tree_model,
 
1172
                                      GtkTreeIter  *iter)
 
1173
{
 
1174
  if (iter == NULL)
 
1175
    {
 
1176
      return G_TYPE_FUNDAMENTAL_MAX;
 
1177
    }
 
1178
  else
 
1179
    {
 
1180
      GType type;
 
1181
      GType* children;
 
1182
      guint n_children = 0;
 
1183
 
 
1184
      type = GPOINTER_TO_INT (iter->user_data);
 
1185
      
 
1186
      children = g_type_children (type, &n_children);
 
1187
      
 
1188
      g_free (children);
 
1189
      
 
1190
      return n_children;
 
1191
    }
 
1192
}
 
1193
 
 
1194
static gboolean
 
1195
gtk_real_model_types_iter_nth_child (GtkTreeModel *tree_model,
 
1196
                                     GtkTreeIter  *iter,
 
1197
                                     GtkTreeIter  *parent,
 
1198
                                     gint          n)
 
1199
{  
 
1200
  if (parent == NULL)
 
1201
    {
 
1202
      /* fundamental type */
 
1203
      if (n < G_TYPE_FUNDAMENTAL_MAX)
 
1204
        {
 
1205
          iter->user_data = GINT_TO_POINTER (n);
 
1206
          return TRUE;
 
1207
        }
 
1208
      else
 
1209
        return FALSE;
 
1210
    }
 
1211
  else
 
1212
    {
 
1213
      GType type = GPOINTER_TO_INT (parent->user_data);      
 
1214
      guint n_children = 0;
 
1215
      GType* children = g_type_children (type, &n_children);
 
1216
 
 
1217
      if (n_children == 0)
 
1218
        {
 
1219
          g_free (children);
 
1220
          return FALSE;
 
1221
        }
 
1222
      else if (n >= n_children)
 
1223
        {
 
1224
          g_free (children);
 
1225
          return FALSE;
 
1226
        }
 
1227
      else
 
1228
        {
 
1229
          iter->user_data = GINT_TO_POINTER (children[n]);
 
1230
          g_free (children);
 
1231
 
 
1232
          return TRUE;
 
1233
        }
 
1234
    }
 
1235
}
 
1236
 
 
1237
static gboolean
 
1238
gtk_real_model_types_iter_parent (GtkTreeModel *tree_model,
 
1239
                                  GtkTreeIter  *iter,
 
1240
                                  GtkTreeIter  *child)
 
1241
{
 
1242
  GType type;
 
1243
  GType parent;
 
1244
  
 
1245
  type = GPOINTER_TO_INT (child->user_data);
 
1246
  
 
1247
  parent = g_type_parent (type);
 
1248
  
 
1249
  if (parent == G_TYPE_INVALID)
 
1250
    {
 
1251
      if (type > G_TYPE_FUNDAMENTAL_MAX)
 
1252
        g_warning ("no parent for %ld %s\n", type, g_type_name (type));
 
1253
      return FALSE;
 
1254
    }
 
1255
  else
 
1256
    {
 
1257
      iter->user_data = GINT_TO_POINTER (parent);
 
1258
      
 
1259
      return TRUE;
 
1260
    }
 
1261
}
 
1262
 
 
1263
/*
 
1264
 * Automated testing
 
1265
 */
 
1266
 
 
1267
static void
 
1268
treestore_torture_recurse (GtkTreeStore *store,
 
1269
                           GtkTreeIter  *root,
 
1270
                           gint          depth)
 
1271
{
 
1272
  GtkTreeModel *model;
 
1273
  gint i;
 
1274
  GtkTreeIter iter;  
 
1275
  
 
1276
  model = GTK_TREE_MODEL (store);    
 
1277
 
 
1278
  if (depth > 2)
 
1279
    return;
 
1280
 
 
1281
  ++depth;
 
1282
 
 
1283
  gtk_tree_store_append (store, &iter, root);
 
1284
  
 
1285
  gtk_tree_model_iter_children (model, &iter, root);
 
1286
  
 
1287
  i = 0;
 
1288
  while (i < 100)
 
1289
    {
 
1290
      gtk_tree_store_append (store, &iter, root);
 
1291
      ++i;
 
1292
    }
 
1293
 
 
1294
  while (gtk_tree_model_iter_children (model, &iter, root))
 
1295
    gtk_tree_store_remove (store, &iter);
 
1296
 
 
1297
  gtk_tree_store_append (store, &iter, root);
 
1298
 
 
1299
  /* inserts before last node in tree */
 
1300
  i = 0;
 
1301
  while (i < 100)
 
1302
    {
 
1303
      gtk_tree_store_insert_before (store, &iter, root, &iter);
 
1304
      ++i;
 
1305
    }
 
1306
 
 
1307
  /* inserts after the node before the last node */
 
1308
  i = 0;
 
1309
  while (i < 100)
 
1310
    {
 
1311
      gtk_tree_store_insert_after (store, &iter, root, &iter);
 
1312
      ++i;
 
1313
    }
 
1314
 
 
1315
  /* inserts after the last node */
 
1316
  gtk_tree_store_append (store, &iter, root);
 
1317
    
 
1318
  i = 0;
 
1319
  while (i < 100)
 
1320
    {
 
1321
      gtk_tree_store_insert_after (store, &iter, root, &iter);
 
1322
      ++i;
 
1323
    }
 
1324
 
 
1325
  /* remove everything again */
 
1326
  while (gtk_tree_model_iter_children (model, &iter, root))
 
1327
    gtk_tree_store_remove (store, &iter);
 
1328
 
 
1329
 
 
1330
    /* Prepends */
 
1331
  gtk_tree_store_prepend (store, &iter, root);
 
1332
    
 
1333
  i = 0;
 
1334
  while (i < 100)
 
1335
    {
 
1336
      gtk_tree_store_prepend (store, &iter, root);
 
1337
      ++i;
 
1338
    }
 
1339
 
 
1340
  /* remove everything again */
 
1341
  while (gtk_tree_model_iter_children (model, &iter, root))
 
1342
    gtk_tree_store_remove (store, &iter);
 
1343
 
 
1344
  gtk_tree_store_append (store, &iter, root);
 
1345
  gtk_tree_store_append (store, &iter, root);
 
1346
  gtk_tree_store_append (store, &iter, root);
 
1347
  gtk_tree_store_append (store, &iter, root);
 
1348
 
 
1349
  while (gtk_tree_model_iter_children (model, &iter, root))
 
1350
    {
 
1351
      treestore_torture_recurse (store, &iter, depth);
 
1352
      gtk_tree_store_remove (store, &iter);
 
1353
    }
 
1354
}
 
1355
 
 
1356
static void
 
1357
run_automated_tests (void)
 
1358
{
 
1359
  g_print ("Running automated tests...\n");
 
1360
  
 
1361
  /* FIXME TreePath basic verification */
 
1362
 
 
1363
  /* FIXME generic consistency checks on the models */
 
1364
 
 
1365
  {
 
1366
    /* Make sure list store mutations don't crash anything */
 
1367
    GtkListStore *store;
 
1368
    GtkTreeModel *model;
 
1369
    gint i;
 
1370
    GtkTreeIter iter;
 
1371
    
 
1372
    store = gtk_list_store_new (1, G_TYPE_INT);
 
1373
 
 
1374
    model = GTK_TREE_MODEL (store);
 
1375
    
 
1376
    i = 0;
 
1377
    while (i < 100)
 
1378
      {
 
1379
        gtk_list_store_append (store, &iter);
 
1380
        ++i;
 
1381
      }
 
1382
 
 
1383
    while (gtk_tree_model_get_iter_first (model, &iter))
 
1384
      gtk_list_store_remove (store, &iter);
 
1385
 
 
1386
    gtk_list_store_append (store, &iter);
 
1387
 
 
1388
    /* inserts before last node in list */
 
1389
    i = 0;
 
1390
    while (i < 100)
 
1391
      {
 
1392
        gtk_list_store_insert_before (store, &iter, &iter);
 
1393
        ++i;
 
1394
      }
 
1395
 
 
1396
    /* inserts after the node before the last node */
 
1397
    i = 0;
 
1398
    while (i < 100)
 
1399
      {
 
1400
        gtk_list_store_insert_after (store, &iter, &iter);
 
1401
        ++i;
 
1402
      }
 
1403
 
 
1404
    /* inserts after the last node */
 
1405
    gtk_list_store_append (store, &iter);
 
1406
    
 
1407
    i = 0;
 
1408
    while (i < 100)
 
1409
      {
 
1410
        gtk_list_store_insert_after (store, &iter, &iter);
 
1411
        ++i;
 
1412
      }
 
1413
 
 
1414
    /* remove everything again */
 
1415
    while (gtk_tree_model_get_iter_first (model, &iter))
 
1416
      gtk_list_store_remove (store, &iter);
 
1417
 
 
1418
 
 
1419
    /* Prepends */
 
1420
    gtk_list_store_prepend (store, &iter);
 
1421
    
 
1422
    i = 0;
 
1423
    while (i < 100)
 
1424
      {
 
1425
        gtk_list_store_prepend (store, &iter);
 
1426
        ++i;
 
1427
      }
 
1428
 
 
1429
    /* remove everything again */
 
1430
    while (gtk_tree_model_get_iter_first (model, &iter))
 
1431
      gtk_list_store_remove (store, &iter);
 
1432
    
 
1433
    g_object_unref (store);
 
1434
  }
 
1435
 
 
1436
  {
 
1437
    /* Make sure tree store mutations don't crash anything */
 
1438
    GtkTreeStore *store;
 
1439
    GtkTreeIter root;
 
1440
 
 
1441
    store = gtk_tree_store_new (1, G_TYPE_INT);
 
1442
    gtk_tree_store_append (GTK_TREE_STORE (store), &root, NULL);
 
1443
    /* Remove test until it is rewritten to work */
 
1444
    /*    treestore_torture_recurse (store, &root, 0);*/
 
1445
    
 
1446
    g_object_unref (store);
 
1447
  }
 
1448
 
 
1449
  g_print ("Passed.\n");
 
1450
}