diff --git a/docs/Overview.md b/docs/Overview.md index a4d42060a..9bbda59c2 100644 --- a/docs/Overview.md +++ b/docs/Overview.md @@ -11,6 +11,9 @@ also owns those files. Window slot is the creator of the file if the file was already not present due to be a bookmark. +The window has a queue with information of the closed tabs, owning references +to previous files. + = Directory Ownership = Every file has a directory associated, that is usually the parent. However, when the file is a root and has no parent, the file is called self_owned, and the directory diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c index a738ad1a2..b2035f20c 100644 --- a/src/nautilus-window-slot.c +++ b/src/nautilus-window-slot.c @@ -153,6 +153,54 @@ static void trash_state_changed_cb (NautilusTrashMonitor *monitor, gboolean is_empty, gpointer user_data); +void +nautilus_window_slot_restore_from_data (NautilusWindowSlot *self, + RestoreTabData *data) +{ + NautilusWindowSlotPrivate *priv; + + priv = nautilus_window_slot_get_instance_private (self); + + priv->back_list = g_list_copy_deep (data->back_list, (GCopyFunc) g_object_ref, NULL); + + priv->forward_list = g_list_copy_deep (data->forward_list, (GCopyFunc) g_object_ref, NULL); + + priv->view_mode_before_search = data->view_before_search; + + priv->location_change_type = NAUTILUS_LOCATION_CHANGE_RELOAD; +} + +RestoreTabData* +nautilus_window_slot_get_restore_tab_data (NautilusWindowSlot *self) +{ + NautilusWindowSlotPrivate *priv; + RestoreTabData *data; + GList *back_list; + GList *forward_list; + + priv = nautilus_window_slot_get_instance_private (self); + + back_list = g_list_copy_deep (priv->back_list, + (GCopyFunc) g_object_ref, + NULL); + forward_list = g_list_copy_deep (priv->forward_list, + (GCopyFunc) g_object_ref, + NULL); + + /* This data is used to restore a tab after it was closed. + * In order to do that we need to keep the history, what was + * the view mode before search and a reference to the file. + * A GFile isn't enough, as the NautilusFile also keeps a + * reference to the search directory */ + data = g_new0 (RestoreTabData, 1); + data->back_list = back_list; + data->forward_list = forward_list; + data->file = nautilus_file_get (priv->location); + data->view_before_search = priv->view_mode_before_search; + + return data; +} + gboolean nautilus_window_slot_handles_location (NautilusWindowSlot *self, GFile *location) @@ -204,7 +252,7 @@ real_get_view_for_location (NautilusWindowSlot *self, /* If it's already set, is because we already made the change to search mode, * so the view mode of the current view will be the one search is using, * which is not the one we are interested in */ - if (priv->view_mode_before_search == NAUTILUS_VIEW_INVALID_ID) + if (priv->view_mode_before_search == NAUTILUS_VIEW_INVALID_ID && priv->content_view) { priv->view_mode_before_search = nautilus_files_view_get_view_id (priv->content_view); } @@ -2170,8 +2218,10 @@ handle_go_elsewhere (NautilusWindowSlot *self, NautilusWindowSlotPrivate *priv; priv = nautilus_window_slot_get_instance_private (self); + /* Clobber the entire forward list, and move displayed location to back list */ nautilus_window_slot_clear_forward_list (self); + slot_location = nautilus_window_slot_get_location (self); if (slot_location != NULL) diff --git a/src/nautilus-window-slot.h b/src/nautilus-window-slot.h index 57b83fab8..573357d9b 100644 --- a/src/nautilus-window-slot.h +++ b/src/nautilus-window-slot.h @@ -42,6 +42,13 @@ G_DECLARE_DERIVABLE_TYPE (NautilusWindowSlot, nautilus_window_slot, NAUTILUS, WI #include "nautilus-window.h" #include "nautilus-toolbar-menu-sections.h" +typedef struct +{ + NautilusFile *file; + gint view_before_search; + GList *back_list; + GList *forward_list; +} RestoreTabData; struct _NautilusWindowSlotClass { GtkBoxClass parent_class; @@ -110,6 +117,11 @@ void nautilus_window_slot_search (NautilusWindowSlot * gboolean nautilus_window_slot_handles_location (NautilusWindowSlot *self, GFile *location); +void nautilus_window_slot_restore_from_data (NautilusWindowSlot *self, + RestoreTabData *data); + +RestoreTabData* nautilus_window_slot_get_restore_tab_data (NautilusWindowSlot *self); + /* Only used by slot-dnd */ NautilusView* nautilus_window_slot_get_current_view (NautilusWindowSlot *slot); diff --git a/src/nautilus-window.c b/src/nautilus-window.c index 585a91f4a..8abf66b69 100644 --- a/src/nautilus-window.c +++ b/src/nautilus-window.c @@ -81,6 +81,8 @@ static GtkWidget *nautilus_window_ensure_location_entry (NautilusWindow *window) static void close_slot (NautilusWindow *window, NautilusWindowSlot *slot, gboolean remove_from_notebook); +static void free_restore_tab_data (gpointer data, + gpointer user_data); /* Sanity check: highest mouse button value I could find was 14. 5 is our * lower threshold (well-documented to be the one of the button events for the @@ -139,6 +141,8 @@ typedef struct guint sidebar_width_handler_id; guint bookmarks_id; + + GQueue *tab_data_queue; } NautilusWindowPrivate; enum @@ -1343,6 +1347,43 @@ should_show_format_command (GVolume *volume) return show_format; } +static void +action_restore_tab (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindowPrivate *priv; + NautilusWindow *window = NAUTILUS_WINDOW (user_data); + NautilusWindowOpenFlags flags; + g_autoptr (GFile) location = NULL; + NautilusWindowSlot *slot; + RestoreTabData *data; + + priv = nautilus_window_get_instance_private (window); + + if (g_queue_get_length (priv->tab_data_queue) == 0) + { + return; + } + + flags = g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_NEW_TAB_POSITION); + + flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB; + flags |= NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE; + + data = g_queue_pop_head (priv->tab_data_queue); + + location = nautilus_file_get_location (data->file); + + slot = nautilus_window_create_slot (window, location); + nautilus_window_initialize_slot (window, slot, flags); + + nautilus_window_slot_open_location_full (slot, location, flags, NULL); + nautilus_window_slot_restore_from_data (slot, data); + + free_restore_tab_data (data, NULL); +} + static void action_format (GSimpleAction *action, GVariant *variant, @@ -1552,6 +1593,7 @@ nautilus_window_slot_close (NautilusWindow *window, { NautilusWindowPrivate *priv; NautilusWindowSlot *next_slot; + RestoreTabData *data; DEBUG ("Requesting to remove slot %p from window %p", slot, window); if (window == NULL) @@ -1567,6 +1609,9 @@ nautilus_window_slot_close (NautilusWindow *window, nautilus_window_set_active_slot (window, next_slot); } + data = nautilus_window_slot_get_restore_tab_data (slot); + g_queue_push_head (priv->tab_data_queue, data); + close_slot (window, slot, TRUE); /* If that was the last slot in the window, close the window. */ @@ -2244,6 +2289,7 @@ const GActionEntry win_entries[] = { "empty-trash", action_empty_trash }, { "properties", action_properties }, { "format", action_format }, + { "restore-tab", action_restore_tab }, }; static void @@ -2289,6 +2335,7 @@ nautilus_window_initialize_actions (NautilusWindow *window) nautilus_application_set_accelerator (app, "win.prompt-root-location", "slash"); nautilus_application_set_accelerator (app, "win.prompt-home-location", "asciitilde"); nautilus_application_set_accelerator (app, "win.view-menu", "F10"); + nautilus_application_set_accelerator (app, "win.restore-tab", "t"); /* Alt+N for the first 9 tabs */ for (i = 0; i < 9; ++i) @@ -2477,6 +2524,19 @@ nautilus_window_destroy (GtkWidget *object) GTK_WIDGET_CLASS (nautilus_window_parent_class)->destroy (object); } +static void +free_restore_tab_data (gpointer data, + gpointer user_data) +{ + RestoreTabData *tab_data = data; + + g_list_free_full (tab_data->back_list, g_object_unref); + g_list_free_full (tab_data->forward_list, g_object_unref); + nautilus_file_unref (tab_data->file); + + g_free (tab_data); +} + static void nautilus_window_finalize (GObject *object) { @@ -2511,6 +2571,9 @@ nautilus_window_finalize (GObject *object) G_CALLBACK (nautilus_window_on_undo_changed), window); + g_queue_foreach (priv->tab_data_queue, (GFunc) free_restore_tab_data, NULL); + g_queue_free (priv->tab_data_queue); + /* nautilus_window_close() should have run */ g_assert (priv->slots == NULL); @@ -2840,6 +2903,8 @@ nautilus_window_init (NautilusWindow *window) window_group = gtk_window_group_new (); gtk_window_group_add_window (window_group, GTK_WINDOW (window)); g_object_unref (window_group); + + priv->tab_data_queue = g_queue_new(); } static void diff --git a/src/resources/gtk/help-overlay.ui b/src/resources/gtk/help-overlay.ui index 6361bad2a..32f7ccd30 100644 --- a/src/resources/gtk/help-overlay.ui +++ b/src/resources/gtk/help-overlay.ui @@ -149,6 +149,13 @@ <shift><Primary>Page_Down + + + True + Restore tab + <shift><Primary>T + +