Explorar el Código

Bug 1057: Remember remote directory tree nodes state when switching sessions

https://winscp.net/tracker/1057

Source commit: 38437663ba337eb817c89c58c0a0ff15149fcc0f
Martin Prikryl hace 4 años
padre
commit
a128fd8e7b

+ 45 - 2
source/components/UnixDirView.cpp

@@ -53,6 +53,7 @@ __fastcall TUnixDirView::TUnixDirView(TComponent* Owner)
   FFullLoad = false;
   FDriveView = NULL;
   FInvalidNameChars = L"/";
+  FLoadingDriveViewState = NULL;
   DragDropFilesEx->PreferCopy = true;
 }
 //---------------------------------------------------------------------------
@@ -558,9 +559,51 @@ void __fastcall TUnixDirView::SetTerminal(TTerminal * value)
   DoSetTerminal(value, false);
 }
 //---------------------------------------------------------------------------
-void __fastcall TUnixDirView::ReplaceTerminal(TTerminal * value)
+class TUnixDirViewState : public TObject
 {
-  DoSetTerminal(value, true);
+public:
+  std::unique_ptr<TObject> CustomDirViewState;
+  std::unique_ptr<TObject> DriveViewState;
+};
+//---------------------------------------------------------------------------
+TObject * __fastcall TUnixDirView::SaveState()
+{
+  TUnixDirViewState * State = new TUnixDirViewState();
+  State->CustomDirViewState.reset(TCustomUnixDirView::SaveState());
+  if (FDriveView != NULL)
+  {
+    State->DriveViewState.reset(FDriveView->SaveState());
+  }
+  return State;
+}
+//---------------------------------------------------------------------------
+void TUnixDirView::LoadTerminal(TTerminal * value, bool Replace, TObject * State)
+{
+  TObject * CustomDirViewState = NULL;
+  TObject * DriveViewState = NULL;
+  if (State != NULL)
+  {
+    TUnixDirViewState * UnixDirViewState = dynamic_cast<TUnixDirViewState *>(State);
+    if (DebugAlwaysTrue(UnixDirViewState != NULL))
+    {
+      CustomDirViewState = UnixDirViewState->CustomDirViewState.get();
+      DriveViewState = UnixDirViewState->DriveViewState.get();
+    }
+  }
+  TValueRestorer<TObject *> LoadingStateRestorer(FLoadingDriveViewState);
+  FLoadingDriveViewState = DriveViewState;
+
+  DoSetTerminal(value, Replace);
+
+  if (value->Active)
+  {
+    value->RefreshDirectory();
+  }
+
+  if (CustomDirViewState != NULL)
+  {
+    RestoreState(CustomDirViewState);
+  }
 }
 #endif
 //---------------------------------------------------------------------------

+ 3 - 1
source/components/UnixDirView.h

@@ -35,6 +35,7 @@ private:
   bool __fastcall GetActive();
   TCustomUnixDriveView * FDriveView;
   TNotifyEvent FOnRead;
+  TObject * FLoadingDriveViewState;
   void __fastcall SetTerminal(TTerminal *value);
   void __fastcall DoSetTerminal(TTerminal *value, bool Replace);
   void __fastcall SetShowInaccesibleDirectories(bool value);
@@ -98,7 +99,8 @@ public:
   virtual bool __fastcall PasteFromClipBoard(UnicodeString TargetPath = L"");
   void __fastcall UpdateFiles();
   void __fastcall DisplayContextMenu(const TPoint &Where);
-  void __fastcall ReplaceTerminal(TTerminal * value);
+  virtual TObject * __fastcall SaveState();
+  void LoadTerminal(TTerminal * value, bool Replace, TObject * State);
 
   __property bool Active = { read = GetActive };
   __property TTerminal *Terminal = { read = FTerminal, write = SetTerminal };

+ 39 - 1
source/components/UnixDriveView.cpp

@@ -202,6 +202,7 @@ void __fastcall TCustomUnixDriveView::UpdatePath(TTreeNode * Node, bool Force,
       ChildrenDirs->Duplicates = Types::dupAccept;
       ChildrenDirs->CaseSensitive = true;
 
+      bool FirstChild = true;
       TTreeNode * ChildNode = Node->getFirstChild();
       while (ChildNode != NULL)
       {
@@ -210,6 +211,7 @@ void __fastcall TCustomUnixDriveView::UpdatePath(TTreeNode * Node, bool Force,
         ChildrenDirs->AddObject(UnixExtractFileName(ChildData->Directory),
           ChildNode);
         ChildNode = Node->GetNextChild(ChildNode);
+        FirstChild = false;
       }
 
       // sort only after adding all items.
@@ -238,6 +240,11 @@ void __fastcall TCustomUnixDriveView::UpdatePath(TTreeNode * Node, bool Force,
             DebugAssert(!IsUnixRootPath(ChildPath));
 
             LoadPathEasy(Node, ChildPath, File);
+            if (FirstChild)
+            {
+              LoadNodeState(Node, Path);
+              FirstChild = false;
+            }
           }
         }
       }
@@ -333,9 +340,11 @@ TTreeNode * __fastcall TCustomUnixDriveView::LoadPath(UnicodeString Path)
     TTreeNode * Parent = NULL;
     TRemoteFile * File = NULL;
 
+    UnicodeString ParentPath;
     if (!IsUnixRootPath(Path))
     {
-      Parent = LoadPath(UnixExtractFileDir(Path));
+      ParentPath = UnixExtractFileDir(Path);
+      Parent = LoadPath(ParentPath);
     }
 
     Node = FindNodeToPath(Path);
@@ -355,6 +364,7 @@ TTreeNode * __fastcall TCustomUnixDriveView::LoadPath(UnicodeString Path)
       Node = LoadPathEasy(Parent, Path, File);
       if (Parent != NULL)
       {
+        LoadNodeState(Parent, ParentPath);
         Parent->AlphaSort(false);
       }
     }
@@ -880,3 +890,31 @@ void __fastcall TCustomUnixDriveView::DisplayPropertiesMenu(TTreeNode * /*Node*/
 {
   // TODO
 }
+//---------------------------------------------------------------------------
+void TCustomUnixDriveView::LoadNodeState(TTreeNode * Node, const UnicodeString & Path)
+{
+  if ((FDirView != NULL) && (FDirView->FLoadingDriveViewState != NULL))
+  {
+    TStrings * LoadingDriveViewState = DebugNotNull(dynamic_cast<TStrings *>(FDirView->FLoadingDriveViewState));
+    if (LoadingDriveViewState->IndexOf(Path) >= 0)
+    {
+      Node->Expand(false);
+    }
+  }
+}
+//---------------------------------------------------------------------------
+TObject * TCustomUnixDriveView::SaveState()
+{
+  std::unique_ptr<TStrings> ExpandedNodes(CreateSortedStringList());
+  TTreeNode * Node = Items->GetFirstNode();
+  while (Node != NULL)
+  {
+    if (Node->Expanded)
+    {
+      DebugAssert(Node->HasChildren);
+      ExpandedNodes->Add(NodePathName(Node));
+    }
+    Node = Node->GetNext();
+  }
+  return ExpandedNodes.release();
+}

+ 3 - 0
source/components/UnixDriveView.h

@@ -72,11 +72,14 @@ protected:
 
   virtual void __fastcall ValidateDirectoryEx(TTreeNode * Node,
     TRecursiveScan Recurse, bool NewDirs);
+  void LoadNodeState(TTreeNode * Node, const UnicodeString & Path);
 
   virtual void __fastcall RebuildTree();
   virtual void __fastcall DisplayContextMenu(TTreeNode * Node, const TPoint & ScreenPos);
   virtual void __fastcall DisplayPropertiesMenu(TTreeNode * Node);
 
+  TObject * SaveState();
+
   #pragma warn -inl
   BEGIN_MESSAGE_MAP
     VCL_MESSAGE_HANDLER(CM_SHOWINGCHANGED, TMessage, CMShowingChanged)

+ 3 - 15
source/forms/CustomScpExplorer.cpp

@@ -596,24 +596,12 @@ void __fastcall TCustomScpExplorerForm::SessionChanged(bool Replaced)
 
   if (Terminal != NULL)
   {
-    if (Replaced)
-    {
-      RemoteDirView->ReplaceTerminal(Terminal);
-    }
-    else
-    {
-      RemoteDirView->Terminal = Terminal;
-    }
-
-    if (Terminal->Active)
-    {
-      Terminal->RefreshDirectory();
-    }
-
+    TObject * State = NULL;
     if (WinConfiguration->PreservePanelState)
     {
-      DirView(osRemote)->RestoreState(Terminal->RemoteExplorerState);
+      State = Terminal->RemoteExplorerState;
     }
+    RemoteDirView->LoadTerminal(Terminal, Replaced, State);
   }
   else
   {

+ 2 - 2
source/packages/filemng/CustomDirView.pas

@@ -337,6 +337,7 @@ type
     procedure UpdateDarkMode;
     procedure DoUpdateStatusBar(Force: Boolean = False);
     procedure DoCustomDrawItem(Item: TListItem; Stage: TCustomDrawStage);
+    procedure RestoreState(AState: TObject);
     property ImageList16: TImageList read FImageList16;
     property ImageList32: TImageList read FImageList32;
   public
@@ -376,8 +377,7 @@ type
     procedure ContinueSession(Continue: Boolean);
     function CanPasteFromClipBoard: Boolean; dynamic;
     function PasteFromClipBoard(TargetPath: string = ''): Boolean; virtual; abstract;
-    function SaveState: TObject;
-    procedure RestoreState(AState: TObject);
+    function SaveState: TObject; virtual;
     procedure DisplayContextMenu(Where: TPoint); virtual; abstract;
     procedure DisplayContextMenuInSitu;
     procedure UpdateStatusBar;

+ 7 - 0
source/packages/filemng/DirView.pas

@@ -261,6 +261,7 @@ type
     function DuplicateSelectedFiles: Boolean; dynamic;
     procedure DisplayPropertiesMenu; override;
     procedure DisplayContextMenu(Where: TPoint); override;
+    procedure RestoreState(AState: TObject);
 
     procedure ExecuteParentDirectory; override;
     procedure ExecuteRootDirectory; override;
@@ -2454,6 +2455,12 @@ begin
   end;
 end;
 
+// Just to make it public
+procedure TDirView.RestoreState(AState: TObject);
+begin
+  inherited;
+end;
+
 procedure TDirView.GetDisplayInfo(ListItem: TListItem;
   var DispInfo: TLVItem);
 var