Преглед изворни кода

Bug 1369: Failure when changing directory while another command was executing already (2nd try)

https://winscp.net/tracker/1369

Source commit: abee25d8866b857cfa5f5043b900fec8f6e98565
Martin Prikryl пре 10 година
родитељ
комит
065d474b01

+ 27 - 57
source/components/UnixDirView.cpp

@@ -804,71 +804,41 @@ TDropEffectSet __fastcall TUnixDirView::GetDragSourceEffects()
   return Result;
 }
 //---------------------------------------------------------------------------
-bool __fastcall TUnixDirView::DoBusy(bool Busy)
-{
-  bool Result = true;
-  if (OnBusy != NULL)
-  {
-    OnBusy(this, Busy, Result);
-  }
-  return Result;
-}
-//---------------------------------------------------------------------------
-bool __fastcall TUnixDirView::StartBusy()
-{
-  return DoBusy(true);
-}
-//---------------------------------------------------------------------------
-void __fastcall TUnixDirView::EndBusy()
-{
-  ALWAYS_TRUE(DoBusy(false));
-}
-//---------------------------------------------------------------------------
 void __fastcall TUnixDirView::ChangeDirectory(UnicodeString Path)
 {
-  if (StartBusy())
+  UnicodeString LastFile = L"";
+  if (ItemFocused) LastFile = ItemFileName(ItemFocused);
+  ClearItems();
+  DoAnimation(true);
+#ifndef DESIGN_ONLY
+  try
   {
-    try
+    FDirLoadedAfterChangeDir = false;
+    if (Path == HOMEDIRECTORY)
     {
-      UnicodeString LastFile = L"";
-      if (ItemFocused) LastFile = ItemFileName(ItemFocused);
-      ClearItems();
-      DoAnimation(true);
-    #ifndef DESIGN_ONLY
-      try
-      {
-        FDirLoadedAfterChangeDir = false;
-        if (Path == HOMEDIRECTORY)
-        {
-          Terminal->HomeDirectory();
-        }
-        else
-        // this works even with LockInHome
-        if (Path == ROOTDIRECTORY)
-        {
-          Terminal->CurrentDirectory = ROOTDIRECTORY;
-        }
-        else
-        {
-          Terminal->ChangeDirectory(Path);
-        }
-      }
-      __finally
-      {
-        // changing directory failed, so we load again old directory
-        if (!FDirLoadedAfterChangeDir)
-        {
-          FSelectFile = LastFile;
-          Reload(false);
-        };
-      }
-    #endif
+      Terminal->HomeDirectory();
     }
-    __finally
+    else
+    // this works even with LockInHome
+    if (Path == ROOTDIRECTORY)
+    {
+      Terminal->CurrentDirectory = ROOTDIRECTORY;
+    }
+    else
     {
-      EndBusy();
+      Terminal->ChangeDirectory(Path);
     }
   }
+  __finally
+  {
+    // changing directory failed, so we load again old directory
+    if (!FDirLoadedAfterChangeDir)
+    {
+      FSelectFile = LastFile;
+      Reload(false);
+    };
+  }
+#endif
 }
 //---------------------------------------------------------------------------
 bool __fastcall TUnixDirView::CanEdit(TListItem* Item)

+ 1 - 7
source/components/UnixDirView.h

@@ -18,8 +18,6 @@ enum TTransferDirection { tdToRemote, tdToLocal };
 enum TTransferType { ttCopy, ttMove };
 typedef void __fastcall (__closure *TDDDragFileName)
   (TObject * Sender, TRemoteFile * File, UnicodeString & FileName);
-typedef void __fastcall (__closure *TDirViewBusy)
-  (TObject * Sender, bool Busy, bool & Allow);
 //---------------------------------------------------------------------------
 class PACKAGE TUnixDirView : public TCustomUnixDirView
 {
@@ -34,7 +32,6 @@ private:
   TTerminal *FTerminal;
   bool FShowInaccesibleDirectories;
   TDDDragFileName FOnDDDragFileName;
-  TDirViewBusy FOnBusy;
   bool __fastcall GetActive();
   TCustomUnixDriveView * FDriveView;
   TNotifyEvent FOnRead;
@@ -80,9 +77,6 @@ protected:
   virtual int __fastcall HiddenCount();
   virtual int __fastcall FilteredCount();
   DYNAMIC void __fastcall UpdatePathLabelCaption();
-  bool __fastcall DoBusy(bool Busy);
-  bool __fastcall StartBusy();
-  void __fastcall EndBusy();
 
   __property TCustomUnixDriveView * DriveView = { read = FDriveView, write = SetDriveView };
 
@@ -111,7 +105,7 @@ __published:
     write = SetDDAllowMove, default = False };
   __property TDDDragFileName OnDDDragFileName = { read = FOnDDDragFileName,
     write = FOnDDDragFileName};
-  __property TDirViewBusy OnBusy = { read = FOnBusy, write = FOnBusy };
+  __property OnBusy;
   __property bool ShowInaccesibleDirectories  =
     { read=FShowInaccesibleDirectories, write=SetShowInaccesibleDirectories,
       default=true  };

+ 8 - 4
source/forms/CustomScpExplorer.cpp

@@ -8719,17 +8719,17 @@ void __fastcall TCustomScpExplorerForm::EditMenuItemPopup(TTBCustomItem * Sender
   NonVisualDataModule->EditMenuItemPopup(Sender, FromLink);
 }
 //---------------------------------------------------------------------------
-void __fastcall TCustomScpExplorerForm::RemoteDirViewBusy(TObject * /*Sender*/, bool Busy, bool & Allow)
+void __fastcall TCustomScpExplorerForm::DirViewBusy(TObject * /*Sender*/, int Busy, bool & State)
 {
   // This is somewhat redundant to LockWindow() call from
   // TTerminalManager::TerminalReadDirectoryProgress.
   // But disabling window is known not to block keyboard shorcuts
   // (see TCustomScpExplorerForm::AllowedAction), this hopefully works.
-  if (Busy)
+  if (Busy > 0)
   {
     if (NonVisualDataModule->Busy)
     {
-      Allow = false;
+      State = false;
     }
     else
     {
@@ -8737,10 +8737,14 @@ void __fastcall TCustomScpExplorerForm::RemoteDirViewBusy(TObject * /*Sender*/,
       LockWindow();
     }
   }
-  else
+  else if (Busy < 0)
   {
     UnlockWindow();
     NonVisualDataModule->EndBusy();
   }
+  else
+  {
+    State = NonVisualDataModule->Busy;
+  }
 }
 //---------------------------------------------------------------------------

+ 1 - 1
source/forms/CustomScpExplorer.dfm

@@ -87,7 +87,7 @@ object CustomScpExplorerForm: TCustomScpExplorerForm
       UnixColProperties.ExtWidth = 20
       UnixColProperties.TypeVisible = False
       OnDDDragFileName = RemoteFileControlDDDragFileName
-      OnBusy = RemoteDirViewBusy
+      OnBusy = DirViewBusy
       OnGetSelectFilter = RemoteDirViewGetSelectFilter
       OnSelectItem = DirViewSelectItem
       OnLoaded = DirViewLoaded

+ 1 - 1
source/forms/CustomScpExplorer.h

@@ -183,7 +183,7 @@ __published:
     int Y, TDragState State, bool &Accept);
   void __fastcall QueueView3Exit(TObject *Sender);
   void __fastcall EditMenuItemPopup(TTBCustomItem *Sender, bool FromLink);
-  void __fastcall RemoteDirViewBusy(TObject *Sender, bool Busy, bool & Allow);
+  void __fastcall DirViewBusy(TObject *Sender, int Busy, bool & Allow);
 
 private:
   TTerminal * FTerminal;

+ 1 - 0
source/forms/ScpCommander.dfm

@@ -1413,6 +1413,7 @@ inherited ScpCommanderForm: TScpCommanderForm
       OnHistoryChange = DirViewHistoryChange
       OnHistoryGo = DirViewHistoryGo
       OnPathChange = LocalDirViewPathChange
+      OnBusy = DirViewBusy
     end
     object LocalTopDock: TTBXDock
       Left = 0

+ 81 - 14
source/packages/filemng/CustomDirView.pas

@@ -93,6 +93,8 @@ type
   TMatchMaskEvent = procedure(Sender: TObject; FileName: string; Directory: Boolean; Size: Int64; Modification: TDateTime; Masks: string; var Matches: Boolean; AllowImplicitMatches: Boolean) of object;
   TDirViewGetOverlayEvent = procedure(Sender: TObject; Item: TListItem; var Indexes: Word) of object;
   TDirViewUpdateStatusBarEvent = procedure(Sender: TObject; const FileInfo: TStatusFileInfo) of object;
+  TDirViewBusy = procedure(Sender: TObject; Busy: Integer; var State: Boolean) of object;
+  TBusyOperation = reference to procedure;
 
 type
   TCustomDirView = class;
@@ -197,6 +199,7 @@ type
     FScrollOnDragOver: TListViewScrollOnDragOver;
     FStatusFileInfo: TStatusFileInfo;
     FDoubleBufferedScrollingWorkaround: Boolean;
+    FOnBusy: TDirViewBusy;
 
     procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
     procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
@@ -340,6 +343,14 @@ type
     procedure EnsureSelectionRedrawn;
     function HiddenCount: Integer; virtual; abstract;
     function FilteredCount: Integer; virtual; abstract;
+    function DoBusy(Busy: Integer): Boolean;
+    function StartBusy: Boolean;
+    procedure EndBusy;
+    function IsBusy: Boolean;
+    procedure BusyOperation(Operation: TBusyOperation);
+    procedure DoDisplayPropertiesMenu;
+    procedure DoExecute(Item: TListItem);
+    procedure DoExecuteParentDirectory;
     property ImageList16: TImageList read FImageList16;
     property ImageList32: TImageList read FImageList32;
   public
@@ -490,6 +501,7 @@ type
     property PathLabel: TCustomPathLabel read FPathLabel write SetPathLabel;
     property ShowHiddenFiles: Boolean read FShowHiddenFiles write SetShowHiddenFiles default True;
     property OnUpdateStatusBar: TDirViewUpdateStatusBarEvent read FOnUpdateStatusBar write FOnUpdateStatusBar;
+    property OnBusy: TDirViewBusy read FOnBusy write FOnBusy;
     {Watch current directory for filename changes (create, rename, delete files)}
     property WatchForChanges: Boolean read FWatchForChanges write SetWatchForChanges default False;
   end;
@@ -1414,6 +1426,22 @@ begin
   end;
 end;
 
+procedure TCustomDirView.DoDisplayPropertiesMenu;
+begin
+  if not IsBusy then
+    DisplayPropertiesMenu;
+end;
+
+procedure TCustomDirView.DoExecute(Item: TListItem);
+begin
+  BusyOperation(procedure begin Execute(Item); end);
+end;
+
+procedure TCustomDirView.DoExecuteParentDirectory;
+begin
+  BusyOperation(ExecuteParentDirectory);
+end;
+
 procedure TCustomDirView.KeyDown(var Key: Word; Shift: TShiftState);
 begin
   if Valid and (not IsEditing) and (not Loading) then
@@ -1424,9 +1452,9 @@ begin
       if Assigned(ItemFocused) then
       begin
          Key := 0;
-         if (Key = VK_RETURN) and (Shift = [ssAlt]) then DisplayPropertiesMenu
+         if (Key = VK_RETURN) and (Shift = [ssAlt]) then DoDisplayPropertiesMenu
            else
-         if (Key <> VK_RETURN) or (Shift = []) then Execute(ItemFocused);
+         if (Key <> VK_RETURN) or (Shift = []) then DoExecute(ItemFocused);
       end;
     end
       else
@@ -1434,7 +1462,7 @@ begin
        (not IsRoot) then
     begin
       Key := 0;
-      ExecuteParentDirectory;
+      DoExecuteParentDirectory;
     end
       else
     if ((Key = VK_UP) and (ssAlt in Shift)) and
@@ -1446,13 +1474,13 @@ begin
       // We could obtain the value programatically using
       // MultiByteToWideChar(CP_OEMCP, MB_USEGLYPHCHARS, "\x8", 1, ...)
       FNextCharToIgnore := $25D8;
-      ExecuteParentDirectory;
+      DoExecuteParentDirectory;
     end
       else
     if (Key = 220 { backslash }) and (ssCtrl in Shift) and (not IsRoot) then
     begin
       Key := 0;
-      ExecuteRootDirectory;
+      BusyOperation(ExecuteRootDirectory);
     end
       else
     if (Key = VK_LEFT) and (ssAlt in Shift) then
@@ -1511,7 +1539,7 @@ var
 begin
   if Key = VK_APPS then
   begin
-    if not Loading then
+    if (not Loading) and (not IsBusy) then
     begin
       if MarkedCount > 0 then
       begin
@@ -1659,8 +1687,8 @@ begin
   if Assigned(ItemFocused) and (not Loading) and
      (GetItemAt(Message.XPos, Message.YPos) = ItemFocused) then
   begin
-    if GetKeyState(VK_MENU) < 0 then DisplayPropertiesMenu
-      else Execute(ItemFocused);
+    if GetKeyState(VK_MENU) < 0 then DoDisplayPropertiesMenu
+      else DoExecute(ItemFocused);
   end;
 end;
 
@@ -2718,13 +2746,13 @@ begin
     if Command = _APPCOMMAND_BROWSER_REFRESH then
     begin
       Message.Result := 1;
-      ReloadDirectory;
+      BusyOperation(ReloadDirectory);
     end
       else
     if Command = _APPCOMMAND_BROWSER_HOME then
     begin
       Message.Result := 1;
-      ExecuteHomeDirectory;
+      BusyOperation(ExecuteHomeDirectory);
     end
       else inherited;
   end
@@ -2842,11 +2870,16 @@ procedure TCustomDirView.DoHistoryGo(Index: Integer);
 var
   Cancel: Boolean;
 begin
-  Cancel := False;
-  if Assigned(OnHistoryGo) then
-    OnHistoryGo(Self, Index, Cancel);
+  if StartBusy then
+    try
+      Cancel := False;
+      if Assigned(OnHistoryGo) then
+        OnHistoryGo(Self, Index, Cancel);
 
-  if not Cancel then HistoryGo(Index);
+      if not Cancel then HistoryGo(Index);
+    finally
+      EndBusy;
+    end;
 end;
 
 procedure TCustomDirView.HistoryGo(Index: Integer);
@@ -3230,6 +3263,40 @@ begin
   end;
 end;
 
+function TCustomDirView.DoBusy(Busy: Integer): Boolean;
+begin
+  Result := True;
+  if Assigned(OnBusy) then
+  begin
+    OnBusy(Self, Busy, Result);
+  end;
+end;
+
+function TCustomDirView.StartBusy: Boolean;
+begin
+  Result := DoBusy(1);
+end;
+
+function TCustomDirView.IsBusy: Boolean;
+begin
+  Result := DoBusy(0);
+end;
+
+procedure TCustomDirView.EndBusy;
+begin
+  DoBusy(-1);
+end;
+
+procedure TCustomDirView.BusyOperation(Operation: TBusyOperation);
+begin
+  if StartBusy then
+    try
+      Operation;
+    finally
+      EndBusy;
+    end;
+end;
+
 initialization
   DropSourceControl := nil;
 

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

@@ -385,6 +385,7 @@ type
     property OnHistoryChange;
     property OnHistoryGo;
     property OnPathChange;
+    property OnBusy;
 
     property ColumnClick;
     property MultiSelect;