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