Ver Fonte

Progress of all synchronization operations shows in the same window

Effectively rolled back 6290dac89, as now that progress window is used for whole synchronization operation, it naturally preserves the speed limit.

Rolled back FOnProcessedItem mechanism from 0de5a412466 as it's no longer needed as SynchronizeApply now runs every operation standalone (grouping of operations by directory was to avoid re-showing progress window for each operation).

Source commit: 3e444844778923fdc067bf58ead2209caf6291ff
Martin Prikryl há 7 anos atrás
pai
commit
4df7eca506

+ 3 - 3
source/core/FileOperationProgress.cpp

@@ -204,7 +204,7 @@ void __fastcall TFileOperationProgressType::Resume()
   DoProgress();
 }
 //---------------------------------------------------------------------------
-int __fastcall TFileOperationProgressType::OperationProgress()
+int __fastcall TFileOperationProgressType::OperationProgress() const
 {
   int Result;
   if (FCount > 0)
@@ -232,7 +232,7 @@ int __fastcall TFileOperationProgressType::TransferProgress()
   return Result;
 }
 //---------------------------------------------------------------------------
-int __fastcall TFileOperationProgressType::TotalTransferProgress()
+int __fastcall TFileOperationProgressType::TotalTransferProgress() const
 {
   TGuard Guard(FSection);
   DebugAssert(TotalSizeSet);
@@ -240,7 +240,7 @@ int __fastcall TFileOperationProgressType::TotalTransferProgress()
   return Result < 100 ? Result : 100;
 }
 //---------------------------------------------------------------------------
-int __fastcall TFileOperationProgressType::OverallProgress()
+int __fastcall TFileOperationProgressType::OverallProgress() const
 {
   if (TotalSizeSet)
   {

+ 3 - 3
source/core/FileOperationProgress.h

@@ -78,7 +78,7 @@ private:
 protected:
   void __fastcall ClearTransfer();
   inline void __fastcall DoProgress();
-  int __fastcall OperationProgress();
+  int __fastcall OperationProgress() const;
   void __fastcall AddTransferredToTotals(__int64 ASize);
   void __fastcall AddSkipped(__int64 ASize);
   void __fastcall AddTotalSize(__int64 ASize);
@@ -174,8 +174,8 @@ public:
   TDateTime __fastcall TimeExpected();
   TDateTime __fastcall TotalTimeLeft();
   int __fastcall TransferProgress();
-  int __fastcall OverallProgress();
-  int __fastcall TotalTransferProgress();
+  int __fastcall OverallProgress() const;
+  int __fastcall TotalTransferProgress() const;
   void __fastcall SetSpeedCounters();
   void __fastcall SetTransferringFile(bool ATransferringFile);
   TCancelStatus __fastcall GetCancel();

+ 77 - 161
source/core/Terminal.cpp

@@ -932,7 +932,6 @@ __fastcall TTerminal::TTerminal(TSessionData * SessionData,
   FOnCustomCommand = NULL;
   FOnClose = NULL;
   FOnFindingFile = NULL;
-  FOnProcessedItem = NULL;
 
   FUseBusyCursor = True;
   FLockDirectory = L"";
@@ -3653,15 +3652,10 @@ void __fastcall TTerminal::AnnounceFileListOperation()
 }
 //---------------------------------------------------------------------------
 void __fastcall TTerminal::OperationFinish(
-  TFileOperationProgressType * Progress, const void * Item, const UnicodeString & FileName,
+  TFileOperationProgressType * Progress, const void * /*Item*/, const UnicodeString & FileName,
   bool Success, TOnceDoneOperation & OnceDoneOperation)
 {
   Progress->Finish(FileName, Success, OnceDoneOperation);
-
-  if ((Item != NULL) && (FOnProcessedItem != NULL) && (Progress->Operation != foCalculateSize))
-  {
-    FOnProcessedItem(Item);
-  }
 }
 //---------------------------------------------------------------------------
 bool __fastcall TTerminal::ProcessFiles(TStrings * FileList,
@@ -5878,7 +5872,7 @@ void __fastcall TTerminal::DoSynchronizeCollectFile(const UnicodeString FileName
 void __fastcall TTerminal::SynchronizeApply(
   TSynchronizeChecklist * Checklist,
   const TCopyParamType * CopyParam, int Params,
-  TSynchronizeDirectory OnSynchronizeDirectory, TProcessedItem OnProcessedItem,
+  TSynchronizeDirectory OnSynchronizeDirectory, TProcessedSynchronizationChecklistItem OnProcessedItem,
   TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems)
 {
   TSynchronizeData Data;
@@ -5921,180 +5915,106 @@ void __fastcall TTerminal::SynchronizeApply(
     }
   }
 
-  DebugAssert(FOnProcessedItem == NULL);
-  FOnProcessedItem = OnProcessedItem;
-
   BeginTransaction();
 
   try
   {
-    int IIndex = 0;
-    while (IIndex < Checklist->Count)
+    int Index = 0;
+    while (Index < Checklist->Count)
     {
-      std::unique_ptr<TStringList> DownloadList(new TStringList());
-      std::unique_ptr<TStringList> DeleteRemoteList(new TStringList());
-      std::unique_ptr<TStringList> UploadList(new TStringList());
-      std::unique_ptr<TStringList> DeleteLocalList(new TStringList());
-      __int64 DownloadSize = 0;
-      __int64 UploadSize = 0;
-
-      const TSynchronizeChecklist::TItem * ChecklistItem = Checklist->Item[IIndex];
-
-      UnicodeString CurrentLocalDirectory = ChecklistItem->Local.Directory;
-      UnicodeString CurrentRemoteDirectory = ChecklistItem->Remote.Directory;
-
-      LogEvent(
-        FORMAT(L"Synchronizing local directory '%s' with remote directory '%s', params = 0x%x (%s)",
-        (CurrentLocalDirectory, CurrentRemoteDirectory, int(Params), SynchronizeParamsStr(Params))));
-
-      int Count = 0;
-
-      while ((IIndex < Checklist->Count) &&
-             (Checklist->Item[IIndex]->Local.Directory == CurrentLocalDirectory) &&
-             (Checklist->Item[IIndex]->Remote.Directory == CurrentRemoteDirectory))
+      const TSynchronizeChecklist::TItem * ChecklistItem = Checklist->Item[Index];
+      if (ChecklistItem->Checked)
       {
-        ChecklistItem = Checklist->Item[IIndex];
-        TObject * ChecklistItemToken = const_cast<TObject *>(reinterpret_cast<const TObject *>(ChecklistItem));
-        if (ChecklistItem->Checked)
+        if (!SamePaths(Data.LocalDirectory, ChecklistItem->Local.Directory) ||
+            !UnixSamePath(Data.RemoteDirectory, ChecklistItem->Remote.Directory))
         {
-          Count++;
-
-          if (FLAGSET(Params, spTimestamp))
-          {
-            switch (ChecklistItem->Action)
-            {
-              case TSynchronizeChecklist::saDownloadUpdate:
-                DownloadList->AddObject(
-                  UnixIncludeTrailingBackslash(ChecklistItem->Remote.Directory) + ChecklistItem->Remote.FileName,
-                  ChecklistItemToken);
-                break;
-
-              case TSynchronizeChecklist::saUploadUpdate:
-                UploadList->AddObject(
-                  IncludeTrailingBackslash(ChecklistItem->Local.Directory) + ChecklistItem->Local.FileName,
-                  ChecklistItemToken);
-                break;
-
-              default:
-                DebugFail();
-                break;
-            }
-          }
-          else
-          {
-            switch (ChecklistItem->Action)
-            {
-              case TSynchronizeChecklist::saDownloadNew:
-              case TSynchronizeChecklist::saDownloadUpdate:
-                DownloadList->AddObject(
-                  UnixIncludeTrailingBackslash(ChecklistItem->Remote.Directory) + ChecklistItem->Remote.FileName,
-                  ChecklistItem->RemoteFile);
-                if ((DownloadSize >= 0) && ChecklistItem->HasSize())
-                {
-                  DownloadSize += ChecklistItem->GetSize();
-                }
-                else
-                {
-                  DownloadSize = -1;
-                }
-                break;
-
-              case TSynchronizeChecklist::saDeleteRemote:
-                DeleteRemoteList->AddObject(
-                  UnixIncludeTrailingBackslash(ChecklistItem->Remote.Directory) + ChecklistItem->Remote.FileName,
-                  ChecklistItem->RemoteFile);
-                break;
-
-              case TSynchronizeChecklist::saUploadNew:
-              case TSynchronizeChecklist::saUploadUpdate:
-                UploadList->AddObject(
-                  IncludeTrailingBackslash(ChecklistItem->Local.Directory) + ChecklistItem->Local.FileName,
-                  ChecklistItemToken);
-                if ((UploadSize >= 0) && ChecklistItem->HasSize())
-                {
-                  UploadSize += ChecklistItem->GetSize();
-                }
-                else
-                {
-                  UploadSize = -1;
-                }
-                break;
+          Data.LocalDirectory = IncludeTrailingBackslash(ChecklistItem->Local.Directory);
+          Data.RemoteDirectory = UnixIncludeTrailingBackslash(ChecklistItem->Remote.Directory);
 
-              case TSynchronizeChecklist::saDeleteLocal:
-                DeleteLocalList->AddObject(
-                  IncludeTrailingBackslash(ChecklistItem->Local.Directory) + ChecklistItem->Local.FileName,
-                  ChecklistItemToken);
-                break;
+          LogEvent(
+            FORMAT(L"Synchronizing local directory '%s' with remote directory '%s', params = 0x%x (%s)",
+            (Data.LocalDirectory, Data.RemoteDirectory, int(Params), SynchronizeParamsStr(Params))));
 
-              default:
-                DebugFail();
-                break;
-            }
-          }
+          DoSynchronizeProgress(Data, false);
         }
-        IIndex++;
-      }
 
-      // prevent showing/updating of progress dialog if there's nothing to do
-      if (Count > 0)
-      {
-        Data.LocalDirectory = IncludeTrailingBackslash(CurrentLocalDirectory);
-        Data.RemoteDirectory = UnixIncludeTrailingBackslash(CurrentRemoteDirectory);
-        DoSynchronizeProgress(Data, false);
+        std::unique_ptr<TStringList> FileList(new TStringList());
+
+        UnicodeString LocalPath = IncludeTrailingBackslash(ChecklistItem->Local.Directory) + ChecklistItem->Local.FileName;
+        UnicodeString RemotePath = UnixIncludeTrailingBackslash(ChecklistItem->Remote.Directory) + ChecklistItem->Remote.FileName;
+        bool Result = true;
 
         if (FLAGSET(Params, spTimestamp))
         {
-          if (DownloadList->Count > 0)
-          {
-            ProcessFiles(DownloadList.get(), foSetProperties, SynchronizeLocalTimestamp, NULL, osLocal);
-          }
-
-          if (UploadList->Count > 0)
+          switch (ChecklistItem->Action)
           {
-            ProcessFiles(UploadList.get(), foSetProperties, SynchronizeRemoteTimestamp);
+            case TSynchronizeChecklist::saDownloadUpdate:
+              FileList->Add(RemotePath);
+              ProcessFiles(FileList.get(), foSetProperties, SynchronizeLocalTimestamp, NULL, osLocal);
+              break;
+
+            case TSynchronizeChecklist::saUploadUpdate:
+              FileList->Add(LocalPath);
+              ProcessFiles(FileList.get(), foSetProperties, SynchronizeRemoteTimestamp);
+              break;
+
+            default:
+              DebugFail();
+              Result = false;
+              break;
           }
         }
         else
         {
-          if (DownloadList->Count > 0)
+          TCopyParamType ItemCopyParam = SyncCopyParam;
+          ItemCopyParam.Size = ChecklistItem->HasSize() ? ChecklistItem->GetSize() : -1;
+          switch (ChecklistItem->Action)
           {
-            TCopyParamType DownloadCopyParam = SyncCopyParam;
-            DownloadCopyParam.Size = DownloadSize;
-            if (!CopyToLocal(DownloadList.get(), Data.LocalDirectory, &DownloadCopyParam, CopyParams, NULL))
-            {
-              Abort();
-            }
-          }
-
-          if ((DeleteRemoteList->Count > 0) &&
-              !DeleteFiles(DeleteRemoteList.get()))
-          {
-            Abort();
+            case TSynchronizeChecklist::saDownloadNew:
+            case TSynchronizeChecklist::saDownloadUpdate:
+              FileList->AddObject(RemotePath, ChecklistItem->RemoteFile);
+              Result = CopyToLocal(FileList.get(), Data.LocalDirectory, &ItemCopyParam, CopyParams, NULL);
+              break;
+
+            case TSynchronizeChecklist::saDeleteRemote:
+              FileList->AddObject(RemotePath, ChecklistItem->RemoteFile);
+              Result = DeleteFiles(FileList.get());
+              break;
+
+            case TSynchronizeChecklist::saUploadNew:
+            case TSynchronizeChecklist::saUploadUpdate:
+              FileList->Add(LocalPath);
+              Result = CopyToRemote(FileList.get(), Data.RemoteDirectory, &ItemCopyParam, CopyParams, NULL);
+              break;
+
+            case TSynchronizeChecklist::saDeleteLocal:
+              FileList->Add(LocalPath);
+              Result = DeleteLocalFiles(FileList.get());
+              break;
+
+            default:
+              DebugFail();
+              Result = false;
+              break;
           }
+        }
 
-          if (UploadList->Count > 0)
-          {
-            TCopyParamType UploadCopyParam = SyncCopyParam;
-            UploadCopyParam.Size = UploadSize;
-            if (!CopyToRemote(UploadList.get(), Data.RemoteDirectory, &UploadCopyParam, CopyParams, NULL))
-            {
-              Abort();
-            }
-          }
+        if (!Result)
+        {
+          Abort();
+        }
 
-          if ((DeleteLocalList->Count > 0) &&
-              !DeleteLocalFiles(DeleteLocalList.get()))
-          {
-            Abort();
-          }
+        if (OnProcessedItem != NULL)
+        {
+          OnProcessedItem(ChecklistItem);
         }
       }
+
+      Index++;
     }
   }
   __finally
   {
-    FOnProcessedItem = NULL;
-
     EndTransaction();
   }
 }
@@ -6537,17 +6457,15 @@ int __fastcall TTerminal::CopyToParallel(TParallelOperation * ParallelOperation,
     try
     {
       FOperationProgress = OperationProgress;
-      // Need own copy, now that CopyToRemote/CopyToLocal modify the instance
-      TCopyParamType CopyParam = *ParallelOperation->CopyParam;
       if (ParallelOperation->Side == osLocal)
       {
         FFileSystem->CopyToRemote(
-          FilesToCopy.get(), TargetDir, &CopyParam, Params, OperationProgress, OnceDoneOperation);
+          FilesToCopy.get(), TargetDir, ParallelOperation->CopyParam, Params, OperationProgress, OnceDoneOperation);
       }
       else if (DebugAlwaysTrue(ParallelOperation->Side == osRemote))
       {
         FFileSystem->CopyToLocal(
-          FilesToCopy.get(), TargetDir, &CopyParam, Params, OperationProgress, OnceDoneOperation);
+          FilesToCopy.get(), TargetDir, ParallelOperation->CopyParam, Params, OperationProgress, OnceDoneOperation);
       }
     }
     __finally
@@ -6645,7 +6563,7 @@ void __fastcall TTerminal::LogTotalTransferDone(TFileOperationProgressType * Ope
 }
 //---------------------------------------------------------------------------
 bool __fastcall TTerminal::CopyToRemote(
-  TStrings * FilesToCopy, const UnicodeString & TargetDir, TCopyParamType * CopyParam, int Params,
+  TStrings * FilesToCopy, const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
   TParallelOperation * ParallelOperation)
 {
   DebugAssert(FFileSystem);
@@ -6743,7 +6661,6 @@ bool __fastcall TTerminal::CopyToRemote(
         Configuration->Usage->Inc(L"UploadTime", CounterTime);
         Configuration->Usage->SetMax(L"MaxUploadTime", CounterTime);
       }
-      CopyParam->CPSLimit = OperationProgress.CPSLimit;
       OperationProgress.Stop();
       FOperationProgress = NULL;
     }
@@ -7077,7 +6994,7 @@ void __fastcall TTerminal::Source(
 }
 //---------------------------------------------------------------------------
 bool __fastcall TTerminal::CopyToLocal(
-  TStrings * FilesToCopy, const UnicodeString & TargetDir, TCopyParamType * CopyParam, int Params,
+  TStrings * FilesToCopy, const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
   TParallelOperation * ParallelOperation)
 {
   DebugAssert(FFileSystem);
@@ -7199,7 +7116,6 @@ bool __fastcall TTerminal::CopyToLocal(
         Configuration->Usage->Inc(L"DownloadTime", CounterTime);
         Configuration->Usage->SetMax(L"MaxDownloadTime", CounterTime);
       }
-      CopyParam->CPSLimit = OperationProgress.CPSLimit;
       FOperationProgress = NULL;
       OperationProgress.Stop();
     }

+ 4 - 5
source/core/Terminal.h

@@ -57,7 +57,7 @@ typedef void __fastcall (__closure *TSynchronizeDirectory)
    bool & Continue, bool Collect);
 typedef void __fastcall (__closure *TUpdatedSynchronizationChecklistItems)(
   const TSynchronizeChecklist::TItemList & Items);
-typedef void __fastcall (__closure *TProcessedItem)(const void * Token);
+typedef void __fastcall (__closure *TProcessedSynchronizationChecklistItem)(const TSynchronizeChecklist::TItem * Item);
 typedef void __fastcall (__closure *TDeleteLocalFileEvent)(
   const UnicodeString FileName, bool Alternative);
 typedef int __fastcall (__closure *TDirectoryModifiedEvent)
@@ -225,7 +225,6 @@ private:
   TEncryptedFileNames FEncryptedFileNames;
   std::set<UnicodeString> FFoldersScannedForEncryptedFiles;
   RawByteString FEncryptKey;
-  TProcessedItem FOnProcessedItem;
 
   void __fastcall CommandError(Exception * E, const UnicodeString Msg);
   unsigned int __fastcall CommandError(Exception * E, const UnicodeString Msg,
@@ -505,10 +504,10 @@ public:
   bool __fastcall FileExists(const UnicodeString FileName, TRemoteFile ** File = NULL);
   void __fastcall ReadSymlink(TRemoteFile * SymlinkFile, TRemoteFile *& File);
   bool __fastcall CopyToLocal(
-    TStrings * FilesToCopy, const UnicodeString & TargetDir, TCopyParamType * CopyParam, int Params,
+    TStrings * FilesToCopy, const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
     TParallelOperation * ParallelOperation);
   bool __fastcall CopyToRemote(
-    TStrings * FilesToCopy, const UnicodeString & TargetDir, TCopyParamType * CopyParam, int Params,
+    TStrings * FilesToCopy, const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
     TParallelOperation * ParallelOperation);
   int __fastcall CopyToParallel(TParallelOperation * ParallelOperation, TFileOperationProgressType * OperationProgress);
   void __fastcall LogParallelTransfer(TParallelOperation * ParallelOperation);
@@ -560,7 +559,7 @@ public:
   void __fastcall SynchronizeApply(
     TSynchronizeChecklist * Checklist,
     const TCopyParamType * CopyParam, int Params,
-    TSynchronizeDirectory OnSynchronizeDirectory, TProcessedItem OnProcessedItem,
+    TSynchronizeDirectory OnSynchronizeDirectory, TProcessedSynchronizationChecklistItem OnProcessedItem,
     TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems);
   void __fastcall SynchronizeChecklistCalculateSize(
     TSynchronizeChecklist * Checklist, const TSynchronizeChecklist::TItemList & Items,

+ 84 - 45
source/forms/CustomScpExplorer.cpp

@@ -694,7 +694,7 @@ UnicodeString __fastcall TCustomScpExplorerForm::GetQueueProgressTitle()
         FQueueStatus->Items[FQueueStatus->DoneCount]->ProgressData;
       if ((ProgressData != NULL) && ProgressData->InProgress)
       {
-        Result = TProgressForm::ProgressStr(ProgressData);
+        Result = TProgressForm::ProgressStr(NULL, ProgressData);
       }
     }
     else if (FQueueStatus->ActiveAndPendingPrimaryCount > 1)
@@ -1346,6 +1346,35 @@ UnicodeString __fastcall TCustomScpExplorerForm::GetToolbarsButtonsStr()
   return Result;
 }
 //---------------------------------------------------------------------------
+void __fastcall TCustomScpExplorerForm::CreateProgressForm(const TSynchronizeChecklist * SynchronizeChecklist)
+{
+  DebugAssert(FProgressForm == NULL);
+  FProgressForm =
+    new TProgressForm(Application, (FTransferResumeList != NULL), Terminal->IsCapable[fsSkipTransfer], SynchronizeChecklist);
+
+  FProgressForm->DeleteLocalToRecycleBin =
+    (WinConfiguration->DeleteToRecycleBin != FAlternativeDelete);
+  FProgressForm->DeleteRemoteToRecycleBin =
+    (Terminal->SessionData->DeleteToRecycleBin != FAlternativeDelete) &&
+    !Terminal->SessionData->RecycleBinPath.IsEmpty();
+
+  // As progress window has delayed show now, we need to lock ourselves, (at least) until then
+  LockWindow();
+
+  if (FTaskbarList != NULL)
+  {
+    // Actually, do not know what hides the progress once the operation finishes
+    SetTaskbarListProgressState(TBPF_NORMAL);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TCustomScpExplorerForm::DestroyProgressForm()
+{
+  UnlockWindow();
+  SAFE_DESTROY(FProgressForm);
+  SetQueueProgress();
+}
+//---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::FileOperationProgress(
   TFileOperationProgressType & ProgressData)
 {
@@ -1364,18 +1393,8 @@ void __fastcall TCustomScpExplorerForm::FileOperationProgress(
   // operation is being executed and we still didn't show up progress form
   if (ProgressData.InProgress && !FProgressForm)
   {
-    bool AllowSkip =
-      ((ProgressData.Operation == foCopy) || (ProgressData.Operation == foMove)) &&
-      Terminal->IsCapable[fsSkipTransfer];
-    FProgressForm = new TProgressForm(Application, (FTransferResumeList != NULL), AllowSkip);
-    // As progress window has delayed show now, we need to lock ourselves,
-    // (at least) until then
-    LockWindow();
-    FProgressForm->DeleteToRecycleBin = (ProgressData.Side == osLocal ?
-      (WinConfiguration->DeleteToRecycleBin != FAlternativeDelete) :
-      ((Terminal->SessionData->DeleteToRecycleBin != FAlternativeDelete) &&
-       !Terminal->SessionData->RecycleBinPath.IsEmpty()));
-    // When main window is hidden, synchronisation form does not exist,
+    CreateProgressForm(NULL);
+    // When main window is hidden, synchronisation form does not exist (we do not get here during synchronization - only comparing),
     // we suppose "/upload" or URL download mode
     if (!Visible && (ProgressData.Operation != foCalculateSize) &&
         (ProgressData.Operation != foCalculateChecksum) &&
@@ -1384,20 +1403,11 @@ void __fastcall TCustomScpExplorerForm::FileOperationProgress(
     {
       FProgressForm->OnceDoneOperation = odoDisconnect;
     }
-
-    if (FTaskbarList != NULL)
-    {
-      // Actually, do not know what hides the progress once the operation finishes
-      SetTaskbarListProgressState(TBPF_NORMAL);
-    }
   }
   // operation is finished (or terminated), so we hide progress form
-  else if (!ProgressData.InProgress && FProgressForm)
+  else if (!ProgressData.InProgress && (FProgressForm != NULL) && (FProgressForm->SynchronizeChecklist == NULL))
   {
-    UnlockWindow();
-    SAFE_DESTROY(FProgressForm);
-
-    SetQueueProgress();
+    DestroyProgressForm();
 
     if (ProgressData.Operation == foCalculateSize)
     {
@@ -1421,7 +1431,9 @@ void __fastcall TCustomScpExplorerForm::FileOperationProgress(
     }
   }
 
-  if (FProgressForm)
+  if (FProgressForm &&
+      // Can happen only during synchronization, when ending one of the operations
+      ProgressData.InProgress)
   {
     FProgressForm->SetProgressData(ProgressData);
 
@@ -1491,6 +1503,22 @@ void __fastcall TCustomScpExplorerForm::OperationProgress(
   FileOperationProgress(ProgressData);
 }
 //---------------------------------------------------------------------------
+UnicodeString __fastcall TCustomScpExplorerForm::GetProgressTitle(const TFileOperationProgressType & ProgressData)
+{
+  UnicodeString Result;
+  if (ProgressData.InProgress)
+  {
+    const TSynchronizeChecklist * SynchronizeChecklist = NULL;
+    if (FProgressForm != NULL)
+    {
+      SynchronizeChecklist = FProgressForm->SynchronizeChecklist;
+    }
+
+    Result = TProgressForm::ProgressStr(SynchronizeChecklist, &ProgressData);
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 bool __fastcall TCustomScpExplorerForm::PanelOperation(TOperationSide /*Side*/,
   bool DragDrop)
 {
@@ -5227,19 +5255,21 @@ void __fastcall TCustomScpExplorerForm::Synchronize(const UnicodeString LocalDir
 
     SAFE_DESTROY(FSynchronizeProgressForm);
 
-    FSynchronizeProgressForm = new TSynchronizeProgressForm(Application, true, false);
-    if (FLAGCLEAR(Params, TTerminal::spDelayProgress))
+    AnyOperation = (AChecklist->CheckedCount > 0);
+    if (AnyOperation)
     {
-      FSynchronizeProgressForm->Start();
-    }
+      CreateProgressForm(AChecklist);
 
-    for (int Index = 0; !AnyOperation && (Index < AChecklist->Count); Index++)
-    {
-      AnyOperation = AChecklist->Item[Index]->Checked;
+      try
+      {
+        Terminal->SynchronizeApply(AChecklist, &CopyParam, Params | TTerminal::spNoConfirmation, TerminalSynchronizeDirectory, NULL, NULL);
+      }
+      __finally
+      {
+        DestroyProgressForm();
+      }
     }
 
-    // No need to call if !AnyOperation
-    Terminal->SynchronizeApply(AChecklist, &CopyParam, Params | TTerminal::spNoConfirmation, TerminalSynchronizeDirectory, NULL, NULL);
   }
   __finally
   {
@@ -5342,7 +5372,8 @@ struct TSynchronizeParams
 };
 //---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::FullSynchronize(
-  TSynchronizeParams & Params, TProcessedItem OnProcessedItem, TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems)
+  TSynchronizeParams & Params, TProcessedSynchronizationChecklistItem OnProcessedItem,
+  TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems)
 {
   DebugAssert(!FAutoOperation);
   void * BatchStorage;
@@ -5351,8 +5382,7 @@ void __fastcall TCustomScpExplorerForm::FullSynchronize(
 
   try
   {
-    FSynchronizeProgressForm = new TSynchronizeProgressForm(Application, true, false);
-    FSynchronizeProgressForm->Start();
+    CreateProgressForm(Params.Checklist);
 
     Terminal->SynchronizeApply(
       Params.Checklist, Params.CopyParam, Params.Params | TTerminal::spNoConfirmation,
@@ -5361,14 +5391,15 @@ void __fastcall TCustomScpExplorerForm::FullSynchronize(
   __finally
   {
     FAutoOperation = false;
-    SAFE_DESTROY(FSynchronizeProgressForm);
+    DestroyProgressForm();
     BatchEnd(BatchStorage);
     ReloadLocalDirectory();
   }
 }
 //---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::DoFullSynchronize(
-  void * Token, TProcessedItem OnProcessedItem, TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems)
+  void * Token, TProcessedSynchronizationChecklistItem OnProcessedItem,
+  TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems)
 {
   TSynchronizeParams & Params = *static_cast<TSynchronizeParams *>(Token);
   *Params.StartTime = Now();
@@ -5496,14 +5527,22 @@ bool __fastcall TCustomScpExplorerForm::DoFullSynchronizeDirectories(
 //---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::TerminalSynchronizeDirectory(
   const UnicodeString LocalDirectory, const UnicodeString RemoteDirectory,
-  bool & Continue, bool /*Collect*/)
+  bool & Continue, bool Collect)
 {
-  DebugAssert(FSynchronizeProgressForm != NULL);
-  if (!FSynchronizeProgressForm->Started)
+  if (Collect)
+  {
+    DebugAssert(FSynchronizeProgressForm != NULL);
+    if (!FSynchronizeProgressForm->Started)
+    {
+      FSynchronizeProgressForm->Start();
+    }
+    FSynchronizeProgressForm->SetData(LocalDirectory, RemoteDirectory, Continue);
+  }
+  else
   {
-    FSynchronizeProgressForm->Start();
+    DebugAssert(FSynchronizeProgressForm == NULL);
+    DebugAssert(FProgressForm != NULL);
   }
-  FSynchronizeProgressForm->SetData(LocalDirectory, RemoteDirectory, Continue);
 }
 //---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::StandaloneEdit(const UnicodeString & FileName)
@@ -7211,7 +7250,7 @@ void __fastcall TCustomScpExplorerForm::RemoteFileControlDDTargetDrop()
 }
 //---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::DDDownload(
-  TStrings * FilesToCopy, const UnicodeString & TargetDir, TCopyParamType * CopyParam, int Params)
+  TStrings * FilesToCopy, const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params)
 {
   void * BatchStorage;
   BatchStart(BatchStorage);

+ 7 - 3
source/forms/CustomScpExplorer.h

@@ -383,6 +383,8 @@ protected:
     TOperationSide Side, bool Temp, const UnicodeString & FileName, bool Success,
     TOnceDoneOperation & OnceDoneOperation);
   virtual void __fastcall DoOpenDirectoryDialog(TOpenDirectoryMode Mode, TOperationSide Side);
+  void __fastcall CreateProgressForm(const TSynchronizeChecklist * SynchronizeChecklist);
+  void __fastcall DestroyProgressForm();
   virtual void __fastcall FileOperationProgress(TFileOperationProgressType & ProgressData);
   void __fastcall OperationComplete(const TDateTime & StartTime);
   void __fastcall ExecutedFileChanged(const UnicodeString FileName,
@@ -462,7 +464,7 @@ protected:
   bool __fastcall RemoteFileControlFileOperation(TObject * Sender,
     TFileOperation Operation, bool NoConfirmation, void * Param);
   void __fastcall DDDownload(
-    TStrings * FilesToCopy, const UnicodeString & TargetDir, TCopyParamType * CopyParam, int Params);
+    TStrings * FilesToCopy, const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params);
   bool __fastcall EnsureCommandSessionFallback(TFSCapability Capability);
   bool __fastcall CommandSessionFallback();
   void __fastcall FileTerminalRemoved(const UnicodeString FileName,
@@ -607,11 +609,12 @@ protected:
   void __fastcall CopyPopup(TControl * DestControl, TControl * SourceControl);
   void __fastcall CreateRemoteDirectory(const UnicodeString & Path, TRemoteProperties & Properties);
   void __fastcall DoFullSynchronize(
-    void * Token, TProcessedItem OnProcessedItem, TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems);
+    void * Token, TProcessedSynchronizationChecklistItem OnProcessedItem,
+    TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems);
   void __fastcall DoSynchronizeChecklistCalculateSize(
     TSynchronizeChecklist * Checklist, const TSynchronizeChecklist::TItemList & Items, void * Token);
   void __fastcall FullSynchronize(
-    TSynchronizeParams & Params, TProcessedItem OnProcessedItem,
+    TSynchronizeParams & Params, TProcessedSynchronizationChecklistItem OnProcessedItem,
     TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems);
   void __fastcall CreateOpenDirMenuList(TTBCustomItem * Menu, TOperationSide Side, TBookmarkList * BookmarkList);
   void __fastcall CreateOpenDirMenu(TTBCustomItem * Menu, TOperationSide Side);
@@ -692,6 +695,7 @@ public:
   void __fastcall OperationFinished(TFileOperation Operation, TOperationSide Side,
     bool Temp, const UnicodeString & FileName, bool Success, TOnceDoneOperation & OnceDoneOperation);
   void __fastcall OperationProgress(TFileOperationProgressType & ProgressData);
+  UnicodeString __fastcall GetProgressTitle(const TFileOperationProgressType & ProgressData);
   void __fastcall ShowExtendedException(TTerminal * Terminal, Exception * E);
   void __fastcall InactiveTerminalException(TTerminal * Terminal, Exception * E);
   void __fastcall TerminalReady();

+ 24 - 7
source/forms/Progress.cpp

@@ -34,7 +34,8 @@ bool __fastcall TProgressForm::IsIndeterminateOperation(TFileOperation Operation
   return (Operation == foCalculateSize);
 }
 //---------------------------------------------------------------------
-UnicodeString __fastcall TProgressForm::ProgressStr(TFileOperationProgressType * ProgressData)
+UnicodeString __fastcall TProgressForm::ProgressStr(
+  const TSynchronizeChecklist * SynchronizeChecklist, const TFileOperationProgressType * ProgressData)
 {
   static const int Captions[] = { 0, 0, PROGRESS_DELETE,
     PROGRESS_SETPROPERTIES, 0, PROGRESS_CUSTOM_COMAND, PROGRESS_CALCULATE_SIZE,
@@ -56,13 +57,19 @@ UnicodeString __fastcall TProgressForm::ProgressStr(TFileOperationProgressType *
   {
     Result = FORMAT(L"%d%% %s", (ProgressData->OverallProgress(), Result));
   }
+  if (SynchronizeChecklist != NULL)
+  {
+    Result = FORMAT(L"%s - %s", (LoadStr(SYNCHRONIZE_PROGRESS_SYNCHRONIZE2), Result));
+  }
   return Result;
 }
 //---------------------------------------------------------------------
-__fastcall TProgressForm::TProgressForm(TComponent * AOwner, bool AllowMoveToQueue, bool AllowSkip)
+__fastcall TProgressForm::TProgressForm(
+  TComponent * AOwner, bool AllowMoveToQueue, bool AllowSkip, const TSynchronizeChecklist * SynchronizeChecklist)
     : FData(), TForm(AOwner)
 {
   FLastOperation = foNone;
+  FLastSide = (TOperationSide)-1;
   FLastTotalSizeSet = false;
   FDataGot = false;
   FDataReceived = false;
@@ -70,13 +77,16 @@ __fastcall TProgressForm::TProgressForm(TComponent * AOwner, bool AllowMoveToQue
   FMoveToQueue = false;
   FMinimizedByMe = false;
   FUpdateCounter = 0;
-  FDeleteToRecycleBin = false;
+  FDeleteLocalToRecycleBin = false;
+  FDeleteRemoteToRecycleBin = false;
   FReadOnly = false;
   FShowAsModalStorage = NULL;
   FStarted = Now();
   FModalBeginHooked = false;
   FModalLevel = -1;
   FPendingSkip = false;
+  FSynchronizeChecklist = SynchronizeChecklist;
+  FAllowSkip = AllowSkip;
   UseSystemSettings(this);
 
   FOnceDoneItems.Add(odoIdle, IdleOnceDoneItem);
@@ -89,7 +99,6 @@ __fastcall TProgressForm::TProgressForm(TComponent * AOwner, bool AllowMoveToQue
 
   SetGlobalMinimizeHandler(this, GlobalMinimize);
   MoveToQueueItem->Visible = AllowMoveToQueue;
-  SkipItem->Visible = AllowSkip;
 }
 //---------------------------------------------------------------------------
 __fastcall TProgressForm::~TProgressForm()
@@ -118,6 +127,7 @@ void __fastcall TProgressForm::UpdateControls()
     ((FData.Operation == foCopy) || (FData.Operation == foMove));
 
   CancelItem->Enabled = !FReadOnly && (FCancel < csCancel);
+  SkipItem->Visible = TransferOperation && FAllowSkip;
   SkipItem->Enabled = !FReadOnly && (FCancel < csCancelFile) && !FPendingSkip;
   MoveToQueueItem->Enabled = !FMoveToQueue && (FCancel == csContinue) && !FPendingSkip;
   CycleOnceDoneItem->Visible =
@@ -128,7 +138,8 @@ void __fastcall TProgressForm::UpdateControls()
   CycleOnceDoneItem->ImageIndex = CurrentOnceDoneItem()->ImageIndex;
   SpeedComboBoxItem->Visible = TransferOperation;
 
-  if (FData.Operation != FLastOperation)
+  if ((FData.Operation != FLastOperation) ||
+      (FData.Side != FLastSide))
   {
     UnicodeString Animation;
     UnicodeString CancelCaption = Vcl_Consts_SMsgDlgCancel;
@@ -172,7 +183,7 @@ void __fastcall TProgressForm::UpdateControls()
         break;
 
       case foDelete:
-        Animation = DeleteToRecycleBin ? L"Recycle" : L"Delete";
+        Animation = ((FData.Side == osRemote) ? DeleteRemoteToRecycleBin : DeleteLocalToRecycleBin) ? L"Recycle" : L"Delete";
         break;
 
       case foCalculateSize:
@@ -201,6 +212,11 @@ void __fastcall TProgressForm::UpdateControls()
 
     OperationProgress->Style = IsIndeterminateOperation(FData.Operation) ? pbstMarquee : pbstNormal;
 
+    if (FSynchronizeChecklist != NULL)
+    {
+      Animation = L"SynchronizeDirectories";
+    }
+
     FFrameAnimation.Init(AnimationPaintBox, Animation);
     FFrameAnimation.Start();
 
@@ -223,6 +239,7 @@ void __fastcall TProgressForm::UpdateControls()
     MoveToQueueItem->ImageIndex = MoveToQueueImageIndex;
 
     FLastOperation = FData.Operation;
+    FLastSide = FData.Side;
     FLastTotalSizeSet = !FData.TotalSizeSet;
   }
 
@@ -263,7 +280,7 @@ void __fastcall TProgressForm::UpdateControls()
   int OverallProgress = FData.OverallProgress();
   OperationProgress->Position = OverallProgress;
   OperationProgress->Hint = IsIndeterminateOperation(FData.Operation) ? UnicodeString() : FORMAT(L"%d%%", (OverallProgress));
-  Caption = FormatFormCaption(this, ProgressStr(&FData));
+  Caption = FormatFormCaption(this, ProgressStr(FSynchronizeChecklist, &FData));
 
   if (TransferOperation)
   {

+ 12 - 4
source/forms/Progress.h

@@ -92,13 +92,15 @@ private:
   bool FDataGot;
   bool FDataReceived;
   TFileOperation FLastOperation;
+  TOperationSide FLastSide;
   bool FLastTotalSizeSet;
   bool FMinimizedByMe;
   int FUpdateCounter;
   bool FAsciiTransferChanged;
   bool FResumeStatusChanged;
   void * FShowAsModalStorage;
-  bool FDeleteToRecycleBin;
+  bool FDeleteLocalToRecycleBin;
+  bool FDeleteRemoteToRecycleBin;
   bool FReadOnly;
   unsigned long FCPSLimit;
   TDateTime FStarted;
@@ -108,6 +110,8 @@ private:
   TFrameAnimation FFrameAnimation;
   typedef BiDiMap<TOnceDoneOperation, TTBCustomItem *> TOnceDoneItems;
   TOnceDoneItems FOnceDoneItems;
+  bool FAllowSkip;
+  const TSynchronizeChecklist * FSynchronizeChecklist;
 
   void __fastcall SetOnceDoneOperation(TOnceDoneOperation value);
   TTBCustomItem * __fastcall CurrentOnceDoneItem();
@@ -132,9 +136,11 @@ protected:
   static bool __fastcall IsIndeterminateOperation(TFileOperation Operation);
 
 public:
-  static UnicodeString __fastcall ProgressStr(TFileOperationProgressType * ProgressData);
+  static UnicodeString __fastcall ProgressStr(
+    const TSynchronizeChecklist * SynchronizeChecklist, const TFileOperationProgressType * ProgressData);
 
-  virtual __fastcall TProgressForm(TComponent * AOwner, bool AllowMoveToQueue, bool AllowSkip);
+  virtual __fastcall TProgressForm(
+    TComponent * AOwner, bool AllowMoveToQueue, bool AllowSkip, const TSynchronizeChecklist * SynchronizeChecklist);
   virtual __fastcall ~TProgressForm();
   void __fastcall SetProgressData(TFileOperationProgressType & AData);
   void __fastcall ClearCancel();
@@ -142,8 +148,10 @@ public:
   __property bool MoveToQueue = { read = FMoveToQueue };
   __property TOnceDoneOperation OnceDoneOperation = { read=GetOnceDoneOperation, write=SetOnceDoneOperation };
   __property bool AllowMinimize = { read=GetAllowMinimize, write=SetAllowMinimize };
-  __property bool DeleteToRecycleBin = { read=FDeleteToRecycleBin, write=FDeleteToRecycleBin };
+  __property bool DeleteLocalToRecycleBin = { read=FDeleteLocalToRecycleBin, write=FDeleteLocalToRecycleBin };
+  __property bool DeleteRemoteToRecycleBin = { read=FDeleteRemoteToRecycleBin, write=FDeleteRemoteToRecycleBin };
   __property bool ReadOnly = { read=FReadOnly, write=SetReadOnly };
+  __property const TSynchronizeChecklist * SynchronizeChecklist = { read = FSynchronizeChecklist };
 };
 //----------------------------------------------------------------------------
 #endif

+ 5 - 15
source/forms/SynchronizeChecklist.cpp

@@ -1055,16 +1055,12 @@ void __fastcall TSynchronizeChecklistDialog::CMDpiChanged(TMessage & Message)
   UpdateImages();
 }
 //---------------------------------------------------------------------------
-void __fastcall TSynchronizeChecklistDialog::ProcessedItem(const void * Token)
+void __fastcall TSynchronizeChecklistDialog::ProcessedItem(const TSynchronizeChecklist::TItem * ChecklistItem)
 {
-  TTokens::const_iterator I = FTokens.find(Token);
-  if (DebugAlwaysTrue(I != FTokens.end()))
-  {
-    TListItem * Item = I->second;
-    DebugAssert(Item->Checked);
-    Item->Checked = false;
-    Item->MakeVisible(false);
-  }
+  TListItem * Item = FChecklistToListViewMap[ChecklistItem];
+  DebugAssert(Item->Checked);
+  Item->Checked = false;
+  Item->MakeVisible(false);
 }
 //---------------------------------------------------------------------------
 void __fastcall TSynchronizeChecklistDialog::UpdatedSynchronizationChecklistItems(
@@ -1090,17 +1086,11 @@ void __fastcall TSynchronizeChecklistDialog::UpdatedSynchronizationChecklistItem
 void __fastcall TSynchronizeChecklistDialog::OkButtonClick(TObject * /*Sender*/)
 {
   ListView->SelectAll(smNone);
-  FTokens.clear();
   for (int Index = 0; Index < ListView->Items->Count; Index++)
   {
     TListItem * Item = ListView->Items->Item[Index];
     const TSynchronizeChecklist::TItem * ChecklistItem = GetChecklistItem(Item);
     FChecklist->Update(ChecklistItem, Item->Checked, GetChecklistItemAction(ChecklistItem));
-    FTokens.insert(std::make_pair(ChecklistItem, Item));
-    if (ChecklistItem->RemoteFile != NULL)
-    {
-      FTokens.insert(std::make_pair(ChecklistItem->RemoteFile, Item));
-    }
   }
 
   TAutoFlag Flag(FSynchronizing);

+ 1 - 3
source/forms/SynchronizeChecklist.h

@@ -122,8 +122,6 @@ protected:
   TActions FActions;
   TFullSynchronizeEvent FOnSynchronize;
   void * FToken;
-  typedef std::map<const void *, TListItem *> TTokens;
-  TTokens FTokens;
   bool FSynchronizing;
   std::unique_ptr<Exception> FException;
   std::map<const TSynchronizeChecklist::TItem *, TListItem *> FChecklistToListViewMap;
@@ -149,7 +147,7 @@ protected:
   void __fastcall UpdateImages();
   void __fastcall CMDpiChanged(TMessage & Message);
   bool __fastcall GetWindowParams(UnicodeString & WindowParams);
-  void __fastcall ProcessedItem(const void * Token);
+  void __fastcall ProcessedItem(const TSynchronizeChecklist::TItem * ChecklistItem);
   void __fastcall UpdatedSynchronizationChecklistItems(const TSynchronizeChecklist::TItemList & Items);
   void __fastcall CountItemSize(const TSynchronizeChecklist::TItem * ChecklistItem, int Factor);
   void __fastcall CountItem(const TSynchronizeChecklist::TItem * ChecklistItem, int Factor);

+ 1 - 1
source/windows/TerminalManager.cpp

@@ -1193,7 +1193,7 @@ void __fastcall TTerminalManager::OperationProgress(
 {
   if (ProgressData.InProgress)
   {
-    FProgressTitle = TProgressForm::ProgressStr(&ProgressData);
+    FProgressTitle = ScpExplorer->GetProgressTitle(ProgressData);
   }
   else
   {

+ 2 - 1
source/windows/WinInterface.h

@@ -352,7 +352,8 @@ class TSynchronizeChecklist;
 typedef void __fastcall (__closure *TCustomCommandMenuEvent)
   (TAction * Action, TStrings * LocalFileList, TStrings * RemoteFileList);
 typedef void __fastcall (__closure *TFullSynchronizeEvent)(
-  void * Token, TProcessedItem OnProcessedItem, TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems);
+  void * Token, TProcessedSynchronizationChecklistItem OnProcessedItem,
+  TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems);
 typedef void __fastcall (__closure *TSynchronizeChecklistCalculateSize)
   (TSynchronizeChecklist * Checklist, const TSynchronizeChecklist::TItemList & Items, void * Token);
 bool __fastcall DoSynchronizeChecklistDialog(TSynchronizeChecklist * Checklist,