]> Pileus Git - ~andy/gtk/blob - gtk/gtkfilesystemmodel.c
Fixes #136082 and #135265, patch by Morten Welinder.
[~andy/gtk] / gtk / gtkfilesystemmodel.c
1 /* GTK - The GIMP Toolkit
2  * gtkfilesystemmodel.c: GtkTreeModel wrapping a GtkFileSystem
3  * Copyright (C) 2003, Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22 #include <string.h>
23
24 #include "gtkfilesystemmodel.h"
25 #include "gtkfilesystem.h"
26 #include "gtkintl.h"
27 #include "gtktreednd.h"
28 #include "gtktreemodel.h"
29
30 typedef struct _GtkFileSystemModelClass GtkFileSystemModelClass;
31 typedef struct _FileModelNode           FileModelNode;
32
33 #define GTK_FILE_SYSTEM_MODEL_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SYSTEM_MODEL, GtkFileSystemModelClass))
34 #define GTK_IS_FILE_SYSTEM_MODEL_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SYSTEM_MODEL))
35 #define GTK_FILE_SYSTEM_MODEL_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_SYSTEM_MODEL, GtkFileSystemModelClass))
36
37 struct _GtkFileSystemModelClass
38 {
39   GObjectClass parent_class;
40 };
41
42 struct _GtkFileSystemModel
43 {
44   GObject parent_instance;
45
46   GtkFileSystem  *file_system;
47   GtkFileInfoType types;
48   FileModelNode  *roots;
49   GtkFileFolder  *root_folder;
50   GtkFilePath    *root_path;
51
52   GtkFileSystemModelFilter filter_func;
53   gpointer filter_data;
54
55   GSList *idle_clears;
56   GSource *idle_clear_source;
57
58   gushort max_depth;
59   
60   guint show_hidden : 1;
61   guint show_folders : 1;
62   guint show_files : 1;
63   guint folders_only : 1;
64   guint has_editable : 1;
65 };
66
67 struct _FileModelNode
68 {
69   GtkFilePath *path;
70   FileModelNode *next;
71
72   GtkFileInfo *info;
73   GtkFileFolder *folder;
74   
75   FileModelNode *children;
76   FileModelNode *parent;
77   GtkFileSystemModel *model;
78
79   guint ref_count;
80   guint n_referenced_children;
81
82   gushort depth;
83
84   guint has_dummy : 1;
85   guint is_dummy : 1;
86   guint is_visible : 1;
87   guint loaded : 1;
88   guint idle_clear : 1;
89 };
90
91 static void gtk_file_system_model_class_init   (GtkFileSystemModelClass *class);
92 static void gtk_file_system_model_iface_init   (GtkTreeModelIface       *iface);
93 static void gtk_file_system_model_init         (GtkFileSystemModel      *model);
94 static void gtk_file_system_model_finalize     (GObject                 *object);
95
96 static void drag_source_iface_init (GtkTreeDragSourceIface *iface);
97
98 static GtkTreeModelFlags gtk_file_system_model_get_flags       (GtkTreeModel *tree_model);
99 static gint              gtk_file_system_model_get_n_columns   (GtkTreeModel *tree_model);
100 static GType             gtk_file_system_model_get_column_type (GtkTreeModel *tree_model,
101                                                                 gint          index);
102 static gboolean          gtk_file_system_model_get_iter        (GtkTreeModel *tree_model,
103                                                                 GtkTreeIter  *iter,
104                                                                 GtkTreePath  *path);
105 static GtkTreePath *     gtk_file_system_model_get_path        (GtkTreeModel *tree_model,
106                                                                 GtkTreeIter  *iter);
107 static void              gtk_file_system_model_get_value       (GtkTreeModel *tree_model,
108                                                                 GtkTreeIter  *iter,
109                                                                 gint          column,
110                                                                 GValue       *value);
111 static gboolean          gtk_file_system_model_iter_next       (GtkTreeModel *tree_model,
112                                                                 GtkTreeIter  *iter);
113 static gboolean          gtk_file_system_model_iter_children   (GtkTreeModel *tree_model,
114                                                                 GtkTreeIter  *iter,
115                                                                 GtkTreeIter  *parent);
116 static gboolean          gtk_file_system_model_iter_has_child  (GtkTreeModel *tree_model,
117                                                                 GtkTreeIter  *iter);
118 static gint              gtk_file_system_model_iter_n_children (GtkTreeModel *tree_model,
119                                                                 GtkTreeIter  *iter);
120 static gboolean          gtk_file_system_model_iter_nth_child  (GtkTreeModel *tree_model,
121                                                                 GtkTreeIter  *iter,
122                                                                 GtkTreeIter  *parent,
123                                                                 gint          n);
124 static gboolean          gtk_file_system_model_iter_parent     (GtkTreeModel *tree_model,
125                                                                 GtkTreeIter  *iter,
126                                                                 GtkTreeIter  *child);
127 static void              gtk_file_system_model_ref_node        (GtkTreeModel *tree_model,
128                                                                 GtkTreeIter  *iter);
129 static void              gtk_file_system_model_unref_node      (GtkTreeModel *tree_model,
130                                                                 GtkTreeIter  *iter);
131
132 static gboolean drag_source_row_draggable (GtkTreeDragSource   *drag_source,
133                                            GtkTreePath         *path);
134 static gboolean drag_source_drag_data_get (GtkTreeDragSource   *drag_source,
135                                            GtkTreePath         *path,
136                                            GtkSelectionData    *selection_data);
137
138 static FileModelNode *file_model_node_new        (GtkFileSystemModel *model,
139                                                   const GtkFilePath  *path);
140 static void           file_model_node_free       (FileModelNode      *node);
141 static void           file_model_node_ref        (FileModelNode      *node);
142 static void           file_model_node_unref      (GtkFileSystemModel *model,
143                                                   FileModelNode      *node);
144
145 static void file_model_node_idle_clear        (FileModelNode *node);
146 static void file_model_node_idle_clear_cancel (FileModelNode *node);
147 static void file_model_node_child_unref       (FileModelNode *parent);
148
149 static const GtkFileInfo *file_model_node_get_info     (GtkFileSystemModel *model,
150                                                         FileModelNode      *node);
151 static gboolean           file_model_node_is_visible   (GtkFileSystemModel *model,
152                                                         FileModelNode      *node);
153 static void               file_model_node_clear        (GtkFileSystemModel *model,
154                                                         FileModelNode      *node);
155 static FileModelNode *    file_model_node_get_children (GtkFileSystemModel *model,
156                                                         FileModelNode      *node);
157
158 #if 0
159 static void roots_changed_callback (GtkFileSystem      *file_system,
160                                     GtkFileSystemModel *model);
161 #endif
162                                     
163 static void deleted_callback       (GtkFileFolder *folder,
164                                     FileModelNode *node);
165 static void files_added_callback   (GtkFileFolder *folder,
166                                     GSList        *paths,
167                                     FileModelNode *node);
168 static void files_changed_callback (GtkFileFolder *folder,
169                                     GSList        *paths,
170                                     FileModelNode *node);
171 static void files_removed_callback (GtkFileFolder *folder,
172                                     GSList        *paths,
173                                     FileModelNode *node);
174
175 static void root_deleted_callback       (GtkFileFolder      *folder,
176                                          GtkFileSystemModel *model);
177 static void root_files_added_callback   (GtkFileFolder      *folder,
178                                          GSList             *paths,
179                                          GtkFileSystemModel *model);
180 static void root_files_changed_callback (GtkFileFolder      *folder,
181                                          GSList             *paths,
182                                          GtkFileSystemModel *model);
183 static void root_files_removed_callback (GtkFileFolder      *folder,
184                                          GSList             *paths,
185                                          GtkFileSystemModel *model);
186
187 static GObjectClass *parent_class = NULL;
188
189 GType
190 _gtk_file_system_model_get_type (void)
191 {
192   static GType file_system_model_type = 0;
193
194   if (!file_system_model_type)
195     {
196       static const GTypeInfo file_system_model_info =
197       {
198         sizeof (GtkFileSystemModelClass),
199         NULL,           /* base_init */
200         NULL,           /* base_finalize */
201         (GClassInitFunc) gtk_file_system_model_class_init,
202         NULL,           /* class_finalize */
203         NULL,           /* class_data */
204         sizeof (GtkFileSystemModel),
205         0,              /* n_preallocs */
206         (GInstanceInitFunc) gtk_file_system_model_init,
207       };
208       
209       static const GInterfaceInfo file_system_info =
210       {
211         (GInterfaceInitFunc) gtk_file_system_model_iface_init, /* interface_init */
212         NULL,                                                  /* interface_finalize */
213         NULL                                                   /* interface_data */
214       };
215
216       static const GInterfaceInfo drag_source_info =
217       {
218         (GInterfaceInitFunc) drag_source_iface_init,           /* interface_init */
219         NULL,                                                  /* interface_finalize */
220         NULL                                                   /* interface_data */
221       };
222
223       file_system_model_type = g_type_register_static (G_TYPE_OBJECT,
224                                                       "GtkFileSystemModel",
225                                                       &file_system_model_info, 0);
226       g_type_add_interface_static (file_system_model_type,
227                                    GTK_TYPE_TREE_MODEL,
228                                    &file_system_info);
229       g_type_add_interface_static (file_system_model_type,
230                                    GTK_TYPE_TREE_DRAG_SOURCE,
231                                    &drag_source_info);
232     }
233
234   return file_system_model_type;
235 }
236
237 static void
238 gtk_file_system_model_class_init (GtkFileSystemModelClass *class)
239 {
240   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
241
242   parent_class = g_type_class_peek_parent (class);
243
244   gobject_class->finalize = gtk_file_system_model_finalize;
245 }
246
247 static void
248 gtk_file_system_model_iface_init (GtkTreeModelIface *iface)
249 {
250   iface->get_flags =       gtk_file_system_model_get_flags;
251   iface->get_n_columns =   gtk_file_system_model_get_n_columns;
252   iface->get_column_type = gtk_file_system_model_get_column_type;
253   iface->get_iter =        gtk_file_system_model_get_iter;
254   iface->get_path =        gtk_file_system_model_get_path;
255   iface->get_value =       gtk_file_system_model_get_value;
256   iface->iter_next =       gtk_file_system_model_iter_next;
257   iface->iter_children =   gtk_file_system_model_iter_children;
258   iface->iter_has_child =  gtk_file_system_model_iter_has_child;
259   iface->iter_n_children = gtk_file_system_model_iter_n_children;
260   iface->iter_nth_child =  gtk_file_system_model_iter_nth_child;
261   iface->iter_parent =     gtk_file_system_model_iter_parent;
262   iface->ref_node =        gtk_file_system_model_ref_node;
263   iface->unref_node =      gtk_file_system_model_unref_node;
264 }
265
266 static void
267 gtk_file_system_model_init (GtkFileSystemModel *model)
268 {
269   model->show_files = TRUE;
270   model->show_folders = TRUE;
271   model->show_hidden = FALSE;
272 }
273
274 static void
275 gtk_file_system_model_finalize (GObject *object)
276 {
277   GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (object);
278   FileModelNode *children, *next;
279
280   if (model->root_folder)
281     g_object_unref (model->root_folder);
282
283   if (model->root_path)
284     gtk_file_path_free (model->root_path);
285
286   if (model->file_system)
287     g_object_unref (model->file_system);
288
289   children = model->roots;
290   while (children)
291     {
292       next = children->next;
293       file_model_node_free (children);
294       children = next;
295     }
296
297   G_OBJECT_CLASS (parent_class)->finalize (object);
298 }
299
300 static void
301 drag_source_iface_init (GtkTreeDragSourceIface *iface)
302 {
303   iface->row_draggable = drag_source_row_draggable;
304   iface->drag_data_get = drag_source_drag_data_get;
305   iface->drag_data_delete = NULL;
306 }
307
308 /*
309  * ******************** GtkTreeModel methods ********************
310  */
311
312 static GtkTreeModelFlags
313 gtk_file_system_model_get_flags (GtkTreeModel *tree_model)
314 {
315   GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
316   GtkTreeModelFlags flags = GTK_TREE_MODEL_ITERS_PERSIST;
317
318   if (model->max_depth == 1)
319     flags |= GTK_TREE_MODEL_LIST_ONLY;
320
321   return flags;
322 }
323
324 static gint
325 gtk_file_system_model_get_n_columns (GtkTreeModel *tree_model)
326 {
327   return GTK_FILE_SYSTEM_MODEL_N_COLUMNS;
328 }
329
330 static GType
331 gtk_file_system_model_get_column_type (GtkTreeModel *tree_model,
332                                        gint          index)
333 {
334   switch (index)
335     {
336     case GTK_FILE_SYSTEM_MODEL_INFO:
337       return GTK_TYPE_FILE_INFO; 
338     case GTK_FILE_SYSTEM_MODEL_DISPLAY_NAME:
339       return G_TYPE_STRING;
340    default:
341       g_assert_not_reached ();
342       return G_TYPE_NONE;
343     }
344 }
345
346 static gboolean
347 gtk_file_system_model_get_iter (GtkTreeModel *tree_model,
348                                 GtkTreeIter  *iter,
349                                 GtkTreePath  *path)
350 {
351   GtkTreeIter parent;
352   gint *indices;
353   gint depth, i;
354
355   indices = gtk_tree_path_get_indices (path);
356   depth = gtk_tree_path_get_depth (path);
357
358   g_return_val_if_fail (depth > 0, FALSE);
359
360   if (!gtk_tree_model_iter_nth_child (tree_model, iter, NULL, indices[0]))
361     return FALSE;
362
363   for (i = 1; i < depth; i++)
364     {
365       parent = *iter;
366       if (!gtk_tree_model_iter_nth_child (tree_model, iter, &parent, indices[i]))
367         return FALSE;
368     }
369
370   return TRUE;
371 }
372
373 static GtkTreePath *
374 gtk_file_system_model_get_path (GtkTreeModel *tree_model,
375                                 GtkTreeIter  *iter)
376 {
377   GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
378   FileModelNode *node = iter->user_data;
379
380   GtkTreePath *result = gtk_tree_path_new ();
381
382   while (node)
383     {
384       FileModelNode *parent = node->parent;
385       FileModelNode *children;
386       int n = 0;
387
388       if (parent)
389         children = parent->children;
390       else
391         children = model->roots;
392
393       while (children != node)
394         {
395           if (children->is_visible)
396             n++;
397           children = children->next;
398         }
399       
400       gtk_tree_path_prepend_index (result, n);
401
402       node = parent;
403     }
404
405   return result;
406 }
407
408 static void
409 gtk_file_system_model_get_value (GtkTreeModel *tree_model,
410                                  GtkTreeIter  *iter,
411                                  gint          column,
412                                  GValue       *value)
413 {
414   GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
415   FileModelNode *node = iter->user_data;
416   const GtkFileInfo *info;
417   
418   switch (column)
419     {
420     case GTK_FILE_SYSTEM_MODEL_INFO:
421       if (model->has_editable && node == model->roots)
422         info = NULL;
423       else
424         info = file_model_node_get_info (model, node);
425
426       g_value_init (value, GTK_TYPE_FILE_INFO);
427       g_value_set_boxed (value, info);
428       break;
429     case GTK_FILE_SYSTEM_MODEL_DISPLAY_NAME:
430       {
431         g_value_init (value, G_TYPE_STRING);
432
433         if (model->has_editable && node == model->roots)
434           g_value_set_string (value, "");
435         else
436           {
437             const GtkFileInfo *info = file_model_node_get_info (model, node);
438
439             g_value_set_string (value, gtk_file_info_get_display_name (info));
440           }
441       }
442       break;
443     default:
444       g_assert_not_reached ();
445     }
446 }
447
448 static gboolean
449 gtk_file_system_model_iter_next (GtkTreeModel *tree_model,
450                                  GtkTreeIter  *iter)
451 {
452   FileModelNode *node = iter->user_data;
453
454   node = node->next;
455   while (node && !node->is_visible)
456     node = node->next;
457   
458   iter->user_data = node;
459
460   return node != NULL;
461 }
462
463 static gboolean
464 gtk_file_system_model_iter_children (GtkTreeModel *tree_model,
465                                      GtkTreeIter  *iter,
466                                      GtkTreeIter  *parent)
467 {
468   GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
469   FileModelNode *children;
470
471   if (parent)
472     {
473       FileModelNode *parent_node = parent->user_data;
474       children = file_model_node_get_children (model, parent_node);
475     }
476   else
477     {
478       children = model->roots;
479     }
480
481   while (children && !children->is_visible)
482     children = children->next;
483
484   iter->user_data = children;
485
486   return children != NULL;
487 }
488
489 static gboolean
490 gtk_file_system_model_iter_has_child (GtkTreeModel *tree_model,
491                                       GtkTreeIter  *iter)
492 {
493   FileModelNode *node = iter->user_data;
494   GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
495
496   if (node->depth == model->max_depth)
497     return FALSE;
498   else
499     {
500       const GtkFileInfo *info = file_model_node_get_info (model, node);
501       return gtk_file_info_get_is_folder (info);
502     }
503 }
504
505 static gint
506 gtk_file_system_model_iter_n_children (GtkTreeModel *tree_model,
507                                        GtkTreeIter  *iter)
508 {
509   GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
510   FileModelNode *children;
511   gint n = 0;
512
513   if (iter)
514     {
515       FileModelNode *node = iter->user_data;
516       children = file_model_node_get_children (model, node);
517     }
518   else
519     {
520       children = model->roots;
521     }
522
523   while (children)
524     {
525       if (children->is_visible)
526         n++;
527       children = children->next;
528     }
529
530   return n;
531 }
532
533 static gboolean
534 gtk_file_system_model_iter_nth_child (GtkTreeModel *tree_model,
535                                       GtkTreeIter  *iter,
536                                       GtkTreeIter  *parent,
537                                       gint          n)
538 {
539   GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
540   FileModelNode *children;
541
542   if (parent)
543     {
544       FileModelNode *parent_node = parent->user_data;
545       children = file_model_node_get_children (model, parent_node);
546     }
547   else
548     {
549       children = model->roots;
550     }
551
552   while (children && !children->is_visible)
553     children = children->next;
554
555   while (n && children)
556     {
557       n--;
558       children = children->next;
559       while (children && !children->is_visible)
560         children = children->next;
561     }
562
563   iter->user_data = children;
564
565   return children != NULL;
566 }
567
568 static gboolean
569 gtk_file_system_model_iter_parent (GtkTreeModel *tree_model,
570                                    GtkTreeIter  *iter,
571                                    GtkTreeIter  *child)
572 {
573   FileModelNode *node = child->user_data;
574   
575   node = node->parent;
576   iter->user_data = node;
577
578   return node != NULL;
579 }
580
581 static void
582 gtk_file_system_model_ref_node (GtkTreeModel *tree_model,
583                                 GtkTreeIter  *iter)
584 {
585   file_model_node_ref (iter->user_data);
586 }
587
588 static void
589 gtk_file_system_model_unref_node (GtkTreeModel *tree_model,
590                                   GtkTreeIter  *iter)
591 {
592   file_model_node_unref (GTK_FILE_SYSTEM_MODEL (tree_model),
593                          iter->user_data);
594 }
595
596 static gboolean
597 drag_source_row_draggable (GtkTreeDragSource *drag_source,
598                            GtkTreePath       *path)
599 {
600   GtkFileSystemModel *model;
601   GtkTreeIter iter;
602   FileModelNode *node;
603
604   model = GTK_FILE_SYSTEM_MODEL (drag_source);
605
606   if (!gtk_file_system_model_get_iter (GTK_TREE_MODEL (model), &iter, path))
607     return FALSE;
608
609   if (!model->has_editable)
610     return TRUE;
611
612   node = iter.user_data;
613   return (node != model->roots);
614 }
615
616 static gboolean
617 drag_source_drag_data_get (GtkTreeDragSource *drag_source,
618                            GtkTreePath       *path,
619                            GtkSelectionData  *selection_data)
620 {
621   GtkFileSystemModel *model;
622   GtkTreeIter iter;
623   const GtkFilePath *file_path;
624   char *uri;
625   char *uris;
626
627   model = GTK_FILE_SYSTEM_MODEL (drag_source);
628
629   if (!gtk_file_system_model_get_iter (GTK_TREE_MODEL (model), &iter, path))
630     return FALSE;
631
632   file_path = _gtk_file_system_model_get_path (model, &iter);
633   g_assert (file_path != NULL);
634
635   uri = gtk_file_system_path_to_uri (model->file_system, file_path);
636   uris = g_strconcat (uri, "\r\n", NULL);
637
638   gtk_selection_data_set (selection_data,
639                           gdk_atom_intern ("text/uri-list", FALSE),
640                           8,
641                           uris,
642                           strlen (uris) + 1);
643
644   g_free (uri);
645   g_free (uris);
646
647   return TRUE;
648 }
649
650 /**
651  * _gtk_file_system_model_new:
652  * @file_system: an object implementing #GtkFileSystem
653  * @root_path: the path of root of the file system to display
654  * @max_depth: the maximum depth from the children of @root_path
655  *             or the roots of the file system to display in
656  *             the file selector). A depth of 0 displays
657  *             only the immediate children of @root_path,
658  *             or the roots of the filesystem. -1 for no
659  *             maximum depth.
660  * @types: a bitmask indicating the types of information
661  *         that is desired about the files. This will
662  *         determine what information is returned by
663  *         _gtk_file_system_model_get_info().
664  *
665  * Creates a new #GtkFileSystemModel object. The #GtkFileSystemModel
666  * object wraps a #GtkFileSystem interface as a #GtkTreeModel.
667  * Using the @root_path and @max_depth parameters, the tree model
668  * can be restricted to a subportion of the entire file system.
669  * 
670  * Return value: the newly created #GtkFileSystemModel object.
671  **/
672 GtkFileSystemModel *
673 _gtk_file_system_model_new (GtkFileSystem     *file_system,
674                             const GtkFilePath *root_path,
675                             gint               max_depth,
676                             GtkFileInfoType    types)
677 {
678   GtkFileSystemModel *model;
679   GSList *roots = NULL;
680   GSList *tmp_list;
681
682   g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
683   g_return_val_if_fail (root_path != NULL, NULL);
684
685   model = g_object_new (GTK_TYPE_FILE_SYSTEM_MODEL, NULL);
686   model->file_system = g_object_ref (file_system);
687   if (max_depth < 0)
688     model->max_depth = G_MAXUSHORT;
689   else
690     model->max_depth = MIN (max_depth, G_MAXUSHORT);
691   model->types = types | GTK_FILE_INFO_IS_FOLDER | GTK_FILE_INFO_IS_HIDDEN;
692
693   if (root_path)
694     {
695       GSList *child_paths;
696
697       model->root_path = gtk_file_path_copy (root_path);
698       model->root_folder = gtk_file_system_get_folder (file_system, root_path,
699                                                        model->types,
700                                                        NULL);   /* NULL-GError */
701
702       if (model->root_folder &&
703           gtk_file_folder_list_children (model->root_folder,
704                                          &child_paths,
705                                          NULL)) /* NULL-GError */
706         {
707           roots = child_paths;
708           
709           g_signal_connect_object (model->root_folder, "deleted",
710                                    G_CALLBACK (root_deleted_callback), model, 0);
711           g_signal_connect_object (model->root_folder, "files-added",
712                                    G_CALLBACK (root_files_added_callback), model, 0);
713           g_signal_connect_object (model->root_folder, "files-changed",
714                                    G_CALLBACK (root_files_changed_callback), model, 0);
715           g_signal_connect_object (model->root_folder, "files-removed",
716                                    G_CALLBACK (root_files_removed_callback), model, 0);
717         }
718     }
719 #if 0
720   else
721     {
722       roots = gtk_file_system_list_roots (file_system);
723       g_signal_connect_object (file_system, "roots-changed",
724                                G_CALLBACK (roots_changed_callback), model, 0);
725     }
726 #endif
727
728   roots = gtk_file_paths_sort (roots);
729   
730   for (tmp_list = roots; tmp_list; tmp_list = tmp_list->next)
731     {
732       FileModelNode *node = file_model_node_new (model, tmp_list->data);
733       gtk_file_path_free (tmp_list->data);
734       node->is_visible = file_model_node_is_visible (model, node);
735       node->next = model->roots;
736       node->depth = 0;
737       model->roots = node;
738     }
739   g_slist_free (roots);
740
741   model->roots = (FileModelNode *)g_slist_reverse ((GSList *)model->roots);
742   
743   return model;
744 }
745
746 static void
747 model_refilter_recurse (GtkFileSystemModel *model,
748                         FileModelNode      *parent,
749                         GtkTreePath        *path)
750 {
751   GtkTreeModel *tree_model = GTK_TREE_MODEL (model);
752   int i = 0;
753   FileModelNode *nodes;
754   gboolean has_children = FALSE;
755
756   if (parent && !parent->loaded)
757     return;
758
759   if (parent)
760     nodes = parent->children;
761   else
762     nodes = model->roots;
763
764   while (nodes)
765     {
766       FileModelNode *next = nodes->next;
767       gboolean is_visible;
768       
769       gtk_tree_path_append_index (path, i);
770
771       is_visible = file_model_node_is_visible (model, nodes);
772       
773       if (!is_visible && nodes->is_visible)
774         {
775           file_model_node_clear (model, nodes);
776           gtk_tree_model_row_deleted (tree_model, path);
777
778           nodes->is_visible = FALSE;
779         }
780       else if (is_visible && !nodes->is_visible)
781         {
782           GtkTreeIter iter;
783
784           iter.user_data = nodes;
785           gtk_tree_model_row_inserted (tree_model, path, &iter);
786
787           nodes->is_visible = TRUE;
788         }
789       else
790         model_refilter_recurse (model, nodes, path);
791
792       if (is_visible)
793         {
794           has_children = TRUE;
795           i++;
796         }
797       
798       gtk_tree_path_up (path);
799       
800       nodes = next;
801     }
802
803   if (parent && !has_children)
804     {
805       /* Fixme - need to insert dummy node here */
806     }
807 }
808
809 static void
810 model_refilter_all (GtkFileSystemModel *model)
811 {
812   GtkTreePath *path;
813
814   path = gtk_tree_path_new ();
815   model_refilter_recurse (model, NULL, path);
816   gtk_tree_path_free (path);
817 }
818
819 /**
820  * _gtk_file_system_model_set_show_hidden:
821  * @model: a #GtkFileSystemModel
822  * @show_hidden: whether hidden files should be displayed
823  * 
824  * Sets whether hidden files should be included in the #GtkTreeModel
825  * for display.
826  **/
827 void
828 _gtk_file_system_model_set_show_hidden (GtkFileSystemModel *model,
829                                         gboolean            show_hidden)
830 {
831   show_hidden = show_hidden != FALSE;
832
833   if (show_hidden != model->show_hidden)
834     {
835       model->show_hidden = show_hidden;
836       model_refilter_all (model);
837     }
838 }
839
840 /**
841  * _gtk_file_system_model_set_show_folders:
842  * @model: a #GtkFileSystemModel
843  * @show_folders: whether folders should be displayed
844  * 
845  * Sets whether folders should be included in the #GtkTreeModel for
846  * display.
847  **/
848 void
849 _gtk_file_system_model_set_show_folders (GtkFileSystemModel *model,
850                                          gboolean            show_folders)
851 {
852   show_folders = show_folders != FALSE;
853
854   if (show_folders != model->show_folders)
855     {
856       model->show_folders = show_folders;
857       model_refilter_all (model);
858     }
859 }
860
861 /**
862  * _gtk_file_system_model_set_show_files:
863  * @model: a #GtkFileSystemModel
864  * @show_files: whether files (as opposed to folders) should
865  *              be displayed.
866  * 
867  * Sets whether files (as opposed to folders) should be included
868  * in the #GtkTreeModel for display.
869  **/
870 void
871 _gtk_file_system_model_set_show_files (GtkFileSystemModel *model,
872                                        gboolean            show_files)
873 {
874   show_files = show_files != FALSE;
875
876   if (show_files != model->show_files)
877     {
878       model->show_files = show_files;
879       model_refilter_all (model);
880     }
881 }
882
883 /**
884  * _gtk_file_system_model_get_info:
885  * @model: a #GtkFileSystemModel
886  * @iter: a #GtkTreeIter pointing to a row of @model
887  * 
888  * Gets the #GtkFileInfo structure for a particular row
889  * of @model. The information included in this structure
890  * is determined by the @types parameter to
891  * _gtk_file_system_model_new().
892  * 
893  * Return value: a #GtkFileInfo structure. This structure
894  *   is owned by @model and must not be modified or freed.
895  *   If you want to save the information for later use,
896  *   you must make a copy, since the structure may be
897  *   freed on later changes to the file system.  If you have
898  *   called _gtk_file_system_model_add_editable() and the @iter
899  *   corresponds to the row that this function returned, the
900  *   return value will be NULL.
901  **/
902 const GtkFileInfo *
903 _gtk_file_system_model_get_info (GtkFileSystemModel *model,
904                                  GtkTreeIter        *iter)
905 {
906   FileModelNode *node;
907
908   node = iter->user_data;
909   if (model->has_editable && node == model->roots)
910     return NULL;
911   else
912     return file_model_node_get_info (model, node);
913 }
914
915 /**
916  * _gtk_file_system_model_get_path:
917  * @model: a #GtkFileSystemModel
918  * @iter: a #GtkTreeIter pointing to a row of @model
919  * 
920  * Gets the path for a particular row in @model. 
921  *
922  * Return value: the path. This string is owned by @model and
923  *   or freed. If you want to save the path for later use,
924  *   you must make a copy, since the string may be freed
925  *   on later changes to the file system.
926  **/
927 const GtkFilePath *
928 _gtk_file_system_model_get_path (GtkFileSystemModel *model,
929                                  GtkTreeIter        *iter)
930 {
931   FileModelNode *node = iter->user_data;
932
933   if (model->has_editable && node == model->roots)
934     return NULL;
935
936   if (node->is_dummy)
937     return node->parent->path;
938   else
939     return node->path;
940 }
941
942 static void
943 unref_node_and_parents (GtkFileSystemModel *model,
944                         FileModelNode      *node)
945 {
946   file_model_node_unref (model, node);
947   if (node->parent)
948     file_model_node_unref (model, node->parent);
949 }
950
951 static FileModelNode *
952 find_child_node (GtkFileSystemModel *model,
953                  FileModelNode      *parent_node,
954                  const GtkFilePath  *path)
955 {
956   FileModelNode *children;
957   
958   if (parent_node)
959     children = file_model_node_get_children (model, parent_node);
960   else
961     children = model->roots;
962
963   while (children)
964     {
965       if (children->is_visible &&
966           children->path &&
967           gtk_file_path_compare (children->path, path) == 0)
968         return children;
969
970       children = children->next;
971     }
972
973   return NULL;
974 }
975                  
976
977 static FileModelNode *
978 find_and_ref_path (GtkFileSystemModel  *model,
979                    const GtkFilePath   *path,
980                    GSList             **cleanups)
981 {
982   GtkFilePath *parent_path;
983   FileModelNode *parent_node;
984   FileModelNode *child_node;
985   GtkFileFolder *folder;
986
987   if (gtk_file_path_compare (path, model->root_path) == 0
988       || !gtk_file_system_get_parent (model->file_system, path, &parent_path, NULL))
989     return NULL;
990
991   if (parent_path)
992     {
993       parent_node = find_and_ref_path (model, parent_path, cleanups);
994       gtk_file_path_free (parent_path);
995     }
996   else
997     parent_node = NULL;
998
999   child_node = find_child_node (model, parent_node, path);
1000   if (child_node)
1001     {
1002       file_model_node_ref (child_node);
1003       return child_node;
1004     }
1005
1006   folder = gtk_file_system_get_folder (model->file_system,
1007                                        path,
1008                                        model->types,
1009                                        NULL);   /* NULL-GError */
1010   if (folder)
1011     {
1012       *cleanups = g_slist_prepend (*cleanups, folder);
1013
1014       child_node = find_child_node (model, parent_node, path);
1015       if (child_node)
1016         {
1017           file_model_node_ref (child_node);
1018           return child_node;
1019         }
1020     }
1021
1022   if (parent_node)
1023     unref_node_and_parents (model, parent_node);
1024
1025   return NULL;
1026 }
1027
1028 /**
1029  * _gtk_file_system_model_set_filter:
1030  * @mode: a #GtkFileSystemModel
1031  * @filter: function to be called for each file
1032  * @user_data: data to pass to @filter
1033  * 
1034  * Sets a callback called for each file/directory to see whether
1035  * it should be included in model. If this function was made
1036  * public, we'd want to include a GDestroyNotify as well.
1037  **/
1038 void
1039 _gtk_file_system_model_set_filter (GtkFileSystemModel      *model,
1040                                    GtkFileSystemModelFilter filter,
1041                                    gpointer                 user_data)
1042 {
1043   g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
1044   
1045   model->filter_func = filter;
1046   model->filter_data = user_data;
1047
1048   model_refilter_all (model);
1049 }
1050
1051 /**
1052  * _gtk_file_system_model_path_do:
1053  * @model: a #GtkFileSystemModel
1054  * @path: a path pointing to a file in the filesystem
1055  *       for @model.
1056  * @func: Function to call with the path and iter corresponding
1057  *        to @path.
1058  * @user_data: data to pass to @func
1059  * 
1060  * Locates @path within @model, referencing
1061  * (gtk_tree_model_ref_node ()) all parent nodes,
1062  * calls @func passing in the path and iter for @path,
1063  * then unrefs all the parent nodes.
1064  *
1065  * The reason for doing this operation as a callback
1066  * is so that if the operation performed with the the
1067  * path and iter results in referencing the the node
1068  * and/or parent nodes, we don't load all the information
1069  * about the nodes.
1070  *
1071  * This function is particularly useful for expanding
1072  * a #GtkTreeView to a particular point in the file system.
1073  * 
1074  * Return value: %TRUE if the path was successfully
1075  *  found in @model and @func was called.
1076  **/
1077 gboolean
1078 _gtk_file_system_model_path_do (GtkFileSystemModel       *model,
1079                                const GtkFilePath         *path,
1080                                GtkFileSystemModelPathFunc func,
1081                                gpointer                   user_data)
1082 {
1083   GSList *cleanups = NULL;
1084   FileModelNode *node = find_and_ref_path (model, path, &cleanups);
1085
1086   if (node)
1087     {
1088       GtkTreeIter iter;
1089       GtkTreePath *path;
1090
1091       iter.user_data = node;
1092       path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
1093
1094       (*func) (model, path, &iter, user_data);
1095
1096       gtk_tree_path_free (path);
1097       unref_node_and_parents (model, node);
1098     }
1099
1100   g_slist_foreach (cleanups, (GFunc)g_object_unref, NULL);
1101   g_slist_free (cleanups);
1102
1103   return node != NULL;
1104 }
1105
1106 /**
1107  * _gtk_file_system_model_add_editable:
1108  * @model: a #GtkFileSystemModel
1109  * @iter: Location to return the iter corresponding to the editable row
1110  * 
1111  * Adds an "empty" row at the beginning of the model.  This does not refer to
1112  * any file, but is a temporary placeholder for a file name that the user will
1113  * type when a corresponding cell is made editable.  When your code is done
1114  * using this temporary row, call _gtk_file_system_model_remove_editable().
1115  **/
1116 void
1117 _gtk_file_system_model_add_editable (GtkFileSystemModel *model, GtkTreeIter *iter)
1118 {
1119   FileModelNode *node;
1120   GtkTreePath *path;
1121
1122   g_return_if_fail (!model->has_editable);
1123
1124   model->has_editable = TRUE;
1125
1126   node = file_model_node_new (model, NULL);
1127   node->is_visible = TRUE;
1128
1129   node->next = model->roots;
1130   model->roots = node;
1131
1132   file_model_node_ref (node);
1133
1134   path = gtk_tree_path_new ();
1135   gtk_tree_path_append_index (path, 0);
1136   iter->user_data = node;
1137
1138   gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, iter);
1139
1140   gtk_tree_path_free (path);
1141 }
1142
1143 /**
1144  * _gtk_file_system_model_remove_editable:
1145  * @model: a #GtkFileSystemModel
1146  * 
1147  * Removes the "empty" row at the beginning of the model that was
1148  * created with _gtk_file_system_model_add_editable().  You should call
1149  * this function when your code is finished editing this temporary row.
1150  **/
1151 void
1152 _gtk_file_system_model_remove_editable (GtkFileSystemModel *model)
1153 {
1154   GtkTreePath *path;
1155
1156   g_return_if_fail (model->has_editable);
1157
1158   model->has_editable = FALSE;
1159   file_model_node_unref (model, model->roots);
1160
1161   model->roots = model->roots->next;
1162
1163   path = gtk_tree_path_new ();
1164   gtk_tree_path_append_index (path, 0);
1165
1166   gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
1167
1168   gtk_tree_path_free (path);
1169 }
1170
1171 static FileModelNode *
1172 file_model_node_new (GtkFileSystemModel *model,
1173                      const GtkFilePath  *path)
1174 {
1175   FileModelNode *node = g_new0 (FileModelNode, 1);
1176
1177   node->model = model;
1178   node->path = path ? gtk_file_path_copy (path) : NULL;
1179
1180   return node;
1181 }
1182
1183 static void
1184 file_model_node_free (FileModelNode *node)
1185 {
1186   file_model_node_clear (node->model, node);
1187   
1188   if (node->path)
1189     gtk_file_path_free (node->path);
1190
1191   if (node->info)
1192     gtk_file_info_free (node->info);
1193
1194   g_free (node);
1195 }
1196
1197 static const GtkFileInfo *
1198 file_model_node_get_info (GtkFileSystemModel *model,
1199                           FileModelNode      *node)
1200 {
1201   if (!node->info)
1202     {
1203       if (node->is_dummy)
1204         {
1205           node->info = gtk_file_info_new ();
1206           gtk_file_info_set_display_name (node->info, _("(Empty)"));
1207         }
1208       else if (node->parent || model->root_folder)
1209         {
1210           node->info = gtk_file_folder_get_info (node->parent ? node->parent->folder : model->root_folder,
1211                                                  node->path,
1212                                                  NULL); /* NULL-GError */
1213         }
1214 #if 0
1215       else
1216         {
1217           node->info = gtk_file_system_get_root_info (model->file_system,
1218                                                       node->path,
1219                                                       model->types,
1220                                                       NULL);  /* NULL-GError */
1221         }
1222 #endif
1223     }
1224
1225   return node->info;
1226 }
1227
1228 static gboolean
1229 file_model_node_is_visible (GtkFileSystemModel *model,
1230                             FileModelNode      *node)
1231 {
1232   if (model->show_folders != model->show_files ||
1233       !model->show_hidden ||
1234       model->filter_func)
1235     {
1236       const GtkFileInfo *info = file_model_node_get_info (model, node);
1237
1238       if (!info)
1239         {
1240           /* File probably disappeared underneath us or resides in a
1241              directory where we have only partial access rights.  */
1242           return FALSE;
1243         }
1244
1245       if (model->show_folders != model->show_files &&
1246           model->show_folders != gtk_file_info_get_is_folder (info))
1247         return FALSE;
1248
1249       if (!model->show_hidden && gtk_file_info_get_is_hidden (info))
1250         return FALSE;
1251
1252       if (model->filter_func &&
1253           !model->filter_func (model, node->path, info, model->filter_data))
1254         return FALSE;
1255     }
1256
1257   return TRUE;
1258 }
1259
1260 static void
1261 file_model_node_clear (GtkFileSystemModel *model,
1262                        FileModelNode      *node)
1263 {
1264   FileModelNode *children;
1265   
1266   file_model_node_idle_clear_cancel (node);
1267   
1268   children = node->children;
1269   node->children = NULL;
1270   node->loaded = FALSE;
1271   
1272   while (children)
1273     {
1274       FileModelNode *next = children->next;
1275       
1276       file_model_node_free (children);
1277       
1278       children = next;
1279     }
1280
1281   if (node->folder)
1282     {
1283       /* Unreffing node->folder may cause roots_changed,
1284        * so we need to be careful about ordering.
1285        */
1286       GtkFileFolder *folder = node->folder;
1287       node->folder = NULL;
1288
1289       g_signal_handlers_disconnect_by_func (folder, G_CALLBACK (deleted_callback), node);
1290       g_signal_handlers_disconnect_by_func (folder, G_CALLBACK (files_added_callback), node);
1291       g_signal_handlers_disconnect_by_func (folder, G_CALLBACK (files_changed_callback), node);
1292       g_signal_handlers_disconnect_by_func (folder, G_CALLBACK (files_removed_callback), node);
1293       
1294       g_object_unref (folder);
1295     }
1296 }
1297
1298 static void
1299 file_model_node_ref (FileModelNode *node)
1300 {
1301   node->ref_count++;
1302   if (node->ref_count == 1 && node->parent)
1303     node->parent->n_referenced_children++;
1304 }
1305
1306 static gboolean
1307 idle_clear_callback (GtkFileSystemModel *model)
1308 {
1309   while (model->idle_clears)
1310     {
1311       FileModelNode *node = model->idle_clears->data;
1312       model->idle_clears = g_slist_delete_link (model->idle_clears, model->idle_clears);
1313
1314       node->idle_clear = FALSE;
1315       file_model_node_clear (node->model, node);
1316     }
1317
1318   return FALSE;
1319 }
1320  
1321 static void
1322 file_model_node_idle_clear (FileModelNode *node)
1323 {
1324   if (!node->idle_clear)
1325     {
1326       GtkFileSystemModel *model = node->model;
1327
1328       node->idle_clear = TRUE;
1329       if (!model->idle_clears)
1330         {
1331           model->idle_clear_source = g_idle_source_new ();
1332           g_source_set_priority (model->idle_clear_source, G_PRIORITY_HIGH);
1333           g_source_set_closure (model->idle_clear_source,
1334                                 g_cclosure_new_object (G_CALLBACK (idle_clear_callback),
1335                                                        G_OBJECT (model)));
1336           g_source_attach (model->idle_clear_source, NULL);
1337         }
1338
1339       model->idle_clears = g_slist_prepend (model->idle_clears, node);
1340       node->idle_clear = TRUE;
1341     }
1342 }
1343
1344 static void
1345 file_model_node_idle_clear_cancel (FileModelNode *node)
1346 {
1347   if (node->idle_clear)
1348     {
1349       GtkFileSystemModel *model = node->model;
1350
1351       model->idle_clears = g_slist_remove (model->idle_clears, node);
1352       if (!model->idle_clears)
1353         {
1354           g_source_destroy (model->idle_clear_source);
1355           model->idle_clear_source = NULL;
1356         }
1357       
1358       node->idle_clear = FALSE;
1359     }
1360 }
1361
1362 static void
1363 file_model_node_unref (GtkFileSystemModel *model,
1364                        FileModelNode       *node)
1365 {
1366   node->ref_count--;
1367   if (node->ref_count == 0)
1368     {
1369       file_model_node_clear (model, node);
1370       if (node->parent)
1371         file_model_node_child_unref (node->parent);
1372     }
1373 }
1374
1375 static void
1376 file_model_node_child_unref (FileModelNode *parent)
1377 {
1378   parent->n_referenced_children--;
1379   if (parent->n_referenced_children == 0)
1380     file_model_node_idle_clear (parent);
1381 }
1382
1383 static FileModelNode *
1384 file_model_node_get_children (GtkFileSystemModel *model,
1385                               FileModelNode      *node)
1386 {
1387   if (node->ref_count == 0)
1388     return NULL;
1389
1390   if (!node->loaded)
1391     {
1392       const GtkFileInfo *info = file_model_node_get_info (model, node);
1393       gboolean has_children = FALSE;
1394       gboolean is_folder = node->depth < model->max_depth && gtk_file_info_get_is_folder (info);
1395
1396       file_model_node_idle_clear_cancel (node);
1397
1398       if (is_folder)
1399         node->folder = gtk_file_system_get_folder (model->file_system,
1400                                                    node->path,
1401                                                    model->types,
1402                                                    NULL);       /* NULL-GError */
1403
1404       if (node->folder)
1405         {
1406           GSList *child_paths, *tmp_list;
1407           
1408           if (gtk_file_folder_list_children (node->folder, &child_paths, NULL)) /* NULL-GError */
1409             {
1410               child_paths = gtk_file_paths_sort (child_paths);
1411
1412               for (tmp_list = child_paths; tmp_list; tmp_list = tmp_list->next)
1413                 {
1414                   FileModelNode *child_node = file_model_node_new (model, tmp_list->data);
1415                   gtk_file_path_free (tmp_list->data);
1416                   child_node->next = node->children;
1417                   child_node->parent = node;
1418                   child_node->depth = node->depth + 1;
1419                   child_node->is_visible = file_model_node_is_visible (model, child_node);
1420                   if (child_node->is_visible)
1421                     has_children = TRUE;
1422                   node->children = child_node;
1423                 }
1424               g_slist_free (child_paths);
1425             }
1426
1427           node->children = (FileModelNode *)g_slist_reverse ((GSList *)node->children);
1428
1429           g_signal_connect (node->folder, "deleted",
1430                             G_CALLBACK (deleted_callback), node);
1431           g_signal_connect (node->folder, "files-added",
1432                             G_CALLBACK (files_added_callback), node);
1433           g_signal_connect (node->folder, "files-changed",
1434                             G_CALLBACK (files_changed_callback), node);
1435           g_signal_connect (node->folder, "files-removed",
1436                             G_CALLBACK (files_removed_callback), node);
1437
1438           g_object_set_data (G_OBJECT (node->folder), "model-node", node);
1439         }
1440       
1441       if (is_folder && !has_children)
1442         {
1443           /* The hard case ... we claimed this folder had children, but actually
1444            * it didn't. We have to add a dummy child, possibly to remove later.
1445            */
1446           FileModelNode *child_node = file_model_node_new (model, NULL);
1447           child_node->is_visible = TRUE;
1448           child_node->parent = node;
1449           child_node->is_dummy = TRUE;
1450
1451           node->children = child_node;
1452           node->has_dummy = TRUE;
1453         }
1454
1455       node->loaded = TRUE;
1456     }
1457
1458   return node->children;
1459 }
1460
1461 static void
1462 do_files_added (GtkFileSystemModel *model,
1463                 FileModelNode      *parent_node,
1464                 GSList             *paths)
1465 {
1466   GtkTreeModel *tree_model = GTK_TREE_MODEL (model);
1467   FileModelNode *children;
1468   FileModelNode *prev = NULL;
1469   GtkTreeIter iter;
1470   GtkTreePath *path;
1471   GSList *sorted_paths;
1472   GSList *tmp_list;
1473
1474   sorted_paths = gtk_file_paths_sort (g_slist_copy (paths));
1475   
1476   if (parent_node)
1477     {
1478       iter.user_data = parent_node;
1479       path = gtk_tree_model_get_path (tree_model, &iter);
1480       children = parent_node->children;
1481     }
1482   else
1483     {
1484       path = gtk_tree_path_new ();
1485       children = model->roots;
1486     }
1487
1488   gtk_tree_path_down (path);
1489   
1490   if (parent_node && parent_node->has_dummy)
1491     {
1492       prev = children;
1493       children = children->next;
1494       gtk_tree_path_next (path);
1495     }
1496
1497   for (tmp_list = sorted_paths; tmp_list; tmp_list = tmp_list->next)
1498     {
1499       const GtkFilePath *file_path = tmp_list->data;
1500       
1501       while (children &&
1502              (!children->path || gtk_file_path_compare (children->path, file_path) < 0))
1503         {
1504           prev = children;
1505           if (children->is_visible)
1506             gtk_tree_path_next (path);
1507           
1508           children = children->next;
1509         }
1510   
1511       if (children &&
1512           children->path && gtk_file_path_compare (children->path, file_path) == 0)
1513         {
1514           /* Shouldn't happen */
1515         }
1516       else
1517         {
1518           FileModelNode *new;
1519           
1520           new = file_model_node_new (model, file_path);
1521           
1522           if (children)
1523             new->next = children;
1524           if (prev)
1525             prev->next = new;
1526           else if (parent_node)
1527             parent_node->children = new;
1528           else
1529             model->roots = new;
1530
1531           prev = new;
1532           
1533           if (parent_node)
1534             {
1535               new->parent = parent_node;
1536               new->depth = parent_node->depth + 1;
1537             }
1538           
1539           new->is_visible = file_model_node_is_visible (model, new);
1540           
1541           if (new->is_visible)
1542             {
1543               iter.user_data = new;
1544               path = gtk_tree_model_get_path (tree_model, &iter);
1545               gtk_tree_model_row_inserted (tree_model, path, &iter);
1546               
1547               if (gtk_file_system_model_iter_has_child (tree_model, &iter))
1548                 gtk_tree_model_row_has_child_toggled (tree_model, path, &iter);
1549               
1550               if (parent_node && parent_node->has_dummy)
1551                 {
1552                   FileModelNode *dummy = parent_node->children;
1553                   GtkTreePath *dummy_path;
1554                   
1555                   parent_node->children = parent_node->children->next;
1556                   parent_node->has_dummy = FALSE;
1557
1558                   dummy_path = gtk_tree_path_copy (path);
1559                   gtk_tree_path_up (dummy_path);
1560                   gtk_tree_path_down (dummy_path);
1561                   
1562                   gtk_tree_model_row_deleted (tree_model, dummy_path);
1563                   gtk_tree_path_free (dummy_path);
1564
1565                   if (dummy->ref_count)
1566                     file_model_node_child_unref (parent_node);
1567                   file_model_node_free (dummy);
1568                 }
1569               
1570               gtk_tree_path_next (path);
1571             }
1572         }
1573     }
1574
1575   gtk_tree_path_free (path);
1576   g_slist_free (sorted_paths);
1577 }
1578
1579 static void
1580 do_files_changed (GtkFileSystemModel *model,
1581                   FileModelNode      *parent_node,
1582                   GSList             *paths)
1583 {
1584   GtkTreeModel *tree_model = GTK_TREE_MODEL (model);
1585   FileModelNode *children;
1586   FileModelNode *prev = NULL;
1587   GtkTreeIter iter;
1588   GtkTreePath *path;
1589   GSList *sorted_paths;
1590   GSList *tmp_list;
1591
1592   sorted_paths = gtk_file_paths_sort (g_slist_copy (paths));
1593   
1594   if (parent_node)
1595     {
1596       iter.user_data = parent_node;
1597       path = gtk_tree_model_get_path (tree_model, &iter);
1598       children = parent_node->children;
1599     }
1600   else
1601     {
1602       path = gtk_tree_path_new ();
1603       children = model->roots;
1604     }
1605
1606   gtk_tree_path_down (path);
1607   
1608   if (parent_node && parent_node->has_dummy)
1609     {
1610       prev = children;
1611       children = children->next;
1612       gtk_tree_path_next (path);
1613     }
1614
1615   for (tmp_list = sorted_paths; tmp_list; tmp_list = tmp_list->next)
1616     {
1617       const GtkFilePath *file_path = tmp_list->data;
1618       
1619       while (children &&
1620              (!children->path || gtk_file_path_compare (children->path, file_path) < 0))
1621         {
1622           prev = children;
1623           if (children->is_visible)
1624             gtk_tree_path_next (path);
1625           
1626           children = children->next;
1627         }
1628   
1629       if (children &&
1630           children->path && gtk_file_path_compare (children->path, file_path) == 0)
1631         {
1632           gtk_tree_model_row_changed (tree_model, path, &iter);
1633         }
1634       else
1635         {
1636           /* Shouldn't happen */
1637         }
1638     }
1639
1640   gtk_tree_path_free (path);
1641   g_slist_free (sorted_paths);
1642 }
1643
1644 static void
1645 do_files_removed (GtkFileSystemModel *model,
1646                   FileModelNode      *parent_node,
1647                   GSList             *paths)
1648 {
1649   GtkTreeModel *tree_model = GTK_TREE_MODEL (model);
1650   FileModelNode *children;
1651   FileModelNode *prev = NULL;
1652   GtkTreeIter iter;
1653   GtkTreePath *path;
1654   GSList *sorted_paths;
1655   GSList *tmp_list;
1656   FileModelNode *tmp_child;
1657   gint n_visible;
1658
1659   sorted_paths = gtk_file_paths_sort (g_slist_copy (paths));
1660   
1661   if (parent_node)
1662     {
1663       iter.user_data = parent_node;
1664       path = gtk_tree_model_get_path (tree_model, &iter);
1665       children = parent_node->children;
1666     }
1667   else
1668     {
1669       path = gtk_tree_path_new ();
1670       children = model->roots;
1671     }
1672
1673   /* Count the number of currently visible children, so that
1674    * can catch when we need to insert a dummy node.
1675    */
1676   n_visible = 0;
1677   for (tmp_child = children; tmp_child; tmp_child = tmp_child->next)
1678     {
1679       if (tmp_child->is_visible)
1680         n_visible++;
1681     }
1682
1683   gtk_tree_path_down (path);
1684   
1685   if (parent_node && parent_node->has_dummy)
1686     {
1687       prev = children;
1688       children = children->next;
1689       gtk_tree_path_next (path);
1690     }
1691
1692   for (tmp_list = sorted_paths; tmp_list; tmp_list = tmp_list->next)
1693     {
1694       const GtkFilePath *file_path = tmp_list->data;
1695       
1696       while (children &&
1697              (!children->path || gtk_file_path_compare (children->path, file_path) < 0))
1698         {
1699           prev = children;
1700           if (children->is_visible)
1701             gtk_tree_path_next (path);
1702           
1703           children = children->next;
1704         }
1705   
1706       if (children &&
1707           children->path && gtk_file_path_compare (children->path, file_path) == 0)
1708         {
1709           FileModelNode *next = children->next;
1710
1711           if (children->is_visible)
1712             n_visible--;
1713           
1714           if (n_visible == 0)
1715             {
1716               FileModelNode *dummy = file_model_node_new (model, NULL);
1717               dummy->is_visible = TRUE;
1718               dummy->parent = parent_node;
1719               dummy->is_dummy = TRUE;
1720
1721               parent_node->children = dummy;
1722               parent_node->has_dummy = TRUE;
1723
1724               iter.user_data = dummy;
1725               gtk_tree_model_row_inserted (tree_model, path, &iter);
1726               gtk_tree_path_next (path);
1727
1728               prev = dummy;
1729             }
1730           
1731           if (prev)
1732             prev->next = next;
1733           else if (parent_node)
1734             parent_node->children = next;
1735           else
1736             model->roots = next;
1737
1738           if (parent_node && children->ref_count)
1739             file_model_node_child_unref (parent_node);
1740               
1741           if (children->is_visible)
1742             gtk_tree_model_row_deleted (tree_model, path);
1743
1744           file_model_node_free (children);
1745
1746           children = next;
1747         }
1748       else
1749         {
1750           /* Shouldn't happen */
1751         }
1752     }
1753
1754   gtk_tree_path_free (path);
1755   g_slist_free (sorted_paths);
1756 }
1757
1758 #if 0
1759 static void
1760 roots_changed_callback (GtkFileSystem      *file_system,
1761                         GtkFileSystemModel *model)
1762 {
1763   GtkTreeModel *tree_model = GTK_TREE_MODEL (model);
1764   GSList *new_roots;
1765   GSList *tmp_list;
1766   FileModelNode *children;
1767   FileModelNode *prev = NULL;
1768   GtkTreePath *path;
1769       
1770   new_roots = gtk_file_system_list_roots (file_system);
1771   new_roots = gtk_file_paths_sort (new_roots);
1772
1773   children = model->roots;
1774   tmp_list = new_roots;
1775   path = gtk_tree_path_new ();
1776   gtk_tree_path_down (path);
1777
1778   while (children || tmp_list)
1779     {
1780       FileModelNode *next = NULL;
1781       int cmp;
1782
1783       if (tmp_list && children)
1784         cmp = gtk_file_path_compare (children->path, tmp_list->data);
1785       else if (children)
1786         cmp = -1;
1787       else
1788         cmp = 1;
1789
1790       if (cmp < 0)
1791         {
1792           next = children->next;
1793           
1794           if (prev)
1795             prev->next = children->next;
1796           else
1797             model->roots = children->next;
1798
1799           if (children->is_visible)
1800             gtk_tree_model_row_deleted (tree_model, path);
1801
1802           file_model_node_free (children);
1803         }
1804       else if (cmp == 0)
1805         {
1806           /* Already there
1807            */
1808           next = children->next;
1809           prev = children;
1810           if (children->is_visible)
1811             gtk_tree_path_next (path);
1812         }
1813       else 
1814         {
1815           GtkTreeIter iter;
1816           FileModelNode *node = file_model_node_new (model, tmp_list->data);
1817           node->is_visible = file_model_node_is_visible (model, node);
1818           node->next = children;
1819           node->depth = 0;
1820
1821           if (prev)
1822             prev->next = node;
1823           else
1824             model->roots = node;
1825
1826           if (node->is_visible)
1827             {
1828               iter.user_data = node;
1829               gtk_tree_model_row_inserted (tree_model, path, &iter);
1830
1831               if (gtk_file_system_model_iter_has_child (tree_model, &iter))
1832                 gtk_tree_model_row_has_child_toggled (tree_model, path, &iter);
1833               
1834               gtk_tree_path_next (path);
1835             }
1836           
1837           prev = node;
1838         }
1839
1840       if (cmp <= 0)
1841         {
1842           children = next;
1843         }
1844
1845       if (cmp >= 0)
1846         {
1847           gtk_file_path_free (tmp_list->data);
1848           tmp_list = tmp_list->next;
1849         }
1850     }
1851   
1852   g_slist_free (new_roots);
1853   gtk_tree_path_free (path);
1854 }
1855 #endif
1856
1857 static void
1858 deleted_callback (GtkFileFolder      *folder,
1859                   FileModelNode      *node)
1860 {
1861 }
1862
1863 static void
1864 files_added_callback (GtkFileFolder      *folder,
1865                       GSList             *paths,
1866                       FileModelNode      *node)
1867 {
1868   do_files_added (node->model, node, paths);
1869 }
1870
1871 static void
1872 files_changed_callback (GtkFileFolder      *folder,
1873                         GSList             *paths,
1874                         FileModelNode      *node)
1875 {
1876   do_files_changed (node->model, node, paths);
1877 }
1878
1879 static void
1880 files_removed_callback (GtkFileFolder      *folder,
1881                         GSList             *paths,
1882                         FileModelNode      *node)
1883 {
1884   do_files_removed (node->model, node, paths);
1885 }
1886
1887 static void
1888 root_deleted_callback (GtkFileFolder      *folder,
1889                        GtkFileSystemModel *model)
1890 {
1891 }
1892
1893 static void
1894 root_files_added_callback (GtkFileFolder      *folder,
1895                            GSList             *paths,
1896                            GtkFileSystemModel *model)
1897 {
1898   do_files_added (model, NULL, paths);
1899 }
1900
1901 static void
1902 root_files_changed_callback (GtkFileFolder      *folder,
1903                              GSList             *paths,
1904                              GtkFileSystemModel *model)
1905 {
1906   do_files_changed (model, NULL, paths);
1907 }
1908
1909 static void
1910 root_files_removed_callback (GtkFileFolder      *folder,
1911                              GSList             *paths,
1912                              GtkFileSystemModel *model)
1913 {
1914   do_files_removed (model, NULL, paths);
1915 }