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

Size of directories can be calculated on Synchronization checklist window

Source commit: 0586532ab65d5a134b9295f8e8e6d8121e9d48f0
This commit is contained in:
Martin Prikryl
2018-07-31 14:40:52 +00:00
parent 9411a657e2
commit 14a6e25248
8 changed files with 250 additions and 20 deletions

View File

@@ -140,7 +140,7 @@ TOverwriteFileParams::TOverwriteFileParams()
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
TSynchronizeChecklist::TItem::TItem() :
Action(saNone), IsDirectory(false), RemoteFile(NULL), Checked(true), ImageIndex(-1)
Action(saNone), IsDirectory(false), RemoteFile(NULL), Checked(true), ImageIndex(-1), FDirectoryHasSize(false)
{
Local.ModificationFmt = mfFull;
Local.Modification = 0;
@@ -237,6 +237,31 @@ void __fastcall TSynchronizeChecklist::Update(const TItem * Item, bool Check, TA
MutableItem->Action = Action;
}
//---------------------------------------------------------------------------
void __fastcall TSynchronizeChecklist::UpdateDirectorySize(const TItem * Item, __int64 Size)
{
// See comment in Update
TItem * MutableItem = const_cast<TItem *>(Item);
DebugAssert(FList->IndexOf(MutableItem) >= 0);
if (DebugAlwaysTrue(Item->IsDirectory))
{
MutableItem->FDirectoryHasSize = true;
if (Item->IsRemoteOnly())
{
MutableItem->Remote.Size = Size;
}
else if (Item->IsLocalOnly())
{
MutableItem->Local.Size = Size;
}
else
{
// "update" actions are not relevant for directories
DebugFail();
}
}
}
//---------------------------------------------------------------------------
TSynchronizeChecklist::TAction __fastcall TSynchronizeChecklist::Reverse(TSynchronizeChecklist::TAction Action)
{
switch (Action)
@@ -4293,6 +4318,7 @@ bool __fastcall TTerminal::LoadFilesProperties(TStrings * FileList)
void __fastcall TTerminal::DoCalculateFileSize(UnicodeString FileName,
const TRemoteFile * File, void * Param)
{
// This is called for top-level entries only
TCalculateSizeParams * AParams = static_cast<TCalculateSizeParams*>(Param);
if (AParams->Stats->FoundFiles != NULL)
@@ -4307,7 +4333,14 @@ void __fastcall TTerminal::DoCalculateFileSize(UnicodeString FileName,
}
}
__int64 PrevSize = AParams->Size;
CalculateFileSize(FileName, File, Param);
if (AParams->Stats->CalculatedSizes != NULL)
{
__int64 Size = AParams->Size - PrevSize;
AParams->Stats->CalculatedSizes->push_back(Size);
}
}
//---------------------------------------------------------------------------
void __fastcall TTerminal::CalculateFileSize(UnicodeString FileName,
@@ -5332,7 +5365,8 @@ void __fastcall TTerminal::CalculateLocalFileSize(
}
//---------------------------------------------------------------------------
bool __fastcall TTerminal::CalculateLocalFilesSize(TStrings * FileList,
__int64 & Size, const TCopyParamType * CopyParam, bool AllowDirs, TStrings * Files)
__int64 & Size, const TCopyParamType * CopyParam, bool AllowDirs, TStrings * Files,
TCalculatedSizes * CalculatedSizes)
{
bool Result = false;
TFileOperationProgressType OperationProgress(&DoProgress, &DoFinished);
@@ -5374,8 +5408,16 @@ bool __fastcall TTerminal::CalculateLocalFilesSize(TStrings * FileList,
}
}
__int64 PrevSize = Params.Size;
CalculateLocalFileSize(FileName, Rec, &Params);
if (CalculatedSizes != NULL)
{
__int64 Size = Params.Size - PrevSize;
CalculatedSizes->push_back(Size);
}
OperationFinish(&OperationProgress, FileList->Objects[Index], FileName, true, OnceDoneOperation);
}
}
@@ -6643,7 +6685,7 @@ bool __fastcall TTerminal::CopyToRemote(TStrings * FilesToCopy,
Files->OwnsObjects = true;
}
bool CalculatedSize =
CalculateLocalFilesSize(FilesToCopy, Size, CopyParam, CopyParam->CalculateSize, Files.get());
CalculateLocalFilesSize(FilesToCopy, Size, CopyParam, CopyParam->CalculateSize, Files.get(), NULL);
FLastProgressLogged = GetTickCount();
TFileOperationProgressType OperationProgress(&DoProgress, &DoFinished);

View File

@@ -31,6 +31,7 @@ class TCallbackGuard;
class TParallelOperation;
class TCollectedFileList;
struct TLocalFileHandle;
typedef std::vector<__int64> TCalculatedSizes;
//---------------------------------------------------------------------------
typedef void __fastcall (__closure *TQueryUserEvent)
(TObject * Sender, const UnicodeString Query, TStrings * MoreMessages, unsigned int Answers,
@@ -316,8 +317,6 @@ protected:
bool __fastcall DoCalculateDirectorySize(const UnicodeString & FileName, TCalculateSizeParams * Params);
void __fastcall CalculateLocalFileSize(
const UnicodeString & FileName, const TSearchRecSmart & Rec, /*__int64*/ void * Size);
bool __fastcall CalculateLocalFilesSize(TStrings * FileList, __int64 & Size,
const TCopyParamType * CopyParam, bool AllowDirs, TStrings * Files);
TBatchOverwrite __fastcall EffectiveBatchOverwrite(
const UnicodeString & SourceFullFileName, const TCopyParamType * CopyParam, int Params,
TFileOperationProgressType * OperationProgress, bool Special);
@@ -546,6 +545,8 @@ public:
bool __fastcall CalculateFilesSize(TStrings * FileList, __int64 & Size,
int Params, const TCopyParamType * CopyParam, bool AllowDirs,
TCalculateSizeStats & Stats);
bool __fastcall CalculateLocalFilesSize(TStrings * FileList, __int64 & Size,
const TCopyParamType * CopyParam, bool AllowDirs, TStrings * Files, TCalculatedSizes * CalculatedSizes);
void __fastcall CalculateFilesChecksum(const UnicodeString & Alg, TStrings * FileList,
TStrings * Checksums, TCalculatedChecksumEvent OnCalculatedChecksum);
void __fastcall ClearCaches();
@@ -697,6 +698,7 @@ struct TCalculateSizeStats
int Directories;
int SymLinks;
TStrings * FoundFiles;
TCalculatedSizes * CalculatedSizes;
};
//---------------------------------------------------------------------------
struct TCalculateSizeParams
@@ -758,6 +760,7 @@ public:
class TItem
{
friend class TTerminal;
friend class TSynchronizeChecklist;
public:
struct TFileInfo
@@ -778,11 +781,15 @@ public:
TRemoteFile * RemoteFile;
const UnicodeString& GetFileName() const;
bool IsRemoteOnly() const { return (Action == saDownloadNew) || (Action == saDeleteRemote); }
bool IsLocalOnly() const { return (Action == saUploadNew) || (Action == saDeleteLocal); }
bool HasSize() const { return !IsDirectory || FDirectoryHasSize; }
~TItem();
private:
FILETIME FLocalLastWriteTime;
bool FDirectoryHasSize;
TItem();
};
@@ -790,6 +797,7 @@ public:
~TSynchronizeChecklist();
void __fastcall Update(const TItem * Item, bool Check, TAction Action);
void __fastcall UpdateDirectorySize(const TItem * Item, __int64 Size);
static TAction __fastcall Reverse(TAction Action);

View File

@@ -5374,6 +5374,102 @@ void __fastcall TCustomScpExplorerForm::DoFullSynchronize(void * Token, TProcess
FullSynchronize(Params, OnProcessedItem);
}
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::DoSynchronizeChecklistCalculateSize(
TSynchronizeChecklist * Checklist, const TSynchronizeChecklistItemList & Items, void * Token)
{
// terminal can be already closed (e.g. dropped connection)
if (Terminal != NULL)
{
TSynchronizeParams & Params = *static_cast<TSynchronizeParams *>(Token);
std::unique_ptr<TStrings> RemoteFileList(new TStringList());
std::unique_ptr<TStrings> LocalFileList(new TStringList());
for (size_t Index = 0; Index < Items.size(); Index++)
{
const TSynchronizeChecklist::TItem * ChecklistItem = Items[Index];
if (ChecklistItem->IsDirectory)
{
if (ChecklistItem->IsRemoteOnly())
{
RemoteFileList->AddObject(ChecklistItem->RemoteFile->FullFileName, ChecklistItem->RemoteFile);
}
else if (ChecklistItem->IsLocalOnly())
{
LocalFileList->Add(IncludeTrailingBackslash(ChecklistItem->Local.Directory) + ChecklistItem->Local.FileName);
}
else
{
// "update" actions are not relevant for directories
DebugFail();
}
}
}
TCalculatedSizes RemoteCalculatedSizes;
TCalculatedSizes LocalCalculatedSizes;
try
{
bool Result = true;
if (LocalFileList->Count > 0)
{
__int64 LocalSize = 0;
Result = Terminal->CalculateLocalFilesSize(LocalFileList.get(), LocalSize, Params.CopyParam, true, NULL, &LocalCalculatedSizes);
}
if (Result && (RemoteFileList->Count > 0))
{
__int64 RemoteSize = 0;
TCalculateSizeStats RemoteStats;
RemoteStats.CalculatedSizes = &RemoteCalculatedSizes;
Terminal->CalculateFilesSize(RemoteFileList.get(), RemoteSize, 0, Params.CopyParam, true, RemoteStats);
}
}
__finally
{
size_t LocalIndex = 0;
size_t RemoteIndex = 0;
for (size_t Index = 0; Index < Items.size(); Index++)
{
const TSynchronizeChecklist::TItem * ChecklistItem = Items[Index];
if (ChecklistItem->IsDirectory)
{
__int64 Size = -1;
if (ChecklistItem->IsRemoteOnly())
{
if (RemoteIndex < RemoteCalculatedSizes.size())
{
Size = RemoteCalculatedSizes[RemoteIndex];
}
RemoteIndex++;
}
else if (ChecklistItem->IsLocalOnly())
{
if (LocalIndex < LocalCalculatedSizes.size())
{
Size = LocalCalculatedSizes[LocalIndex];
}
LocalIndex++;
}
else
{
// "update" actions are not relevant for directories
DebugFail();
}
if (Size >= 0)
{
Checklist->UpdateDirectorySize(ChecklistItem, Size);
}
}
}
DebugAssert(RemoteIndex >= RemoteCalculatedSizes.size());
DebugAssert(LocalIndex >= LocalCalculatedSizes.size());
}
}
}
//---------------------------------------------------------------------------
bool __fastcall TCustomScpExplorerForm::DoFullSynchronizeDirectories(
UnicodeString & LocalDirectory, UnicodeString & RemoteDirectory,
TSynchronizeMode & Mode, bool & SaveMode, bool UseDefaults)
@@ -5452,7 +5548,7 @@ bool __fastcall TCustomScpExplorerForm::DoFullSynchronizeDirectories(
Result =
DoSynchronizeChecklistDialog(
Checklist, Mode, Params, LocalDirectory, RemoteDirectory, CustomCommandMenu, DoFullSynchronize,
&SynchronizeParams);
DoSynchronizeChecklistCalculateSize, &SynchronizeParams);
}
else
{

View File

@@ -606,6 +606,8 @@ protected:
void __fastcall CopyPopup(TControl * DestControl, TControl * SourceControl);
void __fastcall CreateRemoteDirectory(const UnicodeString & Path, TRemoteProperties & Properties);
void __fastcall DoFullSynchronize(void * Token, TProcessedItem OnProcessedItem);
void __fastcall DoSynchronizeChecklistCalculateSize(
TSynchronizeChecklist * Checklist, const TSynchronizeChecklistItemList & Items, void * Token);
void __fastcall FullSynchronize(TSynchronizeParams & Params, TProcessedItem OnProcessedItem);
void __fastcall CreateOpenDirMenuList(TTBCustomItem * Menu, TOperationSide Side, TBookmarkList * BookmarkList);
void __fastcall CreateOpenDirMenu(TTBCustomItem * Menu, TOperationSide Side);

View File

@@ -30,17 +30,21 @@ const int ImageColumnIndex = 4;
bool __fastcall DoSynchronizeChecklistDialog(TSynchronizeChecklist * Checklist,
TSynchronizeMode Mode, int Params,
const UnicodeString LocalDirectory, const UnicodeString RemoteDirectory,
TCustomCommandMenuEvent OnCustomCommandMenu, TFullSynchronizeEvent OnSynchronize, void * Token)
TCustomCommandMenuEvent OnCustomCommandMenu, TFullSynchronizeEvent OnSynchronize,
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, void * Token)
{
std::unique_ptr<TSynchronizeChecklistDialog> Dialog(
new TSynchronizeChecklistDialog(Application, Mode, Params, LocalDirectory, RemoteDirectory, OnCustomCommandMenu, OnSynchronize, Token));
new TSynchronizeChecklistDialog(
Application, Mode, Params, LocalDirectory, RemoteDirectory, OnCustomCommandMenu, OnSynchronize,
OnSynchronizeChecklistCalculateSize, Token));
return Dialog->Execute(Checklist);
}
//---------------------------------------------------------------------
__fastcall TSynchronizeChecklistDialog::TSynchronizeChecklistDialog(
TComponent * AOwner, TSynchronizeMode Mode, int Params,
const UnicodeString LocalDirectory, const UnicodeString RemoteDirectory,
TCustomCommandMenuEvent OnCustomCommandMenu, TFullSynchronizeEvent OnSynchronize, void * Token)
const UnicodeString & LocalDirectory, const UnicodeString & RemoteDirectory,
TCustomCommandMenuEvent OnCustomCommandMenu, TFullSynchronizeEvent OnSynchronize,
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, void * Token)
: TForm(AOwner)
{
FFormRestored = false;
@@ -49,6 +53,7 @@ __fastcall TSynchronizeChecklistDialog::TSynchronizeChecklistDialog(
FLocalDirectory = ExcludeTrailingBackslash(LocalDirectory);
FRemoteDirectory = UnixExcludeTrailingBackslash(RemoteDirectory);
FOnCustomCommandMenu = OnCustomCommandMenu;
FOnSynchronizeChecklistCalculateSize = OnSynchronizeChecklistCalculateSize;
DebugAssert(OnSynchronize != NULL);
FOnSynchronize = OnSynchronize;
FToken = Token;
@@ -123,10 +128,12 @@ void __fastcall TSynchronizeChecklistDialog::UpdateControls()
bool AllUnchecked = true;
bool AnyBoth = false;
bool AnyNonBoth = false;
bool AnyDirectory = false;
TListItem * Item = ListView->Selected;
while (Item != NULL)
{
TSynchronizeChecklist::TAction Action = GetChecklistItemAction(GetChecklistItem(Item));
const TSynchronizeChecklist::TItem * ChecklistItem = GetChecklistItem(Item);
TSynchronizeChecklist::TAction Action = GetChecklistItemAction(ChecklistItem);
if ((Action == TSynchronizeChecklist::saUploadUpdate) ||
(Action == TSynchronizeChecklist::saDownloadUpdate))
{
@@ -145,6 +152,10 @@ void __fastcall TSynchronizeChecklistDialog::UpdateControls()
{
AllChecked = false;
}
if (ChecklistItem->IsDirectory)
{
AnyDirectory = true;
}
Item = ListView->GetNextItem(Item, sdAll, TItemStates() << isSelected);
}
@@ -157,6 +168,7 @@ void __fastcall TSynchronizeChecklistDialog::UpdateControls()
UncheckAllAction->Enabled = (FChecked[0] > 0) && !FSynchronizing;
CustomCommandsAction->Enabled = AnyBoth && !AnyNonBoth && DebugAlwaysTrue(!FSynchronizing);
ReverseAction->Enabled = (ListView->SelCount > 0) && DebugAlwaysTrue(!FSynchronizing);
CalculateSizeAction->Enabled = (ListView->SelCount > 0) && AnyDirectory && DebugAlwaysTrue(!FSynchronizing);
SelectAllAction->Enabled = (ListView->SelCount < ListView->Items->Count) && !FSynchronizing;
}
@@ -249,7 +261,7 @@ void __fastcall TSynchronizeChecklistDialog::LoadItem(TListItem * Item)
}
else
{
if (ChecklistItem->IsDirectory)
if (!ChecklistItem->HasSize())
{
AddSubItem(Item, Index, L"");
}
@@ -293,7 +305,7 @@ void __fastcall TSynchronizeChecklistDialog::LoadItem(TListItem * Item)
}
else
{
if (ChecklistItem->IsDirectory)
if (!ChecklistItem->HasSize())
{
AddSubItem(Item, Index, L"");
}
@@ -1124,3 +1136,48 @@ void __fastcall TSynchronizeChecklistDialog::OkButtonClick(TObject * /*Sender*/)
}
}
//---------------------------------------------------------------------------
void __fastcall TSynchronizeChecklistDialog::CalculateSizeActionExecute(TObject * /*Sender*/)
{
std::map<const TSynchronizeChecklist::TItem *, TListItem *> ChecklistToListViewMap;
TSynchronizeChecklistItemList Items;
TListItem * Item = ListView->Selected;
while (Item != NULL)
{
const TSynchronizeChecklist::TItem * ChecklistItem = GetChecklistItem(Item);
ChecklistToListViewMap.insert(std::make_pair(ChecklistItem, Item));
Items.push_back(ChecklistItem);
if (Item->Checked)
{
__int64 ItemSize = GetItemSize(ChecklistItem);
int ActionIndex = int(GetChecklistItemAction(ChecklistItem));
FCheckedSize[ActionIndex] -= ItemSize;
FCheckedSize[0] -= ItemSize;
}
Item = ListView->GetNextItem(Item, sdAll, TItemStates() << isSelected);
}
try
{
FOnSynchronizeChecklistCalculateSize(FChecklist, Items, FToken);
}
__finally
{
TSynchronizeChecklistItemList::const_iterator Iter = Items.begin();
while (Iter != Items.end())
{
const TSynchronizeChecklist::TItem * ChecklistItem = *Iter;
TListItem * Item = ChecklistToListViewMap[ChecklistItem];
LoadItem(Item);
if (Item->Checked)
{
__int64 ItemSize = GetItemSize(ChecklistItem);
int ActionIndex = int(GetChecklistItemAction(ChecklistItem));
FCheckedSize[ActionIndex] += ItemSize;
FCheckedSize[0] += ItemSize;
}
Iter++;
}
UpdateControls();
}
}
//---------------------------------------------------------------------------

View File

@@ -1443,7 +1443,7 @@ object SynchronizeChecklistDialog: TSynchronizeChecklistDialog
end
object CustomCommandsButton2: TButton
Left = 8
Top = 292
Top = 322
Width = 108
Height = 25
Action = CustomCommandsAction
@@ -1460,6 +1460,15 @@ object SynchronizeChecklistDialog: TSynchronizeChecklistDialog
Anchors = [akLeft, akTop, akRight]
TabOrder = 7
end
object CalculateSizeButton: TButton
Left = 8
Top = 291
Width = 108
Height = 25
Action = CalculateSizeAction
Anchors = [akLeft, akTop, akRight]
TabOrder = 9
end
end
object ListView: TIEListView
Left = 0
@@ -2323,6 +2332,9 @@ object SynchronizeChecklistDialog: TSynchronizeChecklistDialog
object ReverseItem: TMenuItem
Action = ReverseAction
end
object Calculate1: TMenuItem
Action = CalculateSizeAction
end
object TMenuItem
Action = CustomCommandsAction
object TMenuItem
@@ -2374,6 +2386,10 @@ object SynchronizeChecklistDialog: TSynchronizeChecklistDialog
Caption = '&Reverse'
OnExecute = ReverseActionExecute
end
object CalculateSizeAction: TAction
Caption = 'C&alculate'
OnExecute = CalculateSizeActionExecute
end
end
object ActionImages120: TPngImageList
Height = 20

View File

@@ -52,6 +52,9 @@ __published:
TPngImageList *ActionImages120;
TPngImageList *ActionImages144;
TPngImageList *ActionImages192;
TAction *CalculateSizeAction;
TMenuItem *Calculate1;
TButton *CalculateSizeButton;
void __fastcall HelpButtonClick(TObject * Sender);
void __fastcall FormShow(TObject * Sender);
void __fastcall StatusBarDrawPanel(TStatusBar *StatusBar,
@@ -85,13 +88,14 @@ __published:
void __fastcall ReverseActionExecute(TObject *Sender);
void __fastcall ListViewClick(TObject *Sender);
void __fastcall OkButtonClick(TObject *Sender);
void __fastcall CalculateSizeActionExecute(TObject *Sender);
public:
__fastcall TSynchronizeChecklistDialog(TComponent * AOwner,
TSynchronizeMode Mode, int Params, const UnicodeString LocalDirectory,
const UnicodeString RemoteDirectory, TCustomCommandMenuEvent OnCustomCommandMenu,
TFullSynchronizeEvent OnSynchronize, void * Token);
__fastcall TSynchronizeChecklistDialog(
TComponent * AOwner, TSynchronizeMode Mode, int Params,
const UnicodeString & LocalDirectory, const UnicodeString & RemoteDirectory,
TCustomCommandMenuEvent OnCustomCommandMenu, TFullSynchronizeEvent OnSynchronize,
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, void * Token);
virtual __fastcall ~TSynchronizeChecklistDialog();
bool __fastcall Execute(TSynchronizeChecklist * Checklist);
@@ -113,6 +117,7 @@ protected:
bool FChangingItemMass;
UnicodeString FGeneralHint;
TCustomCommandMenuEvent FOnCustomCommandMenu;
TSynchronizeChecklistCalculateSize FOnSynchronizeChecklistCalculateSize;
typedef std::map<const TSynchronizeChecklist::TItem *, TSynchronizeChecklist::TAction> TActions;
TActions FActions;
TFullSynchronizeEvent FOnSynchronize;

View File

@@ -352,10 +352,14 @@ class TSynchronizeChecklist;
typedef void __fastcall (__closure *TCustomCommandMenuEvent)
(TAction * Action, TStrings * LocalFileList, TStrings * RemoteFileList);
typedef void __fastcall (__closure *TFullSynchronizeEvent)(void * Token, TProcessedItem OnProcessedItem);
typedef std::vector<const TSynchronizeChecklist::TItem *> TSynchronizeChecklistItemList;
typedef void __fastcall (__closure *TSynchronizeChecklistCalculateSize)
(TSynchronizeChecklist * Checklist, const TSynchronizeChecklistItemList & Items, void * Token);
bool __fastcall DoSynchronizeChecklistDialog(TSynchronizeChecklist * Checklist,
TSynchronizeMode Mode, int Params,
const UnicodeString LocalDirectory, const UnicodeString RemoteDirectory,
TCustomCommandMenuEvent OnCustomCommandMenu, TFullSynchronizeEvent OnSynchronize, void * Token);
TCustomCommandMenuEvent OnCustomCommandMenu, TFullSynchronizeEvent OnSynchronize,
TSynchronizeChecklistCalculateSize OnSynchronizeChecklistCalculateSize, void * Token);
// forms\Editor.cpp
typedef void __fastcall (__closure *TFileClosedEvent)