From a7f4e526831e6b11d380925bf48bb30d55346bd3 Mon Sep 17 00:00:00 2001 From: Maciej Stachowiak Date: Thu, 3 Aug 2000 08:34:29 +0000 Subject: Rewrote the tree view to do model/view separation, and in the process fixed bugs 1520, 1526, 1529, 1531 and 1522. Some of these are not for the current milestone, but just fell out naturally from doing the model/view separation, which makes the remaining required tasks far easier. * components/tree/nautilus-tree-model.h: * components/tree/nautilus-tree-model.c: (nautilus_tree_model_initialize_class), (nautilus_tree_model_initialize), (nautilus_tree_stop_monitoring_internal), (nautilus_tree_model_destroy), (nautilus_tree_model_new), (report_root_node_if_possible), (nautilus_tree_model_root_node_file_monitor), (nautilus_tree_model_set_root_uri), (nautilus_tree_model_monitor_add), (nautilus_tree_model_monitor_remove), (nautilus_tree_model_directory_files_changed_callback), (nautilus_tree_model_directory_files_added_callback), (nautilus_tree_model_directory_done_loading_callback), (nautilus_tree_model_monitor_node), (nautilus_tree_model_stop_monitoring_node), (nautilus_tree_model_get_node), (uri_get_parent_text), (report_node_added), (report_node_changed), (report_node_removed), (report_done_loading): Implemented all the calls and signals and monitoring and stuff for the new tree model. * components/tree/nautilus-tree-node.h, components/tree/nautilus-tree-node.c: (nautilus_tree_node_initialize_class), (nautilus_tree_node_initialize), (nautilus_tree_node_destroy), (nautilus_tree_node_new), (nautilus_tree_node_set_parent), (nautilus_tree_remove_from_parent): New class that represents a single node in the tree. * components/tree/nautilus-tree-view.c: (nautilus_tree_view_should_skip_file), (nautilus_tree_view_insert_model_node), (nautilus_tree_view_remove_model_node), (nautilus_tree_view_update_model_node), (nautilus_tree_view_model_node_added_callback), (nautilus_tree_view_model_node_changed_callback), (nautilus_tree_view_model_node_removed_callback), (nautilus_tree_view_load_from_filesystem), (nautilus_tree_view_initialize), (disconnect_model_handlers), (nautilus_tree_view_destroy), (tree_expand_callback), (tree_collapse_callback), (tree_select_row_callback): Adapt to using the new NautilusTreeModel and NautilusTreeNodes instead of using NautilusDirectories and NautilusFiles directly. * components/tree/Makefile.am: Include new files in build. --- components/tree/Makefile.am | 3 + components/tree/nautilus-tree-model.c | 576 ++++++++++++++++++++++++++- components/tree/nautilus-tree-model.h | 29 +- components/tree/nautilus-tree-node.c | 103 ++++- components/tree/nautilus-tree-node.h | 13 +- components/tree/nautilus-tree-view.c | 722 ++++++++++++---------------------- 6 files changed, 923 insertions(+), 523 deletions(-) (limited to 'components') diff --git a/components/tree/Makefile.am b/components/tree/Makefile.am index dcb2fa195..a6e0f654a 100644 --- a/components/tree/Makefile.am +++ b/components/tree/Makefile.am @@ -29,6 +29,9 @@ nautilus_tree_view_SOURCES = \ nautilus-tree-view.c \ nautilus-tree-model.h \ nautilus-tree-model.c \ + nautilus-tree-node-private.h \ + nautilus-tree-node.h \ + nautilus-tree-node.c \ main.c \ $(NULL) diff --git a/components/tree/nautilus-tree-model.c b/components/tree/nautilus-tree-model.c index 4e214c2e6..b36084f53 100644 --- a/components/tree/nautilus-tree-model.c +++ b/components/tree/nautilus-tree-model.c @@ -25,46 +25,417 @@ #include #include "nautilus-tree-model.h" +#include "nautilus-tree-node-private.h" +#include +#include +#include +enum { + NODE_ADDED, + NODE_CHANGED, + NODE_REMOVED, + DONE_LOADING_CHILDREN, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; struct NautilusTreeModelDetails { - GHashTable *uri_to_node_map; + GHashTable *uri_to_node_map; + + GList *monitor_clients; NautilusTreeNode *root_node; + gboolean root_node_reported; + gint root_node_changed_signal_id; }; -#if 0 - void (*node_added) (NautilusTreeModel *model, - NautilusTreeNode *node); +static void nautilus_tree_model_set_root_uri (NautilusTreeModel *model, + const char *root_uri); +static void report_node_added (NautilusTreeModel *model, + NautilusTreeNode *node); +static void report_node_changed (NautilusTreeModel *model, + NautilusTreeNode *node); +static void report_node_removed (NautilusTreeModel *model, + NautilusTreeNode *node); +static void report_done_loading (NautilusTreeModel *model, + NautilusTreeNode *node); - void (*node_changed) (NautilusTreeModel *model, - NautilusTreeNode *node); - void (*node_removed) (NautilusTreeModel *model, - NautilusTreeNode *node); +static void nautilus_tree_model_destroy (GtkObject *object); +static void nautilus_tree_model_initialize (gpointer object, + gpointer klass); +static void nautilus_tree_model_initialize_class (gpointer klass); - void (*done_loading_children) (NautilusTreeModel *model, - NautilusTreeNode *node); -#endif +NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusTreeModel, nautilus_tree_model, GTK_TYPE_OBJECT) -GtkType nautilus_tree_model_get_type (void); -NautilusTreeModel *nautilus_tree_model_new (const char *root_uri); +static void +nautilus_tree_model_initialize_class (gpointer klass) +{ + GtkObjectClass *object_class; + object_class = GTK_OBJECT_CLASS (klass); + + object_class->destroy = nautilus_tree_model_destroy; -NautilusTreeModel *nautilus_tree_model_set_root_uri (const char *root_uri); + signals[NODE_ADDED] = + gtk_signal_new ("node_added", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (NautilusTreeModelClass, node_added), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + signals[NODE_CHANGED] = + gtk_signal_new ("node_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (NautilusTreeModelClass, node_changed), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); -void nautilus_tree_model_load_children (NautilusTreeModel *model, - NautilusTreeNode *node); + signals[NODE_REMOVED] = + gtk_signal_new ("node_removed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (NautilusTreeModelClass, node_removed), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); -void nautilus_tree_model_stop_monitoring_children (NautilusTreeModel *model, - NautilusTreeNode *node); + signals[DONE_LOADING_CHILDREN] = + gtk_signal_new ("done_loading_children", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (NautilusTreeModelClass, done_loading_children), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); -NautilusTreeNode *nautilus_tree_model_get_node (NautilusTreeModel *model, - const char *uri); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); +} + +static void +nautilus_tree_model_initialize (gpointer object, gpointer klass) +{ + NautilusTreeModel *model; + + model = NAUTILUS_TREE_MODEL (object); + + model->details = g_new0 (NautilusTreeModelDetails, 1); + + model->details->uri_to_node_map = g_hash_table_new (g_str_hash, + g_str_equal); +} + +static void +nautilus_tree_stop_monitoring_internal (NautilusTreeModel *model) +{ + /* FIXME: stop monitoring everything; we should probably + forget everything in the hash table too. */ + +} + +static void +nautilus_tree_model_destroy (GtkObject *object) +{ + NautilusTreeModel *model; + + model = (NautilusTreeModel *) object; + + /* FIXME: Free all the key strings and unref all the value nodes in + the uri_to_node_map */ + + g_hash_table_destroy (model->details->uri_to_node_map); + + nautilus_tree_stop_monitoring_internal (model); + + if (model->details->root_node != NULL) { + gtk_object_unref (GTK_OBJECT (model->details->root_node)); + } + + g_free (model->details->monitor_clients); + + g_free (model->details); + + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); +} + +NautilusTreeModel * +nautilus_tree_model_new (const char *root_uri) +{ + NautilusTreeModel *model; + + model = NAUTILUS_TREE_MODEL (gtk_type_new (NAUTILUS_TYPE_TREE_MODEL)); + + nautilus_tree_model_set_root_uri (model, root_uri); + + return model; +} + + +static void +report_root_node_if_possible (NautilusTreeModel *model) +{ + if (nautilus_file_get_file_type (nautilus_tree_node_get_file (model->details->root_node)) + != GNOME_VFS_FILE_TYPE_UNKNOWN) { + model->details->root_node_reported = TRUE; + + report_node_added (model, model->details->root_node); + } +} + +static void +nautilus_tree_model_root_node_file_monitor (NautilusFile *file, + NautilusTreeModel *model) +{ + if (model->details->root_node_reported == FALSE) { + report_root_node_if_possible (model); + } else { + /* report that the root node changed */ + } +} + + +static void +nautilus_tree_model_set_root_uri (NautilusTreeModel *model, + const char *root_uri) +{ + NautilusFile *file; + + /* You can only set the root node once */ + g_return_if_fail (model->details->root_node == NULL); + + file = nautilus_file_get (root_uri); + model->details->root_node = nautilus_tree_node_new (file); + nautilus_file_unref (file); +} + + +void +nautilus_tree_model_monitor_add (NautilusTreeModel *model, + gconstpointer client, + NautilusTreeModelCallback initial_nodes_callback, + gpointer callback_data) +{ + NautilusTreeNode *current_node; + GList *reporting_queue; + GList *monitor_attributes; + + reporting_queue = NULL; + + /* If we just (re)started monitoring the whole tree, make sure + to monitor the root node itself. */ + + if (model->details->monitor_clients == NULL) { + if (model->details->root_node_reported == FALSE) { + report_root_node_if_possible (model); + } + + model->details->root_node_changed_signal_id = gtk_signal_connect + (GTK_OBJECT (nautilus_tree_node_get_file (model->details->root_node)), + "changed", + nautilus_tree_model_root_node_file_monitor, + model); + + monitor_attributes = g_list_prepend (NULL, "is directory"); + + nautilus_file_monitor_add (nautilus_tree_node_get_file (model->details->root_node), + model, + monitor_attributes, + FALSE); + + g_list_free (monitor_attributes); + } + + if (! g_list_find (model->details->monitor_clients, (gpointer) client)) { + model->details->monitor_clients = g_list_prepend (model->details->monitor_clients, (gpointer) client); + } + + if (model->details->root_node_reported) { + reporting_queue = g_list_prepend (reporting_queue, model->details->root_node); + + while (reporting_queue != NULL) { + current_node = (NautilusTreeNode *) reporting_queue->data; + reporting_queue = g_list_remove_link (reporting_queue, reporting_queue); + + (*initial_nodes_callback) (model, current_node, callback_data); + + /* We are doing a depth-first scan here, we + could do breadth-first instead by reversing + the args to the g_list_concat call + below. */ + g_list_concat (g_list_copy (nautilus_tree_node_get_children (current_node)), + reporting_queue); + } + } + +} + + +void +nautilus_tree_model_monitor_remove (NautilusTreeModel *model, + gconstpointer client) +{ + model->details->monitor_clients = g_list_remove (model->details->monitor_clients, (gpointer) client); + + if (model->details->monitor_clients == NULL) { + /* FIXME: stop monitoring root node file, dunno what else */ + } +} + + + +static void +nautilus_tree_model_directory_files_changed_callback (NautilusDirectory *directory, + GList *added_files, + NautilusTreeModel *model) +{ + GList *p; + NautilusFile *file; + NautilusTreeNode *node; + char *uri; + + for (p = added_files; p != NULL; p = p->next) { + file = (NautilusFile *) p->data; + + uri = nautilus_file_get_uri (file); + node = nautilus_tree_model_get_node (model, uri); + g_free (uri); + + if (!nautilus_directory_contains_file (directory, file)) { + report_node_removed (model, node); + } else { + report_node_changed (model, node); + } + } +} + +static void +nautilus_tree_model_directory_files_added_callback (NautilusDirectory *directory, + GList *added_files, + NautilusTreeModel *model) +{ + GList *p; + NautilusFile *file; + NautilusTreeNode *node; + + for (p = added_files; p != NULL; p = p->next) { + file = (NautilusFile *) p->data; + + node = nautilus_tree_node_new (file); + + report_node_added (model, node); + } +} + + +static void +nautilus_tree_model_directory_done_loading_callback (NautilusDirectory *directory, + NautilusTreeModel *model) +{ + char *uri; + NautilusTreeNode *node; + + uri = nautilus_directory_get_uri (directory); + node = nautilus_tree_model_get_node (model, uri); + g_free (uri); + + report_done_loading (model, node); +} + + + +void +nautilus_tree_model_monitor_node (NautilusTreeModel *model, + NautilusTreeNode *node, + gconstpointer client) +{ + NautilusDirectory *directory; + GList *monitor_attributes; + + if (!nautilus_file_is_directory (nautilus_tree_node_get_file (node))) { + report_done_loading (model, node); + return; + } + + if (node->details->monitor_clients == NULL) { + /* we must connect to signals */ + directory = nautilus_tree_node_get_directory (node); + + node->details->files_added_id = gtk_signal_connect + (GTK_OBJECT (directory), + "files_added", + nautilus_tree_model_directory_files_added_callback, + model); + + node->details->files_changed_id = gtk_signal_connect + (GTK_OBJECT (directory), + "files_changed", + nautilus_tree_model_directory_files_changed_callback, + model); + + node->details->done_loading_id = gtk_signal_connect + (GTK_OBJECT (directory), + "done_loading", + nautilus_tree_model_directory_done_loading_callback, + model); + } + + monitor_attributes = g_list_prepend (NULL, "is directory"); + + node->details->provisional_children = node->details->children; + node->details->children = NULL; + + nautilus_directory_file_monitor_add (directory, + model, + monitor_attributes, + FALSE, + TRUE, + (NautilusDirectoryCallback) nautilus_tree_model_directory_files_added_callback, + model); + + g_list_free (monitor_attributes); + + if (! g_list_find (node->details->monitor_clients, (gpointer) client)) { + node->details->monitor_clients = g_list_prepend (node->details->monitor_clients, (gpointer) client); + } +} + + +void +nautilus_tree_model_stop_monitoring_node (NautilusTreeModel *model, + NautilusTreeNode *node, + gconstpointer client) +{ + if (!nautilus_file_is_directory (nautilus_tree_node_get_file (node)) || node->details->monitor_clients == NULL) { + return; + } + + node->details->monitor_clients = g_list_remove (node->details->monitor_clients, (gpointer) client); + + if (node->details->monitor_clients == NULL) { + gtk_signal_disconnect (GTK_OBJECT (node), node->details->files_added_id); + gtk_signal_disconnect (GTK_OBJECT (node), node->details->files_changed_id); + gtk_signal_disconnect (GTK_OBJECT (node), node->details->done_loading_id); + + nautilus_directory_file_monitor_remove (node->details->directory, + model); + } +} + + +NautilusTreeNode * +nautilus_tree_model_get_node (NautilusTreeModel *model, + const char *uri) +{ + return g_hash_table_lookup (model->details->uri_to_node_map, uri); +} + + +#if 0 NautilusTreeNode *nautilus_tree_model_get_nearest_parent_node (NautilusTreeModel *model, const char *uri); @@ -72,4 +443,169 @@ NautilusTreeNode *nautilus_tree_model_get_nearest_parent_node (NautilusTreeMod NautilusTreeNode *nautilus_tree_model_get_root_node (NautilusTreeModel *model); +#endif + + +static char *uri_get_parent_text (const char *uri_text) +{ + GnomeVFSURI *uri; + GnomeVFSURI *parent; + char *parent_text; + + uri = gnome_vfs_uri_new (uri_text); + parent = gnome_vfs_uri_get_parent (uri); + gnome_vfs_uri_unref (uri); + + if (parent == NULL) { + return NULL; + } + + parent_text = gnome_vfs_uri_to_string (parent, GNOME_VFS_URI_HIDE_NONE); + gnome_vfs_uri_unref (parent); + + return parent_text; +} + +static void +report_node_added (NautilusTreeModel *model, + NautilusTreeNode *node) +{ + char *uri; + char *parent_uri; + NautilusTreeNode *parent_node; + + uri = nautilus_file_get_uri (nautilus_tree_node_get_file (node)); + + if (g_hash_table_lookup (model->details->uri_to_node_map, uri) == NULL) { + parent_uri = uri_get_parent_text (uri); + + if (parent_uri != NULL) { + parent_node = g_hash_table_lookup (model->details->uri_to_node_map, parent_uri); + + if (parent_node != NULL) { + nautilus_tree_node_set_parent (node, + parent_node); + } + + g_free (parent_uri); + } + + + g_hash_table_insert (model->details->uri_to_node_map, + g_strdup (nautilus_file_get_uri (nautilus_tree_node_get_file (node))), + node); + + gtk_signal_emit (GTK_OBJECT (model), + signals[NODE_ADDED], + node); + } else { + /* FIXME: reconstruct internals and report that it changed?? */ + } +} + + +static void +report_node_changed (NautilusTreeModel *model, + NautilusTreeNode *node) +{ + char *uri; + char *parent_uri; + NautilusTreeNode *parent_node; + + uri = nautilus_file_get_uri (nautilus_tree_node_get_file (node)); + + if (g_hash_table_lookup (model->details->uri_to_node_map, uri) == NULL) { + /* Actually added, go figure */ + + parent_uri = uri_get_parent_text (uri); + + if (parent_uri != NULL) { + parent_node = g_hash_table_lookup (model->details->uri_to_node_map, parent_uri); + + if (parent_node != NULL) { + nautilus_tree_node_set_parent (node, + parent_node); + } + + g_free (parent_uri); + } + + + g_hash_table_insert (model->details->uri_to_node_map, + g_strdup (nautilus_file_get_uri (nautilus_tree_node_get_file (node))), + node); + + gtk_signal_emit (GTK_OBJECT (model), + signals[NODE_ADDED], + node); + } else { + /* really changed */ + gtk_signal_emit (GTK_OBJECT (model), + signals[NODE_CHANGED], + node); + } + + g_free (uri); +} + +static void +report_node_removed (NautilusTreeModel *model, + NautilusTreeNode *node) +{ + char *uri; + gpointer orig_key; + gpointer dummy; + char *parent_uri; + NautilusTreeNode *parent_node; + + if (node == NULL) { + return; + } + + uri = nautilus_file_get_uri (nautilus_tree_node_get_file (node)); + + if (g_hash_table_lookup (model->details->uri_to_node_map, uri) != NULL) { + parent_uri = uri_get_parent_text (uri); + + if (parent_uri != NULL) { + parent_node = g_hash_table_lookup (model->details->uri_to_node_map, parent_uri); + + if (parent_node != NULL) { + nautilus_tree_remove_from_parent (node); + } + + g_free (parent_uri); + } + + + g_hash_table_lookup_extended (model->details->uri_to_node_map, + nautilus_file_get_uri (nautilus_tree_node_get_file (node)), + &orig_key, + &dummy); + + g_hash_table_remove (model->details->uri_to_node_map, + nautilus_file_get_uri (nautilus_tree_node_get_file (node))); + + g_free (orig_key); + + gtk_signal_emit (GTK_OBJECT (model), + signals[NODE_REMOVED], + node); + + + gtk_object_unref (GTK_OBJECT (node)); + } + + g_free (uri); + +} + +static void +report_done_loading (NautilusTreeModel *model, + NautilusTreeNode *node) +{ + gtk_signal_emit (GTK_OBJECT (model), + signals[DONE_LOADING_CHILDREN], + node); +} diff --git a/components/tree/nautilus-tree-model.h b/components/tree/nautilus-tree-model.h index 6216143ed..04dae95ca 100644 --- a/components/tree/nautilus-tree-model.h +++ b/components/tree/nautilus-tree-model.h @@ -62,10 +62,9 @@ struct NautilusTreeModelClass { NautilusTreeNode *node); }; -typedef void (*NautilusTreeCallback) (NautilusTreeModel *model, - NautilusTreeNode *node, - GList *child_nodes, - gpointer callback_data); +typedef void (*NautilusTreeModelCallback) (NautilusTreeModel *model, + NautilusTreeNode *node, + gpointer callback_data); GtkType nautilus_tree_model_get_type (void); @@ -73,14 +72,21 @@ GtkType nautilus_tree_model_get_type (void); NautilusTreeModel *nautilus_tree_model_new (const char *root_uri); -void nautilus_tree_model_monitor_node (NautilusTreeModel *model, - NautilusTreeNode *node, - gboolean force_reload, - NautilusTreeCallback initial_files_callback, - gpointer callback_data); +void nautilus_tree_model_monitor_add (NautilusTreeModel *model, + gconstpointer client, + NautilusTreeModelCallback initial_nodes_callback, + gpointer callback_data); -void nautilus_tree_model_stop_monitoring_node (NautilusTreeModel *model, - NautilusTreeNode *node); +void nautilus_tree_model_monitor_remove (NautilusTreeModel *model, + gconstpointer client); + +void nautilus_tree_model_monitor_node (NautilusTreeModel *model, + NautilusTreeNode *node, + gconstpointer client); + +void nautilus_tree_model_stop_monitoring_node (NautilusTreeModel *model, + NautilusTreeNode *node, + gconstpointer client); NautilusTreeNode *nautilus_tree_model_get_node (NautilusTreeModel *model, const char *uri); @@ -95,3 +101,4 @@ NautilusTreeNode *nautilus_tree_model_get_root_node (NautilusTreeMod #endif /* NAUTILUS_TREE_MODEL_H */ + diff --git a/components/tree/nautilus-tree-node.c b/components/tree/nautilus-tree-node.c index 0e4c7d11d..c9ad14175 100644 --- a/components/tree/nautilus-tree-node.c +++ b/components/tree/nautilus-tree-node.c @@ -28,12 +28,81 @@ #include "nautilus-tree-node.h" #include "nautilus-tree-node-private.h" +#include #include #include +static void nautilus_tree_node_destroy (GtkObject *object); +static void nautilus_tree_node_initialize (gpointer object, + gpointer klass); +static void nautilus_tree_node_initialize_class (gpointer klass); + + + +NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusTreeNode, nautilus_tree_node, GTK_TYPE_OBJECT) + + +static void +nautilus_tree_node_initialize_class (gpointer klass) +{ + GtkObjectClass *object_class; + + object_class = GTK_OBJECT_CLASS (klass); + + object_class->destroy = nautilus_tree_node_destroy; +} + +static void +nautilus_tree_node_initialize (gpointer object, gpointer klass) +{ + NautilusTreeNode *node; + + node = NAUTILUS_TREE_NODE (object); + + node->details = g_new0 (NautilusTreeNodeDetails, 1); +} + + +static void +nautilus_tree_node_destroy (GtkObject *object) +{ + NautilusTreeNode *node; + + node = NAUTILUS_TREE_NODE (object); + + nautilus_directory_unref (node->details->directory); + + nautilus_file_unref (node->details->file); + + g_list_free (node->details->children); + + g_free (node->details); + + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); +} + +NautilusTreeNode * +nautilus_tree_node_new (NautilusFile *file) +{ + NautilusTreeNode *node; + char *uri; + + node = NAUTILUS_TREE_NODE (gtk_type_new (NAUTILUS_TYPE_TREE_NODE)); + + node->details = g_new0 (NautilusTreeNodeDetails, 1); + node->details->file = nautilus_file_ref (file); + + uri = nautilus_file_get_uri (file); + node->details->directory = nautilus_directory_get (uri); + g_free (uri); + + return node; +} + + NautilusTreeNode * nautilus_tree_node_get_parent (NautilusTreeNode *node) @@ -41,43 +110,41 @@ nautilus_tree_node_get_parent (NautilusTreeNode *node) return node->details->parent; } -NautilusTreeNode * +GList * nautilus_tree_node_get_children (NautilusTreeNode *node) { return node->details->children; } -NautilusTreeNode * +NautilusFile * nautilus_tree_node_get_file (NautilusTreeNode *node) { return node->details->file; } -NautilusTreeNode * +NautilusDirectory * nautilus_tree_node_get_directory (NautilusTreeNode *node) { return node->details->directory; } - void -nautilus_tree_node_set_user_data (NautilusTreeNode *node, - gpointer user_data, - GDestroyNotifyFunc destroy_notify) +nautilus_tree_node_set_parent (NautilusTreeNode *node, + NautilusTreeNode *parent) { - if (node->details->user_data != NULL) { - /* FIXME: call old destroy_notify */ - } + g_assert (node->details->parent == NULL); - node->details->user_data = user_data; - node->details->destroy_notify = destroy_notify; + node->details->parent = parent; + parent->details->children = g_list_append (parent->details->children, node); } -gpointer -nautilus_tree_node_get_user_data (NautilusTreeNode *node) -{ - return node->details->user_data; +void +nautilus_tree_remove_from_parent (NautilusTreeNode *node) +{ + if (node->details->parent != NULL) { + node->details->parent->details->children = g_list_remove + (node->details->parent->details->children, node); + node->details->parent = NULL; + } } - - diff --git a/components/tree/nautilus-tree-node.h b/components/tree/nautilus-tree-node.h index 45a55ee6c..b8e942fcf 100644 --- a/components/tree/nautilus-tree-node.h +++ b/components/tree/nautilus-tree-node.h @@ -27,6 +27,9 @@ #define NAUTILUS_TREE_NODE_H #include +#include +#include +#include typedef struct NautilusTreeNode NautilusTreeNode; typedef struct NautilusTreeNodeClass NautilusTreeNodeClass; @@ -49,10 +52,12 @@ struct NautilusTreeNodeClass { }; -NautilusTreeNode *nautilus_tree_node_get_parent (NautilusTreeNode *node); -NautilusTreeNode *nautilus_tree_node_get_children (NautilusTreeNode *node); -NautilusTreeNode *nautilus_tree_node_get_file (NautilusTreeNode *node); -NautilusTreeNode *nautilus_tree_node_get_directory (NautilusTreeNode *node); +GtkType nautilus_tree_node_get_type (void); + +NautilusTreeNode *nautilus_tree_node_get_parent (NautilusTreeNode *node); +GList *nautilus_tree_node_get_children (NautilusTreeNode *node); +NautilusFile *nautilus_tree_node_get_file (NautilusTreeNode *node); +NautilusDirectory *nautilus_tree_node_get_directory (NautilusTreeNode *node); void nautilus_tree_node_set_user_data (NautilusTreeNode *node, gpointer user_data, diff --git a/components/tree/nautilus-tree-view.c b/components/tree/nautilus-tree-view.c index 87a669048..085dae926 100644 --- a/components/tree/nautilus-tree-view.c +++ b/components/tree/nautilus-tree-view.c @@ -30,6 +30,8 @@ #include #include "nautilus-tree-view.h" +#include "nautilus-tree-model.h" + #include #include #include @@ -56,34 +58,27 @@ struct NautilusTreeViewDetails { GtkWidget *tree; - GHashTable *uri_to_node_map; - GHashTable *uri_to_directory_map; - - GList *directory_read_queue; - NautilusDirectory *current_directory; + NautilusTreeModel *model; - GList *pending_files_added; - GList *pending_files_changed; - - guint display_pending_timeout_id; - guint display_pending_idle_id; - guint files_added_handler_id; - guint files_changed_handler_id; + GHashTable *uri_to_node_map; gboolean show_hidden_files; }; #define TREE_SPACING 3 -static void nautilus_tree_view_insert_file (NautilusTreeView *view, NautilusFile *file); - static void nautilus_tree_view_initialize_class (NautilusTreeViewClass *klass); static void nautilus_tree_view_initialize (NautilusTreeView *view); static void nautilus_tree_view_destroy (GtkObject *object); static void tree_load_location_callback (NautilusView *nautilus_view, const char *location, NautilusTreeView *view); -static void tree_expand_callback (NautilusView *nautilus_view, + +static void tree_expand_callback (GtkCTree *tree, + GtkCTreeNode *node, + NautilusTreeView *view); + +static void tree_collapse_callback (GtkCTree *tree, GtkCTreeNode *node, NautilusTreeView *view); @@ -95,41 +90,11 @@ static void tree_select_row_callback (GtkCTree *tree, static void nautilus_tree_view_load_uri (NautilusTreeView *view, const char *uri); -static void files_added_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data); - -static void files_changed_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data); - -static void done_loading_callback (NautilusDirectory *directory, - gpointer callback_data); - NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusTreeView, nautilus_tree_view, GTK_TYPE_SCROLLED_WINDOW) -static void -nautilus_tree_view_file_added (NautilusTreeView *view, NautilusFile *file) -{ -#ifdef DEBUG_TREE - printf ("file added: %s\n", nautilus_file_get_uri (file)); -#endif - nautilus_tree_view_insert_file (view, file); - -} - -static void -nautilus_tree_view_file_changed (NautilusTreeView *view, NautilusFile *file) -{ -#ifdef DEBUG_TREE - printf ("file changed: %s\n", nautilus_file_get_uri (file)); -#endif - /* FIXME bugzilla.eazel.com 1522: should actually do something here. */ -} - static void nautilus_tree_view_initialize_class (NautilusTreeViewClass *klass) @@ -142,317 +107,6 @@ nautilus_tree_view_initialize_class (NautilusTreeViewClass *klass) } -static void -nautilus_tree_view_read_head_of_queue (NautilusTreeView *view) -{ - if (view->details->directory_read_queue == NULL) { -#ifdef DEBUG_TREE - puts ("No queue"); -#endif - return; - } - - view->details->current_directory = NAUTILUS_DIRECTORY (view->details->directory_read_queue->data); - - -#ifdef DEBUG_TREE - printf ("XXX: Now scanning directory %s\n", nautilus_directory_get_uri (view->details->current_directory)); -#endif - - /* Attach a handler to get any further files that show up as we - * load and sychronize. We won't miss any files because this - * signal is emitted from an idle routine and so we will be - * connected before the next time it is emitted. - */ - view->details->files_added_handler_id = gtk_signal_connect - (GTK_OBJECT (view->details->current_directory), - "files_added", - GTK_SIGNAL_FUNC (files_added_callback), - view); - view->details->files_changed_handler_id = gtk_signal_connect - (GTK_OBJECT (view->details->current_directory), - "files_changed", - GTK_SIGNAL_FUNC (files_changed_callback), - view); - view->details->files_added_handler_id = gtk_signal_connect - (GTK_OBJECT (view->details->current_directory), - "done_loading", - GTK_SIGNAL_FUNC (done_loading_callback), - view); - - nautilus_directory_file_monitor_add (view->details->current_directory, view, - NULL, FALSE, TRUE, - files_added_callback, view); - - - - - view->details->directory_read_queue = view->details->directory_read_queue->next; -} - - -static gboolean -display_pending_files (NautilusTreeView *view) -{ - GList *files_added, *files_changed, *p; - NautilusFile *file; - - if (view->details->current_directory != NULL - && nautilus_directory_are_all_files_seen (view->details->current_directory)) { - /* done_loading (view); */ - } - - files_added = view->details->pending_files_added; - files_changed = view->details->pending_files_changed; - - if (files_added == NULL && files_changed == NULL) { - return FALSE; - } - - view->details->pending_files_added = NULL; - view->details->pending_files_changed = NULL; - - /* XXX gtk_signal_emit (GTK_OBJECT (view), signals[BEGIN_ADDING_FILES]); */ - - for (p = files_added; p != NULL; p = p->next) { - file = p->data; - - /* FIXME bugzilla.eazel.com 1520: Need to do a better test to see if the info is up to date. */ -#if 0 - if (nautilus_directory_contains_file (view->details->current_directory, file)) { -#endif - nautilus_tree_view_file_added (view, file); -#if 0 - } -#endif - } - - for (p = files_changed; p != NULL; p = p->next) { - file = p->data; - - nautilus_tree_view_file_changed (view, file); - } - - /* gtk_signal_emit (GTK_OBJECT (view), signals[DONE_ADDING_FILES]); */ - - nautilus_file_list_free (files_added); - nautilus_file_list_free (files_changed); - - return TRUE; -} - - -static gboolean -display_pending_idle_callback (gpointer data) -{ - /* Don't do another idle until we receive more files. */ - - NautilusTreeView *view; - - view = NAUTILUS_TREE_VIEW (data); - - view->details->display_pending_idle_id = 0; - - display_pending_files (view); - - return FALSE; -} - - -static gboolean -display_pending_timeout_callback (gpointer data) -{ - /* Do another timeout if we displayed some files. - * Once we get all the files, we'll start using - * idle instead. - */ - - NautilusTreeView *view; - gboolean displayed_some; - - view = NAUTILUS_TREE_VIEW (data); - - displayed_some = display_pending_files (view); - if (displayed_some) { - return TRUE; - } - - view->details->display_pending_timeout_id = 0; - return FALSE; -} - - - -static void -unschedule_timeout_display_of_pending_files (NautilusTreeView *view) -{ - /* Get rid of timeout if it's active. */ - if (view->details->display_pending_timeout_id != 0) { - g_assert (view->details->display_pending_idle_id == 0); - gtk_timeout_remove (view->details->display_pending_timeout_id); - view->details->display_pending_timeout_id = 0; - } -} - -static void -schedule_idle_display_of_pending_files (NautilusTreeView *view) -{ - /* No need to schedule an idle if there's already one pending. */ - if (view->details->display_pending_idle_id != 0) { - return; - } - - /* An idle takes precedence over a timeout. */ - unschedule_timeout_display_of_pending_files (view); - - view->details->display_pending_idle_id = - gtk_idle_add (display_pending_idle_callback, view); -} - -static void -schedule_timeout_display_of_pending_files (NautilusTreeView *view) -{ - /* No need to schedule a timeout if there's already one pending. */ - if (view->details->display_pending_timeout_id != 0) { - return; - } - - /* An idle takes precedence over a timeout. */ - if (view->details->display_pending_idle_id != 0) { - return; - } - - view->details->display_pending_timeout_id = - gtk_timeout_add (DISPLAY_TIMEOUT_INTERVAL_MSECS, - display_pending_timeout_callback, view); -} - -static void -unschedule_idle_display_of_pending_files (NautilusTreeView *view) -{ - /* Get rid of idle if it's active. */ - if (view->details->display_pending_idle_id != 0) { - g_assert (view->details->display_pending_timeout_id == 0); - gtk_idle_remove (view->details->display_pending_idle_id); - view->details->display_pending_idle_id = 0; - } -} - -static void -unschedule_display_of_pending_files (NautilusTreeView *view) -{ - unschedule_idle_display_of_pending_files (view); - unschedule_timeout_display_of_pending_files (view); -} - -static void -queue_pending_files (NautilusTreeView *view, - GList *files, - GList **pending_list) -{ - GList *filtered_files = NULL; - GList *files_iterator; - NautilusFile *file; - char * name; - - /* Filter out hidden files if needed */ - if (!view->details->show_hidden_files) { - /* FIXME bugzilla.eazel.com 653: - * Eventually this should become a generic filtering thingy. - */ - for (files_iterator = files; - files_iterator != NULL; - files_iterator = files_iterator->next) { - file = NAUTILUS_FILE (files_iterator->data); - - g_assert (file != NULL); - - name = nautilus_file_get_name (file); - - g_assert (name != NULL); - - if (!nautilus_str_has_prefix (name, ".")) { - filtered_files = g_list_append (filtered_files, file); - } - - g_free (name); - } - - files = filtered_files; - } - - /* Put the files on the pending list if there are any. */ - if (files != NULL) { - nautilus_file_list_ref (files); - *pending_list = g_list_concat (*pending_list, g_list_copy (files)); - - /* If we haven't see all the files yet, then we'll wait for the - * timeout to fire. If we have seen all the files, then we'll use - * an idle instead. - */ - if (nautilus_directory_are_all_files_seen (view->details->current_directory)) { - schedule_idle_display_of_pending_files (view); - } else { - schedule_timeout_display_of_pending_files (view); - } - } -} - -static void -files_added_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data) -{ - NautilusTreeView *view; - -#ifdef DEBUG_TREE - puts ("XXX - files_added_callback"); -#endif - - view = NAUTILUS_TREE_VIEW (callback_data); - queue_pending_files (view, files, &view->details->pending_files_added); -} - -static void -done_loading_callback (NautilusDirectory *directory, - gpointer callback_data) -{ - NautilusTreeView *view; - -#ifdef DEBUG_TREE - puts ("XXX - files_added_callback"); -#endif - - view = NAUTILUS_TREE_VIEW (callback_data); - - if (nautilus_directory_are_all_files_seen (directory)) { -#ifdef DEBUG_TREE - puts ("XXX - should move head of queue ahead here"); -#endif - -#ifdef DEBUG_TREE - printf ("Just finished reading '%s', moving queue ahead to '%s'\n", - nautilus_directory_get_uri (directory), - (view->details->directory_read_queue == NULL ? "none" : nautilus_directory_get_uri (NAUTILUS_DIRECTORY (view->details->directory_read_queue->data)))); -#endif DEBUG_TREE - - - view->details->current_directory = NULL; - nautilus_tree_view_read_head_of_queue (view); - } -} - - -static void -files_changed_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data) -{ - NautilusTreeView *view; - - view = NAUTILUS_TREE_VIEW (callback_data); - queue_pending_files (view, files, &view->details->pending_files_changed); -} static char * @@ -530,62 +184,107 @@ nautilus_tree_view_get_canonical_uri (const char *uri) +static gboolean +nautilus_tree_view_should_skip_file (NautilusTreeView *view, + NautilusFile *file) +{ + char *name; + gboolean should_skip; + + should_skip = FALSE; + + /* FIXME: maybe this should track the "show hidden files" preference? */ + + if (!view->details->show_hidden_files) { + + /* FIXME bugzilla.eazel.com 653: + * Eventually this should become a generic filtering thingy. + */ + + name = nautilus_file_get_name (file); + + g_assert (name != NULL); + + if (nautilus_str_has_prefix (name, ".")) { + should_skip = TRUE; + } + + g_free (name); + } + + return should_skip; +} + static void -nautilus_tree_view_insert_file (NautilusTreeView *view, NautilusFile *file) +nautilus_tree_view_insert_model_node (NautilusTreeView *view, NautilusTreeNode *node) { - GtkCTreeNode *parent_node; - GtkCTreeNode *node; - GtkCTreeNode *previous_sibling_node; + GtkCTreeNode *parent_view_node; + GtkCTreeNode *view_node; + NautilusFile *file; + char *uri; + char *canonical_uri; char *name; char *text[2]; - char *canonical_uri; GdkPixmap *pixmap; GdkBitmap *mask; - canonical_uri = nautilus_tree_view_get_canonical_uri (nautilus_file_get_uri (file)); + file = nautilus_tree_node_get_file (node); + + if (nautilus_tree_view_should_skip_file (view, file)) { + return; + } + + uri = nautilus_file_get_uri (file); + + canonical_uri = nautilus_tree_view_get_canonical_uri (uri); + + g_free (uri); #ifdef DEBUG_TREE printf ("Inserting URI into tree: %s\n", canonical_uri); #endif + parent_view_node = nautilus_tree_view_find_parent_node (view, canonical_uri); + +#ifdef DEBUG_TREE + printf ("parent_view_node 0x%x (%s)\n", (unsigned) parent_view_node, + (char *) gtk_ctree_node_get_row_data (GTK_CTREE (view->details->tree), + parent_view_node)); +#endif - parent_node = nautilus_tree_view_find_parent_node (view, canonical_uri); - previous_sibling_node = NULL; name = nautilus_tree_view_uri_to_name (canonical_uri); text[0] = name; text[1] = NULL; - node = g_hash_table_lookup (view->details->uri_to_node_map, canonical_uri); - - if (node == NULL) { + if (g_hash_table_lookup (view->details->uri_to_node_map, canonical_uri) == NULL) { /* FIXME bugzilla.eazel.com 1524: still need to respond to icon theme changes. */ - nautilus_icon_factory_get_pixmap_and_mask_for_file (file, NULL, NAUTILUS_ICON_SIZE_FOR_MENUS, &pixmap, &mask); - node = gtk_ctree_insert_node (GTK_CTREE (view->details->tree), - parent_node, - previous_sibling_node, - text, - TREE_SPACING, - pixmap, mask, pixmap, mask, - FALSE, - - /* FIXME bugzilla.eazel.com 1525: should - remember what was - expanded last time and what - wasn't. On first start, we should - expand "/" and leave everything else - collapsed. */ - FALSE); + view_node = gtk_ctree_insert_node (GTK_CTREE (view->details->tree), + parent_view_node, + NULL, + text, + TREE_SPACING, + pixmap, mask, pixmap, mask, + FALSE, + + /* FIXME bugzilla.eazel.com 1525: should + remember what was + expanded last time and what + wasn't. On first start, we should + expand "/" and leave everything else + collapsed. */ + FALSE); + if (nautilus_file_is_directory (file)) { /* Gratuitous hack so node can be expandable w/o immediately inserting all the real children. */ @@ -593,7 +292,7 @@ nautilus_tree_view_insert_file (NautilusTreeView *view, NautilusFile *file) text[0] = "...HACK..."; text[1] = NULL; gtk_ctree_insert_node (GTK_CTREE (view->details->tree), - node, + view_node, NULL, text, TREE_SPACING, @@ -601,95 +300,176 @@ nautilus_tree_view_insert_file (NautilusTreeView *view, NautilusFile *file) FALSE, FALSE); } - } - - - gtk_ctree_node_set_row_data_full (GTK_CTREE (view->details->tree), - node, - g_strdup (canonical_uri), - g_free); + gtk_ctree_node_set_row_data_full (GTK_CTREE (view->details->tree), + view_node, + g_strdup (canonical_uri), + g_free); -#ifdef DEBUG_TREE - printf ("XXX - putting node in hash_table: %s\n", canonical_uri); -#endif - - g_hash_table_insert (view->details->uri_to_node_map, canonical_uri, node); + g_hash_table_insert (view->details->uri_to_node_map, canonical_uri, view_node); + } } static void -nautilus_tree_view_enqueue_directory (NautilusTreeView *view, - NautilusDirectory *directory) +nautilus_tree_view_remove_model_node (NautilusTreeView *view, NautilusTreeNode *node) { - /* FIXME bugzilla.eazel.com 1526: check if it's already on the - queue first. */ + GtkCTreeNode *view_node; + NautilusFile *file; + char *canonical_uri; + char *uri; + + file = nautilus_tree_node_get_file (node); - view->details->directory_read_queue = g_list_append (view->details->directory_read_queue, - directory); + uri = nautilus_file_get_uri (file); + canonical_uri = nautilus_tree_view_get_canonical_uri (uri); + g_free (uri); + + view_node = g_hash_table_lookup (view->details->uri_to_node_map, canonical_uri); + + if (view_node != NULL) { + gtk_ctree_remove_node (GTK_CTREE (view->details->tree), + view_node); + + /* FIXME: free the original key */ + g_hash_table_remove (view->details->uri_to_node_map, canonical_uri); + } -#ifdef DEBUG_TREE - printf ("just enqueue'd: 0x%x (%s)\n", (unsigned) directory, nautilus_directory_get_uri (directory)); - printf ("queue length: %d\n", g_list_length (view->details->directory_read_queue)); -#endif + g_free (canonical_uri); - if (view->details->current_directory == NULL) { -#ifdef DEBUG_TREE - printf ("reading head of queue"); -#endif - nautilus_tree_view_read_head_of_queue (view); - } } static void -nautilus_tree_view_load_uri_children (NautilusTreeView *view, const char *uri, gboolean is_root) +nautilus_tree_view_update_model_node (NautilusTreeView *view, NautilusTreeNode *node) { - NautilusDirectory *directory; - NautilusFile *file; - + GtkCTreeNode *view_node; + NautilusFile *file; char *canonical_uri; + char *uri; + char *name; + GdkPixmap *pixmap; + GdkBitmap *mask; - canonical_uri = nautilus_tree_view_get_canonical_uri (uri); + file = nautilus_tree_node_get_file (node); - file = nautilus_file_get (canonical_uri); + /* FIXME: leaks non-canonical URI */ + uri = nautilus_file_get_uri (file); + canonical_uri = nautilus_tree_view_get_canonical_uri (uri); + g_free (uri); - /* FIXME bugzilla.eazel.com 1519: remove gone files when - rescaning directory. To implement it here, we should remove all - children of the node for the dir before we load it. */ + view_node = g_hash_table_lookup (view->details->uri_to_node_map, canonical_uri); - if (is_root || nautilus_file_is_directory (file)) { - directory = nautilus_directory_get (canonical_uri); + if (view_node != NULL) { - /* Should clear out all children first */ + name = nautilus_tree_view_uri_to_name (canonical_uri); + + nautilus_icon_factory_get_pixmap_and_mask_for_file (file, + NULL, + NAUTILUS_ICON_SIZE_FOR_MENUS, + &pixmap, + &mask); - nautilus_tree_view_enqueue_directory (view, - directory); + gtk_ctree_node_set_pixtext (GTK_CTREE (view->details->tree), + view_node, + 0, + name, + TREE_SPACING, + pixmap, + mask); + +#if 0 + /* FIXME: should switch to this call so we can set open/closed pixamps */ + void gtk_ctree_set_node_info (GtkCTree *ctree, + GtkCTreeNode *node, + const gchar *text, + guint8 spacing, + GdkPixmap *pixmap_closed, + GdkBitmap *mask_closed, + GdkPixmap *pixmap_opened, + GdkBitmap *mask_opened, + gboolean is_leaf, + gboolean expanded); +#endif } - nautilus_file_unref (file); + } + static void -nautilus_tree_view_load_from_filesystem (NautilusTreeView *view) +nautilus_tree_view_model_node_added_callback (NautilusTreeModel *model, + NautilusTreeNode *node, + gpointer callback_data) { - NautilusFile *file; - /* Start loading. */ + NautilusTreeView *view; + + view = NAUTILUS_TREE_VIEW (callback_data); + + nautilus_tree_view_insert_model_node (view, node); +} + + + + + +static void +nautilus_tree_view_model_node_changed_callback (NautilusTreeModel *model, + NautilusTreeNode *node, + gpointer callback_data) +{ + NautilusTreeView *view; + + view = NAUTILUS_TREE_VIEW (callback_data); + + /* Assume file did not change location - we will model that as a remove + an add */ + nautilus_tree_view_update_model_node (view, node); +} - file = nautilus_file_get ("file:/"); +static void +nautilus_tree_view_model_node_removed_callback (NautilusTreeModel *model, + NautilusTreeNode *node, + gpointer callback_data) +{ + NautilusTreeView *view; - nautilus_tree_view_insert_file (view, file); - nautilus_tree_view_load_uri_children (view, "file:/", TRUE); + view = NAUTILUS_TREE_VIEW (callback_data); - nautilus_file_unref (file); + nautilus_tree_view_remove_model_node (view, node); } +static void +nautilus_tree_view_load_from_filesystem (NautilusTreeView *view) +{ + view->details->model = nautilus_tree_model_new ("file:///"); + + nautilus_tree_model_monitor_add (view->details->model, + view, + nautilus_tree_view_model_node_added_callback, + view); + + gtk_signal_connect (GTK_OBJECT (view->details->model), + "node_added", + nautilus_tree_view_model_node_added_callback, + view); + gtk_signal_connect (GTK_OBJECT (view->details->model), + "node_changed", + nautilus_tree_view_model_node_changed_callback, + view); + gtk_signal_connect (GTK_OBJECT (view->details->model), + "node_removed", + nautilus_tree_view_model_node_removed_callback, + view); +} + + + static void nautilus_tree_view_initialize (NautilusTreeView *view) { @@ -719,6 +499,11 @@ nautilus_tree_view_initialize (NautilusTreeView *view) "tree_expand", GTK_SIGNAL_FUNC (tree_expand_callback), view); + + gtk_signal_connect (GTK_OBJECT (view->details->tree), + "tree_collapse", + GTK_SIGNAL_FUNC (tree_collapse_callback), + view); gtk_signal_connect (GTK_OBJECT (view->details->tree), "tree_select_row", @@ -733,7 +518,7 @@ nautilus_tree_view_initialize (NautilusTreeView *view) view); view->details->uri_to_node_map = g_hash_table_new (g_str_hash, g_str_equal); - + nautilus_tree_view_load_from_filesystem (view); gtk_widget_show (view->details->tree); @@ -744,27 +529,12 @@ nautilus_tree_view_initialize (NautilusTreeView *view) } -static void -disconnect_handler (NautilusTreeView *view, int *id) -{ - if (*id != 0) { - gtk_signal_disconnect (GTK_OBJECT (view->details->current_directory), *id); - *id = 0; - } -} static void disconnect_model_handlers (NautilusTreeView *view) { - /* FIXME bugzilla.eazel.com 1527: this is bogus, we need to - disconnect from all NautilusDirectories, not just the most - recent one. */ - - disconnect_handler (view, &view->details->files_added_handler_id); - disconnect_handler (view, &view->details->files_changed_handler_id); - if (view->details->current_directory != NULL) { - nautilus_directory_file_monitor_remove (view->details->current_directory, view); - } + /* stop monitoring all the nodes, then stop monitoring the + whole */ } @@ -775,13 +545,7 @@ nautilus_tree_view_destroy (GtkObject *object) view = NAUTILUS_TREE_VIEW (object); - - if (view->details->current_directory != NULL) { - disconnect_model_handlers (view); - nautilus_directory_unref (view->details->current_directory); - } - - unschedule_display_of_pending_files (view); + disconnect_model_handlers (view); g_free (view->details); @@ -847,34 +611,49 @@ tree_load_location_callback (NautilusView *nautilus_view, } + static void -nautilus_tree_expand_uri (NautilusTreeView *view, const char *uri) +tree_expand_callback (GtkCTree *ctree, + GtkCTreeNode *node, + NautilusTreeView *view) { - /* Refresh children */ - nautilus_tree_view_load_uri_children (view, uri, FALSE); + const char *uri; + + uri = (const char *) gtk_ctree_node_get_row_data (GTK_CTREE (view->details->tree), + node); + + nautilus_tree_model_monitor_node (view->details->model, + nautilus_tree_model_get_node (view->details->model, + uri), + view); } + static void -tree_expand_callback (NautilusView *nautilus_view, - GtkCTreeNode *node, - NautilusTreeView *view) +tree_collapse_callback (GtkCTree *ctree, + GtkCTreeNode *node, + NautilusTreeView *view) { const char *uri; uri = (const char *) gtk_ctree_node_get_row_data (GTK_CTREE (view->details->tree), node); - nautilus_tree_expand_uri (view, uri); + nautilus_tree_model_stop_monitoring_node (view->details->model, + nautilus_tree_model_get_node (view->details->model, + uri), + view); } -static void tree_select_row_callback (GtkCTree *tree, - GtkCTreeNode *node, - gint column, - NautilusTreeView *view) +static void +tree_select_row_callback (GtkCTree *tree, + GtkCTreeNode *node, + gint column, + NautilusTreeView *view) { const char *uri; @@ -886,3 +665,6 @@ static void tree_select_row_callback (GtkCTree *tree, nautilus_view_open_location (NAUTILUS_VIEW (view->details->nautilus_view), uri); } } + + + -- cgit v1.2.1