View Issue Details

IDProjectCategoryView StatusLast Update
0002032Double CommanderLogicpublic2019-03-31 14:54
ReporterCryHam Assigned To 
PrioritynormalSeverityminorReproducibilityN/A
Status newResolutionopen 
ProjectionnoneETAnone 
Product Version1.0.0 (trunk) 
Summary0002032: Undo Close Tab
DescriptionFor me it would be very useful to have a key binding to Undo last closed tab (and then any more, not just one).

The way Total commander does it is somewhat different, I think that upon closing tab they push its path(s) to current history. So that if I close tab and land on another I can still go back to it by pressing alt-Left (backwards).
I think this way would also be good (instead of undo close tab).
TagsNo tags attached.
Attached Files
Undo-Close-Tab.patch (4,879 bytes)   
From e975f35d14a372062ed174002ca486abc7148c43 Mon Sep 17 00:00:00 2001
From: cryham <cryham@gmail.com>
Date: Sun, 10 Mar 2019 12:01:05 +0100
Subject: [PATCH 2/2] Undo Close Tab

---
 src/fmain.lfm             | 10 ++++++++++
 src/fmain.pas             |  2 ++
 src/ufileviewnotebook.pas | 23 ++++++++++++++++++++++-
 src/uglobs.pas            |  1 +
 src/umaincommands.pas     |  6 ++++++
 5 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/src/fmain.lfm b/src/fmain.lfm
index c3cc3113..ace620c9 100644
--- a/src/fmain.lfm
+++ b/src/fmain.lfm
@@ -1219,6 +1219,9 @@ object frmMain: TfrmMain
       object miLine15: TMenuItem
         Caption = '-'
       end
+      object mnuUndoCloseTab: TMenuItem
+        Action = actUndoCloseTab
+      end
       object mnuCloseTab: TMenuItem
         Action = actCloseTab
       end
@@ -1682,6 +1685,13 @@ object frmMain: TfrmMain
       Caption = '&Benchmark'
       OnExecute = actExecute
     end
+    object actUndoCloseTab: TAction
+      Tag = 21
+      Category = 'Tabs'
+      Caption = '&Undo Close Tab'
+      HelpType = htKeyword
+      OnExecute = actExecute
+    end
     object actNewTab: TAction
       Tag = 21
       Category = 'Tabs'
diff --git a/src/fmain.pas b/src/fmain.pas
index 130f66dc..f12ca463 100644
--- a/src/fmain.pas
+++ b/src/fmain.pas
@@ -120,6 +120,7 @@ type
     actFocusTreeView: TAction;
     actToggleFullscreenConsole: TAction;
     actSrcOpenDrives: TAction;
+    actUndoCloseTab: TAction;
     actRightReverseOrder: TAction;
     actLeftReverseOrder: TAction;
     actRightFlatView: TAction;
@@ -334,6 +335,7 @@ type
     mnuTabOptionPathResets: TMenuItem;
     mnuCloseAllTabs: TMenuItem;
     mnuCloseTab: TMenuItem;
+    mnuUndoCloseTab: TMenuItem;
     miLine15: TMenuItem;
     mnuOpenDirInNewTab: TMenuItem;
     mnuNewTab: TMenuItem;
diff --git a/src/ufileviewnotebook.pas b/src/ufileviewnotebook.pas
index b470486e..e639fa2c 100644
--- a/src/ufileviewnotebook.pas
+++ b/src/ufileviewnotebook.pas
@@ -150,6 +150,7 @@ type
     FNotebookSide: TFilePanelSelect;
     FOnCloseTabClicked: TNotifyEvent;
     FPageControl: TFileViewPageControl;
+    FClosedPages: array of TFileViewPage;
 
     function GetActivePage: TFileViewPage;
     function GetActiveView: TFileView;
@@ -186,6 +187,7 @@ type
     function NewEmptyPage: TFileViewPage;
     function NewPage(CloneFromPage: TFileViewPage): TFileViewPage;
     function NewPage(CloneFromView: TFileView): TFileViewPage;
+    procedure UndoClosePage();
     procedure DeletePage(Index: Integer);
     procedure RemovePage(Index: Integer); reintroduce;
     procedure RemovePage(var APage: TFileViewPage);
@@ -877,8 +879,27 @@ var
   APage: TFileViewPage;
 begin
   APage:= GetPage(Index);
+  SetLength(FClosedPages, Length(FClosedPages) + 1);  // push
+  FClosedPages[High(FClosedPages)]:= APage;
+
   FPageControl.Pages[Index].Free;
-  APage.Free;
+  //APage.Free;
+end;
+
+procedure TFileViewNotebook.UndoClosePage();
+var
+  ANewPage: TFileViewPage;
+  Last: TFileViewPage;
+begin
+  if Length(FClosedPages) > 0 then
+  begin
+    ANewPage := NewEmptyPage();
+    Last := FClosedPages[High(FClosedPages)];
+    ANewPage.AssignPage(Last);
+    ANewPage.MakeActive;
+    SetLength(FClosedPages, Length(FClosedPages) - 1);  // pop
+    Last.Free;
+  end;
 end;
 
 procedure TFileViewNotebook.RemovePage(Index: Integer);
diff --git a/src/uglobs.pas b/src/uglobs.pas
index 39ae4fa8..55c4f21d 100644
--- a/src/uglobs.pas
+++ b/src/uglobs.pas
@@ -974,6 +974,7 @@ begin
       AddIfNotExists(['Ctrl+T'],[],'cm_NewTab');
       AddIfNotExists(['Ctrl+U'],[],'cm_Exchange');
       AddIfNotExists(['Ctrl+W'],[],'cm_CloseTab');
+      AddIfNotExists(['Ctrl+Shift+W'],[],'cm_UndoCloseTab');
       AddIfNotExists(['Ctrl+F1'],[],'cm_BriefView');
       AddIfNotExists(['Ctrl+F2'],[],'cm_ColumnsView');
       AddIfNotExists(['Ctrl+F3'],[],'cm_SortByName');
diff --git a/src/umaincommands.pas b/src/umaincommands.pas
index dd56c60b..09fa9827 100644
--- a/src/umaincommands.pas
+++ b/src/umaincommands.pas
@@ -187,6 +187,7 @@ type
    procedure cm_QuickSearch(const Params: array of string);
    procedure cm_QuickFilter(const Params: array of string);
    procedure cm_SrcOpenDrives(const {%H-}Params: array of string);
+   procedure cm_UndoCloseTab(const {%H-}Params: array of string);
    procedure cm_LeftOpenDrives(const {%H-}Params: array of string);
    procedure cm_RightOpenDrives(const {%H-}Params: array of string);
    procedure cm_OpenBar(const {%H-}Params: array of string);
@@ -1365,6 +1366,11 @@ begin
   frmMain.ShowDrivesList(frmMain.SelectedPanel);
 end;
 
+procedure TMainCommands.cm_UndoCloseTab(const Params: array of string);
+begin
+  frmMain.ActiveNotebook.UndoClosePage();
+end;
+
 procedure TMainCommands.cm_LeftOpenDrives(const Params: array of string);
 begin
   frmMain.ShowDrivesList(fpLeft);
-- 
2.21.0.windows.1

Undo-Close-Tab.patch (4,879 bytes)   
Undo-Close-Tab2.patch (1,011 bytes)   
 src/ufileviewnotebook.pas | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/ufileviewnotebook.pas b/src/ufileviewnotebook.pas
index e639fa2c..88d85b0f 100644
--- a/src/ufileviewnotebook.pas
+++ b/src/ufileviewnotebook.pas
@@ -877,11 +877,19 @@ end;
 procedure TFileViewNotebook.DeletePage(Index: Integer);
 var
   APage: TFileViewPage;
+  I: Integer;
 begin
   APage:= GetPage(Index);
-  SetLength(FClosedPages, Length(FClosedPages) + 1);  // push
-  FClosedPages[High(FClosedPages)]:= APage;
-
+  if Length(FClosedPages) >= 10 then  // max undo pages count
+  begin
+    FClosedPages[0].Free;  // pop first
+    for I:= 0 to Length(FClosedPages) - 2 do  // move all left
+      FClosedPages[I]:= FClosedPages[I+1];
+    FClosedPages[High(FClosedPages)]:= APage;  // put last
+  end else begin
+    SetLength(FClosedPages, Length(FClosedPages) + 1);  // push
+    FClosedPages[High(FClosedPages)]:= APage;
+  end;
   FPageControl.Pages[Index].Free;
   //APage.Free;
 end;
Undo-Close-Tab2.patch (1,011 bytes)   
Undo-Close-Tab-svn.patch (4,952 bytes)   
Index: src/fmain.lfm
===================================================================
--- src/fmain.lfm	(revision 8763)
+++ src/fmain.lfm	(working copy)
@@ -1219,6 +1219,9 @@
       object miLine15: TMenuItem
         Caption = '-'
       end
+      object mnuUndoCloseTab: TMenuItem
+        Action = actUndoCloseTab
+      end
       object mnuCloseTab: TMenuItem
         Action = actCloseTab
       end
@@ -1682,6 +1685,13 @@
       Caption = '&Benchmark'
       OnExecute = actExecute
     end
+    object actUndoCloseTab: TAction
+      Tag = 21
+      Category = 'Tabs'
+      Caption = '&Undo Close Tab'
+      HelpType = htKeyword
+      OnExecute = actExecute
+    end
     object actNewTab: TAction
       Tag = 21
       Category = 'Tabs'
Index: src/fmain.pas
===================================================================
--- src/fmain.pas	(revision 8763)
+++ src/fmain.pas	(working copy)
@@ -122,6 +122,7 @@
     actFocusTreeView: TAction;
     actToggleFullscreenConsole: TAction;
     actSrcOpenDrives: TAction;
+    actUndoCloseTab: TAction;
     actRightReverseOrder: TAction;
     actLeftReverseOrder: TAction;
     actRightFlatView: TAction;
@@ -336,6 +337,7 @@
     mnuTabOptionPathResets: TMenuItem;
     mnuCloseAllTabs: TMenuItem;
     mnuCloseTab: TMenuItem;
+    mnuUndoCloseTab: TMenuItem;
     miLine15: TMenuItem;
     mnuOpenDirInNewTab: TMenuItem;
     mnuNewTab: TMenuItem;
Index: src/ufileviewnotebook.pas
===================================================================
--- src/ufileviewnotebook.pas	(revision 8763)
+++ src/ufileviewnotebook.pas	(working copy)
@@ -150,6 +150,7 @@
     FNotebookSide: TFilePanelSelect;
     FOnCloseTabClicked: TNotifyEvent;
     FPageControl: TFileViewPageControl;
+    FClosedPages: array of TFileViewPage;
 
     function GetActivePage: TFileViewPage;
     function GetActiveView: TFileView;
@@ -186,6 +187,7 @@
     function NewEmptyPage: TFileViewPage;
     function NewPage(CloneFromPage: TFileViewPage): TFileViewPage;
     function NewPage(CloneFromView: TFileView): TFileViewPage;
+    procedure UndoClosePage();
     procedure DeletePage(Index: Integer);
     procedure RemovePage(Index: Integer); reintroduce;
     procedure RemovePage(var APage: TFileViewPage);
@@ -875,12 +877,39 @@
 procedure TFileViewNotebook.DeletePage(Index: Integer);
 var
   APage: TFileViewPage;
+  I: Integer;
 begin
   APage:= GetPage(Index);
+  if Length(FClosedPages) >= 10 then  // max undo pages count
+  begin
+    FClosedPages[0].Free;  // pop first
+    for I:= 0 to Length(FClosedPages) - 2 do  // move all left
+      FClosedPages[I]:= FClosedPages[I+1];
+    FClosedPages[High(FClosedPages)]:= APage;  // put last
+  end else begin
+    SetLength(FClosedPages, Length(FClosedPages) + 1);  // push
+    FClosedPages[High(FClosedPages)]:= APage;
+  end;
   FPageControl.Pages[Index].Free;
-  APage.Free;
+  //APage.Free;
 end;
 
+procedure TFileViewNotebook.UndoClosePage();
+var
+  ANewPage: TFileViewPage;
+  Last: TFileViewPage;
+begin
+  if Length(FClosedPages) > 0 then
+  begin
+    ANewPage := NewEmptyPage();
+    Last := FClosedPages[High(FClosedPages)];
+    ANewPage.AssignPage(Last);
+    ANewPage.MakeActive;
+    SetLength(FClosedPages, Length(FClosedPages) - 1);  // pop
+    Last.Free;
+  end;
+end;
+
 procedure TFileViewNotebook.RemovePage(Index: Integer);
 begin
 {$IFDEF LCLGTK2}
Index: src/uglobs.pas
===================================================================
--- src/uglobs.pas	(revision 8763)
+++ src/uglobs.pas	(working copy)
@@ -975,6 +975,7 @@
       AddIfNotExists(['Ctrl+T'],[],'cm_NewTab');
       AddIfNotExists(['Ctrl+U'],[],'cm_Exchange');
       AddIfNotExists(['Ctrl+W'],[],'cm_CloseTab');
+      AddIfNotExists(['Ctrl+Shift+W'],[],'cm_UndoCloseTab');
       AddIfNotExists(['Ctrl+F1'],[],'cm_BriefView');
       AddIfNotExists(['Ctrl+F2'],[],'cm_ColumnsView');
       AddIfNotExists(['Ctrl+F3'],[],'cm_SortByName');
Index: src/umaincommands.pas
===================================================================
--- src/umaincommands.pas	(revision 8763)
+++ src/umaincommands.pas	(working copy)
@@ -187,6 +187,7 @@
    procedure cm_QuickSearch(const Params: array of string);
    procedure cm_QuickFilter(const Params: array of string);
    procedure cm_SrcOpenDrives(const {%H-}Params: array of string);
+   procedure cm_UndoCloseTab(const {%H-}Params: array of string);
    procedure cm_LeftOpenDrives(const {%H-}Params: array of string);
    procedure cm_RightOpenDrives(const {%H-}Params: array of string);
    procedure cm_OpenBar(const {%H-}Params: array of string);
@@ -1367,6 +1368,11 @@
   frmMain.ShowDrivesList(frmMain.SelectedPanel);
 end;
 
+procedure TMainCommands.cm_UndoCloseTab(const Params: array of string);
+begin
+  frmMain.ActiveNotebook.UndoClosePage();
+end;
+
 procedure TMainCommands.cm_LeftOpenDrives(const Params: array of string);
 begin
   frmMain.ShowDrivesList(fpLeft);
Undo-Close-Tab-svn.patch (4,952 bytes)   
Fixed in Revision
Operating system
Widgetset
Architecture

Relationships

duplicate of 0000942 new Ability to restore accidentally closed tab 

Activities

CryHam

2019-03-10 14:31

reporter   ~0003085

Right, so I've implemented it.
I'm attaching the patch file (from my git repo). I hope it's ok, it was done on today's trunk.

I followed the "RECIPE TO ADD A "cm_" COMMAND:" from uMainCommands, at least half of it.
But: I didn't make an icon, didn't test toolbar (I never use it), I don't see a file "doc\en\cmds.html" and I'm not sure about TC compatibility at all.

Alexx2000

2019-03-17 12:20

administrator   ~0003097

I think it's not a good solution. Unlimited history is bad, user close tabs but really they exists and consume resources.

CryHam

2019-03-17 13:27

reporter   ~0003098

Right.
I've added some code limiting to max. 10 undo pages in 2nd patch file.
It destroys 1st and moves all left in array (I'm not sure if there is a nicer way to code this).

CryHam

2019-03-31 00:20

reporter   ~0003122

I've attached Undo-Close-Tab-svn.patch, done on svn rev 8763.
It has both previous files.

Alexx2000

2019-03-31 00:26

administrator   ~0003124

I think this behavior should be optional. So it is also needed to add an option to enable/disable.

CryHam

2019-03-31 14:54

reporter   ~0003125

Hmm. Why optional?
Are there any downsides to having undo? Since there is a maximum of 10 there is no memory issue here. Will anything bad happen if a user does undo a closed tab by accident? I'm not sure where the benefit is.
Sure, I can add a checkbox in options. But this means more options in GUI and more strings to translate, right?.

Issue History

Date Modified Username Field Change
2018-03-05 13:19 CryHam New Issue
2018-03-06 19:22 cordylus Relationship added duplicate of 0000942
2019-03-10 14:31 CryHam File Added: Undo-Close-Tab.patch
2019-03-10 14:31 CryHam Note Added: 0003085
2019-03-17 12:20 Alexx2000 Note Added: 0003097
2019-03-17 13:25 CryHam File Added: Undo-Close-Tab2.patch
2019-03-17 13:27 CryHam Note Added: 0003098
2019-03-31 00:18 CryHam File Added: Undo-Close-Tab-svn.patch
2019-03-31 00:20 CryHam Note Added: 0003122
2019-03-31 00:26 Alexx2000 Note Added: 0003124
2019-03-31 14:54 CryHam Note Added: 0003125