1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

File/directory rename can be resolved on Synchronization checklist window

Source commit: a2e0c76a2586ab0584f68dbc81081d6b0912058c
This commit is contained in:
Martin Prikryl
2018-10-03 12:15:07 +00:00
parent 72b9a479a1
commit 2389dd4a1c
8 changed files with 227 additions and 15 deletions

View File

@@ -2832,6 +2832,14 @@ void __fastcall TSynchronizeChecklist::Update(const TItem * Item, bool Check, TA
MutableItem->Action = Action;
}
//---------------------------------------------------------------------------
void TSynchronizeChecklist::Delete(const TItem * Item)
{
// See comment in Update()
TItem * MutableItem = const_cast<TItem *>(Item);
FList->Extract(MutableItem);
delete Item;
}
//---------------------------------------------------------------------------
void __fastcall TSynchronizeChecklist::UpdateDirectorySize(const TItem * Item, __int64 Size)
{
// See comment in Update

View File

@@ -493,6 +493,7 @@ public:
void __fastcall Update(const TItem * Item, bool Check, TAction Action);
void __fastcall UpdateDirectorySize(const TItem * Item, __int64 Size);
void Delete(const TItem * Item);
static TAction __fastcall Reverse(TAction Action);
static bool __fastcall IsItemSizeIrrelevant(TAction Action);

View File

@@ -125,6 +125,25 @@ private:
TCustomScpExplorerForm * FForm;
};
//---------------------------------------------------------------------------
class TAutoBatch
{
public:
TAutoBatch(TCustomScpExplorerForm * Form) :
FForm(Form)
{
FForm->BatchStart(FBatchStorage);
}
~TAutoBatch()
{
FForm->BatchEnd(FBatchStorage);
}
private:
TCustomScpExplorerForm * FForm;
void * FBatchStorage;
};
//---------------------------------------------------------------------------
struct TTransferOperationParam
{
TTransferOperationParam();
@@ -5532,6 +5551,48 @@ void __fastcall TCustomScpExplorerForm::DoSynchronizeChecklistCalculateSize(
}
}
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::DoSynchronizeMove(
TOperationSide Side, const UnicodeString & FileName, const UnicodeString & NewFileName, TRemoteFile * RemoteFile)
{
TAutoBatch AutoBatch(this);
TAutoFlag AutoOperationFlag(FAutoOperation);
if (Side == osRemote)
{
std::unique_ptr<TStrings> FileList(new TStringList());
FileList->AddObject(FileName, RemoteFile);
UnicodeString Target = UnixExtractFileDir(NewFileName);
UnicodeString FileMask = DelimitFileNameMask(UnixExtractFileName(NewFileName));
RemoteDirView->SaveSelection();
RemoteDirView->SaveSelectedNames();
try
{
Terminal->MoveFiles(FileList.get(), Target, FileMask);
}
catch(...)
{
RemoteDirView->DiscardSavedSelection();
throw;
}
RemoteDirView->RestoreSelection();
}
else if (DebugAlwaysTrue(Side == osLocal))
{
if (!MoveFile(FileName.c_str(), NewFileName.c_str()))
{
throw EOSExtException(FMTLOAD(RENAME_FILE_ERROR, (FileName, NewFileName)));
}
UnicodeString Directory = ExtractFileDir(FileName);
ReloadLocalDirectory(Directory);
UnicodeString NewDirectory = ExtractFileDir(NewFileName);
if (!SamePaths(Directory, NewDirectory))
{
ReloadLocalDirectory(NewDirectory);
}
}
}
//---------------------------------------------------------------------------
int __fastcall TCustomScpExplorerForm::DoFullSynchronizeDirectories(
UnicodeString & LocalDirectory, UnicodeString & RemoteDirectory,
TSynchronizeMode & Mode, bool & SaveMode, bool UseDefaults)
@@ -5607,7 +5668,7 @@ int __fastcall TCustomScpExplorerForm::DoFullSynchronizeDirectories(
{
if (!DoSynchronizeChecklistDialog(
Checklist, Mode, Params, LocalDirectory, RemoteDirectory, CustomCommandMenu, DoFullSynchronize,
DoSynchronizeChecklistCalculateSize, &SynchronizeParams))
DoSynchronizeChecklistCalculateSize, DoSynchronizeMove, &SynchronizeParams))
{
Result = -1;
}

View File

@@ -62,6 +62,7 @@ enum TCustomCommandListType { ccltAll, ccltBoth, ccltNonFile, ccltFile };
//---------------------------------------------------------------------------
class TCustomScpExplorerForm : public TForm
{
friend class TAutoBatch;
__published:
TPanel *RemotePanel;
TTBXStatusBar *RemoteStatusBar;
@@ -621,6 +622,8 @@ protected:
TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems);
void __fastcall DoSynchronizeChecklistCalculateSize(
TSynchronizeChecklist * Checklist, const TSynchronizeChecklist::TItemList & Items, void * Token);
void __fastcall DoSynchronizeMove(
TOperationSide Side, const UnicodeString & FileName, const UnicodeString & NewFileName, TRemoteFile * RemoteFile);
void __fastcall FullSynchronize(
TSynchronizeParams & Params, TProcessedSynchronizationChecklistItem OnProcessedItem,
TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems);

View File

@@ -18,6 +18,7 @@
#include <WinConfiguration.h>
#include <GUITools.h>
#include <TerminalManager.h>
#include <System.IOUtils.hpp>
//---------------------------------------------------------------------
#pragma link "IEListView"
#pragma link "NortonLikeListView"
@@ -32,12 +33,13 @@ bool __fastcall DoSynchronizeChecklistDialog(TSynchronizeChecklist * Checklist,
TSynchronizeMode Mode, int Params,
const UnicodeString LocalDirectory, const UnicodeString RemoteDirectory,
TCustomCommandMenuEvent OnCustomCommandMenu, TFullSynchronizeEvent OnSynchronize,
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, void * Token)
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, TSynchronizeMoveEvent OnSynchronizeMove,
void * Token)
{
std::unique_ptr<TSynchronizeChecklistDialog> Dialog(
new TSynchronizeChecklistDialog(
Application, Mode, Params, LocalDirectory, RemoteDirectory, OnCustomCommandMenu, OnSynchronize,
OnSynchronizeChecklistCalculateSize, Token));
OnSynchronizeChecklistCalculateSize, OnSynchronizeMove, Token));
return Dialog->Execute(Checklist);
}
//---------------------------------------------------------------------
@@ -45,7 +47,7 @@ __fastcall TSynchronizeChecklistDialog::TSynchronizeChecklistDialog(
TComponent * AOwner, TSynchronizeMode Mode, int Params,
const UnicodeString & LocalDirectory, const UnicodeString & RemoteDirectory,
TCustomCommandMenuEvent OnCustomCommandMenu, TFullSynchronizeEvent OnSynchronize,
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, void * Token)
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, TSynchronizeMoveEvent OnSynchronizeMove, void * Token)
: TForm(AOwner)
{
FFormRestored = false;
@@ -55,6 +57,7 @@ __fastcall TSynchronizeChecklistDialog::TSynchronizeChecklistDialog(
FRemoteDirectory = UnixExcludeTrailingBackslash(RemoteDirectory);
FOnCustomCommandMenu = OnCustomCommandMenu;
FOnSynchronizeChecklistCalculateSize = OnSynchronizeChecklistCalculateSize;
FOnSynchronizeMove = OnSynchronizeMove;
DebugAssert(OnSynchronize != NULL);
FOnSynchronize = OnSynchronize;
FToken = Token;
@@ -181,6 +184,7 @@ void __fastcall TSynchronizeChecklistDialog::UpdateControls()
UncheckAllAction->Enabled = (FChecked[0] > 0) && !FSynchronizing;
CustomCommandsAction->Enabled = AnyBoth && !AnyNonBoth && DebugAlwaysTrue(!FSynchronizing);
ReverseAction->Enabled = (ListView->SelCount > 0) && DebugAlwaysTrue(!FSynchronizing);
MoveAction->Enabled = (GetMoveItems() != TSynchronizeMoveItems());
CalculateSizeAction->Enabled = (ListView->SelCount > 0) && AnyDirectory && DebugAlwaysTrue(!FSynchronizing);
SelectAllAction->Enabled = (ListView->SelCount < ListView->Items->Count) && !FSynchronizing;
@@ -351,12 +355,18 @@ void __fastcall TSynchronizeChecklistDialog::CountItem(const TSynchronizeCheckli
CountItemSize(ChecklistItem, Factor);
}
//---------------------------------------------------------------------------
void __fastcall TSynchronizeChecklistDialog::CountItemTotal(const TSynchronizeChecklist::TItem * ChecklistItem, int Factor)
{
FTotals[0] += Factor;
int ActionIndex = int(GetChecklistItemAction(ChecklistItem));
FTotals[ActionIndex] += Factor;
}
//---------------------------------------------------------------------------
void __fastcall TSynchronizeChecklistDialog::LoadList()
{
memset(&FTotals, 0, sizeof(FTotals));
memset(&FChecked, 0, sizeof(FChecked));
memset(&FCheckedSize, 0, sizeof(FCheckedSize));
FTotals[0] = FChecklist->Count;
ListView->Items->BeginUpdate();
try
@@ -382,8 +392,7 @@ void __fastcall TSynchronizeChecklistDialog::LoadList()
FChangingItemIgnore = false;
}
int ActionIndex = int(GetChecklistItemAction(ChecklistItem));
FTotals[ActionIndex]++;
CountItemTotal(ChecklistItem, 1);
if (ChecklistItem->Checked)
{
CountItem(ChecklistItem, 1);
@@ -986,7 +995,7 @@ void __fastcall TSynchronizeChecklistDialog::ReverseActionExecute(TObject * /*Se
{
int ActionIndex = int(Action);
FTotals[ActionIndex]--;
CountItemTotal(ChecklistItem, -1);
if (Item->Checked)
{
CountItem(ChecklistItem, -1);
@@ -995,7 +1004,7 @@ void __fastcall TSynchronizeChecklistDialog::ReverseActionExecute(TObject * /*Se
Action = NewAction;
ActionIndex = int(Action);
FTotals[ActionIndex]++;
CountItemTotal(ChecklistItem, 1);
if (Item->Checked)
{
// item size may differ with action (0 for delete, but non-0 for new file transfer)
@@ -1159,3 +1168,103 @@ void __fastcall TSynchronizeChecklistDialog::CalculateSizeAllActionExecute(TObje
CalculateSizeActionExecute(Sender);
}
//---------------------------------------------------------------------------
TSynchronizeChecklistDialog::TSynchronizeMoveItems __fastcall TSynchronizeChecklistDialog::GetMoveItems()
{
if ((ListView->SelCount != 2) || DebugAlwaysFalse(FSynchronizing))
{
return TSynchronizeMoveItems();
}
else
{
TListItem * Item1 = ListView->Selected;
const TSynchronizeChecklist::TItem * ChecklistItem1 = GetChecklistItem(DebugNotNull(ListView->Selected));
TListItem * Item2 = ListView->GetNextItem(ListView->Selected, sdAll, TItemStates() << isSelected);
const TSynchronizeChecklist::TItem * ChecklistItem2 = GetChecklistItem(DebugNotNull(Item2));
if (ChecklistItem1->IsDirectory != ChecklistItem2->IsDirectory)
{
return TSynchronizeMoveItems();
}
else
{
TSynchronizeChecklist::TAction Action1 = GetChecklistItemAction(ChecklistItem1);
TSynchronizeChecklist::TAction Action2 = GetChecklistItemAction(ChecklistItem2);
if ((Action1 == TSynchronizeChecklist::saUploadNew) && (Action2 == TSynchronizeChecklist::saDeleteRemote))
{
return TSynchronizeMoveItems(ChecklistItem1, ChecklistItem2);
}
else if ((Action1 == TSynchronizeChecklist::saDownloadNew) && (Action2 == TSynchronizeChecklist::saDeleteLocal))
{
return TSynchronizeMoveItems(ChecklistItem1, ChecklistItem2);
}
else if ((Action1 == TSynchronizeChecklist::saDeleteRemote) && (Action2 == TSynchronizeChecklist::saUploadNew))
{
return TSynchronizeMoveItems(ChecklistItem2, ChecklistItem1);
}
else if ((Action1 == TSynchronizeChecklist::saDeleteLocal) && (Action2 == TSynchronizeChecklist::saDownloadNew))
{
return TSynchronizeMoveItems(ChecklistItem2, ChecklistItem1);
}
else
{
return TSynchronizeMoveItems();
}
}
}
}
//---------------------------------------------------------------------------
void __fastcall TSynchronizeChecklistDialog::DeleteItem(TListItem * Item)
{
const TSynchronizeChecklist::TItem * ChecklistItem = GetChecklistItem(Item);
CountItemTotal(ChecklistItem, -1);
if (Item->Checked)
{
CountItem(ChecklistItem, -1);
}
FActions.erase(ChecklistItem);
FChecklistToListViewMap.erase(ChecklistItem);
FChecklist->Delete(ChecklistItem);
ListView->Items->Delete(Item->Index);
}
//---------------------------------------------------------------------------
void __fastcall TSynchronizeChecklistDialog::MoveActionExecute(TObject *)
{
TSynchronizeMoveItems MoveItems = GetMoveItems();
TSynchronizeChecklist::TAction Action2 = GetChecklistItemAction(MoveItems.second);
TOperationSide Side;
UnicodeString FileName;
UnicodeString NewFileName;
TRemoteFile * RemoteFile;
if (Action2 == TSynchronizeChecklist::saDeleteRemote)
{
Side = osRemote;
FileName = UnixCombinePaths(MoveItems.second->Remote.Directory, MoveItems.second->Remote.FileName);
NewFileName = UnixCombinePaths(MoveItems.first->Remote.Directory, MoveItems.first->Local.FileName);
RemoteFile = MoveItems.second->RemoteFile;
}
else if (Action2 == TSynchronizeChecklist::saDeleteLocal)
{
Side = osLocal;
FileName = TPath::Combine(MoveItems.second->Local.Directory, MoveItems.second->Local.FileName);
NewFileName = TPath::Combine(MoveItems.first->Local.Directory, MoveItems.first->Remote.FileName);
RemoteFile = NULL;
}
else
{
DebugFail();
Abort();
}
FOnSynchronizeMove(Side, FileName, NewFileName, RemoteFile);
TListItem * Item1 = DebugNotNull(ListView->FindData(0, const_cast<TSynchronizeChecklist::TItem *>(MoveItems.first), true, false));
TListItem * Item2 = DebugNotNull(ListView->FindData(0, const_cast<TSynchronizeChecklist::TItem *>(MoveItems.second), true, false));
DeleteItem(Item1);
DeleteItem(Item2);
}
//---------------------------------------------------------------------------

View File

@@ -1443,13 +1443,13 @@ object SynchronizeChecklistDialog: TSynchronizeChecklistDialog
end
object CustomCommandsButton2: TButton
Left = 8
Top = 322
Top = 353
Width = 108
Height = 25
Action = CustomCommandsAction
Anchors = [akLeft, akTop, akRight]
Caption = 'Co&mmands'
TabOrder = 8
TabOrder = 9
end
object ReverseButton: TButton
Left = 8
@@ -1462,12 +1462,21 @@ object SynchronizeChecklistDialog: TSynchronizeChecklistDialog
end
object CalculateSizeButton: TButton
Left = 8
Top = 291
Top = 322
Width = 108
Height = 25
Action = CalculateSizeAction
Anchors = [akLeft, akTop, akRight]
TabOrder = 9
TabOrder = 10
end
object MoveButton: TButton
Left = 8
Top = 291
Width = 108
Height = 25
Action = MoveAction
Anchors = [akLeft, akTop, akRight]
TabOrder = 8
end
end
object ListView: TIEListView
@@ -2334,6 +2343,9 @@ object SynchronizeChecklistDialog: TSynchronizeChecklistDialog
object ReverseItem: TMenuItem
Action = ReverseAction
end
object MoveItem: TMenuItem
Action = MoveAction
end
object Calculate1: TMenuItem
Action = CalculateSizeAction
end
@@ -2396,6 +2408,11 @@ object SynchronizeChecklistDialog: TSynchronizeChecklistDialog
ShortCut = 49217
OnExecute = CalculateSizeAllActionExecute
end
object MoveAction: TAction
Caption = '&Move'
ShortCut = 117
OnExecute = MoveActionExecute
end
end
object ActionImages120: TPngImageList
Height = 20

View File

@@ -56,6 +56,9 @@ __published:
TMenuItem *Calculate1;
TButton *CalculateSizeButton;
TAction *CalculateSizeAllAction;
TAction *MoveAction;
TButton *MoveButton;
TMenuItem *MoveItem;
void __fastcall HelpButtonClick(TObject * Sender);
void __fastcall FormShow(TObject * Sender);
void __fastcall StatusBarDrawPanel(TStatusBar *StatusBar,
@@ -91,13 +94,15 @@ __published:
void __fastcall OkButtonClick(TObject *Sender);
void __fastcall CalculateSizeActionExecute(TObject *Sender);
void __fastcall CalculateSizeAllActionExecute(TObject *Sender);
void __fastcall MoveActionExecute(TObject *Sender);
public:
__fastcall TSynchronizeChecklistDialog(
TComponent * AOwner, TSynchronizeMode Mode, int Params,
const UnicodeString & LocalDirectory, const UnicodeString & RemoteDirectory,
TCustomCommandMenuEvent OnCustomCommandMenu, TFullSynchronizeEvent OnSynchronize,
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, void * Token);
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, TSynchronizeMoveEvent OnSynchronizeMove,
void * Token);
virtual __fastcall ~TSynchronizeChecklistDialog();
bool __fastcall Execute(TSynchronizeChecklist * Checklist);
@@ -120,6 +125,7 @@ protected:
UnicodeString FGeneralHint;
TCustomCommandMenuEvent FOnCustomCommandMenu;
TSynchronizeChecklistCalculateSize FOnSynchronizeChecklistCalculateSize;
TSynchronizeMoveEvent FOnSynchronizeMove;
typedef std::map<const TSynchronizeChecklist::TItem *, TSynchronizeChecklist::TAction> TActions;
TActions FActions;
TFullSynchronizeEvent FOnSynchronize;
@@ -154,6 +160,10 @@ protected:
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);
void __fastcall CountItemTotal(const TSynchronizeChecklist::TItem * ChecklistItem, int Factor);
typedef std::pair<const TSynchronizeChecklist::TItem *, const TSynchronizeChecklist::TItem *> TSynchronizeMoveItems;
TSynchronizeMoveItems __fastcall GetMoveItems();
void __fastcall DeleteItem(TListItem * Item);
static int __fastcall CompareNumber(__int64 Value1, __int64 Value2);
};
//----------------------------------------------------------------------------

View File

@@ -357,11 +357,14 @@ typedef void __fastcall (__closure *TFullSynchronizeEvent)(
TUpdatedSynchronizationChecklistItems OnUpdatedSynchronizationChecklistItems);
typedef void __fastcall (__closure *TSynchronizeChecklistCalculateSize)
(TSynchronizeChecklist * Checklist, const TSynchronizeChecklist::TItemList & Items, void * Token);
typedef void __fastcall (__closure *TSynchronizeMoveEvent)(
TOperationSide Side, const UnicodeString & FileName, const UnicodeString & NewFileName, TRemoteFile * RemoteFile);
bool __fastcall DoSynchronizeChecklistDialog(TSynchronizeChecklist * Checklist,
TSynchronizeMode Mode, int Params,
const UnicodeString LocalDirectory, const UnicodeString RemoteDirectory,
TCustomCommandMenuEvent OnCustomCommandMenu, TFullSynchronizeEvent OnSynchronize,
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, void * Token);
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, TSynchronizeMoveEvent OnSynchronizeMove,
void * Token);
// forms\Editor.cpp
typedef void __fastcall (__closure *TFileClosedEvent)