1 /* GTK - The GIMP Toolkit
2 * gtkfilesystemmodel.c: GtkTreeModel wrapping a GtkFileSystem
3 * Copyright (C) 2003, Red Hat, Inc.
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.
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.
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.
21 #include "gtkfilesystemmodel.h"
22 #include "gtkfilesystem.h"
23 #include <gtk/gtktreemodel.h>
26 typedef struct _GtkFileSystemModelClass GtkFileSystemModelClass;
27 typedef struct _FileModelNode FileModelNode;
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))
33 struct _GtkFileSystemModelClass
35 GObjectClass parent_class;
38 struct _GtkFileSystemModel
40 GObject parent_instance;
42 GtkFileSystem *file_system;
43 GtkFileInfoType types;
45 GtkFileFolder *root_folder;
48 GSList *dummy_idle_nodes;
52 guint show_hidden : 1;
53 guint show_folders : 1;
55 guint folders_only : 1;
64 GtkFileFolder *folder;
66 FileModelNode *children;
67 FileModelNode *parent;
76 guint has_children : 1;
79 static void gtk_file_system_model_class_init (GtkFileSystemModelClass *class);
80 static void gtk_file_system_model_iface_init (GtkTreeModelIface *iface);
81 static void gtk_file_system_model_init (GtkFileSystemModel *model);
82 static void gtk_file_system_model_finalize (GObject *object);
84 static GtkTreeModelFlags gtk_file_system_model_get_flags (GtkTreeModel *tree_model);
85 static gint gtk_file_system_model_get_n_columns (GtkTreeModel *tree_model);
86 static GType gtk_file_system_model_get_column_type (GtkTreeModel *tree_model,
88 static gboolean gtk_file_system_model_get_iter (GtkTreeModel *tree_model,
91 static GtkTreePath * gtk_file_system_model_get_path (GtkTreeModel *tree_model,
93 static void gtk_file_system_model_get_value (GtkTreeModel *tree_model,
97 static gboolean gtk_file_system_model_iter_next (GtkTreeModel *tree_model,
99 static gboolean gtk_file_system_model_iter_children (GtkTreeModel *tree_model,
101 GtkTreeIter *parent);
102 static gboolean gtk_file_system_model_iter_has_child (GtkTreeModel *tree_model,
104 static gint gtk_file_system_model_iter_n_children (GtkTreeModel *tree_model,
106 static gboolean gtk_file_system_model_iter_nth_child (GtkTreeModel *tree_model,
110 static gboolean gtk_file_system_model_iter_parent (GtkTreeModel *tree_model,
113 static void gtk_file_system_model_ref_node (GtkTreeModel *tree_model,
115 static void gtk_file_system_model_unref_node (GtkTreeModel *tree_model,
118 static void queue_dummy_idle (GtkFileSystemModel *model,
119 FileModelNode *node);
120 static void unqueue_dummy_idle (GtkFileSystemModel *model,
121 FileModelNode *node);
123 static FileModelNode *file_model_node_new (const gchar *uri);
124 static void file_model_node_free (FileModelNode *node);
125 static void file_model_node_ref (FileModelNode *node);
126 static void file_model_node_unref (GtkFileSystemModel *model,
127 FileModelNode *node);
129 static const GtkFileInfo *file_model_node_get_info (GtkFileSystemModel *model,
130 FileModelNode *node);
131 static gboolean file_model_node_is_visible (GtkFileSystemModel *model,
132 FileModelNode *node);
133 static void file_model_node_clear (GtkFileSystemModel *model,
134 FileModelNode *node);
135 static FileModelNode * file_model_node_get_children (GtkFileSystemModel *model,
136 FileModelNode *node);
139 _gtk_file_system_model_get_type (void)
141 static GType file_system_model_type = 0;
143 if (!file_system_model_type)
145 static const GTypeInfo file_system_model_info =
147 sizeof (GtkFileSystemModelClass),
148 NULL, /* base_init */
149 NULL, /* base_finalize */
150 (GClassInitFunc) gtk_file_system_model_class_init,
151 NULL, /* class_finalize */
152 NULL, /* class_data */
153 sizeof (GtkFileSystemModel),
155 (GInstanceInitFunc) gtk_file_system_model_init,
158 static const GInterfaceInfo file_system_info =
160 (GInterfaceInitFunc) gtk_file_system_model_iface_init, /* interface_init */
161 NULL, /* interface_finalize */
162 NULL /* interface_data */
165 file_system_model_type = g_type_register_static (G_TYPE_OBJECT,
166 "GtkFileSystemModel",
167 &file_system_model_info, 0);
168 g_type_add_interface_static (file_system_model_type,
173 return file_system_model_type;
177 gtk_file_system_model_class_init (GtkFileSystemModelClass *class)
179 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
181 gobject_class->finalize = gtk_file_system_model_finalize;
185 gtk_file_system_model_iface_init (GtkTreeModelIface *iface)
187 iface->get_flags = gtk_file_system_model_get_flags;
188 iface->get_n_columns = gtk_file_system_model_get_n_columns;
189 iface->get_column_type = gtk_file_system_model_get_column_type;
190 iface->get_iter = gtk_file_system_model_get_iter;
191 iface->get_path = gtk_file_system_model_get_path;
192 iface->get_value = gtk_file_system_model_get_value;
193 iface->iter_next = gtk_file_system_model_iter_next;
194 iface->iter_children = gtk_file_system_model_iter_children;
195 iface->iter_has_child = gtk_file_system_model_iter_has_child;
196 iface->iter_n_children = gtk_file_system_model_iter_n_children;
197 iface->iter_nth_child = gtk_file_system_model_iter_nth_child;
198 iface->iter_parent = gtk_file_system_model_iter_parent;
199 iface->ref_node = gtk_file_system_model_ref_node;
200 iface->unref_node = gtk_file_system_model_unref_node;
204 gtk_file_system_model_init (GtkFileSystemModel *model)
206 model->show_files = TRUE;
207 model->show_folders = TRUE;
208 model->show_hidden = FALSE;
212 gtk_file_system_model_finalize (GObject *object)
214 GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (object);
215 FileModelNode *children;
217 if (model->root_folder)
218 g_object_unref (model->root_folder);
220 children = model->roots;
223 file_model_node_free (children);
224 children = children->next;
229 * ******************** GtkTreeModel methods ********************
232 static GtkTreeModelFlags
233 gtk_file_system_model_get_flags (GtkTreeModel *tree_model)
235 GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
236 GtkTreeModelFlags flags = GTK_TREE_MODEL_ITERS_PERSIST;
238 if (model->max_depth == 1)
239 flags |= GTK_TREE_MODEL_LIST_ONLY;
245 gtk_file_system_model_get_n_columns (GtkTreeModel *tree_model)
247 return GTK_FILE_SYSTEM_MODEL_N_COLUMNS;
251 gtk_file_system_model_get_column_type (GtkTreeModel *tree_model,
256 case GTK_FILE_SYSTEM_MODEL_URI:
257 return G_TYPE_STRING;
258 case GTK_FILE_SYSTEM_MODEL_INFO:
259 return GTK_TYPE_FILE_INFO;
261 g_assert_not_reached ();
267 gtk_file_system_model_get_iter (GtkTreeModel *tree_model,
275 indices = gtk_tree_path_get_indices (path);
276 depth = gtk_tree_path_get_depth (path);
278 g_return_val_if_fail (depth > 0, FALSE);
280 if (!gtk_tree_model_iter_nth_child (tree_model, iter, NULL, indices[0]))
283 for (i = 1; i < depth; i++)
286 if (!gtk_tree_model_iter_nth_child (tree_model, iter, &parent, indices[i]))
294 gtk_file_system_model_get_path (GtkTreeModel *tree_model,
297 GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
298 FileModelNode *node = iter->user_data;
300 GtkTreePath *result = gtk_tree_path_new ();
304 FileModelNode *parent = node->parent;
305 FileModelNode *children;
309 children = parent->children;
311 children = model->roots;
313 while (children != node)
315 if (children->is_visible)
317 children = children->next;
320 gtk_tree_path_prepend_index (result, n);
329 gtk_file_system_model_get_value (GtkTreeModel *tree_model,
334 GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
335 FileModelNode *node = iter->user_data;
339 case GTK_FILE_SYSTEM_MODEL_URI:
340 g_value_set_string (value, node->uri);
342 case GTK_FILE_SYSTEM_MODEL_INFO:
343 g_value_set_boxed (value, file_model_node_get_info (model, node));
346 g_assert_not_reached ();
351 gtk_file_system_model_iter_next (GtkTreeModel *tree_model,
354 FileModelNode *node = iter->user_data;
357 while (node && !node->is_visible)
360 iter->user_data = node;
366 gtk_file_system_model_iter_children (GtkTreeModel *tree_model,
370 GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
371 FileModelNode *children;
375 FileModelNode *parent_node = parent->user_data;
376 children = file_model_node_get_children (model, parent_node);
380 children = model->roots;
383 while (children && !children->is_visible)
384 children = children->next;
386 iter->user_data = children;
388 return children != NULL;
392 gtk_file_system_model_iter_has_child (GtkTreeModel *tree_model,
395 FileModelNode *node = iter->user_data;
397 /* We never want to go into a directory just to
398 * find out if it has children
401 return node->has_children;
404 GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
406 if (node->depth == model->max_depth)
410 const GtkFileInfo *info = file_model_node_get_info (model, node);
411 return gtk_file_info_get_is_folder (info);
417 gtk_file_system_model_iter_n_children (GtkTreeModel *tree_model,
420 GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
421 FileModelNode *children;
426 FileModelNode *node = iter->user_data;
427 children = file_model_node_get_children (model, node);
431 children = model->roots;
436 if (children->is_visible)
438 children = children->next;
445 gtk_file_system_model_iter_nth_child (GtkTreeModel *tree_model,
450 GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
451 FileModelNode *children;
455 FileModelNode *parent_node = parent->user_data;
456 children = file_model_node_get_children (model, parent_node);
460 children = model->roots;
463 while (children && !children->is_visible)
464 children = children->next;
466 while (n && children)
469 children = children->next;
470 while (children && !children->is_visible)
471 children = children->next;
474 iter->user_data = children;
476 return children != NULL;
480 gtk_file_system_model_iter_parent (GtkTreeModel *tree_model,
484 FileModelNode *node = child->user_data;
487 iter->user_data = node;
493 gtk_file_system_model_ref_node (GtkTreeModel *tree_model,
496 file_model_node_ref (iter->user_data);
500 gtk_file_system_model_unref_node (GtkTreeModel *tree_model,
503 file_model_node_unref (GTK_FILE_SYSTEM_MODEL (tree_model),
508 * _gtk_file_system_model_new:
509 * @file_system: an object implementing #GtkFileSystem
510 * @root_uri: the URI of root of the file system to display,
511 * or %NULL to display starting from the
512 * root or roots of the fielsystem.
513 * @max_depth: the maximum depth from the children of @root_uri
514 * or the roots of the file system to display in
515 * the file selector). A depth of 0 displays
516 * only the immediate children of @root_uri,
517 * or the roots of the filesystem. -1 for no
519 * @types: a bitmask indicating the types of information
520 * that is desired about the files. This will
521 * determine what information is returned by
522 * _gtk_file_system_model_get_info().
524 * Creates a new #GtkFileSystemModel object. The #GtkFileSystemModel
525 * object wraps a #GtkFileSystem interface as a #GtkTreeModel.
526 * Using the @root_uri and @max_depth parameters, the tree model
527 * can be restricted to a subportion of the entire file system.
529 * Return value: the newly created #GtkFileSystemModel object.
532 _gtk_file_system_model_new (GtkFileSystem *file_system,
533 const gchar *root_uri,
535 GtkFileInfoType types)
537 GtkFileSystemModel *model;
538 GSList *roots, *tmp_list;
540 g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
542 model = g_object_new (GTK_TYPE_FILE_SYSTEM_MODEL, NULL);
543 model->file_system = g_object_ref (file_system);
545 model->max_depth = G_MAXUSHORT;
547 model->max_depth = MIN (max_depth, G_MAXUSHORT);
548 model->types = types | GTK_FILE_INFO_IS_FOLDER | GTK_FILE_INFO_IS_HIDDEN;
554 model->root_folder = gtk_file_system_get_folder (file_system, root_uri,
556 NULL); /* NULL-GError */
558 if (model->root_folder &&
559 gtk_file_folder_list_children (model->root_folder,
561 NULL)) /* NULL-GError */
565 roots = gtk_file_system_list_roots (file_system);
567 roots = g_slist_sort (roots, (GCompareFunc)strcmp);
569 for (tmp_list = roots; tmp_list; tmp_list = tmp_list->next)
571 FileModelNode *node = file_model_node_new (tmp_list->data);
572 g_free (tmp_list->data);
573 node->is_visible = file_model_node_is_visible (model, node);
574 node->next = model->roots;
578 g_slist_free (roots);
580 model->roots = (FileModelNode *)g_slist_reverse ((GSList *)model->roots);
586 model_refilter_recurse (GtkFileSystemModel *model,
587 FileModelNode *parent,
590 GtkTreeModel *tree_model = GTK_TREE_MODEL (model);
592 FileModelNode *nodes;
593 gboolean has_children = FALSE;
595 if (parent && !parent->loaded)
599 nodes = parent->children;
601 nodes = model->roots;
605 FileModelNode *next = nodes->next;
608 gtk_tree_path_append_index (path, i);
610 is_visible = file_model_node_is_visible (model, nodes);
612 if (!is_visible && nodes->is_visible)
614 file_model_node_clear (model, nodes);
615 gtk_tree_model_row_deleted (tree_model, path);
617 nodes->is_visible = FALSE;
619 else if (is_visible && !nodes->is_visible)
623 iter.user_data = nodes;
624 gtk_tree_model_row_inserted (tree_model, path, &iter);
626 nodes->is_visible = TRUE;
629 model_refilter_recurse (model, nodes, path);
637 gtk_tree_path_up (path);
642 if (parent && (has_children != parent->has_children))
646 parent->has_children = has_children;
648 iter.user_data = parent;
649 gtk_tree_model_row_has_child_toggled (tree_model, path, &iter);
654 * _gtk_file_system_model_set_show_hidden:
655 * @model: a #GtkFileSystemModel
656 * @show_hidden: whether hidden files should be displayed
658 * Sets whether hidden files should be included in the #GtkTreeModel
662 _gtk_file_system_model_set_show_hidden (GtkFileSystemModel *model,
663 gboolean show_hidden)
665 show_hidden = show_hidden != FALSE;
667 if (show_hidden != model->show_hidden)
671 model->show_hidden = show_hidden;
673 path = gtk_tree_path_new ();
674 model_refilter_recurse (model, NULL, path);
675 gtk_tree_path_free (path);
680 * _gtk_file_system_model_set_show_folders:
681 * @model: a #GtkFileSystemModel
682 * @show_folders: whether folders should be displayed
684 * Sets whether folders should be included in the #GtkTreeModel for
688 _gtk_file_system_model_set_show_folders (GtkFileSystemModel *model,
689 gboolean show_folders)
691 show_folders = show_folders != FALSE;
693 if (show_folders != model->show_folders)
697 model->show_folders = show_folders;
699 path = gtk_tree_path_new ();
700 model_refilter_recurse (model, NULL, path);
701 gtk_tree_path_free (path);
706 * _gtk_file_system_model_set_show_files:
707 * @model: a #GtkFileSystemModel
708 * @show_files: whether files (as opposed to folders) should
711 * Sets whether files (as opposed to folders) should be included
712 * in the #GtkTreeModel for display.
715 _gtk_file_system_model_set_show_files (GtkFileSystemModel *model,
718 show_files = show_files != FALSE;
720 if (show_files != model->show_files)
724 model->show_files = show_files;
726 path = gtk_tree_path_new ();
727 model_refilter_recurse (model, NULL, path);
728 gtk_tree_path_free (path);
733 * _gtk_file_system_model_get_info:
734 * @model: a #GtkFileSystemModel
735 * @iter: a #GtkTreeIter pointing to a row of @model
737 * Gets the #GtkFileInfo structure for a particular row
738 * of @model. The information included in this structure
739 * is determined by the @types parameter to
740 * _gtk_file_system_model_new().
742 * Return value: a #GtkFileInfo structure. This structure
743 * is owned by @model and must not be modified or freed.
744 * If you want to save the information for later use,
745 * you must make a copy, since the structure may be
746 * freed on later changes to the file system.
749 _gtk_file_system_model_get_info (GtkFileSystemModel *model,
752 return file_model_node_get_info (model, iter->user_data);
756 * _gtk_file_system_model_get_uri:
757 * @model: a #GtkFileSystemModel
758 * @iter: a #GtkTreeIter pointing to a row of @model
760 * Gets the URI for a particular row in @model.
762 * Return value: the URI. This string is owned by @model and
763 * or freed. If you want to save the URI for later use,
764 * you must make a copy, since the string may be freed
765 * on later changes to the file system.
768 _gtk_file_system_model_get_uri (GtkFileSystemModel *model,
771 FileModelNode *node = iter->user_data;
777 unref_node_and_parents (GtkFileSystemModel *model,
780 file_model_node_unref (model, node);
782 file_model_node_unref (model, node->parent);
785 static FileModelNode *
786 find_and_ref_uri (GtkFileSystemModel *model,
790 FileModelNode *parent_node;
791 FileModelNode *children;
793 if (!gtk_file_system_get_parent (model->file_system, uri, &parent_uri, NULL))
798 parent_node = find_and_ref_uri (model, parent_uri);
808 children = file_model_node_get_children (model, parent_node);
810 children = model->roots;
814 if (children->is_visible &&
815 strcmp (children->uri, uri) == 0)
817 file_model_node_ref (children);
821 children = children->next;
825 unref_node_and_parents (model, parent_node);
831 * _gtk_file_system_model_uri_do:
832 * @model: a #GtkFileSystemModel
833 * @uri: a URI pointing to a file in the filesystem
835 * @func: Function to call with the path and iter corresponding
837 * @user_data: data to pass to @func
839 * Locates @uri within @model, referencing
840 * (gtk_tree_model_ref_node ()) all parent nodes,
841 * calls @func passing in the path and iter for @uri,
842 * then unrefs all the parent nodes.
844 * The reason for doing this operation as a callback
845 * is so that if the operation performed with the the
846 * path and iter results in referencing the the node
847 * and/or parent nodes, we don't load all the information
850 * This function is particularly useful for expanding
851 * a #GtkTreeView to a particular point in the file system.
853 * Return value: %TRUE if the URI was successfully
854 * found in @model and @func was called.
857 _gtk_file_system_model_uri_do (GtkFileSystemModel *model,
859 GtkFileSystemModelURIFunc func,
862 FileModelNode *node = find_and_ref_uri (model, uri);
869 iter.user_data = node;
870 path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
872 (*func) (model, path, &iter, user_data);
874 gtk_tree_path_free (path);
875 unref_node_and_parents (model, node);
884 dummy_idle_callback (GtkFileSystemModel *model)
886 GtkTreeModel *tree_model = GTK_TREE_MODEL (model);
889 for (tmp_list = model->dummy_idle_nodes; tmp_list; tmp_list = tmp_list->next)
894 FileModelNode *node = tmp_list->data;
895 g_assert (node->children && !node->children->next && !node->children->children);
897 iter.user_data = node->children;
898 path = gtk_tree_model_get_path (tree_model, &iter);
900 if (node->children->ref_count)
901 gtk_tree_model_row_deleted (tree_model, path);
903 gtk_tree_path_up (path);
904 iter.user_data = node;
905 gtk_tree_model_row_has_child_toggled (tree_model, path, &iter);
907 gtk_tree_path_free (path);
909 file_model_node_free (node->children);
910 node->children = NULL;
911 node->has_children = FALSE;
912 node->has_dummy = FALSE;
915 model->dummy_idle_nodes = FALSE;
916 model->dummy_idle = NULL;
922 queue_dummy_idle (GtkFileSystemModel *model,
925 model->dummy_idle_nodes = g_slist_prepend (model->dummy_idle_nodes, node);
927 if (!model->dummy_idle)
929 model->dummy_idle = g_idle_source_new ();
930 g_source_set_priority (model->dummy_idle, G_PRIORITY_HIGH_IDLE);
931 g_source_set_closure (model->dummy_idle,
932 g_cclosure_new_object (G_CALLBACK (dummy_idle_callback), G_OBJECT (model)));
933 g_source_attach (model->dummy_idle, NULL);
938 unqueue_dummy_idle (GtkFileSystemModel *model,
941 model->dummy_idle_nodes = g_slist_remove (model->dummy_idle_nodes, node);
943 if (!model->dummy_idle_nodes)
944 g_source_destroy (model->dummy_idle);
947 static FileModelNode *
948 file_model_node_new (const gchar *uri)
950 FileModelNode *node = g_new0 (FileModelNode, 1);
952 node->uri = g_strdup (uri);
958 file_model_node_free (FileModelNode *node)
962 FileModelNode *children;
964 for (children = node->children; children; children = children->next)
965 file_model_node_free (children);
972 gtk_file_info_free (node->info);
975 g_object_unref (node->folder);
980 static const GtkFileInfo *
981 file_model_node_get_info (GtkFileSystemModel *model,
986 if (node->parent && node->parent->has_dummy)
988 node->info = gtk_file_info_new ();
989 gtk_file_info_set_display_name (node->info, "Loading...");
991 else if (node->parent || model->root_folder)
993 node->info = gtk_file_folder_get_info (node->parent ? node->parent->folder : model->root_folder,
995 NULL); /* NULL-GError */
999 node->info = gtk_file_system_get_root_info (model->file_system,
1002 NULL); /* NULL-GError */
1010 file_model_node_is_visible (GtkFileSystemModel *model,
1011 FileModelNode *node)
1013 if (model->show_hidden && model->show_folders && model->show_files)
1017 const GtkFileInfo *info = file_model_node_get_info (model, node);
1018 gboolean is_folder = gtk_file_info_get_is_folder (info);
1020 if (!model->show_folders && is_folder)
1022 if (!model->show_files && !is_folder)
1024 if (!model->show_hidden && gtk_file_info_get_is_hidden (info))
1032 file_model_node_clear (GtkFileSystemModel *model,
1033 FileModelNode *node)
1035 FileModelNode *children;
1037 if (node->has_dummy)
1038 unqueue_dummy_idle (model, node);
1042 g_object_unref (node->folder);
1043 node->folder = NULL;
1046 children = node->children;
1047 node->children = NULL;
1048 node->has_children = FALSE;
1049 node->loaded = FALSE;
1053 FileModelNode *next = children->next;
1055 file_model_node_clear (model, children);
1056 file_model_node_free (children);
1061 node->ref_count = 0;
1065 file_model_node_ref (FileModelNode *node)
1071 file_model_node_unref (GtkFileSystemModel *model,
1072 FileModelNode *node)
1075 if (node->ref_count == 0)
1076 file_model_node_clear (model, node);
1079 static FileModelNode *
1080 file_model_node_get_children (GtkFileSystemModel *model,
1081 FileModelNode *node)
1083 if (node->ref_count == 0)
1088 const GtkFileInfo *info = file_model_node_get_info (model, node);
1089 gboolean has_children = FALSE;
1090 gboolean is_folder = node->depth < model->max_depth && gtk_file_info_get_is_folder (info);
1093 node->folder = gtk_file_system_get_folder (model->file_system,
1096 NULL); /* NULL-GError */
1100 GSList *child_uris, *tmp_list;
1102 if (gtk_file_folder_list_children (node->folder, &child_uris, NULL)) /* NULL-GError */
1104 child_uris = g_slist_sort (child_uris, (GCompareFunc)strcmp);
1106 for (tmp_list = child_uris; tmp_list; tmp_list = tmp_list->next)
1108 FileModelNode *child_node = file_model_node_new (tmp_list->data);
1109 g_free (tmp_list->data);
1110 child_node->next = node->children;
1111 child_node->parent = node;
1112 child_node->depth = node->depth + 1;
1113 child_node->is_visible = file_model_node_is_visible (model, child_node);
1114 if (child_node->is_visible)
1115 has_children = TRUE;
1116 node->children = child_node;
1118 g_slist_free (child_uris);
1121 node->children = (FileModelNode *)g_slist_reverse ((GSList *)node->children);
1124 node->has_children = has_children;
1126 if (is_folder && !node->has_children)
1128 /* The hard case ... we claimed this folder had children, but actually
1129 * it didn't. We have to add a dummy child, then remove it later
1131 FileModelNode *child_node = file_model_node_new ("***dummy***");
1132 child_node->is_visible = TRUE;
1133 child_node->parent = node;
1135 node->children = child_node;
1136 node->has_children = TRUE;
1137 node->has_dummy = TRUE;
1139 queue_dummy_idle (model, node);
1142 node->loaded = TRUE;
1145 return node->children;