mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-10-05 23:40:01 +00:00
add "restore tab" action
Adds option to reopen closed tabs with Ctrl+Shift+T. In order to do so, keep a list with data needed to restore closed tabs. So, this list keeps the location bookmark, the view id before search, which is needed in case the closed tab was a search and the back/forward history. https://bugzilla.gnome.org/show_bug.cgi?id=561136
This commit is contained in:
parent
e4e9eb83d5
commit
6e16bc32e8
|
@ -11,6 +11,9 @@ also owns those files.
|
||||||
Window slot is the creator of the file if the file was already not present due
|
Window slot is the creator of the file if the file was already not present due
|
||||||
to be a bookmark.
|
to be a bookmark.
|
||||||
|
|
||||||
|
The window has a queue with information of the closed tabs, owning references
|
||||||
|
to previous files.
|
||||||
|
|
||||||
= Directory Ownership =
|
= Directory Ownership =
|
||||||
Every file has a directory associated, that is usually the parent. However, when
|
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
|
the file is a root and has no parent, the file is called self_owned, and the directory
|
||||||
|
|
|
@ -153,6 +153,54 @@ static void trash_state_changed_cb (NautilusTrashMonitor *monitor,
|
||||||
gboolean is_empty,
|
gboolean is_empty,
|
||||||
gpointer user_data);
|
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
|
gboolean
|
||||||
nautilus_window_slot_handles_location (NautilusWindowSlot *self,
|
nautilus_window_slot_handles_location (NautilusWindowSlot *self,
|
||||||
GFile *location)
|
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,
|
/* 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,
|
* so the view mode of the current view will be the one search is using,
|
||||||
* which is not the one we are interested in */
|
* 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);
|
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;
|
NautilusWindowSlotPrivate *priv;
|
||||||
|
|
||||||
priv = nautilus_window_slot_get_instance_private (self);
|
priv = nautilus_window_slot_get_instance_private (self);
|
||||||
|
|
||||||
/* Clobber the entire forward list, and move displayed location to back list */
|
/* Clobber the entire forward list, and move displayed location to back list */
|
||||||
nautilus_window_slot_clear_forward_list (self);
|
nautilus_window_slot_clear_forward_list (self);
|
||||||
|
|
||||||
slot_location = nautilus_window_slot_get_location (self);
|
slot_location = nautilus_window_slot_get_location (self);
|
||||||
|
|
||||||
if (slot_location != NULL)
|
if (slot_location != NULL)
|
||||||
|
|
|
@ -42,6 +42,13 @@ G_DECLARE_DERIVABLE_TYPE (NautilusWindowSlot, nautilus_window_slot, NAUTILUS, WI
|
||||||
#include "nautilus-window.h"
|
#include "nautilus-window.h"
|
||||||
#include "nautilus-toolbar-menu-sections.h"
|
#include "nautilus-toolbar-menu-sections.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
NautilusFile *file;
|
||||||
|
gint view_before_search;
|
||||||
|
GList *back_list;
|
||||||
|
GList *forward_list;
|
||||||
|
} RestoreTabData;
|
||||||
|
|
||||||
struct _NautilusWindowSlotClass {
|
struct _NautilusWindowSlotClass {
|
||||||
GtkBoxClass parent_class;
|
GtkBoxClass parent_class;
|
||||||
|
@ -110,6 +117,11 @@ void nautilus_window_slot_search (NautilusWindowSlot *
|
||||||
gboolean nautilus_window_slot_handles_location (NautilusWindowSlot *self,
|
gboolean nautilus_window_slot_handles_location (NautilusWindowSlot *self,
|
||||||
GFile *location);
|
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 */
|
/* Only used by slot-dnd */
|
||||||
NautilusView* nautilus_window_slot_get_current_view (NautilusWindowSlot *slot);
|
NautilusView* nautilus_window_slot_get_current_view (NautilusWindowSlot *slot);
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,8 @@ static GtkWidget *nautilus_window_ensure_location_entry (NautilusWindow *window)
|
||||||
static void close_slot (NautilusWindow *window,
|
static void close_slot (NautilusWindow *window,
|
||||||
NautilusWindowSlot *slot,
|
NautilusWindowSlot *slot,
|
||||||
gboolean remove_from_notebook);
|
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
|
/* 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
|
* 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 sidebar_width_handler_id;
|
||||||
guint bookmarks_id;
|
guint bookmarks_id;
|
||||||
|
|
||||||
|
GQueue *tab_data_queue;
|
||||||
} NautilusWindowPrivate;
|
} NautilusWindowPrivate;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -1343,6 +1347,43 @@ should_show_format_command (GVolume *volume)
|
||||||
return show_format;
|
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
|
static void
|
||||||
action_format (GSimpleAction *action,
|
action_format (GSimpleAction *action,
|
||||||
GVariant *variant,
|
GVariant *variant,
|
||||||
|
@ -1552,6 +1593,7 @@ nautilus_window_slot_close (NautilusWindow *window,
|
||||||
{
|
{
|
||||||
NautilusWindowPrivate *priv;
|
NautilusWindowPrivate *priv;
|
||||||
NautilusWindowSlot *next_slot;
|
NautilusWindowSlot *next_slot;
|
||||||
|
RestoreTabData *data;
|
||||||
|
|
||||||
DEBUG ("Requesting to remove slot %p from window %p", slot, window);
|
DEBUG ("Requesting to remove slot %p from window %p", slot, window);
|
||||||
if (window == NULL)
|
if (window == NULL)
|
||||||
|
@ -1567,6 +1609,9 @@ nautilus_window_slot_close (NautilusWindow *window,
|
||||||
nautilus_window_set_active_slot (window, next_slot);
|
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);
|
close_slot (window, slot, TRUE);
|
||||||
|
|
||||||
/* If that was the last slot in the window, close the window. */
|
/* 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 },
|
{ "empty-trash", action_empty_trash },
|
||||||
{ "properties", action_properties },
|
{ "properties", action_properties },
|
||||||
{ "format", action_format },
|
{ "format", action_format },
|
||||||
|
{ "restore-tab", action_restore_tab },
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
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-root-location", "slash");
|
||||||
nautilus_application_set_accelerator (app, "win.prompt-home-location", "asciitilde");
|
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.view-menu", "F10");
|
||||||
|
nautilus_application_set_accelerator (app, "win.restore-tab", "<shift><control>t");
|
||||||
|
|
||||||
/* Alt+N for the first 9 tabs */
|
/* Alt+N for the first 9 tabs */
|
||||||
for (i = 0; i < 9; ++i)
|
for (i = 0; i < 9; ++i)
|
||||||
|
@ -2477,6 +2524,19 @@ nautilus_window_destroy (GtkWidget *object)
|
||||||
GTK_WIDGET_CLASS (nautilus_window_parent_class)->destroy (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
|
static void
|
||||||
nautilus_window_finalize (GObject *object)
|
nautilus_window_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
|
@ -2511,6 +2571,9 @@ nautilus_window_finalize (GObject *object)
|
||||||
G_CALLBACK (nautilus_window_on_undo_changed),
|
G_CALLBACK (nautilus_window_on_undo_changed),
|
||||||
window);
|
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 */
|
/* nautilus_window_close() should have run */
|
||||||
g_assert (priv->slots == NULL);
|
g_assert (priv->slots == NULL);
|
||||||
|
|
||||||
|
@ -2840,6 +2903,8 @@ nautilus_window_init (NautilusWindow *window)
|
||||||
window_group = gtk_window_group_new ();
|
window_group = gtk_window_group_new ();
|
||||||
gtk_window_group_add_window (window_group, GTK_WINDOW (window));
|
gtk_window_group_add_window (window_group, GTK_WINDOW (window));
|
||||||
g_object_unref (window_group);
|
g_object_unref (window_group);
|
||||||
|
|
||||||
|
priv->tab_data_queue = g_queue_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -149,6 +149,13 @@
|
||||||
<property name="accelerator"><shift><Primary>Page_Down</property>
|
<property name="accelerator"><shift><Primary>Page_Down</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkShortcutsShortcut">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="title" translatable="yes" context="shortcut window">Restore tab</property>
|
||||||
|
<property name="accelerator"><shift><Primary>T</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
|
Loading…
Reference in a new issue