diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index 926658816d8b40891a745940379feea9f55064a8..5057f3b20d2faf3aeaac0a8ee59870feb481d88d 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -212,7 +212,6 @@ typedef struct * after it finishes loading the directory and its view. */ gboolean loading; - gboolean subdirectory_loading; gboolean in_destruction; @@ -224,6 +223,7 @@ typedef struct gboolean metadata_for_files_in_directory_pending; GList *subdirectory_list; + GList *subdirectories_loading; GMenu *selection_menu_model; GMenu *background_menu_model; @@ -734,23 +734,6 @@ real_end_loading (NautilusFilesView *self, update_cut_status (self); } -static char * -real_get_backing_uri (NautilusFilesView *view) -{ - NautilusFilesViewPrivate *priv; - - g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); - - priv = nautilus_files_view_get_instance_private (view); - - if (priv->directory == NULL) - { - return NULL; - } - - return nautilus_directory_get_uri (priv->directory); -} - /** * * nautilus_files_view_get_backing_uri: @@ -764,7 +747,19 @@ nautilus_files_view_get_backing_uri (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); - return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_backing_uri (view); + NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); + g_autoptr (NautilusViewItem) item = nautilus_list_base_get_backing_item (NAUTILUS_LIST_BASE (view)); + + if (item != NULL) + { + return nautilus_file_get_uri (nautilus_view_item_get_file (item)); + } + else if (priv->directory != NULL) + { + return nautilus_directory_get_uri (priv->directory); + } + + return NULL; } /** @@ -1225,18 +1220,6 @@ nautilus_files_view_get_window (NautilusFilesView *view) return nautilus_window_slot_get_window (priv->slot); } -NautilusWindowSlot * -nautilus_files_view_get_nautilus_window_slot (NautilusFilesView *view) -{ - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - g_assert (priv->slot != NULL); - - return priv->slot; -} - /* Returns the GtkWindow that this directory view occupies, or NULL * if at the moment this directory view is not in a GtkWindow or the * GtkWindow cannot be determined. Primarily used for parenting dialogs. @@ -1446,7 +1429,8 @@ action_open_item_location (GSimpleAction *action, GVariant *state, gpointer user_data) { - NautilusFilesView *view; + NautilusFilesView *view = NAUTILUS_FILES_VIEW (user_data); + NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); g_autolist (NautilusFile) selection = NULL; NautilusFile *item; GFile *activation_location; @@ -1454,7 +1438,6 @@ action_open_item_location (GSimpleAction *action, NautilusFile *parent; g_autoptr (GFile) parent_location = NULL; - view = NAUTILUS_FILES_VIEW (user_data); selection = nautilus_view_get_selection (NAUTILUS_VIEW (view)); if (!selection) @@ -1479,7 +1462,7 @@ action_open_item_location (GSimpleAction *action, nautilus_application_open_location_full (NAUTILUS_APPLICATION (g_application_get_default ()), parent_location, 0, selection, NULL, - nautilus_files_view_get_nautilus_window_slot (view)); + priv->slot); nautilus_file_unref (parent); nautilus_file_unref (activation_file); @@ -3282,6 +3265,34 @@ on_popup_selection_context_menu (NautilusListBase *list_base, nautilus_files_view_pop_up_selection_context_menu (self, &view_point); } +static void +on_load_subdirectory (NautilusListBase *list_base, + NautilusViewItem *item, + gpointer user_data) +{ + NautilusFilesView *self = NAUTILUS_FILES_VIEW (user_data); + g_autoptr (NautilusDirectory) directory = nautilus_directory_get_for_file (nautilus_view_item_get_file (item)); + + if (!nautilus_files_view_has_subdirectory (self, directory)) + { + nautilus_files_view_add_subdirectory (self, directory); + } +} + +static void +on_unload_subdirectory (NautilusListBase *list_base, + NautilusViewItem *item, + gpointer user_data) +{ + NautilusFilesView *self = NAUTILUS_FILES_VIEW (user_data); + g_autoptr (NautilusDirectory) directory = nautilus_directory_get_for_file (nautilus_view_item_get_file (item)); + + if (nautilus_files_view_has_subdirectory (self, directory)) + { + nautilus_files_view_remove_subdirectory (self, directory); + } +} + static void nautilus_files_view_constructed (GObject *object) { @@ -3311,6 +3322,16 @@ nautilus_files_view_constructed (GObject *object) g_signal_connect_object (NAUTILUS_LIST_BASE (self), "popup-selection-context-menu", G_CALLBACK (on_popup_selection_context_menu), self, G_CONNECT_DEFAULT); + + if (NAUTILUS_IS_LIST_VIEW (NAUTILUS_LIST_BASE (self))) + { + g_signal_connect_object (NAUTILUS_LIST_BASE (self), "load-subdirectory", + G_CALLBACK (on_load_subdirectory), self, + G_CONNECT_DEFAULT); + g_signal_connect_object (NAUTILUS_LIST_BASE (self), "unload-subdirectory", + G_CALLBACK (on_unload_subdirectory), self, + G_CONNECT_DEFAULT); + } } static void @@ -3349,6 +3370,7 @@ nautilus_files_view_dispose (GObject *object) remove_directory_from_templates_directory_list (view, node->data); } + g_clear_pointer (&priv->subdirectories_loading, g_list_free); while (priv->subdirectory_list != NULL) { nautilus_files_view_remove_subdirectory (view, @@ -4612,7 +4634,7 @@ queue_pending_files (NautilusFilesView *view, * search it can be a long wait, and we actually want to show files as * they are getting found. So for search is fine if not all files are * seen */ - if ((!priv->loading && !priv->subdirectory_loading) || + if ((!priv->loading && priv->subdirectories_loading == NULL) || (nautilus_directory_are_all_files_seen (directory) || nautilus_view_is_searching (NAUTILUS_VIEW (view)))) { @@ -4823,8 +4845,15 @@ subdirectory_done_loading (NautilusDirectory *directory, { NautilusFilesView *view = user_data; NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); + g_autoptr (NautilusFile) file = nautilus_directory_get_corresponding_file (directory); + NautilusViewItem *item = nautilus_view_model_get_item_for_file (priv->model, file); - priv->subdirectory_loading = FALSE; + priv->subdirectories_loading = g_list_remove (priv->subdirectories_loading, directory); + + if (item != NULL) + { + nautilus_view_item_set_loading (item, FALSE); + } } void @@ -4832,11 +4861,9 @@ nautilus_files_view_add_subdirectory (NautilusFilesView *view, NautilusDirectory *directory) { NautilusFileAttributes attributes; - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - priv->subdirectory_loading = TRUE; + NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); + g_autoptr (NautilusFile) file = nautilus_directory_get_corresponding_file (directory); + NautilusViewItem *item = nautilus_view_model_get_item_for_file (priv->model, file); g_return_if_fail (!g_list_find (priv->subdirectory_list, directory)); @@ -4865,23 +4892,36 @@ nautilus_files_view_add_subdirectory (NautilusFilesView *view, G_CALLBACK (subdirectory_done_loading), view, 0); - priv->subdirectory_list = g_list_prepend ( - priv->subdirectory_list, directory); + priv->subdirectory_list = g_list_prepend (priv->subdirectory_list, directory); + priv->subdirectories_loading = g_list_prepend (priv->subdirectories_loading, directory); + + if (item != NULL && + !nautilus_directory_are_all_files_seen (directory)) + { + nautilus_view_item_set_loading (item, TRUE); + } } void nautilus_files_view_remove_subdirectory (NautilusFilesView *view, NautilusDirectory *directory) { - NautilusFilesViewPrivate *priv; - priv = nautilus_files_view_get_instance_private (view); - - priv->subdirectory_loading = FALSE; + NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); + g_autoptr (NautilusFile) file = nautilus_directory_get_corresponding_file (directory); + NautilusViewItem *item = nautilus_view_model_get_item_for_file (priv->model, file); g_return_if_fail (g_list_find (priv->subdirectory_list, directory)); - priv->subdirectory_list = g_list_remove ( - priv->subdirectory_list, directory); + priv->subdirectory_list = g_list_remove (priv->subdirectory_list, directory); + priv->subdirectories_loading = g_list_remove (priv->subdirectories_loading, directory); + + if (item != NULL) + { + nautilus_view_item_set_loading (item, FALSE); + + /* The model holds a GListStore for every subdirectory. Empty it. */ + nautilus_view_model_clear_subdirectory (priv->model, item); + } g_signal_handlers_disconnect_by_func (directory, G_CALLBACK (files_added_callback), @@ -8688,6 +8728,7 @@ load_directory (NautilusFilesView *view, */ schedule_update_context_menus (view); + g_clear_pointer (&priv->subdirectories_loading, g_list_free); while (priv->subdirectory_list != NULL) { nautilus_files_view_remove_subdirectory (view, @@ -9538,7 +9579,6 @@ nautilus_files_view_class_init (NautilusFilesViewClass *klass) klass->end_file_changes = real_end_file_changes; klass->begin_loading = real_begin_loading; klass->end_loading = real_end_loading; - klass->get_backing_uri = real_get_backing_uri; klass->update_context_menus = real_update_context_menus; klass->update_actions_state = real_update_actions_state; klass->check_empty_states = real_check_empty_states; diff --git a/src/nautilus-files-view.h b/src/nautilus-files-view.h index 3c198d73473bcf6fe013f9a65adbc0731a49a3a4..3f6cdaa36a6081b9acbb457c627b7b42d77191b0 100644 --- a/src/nautilus-files-view.h +++ b/src/nautilus-files-view.h @@ -98,14 +98,6 @@ struct _NautilusFilesViewClass { /* Function pointers that don't have corresponding signals */ - /* get_backing uri is a function pointer for subclasses to - * override. Subclasses may replace it with a function that - * returns the URI for the location where to create new folders, - * files, links and paste the clipboard to. - */ - - char * (* get_backing_uri) (NautilusFilesView *view); - /* update_menus is a function pointer that subclasses can override to * update the sensitivity or wording of menu items in the menu bar. * It is called (at least) whenever the selection changes. If overridden, @@ -123,9 +115,6 @@ struct _NautilusFilesViewClass { NautilusFilesView * nautilus_files_view_new (guint id, NautilusWindowSlot *slot); -/* Functions callable from the user interface and elsewhere. */ -NautilusWindowSlot *nautilus_files_view_get_nautilus_window_slot (NautilusFilesView *view); - /* Wrappers for signal emitters. These are normally called * only by NautilusFilesView itself. They have corresponding signals * that observers might want to connect with. diff --git a/src/nautilus-list-base.c b/src/nautilus-list-base.c index be2bdbeb5b074946775b6d8517d22922a8b7f8fc..45f49b96f88c50ee56659097453e377353878266 100644 --- a/src/nautilus-list-base.c +++ b/src/nautilus-list-base.c @@ -945,6 +945,12 @@ nautilus_list_base_get_selected_item_ui (NautilusListBase *self) return nautilus_view_item_get_item_ui (item); } +static NautilusViewItem * +default_get_backing_item (NautilusListBase *self) +{ + return NULL; +} + static void default_preview_selection_event (NautilusListBase *self, GtkDirectionType direction) @@ -1091,6 +1097,7 @@ nautilus_list_base_class_init (NautilusListBaseClass *klass) widget_class->focus = nautilus_list_base_focus; + klass->get_backing_item = default_get_backing_item; klass->preview_selection_event = default_preview_selection_event; klass->setup_directory = base_setup_directory; @@ -1203,6 +1210,23 @@ nautilus_list_base_setup_gestures (NautilusListBase *self) priv->view_drop_target = drop_target; } +/** + * nautilus_list_base_get_backing_item: + * + * Get a view item representing the subdirectory which, based on user action, + * should be used in place the view directory when performing file operations + * such as create new folders, paste from the clipboard, etc. + * + * If the view directory should be used, NULL is returned instead. + * + * Returns: (transfer full) (nullable): The subdirectory backing file operations. + */ +NautilusViewItem * +nautilus_list_base_get_backing_item (NautilusListBase *self) +{ + return NAUTILUS_LIST_BASE_CLASS (G_OBJECT_GET_CLASS (self))->get_backing_item (self); +} + NautilusViewInfo nautilus_list_base_get_view_info (NautilusListBase *self) { diff --git a/src/nautilus-list-base.h b/src/nautilus-list-base.h index 067b76cd879fdf01f741fb38517107114b4605a1..1e92dd814fd4c2c4d401cd59b01d97bf5befe9f4 100644 --- a/src/nautilus-list-base.h +++ b/src/nautilus-list-base.h @@ -27,13 +27,12 @@ struct _NautilusListBaseClass { NautilusFilesViewClass parent_class; + /* Subclasses must provide implementation. */ NautilusViewInfo (*get_view_info) (NautilusListBase *self); guint (*get_icon_size) (NautilusListBase *self); GVariant *(*get_sort_state) (NautilusListBase *self); GtkWidget *(*get_view_ui) (NautilusListBase *self); int (*get_zoom_level) (NautilusListBase *self); - void (*preview_selection_event) (NautilusListBase *self, - GtkDirectionType direction); void (*scroll_to) (NautilusListBase *self, guint position, GtkListScrollFlags flags, @@ -43,11 +42,17 @@ struct _NautilusListBaseClass void (*set_zoom_level) (NautilusListBase *self, int new_zoom_level); + /* Subclasses may override base implementation. */ + NautilusViewItem *(*get_backing_item) (NautilusListBase *self); + void (*preview_selection_event) (NautilusListBase *self, + GtkDirectionType direction); + /* Subclass override must chain-up to base implementation. */ void (*setup_directory) (NautilusListBase *self, NautilusDirectory *directory); }; +NautilusViewItem *nautilus_list_base_get_backing_item (NautilusListBase *self); GtkWidget *nautilus_list_base_get_selected_item_ui (NautilusListBase *self); GVariant *nautilus_list_base_get_sort_state (NautilusListBase *self); NautilusViewInfo nautilus_list_base_get_view_info (NautilusListBase *self) G_GNUC_PURE; diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index aac6a185c88f8c9f80a2b7d366d895c941227011..82080240e15a8b8146a37f613f5b8cd0b4b1bb00 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -54,6 +54,15 @@ struct _NautilusListView G_DEFINE_TYPE (NautilusListView, nautilus_list_view, NAUTILUS_TYPE_LIST_BASE) +enum +{ + LOAD_SUBDIRECTORY, + UNLOAD_SUBDIRECTORY, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + #define get_view_item(cell) \ (NAUTILUS_VIEW_ITEM (gtk_tree_list_row_get_item (GTK_TREE_LIST_ROW (gtk_column_view_cell_get_item (cell))))) @@ -606,73 +615,69 @@ get_default_zoom_level (void) list_view_info.zoom_level_max); } -static char * -real_get_backing_uri (NautilusFilesView *view) +static NautilusViewItem * +real_get_backing_item (NautilusListBase *list_base) { - NautilusListView *self = NAUTILUS_LIST_VIEW (view); - NautilusViewModel *model = nautilus_list_base_get_model (NAUTILUS_LIST_BASE (self)); - g_autoptr (NautilusFile) common_parent = NULL; + NautilusListView *self = NAUTILUS_LIST_VIEW (list_base); if (!self->expand_as_a_tree) { - return NAUTILUS_FILES_VIEW_CLASS (nautilus_list_view_parent_class)->get_backing_uri (view); + return NULL; } /* If we are using tree expanders use the items parent, unless it * is an expanded folder, in which case we should use that folder directly. * When dealing with multiple selections, use the same rules, but only * if a common parent exists. */ - - for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (model)); i++) + NautilusViewModel *model = nautilus_list_base_get_model (list_base); + g_autoptr (GtkBitset) selection = gtk_selection_model_get_selection (GTK_SELECTION_MODEL (model)); + g_autoptr (GtkTreeListRow) common_parent = NULL; + GtkBitsetIter iter; + guint i; + + for (gtk_bitset_iter_init_first (&iter, selection, &i); + gtk_bitset_iter_is_valid (&iter); + gtk_bitset_iter_next (&iter, &i)) { g_autoptr (GtkTreeListRow) row = g_list_model_get_item (G_LIST_MODEL (model), i); - g_autoptr (NautilusViewItem) item = NULL; - g_autoptr (NautilusFile) parent_file = NULL; - NautilusFile *file; - NautilusFile *current_parent; + g_autoptr (GtkTreeListRow) parent = gtk_tree_list_row_get_parent (row); + GtkTreeListRow *current_parent = gtk_tree_list_row_get_expanded (row) ? row : parent; - if (!gtk_selection_model_is_selected (GTK_SELECTION_MODEL (model), i)) + if (current_parent == NULL) { - continue; + return NULL; } - item = gtk_tree_list_row_get_item (row); - file = nautilus_view_item_get_file (item); - parent_file = nautilus_file_get_parent (file); - current_parent = gtk_tree_list_row_get_expanded (row) ? file : parent_file; - if (common_parent == NULL) { - common_parent = nautilus_file_ref (current_parent); + common_parent = g_object_ref (current_parent); } else if (current_parent != common_parent) { - g_clear_pointer (&common_parent, nautilus_file_unref); + g_clear_object (&common_parent); break; } } if (common_parent != NULL) { - return nautilus_file_get_uri (common_parent); + return gtk_tree_list_row_get_item (common_parent); } - return NAUTILUS_FILES_VIEW_CLASS (nautilus_list_view_parent_class)->get_backing_uri (view); + return NULL; } typedef struct { NautilusListView *self; - NautilusViewItem *item; - NautilusDirectory *directory; + GtkTreeListRow *row; } UnloadDelayData; static void unload_delay_data_free (UnloadDelayData *unload_data) { g_clear_weak_pointer (&unload_data->self); - g_clear_object (&unload_data->item); - g_clear_object (&unload_data->directory); + g_clear_object (&unload_data->row); g_free (unload_data); } @@ -680,79 +685,44 @@ unload_delay_data_free (UnloadDelayData *unload_data) G_DEFINE_AUTOPTR_CLEANUP_FUNC (UnloadDelayData, unload_delay_data_free) static UnloadDelayData * -unload_delay_data_new (NautilusListView *self, - NautilusViewItem *item, - NautilusDirectory *directory) +unload_delay_data_new (NautilusListView *self, + GtkTreeListRow *row) { UnloadDelayData *unload_data; unload_data = g_new0 (UnloadDelayData, 1); g_set_weak_pointer (&unload_data->self, self); - g_set_object (&unload_data->item, item); - g_set_object (&unload_data->directory, directory); + g_set_object (&unload_data->row, row); return unload_data; } -static gboolean +static void unload_file_timeout (gpointer data) { g_autoptr (UnloadDelayData) unload_data = data; NautilusListView *self = unload_data->self; - NautilusViewModel *model; if (unload_data->self == NULL) { - return G_SOURCE_REMOVE; - } - model = nautilus_list_base_get_model (NAUTILUS_LIST_BASE (self)); - - for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (model)); i++) - { - g_autoptr (GtkTreeListRow) row = g_list_model_get_item (G_LIST_MODEL (model), i); - g_autoptr (NautilusViewItem) item = gtk_tree_list_row_get_item (row); - if (item != NULL && item == unload_data->item) - { - if (gtk_tree_list_row_get_expanded (row)) - { - /* It has been expanded again before the timeout. Do nothing. */ - return G_SOURCE_REMOVE; - } - break; - } + return; } - if (nautilus_files_view_has_subdirectory (NAUTILUS_FILES_VIEW (self), - unload_data->directory)) + if (gtk_tree_list_row_get_expanded (unload_data->row)) { - nautilus_files_view_remove_subdirectory (NAUTILUS_FILES_VIEW (self), - unload_data->directory); + /* It has been expanded again before the timeout. Do nothing. */ + return; } - /* The model holds a GListStore for every subdirectory. Empty it. */ - nautilus_view_model_clear_subdirectory (model, unload_data->item); + g_autoptr (NautilusViewItem) item = gtk_tree_list_row_get_item (unload_data->row); - return G_SOURCE_REMOVE; -} - -static void -on_subdirectory_done_loading (NautilusDirectory *directory, - GtkTreeListRow *row) -{ - g_autoptr (NautilusViewItem) item = NULL; - - g_signal_handlers_disconnect_by_func (directory, on_subdirectory_done_loading, row); - - item = NAUTILUS_VIEW_ITEM (gtk_tree_list_row_get_item (row)); - nautilus_view_item_set_loading (item, FALSE); - - if (!nautilus_directory_is_not_empty (directory)) + if (nautilus_file_is_gone (nautilus_view_item_get_file (item))) { - GtkWidget *name_cell = nautilus_view_item_get_item_ui (item); - GtkTreeExpander *expander = nautilus_name_cell_get_expander (NAUTILUS_NAME_CELL (name_cell)); - - gtk_tree_expander_set_hide_expander (expander, TRUE); + /* It's been removed in the meantime. */ + return; } + + g_signal_emit (self, signals[UNLOAD_SUBDIRECTORY], 0, item); } static void @@ -762,42 +732,18 @@ on_row_expanded_changed (GObject *gobject, { GtkTreeListRow *row = GTK_TREE_LIST_ROW (gobject); NautilusListView *self = NAUTILUS_LIST_VIEW (user_data); - g_autoptr (NautilusViewItem) item = NULL; - g_autoptr (NautilusDirectory) directory = NULL; - gboolean expanded; + g_autoptr (NautilusViewItem) item = NAUTILUS_VIEW_ITEM (gtk_tree_list_row_get_item (row)); - item = NAUTILUS_VIEW_ITEM (gtk_tree_list_row_get_item (row)); - if (item == NULL) + if (gtk_tree_list_row_get_expanded (row)) { - /* Row has been destroyed. */ - return; - } - - directory = nautilus_directory_get_for_file (nautilus_view_item_get_file (item)); - expanded = gtk_tree_list_row_get_expanded (row); - if (expanded) - { - if (!nautilus_files_view_has_subdirectory (NAUTILUS_FILES_VIEW (self), directory)) - { - nautilus_files_view_add_subdirectory (NAUTILUS_FILES_VIEW (self), directory); - } - if (!nautilus_directory_are_all_files_seen (directory)) - { - nautilus_view_item_set_loading (item, TRUE); - - g_signal_connect_object (directory, - "done-loading", - G_CALLBACK (on_subdirectory_done_loading), - row, - 0); - } + g_signal_emit (self, signals[LOAD_SUBDIRECTORY], 0, item); } else { nautilus_view_item_set_loading (item, FALSE); - g_timeout_add_seconds (COLLAPSE_TO_UNLOAD_DELAY, - unload_file_timeout, - unload_delay_data_new (self, item, directory)); + g_timeout_add_seconds_once (COLLAPSE_TO_UNLOAD_DELAY, + unload_file_timeout, + unload_delay_data_new (self, row)); } } @@ -1103,10 +1049,7 @@ setup_view_columns (NautilusListView *self) static void nautilus_list_view_reload (NautilusListView *self) { - NautilusWindowSlot *slot; - - slot = nautilus_files_view_get_nautilus_window_slot (NAUTILUS_FILES_VIEW (self)); - nautilus_window_slot_queue_reload (slot); + gtk_widget_activate_action (GTK_WIDGET (self), "win.reload", NULL); } static void @@ -1216,14 +1159,12 @@ static void nautilus_list_view_class_init (NautilusListViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NautilusFilesViewClass *files_view_class = NAUTILUS_FILES_VIEW_CLASS (klass); NautilusListBaseClass *list_base_view_class = NAUTILUS_LIST_BASE_CLASS (klass); object_class->dispose = nautilus_list_view_dispose; object_class->finalize = nautilus_list_view_finalize; - files_view_class->get_backing_uri = real_get_backing_uri; - + list_base_view_class->get_backing_item = real_get_backing_item; list_base_view_class->get_icon_size = real_get_icon_size; list_base_view_class->get_sort_state = real_get_sort_state; list_base_view_class->get_view_info = real_get_view_info; @@ -1233,6 +1174,21 @@ nautilus_list_view_class_init (NautilusListViewClass *klass) list_base_view_class->set_sort_state = real_set_sort_state; list_base_view_class->set_zoom_level = real_set_zoom_level; list_base_view_class->setup_directory = nautilus_list_view_setup_directory; + + signals[LOAD_SUBDIRECTORY] = g_signal_new ("load-subdirectory", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, NAUTILUS_TYPE_VIEW_ITEM); + signals[UNLOAD_SUBDIRECTORY] = g_signal_new ("unload-subdirectory", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, NAUTILUS_TYPE_VIEW_ITEM); } NautilusListView * diff --git a/src/nautilus-name-cell.c b/src/nautilus-name-cell.c index f18a83efbd6dcc1b9049db8b3e055bdbc1e531e0..09667a488ad20151fd149195190145b72fec1a22 100644 --- a/src/nautilus-name-cell.c +++ b/src/nautilus-name-cell.c @@ -6,10 +6,11 @@ #include "nautilus-name-cell.h" +#include "nautilus-directory.h" #include "nautilus-file-utilities.h" #include "nautilus-thumbnails.h" -#define LOADING_TIMEOUT_SECONDS 1 +#define SPINNER_DELAY_MS 200 struct _NautilusNameCell { @@ -272,43 +273,43 @@ on_item_is_cut_changed (NautilusNameCell *self) } } -static gboolean +static void on_loading_timeout (gpointer user_data) { NautilusNameCell *self = NAUTILUS_NAME_CELL (user_data); g_autoptr (NautilusViewItem) item = nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self)); - gboolean is_loading; + gboolean is_loading = nautilus_view_item_get_loading (item); self->loading_timeout_id = 0; - g_object_get (item, - "is-loading", &is_loading, - NULL); if (is_loading) { gtk_widget_set_visible (self->spinner, TRUE); gtk_spinner_start (GTK_SPINNER (self->spinner)); } - - return G_SOURCE_REMOVE; } static void on_item_is_loading_changed (NautilusNameCell *self) { - gboolean is_loading; g_autoptr (NautilusViewItem) item = nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self)); + gboolean is_loading = nautilus_view_item_get_loading (item); g_clear_handle_id (&self->loading_timeout_id, g_source_remove); - g_object_get (item, "is-loading", &is_loading, NULL); + if (is_loading) { - self->loading_timeout_id = g_timeout_add_seconds (LOADING_TIMEOUT_SECONDS, - G_SOURCE_FUNC (on_loading_timeout), - self); + self->loading_timeout_id = g_timeout_add_once (SPINNER_DELAY_MS, + on_loading_timeout, + self); } else { + g_autoptr (NautilusDirectory) directory = nautilus_directory_get_for_file (nautilus_view_item_get_file (item)); + + gtk_tree_expander_set_hide_expander (GTK_TREE_EXPANDER (self->expander), + !nautilus_directory_is_not_empty (directory)); + gtk_widget_set_visible (self->spinner, FALSE); gtk_spinner_stop (GTK_SPINNER (self->spinner)); } @@ -356,7 +357,7 @@ nautilus_name_cell_init (NautilusNameCell *self) (GCallback) on_item_drag_accept_changed, self); g_signal_group_connect_swapped (self->item_signal_group, "notify::is-cut", (GCallback) on_item_is_cut_changed, self); - g_signal_group_connect_swapped (self->item_signal_group, "notify::is-loading", + g_signal_group_connect_swapped (self->item_signal_group, "notify::loading", (GCallback) on_item_is_loading_changed, self); g_signal_group_connect_swapped (self->item_signal_group, "file-changed", (GCallback) on_file_changed, self); diff --git a/src/nautilus-view-item.c b/src/nautilus-view-item.c index b83862b78f3ba39407201d9a59715ce91ca8ae93..6c2247c1eb82d6408c81b8367cc6dc6c145a763b 100644 --- a/src/nautilus-view-item.c +++ b/src/nautilus-view-item.c @@ -11,7 +11,7 @@ struct _NautilusViewItem GObject parent_instance; gboolean is_cut; gboolean drag_accept; - gboolean is_loading; + gboolean loading; NautilusFile *file; GtkWidget *item_ui; }; @@ -24,7 +24,7 @@ enum PROP_FILE, PROP_IS_CUT, PROP_DRAG_ACCEPT, - PROP_IS_LOADING, + PROP_LOADING, N_PROPS }; @@ -86,9 +86,9 @@ nautilus_view_item_get_property (GObject *object, } break; - case PROP_IS_LOADING: + case PROP_LOADING: { - g_value_set_boolean (value, self->is_loading); + g_value_set_boolean (value, self->loading); } break; @@ -127,9 +127,9 @@ nautilus_view_item_set_property (GObject *object, } break; - case PROP_IS_LOADING: + case PROP_LOADING: { - self->is_loading = g_value_get_boolean (value); + nautilus_view_item_set_loading (self, g_value_get_boolean (value)); } break; @@ -167,10 +167,9 @@ nautilus_view_item_class_init (NautilusViewItemClass *klass) "", "", NAUTILUS_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - properties[PROP_IS_LOADING] = g_param_spec_boolean ("is-loading", - "", "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_LOADING] = g_param_spec_boolean ("loading", NULL, NULL, + FALSE, + G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, properties); signals[FILE_CHANGED] = g_signal_new ("file-changed", @@ -208,13 +207,25 @@ nautilus_view_item_set_drag_accept (NautilusViewItem *self, g_object_set (self, "drag-accept", drag_accept, NULL); } +gboolean +nautilus_view_item_get_loading (NautilusViewItem *self) +{ + g_return_val_if_fail (NAUTILUS_IS_VIEW_ITEM (self), FALSE); + + return self->loading; +} + void nautilus_view_item_set_loading (NautilusViewItem *self, gboolean loading) { g_return_if_fail (NAUTILUS_IS_VIEW_ITEM (self)); - g_object_set (self, "is-loading", loading, NULL); + if (self->loading != loading) + { + self->loading = loading; + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LOADING]); + } } NautilusFile * diff --git a/src/nautilus-view-item.h b/src/nautilus-view-item.h index 6b21645f595cdf10320535d890e065ff43d05b54..42f74a708c0c8e535c80a861850df12a5a8d7eeb 100644 --- a/src/nautilus-view-item.h +++ b/src/nautilus-view-item.h @@ -23,6 +23,7 @@ void nautilus_view_item_set_cut (NautilusViewItem *self, gboolean is_cut); void nautilus_view_item_set_drag_accept (NautilusViewItem *self, gboolean drag_accept); +gboolean nautilus_view_item_get_loading (NautilusViewItem *self); void nautilus_view_item_set_loading (NautilusViewItem *self, gboolean is_loading); diff --git a/src/resources/ui/nautilus-name-cell.ui b/src/resources/ui/nautilus-name-cell.ui index 30415032056be6dc00cda9e70aefe2fccc3621c8..ba0ea0cd492f086cf524e992014652338a74eb21 100644 --- a/src/resources/ui/nautilus-name-cell.ui +++ b/src/resources/ui/nautilus-name-cell.ui @@ -19,14 +19,6 @@ horizontal fill center - - - False - False - center - center - - vertical @@ -85,6 +77,14 @@ 6 + + + False + False + center + center + +