[nautilus] add "restore tab" action



commit 6e16bc32e85c80229578ddff6615554f84c492c8
Author: Alexandru Pandelea <alexandru pandelea gmail com>
Date:   Mon Mar 27 23:00:43 2017 +0300

    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

 docs/Overview.md                  |    3 ++
 src/nautilus-window-slot.c        |   52 +++++++++++++++++++++++++++++-
 src/nautilus-window-slot.h        |   12 +++++++
 src/nautilus-window.c             |   65 +++++++++++++++++++++++++++++++++++++
 src/resources/gtk/help-overlay.ui |    7 ++++
 5 files changed, 138 insertions(+), 1 deletions(-)
---
diff --git a/docs/Overview.md b/docs/Overview.md
index a4d4206..9bbda59 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 a738ad1..b2035f2 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 57b83fa..573357d 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 585a91f..8abf66b 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
@@ -1344,6 +1348,43 @@ should_show_format_command (GVolume *volume)
 }
 
 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,
                gpointer       user_data)
@@ -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", "<shift><control>t");
 
     /* Alt+N for the first 9 tabs */
     for (i = 0; i < 9; ++i)
@@ -2478,6 +2525,19 @@ nautilus_window_destroy (GtkWidget *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)
 {
     NautilusWindow *window;
@@ -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 6361bad..32f7ccd 100644
--- a/src/resources/gtk/help-overlay.ui
+++ b/src/resources/gtk/help-overlay.ui
@@ -149,6 +149,13 @@
                 <property name="accelerator">&lt;shift&gt;&lt;Primary&gt;Page_Down</property>
               </object>
             </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">True</property>
+                <property name="title" translatable="yes" context="shortcut window">Restore tab</property>
+                <property name="accelerator">&lt;shift&gt;&lt;Primary&gt;T</property>
+              </object>
+            </child>
           </object>
         </child>
         <child>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]