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

« back to all changes in this revision

Viewing changes to gtk/gtktreestore.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
/* gtktreestore.c
 
2
 * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Library 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
 * Library General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Library 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 <config.h>
 
21
#include <string.h>
 
22
#include <gobject/gvaluecollector.h>
 
23
#include "gtktreemodel.h"
 
24
#include "gtktreestore.h"
 
25
#include "gtktreedatalist.h"
 
26
#include "gtktreednd.h"
 
27
#include "gtkintl.h"
 
28
#include "gtkalias.h"
 
29
 
 
30
#define G_NODE(node) ((GNode *)node)
 
31
#define GTK_TREE_STORE_IS_SORTED(tree) (((GtkTreeStore*)(tree))->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
 
32
#define VALID_ITER(iter, tree_store) ((iter)!= NULL && (iter)->user_data != NULL && ((GtkTreeStore*)(tree_store))->stamp == (iter)->stamp)
 
33
 
 
34
static void         gtk_tree_store_tree_model_init (GtkTreeModelIface *iface);
 
35
static void         gtk_tree_store_drag_source_init(GtkTreeDragSourceIface *iface);
 
36
static void         gtk_tree_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
 
37
static void         gtk_tree_store_sortable_init   (GtkTreeSortableIface   *iface);
 
38
static void         gtk_tree_store_finalize        (GObject           *object);
 
39
static GtkTreeModelFlags gtk_tree_store_get_flags  (GtkTreeModel      *tree_model);
 
40
static gint         gtk_tree_store_get_n_columns   (GtkTreeModel      *tree_model);
 
41
static GType        gtk_tree_store_get_column_type (GtkTreeModel      *tree_model,
 
42
                                                    gint               index);
 
43
static gboolean     gtk_tree_store_get_iter        (GtkTreeModel      *tree_model,
 
44
                                                    GtkTreeIter       *iter,
 
45
                                                    GtkTreePath       *path);
 
46
static GtkTreePath *gtk_tree_store_get_path        (GtkTreeModel      *tree_model,
 
47
                                                    GtkTreeIter       *iter);
 
48
static void         gtk_tree_store_get_value       (GtkTreeModel      *tree_model,
 
49
                                                    GtkTreeIter       *iter,
 
50
                                                    gint               column,
 
51
                                                    GValue            *value);
 
52
static gboolean     gtk_tree_store_iter_next       (GtkTreeModel      *tree_model,
 
53
                                                    GtkTreeIter       *iter);
 
54
static gboolean     gtk_tree_store_iter_children   (GtkTreeModel      *tree_model,
 
55
                                                    GtkTreeIter       *iter,
 
56
                                                    GtkTreeIter       *parent);
 
57
static gboolean     gtk_tree_store_iter_has_child  (GtkTreeModel      *tree_model,
 
58
                                                    GtkTreeIter       *iter);
 
59
static gint         gtk_tree_store_iter_n_children (GtkTreeModel      *tree_model,
 
60
                                                    GtkTreeIter       *iter);
 
61
static gboolean     gtk_tree_store_iter_nth_child  (GtkTreeModel      *tree_model,
 
62
                                                    GtkTreeIter       *iter,
 
63
                                                    GtkTreeIter       *parent,
 
64
                                                    gint               n);
 
65
static gboolean     gtk_tree_store_iter_parent     (GtkTreeModel      *tree_model,
 
66
                                                    GtkTreeIter       *iter,
 
67
                                                    GtkTreeIter       *child);
 
68
 
 
69
 
 
70
static void gtk_tree_store_set_n_columns   (GtkTreeStore *tree_store,
 
71
                                            gint          n_columns);
 
72
static void gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
 
73
                                            gint          column,
 
74
                                            GType         type);
 
75
 
 
76
static void gtk_tree_store_increment_stamp (GtkTreeStore  *tree_store);
 
77
 
 
78
 
 
79
/* DND interfaces */
 
80
static gboolean real_gtk_tree_store_row_draggable   (GtkTreeDragSource *drag_source,
 
81
                                                   GtkTreePath       *path);
 
82
static gboolean gtk_tree_store_drag_data_delete   (GtkTreeDragSource *drag_source,
 
83
                                                   GtkTreePath       *path);
 
84
static gboolean gtk_tree_store_drag_data_get      (GtkTreeDragSource *drag_source,
 
85
                                                   GtkTreePath       *path,
 
86
                                                   GtkSelectionData  *selection_data);
 
87
static gboolean gtk_tree_store_drag_data_received (GtkTreeDragDest   *drag_dest,
 
88
                                                   GtkTreePath       *dest,
 
89
                                                   GtkSelectionData  *selection_data);
 
90
static gboolean gtk_tree_store_row_drop_possible  (GtkTreeDragDest   *drag_dest,
 
91
                                                   GtkTreePath       *dest_path,
 
92
                                                   GtkSelectionData  *selection_data);
 
93
 
 
94
/* Sortable Interfaces */
 
95
 
 
96
static void     gtk_tree_store_sort                    (GtkTreeStore           *tree_store);
 
97
static void     gtk_tree_store_sort_iter_changed       (GtkTreeStore           *tree_store,
 
98
                                                        GtkTreeIter            *iter,
 
99
                                                        gint                    column,
 
100
                                                        gboolean                emit_signal);
 
101
static gboolean gtk_tree_store_get_sort_column_id      (GtkTreeSortable        *sortable,
 
102
                                                        gint                   *sort_column_id,
 
103
                                                        GtkSortType            *order);
 
104
static void     gtk_tree_store_set_sort_column_id      (GtkTreeSortable        *sortable,
 
105
                                                        gint                    sort_column_id,
 
106
                                                        GtkSortType             order);
 
107
static void     gtk_tree_store_set_sort_func           (GtkTreeSortable        *sortable,
 
108
                                                        gint                    sort_column_id,
 
109
                                                        GtkTreeIterCompareFunc  func,
 
110
                                                        gpointer                data,
 
111
                                                        GtkDestroyNotify        destroy);
 
112
static void     gtk_tree_store_set_default_sort_func   (GtkTreeSortable        *sortable,
 
113
                                                        GtkTreeIterCompareFunc  func,
 
114
                                                        gpointer                data,
 
115
                                                        GtkDestroyNotify        destroy);
 
116
static gboolean gtk_tree_store_has_default_sort_func   (GtkTreeSortable        *sortable);
 
117
 
 
118
static void     validate_gnode                         (GNode *node);
 
119
 
 
120
static void     gtk_tree_store_move                    (GtkTreeStore           *tree_store,
 
121
                                                        GtkTreeIter            *iter,
 
122
                                                        GtkTreeIter            *position,
 
123
                                                        gboolean                before);
 
124
 
 
125
 
 
126
static inline void
 
127
validate_tree (GtkTreeStore *tree_store)
 
128
{
 
129
  if (gtk_debug_flags & GTK_DEBUG_TREE)
 
130
    {
 
131
      g_assert (G_NODE (tree_store->root)->parent == NULL);
 
132
 
 
133
      validate_gnode (G_NODE (tree_store->root));
 
134
    }
 
135
}
 
136
 
 
137
G_DEFINE_TYPE_WITH_CODE (GtkTreeStore, gtk_tree_store, G_TYPE_OBJECT,
 
138
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
 
139
                                                gtk_tree_store_tree_model_init)
 
140
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
 
141
                                                gtk_tree_store_drag_source_init)
 
142
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
 
143
                                                gtk_tree_store_drag_dest_init)
 
144
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
 
145
                                                gtk_tree_store_sortable_init))
 
146
 
 
147
static void
 
148
gtk_tree_store_class_init (GtkTreeStoreClass *class)
 
149
{
 
150
  GObjectClass *object_class;
 
151
 
 
152
  object_class = (GObjectClass *) class;
 
153
 
 
154
  object_class->finalize = gtk_tree_store_finalize;
 
155
}
 
156
 
 
157
static void
 
158
gtk_tree_store_tree_model_init (GtkTreeModelIface *iface)
 
159
{
 
160
  iface->get_flags = gtk_tree_store_get_flags;
 
161
  iface->get_n_columns = gtk_tree_store_get_n_columns;
 
162
  iface->get_column_type = gtk_tree_store_get_column_type;
 
163
  iface->get_iter = gtk_tree_store_get_iter;
 
164
  iface->get_path = gtk_tree_store_get_path;
 
165
  iface->get_value = gtk_tree_store_get_value;
 
166
  iface->iter_next = gtk_tree_store_iter_next;
 
167
  iface->iter_children = gtk_tree_store_iter_children;
 
168
  iface->iter_has_child = gtk_tree_store_iter_has_child;
 
169
  iface->iter_n_children = gtk_tree_store_iter_n_children;
 
170
  iface->iter_nth_child = gtk_tree_store_iter_nth_child;
 
171
  iface->iter_parent = gtk_tree_store_iter_parent;
 
172
}
 
173
 
 
174
static void
 
175
gtk_tree_store_drag_source_init (GtkTreeDragSourceIface *iface)
 
176
{
 
177
  iface->row_draggable = real_gtk_tree_store_row_draggable;
 
178
  iface->drag_data_delete = gtk_tree_store_drag_data_delete;
 
179
  iface->drag_data_get = gtk_tree_store_drag_data_get;
 
180
}
 
181
 
 
182
static void
 
183
gtk_tree_store_drag_dest_init (GtkTreeDragDestIface *iface)
 
184
{
 
185
  iface->drag_data_received = gtk_tree_store_drag_data_received;
 
186
  iface->row_drop_possible = gtk_tree_store_row_drop_possible;
 
187
}
 
188
 
 
189
static void
 
190
gtk_tree_store_sortable_init (GtkTreeSortableIface *iface)
 
191
{
 
192
  iface->get_sort_column_id = gtk_tree_store_get_sort_column_id;
 
193
  iface->set_sort_column_id = gtk_tree_store_set_sort_column_id;
 
194
  iface->set_sort_func = gtk_tree_store_set_sort_func;
 
195
  iface->set_default_sort_func = gtk_tree_store_set_default_sort_func;
 
196
  iface->has_default_sort_func = gtk_tree_store_has_default_sort_func;
 
197
}
 
198
 
 
199
static void
 
200
gtk_tree_store_init (GtkTreeStore *tree_store)
 
201
{
 
202
  tree_store->root = g_node_new (NULL);
 
203
  /* While the odds are against us getting 0...
 
204
   */
 
205
  do
 
206
    {
 
207
      tree_store->stamp = g_random_int ();
 
208
    }
 
209
  while (tree_store->stamp == 0);
 
210
 
 
211
  tree_store->sort_list = NULL;
 
212
  tree_store->sort_column_id = -2;
 
213
  tree_store->columns_dirty = FALSE;
 
214
}
 
215
 
 
216
/**
 
217
 * gtk_tree_store_new:
 
218
 * @n_columns: number of columns in the tree store
 
219
 * @Varargs: all #GType types for the columns, from first to last
 
220
 *
 
221
 * Creates a new tree store as with @n_columns columns each of the types passed
 
222
 * in.  Note that only types derived from standard GObject fundamental types 
 
223
 * are supported. 
 
224
 *
 
225
 * As an example, <literal>gtk_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING,
 
226
 * GDK_TYPE_PIXBUF);</literal> will create a new #GtkTreeStore with three columns, of type
 
227
 * <type>int</type>, <type>string</type> and #GdkPixbuf respectively.
 
228
 *
 
229
 * Return value: a new #GtkTreeStore
 
230
 **/
 
231
GtkTreeStore *
 
232
gtk_tree_store_new (gint n_columns,
 
233
                               ...)
 
234
{
 
235
  GtkTreeStore *retval;
 
236
  va_list args;
 
237
  gint i;
 
238
 
 
239
  g_return_val_if_fail (n_columns > 0, NULL);
 
240
 
 
241
  retval = g_object_new (GTK_TYPE_TREE_STORE, NULL);
 
242
  gtk_tree_store_set_n_columns (retval, n_columns);
 
243
 
 
244
  va_start (args, n_columns);
 
245
 
 
246
  for (i = 0; i < n_columns; i++)
 
247
    {
 
248
      GType type = va_arg (args, GType);
 
249
      if (! _gtk_tree_data_list_check_type (type))
 
250
        {
 
251
          g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
 
252
          g_object_unref (retval);
 
253
          return NULL;
 
254
        }
 
255
      gtk_tree_store_set_column_type (retval, i, type);
 
256
    }
 
257
  va_end (args);
 
258
 
 
259
  return retval;
 
260
}
 
261
/**
 
262
 * gtk_tree_store_newv:
 
263
 * @n_columns: number of columns in the tree store
 
264
 * @types: an array of #GType types for the columns, from first to last
 
265
 *
 
266
 * Non vararg creation function.  Used primarily by language bindings.
 
267
 *
 
268
 * Return value: a new #GtkTreeStore
 
269
 **/
 
270
GtkTreeStore *
 
271
gtk_tree_store_newv (gint   n_columns,
 
272
                     GType *types)
 
273
{
 
274
  GtkTreeStore *retval;
 
275
  gint i;
 
276
 
 
277
  g_return_val_if_fail (n_columns > 0, NULL);
 
278
 
 
279
  retval = g_object_new (GTK_TYPE_TREE_STORE, NULL);
 
280
  gtk_tree_store_set_n_columns (retval, n_columns);
 
281
 
 
282
   for (i = 0; i < n_columns; i++)
 
283
    {
 
284
      if (! _gtk_tree_data_list_check_type (types[i]))
 
285
        {
 
286
          g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
 
287
          g_object_unref (retval);
 
288
          return NULL;
 
289
        }
 
290
      gtk_tree_store_set_column_type (retval, i, types[i]);
 
291
    }
 
292
 
 
293
  return retval;
 
294
}
 
295
 
 
296
 
 
297
/**
 
298
 * gtk_tree_store_set_column_types:
 
299
 * @tree_store: A #GtkTreeStore
 
300
 * @n_columns: Number of columns for the tree store
 
301
 * @types: An array of #GType types, one for each column
 
302
 * 
 
303
 * This function is meant primarily for #GObjects that inherit from 
 
304
 * #GtkTreeStore, and should only be used when constructing a new 
 
305
 * #GtkTreeStore.  It will not function after a row has been added, 
 
306
 * or a method on the #GtkTreeModel interface is called.
 
307
 **/
 
308
void
 
309
gtk_tree_store_set_column_types (GtkTreeStore *tree_store,
 
310
                                 gint          n_columns,
 
311
                                 GType        *types)
 
312
{
 
313
  gint i;
 
314
 
 
315
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
316
  g_return_if_fail (tree_store->columns_dirty == 0);
 
317
 
 
318
  gtk_tree_store_set_n_columns (tree_store, n_columns);
 
319
   for (i = 0; i < n_columns; i++)
 
320
    {
 
321
      if (! _gtk_tree_data_list_check_type (types[i]))
 
322
        {
 
323
          g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
 
324
          continue;
 
325
        }
 
326
      gtk_tree_store_set_column_type (tree_store, i, types[i]);
 
327
    }
 
328
}
 
329
 
 
330
static void
 
331
gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
 
332
                              gint          n_columns)
 
333
{
 
334
  GType *new_columns;
 
335
 
 
336
  if (tree_store->n_columns == n_columns)
 
337
    return;
 
338
 
 
339
  new_columns = g_new0 (GType, n_columns);
 
340
  if (tree_store->column_headers)
 
341
    {
 
342
      /* copy the old header orders over */
 
343
      if (n_columns >= tree_store->n_columns)
 
344
        memcpy (new_columns, tree_store->column_headers, tree_store->n_columns * sizeof (gchar *));
 
345
      else
 
346
        memcpy (new_columns, tree_store->column_headers, n_columns * sizeof (GType));
 
347
 
 
348
      g_free (tree_store->column_headers);
 
349
    }
 
350
 
 
351
  if (tree_store->sort_list)
 
352
    _gtk_tree_data_list_header_free (tree_store->sort_list);
 
353
 
 
354
  tree_store->sort_list = _gtk_tree_data_list_header_new (n_columns, tree_store->column_headers);
 
355
 
 
356
  tree_store->column_headers = new_columns;
 
357
  tree_store->n_columns = n_columns;
 
358
}
 
359
 
 
360
/**
 
361
 * gtk_tree_store_set_column_type:
 
362
 * @tree_store: a #GtkTreeStore
 
363
 * @column: column number
 
364
 * @type: type of the data to be stored in @column
 
365
 *
 
366
 * Supported types include: %G_TYPE_UINT, %G_TYPE_INT, %G_TYPE_UCHAR,
 
367
 * %G_TYPE_CHAR, %G_TYPE_BOOLEAN, %G_TYPE_POINTER, %G_TYPE_FLOAT,
 
368
 * %G_TYPE_DOUBLE, %G_TYPE_STRING, %G_TYPE_OBJECT, and %G_TYPE_BOXED, along with
 
369
 * subclasses of those types such as %GDK_TYPE_PIXBUF.
 
370
 *
 
371
 **/
 
372
static void
 
373
gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
 
374
                                gint          column,
 
375
                                GType         type)
 
376
{
 
377
  if (!_gtk_tree_data_list_check_type (type))
 
378
    {
 
379
      g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
 
380
      return;
 
381
    }
 
382
  tree_store->column_headers[column] = type;
 
383
}
 
384
 
 
385
static gboolean
 
386
node_free (GNode *node, gpointer data)
 
387
{
 
388
  if (node->data)
 
389
    _gtk_tree_data_list_free (node->data, (GType*)data);
 
390
  node->data = NULL;
 
391
 
 
392
  return FALSE;
 
393
}
 
394
 
 
395
static void
 
396
gtk_tree_store_finalize (GObject *object)
 
397
{
 
398
  GtkTreeStore *tree_store = GTK_TREE_STORE (object);
 
399
 
 
400
  g_node_traverse (tree_store->root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
 
401
                   node_free, tree_store->column_headers);
 
402
  g_node_destroy (tree_store->root);
 
403
  _gtk_tree_data_list_header_free (tree_store->sort_list);
 
404
  g_free (tree_store->column_headers);
 
405
 
 
406
  if (tree_store->default_sort_destroy)
 
407
    {
 
408
      GtkDestroyNotify d = tree_store->default_sort_destroy;
 
409
 
 
410
      tree_store->default_sort_destroy = NULL;
 
411
      d (tree_store->default_sort_data);
 
412
      tree_store->default_sort_data = NULL;
 
413
    }
 
414
 
 
415
  /* must chain up */
 
416
  G_OBJECT_CLASS (gtk_tree_store_parent_class)->finalize (object);
 
417
}
 
418
 
 
419
/* fulfill the GtkTreeModel requirements */
 
420
/* NOTE: GtkTreeStore::root is a GNode, that acts as the parent node.  However,
 
421
 * it is not visible to the tree or to the user., and the path "0" refers to the
 
422
 * first child of GtkTreeStore::root.
 
423
 */
 
424
 
 
425
 
 
426
static GtkTreeModelFlags
 
427
gtk_tree_store_get_flags (GtkTreeModel *tree_model)
 
428
{
 
429
  return GTK_TREE_MODEL_ITERS_PERSIST;
 
430
}
 
431
 
 
432
static gint
 
433
gtk_tree_store_get_n_columns (GtkTreeModel *tree_model)
 
434
{
 
435
  GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
 
436
 
 
437
  tree_store->columns_dirty = TRUE;
 
438
 
 
439
  return tree_store->n_columns;
 
440
}
 
441
 
 
442
static GType
 
443
gtk_tree_store_get_column_type (GtkTreeModel *tree_model,
 
444
                                gint          index)
 
445
{
 
446
  GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
 
447
 
 
448
  g_return_val_if_fail (index < tree_store->n_columns, G_TYPE_INVALID);
 
449
 
 
450
  tree_store->columns_dirty = TRUE;
 
451
 
 
452
  return tree_store->column_headers[index];
 
453
}
 
454
 
 
455
static gboolean
 
456
gtk_tree_store_get_iter (GtkTreeModel *tree_model,
 
457
                         GtkTreeIter  *iter,
 
458
                         GtkTreePath  *path)
 
459
{
 
460
  GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
 
461
  GtkTreeIter parent;
 
462
  gint *indices;
 
463
  gint depth, i;
 
464
 
 
465
  tree_store->columns_dirty = TRUE;
 
466
 
 
467
  indices = gtk_tree_path_get_indices (path);
 
468
  depth = gtk_tree_path_get_depth (path);
 
469
 
 
470
  g_return_val_if_fail (depth > 0, FALSE);
 
471
 
 
472
  parent.stamp = tree_store->stamp;
 
473
  parent.user_data = tree_store->root;
 
474
 
 
475
  if (!gtk_tree_store_iter_nth_child (tree_model, iter, &parent, indices[0]))
 
476
    return FALSE;
 
477
 
 
478
  for (i = 1; i < depth; i++)
 
479
    {
 
480
      parent = *iter;
 
481
      if (!gtk_tree_store_iter_nth_child (tree_model, iter, &parent, indices[i]))
 
482
        return FALSE;
 
483
    }
 
484
 
 
485
  return TRUE;
 
486
}
 
487
 
 
488
static GtkTreePath *
 
489
gtk_tree_store_get_path (GtkTreeModel *tree_model,
 
490
                         GtkTreeIter  *iter)
 
491
{
 
492
  GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
 
493
  GtkTreePath *retval;
 
494
  GNode *tmp_node;
 
495
  gint i = 0;
 
496
 
 
497
  g_return_val_if_fail (iter->user_data != NULL, NULL);
 
498
  g_return_val_if_fail (iter->stamp == tree_store->stamp, NULL);
 
499
 
 
500
  validate_tree (tree_store);
 
501
 
 
502
  if (G_NODE (iter->user_data)->parent == NULL &&
 
503
      G_NODE (iter->user_data) == tree_store->root)
 
504
    return gtk_tree_path_new ();
 
505
  g_assert (G_NODE (iter->user_data)->parent != NULL);
 
506
 
 
507
  if (G_NODE (iter->user_data)->parent == G_NODE (tree_store->root))
 
508
    {
 
509
      retval = gtk_tree_path_new ();
 
510
      tmp_node = G_NODE (tree_store->root)->children;
 
511
    }
 
512
  else
 
513
    {
 
514
      GtkTreeIter tmp_iter = *iter;
 
515
 
 
516
      tmp_iter.user_data = G_NODE (iter->user_data)->parent;
 
517
 
 
518
      retval = gtk_tree_store_get_path (tree_model, &tmp_iter);
 
519
      tmp_node = G_NODE (iter->user_data)->parent->children;
 
520
    }
 
521
 
 
522
  if (retval == NULL)
 
523
    return NULL;
 
524
 
 
525
  if (tmp_node == NULL)
 
526
    {
 
527
      gtk_tree_path_free (retval);
 
528
      return NULL;
 
529
    }
 
530
 
 
531
  for (; tmp_node; tmp_node = tmp_node->next)
 
532
    {
 
533
      if (tmp_node == G_NODE (iter->user_data))
 
534
        break;
 
535
      i++;
 
536
    }
 
537
 
 
538
  if (tmp_node == NULL)
 
539
    {
 
540
      /* We couldn't find node, meaning it's prolly not ours */
 
541
      /* Perhaps I should do a g_return_if_fail here. */
 
542
      gtk_tree_path_free (retval);
 
543
      return NULL;
 
544
    }
 
545
 
 
546
  gtk_tree_path_append_index (retval, i);
 
547
 
 
548
  return retval;
 
549
}
 
550
 
 
551
 
 
552
static void
 
553
gtk_tree_store_get_value (GtkTreeModel *tree_model,
 
554
                          GtkTreeIter  *iter,
 
555
                          gint          column,
 
556
                          GValue       *value)
 
557
{
 
558
  GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
 
559
  GtkTreeDataList *list;
 
560
  gint tmp_column = column;
 
561
 
 
562
  g_return_if_fail (column < tree_store->n_columns);
 
563
  g_return_if_fail (VALID_ITER (iter, tree_store));
 
564
 
 
565
  list = G_NODE (iter->user_data)->data;
 
566
 
 
567
  while (tmp_column-- > 0 && list)
 
568
    list = list->next;
 
569
 
 
570
  if (list)
 
571
    {
 
572
      _gtk_tree_data_list_node_to_value (list,
 
573
                                         tree_store->column_headers[column],
 
574
                                         value);
 
575
    }
 
576
  else
 
577
    {
 
578
      /* We want to return an initialized but empty (default) value */
 
579
      g_value_init (value, tree_store->column_headers[column]);
 
580
    }
 
581
}
 
582
 
 
583
static gboolean
 
584
gtk_tree_store_iter_next (GtkTreeModel  *tree_model,
 
585
                          GtkTreeIter   *iter)
 
586
{
 
587
  g_return_val_if_fail (iter->user_data != NULL, FALSE);
 
588
  g_return_val_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp, FALSE);
 
589
 
 
590
  if (G_NODE (iter->user_data)->next)
 
591
    {
 
592
      iter->user_data = G_NODE (iter->user_data)->next;
 
593
      return TRUE;
 
594
    }
 
595
  else
 
596
    return FALSE;
 
597
}
 
598
 
 
599
static gboolean
 
600
gtk_tree_store_iter_children (GtkTreeModel *tree_model,
 
601
                              GtkTreeIter  *iter,
 
602
                              GtkTreeIter  *parent)
 
603
{
 
604
  GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
 
605
  GNode *children;
 
606
 
 
607
  if (parent)
 
608
    g_return_val_if_fail (VALID_ITER (parent, tree_store), FALSE);
 
609
 
 
610
  if (parent)
 
611
    children = G_NODE (parent->user_data)->children;
 
612
  else
 
613
    children = G_NODE (tree_store->root)->children;
 
614
 
 
615
  if (children)
 
616
    {
 
617
      iter->stamp = tree_store->stamp;
 
618
      iter->user_data = children;
 
619
      return TRUE;
 
620
    }
 
621
  else
 
622
    return FALSE;
 
623
}
 
624
 
 
625
static gboolean
 
626
gtk_tree_store_iter_has_child (GtkTreeModel *tree_model,
 
627
                               GtkTreeIter  *iter)
 
628
{
 
629
  g_return_val_if_fail (iter->user_data != NULL, FALSE);
 
630
  g_return_val_if_fail (VALID_ITER (iter, tree_model), FALSE);
 
631
 
 
632
  return G_NODE (iter->user_data)->children != NULL;
 
633
}
 
634
 
 
635
static gint
 
636
gtk_tree_store_iter_n_children (GtkTreeModel *tree_model,
 
637
                                GtkTreeIter  *iter)
 
638
{
 
639
  GNode *node;
 
640
  gint i = 0;
 
641
 
 
642
  g_return_val_if_fail (iter == NULL || iter->user_data != NULL, 0);
 
643
 
 
644
  if (iter == NULL)
 
645
    node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
 
646
  else
 
647
    node = G_NODE (iter->user_data)->children;
 
648
 
 
649
  while (node)
 
650
    {
 
651
      i++;
 
652
      node = node->next;
 
653
    }
 
654
 
 
655
  return i;
 
656
}
 
657
 
 
658
static gboolean
 
659
gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model,
 
660
                               GtkTreeIter  *iter,
 
661
                               GtkTreeIter  *parent,
 
662
                               gint          n)
 
663
{
 
664
  GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
 
665
  GNode *parent_node;
 
666
  GNode *child;
 
667
 
 
668
  g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
 
669
 
 
670
  if (parent == NULL)
 
671
    parent_node = tree_store->root;
 
672
  else
 
673
    parent_node = parent->user_data;
 
674
 
 
675
  child = g_node_nth_child (parent_node, n);
 
676
 
 
677
  if (child)
 
678
    {
 
679
      iter->user_data = child;
 
680
      iter->stamp = tree_store->stamp;
 
681
      return TRUE;
 
682
    }
 
683
  else
 
684
    return FALSE;
 
685
}
 
686
 
 
687
static gboolean
 
688
gtk_tree_store_iter_parent (GtkTreeModel *tree_model,
 
689
                            GtkTreeIter  *iter,
 
690
                            GtkTreeIter  *child)
 
691
{
 
692
  GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
 
693
  GNode *parent;
 
694
 
 
695
  g_return_val_if_fail (iter != NULL, FALSE);
 
696
  g_return_val_if_fail (VALID_ITER (child, tree_store), FALSE);
 
697
 
 
698
  parent = G_NODE (child->user_data)->parent;
 
699
 
 
700
  g_assert (parent != NULL);
 
701
 
 
702
  if (parent != tree_store->root)
 
703
    {
 
704
      iter->user_data = parent;
 
705
      iter->stamp = tree_store->stamp;
 
706
      return TRUE;
 
707
    }
 
708
  else
 
709
    return FALSE;
 
710
}
 
711
 
 
712
 
 
713
/* Does not emit a signal */
 
714
static gboolean
 
715
gtk_tree_store_real_set_value (GtkTreeStore *tree_store,
 
716
                               GtkTreeIter  *iter,
 
717
                               gint          column,
 
718
                               GValue       *value,
 
719
                               gboolean      sort)
 
720
{
 
721
  GtkTreeDataList *list;
 
722
  GtkTreeDataList *prev;
 
723
  gint old_column = column;
 
724
  GValue real_value = {0, };
 
725
  gboolean converted = FALSE;
 
726
  gboolean retval = FALSE;
 
727
 
 
728
  if (! g_type_is_a (G_VALUE_TYPE (value), tree_store->column_headers[column]))
 
729
    {
 
730
      if (! (g_value_type_compatible (G_VALUE_TYPE (value), tree_store->column_headers[column]) &&
 
731
             g_value_type_compatible (tree_store->column_headers[column], G_VALUE_TYPE (value))))
 
732
        {
 
733
          g_warning ("%s: Unable to convert from %s to %s\n",
 
734
                     G_STRLOC,
 
735
                     g_type_name (G_VALUE_TYPE (value)),
 
736
                     g_type_name (tree_store->column_headers[column]));
 
737
          return retval;
 
738
        }
 
739
      if (!g_value_transform (value, &real_value))
 
740
        {
 
741
          g_warning ("%s: Unable to make conversion from %s to %s\n",
 
742
                     G_STRLOC,
 
743
                     g_type_name (G_VALUE_TYPE (value)),
 
744
                     g_type_name (tree_store->column_headers[column]));
 
745
          g_value_unset (&real_value);
 
746
          return retval;
 
747
        }
 
748
      converted = TRUE;
 
749
    }
 
750
 
 
751
  prev = list = G_NODE (iter->user_data)->data;
 
752
 
 
753
  while (list != NULL)
 
754
    {
 
755
      if (column == 0)
 
756
        {
 
757
          if (converted)
 
758
            _gtk_tree_data_list_value_to_node (list, &real_value);
 
759
          else
 
760
            _gtk_tree_data_list_value_to_node (list, value);
 
761
          retval = TRUE;
 
762
          if (converted)
 
763
            g_value_unset (&real_value);
 
764
          if (sort && GTK_TREE_STORE_IS_SORTED (tree_store))
 
765
            gtk_tree_store_sort_iter_changed (tree_store, iter, old_column, TRUE);
 
766
          return retval;
 
767
        }
 
768
 
 
769
      column--;
 
770
      prev = list;
 
771
      list = list->next;
 
772
    }
 
773
 
 
774
  if (G_NODE (iter->user_data)->data == NULL)
 
775
    {
 
776
      G_NODE (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
 
777
      list->next = NULL;
 
778
    }
 
779
  else
 
780
    {
 
781
      list = prev->next = _gtk_tree_data_list_alloc ();
 
782
      list->next = NULL;
 
783
    }
 
784
 
 
785
  while (column != 0)
 
786
    {
 
787
      list->next = _gtk_tree_data_list_alloc ();
 
788
      list = list->next;
 
789
      list->next = NULL;
 
790
      column --;
 
791
    }
 
792
 
 
793
  if (converted)
 
794
    _gtk_tree_data_list_value_to_node (list, &real_value);
 
795
  else
 
796
    _gtk_tree_data_list_value_to_node (list, value);
 
797
  
 
798
  retval = TRUE;
 
799
  if (converted)
 
800
    g_value_unset (&real_value);
 
801
 
 
802
  if (sort && GTK_TREE_STORE_IS_SORTED (tree_store))
 
803
    gtk_tree_store_sort_iter_changed (tree_store, iter, old_column, TRUE);
 
804
 
 
805
  return retval;
 
806
}
 
807
 
 
808
/**
 
809
 * gtk_tree_store_set_value:
 
810
 * @tree_store: a #GtkTreeStore
 
811
 * @iter: A valid #GtkTreeIter for the row being modified
 
812
 * @column: column number to modify
 
813
 * @value: new value for the cell
 
814
 *
 
815
 * Sets the data in the cell specified by @iter and @column.
 
816
 * The type of @value must be convertible to the type of the
 
817
 * column.
 
818
 *
 
819
 **/
 
820
void
 
821
gtk_tree_store_set_value (GtkTreeStore *tree_store,
 
822
                          GtkTreeIter  *iter,
 
823
                          gint          column,
 
824
                          GValue       *value)
 
825
{
 
826
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
827
  g_return_if_fail (VALID_ITER (iter, tree_store));
 
828
  g_return_if_fail (column >= 0 && column < tree_store->n_columns);
 
829
  g_return_if_fail (G_IS_VALUE (value));
 
830
 
 
831
  if (gtk_tree_store_real_set_value (tree_store, iter, column, value, TRUE))
 
832
    {
 
833
      GtkTreePath *path;
 
834
 
 
835
      path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
836
      gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter);
 
837
      gtk_tree_path_free (path);
 
838
    }
 
839
}
 
840
 
 
841
static GtkTreeIterCompareFunc
 
842
gtk_tree_store_get_compare_func (GtkTreeStore *tree_store)
 
843
{
 
844
  GtkTreeIterCompareFunc func = NULL;
 
845
 
 
846
  if (GTK_TREE_STORE_IS_SORTED (tree_store))
 
847
    {
 
848
      if (tree_store->sort_column_id != -1)
 
849
        {
 
850
          GtkTreeDataSortHeader *header;
 
851
          header = _gtk_tree_data_list_get_header (tree_store->sort_list,
 
852
                                                   tree_store->sort_column_id);
 
853
          g_return_val_if_fail (header != NULL, NULL);
 
854
          g_return_val_if_fail (header->func != NULL, NULL);
 
855
          func = header->func;
 
856
        }
 
857
      else
 
858
        {
 
859
          func = tree_store->default_sort_func;
 
860
        }
 
861
    }
 
862
 
 
863
  return func;
 
864
}
 
865
 
 
866
static void
 
867
gtk_tree_store_set_valist_internal (GtkTreeStore *tree_store,
 
868
                                    GtkTreeIter  *iter,
 
869
                                    gboolean     *emit_signal,
 
870
                                    gboolean     *maybe_need_sort,
 
871
                                    va_list       var_args)
 
872
{
 
873
  gint column;
 
874
  GtkTreeIterCompareFunc func = NULL;
 
875
 
 
876
  column = va_arg (var_args, gint);
 
877
 
 
878
  func = gtk_tree_store_get_compare_func (tree_store);
 
879
  if (func != _gtk_tree_data_list_compare_func)
 
880
    *maybe_need_sort = TRUE;
 
881
 
 
882
  while (column != -1)
 
883
    {
 
884
      GValue value = { 0, };
 
885
      gchar *error = NULL;
 
886
 
 
887
      if (column < 0 || column >= tree_store->n_columns)
 
888
        {
 
889
          g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
 
890
          break;
 
891
        }
 
892
      g_value_init (&value, tree_store->column_headers[column]);
 
893
 
 
894
      G_VALUE_COLLECT (&value, var_args, 0, &error);
 
895
      if (error)
 
896
        {
 
897
          g_warning ("%s: %s", G_STRLOC, error);
 
898
          g_free (error);
 
899
 
 
900
          /* we purposely leak the value here, it might not be
 
901
           * in a sane state if an error condition occoured
 
902
           */
 
903
          break;
 
904
        }
 
905
 
 
906
      *emit_signal = gtk_tree_store_real_set_value (tree_store,
 
907
                                                    iter,
 
908
                                                    column,
 
909
                                                    &value,
 
910
                                                    FALSE) || *emit_signal;
 
911
 
 
912
      if (func == _gtk_tree_data_list_compare_func &&
 
913
          column == tree_store->sort_column_id)
 
914
        *maybe_need_sort = TRUE;
 
915
 
 
916
      g_value_unset (&value);
 
917
 
 
918
      column = va_arg (var_args, gint);
 
919
    }
 
920
}
 
921
 
 
922
/**
 
923
 * gtk_tree_store_set_valist:
 
924
 * @tree_store: A #GtkTreeStore
 
925
 * @iter: A valid #GtkTreeIter for the row being modified
 
926
 * @var_args: <type>va_list</type> of column/value pairs
 
927
 *
 
928
 * See gtk_tree_store_set(); this version takes a <type>va_list</type> for
 
929
 * use by language bindings.
 
930
 *
 
931
 **/
 
932
void
 
933
gtk_tree_store_set_valist (GtkTreeStore *tree_store,
 
934
                           GtkTreeIter  *iter,
 
935
                           va_list       var_args)
 
936
{
 
937
  gboolean emit_signal = FALSE;
 
938
  gboolean maybe_need_sort = FALSE;
 
939
 
 
940
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
941
  g_return_if_fail (VALID_ITER (iter, tree_store));
 
942
 
 
943
  gtk_tree_store_set_valist_internal (tree_store, iter,
 
944
                                      &emit_signal,
 
945
                                      &maybe_need_sort,
 
946
                                      var_args);
 
947
 
 
948
  if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
 
949
    gtk_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id, TRUE);
 
950
 
 
951
  if (emit_signal)
 
952
    {
 
953
      GtkTreePath *path;
 
954
 
 
955
      path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
956
      gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter);
 
957
      gtk_tree_path_free (path);
 
958
    }
 
959
}
 
960
 
 
961
/**
 
962
 * gtk_tree_store_set:
 
963
 * @tree_store: A #GtkTreeStore
 
964
 * @iter: A valid #GtkTreeIter for the row being modified
 
965
 * @Varargs: pairs of column number and value, terminated with -1
 
966
 *
 
967
 * Sets the value of one or more cells in the row referenced by @iter.
 
968
 * The variable argument list should contain integer column numbers,
 
969
 * each column number followed by the value to be set. 
 
970
 * The list is terminated by a -1. For example, to set column 0 with type
 
971
 * %G_TYPE_STRING to "Foo", you would write 
 
972
 * <literal>gtk_tree_store_set (store, iter, 0, "Foo", -1)</literal>.
 
973
 **/
 
974
void
 
975
gtk_tree_store_set (GtkTreeStore *tree_store,
 
976
                    GtkTreeIter  *iter,
 
977
                    ...)
 
978
{
 
979
  va_list var_args;
 
980
 
 
981
  va_start (var_args, iter);
 
982
  gtk_tree_store_set_valist (tree_store, iter, var_args);
 
983
  va_end (var_args);
 
984
}
 
985
 
 
986
/**
 
987
 * gtk_tree_store_remove:
 
988
 * @tree_store: A #GtkTreeStore
 
989
 * @iter: A valid #GtkTreeIter
 
990
 * 
 
991
 * Removes @iter from @tree_store.  After being removed, @iter is set to the
 
992
 * next valid row at that level, or invalidated if it previously pointed to the
 
993
 * last one.
 
994
 *
 
995
 * Return value: %TRUE if @iter is still valid, %FALSE if not.
 
996
 **/
 
997
gboolean
 
998
gtk_tree_store_remove (GtkTreeStore *tree_store,
 
999
                       GtkTreeIter  *iter)
 
1000
{
 
1001
  GtkTreePath *path;
 
1002
  GtkTreeIter new_iter = {0,};
 
1003
  GNode *parent;
 
1004
  GNode *next_node;
 
1005
 
 
1006
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), FALSE);
 
1007
  g_return_val_if_fail (VALID_ITER (iter, tree_store), FALSE);
 
1008
 
 
1009
  parent = G_NODE (iter->user_data)->parent;
 
1010
 
 
1011
  g_assert (parent != NULL);
 
1012
  next_node = G_NODE (iter->user_data)->next;
 
1013
 
 
1014
  if (G_NODE (iter->user_data)->data)
 
1015
    g_node_traverse (G_NODE (iter->user_data), G_POST_ORDER, G_TRAVERSE_ALL,
 
1016
                     -1, node_free, tree_store->column_headers);
 
1017
 
 
1018
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
1019
  g_node_destroy (G_NODE (iter->user_data));
 
1020
 
 
1021
  gtk_tree_model_row_deleted (GTK_TREE_MODEL (tree_store), path);
 
1022
 
 
1023
  if (parent != G_NODE (tree_store->root))
 
1024
    {
 
1025
      /* child_toggled */
 
1026
      if (parent->children == NULL)
 
1027
        {
 
1028
          gtk_tree_path_up (path);
 
1029
 
 
1030
          new_iter.stamp = tree_store->stamp;
 
1031
          new_iter.user_data = parent;
 
1032
          gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &new_iter);
 
1033
        }
 
1034
    }
 
1035
  gtk_tree_path_free (path);
 
1036
 
 
1037
  /* revalidate iter */
 
1038
  if (next_node != NULL)
 
1039
    {
 
1040
      iter->stamp = tree_store->stamp;
 
1041
      iter->user_data = next_node;
 
1042
      return TRUE;
 
1043
    }
 
1044
  else
 
1045
    {
 
1046
      iter->stamp = 0;
 
1047
      iter->user_data = NULL;
 
1048
    }
 
1049
 
 
1050
  return FALSE;
 
1051
}
 
1052
 
 
1053
/**
 
1054
 * gtk_tree_store_insert:
 
1055
 * @tree_store: A #GtkTreeStore
 
1056
 * @iter: An unset #GtkTreeIter to set to the new row
 
1057
 * @parent: A valid #GtkTreeIter, or %NULL
 
1058
 * @position: position to insert the new row
 
1059
 *
 
1060
 * Creates a new row at @position.  If parent is non-%NULL, then the row will be
 
1061
 * made a child of @parent.  Otherwise, the row will be created at the toplevel.
 
1062
 * If @position is larger than the number of rows at that level, then the new
 
1063
 * row will be inserted to the end of the list.  @iter will be changed to point
 
1064
 * to this new row.  The row will be empty after this function is called.  To
 
1065
 * fill in values, you need to call gtk_tree_store_set() or
 
1066
 * gtk_tree_store_set_value().
 
1067
 *
 
1068
 **/
 
1069
void
 
1070
gtk_tree_store_insert (GtkTreeStore *tree_store,
 
1071
                       GtkTreeIter  *iter,
 
1072
                       GtkTreeIter  *parent,
 
1073
                       gint          position)
 
1074
{
 
1075
  GtkTreePath *path;
 
1076
  GNode *parent_node;
 
1077
  GNode *new_node;
 
1078
 
 
1079
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
1080
  g_return_if_fail (iter != NULL);
 
1081
  if (parent)
 
1082
    g_return_if_fail (VALID_ITER (parent, tree_store));
 
1083
 
 
1084
  if (parent)
 
1085
    parent_node = parent->user_data;
 
1086
  else
 
1087
    parent_node = tree_store->root;
 
1088
 
 
1089
  tree_store->columns_dirty = TRUE;
 
1090
 
 
1091
  new_node = g_node_new (NULL);
 
1092
 
 
1093
  iter->stamp = tree_store->stamp;
 
1094
  iter->user_data = new_node;
 
1095
  g_node_insert (parent_node, position, new_node);
 
1096
 
 
1097
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
1098
  gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
 
1099
 
 
1100
  if (parent_node != tree_store->root)
 
1101
    {
 
1102
      if (new_node->prev == NULL && new_node->next == NULL)
 
1103
        {
 
1104
          gtk_tree_path_up (path);
 
1105
          gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
 
1106
        }
 
1107
    }
 
1108
 
 
1109
  gtk_tree_path_free (path);
 
1110
 
 
1111
  validate_tree ((GtkTreeStore*)tree_store);
 
1112
}
 
1113
 
 
1114
/**
 
1115
 * gtk_tree_store_insert_before:
 
1116
 * @tree_store: A #GtkTreeStore
 
1117
 * @iter: An unset #GtkTreeIter to set to the new row
 
1118
 * @parent: A valid #GtkTreeIter, or %NULL
 
1119
 * @sibling: A valid #GtkTreeIter, or %NULL
 
1120
 *
 
1121
 * Inserts a new row before @sibling.  If @sibling is %NULL, then the row will
 
1122
 * be appended to @parent 's children.  If @parent and @sibling are %NULL, then
 
1123
 * the row will be appended to the toplevel.  If both @sibling and @parent are
 
1124
 * set, then @parent must be the parent of @sibling.  When @sibling is set,
 
1125
 * @parent is optional.
 
1126
 *
 
1127
 * @iter will be changed to point to this new row.  The row will be empty after
 
1128
 * this function is called.  To fill in values, you need to call
 
1129
 * gtk_tree_store_set() or gtk_tree_store_set_value().
 
1130
 *
 
1131
 **/
 
1132
void
 
1133
gtk_tree_store_insert_before (GtkTreeStore *tree_store,
 
1134
                              GtkTreeIter  *iter,
 
1135
                              GtkTreeIter  *parent,
 
1136
                              GtkTreeIter  *sibling)
 
1137
{
 
1138
  GtkTreePath *path;
 
1139
  GNode *parent_node = NULL;
 
1140
  GNode *new_node;
 
1141
 
 
1142
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
1143
  g_return_if_fail (iter != NULL);
 
1144
  if (parent != NULL)
 
1145
    g_return_if_fail (VALID_ITER (parent, tree_store));
 
1146
  if (sibling != NULL)
 
1147
    g_return_if_fail (VALID_ITER (sibling, tree_store));
 
1148
 
 
1149
  if (parent == NULL && sibling == NULL)
 
1150
    parent_node = tree_store->root;
 
1151
  else if (parent == NULL)
 
1152
    parent_node = G_NODE (sibling->user_data)->parent;
 
1153
  else if (sibling == NULL)
 
1154
    parent_node = G_NODE (parent->user_data);
 
1155
  else
 
1156
    {
 
1157
      g_return_if_fail (G_NODE (sibling->user_data)->parent == G_NODE (parent->user_data));
 
1158
      parent_node = G_NODE (parent->user_data);
 
1159
    }
 
1160
 
 
1161
  tree_store->columns_dirty = TRUE;
 
1162
 
 
1163
  new_node = g_node_new (NULL);
 
1164
 
 
1165
  g_node_insert_before (parent_node,
 
1166
                        sibling ? G_NODE (sibling->user_data) : NULL,
 
1167
                        new_node);
 
1168
 
 
1169
  iter->stamp = tree_store->stamp;
 
1170
  iter->user_data = new_node;
 
1171
 
 
1172
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
1173
  gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
 
1174
 
 
1175
  if (parent_node != tree_store->root)
 
1176
    {
 
1177
      if (new_node->prev == NULL && new_node->next == NULL)
 
1178
        {
 
1179
          GtkTreeIter parent_iter;
 
1180
 
 
1181
          parent_iter.stamp = tree_store->stamp;
 
1182
          parent_iter.user_data = parent_node;
 
1183
 
 
1184
          gtk_tree_path_up (path);
 
1185
          gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &parent_iter);
 
1186
        }
 
1187
    }
 
1188
 
 
1189
  gtk_tree_path_free (path);
 
1190
 
 
1191
  validate_tree (tree_store);
 
1192
}
 
1193
 
 
1194
/**
 
1195
 * gtk_tree_store_insert_after:
 
1196
 * @tree_store: A #GtkTreeStore
 
1197
 * @iter: An unset #GtkTreeIter to set to the new row
 
1198
 * @parent: A valid #GtkTreeIter, or %NULL
 
1199
 * @sibling: A valid #GtkTreeIter, or %NULL
 
1200
 *
 
1201
 * Inserts a new row after @sibling.  If @sibling is %NULL, then the row will be
 
1202
 * prepended to @parent 's children.  If @parent and @sibling are %NULL, then
 
1203
 * the row will be prepended to the toplevel.  If both @sibling and @parent are
 
1204
 * set, then @parent must be the parent of @sibling.  When @sibling is set,
 
1205
 * @parent is optional.
 
1206
 *
 
1207
 * @iter will be changed to point to this new row.  The row will be empty after
 
1208
 * this function is called.  To fill in values, you need to call
 
1209
 * gtk_tree_store_set() or gtk_tree_store_set_value().
 
1210
 *
 
1211
 **/
 
1212
void
 
1213
gtk_tree_store_insert_after (GtkTreeStore *tree_store,
 
1214
                             GtkTreeIter  *iter,
 
1215
                             GtkTreeIter  *parent,
 
1216
                             GtkTreeIter  *sibling)
 
1217
{
 
1218
  GtkTreePath *path;
 
1219
  GNode *parent_node;
 
1220
  GNode *new_node;
 
1221
 
 
1222
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
1223
  g_return_if_fail (iter != NULL);
 
1224
  if (parent != NULL)
 
1225
    g_return_if_fail (VALID_ITER (parent, tree_store));
 
1226
  if (sibling != NULL)
 
1227
    g_return_if_fail (VALID_ITER (sibling, tree_store));
 
1228
 
 
1229
  if (parent == NULL && sibling == NULL)
 
1230
    parent_node = tree_store->root;
 
1231
  else if (parent == NULL)
 
1232
    parent_node = G_NODE (sibling->user_data)->parent;
 
1233
  else if (sibling == NULL)
 
1234
    parent_node = G_NODE (parent->user_data);
 
1235
  else
 
1236
    {
 
1237
      g_return_if_fail (G_NODE (sibling->user_data)->parent ==
 
1238
                        G_NODE (parent->user_data));
 
1239
      parent_node = G_NODE (parent->user_data);
 
1240
    }
 
1241
 
 
1242
  tree_store->columns_dirty = TRUE;
 
1243
 
 
1244
  new_node = g_node_new (NULL);
 
1245
 
 
1246
  g_node_insert_after (parent_node,
 
1247
                       sibling ? G_NODE (sibling->user_data) : NULL,
 
1248
                       new_node);
 
1249
 
 
1250
  iter->stamp = tree_store->stamp;
 
1251
  iter->user_data = new_node;
 
1252
 
 
1253
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
1254
  gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
 
1255
 
 
1256
  if (parent_node != tree_store->root)
 
1257
    {
 
1258
      if (new_node->prev == NULL && new_node->next == NULL)
 
1259
        {
 
1260
          GtkTreeIter parent_iter;
 
1261
 
 
1262
          parent_iter.stamp = tree_store->stamp;
 
1263
          parent_iter.user_data = parent_node;
 
1264
 
 
1265
          gtk_tree_path_up (path);
 
1266
          gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &parent_iter);
 
1267
        }
 
1268
    }
 
1269
 
 
1270
  gtk_tree_path_free (path);
 
1271
 
 
1272
  validate_tree (tree_store);
 
1273
}
 
1274
 
 
1275
/**
 
1276
 * gtk_tree_store_insert_with_values:
 
1277
 * @tree_store: A #GtkTreeStore
 
1278
 * @iter: An unset #GtkTreeIter to set the new row, or %NULL.
 
1279
 * @parent: A valid #GtkTreeIter, or %NULL
 
1280
 * @position: position to insert the new row
 
1281
 * @Varargs: pairs of column number and value, terminated with -1
 
1282
 *
 
1283
 * Creates a new row at @position.  @iter will be changed to point to this
 
1284
 * new row.  If @position is larger than the number of rows on the list, then
 
1285
 * the new row will be appended to the list.  The row will be filled with
 
1286
 * the values given to this function.
 
1287
 *
 
1288
 * Calling
 
1289
 * <literal>gtk_tree_store_insert_with_values (tree_store, iter, position, ...)</literal>
 
1290
 * has the same effect as calling
 
1291
 * <informalexample><programlisting>
 
1292
 * gtk_tree_store_insert (tree_store, iter, position);
 
1293
 * gtk_tree_store_set (tree_store, iter, ...);
 
1294
 * </programlisting></informalexample>
 
1295
 * with the different that the former will only emit a row_inserted signal,
 
1296
 * while the latter will emit row_inserted, row_changed and if the tree store
 
1297
 * is sorted, rows_reordered.  Since emitting the rows_reordered signal
 
1298
 * repeatedly can affect the performance of the program,
 
1299
 * gtk_tree_store_insert_with_values() should generally be preferred when
 
1300
 * inserting rows in a sorted tree store.
 
1301
 *
 
1302
 * Since: 2.10
 
1303
 */
 
1304
void
 
1305
gtk_tree_store_insert_with_values (GtkTreeStore *tree_store,
 
1306
                                   GtkTreeIter  *iter,
 
1307
                                   GtkTreeIter  *parent,
 
1308
                                   gint          position,
 
1309
                                   ...)
 
1310
{
 
1311
  GtkTreePath *path;
 
1312
  GNode *parent_node;
 
1313
  GNode *new_node;
 
1314
  GtkTreeIter tmp_iter;
 
1315
  va_list var_args;
 
1316
  gboolean changed = FALSE;
 
1317
  gboolean maybe_need_sort = FALSE;
 
1318
 
 
1319
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
1320
 
 
1321
  if (!iter)
 
1322
    iter = &tmp_iter;
 
1323
 
 
1324
  if (parent)
 
1325
    g_return_if_fail (VALID_ITER (parent, tree_store));
 
1326
 
 
1327
  if (parent)
 
1328
    parent_node = parent->user_data;
 
1329
  else
 
1330
    parent_node = tree_store->root;
 
1331
 
 
1332
  tree_store->columns_dirty = TRUE;
 
1333
 
 
1334
  new_node = g_node_new (NULL);
 
1335
 
 
1336
  iter->stamp = tree_store->stamp;
 
1337
  iter->user_data = new_node;
 
1338
  g_node_insert (parent_node, position, new_node);
 
1339
 
 
1340
  va_start (var_args, position);
 
1341
  gtk_tree_store_set_valist_internal (tree_store, iter,
 
1342
                                      &changed, &maybe_need_sort,
 
1343
                                      var_args);
 
1344
  va_end (var_args);
 
1345
 
 
1346
  if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
 
1347
    gtk_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id, FALSE);
 
1348
 
 
1349
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
1350
  gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
 
1351
 
 
1352
  if (parent_node != tree_store->root)
 
1353
    {
 
1354
      if (new_node->prev == NULL && new_node->next == NULL)
 
1355
        {
 
1356
          gtk_tree_path_up (path);
 
1357
          gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
 
1358
        }
 
1359
    }
 
1360
 
 
1361
  gtk_tree_path_free (path);
 
1362
 
 
1363
  validate_tree ((GtkTreeStore *)tree_store);
 
1364
}
 
1365
 
 
1366
/**
 
1367
 * gtk_tree_store_insert_with_valuesv:
 
1368
 * @tree_store: A #GtkTreeStore
 
1369
 * @iter: An unset #GtkTreeIter to set the new row, or %NULL.
 
1370
 * @parent: A valid #GtkTreeIter, or %NULL
 
1371
 * @position: position to insert the new row
 
1372
 * @columns: an array of column numbers
 
1373
 * @values: an array of GValues
 
1374
 * @n_values: the length of the @columns and @values arrays
 
1375
 *
 
1376
 * A variant of gtk_tree_store_insert_with_values() which takes
 
1377
 * the columns and values as two arrays, instead of varargs.  This
 
1378
 * function is mainly intended for language bindings.
 
1379
 *
 
1380
 * Since: 2.10
 
1381
 */
 
1382
void
 
1383
gtk_tree_store_insert_with_valuesv (GtkTreeStore *tree_store,
 
1384
                                    GtkTreeIter  *iter,
 
1385
                                    GtkTreeIter  *parent,
 
1386
                                    gint          position,
 
1387
                                    gint         *columns,
 
1388
                                    GValue       *values,
 
1389
                                    gint          n_values)
 
1390
{
 
1391
  GtkTreePath *path;
 
1392
  GNode *parent_node;
 
1393
  GNode *new_node;
 
1394
  GtkTreeIter tmp_iter;
 
1395
  gboolean changed = FALSE;
 
1396
  gboolean maybe_need_sort = FALSE;
 
1397
  GtkTreeIterCompareFunc func = NULL;
 
1398
  gint i;
 
1399
 
 
1400
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
1401
 
 
1402
  if (!iter)
 
1403
    iter = &tmp_iter;
 
1404
 
 
1405
  if (parent)
 
1406
    g_return_if_fail (VALID_ITER (parent, tree_store));
 
1407
 
 
1408
  if (parent)
 
1409
    parent_node = parent->user_data;
 
1410
  else
 
1411
    parent_node = tree_store->root;
 
1412
 
 
1413
  tree_store->columns_dirty = TRUE;
 
1414
 
 
1415
  new_node = g_node_new (NULL);
 
1416
 
 
1417
  iter->stamp = tree_store->stamp;
 
1418
  iter->user_data = new_node;
 
1419
  g_node_insert (parent_node, position, new_node);
 
1420
 
 
1421
  func = gtk_tree_store_get_compare_func (tree_store);
 
1422
  if (func != _gtk_tree_data_list_compare_func)
 
1423
    maybe_need_sort = TRUE;
 
1424
 
 
1425
  for (i = 0; i < n_values; i++)
 
1426
    {
 
1427
      changed = gtk_tree_store_real_set_value (tree_store, iter,
 
1428
                                               columns[i], &values[i],
 
1429
                                               FALSE) || changed;
 
1430
 
 
1431
      if (func == _gtk_tree_data_list_compare_func &&
 
1432
          columns[i] == tree_store->sort_column_id)
 
1433
        maybe_need_sort = TRUE;
 
1434
    }
 
1435
 
 
1436
  if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
 
1437
    gtk_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id, FALSE);
 
1438
 
 
1439
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
1440
  gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
 
1441
 
 
1442
  if (parent_node != tree_store->root)
 
1443
    {
 
1444
      if (new_node->prev == NULL && new_node->next == NULL)
 
1445
        {
 
1446
          gtk_tree_path_up (path);
 
1447
          gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
 
1448
        }
 
1449
    }
 
1450
 
 
1451
  gtk_tree_path_free (path);
 
1452
 
 
1453
  validate_tree ((GtkTreeStore *)tree_store);
 
1454
}
 
1455
 
 
1456
/**
 
1457
 * gtk_tree_store_prepend:
 
1458
 * @tree_store: A #GtkTreeStore
 
1459
 * @iter: An unset #GtkTreeIter to set to the prepended row
 
1460
 * @parent: A valid #GtkTreeIter, or %NULL
 
1461
 * 
 
1462
 * Prepends a new row to @tree_store.  If @parent is non-%NULL, then it will prepend
 
1463
 * the new row before the first child of @parent, otherwise it will prepend a row
 
1464
 * to the top level.  @iter will be changed to point to this new row.  The row
 
1465
 * will be empty after this function is called.  To fill in values, you need to
 
1466
 * call gtk_tree_store_set() or gtk_tree_store_set_value().
 
1467
 **/
 
1468
void
 
1469
gtk_tree_store_prepend (GtkTreeStore *tree_store,
 
1470
                        GtkTreeIter  *iter,
 
1471
                        GtkTreeIter  *parent)
 
1472
{
 
1473
  GNode *parent_node;
 
1474
 
 
1475
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
1476
  g_return_if_fail (iter != NULL);
 
1477
  if (parent != NULL)
 
1478
    g_return_if_fail (VALID_ITER (parent, tree_store));
 
1479
 
 
1480
  tree_store->columns_dirty = TRUE;
 
1481
 
 
1482
  if (parent == NULL)
 
1483
    parent_node = tree_store->root;
 
1484
  else
 
1485
    parent_node = parent->user_data;
 
1486
 
 
1487
  if (parent_node->children == NULL)
 
1488
    {
 
1489
      GtkTreePath *path;
 
1490
      
 
1491
      iter->stamp = tree_store->stamp;
 
1492
      iter->user_data = g_node_new (NULL);
 
1493
 
 
1494
      g_node_prepend (parent_node, G_NODE (iter->user_data));
 
1495
 
 
1496
      path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
1497
      gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
 
1498
 
 
1499
      if (parent_node != tree_store->root)
 
1500
        {
 
1501
          gtk_tree_path_up (path);
 
1502
          gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
 
1503
        }
 
1504
      gtk_tree_path_free (path);
 
1505
    }
 
1506
  else
 
1507
    {
 
1508
      gtk_tree_store_insert_after (tree_store, iter, parent, NULL);
 
1509
    }
 
1510
 
 
1511
  validate_tree (tree_store);
 
1512
}
 
1513
 
 
1514
/**
 
1515
 * gtk_tree_store_append:
 
1516
 * @tree_store: A #GtkTreeStore
 
1517
 * @iter: An unset #GtkTreeIter to set to the appended row
 
1518
 * @parent: A valid #GtkTreeIter, or %NULL
 
1519
 * 
 
1520
 * Appends a new row to @tree_store.  If @parent is non-%NULL, then it will append the
 
1521
 * new row after the last child of @parent, otherwise it will append a row to
 
1522
 * the top level.  @iter will be changed to point to this new row.  The row will
 
1523
 * be empty after this function is called.  To fill in values, you need to call
 
1524
 * gtk_tree_store_set() or gtk_tree_store_set_value().
 
1525
 **/
 
1526
void
 
1527
gtk_tree_store_append (GtkTreeStore *tree_store,
 
1528
                       GtkTreeIter  *iter,
 
1529
                       GtkTreeIter  *parent)
 
1530
{
 
1531
  GNode *parent_node;
 
1532
 
 
1533
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
1534
  g_return_if_fail (iter != NULL);
 
1535
  if (parent != NULL)
 
1536
    g_return_if_fail (VALID_ITER (parent, tree_store));
 
1537
 
 
1538
  if (parent == NULL)
 
1539
    parent_node = tree_store->root;
 
1540
  else
 
1541
    parent_node = parent->user_data;
 
1542
 
 
1543
  tree_store->columns_dirty = TRUE;
 
1544
 
 
1545
  if (parent_node->children == NULL)
 
1546
    {
 
1547
      GtkTreePath *path;
 
1548
 
 
1549
      iter->stamp = tree_store->stamp;
 
1550
      iter->user_data = g_node_new (NULL);
 
1551
 
 
1552
      g_node_append (parent_node, G_NODE (iter->user_data));
 
1553
 
 
1554
      path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
1555
      gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
 
1556
 
 
1557
      if (parent_node != tree_store->root)
 
1558
        {
 
1559
          gtk_tree_path_up (path);
 
1560
          gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
 
1561
        }
 
1562
      gtk_tree_path_free (path);
 
1563
    }
 
1564
  else
 
1565
    {
 
1566
      gtk_tree_store_insert_before (tree_store, iter, parent, NULL);
 
1567
    }
 
1568
 
 
1569
  validate_tree (tree_store);
 
1570
}
 
1571
 
 
1572
/**
 
1573
 * gtk_tree_store_is_ancestor:
 
1574
 * @tree_store: A #GtkTreeStore
 
1575
 * @iter: A valid #GtkTreeIter
 
1576
 * @descendant: A valid #GtkTreeIter
 
1577
 * 
 
1578
 * Returns %TRUE if @iter is an ancestor of @descendant.  That is, @iter is the
 
1579
 * parent (or grandparent or great-grandparent) of @descendant.
 
1580
 * 
 
1581
 * Return value: %TRUE, if @iter is an ancestor of @descendant
 
1582
 **/
 
1583
gboolean
 
1584
gtk_tree_store_is_ancestor (GtkTreeStore *tree_store,
 
1585
                            GtkTreeIter  *iter,
 
1586
                            GtkTreeIter  *descendant)
 
1587
{
 
1588
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), FALSE);
 
1589
  g_return_val_if_fail (VALID_ITER (iter, tree_store), FALSE);
 
1590
  g_return_val_if_fail (VALID_ITER (descendant, tree_store), FALSE);
 
1591
 
 
1592
  return g_node_is_ancestor (G_NODE (iter->user_data),
 
1593
                             G_NODE (descendant->user_data));
 
1594
}
 
1595
 
 
1596
 
 
1597
/**
 
1598
 * gtk_tree_store_iter_depth:
 
1599
 * @tree_store: A #GtkTreeStore
 
1600
 * @iter: A valid #GtkTreeIter
 
1601
 * 
 
1602
 * Returns the depth of @iter.  This will be 0 for anything on the root level, 1
 
1603
 * for anything down a level, etc.
 
1604
 * 
 
1605
 * Return value: The depth of @iter
 
1606
 **/
 
1607
gint
 
1608
gtk_tree_store_iter_depth (GtkTreeStore *tree_store,
 
1609
                           GtkTreeIter  *iter)
 
1610
{
 
1611
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), 0);
 
1612
  g_return_val_if_fail (VALID_ITER (iter, tree_store), 0);
 
1613
 
 
1614
  return g_node_depth (G_NODE (iter->user_data)) - 2;
 
1615
}
 
1616
 
 
1617
/* simple ripoff from g_node_traverse_post_order */
 
1618
static gboolean
 
1619
gtk_tree_store_clear_traverse (GNode        *node,
 
1620
                               GtkTreeStore *store)
 
1621
{
 
1622
  GtkTreeIter iter;
 
1623
 
 
1624
  if (node->children)
 
1625
    {
 
1626
      GNode *child;
 
1627
 
 
1628
      child = node->children;
 
1629
      while (child)
 
1630
        {
 
1631
          register GNode *current;
 
1632
 
 
1633
          current = child;
 
1634
          child = current->next;
 
1635
          if (gtk_tree_store_clear_traverse (current, store))
 
1636
            return TRUE;
 
1637
        }
 
1638
 
 
1639
      if (node->parent)
 
1640
        {
 
1641
          iter.stamp = store->stamp;
 
1642
          iter.user_data = node;
 
1643
 
 
1644
          gtk_tree_store_remove (store, &iter);
 
1645
        }
 
1646
    }
 
1647
  else if (node->parent)
 
1648
    {
 
1649
      iter.stamp = store->stamp;
 
1650
      iter.user_data = node;
 
1651
 
 
1652
      gtk_tree_store_remove (store, &iter);
 
1653
    }
 
1654
 
 
1655
  return FALSE;
 
1656
}
 
1657
 
 
1658
static void
 
1659
gtk_tree_store_increment_stamp (GtkTreeStore *tree_store)
 
1660
{
 
1661
  do
 
1662
    {
 
1663
      tree_store->stamp++;
 
1664
    }
 
1665
  while (tree_store->stamp == 0);
 
1666
}
 
1667
 
 
1668
/**
 
1669
 * gtk_tree_store_clear:
 
1670
 * @tree_store: a #GtkTreeStore
 
1671
 * 
 
1672
 * Removes all rows from @tree_store
 
1673
 **/
 
1674
void
 
1675
gtk_tree_store_clear (GtkTreeStore *tree_store)
 
1676
{
 
1677
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
1678
 
 
1679
  gtk_tree_store_clear_traverse (tree_store->root, tree_store);
 
1680
  gtk_tree_store_increment_stamp (tree_store);
 
1681
}
 
1682
 
 
1683
static gboolean
 
1684
gtk_tree_store_iter_is_valid_helper (GtkTreeIter *iter,
 
1685
                                     GNode       *first)
 
1686
{
 
1687
  GNode *node;
 
1688
 
 
1689
  node = first;
 
1690
 
 
1691
  do
 
1692
    {
 
1693
      if (node == iter->user_data)
 
1694
        return TRUE;
 
1695
 
 
1696
      if (node->children)
 
1697
        if (gtk_tree_store_iter_is_valid_helper (iter, node->children))
 
1698
          return TRUE;
 
1699
 
 
1700
      node = node->next;
 
1701
    }
 
1702
  while (node);
 
1703
 
 
1704
  return FALSE;
 
1705
}
 
1706
 
 
1707
/**
 
1708
 * gtk_tree_store_iter_is_valid:
 
1709
 * @tree_store: A #GtkTreeStore.
 
1710
 * @iter: A #GtkTreeIter.
 
1711
 *
 
1712
 * WARNING: This function is slow. Only use it for debugging and/or testing
 
1713
 * purposes.
 
1714
 *
 
1715
 * Checks if the given iter is a valid iter for this #GtkTreeStore.
 
1716
 *
 
1717
 * Return value: %TRUE if the iter is valid, %FALSE if the iter is invalid.
 
1718
 *
 
1719
 * Since: 2.2
 
1720
 **/
 
1721
gboolean
 
1722
gtk_tree_store_iter_is_valid (GtkTreeStore *tree_store,
 
1723
                              GtkTreeIter  *iter)
 
1724
{
 
1725
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), FALSE);
 
1726
  g_return_val_if_fail (iter != NULL, FALSE);
 
1727
 
 
1728
  if (!VALID_ITER (iter, tree_store))
 
1729
    return FALSE;
 
1730
 
 
1731
  return gtk_tree_store_iter_is_valid_helper (iter, tree_store->root);
 
1732
}
 
1733
 
 
1734
/* DND */
 
1735
 
 
1736
 
 
1737
static gboolean real_gtk_tree_store_row_draggable (GtkTreeDragSource *drag_source,
 
1738
                                                   GtkTreePath       *path)
 
1739
{
 
1740
  return TRUE;
 
1741
}
 
1742
               
 
1743
static gboolean
 
1744
gtk_tree_store_drag_data_delete (GtkTreeDragSource *drag_source,
 
1745
                                 GtkTreePath       *path)
 
1746
{
 
1747
  GtkTreeIter iter;
 
1748
 
 
1749
  if (gtk_tree_store_get_iter (GTK_TREE_MODEL (drag_source),
 
1750
                               &iter,
 
1751
                               path))
 
1752
    {
 
1753
      gtk_tree_store_remove (GTK_TREE_STORE (drag_source),
 
1754
                             &iter);
 
1755
      return TRUE;
 
1756
    }
 
1757
  else
 
1758
    {
 
1759
      return FALSE;
 
1760
    }
 
1761
}
 
1762
 
 
1763
static gboolean
 
1764
gtk_tree_store_drag_data_get (GtkTreeDragSource *drag_source,
 
1765
                              GtkTreePath       *path,
 
1766
                              GtkSelectionData  *selection_data)
 
1767
{
 
1768
  /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
 
1769
   * target, because the default handler does it for us, but
 
1770
   * we do anyway for the convenience of someone maybe overriding the
 
1771
   * default handler.
 
1772
   */
 
1773
 
 
1774
  if (gtk_tree_set_row_drag_data (selection_data,
 
1775
                                  GTK_TREE_MODEL (drag_source),
 
1776
                                  path))
 
1777
    {
 
1778
      return TRUE;
 
1779
    }
 
1780
  else
 
1781
    {
 
1782
      /* FIXME handle text targets at least. */
 
1783
    }
 
1784
 
 
1785
  return FALSE;
 
1786
}
 
1787
 
 
1788
static void
 
1789
copy_node_data (GtkTreeStore *tree_store,
 
1790
                GtkTreeIter  *src_iter,
 
1791
                GtkTreeIter  *dest_iter)
 
1792
{
 
1793
  GtkTreeDataList *dl = G_NODE (src_iter->user_data)->data;
 
1794
  GtkTreeDataList *copy_head = NULL;
 
1795
  GtkTreeDataList *copy_prev = NULL;
 
1796
  GtkTreeDataList *copy_iter = NULL;
 
1797
  GtkTreePath *path;
 
1798
  gint col;
 
1799
 
 
1800
  col = 0;
 
1801
  while (dl)
 
1802
    {
 
1803
      copy_iter = _gtk_tree_data_list_node_copy (dl, tree_store->column_headers[col]);
 
1804
 
 
1805
      if (copy_head == NULL)
 
1806
        copy_head = copy_iter;
 
1807
 
 
1808
      if (copy_prev)
 
1809
        copy_prev->next = copy_iter;
 
1810
 
 
1811
      copy_prev = copy_iter;
 
1812
 
 
1813
      dl = dl->next;
 
1814
      ++col;
 
1815
    }
 
1816
 
 
1817
  G_NODE (dest_iter->user_data)->data = copy_head;
 
1818
 
 
1819
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), dest_iter);
 
1820
  gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, dest_iter);
 
1821
  gtk_tree_path_free (path);
 
1822
}
 
1823
 
 
1824
static void
 
1825
recursive_node_copy (GtkTreeStore *tree_store,
 
1826
                     GtkTreeIter  *src_iter,
 
1827
                     GtkTreeIter  *dest_iter)
 
1828
{
 
1829
  GtkTreeIter child;
 
1830
  GtkTreeModel *model;
 
1831
 
 
1832
  model = GTK_TREE_MODEL (tree_store);
 
1833
 
 
1834
  copy_node_data (tree_store, src_iter, dest_iter);
 
1835
 
 
1836
  if (gtk_tree_store_iter_children (model,
 
1837
                                    &child,
 
1838
                                    src_iter))
 
1839
    {
 
1840
      /* Need to create children and recurse. Note our
 
1841
       * dependence on persistent iterators here.
 
1842
       */
 
1843
      do
 
1844
        {
 
1845
          GtkTreeIter copy;
 
1846
 
 
1847
          /* Gee, a really slow algorithm... ;-) FIXME */
 
1848
          gtk_tree_store_append (tree_store,
 
1849
                                 &copy,
 
1850
                                 dest_iter);
 
1851
 
 
1852
          recursive_node_copy (tree_store, &child, &copy);
 
1853
        }
 
1854
      while (gtk_tree_store_iter_next (model, &child));
 
1855
    }
 
1856
}
 
1857
 
 
1858
static gboolean
 
1859
gtk_tree_store_drag_data_received (GtkTreeDragDest   *drag_dest,
 
1860
                                   GtkTreePath       *dest,
 
1861
                                   GtkSelectionData  *selection_data)
 
1862
{
 
1863
  GtkTreeModel *tree_model;
 
1864
  GtkTreeStore *tree_store;
 
1865
  GtkTreeModel *src_model = NULL;
 
1866
  GtkTreePath *src_path = NULL;
 
1867
  gboolean retval = FALSE;
 
1868
 
 
1869
  tree_model = GTK_TREE_MODEL (drag_dest);
 
1870
  tree_store = GTK_TREE_STORE (drag_dest);
 
1871
 
 
1872
  validate_tree (tree_store);
 
1873
 
 
1874
  if (gtk_tree_get_row_drag_data (selection_data,
 
1875
                                  &src_model,
 
1876
                                  &src_path) &&
 
1877
      src_model == tree_model)
 
1878
    {
 
1879
      /* Copy the given row to a new position */
 
1880
      GtkTreeIter src_iter;
 
1881
      GtkTreeIter dest_iter;
 
1882
      GtkTreePath *prev;
 
1883
 
 
1884
      if (!gtk_tree_store_get_iter (src_model,
 
1885
                                    &src_iter,
 
1886
                                    src_path))
 
1887
        {
 
1888
          goto out;
 
1889
        }
 
1890
 
 
1891
      /* Get the path to insert _after_ (dest is the path to insert _before_) */
 
1892
      prev = gtk_tree_path_copy (dest);
 
1893
 
 
1894
      if (!gtk_tree_path_prev (prev))
 
1895
        {
 
1896
          GtkTreeIter dest_parent;
 
1897
          GtkTreePath *parent;
 
1898
          GtkTreeIter *dest_parent_p;
 
1899
 
 
1900
          /* dest was the first spot at the current depth; which means
 
1901
           * we are supposed to prepend.
 
1902
           */
 
1903
 
 
1904
          /* Get the parent, NULL if parent is the root */
 
1905
          dest_parent_p = NULL;
 
1906
          parent = gtk_tree_path_copy (dest);
 
1907
          if (gtk_tree_path_up (parent) &&
 
1908
              gtk_tree_path_get_depth (parent) > 0)
 
1909
            {
 
1910
              gtk_tree_store_get_iter (tree_model,
 
1911
                                       &dest_parent,
 
1912
                                       parent);
 
1913
              dest_parent_p = &dest_parent;
 
1914
            }
 
1915
          gtk_tree_path_free (parent);
 
1916
          parent = NULL;
 
1917
 
 
1918
          gtk_tree_store_prepend (tree_store,
 
1919
                                  &dest_iter,
 
1920
                                  dest_parent_p);
 
1921
 
 
1922
          retval = TRUE;
 
1923
        }
 
1924
      else
 
1925
        {
 
1926
          if (gtk_tree_store_get_iter (tree_model, &dest_iter, prev))
 
1927
            {
 
1928
              GtkTreeIter tmp_iter = dest_iter;
 
1929
 
 
1930
              gtk_tree_store_insert_after (tree_store, &dest_iter, NULL,
 
1931
                                           &tmp_iter);
 
1932
 
 
1933
              retval = TRUE;
 
1934
            }
 
1935
        }
 
1936
 
 
1937
      gtk_tree_path_free (prev);
 
1938
 
 
1939
      /* If we succeeded in creating dest_iter, walk src_iter tree branch,
 
1940
       * duplicating it below dest_iter.
 
1941
       */
 
1942
 
 
1943
      if (retval)
 
1944
        {
 
1945
          recursive_node_copy (tree_store,
 
1946
                               &src_iter,
 
1947
                               &dest_iter);
 
1948
        }
 
1949
    }
 
1950
  else
 
1951
    {
 
1952
      /* FIXME maybe add some data targets eventually, or handle text
 
1953
       * targets in the simple case.
 
1954
       */
 
1955
 
 
1956
    }
 
1957
 
 
1958
 out:
 
1959
 
 
1960
  if (src_path)
 
1961
    gtk_tree_path_free (src_path);
 
1962
 
 
1963
  return retval;
 
1964
}
 
1965
 
 
1966
static gboolean
 
1967
gtk_tree_store_row_drop_possible (GtkTreeDragDest  *drag_dest,
 
1968
                                  GtkTreePath      *dest_path,
 
1969
                                  GtkSelectionData *selection_data)
 
1970
{
 
1971
  GtkTreeModel *src_model = NULL;
 
1972
  GtkTreePath *src_path = NULL;
 
1973
  GtkTreePath *tmp = NULL;
 
1974
  gboolean retval = FALSE;
 
1975
  
 
1976
  /* don't accept drops if the tree has been sorted */
 
1977
  if (GTK_TREE_STORE_IS_SORTED (drag_dest))
 
1978
    return FALSE;
 
1979
 
 
1980
  if (!gtk_tree_get_row_drag_data (selection_data,
 
1981
                                   &src_model,
 
1982
                                   &src_path))
 
1983
    goto out;
 
1984
    
 
1985
  /* can only drag to ourselves */
 
1986
  if (src_model != GTK_TREE_MODEL (drag_dest))
 
1987
    goto out;
 
1988
 
 
1989
  /* Can't drop into ourself. */
 
1990
  if (gtk_tree_path_is_ancestor (src_path,
 
1991
                                 dest_path))
 
1992
    goto out;
 
1993
 
 
1994
  /* Can't drop if dest_path's parent doesn't exist */
 
1995
  {
 
1996
    GtkTreeIter iter;
 
1997
 
 
1998
    if (gtk_tree_path_get_depth (dest_path) > 1)
 
1999
      {
 
2000
        tmp = gtk_tree_path_copy (dest_path);
 
2001
        gtk_tree_path_up (tmp);
 
2002
        
 
2003
        if (!gtk_tree_store_get_iter (GTK_TREE_MODEL (drag_dest),
 
2004
                                      &iter, tmp))
 
2005
          goto out;
 
2006
      }
 
2007
  }
 
2008
  
 
2009
  /* Can otherwise drop anywhere. */
 
2010
  retval = TRUE;
 
2011
 
 
2012
 out:
 
2013
 
 
2014
  if (src_path)
 
2015
    gtk_tree_path_free (src_path);
 
2016
  if (tmp)
 
2017
    gtk_tree_path_free (tmp);
 
2018
 
 
2019
  return retval;
 
2020
}
 
2021
 
 
2022
/* Sorting and reordering */
 
2023
typedef struct _SortTuple
 
2024
{
 
2025
  gint offset;
 
2026
  GNode *node;
 
2027
} SortTuple;
 
2028
 
 
2029
/* Reordering */
 
2030
static gint
 
2031
gtk_tree_store_reorder_func (gconstpointer a,
 
2032
                             gconstpointer b,
 
2033
                             gpointer      user_data)
 
2034
{
 
2035
  SortTuple *a_reorder;
 
2036
  SortTuple *b_reorder;
 
2037
 
 
2038
  a_reorder = (SortTuple *)a;
 
2039
  b_reorder = (SortTuple *)b;
 
2040
 
 
2041
  if (a_reorder->offset < b_reorder->offset)
 
2042
    return -1;
 
2043
  if (a_reorder->offset > b_reorder->offset)
 
2044
    return 1;
 
2045
 
 
2046
  return 0;
 
2047
}
 
2048
 
 
2049
/**
 
2050
 * gtk_tree_store_reorder:
 
2051
 * @tree_store: A #GtkTreeStore.
 
2052
 * @parent: A #GtkTreeIter.
 
2053
 * @new_order: an array of integers mapping the new position of each child
 
2054
 *      to its old position before the re-ordering,
 
2055
 *      i.e. @new_order<literal>[newpos] = oldpos</literal>.
 
2056
 *
 
2057
 * Reorders the children of @parent in @tree_store to follow the order
 
2058
 * indicated by @new_order. Note that this function only works with
 
2059
 * unsorted stores.
 
2060
 *
 
2061
 * Since: 2.2
 
2062
 **/
 
2063
void
 
2064
gtk_tree_store_reorder (GtkTreeStore *tree_store,
 
2065
                        GtkTreeIter  *parent,
 
2066
                        gint         *new_order)
 
2067
{
 
2068
  gint i, length = 0;
 
2069
  GNode *level, *node;
 
2070
  GtkTreePath *path;
 
2071
  SortTuple *sort_array;
 
2072
 
 
2073
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
2074
  g_return_if_fail (!GTK_TREE_STORE_IS_SORTED (tree_store));
 
2075
  g_return_if_fail (parent == NULL || VALID_ITER (parent, tree_store));
 
2076
  g_return_if_fail (new_order != NULL);
 
2077
 
 
2078
  if (!parent)
 
2079
    level = G_NODE (tree_store->root)->children;
 
2080
  else
 
2081
    level = G_NODE (parent->user_data)->children;
 
2082
 
 
2083
  /* count nodes */
 
2084
  node = level;
 
2085
  while (node)
 
2086
    {
 
2087
      length++;
 
2088
      node = node->next;
 
2089
    }
 
2090
 
 
2091
  /* set up sortarray */
 
2092
  sort_array = g_new (SortTuple, length);
 
2093
 
 
2094
  node = level;
 
2095
  for (i = 0; i < length; i++)
 
2096
    {
 
2097
      sort_array[new_order[i]].offset = i;
 
2098
      sort_array[i].node = node;
 
2099
 
 
2100
      node = node->next;
 
2101
    }
 
2102
 
 
2103
  g_qsort_with_data (sort_array,
 
2104
                     length,
 
2105
                     sizeof (SortTuple),
 
2106
                     gtk_tree_store_reorder_func,
 
2107
                     NULL);
 
2108
 
 
2109
  /* fix up level */
 
2110
  for (i = 0; i < length - 1; i++)
 
2111
    {
 
2112
      sort_array[i].node->next = sort_array[i+1].node;
 
2113
      sort_array[i+1].node->prev = sort_array[i].node;
 
2114
    }
 
2115
 
 
2116
  sort_array[length-1].node->next = NULL;
 
2117
  sort_array[0].node->prev = NULL;
 
2118
  if (parent)
 
2119
    G_NODE (parent->user_data)->children = sort_array[0].node;
 
2120
  else
 
2121
    G_NODE (tree_store->root)->children = sort_array[0].node;
 
2122
 
 
2123
  /* emit signal */
 
2124
  if (parent)
 
2125
    path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), parent);
 
2126
  else
 
2127
    path = gtk_tree_path_new ();
 
2128
  gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), path,
 
2129
                                 parent, new_order);
 
2130
  gtk_tree_path_free (path);
 
2131
  g_free (sort_array);
 
2132
}
 
2133
 
 
2134
/**
 
2135
 * gtk_tree_store_swap:
 
2136
 * @tree_store: A #GtkTreeStore.
 
2137
 * @a: A #GtkTreeIter.
 
2138
 * @b: Another #GtkTreeIter.
 
2139
 *
 
2140
 * Swaps @a and @b in the same level of @tree_store. Note that this function
 
2141
 * only works with unsorted stores.
 
2142
 *
 
2143
 * Since: 2.2
 
2144
 **/
 
2145
void
 
2146
gtk_tree_store_swap (GtkTreeStore *tree_store,
 
2147
                     GtkTreeIter  *a,
 
2148
                     GtkTreeIter  *b)
 
2149
{
 
2150
  GNode *tmp, *node_a, *node_b, *parent_node;
 
2151
  GNode *a_prev, *a_next, *b_prev, *b_next;
 
2152
  gint i, a_count, b_count, length, *order;
 
2153
  GtkTreePath *path_a, *path_b;
 
2154
  GtkTreeIter parent;
 
2155
 
 
2156
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
2157
  g_return_if_fail (VALID_ITER (a, tree_store));
 
2158
  g_return_if_fail (VALID_ITER (b, tree_store));
 
2159
 
 
2160
  node_a = G_NODE (a->user_data);
 
2161
  node_b = G_NODE (b->user_data);
 
2162
 
 
2163
  /* basic sanity checking */
 
2164
  if (node_a == node_b)
 
2165
    return;
 
2166
 
 
2167
  path_a = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), a);
 
2168
  path_b = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), b);
 
2169
 
 
2170
  g_return_if_fail (path_a && path_b);
 
2171
 
 
2172
  gtk_tree_path_up (path_a);
 
2173
  gtk_tree_path_up (path_b);
 
2174
 
 
2175
  if (gtk_tree_path_get_depth (path_a) == 0
 
2176
      || gtk_tree_path_get_depth (path_b) == 0)
 
2177
    {
 
2178
      if (gtk_tree_path_get_depth (path_a) != gtk_tree_path_get_depth (path_b))
 
2179
        {
 
2180
          gtk_tree_path_free (path_a);
 
2181
          gtk_tree_path_free (path_b);
 
2182
                                                                                
 
2183
          g_warning ("Given children are not in the same level\n");
 
2184
          return;
 
2185
        }
 
2186
      parent_node = G_NODE (tree_store->root);
 
2187
    }
 
2188
  else
 
2189
    {
 
2190
      if (gtk_tree_path_compare (path_a, path_b))
 
2191
        {
 
2192
          gtk_tree_path_free (path_a);
 
2193
          gtk_tree_path_free (path_b);
 
2194
                                                                                
 
2195
          g_warning ("Given children don't have a common parent\n");
 
2196
          return;
 
2197
        }
 
2198
      gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store), &parent,
 
2199
                               path_a);
 
2200
      parent_node = G_NODE (parent.user_data);
 
2201
    }
 
2202
  gtk_tree_path_free (path_b);
 
2203
 
 
2204
  /* old links which we have to keep around */
 
2205
  a_prev = node_a->prev;
 
2206
  a_next = node_a->next;
 
2207
 
 
2208
  b_prev = node_b->prev;
 
2209
  b_next = node_b->next;
 
2210
 
 
2211
  /* fix up links if the nodes are next to eachother */
 
2212
  if (a_prev == node_b)
 
2213
    a_prev = node_a;
 
2214
  if (a_next == node_b)
 
2215
    a_next = node_a;
 
2216
 
 
2217
  if (b_prev == node_a)
 
2218
    b_prev = node_b;
 
2219
  if (b_next == node_a)
 
2220
    b_next = node_b;
 
2221
 
 
2222
  /* counting nodes */
 
2223
  tmp = parent_node->children;
 
2224
  i = a_count = b_count = 0;
 
2225
  while (tmp)
 
2226
    {
 
2227
      if (tmp == node_a)
 
2228
        a_count = i;
 
2229
      if (tmp == node_b)
 
2230
        b_count = i;
 
2231
 
 
2232
      tmp = tmp->next;
 
2233
      i++;
 
2234
    }
 
2235
  length = i;
 
2236
 
 
2237
  /* hacking the tree */
 
2238
  if (!a_prev)
 
2239
    parent_node->children = node_b;
 
2240
  else
 
2241
    a_prev->next = node_b;
 
2242
 
 
2243
  if (a_next)
 
2244
    a_next->prev = node_b;
 
2245
 
 
2246
  if (!b_prev)
 
2247
    parent_node->children = node_a;
 
2248
  else
 
2249
    b_prev->next = node_a;
 
2250
 
 
2251
  if (b_next)
 
2252
    b_next->prev = node_a;
 
2253
 
 
2254
  node_a->prev = b_prev;
 
2255
  node_a->next = b_next;
 
2256
 
 
2257
  node_b->prev = a_prev;
 
2258
  node_b->next = a_next;
 
2259
 
 
2260
  /* emit signal */
 
2261
  order = g_new (gint, length);
 
2262
  for (i = 0; i < length; i++)
 
2263
    if (i == a_count)
 
2264
      order[i] = b_count;
 
2265
    else if (i == b_count)
 
2266
      order[i] = a_count;
 
2267
    else
 
2268
      order[i] = i;
 
2269
 
 
2270
  gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), path_a,
 
2271
                                 parent_node == tree_store->root 
 
2272
                                 ? NULL : &parent, order);
 
2273
  gtk_tree_path_free (path_a);
 
2274
  g_free (order);
 
2275
}
 
2276
 
 
2277
/* WARNING: this function is *incredibly* fragile. Please smashtest after
 
2278
 * making changes here.
 
2279
 *      -Kris
 
2280
 */
 
2281
static void
 
2282
gtk_tree_store_move (GtkTreeStore *tree_store,
 
2283
                     GtkTreeIter  *iter,
 
2284
                     GtkTreeIter  *position,
 
2285
                     gboolean      before)
 
2286
{
 
2287
  GNode *parent, *node, *a, *b, *tmp, *tmp_a, *tmp_b;
 
2288
  gint old_pos, new_pos, length, i, *order;
 
2289
  GtkTreePath *path = NULL, *tmppath, *pos_path = NULL;
 
2290
  GtkTreeIter parent_iter, dst_a, dst_b;
 
2291
  gint depth = 0;
 
2292
  gboolean handle_b = TRUE;
 
2293
 
 
2294
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
 
2295
  g_return_if_fail (!GTK_TREE_STORE_IS_SORTED (tree_store));
 
2296
  g_return_if_fail (VALID_ITER (iter, tree_store));
 
2297
  if (position)
 
2298
    g_return_if_fail (VALID_ITER (position, tree_store));
 
2299
 
 
2300
  a = b = NULL;
 
2301
 
 
2302
  /* sanity checks */
 
2303
  if (position)
 
2304
    {
 
2305
      path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
2306
      pos_path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store),
 
2307
                                          position);
 
2308
 
 
2309
      /* if before:
 
2310
       *   moving the iter before path or "path + 1" doesn't make sense
 
2311
       * else
 
2312
       *   moving the iter before path or "path - 1" doesn't make sense
 
2313
       */
 
2314
      if (!gtk_tree_path_compare (path, pos_path))
 
2315
        goto free_paths_and_out;
 
2316
 
 
2317
      if (before)
 
2318
        gtk_tree_path_next (path);
 
2319
      else
 
2320
        gtk_tree_path_prev (path);
 
2321
 
 
2322
      if (!gtk_tree_path_compare (path, pos_path))
 
2323
        goto free_paths_and_out;
 
2324
 
 
2325
      if (before)
 
2326
        gtk_tree_path_prev (path);
 
2327
      else
 
2328
        gtk_tree_path_next (path);
 
2329
 
 
2330
      if (gtk_tree_path_get_depth (path) != gtk_tree_path_get_depth (pos_path))
 
2331
        {
 
2332
          g_warning ("Given children are not in the same level\n");
 
2333
 
 
2334
          goto free_paths_and_out;
 
2335
        }
 
2336
 
 
2337
      tmppath = gtk_tree_path_copy (pos_path);
 
2338
      gtk_tree_path_up (path);
 
2339
      gtk_tree_path_up (tmppath);
 
2340
 
 
2341
      if (gtk_tree_path_get_depth (path) > 0 &&
 
2342
          gtk_tree_path_compare (path, tmppath))
 
2343
        {
 
2344
          g_warning ("Given children are not in the same level\n");
 
2345
 
 
2346
          gtk_tree_path_free (tmppath);
 
2347
          goto free_paths_and_out;
 
2348
        }
 
2349
 
 
2350
      gtk_tree_path_free (tmppath);
 
2351
    }
 
2352
 
 
2353
  if (!path)
 
2354
    {
 
2355
      path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
 
2356
      gtk_tree_path_up (path);
 
2357
    }
 
2358
 
 
2359
  depth = gtk_tree_path_get_depth (path);
 
2360
 
 
2361
  if (depth)
 
2362
    {
 
2363
      gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store), 
 
2364
                               &parent_iter, path);
 
2365
 
 
2366
      parent = G_NODE (parent_iter.user_data);
 
2367
    }
 
2368
  else
 
2369
    parent = G_NODE (tree_store->root);
 
2370
 
 
2371
  /* yes, I know that this can be done shorter, but I'm doing it this way
 
2372
   * so the code is also maintainable
 
2373
   */
 
2374
 
 
2375
  if (before && position)
 
2376
    {
 
2377
      b = G_NODE (position->user_data);
 
2378
 
 
2379
      if (gtk_tree_path_get_indices (pos_path)[gtk_tree_path_get_depth (pos_path) - 1] > 0)
 
2380
        {
 
2381
          gtk_tree_path_prev (pos_path);
 
2382
          if (gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store), 
 
2383
                                       &dst_a, pos_path))
 
2384
            a = G_NODE (dst_a.user_data);
 
2385
          else
 
2386
            a = NULL;
 
2387
          gtk_tree_path_next (pos_path);
 
2388
        }
 
2389
 
 
2390
      /* if b is NULL, a is NULL too -- we are at the beginning of the list
 
2391
       * yes and we leak memory here ...
 
2392
       */
 
2393
      g_return_if_fail (b);
 
2394
    }
 
2395
  else if (before && !position)
 
2396
    {
 
2397
      /* move before without position is appending */
 
2398
      a = NULL;
 
2399
      b = NULL;
 
2400
    }
 
2401
  else /* !before */
 
2402
    {
 
2403
      if (position)
 
2404
        a = G_NODE (position->user_data);
 
2405
      else
 
2406
        a = NULL;
 
2407
 
 
2408
      if (position)
 
2409
        {
 
2410
          gtk_tree_path_next (pos_path);
 
2411
          if (gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store), &dst_b, pos_path))
 
2412
             b = G_NODE (dst_b.user_data);
 
2413
          else
 
2414
             b = NULL;
 
2415
          gtk_tree_path_prev (pos_path);
 
2416
        }
 
2417
      else
 
2418
        {
 
2419
          /* move after without position is prepending */
 
2420
          if (depth)
 
2421
            gtk_tree_store_iter_children (GTK_TREE_MODEL (tree_store), &dst_b,
 
2422
                                          &parent_iter);
 
2423
          else
 
2424
            gtk_tree_store_iter_children (GTK_TREE_MODEL (tree_store), &dst_b,
 
2425
                                          NULL);
 
2426
 
 
2427
          b = G_NODE (dst_b.user_data);
 
2428
        }
 
2429
 
 
2430
      /* if a is NULL, b is NULL too -- we are at the end of the list
 
2431
       * yes and we leak memory here ...
 
2432
       */
 
2433
      if (position)
 
2434
        g_return_if_fail (a);
 
2435
    }
 
2436
 
 
2437
  /* counting nodes */
 
2438
  tmp = parent->children;
 
2439
 
 
2440
  length = old_pos = 0;
 
2441
  while (tmp)
 
2442
    {
 
2443
      if (tmp == iter->user_data)
 
2444
        old_pos = length;
 
2445
 
 
2446
      tmp = tmp->next;
 
2447
      length++;
 
2448
    }
 
2449
 
 
2450
  /* remove node from list */
 
2451
  node = G_NODE (iter->user_data);
 
2452
  tmp_a = node->prev;
 
2453
  tmp_b = node->next;
 
2454
 
 
2455
  if (tmp_a)
 
2456
    tmp_a->next = tmp_b;
 
2457
  else
 
2458
    parent->children = tmp_b;
 
2459
 
 
2460
  if (tmp_b)
 
2461
    tmp_b->prev = tmp_a;
 
2462
 
 
2463
  /* and reinsert the node */
 
2464
  if (a)
 
2465
    {
 
2466
      tmp = a->next;
 
2467
 
 
2468
      a->next = node;
 
2469
      node->next = tmp;
 
2470
      node->prev = a;
 
2471
    }
 
2472
  else if (!a && !before)
 
2473
    {
 
2474
      tmp = parent->children;
 
2475
 
 
2476
      node->prev = NULL;
 
2477
      parent->children = node;
 
2478
 
 
2479
      node->next = tmp;
 
2480
      if (tmp) 
 
2481
        tmp->prev = node;
 
2482
 
 
2483
      handle_b = FALSE;
 
2484
    }
 
2485
  else if (!a && before)
 
2486
    {
 
2487
      if (!position)
 
2488
        {
 
2489
          node->parent = NULL;
 
2490
          node->next = node->prev = NULL;
 
2491
 
 
2492
          /* before with sibling = NULL appends */
 
2493
          g_node_insert_before (parent, NULL, node);
 
2494
        }
 
2495
      else
 
2496
        {
 
2497
          node->parent = NULL;
 
2498
          node->next = node->prev = NULL;
 
2499
 
 
2500
          /* after with sibling = NULL prepends */
 
2501
          g_node_insert_after (parent, NULL, node);
 
2502
        }
 
2503
 
 
2504
      handle_b = FALSE;
 
2505
    }
 
2506
 
 
2507
  if (handle_b)
 
2508
    {
 
2509
      if (b)
 
2510
        {
 
2511
          tmp = b->prev;
 
2512
 
 
2513
          b->prev = node;
 
2514
          node->prev = tmp;
 
2515
          node->next = b;
 
2516
        }
 
2517
      else if (!(!a && before)) /* !a && before is completely handled above */
 
2518
        node->next = NULL;
 
2519
    }
 
2520
 
 
2521
  /* emit signal */
 
2522
  if (position)
 
2523
    new_pos = gtk_tree_path_get_indices (pos_path)[gtk_tree_path_get_depth (pos_path)-1];
 
2524
  else if (before)
 
2525
    {
 
2526
      if (depth)
 
2527
        new_pos = gtk_tree_store_iter_n_children (GTK_TREE_MODEL (tree_store),
 
2528
                                                  &parent_iter) - 1;
 
2529
      else
 
2530
        new_pos = gtk_tree_store_iter_n_children (GTK_TREE_MODEL (tree_store),
 
2531
                                                  NULL) - 1;
 
2532
    }
 
2533
  else
 
2534
    new_pos = 0;
 
2535
 
 
2536
  if (new_pos > old_pos)
 
2537
    {
 
2538
      if (before && position)
 
2539
        new_pos--;
 
2540
    }
 
2541
  else
 
2542
    {
 
2543
      if (!before && position)
 
2544
        new_pos++;
 
2545
    }
 
2546
 
 
2547
  order = g_new (gint, length);
 
2548
  if (new_pos > old_pos)
 
2549
    {
 
2550
      for (i = 0; i < length; i++)
 
2551
        if (i < old_pos)
 
2552
          order[i] = i;
 
2553
        else if (i >= old_pos && i < new_pos)
 
2554
          order[i] = i + 1;
 
2555
        else if (i == new_pos)
 
2556
          order[i] = old_pos;
 
2557
        else
 
2558
          order[i] = i;
 
2559
    }
 
2560
  else
 
2561
    {
 
2562
      for (i = 0; i < length; i++)
 
2563
        if (i == new_pos)
 
2564
          order[i] = old_pos;
 
2565
        else if (i > new_pos && i <= old_pos)
 
2566
          order[i] = i - 1;
 
2567
        else
 
2568
          order[i] = i;
 
2569
    }
 
2570
 
 
2571
  if (depth)
 
2572
    {
 
2573
      tmppath = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), 
 
2574
                                         &parent_iter);
 
2575
      gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
 
2576
                                     tmppath, &parent_iter, order);
 
2577
    }
 
2578
  else
 
2579
    {
 
2580
      tmppath = gtk_tree_path_new ();
 
2581
      gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
 
2582
                                     tmppath, NULL, order);
 
2583
    }
 
2584
 
 
2585
  gtk_tree_path_free (tmppath);
 
2586
  gtk_tree_path_free (path);
 
2587
  if (position)
 
2588
    gtk_tree_path_free (pos_path);
 
2589
  g_free (order);
 
2590
 
 
2591
  return;
 
2592
 
 
2593
free_paths_and_out:
 
2594
  gtk_tree_path_free (path);
 
2595
  gtk_tree_path_free (pos_path);
 
2596
}
 
2597
 
 
2598
/**
 
2599
 * gtk_tree_store_move_before:
 
2600
 * @tree_store: A #GtkTreeStore.
 
2601
 * @iter: A #GtkTreeIter.
 
2602
 * @position: A #GtkTreeIter or %NULL.
 
2603
 *
 
2604
 * Moves @iter in @tree_store to the position before @position. @iter and
 
2605
 * @position should be in the same level. Note that this function only
 
2606
 * works with unsorted stores. If @position is %NULL, @iter will be
 
2607
 * moved to the end of the level.
 
2608
 *
 
2609
 * Since: 2.2
 
2610
 **/
 
2611
void
 
2612
gtk_tree_store_move_before (GtkTreeStore *tree_store,
 
2613
                            GtkTreeIter  *iter,
 
2614
                            GtkTreeIter  *position)
 
2615
{
 
2616
  gtk_tree_store_move (tree_store, iter, position, TRUE);
 
2617
}
 
2618
 
 
2619
/**
 
2620
 * gtk_tree_store_move_after:
 
2621
 * @tree_store: A #GtkTreeStore.
 
2622
 * @iter: A #GtkTreeIter.
 
2623
 * @position: A #GtkTreeIter.
 
2624
 *
 
2625
 * Moves @iter in @tree_store to the position after @position. @iter and
 
2626
 * @position should be in the same level. Note that this function only
 
2627
 * works with unsorted stores. If @position is %NULL, @iter will be moved
 
2628
 * to the start of the level.
 
2629
 *
 
2630
 * Since: 2.2
 
2631
 **/
 
2632
void
 
2633
gtk_tree_store_move_after (GtkTreeStore *tree_store,
 
2634
                           GtkTreeIter  *iter,
 
2635
                           GtkTreeIter  *position)
 
2636
{
 
2637
  gtk_tree_store_move (tree_store, iter, position, FALSE);
 
2638
}
 
2639
 
 
2640
/* Sorting */
 
2641
static gint
 
2642
gtk_tree_store_compare_func (gconstpointer a,
 
2643
                             gconstpointer b,
 
2644
                             gpointer      user_data)
 
2645
{
 
2646
  GtkTreeStore *tree_store = user_data;
 
2647
  GNode *node_a;
 
2648
  GNode *node_b;
 
2649
  GtkTreeIterCompareFunc func;
 
2650
  gpointer data;
 
2651
 
 
2652
  GtkTreeIter iter_a;
 
2653
  GtkTreeIter iter_b;
 
2654
  gint retval;
 
2655
 
 
2656
  if (tree_store->sort_column_id != -1)
 
2657
    {
 
2658
      GtkTreeDataSortHeader *header;
 
2659
 
 
2660
      header = _gtk_tree_data_list_get_header (tree_store->sort_list,
 
2661
                                               tree_store->sort_column_id);
 
2662
      g_return_val_if_fail (header != NULL, 0);
 
2663
      g_return_val_if_fail (header->func != NULL, 0);
 
2664
 
 
2665
      func = header->func;
 
2666
      data = header->data;
 
2667
    }
 
2668
  else
 
2669
    {
 
2670
      g_return_val_if_fail (tree_store->default_sort_func != NULL, 0);
 
2671
      func = tree_store->default_sort_func;
 
2672
      data = tree_store->default_sort_data;
 
2673
    }
 
2674
 
 
2675
  node_a = ((SortTuple *) a)->node;
 
2676
  node_b = ((SortTuple *) b)->node;
 
2677
 
 
2678
  iter_a.stamp = tree_store->stamp;
 
2679
  iter_a.user_data = node_a;
 
2680
  iter_b.stamp = tree_store->stamp;
 
2681
  iter_b.user_data = node_b;
 
2682
 
 
2683
  retval = (* func) (GTK_TREE_MODEL (user_data), &iter_a, &iter_b, data);
 
2684
 
 
2685
  if (tree_store->order == GTK_SORT_DESCENDING)
 
2686
    {
 
2687
      if (retval > 0)
 
2688
        retval = -1;
 
2689
      else if (retval < 0)
 
2690
        retval = 1;
 
2691
    }
 
2692
  return retval;
 
2693
}
 
2694
 
 
2695
static void
 
2696
gtk_tree_store_sort_helper (GtkTreeStore *tree_store,
 
2697
                            GNode        *parent,
 
2698
                            gboolean      recurse)
 
2699
{
 
2700
  GtkTreeIter iter;
 
2701
  GArray *sort_array;
 
2702
  GNode *node;
 
2703
  GNode *tmp_node;
 
2704
  gint list_length;
 
2705
  gint i;
 
2706
  gint *new_order;
 
2707
  GtkTreePath *path;
 
2708
 
 
2709
  node = parent->children;
 
2710
  if (node == NULL || node->next == NULL)
 
2711
    {
 
2712
      if (recurse && node && node->children)
 
2713
        gtk_tree_store_sort_helper (tree_store, node, TRUE);
 
2714
 
 
2715
      return;
 
2716
    }
 
2717
 
 
2718
  list_length = 0;
 
2719
  for (tmp_node = node; tmp_node; tmp_node = tmp_node->next)
 
2720
    list_length++;
 
2721
 
 
2722
  sort_array = g_array_sized_new (FALSE, FALSE, sizeof (SortTuple), list_length);
 
2723
 
 
2724
  i = 0;
 
2725
  for (tmp_node = node; tmp_node; tmp_node = tmp_node->next)
 
2726
    {
 
2727
      SortTuple tuple;
 
2728
 
 
2729
      tuple.offset = i;
 
2730
      tuple.node = tmp_node;
 
2731
      g_array_append_val (sort_array, tuple);
 
2732
      i++;
 
2733
    }
 
2734
 
 
2735
  /* Sort the array */
 
2736
  g_array_sort_with_data (sort_array, gtk_tree_store_compare_func, tree_store);
 
2737
 
 
2738
  for (i = 0; i < list_length - 1; i++)
 
2739
    {
 
2740
      g_array_index (sort_array, SortTuple, i).node->next =
 
2741
        g_array_index (sort_array, SortTuple, i + 1).node;
 
2742
      g_array_index (sort_array, SortTuple, i + 1).node->prev =
 
2743
        g_array_index (sort_array, SortTuple, i).node;
 
2744
    }
 
2745
  g_array_index (sort_array, SortTuple, list_length - 1).node->next = NULL;
 
2746
  g_array_index (sort_array, SortTuple, 0).node->prev = NULL;
 
2747
  parent->children = g_array_index (sort_array, SortTuple, 0).node;
 
2748
 
 
2749
  /* Let the world know about our new order */
 
2750
  new_order = g_new (gint, list_length);
 
2751
  for (i = 0; i < list_length; i++)
 
2752
    new_order[i] = g_array_index (sort_array, SortTuple, i).offset;
 
2753
 
 
2754
  iter.stamp = tree_store->stamp;
 
2755
  iter.user_data = parent;
 
2756
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), &iter);
 
2757
  gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
 
2758
                                 path, &iter, new_order);
 
2759
  gtk_tree_path_free (path);
 
2760
  g_free (new_order);
 
2761
  g_array_free (sort_array, TRUE);
 
2762
 
 
2763
  if (recurse)
 
2764
    {
 
2765
      for (tmp_node = parent->children; tmp_node; tmp_node = tmp_node->next)
 
2766
        {
 
2767
          if (tmp_node->children)
 
2768
            gtk_tree_store_sort_helper (tree_store, tmp_node, TRUE);
 
2769
        }
 
2770
    }
 
2771
}
 
2772
 
 
2773
static void
 
2774
gtk_tree_store_sort (GtkTreeStore *tree_store)
 
2775
{
 
2776
  if (!GTK_TREE_STORE_IS_SORTED (tree_store))
 
2777
    return;
 
2778
 
 
2779
  if (tree_store->sort_column_id != -1)
 
2780
    {
 
2781
      GtkTreeDataSortHeader *header = NULL;
 
2782
 
 
2783
      header = _gtk_tree_data_list_get_header (tree_store->sort_list, 
 
2784
                                               tree_store->sort_column_id);
 
2785
 
 
2786
      /* We want to make sure that we have a function */
 
2787
      g_return_if_fail (header != NULL);
 
2788
      g_return_if_fail (header->func != NULL);
 
2789
    }
 
2790
  else
 
2791
    {
 
2792
      g_return_if_fail (tree_store->default_sort_func != NULL);
 
2793
    }
 
2794
 
 
2795
  gtk_tree_store_sort_helper (tree_store, G_NODE (tree_store->root), TRUE);
 
2796
}
 
2797
 
 
2798
static void
 
2799
gtk_tree_store_sort_iter_changed (GtkTreeStore *tree_store,
 
2800
                                  GtkTreeIter  *iter,
 
2801
                                  gint          column,
 
2802
                                  gboolean      emit_signal)
 
2803
{
 
2804
  GNode *prev = NULL;
 
2805
  GNode *next = NULL;
 
2806
  GNode *node;
 
2807
  GtkTreePath *tmp_path;
 
2808
  GtkTreeIter tmp_iter;
 
2809
  gint cmp_a = 0;
 
2810
  gint cmp_b = 0;
 
2811
  gint i;
 
2812
  gint old_location;
 
2813
  gint new_location;
 
2814
  gint *new_order;
 
2815
  gint length;
 
2816
  GtkTreeIterCompareFunc func;
 
2817
  gpointer data;
 
2818
 
 
2819
  g_return_if_fail (G_NODE (iter->user_data)->parent != NULL);
 
2820
 
 
2821
  tmp_iter.stamp = tree_store->stamp;
 
2822
  if (tree_store->sort_column_id != -1)
 
2823
    {
 
2824
      GtkTreeDataSortHeader *header;
 
2825
      header = _gtk_tree_data_list_get_header (tree_store->sort_list,
 
2826
                                               tree_store->sort_column_id);
 
2827
      g_return_if_fail (header != NULL);
 
2828
      g_return_if_fail (header->func != NULL);
 
2829
      func = header->func;
 
2830
      data = header->data;
 
2831
    }
 
2832
  else
 
2833
    {
 
2834
      g_return_if_fail (tree_store->default_sort_func != NULL);
 
2835
      func = tree_store->default_sort_func;
 
2836
      data = tree_store->default_sort_data;
 
2837
    }
 
2838
 
 
2839
  /* If it's the built in function, we don't sort. */
 
2840
  if (func == _gtk_tree_data_list_compare_func &&
 
2841
      tree_store->sort_column_id != column)
 
2842
    return;
 
2843
 
 
2844
  old_location = 0;
 
2845
  node = G_NODE (iter->user_data)->parent->children;
 
2846
  /* First we find the iter, its prev, and its next */
 
2847
  while (node)
 
2848
    {
 
2849
      if (node == G_NODE (iter->user_data))
 
2850
        break;
 
2851
      old_location++;
 
2852
      node = node->next;
 
2853
    }
 
2854
  g_assert (node != NULL);
 
2855
 
 
2856
  prev = node->prev;
 
2857
  next = node->next;
 
2858
 
 
2859
  /* Check the common case, where we don't need to sort it moved. */
 
2860
  if (prev != NULL)
 
2861
    {
 
2862
      tmp_iter.user_data = prev;
 
2863
      cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data);
 
2864
    }
 
2865
 
 
2866
  if (next != NULL)
 
2867
    {
 
2868
      tmp_iter.user_data = next;
 
2869
      cmp_b = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data);
 
2870
    }
 
2871
 
 
2872
  if (tree_store->order == GTK_SORT_DESCENDING)
 
2873
    {
 
2874
      if (cmp_a < 0)
 
2875
        cmp_a = 1;
 
2876
      else if (cmp_a > 0)
 
2877
        cmp_a = -1;
 
2878
 
 
2879
      if (cmp_b < 0)
 
2880
        cmp_b = 1;
 
2881
      else if (cmp_b > 0)
 
2882
        cmp_b = -1;
 
2883
    }
 
2884
 
 
2885
  if (prev == NULL && cmp_b <= 0)
 
2886
    return;
 
2887
  else if (next == NULL && cmp_a <= 0)
 
2888
    return;
 
2889
  else if (prev != NULL && next != NULL &&
 
2890
           cmp_a <= 0 && cmp_b <= 0)
 
2891
    return;
 
2892
 
 
2893
  /* We actually need to sort it */
 
2894
  /* First, remove the old link. */
 
2895
 
 
2896
  if (prev)
 
2897
    prev->next = next;
 
2898
  else
 
2899
    node->parent->children = next;
 
2900
 
 
2901
  if (next)
 
2902
    next->prev = prev;
 
2903
 
 
2904
  node->prev = NULL;
 
2905
  node->next = NULL;
 
2906
 
 
2907
  /* FIXME: as an optimization, we can potentially start at next */
 
2908
  prev = NULL;
 
2909
  node = node->parent->children;
 
2910
  new_location = 0;
 
2911
  tmp_iter.user_data = node;
 
2912
  if (tree_store->order == GTK_SORT_DESCENDING)
 
2913
    cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data);
 
2914
  else
 
2915
    cmp_a = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data);
 
2916
 
 
2917
  while ((node->next) && (cmp_a > 0))
 
2918
    {
 
2919
      prev = node;
 
2920
      node = node->next;
 
2921
      new_location++;
 
2922
      tmp_iter.user_data = node;
 
2923
      if (tree_store->order == GTK_SORT_DESCENDING)
 
2924
        cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data);
 
2925
      else
 
2926
        cmp_a = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data);
 
2927
    }
 
2928
 
 
2929
  if ((!node->next) && (cmp_a > 0))
 
2930
    {
 
2931
      new_location++;
 
2932
      node->next = G_NODE (iter->user_data);
 
2933
      node->next->prev = node;
 
2934
    }
 
2935
  else if (prev)
 
2936
    {
 
2937
      prev->next = G_NODE (iter->user_data);
 
2938
      prev->next->prev = prev;
 
2939
      G_NODE (iter->user_data)->next = node;
 
2940
      G_NODE (iter->user_data)->next->prev = G_NODE (iter->user_data);
 
2941
    }
 
2942
  else
 
2943
    {
 
2944
      G_NODE (iter->user_data)->next = G_NODE (iter->user_data)->parent->children;
 
2945
      G_NODE (iter->user_data)->next->prev = G_NODE (iter->user_data);
 
2946
      G_NODE (iter->user_data)->parent->children = G_NODE (iter->user_data);
 
2947
    }
 
2948
 
 
2949
  if (!emit_signal)
 
2950
    return;
 
2951
 
 
2952
  /* Emit the reordered signal. */
 
2953
  length = g_node_n_children (node->parent);
 
2954
  new_order = g_new (int, length);
 
2955
  if (old_location < new_location)
 
2956
    for (i = 0; i < length; i++)
 
2957
      {
 
2958
        if (i < old_location ||
 
2959
            i > new_location)
 
2960
          new_order[i] = i;
 
2961
        else if (i >= old_location &&
 
2962
                 i < new_location)
 
2963
          new_order[i] = i + 1;
 
2964
        else if (i == new_location)
 
2965
          new_order[i] = old_location;
 
2966
      }
 
2967
  else
 
2968
    for (i = 0; i < length; i++)
 
2969
      {
 
2970
        if (i < new_location ||
 
2971
            i > old_location)
 
2972
          new_order[i] = i;
 
2973
        else if (i > new_location &&
 
2974
                 i <= old_location)
 
2975
          new_order[i] = i - 1;
 
2976
        else if (i == new_location)
 
2977
          new_order[i] = old_location;
 
2978
      }
 
2979
 
 
2980
  tmp_iter.user_data = node->parent;
 
2981
  tmp_path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), &tmp_iter);
 
2982
 
 
2983
  gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
 
2984
                                 tmp_path, &tmp_iter,
 
2985
                                 new_order);
 
2986
 
 
2987
  gtk_tree_path_free (tmp_path);
 
2988
  g_free (new_order);
 
2989
}
 
2990
 
 
2991
 
 
2992
static gboolean
 
2993
gtk_tree_store_get_sort_column_id (GtkTreeSortable  *sortable,
 
2994
                                   gint             *sort_column_id,
 
2995
                                   GtkSortType      *order)
 
2996
{
 
2997
  GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
 
2998
 
 
2999
  if (sort_column_id)
 
3000
    * sort_column_id = tree_store->sort_column_id;
 
3001
  if (order)
 
3002
    * order = tree_store->order;
 
3003
 
 
3004
  if (tree_store->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID ||
 
3005
      tree_store->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
 
3006
    return FALSE;
 
3007
 
 
3008
  return TRUE;
 
3009
}
 
3010
 
 
3011
static void
 
3012
gtk_tree_store_set_sort_column_id (GtkTreeSortable  *sortable,
 
3013
                                   gint              sort_column_id,
 
3014
                                   GtkSortType       order)
 
3015
{
 
3016
  GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
 
3017
 
 
3018
  
 
3019
  if ((tree_store->sort_column_id == sort_column_id) &&
 
3020
      (tree_store->order == order))
 
3021
    return;
 
3022
 
 
3023
  if (sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
 
3024
    {
 
3025
      if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
 
3026
        {
 
3027
          GtkTreeDataSortHeader *header = NULL;
 
3028
 
 
3029
          header = _gtk_tree_data_list_get_header (tree_store->sort_list, 
 
3030
                                                   sort_column_id);
 
3031
 
 
3032
          /* We want to make sure that we have a function */
 
3033
          g_return_if_fail (header != NULL);
 
3034
          g_return_if_fail (header->func != NULL);
 
3035
        }
 
3036
      else
 
3037
        {
 
3038
          g_return_if_fail (tree_store->default_sort_func != NULL);
 
3039
        }
 
3040
    }
 
3041
 
 
3042
  tree_store->sort_column_id = sort_column_id;
 
3043
  tree_store->order = order;
 
3044
 
 
3045
  gtk_tree_sortable_sort_column_changed (sortable);
 
3046
 
 
3047
  gtk_tree_store_sort (tree_store);
 
3048
}
 
3049
 
 
3050
static void
 
3051
gtk_tree_store_set_sort_func (GtkTreeSortable        *sortable,
 
3052
                              gint                    sort_column_id,
 
3053
                              GtkTreeIterCompareFunc  func,
 
3054
                              gpointer                data,
 
3055
                              GtkDestroyNotify        destroy)
 
3056
{
 
3057
  GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
 
3058
 
 
3059
  tree_store->sort_list = _gtk_tree_data_list_set_header (tree_store->sort_list, 
 
3060
                                                          sort_column_id, 
 
3061
                                                          func, data, destroy);
 
3062
 
 
3063
  if (tree_store->sort_column_id == sort_column_id)
 
3064
    gtk_tree_store_sort (tree_store);
 
3065
}
 
3066
 
 
3067
static void
 
3068
gtk_tree_store_set_default_sort_func (GtkTreeSortable        *sortable,
 
3069
                                      GtkTreeIterCompareFunc  func,
 
3070
                                      gpointer                data,
 
3071
                                      GtkDestroyNotify        destroy)
 
3072
{
 
3073
  GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
 
3074
 
 
3075
  if (tree_store->default_sort_destroy)
 
3076
    {
 
3077
      GtkDestroyNotify d = tree_store->default_sort_destroy;
 
3078
 
 
3079
      tree_store->default_sort_destroy = NULL;
 
3080
      d (tree_store->default_sort_data);
 
3081
    }
 
3082
 
 
3083
  tree_store->default_sort_func = func;
 
3084
  tree_store->default_sort_data = data;
 
3085
  tree_store->default_sort_destroy = destroy;
 
3086
 
 
3087
  if (tree_store->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
 
3088
    gtk_tree_store_sort (tree_store);
 
3089
}
 
3090
 
 
3091
static gboolean
 
3092
gtk_tree_store_has_default_sort_func (GtkTreeSortable *sortable)
 
3093
{
 
3094
  GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
 
3095
 
 
3096
  return (tree_store->default_sort_func != NULL);
 
3097
}
 
3098
 
 
3099
static void
 
3100
validate_gnode (GNode* node)
 
3101
{
 
3102
  GNode *iter;
 
3103
 
 
3104
  iter = node->children;
 
3105
  while (iter != NULL)
 
3106
    {
 
3107
      g_assert (iter->parent == node);
 
3108
      if (iter->prev)
 
3109
        g_assert (iter->prev->next == iter);
 
3110
      validate_gnode (iter);
 
3111
      iter = iter->next;
 
3112
    }
 
3113
}
 
3114
 
 
3115
#define __GTK_TREE_STORE_C__
 
3116
#include "gtkaliasdef.c"