mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
ADD: Possibility to use a search template for move operation (only for FileSystemFileSource). The template defines which files/directories to move and which to exclude.
This commit is contained in:
parent
eff0e04dd4
commit
bf0fa71a4c
5 changed files with 56 additions and 17 deletions
|
|
@ -201,7 +201,6 @@ inherited FileSystemCopyMoveOperationOptionsUI: TFileSystemCopyMoveOperationOpti
|
|||
ClientHeight = 64
|
||||
ClientWidth = 213
|
||||
TabOrder = 1
|
||||
Visible = False
|
||||
object btnSearchTemplate: TBitBtn
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = gbFileTemplate
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ begin
|
|||
SearchTemplate := FTemplate;
|
||||
FTemplate := nil;
|
||||
end;
|
||||
RemoveEmptyTemplateDirectories := cbExcludeEmptyDirectories.Checked;
|
||||
ExcludeEmptyTemplateDirectories := cbExcludeEmptyDirectories.Checked;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -289,6 +289,12 @@ begin
|
|||
SetCopyOption(Options, caoCopyTime, cbCopyTime.Checked);
|
||||
SetCopyOption(Options, caoCopyOwnership, cbCopyOwnership.Checked);
|
||||
CopyAttributesOptions := Options;
|
||||
if Assigned(FTemplate) then
|
||||
begin
|
||||
SearchTemplate := FTemplate;
|
||||
FTemplate := nil;
|
||||
end;
|
||||
ExcludeEmptyTemplateDirectories := cbExcludeEmptyDirectories.Checked;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -299,7 +305,6 @@ begin
|
|||
inherited;
|
||||
cbDropReadOnlyFlag.Visible := True;
|
||||
cbFollowLinks.Visible := True;
|
||||
gbFileTemplate.Visible := True;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ type
|
|||
|
||||
private
|
||||
FOperationHelper: TFileSystemOperationHelper;
|
||||
FRemoveEmptyTemplateDirectories: Boolean;
|
||||
FExcludeEmptyTemplateDirectories: Boolean;
|
||||
FSearchTemplate: TSearchTemplate;
|
||||
FSetPropertyError: TFileSourceOperationOptionSetPropertyError;
|
||||
FSourceFilesTree: TFileTree; // source files including all files/dirs in subdirectories
|
||||
|
|
@ -64,7 +64,7 @@ type
|
|||
property FileExistsOption: TFileSourceOperationOptionFileExists read FFileExistsOption write FFileExistsOption;
|
||||
property DirExistsOption: TFileSourceOperationOptionDirectoryExists read FDirExistsOption write FDirExistsOption;
|
||||
property SetPropertyError: TFileSourceOperationOptionSetPropertyError read FSetPropertyError write FSetPropertyError;
|
||||
property RemoveEmptyTemplateDirectories: Boolean read FRemoveEmptyTemplateDirectories write FRemoveEmptyTemplateDirectories;
|
||||
property ExcludeEmptyTemplateDirectories: Boolean read FExcludeEmptyTemplateDirectories write FExcludeEmptyTemplateDirectories;
|
||||
{en
|
||||
Operation takes ownership of assigned template and will free it.
|
||||
}
|
||||
|
|
@ -125,6 +125,7 @@ begin
|
|||
FSkipAllBigFiles := False;
|
||||
FAutoRenameItSelf := False;
|
||||
FCorrectSymLinks := gOperationOptionCorrectLinks;
|
||||
FExcludeEmptyTemplateDirectories := True;
|
||||
|
||||
inherited Create(aSourceFileSource, aTargetFileSource, theSourceFiles, aTargetPath);
|
||||
end;
|
||||
|
|
@ -150,7 +151,7 @@ begin
|
|||
try
|
||||
TreeBuilder.SymLinkOption := Self.SymLinkOption;
|
||||
TreeBuilder.SearchTemplate := Self.SearchTemplate;
|
||||
TreeBuilder.RemoveEmptyTemplateDirectories := Self.RemoveEmptyTemplateDirectories;
|
||||
TreeBuilder.ExcludeEmptyTemplateDirectories := Self.ExcludeEmptyTemplateDirectories;
|
||||
|
||||
TreeBuilder.BuildFromFiles(SourceFiles);
|
||||
FSourceFilesTree := TreeBuilder.ReleaseTree;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ uses
|
|||
uFileSourceOperationOptionsUI,
|
||||
uFile,
|
||||
uFileSystemUtil,
|
||||
DCOSUtils;
|
||||
DCOSUtils,
|
||||
uSearchTemplate;
|
||||
|
||||
type
|
||||
|
||||
|
|
@ -23,6 +24,8 @@ type
|
|||
private
|
||||
FCopyAttributesOptions: TCopyAttributesOptions;
|
||||
FOperationHelper: TFileSystemOperationHelper;
|
||||
FExcludeEmptyTemplateDirectories: Boolean;
|
||||
FSearchTemplate: TSearchTemplate;
|
||||
FSetPropertyError: TFileSourceOperationOptionSetPropertyError;
|
||||
FSourceFilesTree: TFileTree; // source files including all files/dirs in subdirectories
|
||||
FStatistics: TFileSourceMoveOperationStatistics; // local copy of statistics
|
||||
|
|
@ -33,6 +36,7 @@ type
|
|||
FFileExistsOption: TFileSourceOperationOptionFileExists;
|
||||
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
|
||||
FCorrectSymlinks: Boolean;
|
||||
procedure SetSearchTemplate(AValue: TSearchTemplate);
|
||||
|
||||
protected
|
||||
|
||||
|
|
@ -56,6 +60,11 @@ type
|
|||
property FileExistsOption: TFileSourceOperationOptionFileExists read FFileExistsOption write FFileExistsOption;
|
||||
property DirExistsOption: TFileSourceOperationOptionDirectoryExists read FDirExistsOption write FDirExistsOption;
|
||||
property SetPropertyError: TFileSourceOperationOptionSetPropertyError read FSetPropertyError write FSetPropertyError;
|
||||
property ExcludeEmptyTemplateDirectories: Boolean read FExcludeEmptyTemplateDirectories write FExcludeEmptyTemplateDirectories;
|
||||
{en
|
||||
Operation takes ownership of assigned template and will free it.
|
||||
}
|
||||
property SearchTemplate: TSearchTemplate read FSearchTemplate write SetSearchTemplate;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
|
@ -81,6 +90,7 @@ begin
|
|||
FCheckFreeSpace := gOperationOptionCheckFreeSpace;
|
||||
FSkipAllBigFiles := False;
|
||||
FCorrectSymlinks := gOperationOptionCorrectLinks;
|
||||
FExcludeEmptyTemplateDirectories := True;
|
||||
|
||||
inherited Create(aFileSource, theSourceFiles, aTargetPath);
|
||||
end;
|
||||
|
|
@ -90,6 +100,7 @@ begin
|
|||
inherited Destroy;
|
||||
FreeAndNil(FSourceFilesTree);
|
||||
FreeAndNil(FOperationHelper);
|
||||
FreeAndNil(FSearchTemplate);
|
||||
end;
|
||||
|
||||
procedure TFileSystemMoveOperation.Initialize;
|
||||
|
|
@ -105,6 +116,9 @@ begin
|
|||
try
|
||||
// In move operation don't follow symlinks.
|
||||
TreeBuilder.SymLinkOption := fsooslDontFollow;
|
||||
TreeBuilder.SearchTemplate := Self.SearchTemplate;
|
||||
TreeBuilder.ExcludeEmptyTemplateDirectories := Self.ExcludeEmptyTemplateDirectories;
|
||||
|
||||
TreeBuilder.BuildFromFiles(SourceFiles);
|
||||
FSourceFilesTree := TreeBuilder.ReleaseTree;
|
||||
FStatistics.TotalFiles := TreeBuilder.FilesCount;
|
||||
|
|
@ -142,6 +156,12 @@ begin
|
|||
FOperationHelper.ProcessTree(FSourceFilesTree);
|
||||
end;
|
||||
|
||||
procedure TFileSystemMoveOperation.SetSearchTemplate(AValue: TSearchTemplate);
|
||||
begin
|
||||
FSearchTemplate.Free;
|
||||
FSearchTemplate := AValue;
|
||||
end;
|
||||
|
||||
procedure TFileSystemMoveOperation.Finalize;
|
||||
begin
|
||||
if Assigned(FOperationHelper) then
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ type
|
|||
public
|
||||
// True if any of the subnodes (recursively) are links.
|
||||
SubnodesHaveLinks: Boolean;
|
||||
// Whether directory or subdirectories have any elements that will not be copied/moved.
|
||||
SubnodesHaveExclusions: Boolean;
|
||||
end;
|
||||
|
||||
TUpdateStatisticsFunction = procedure(var NewStatistics: TFileSourceCopyOperationStatistics) of object;
|
||||
|
|
@ -57,7 +59,7 @@ type
|
|||
FFilesSize: Int64;
|
||||
FExcludeRootDir: Boolean;
|
||||
FFileTemplate: TSearchTemplate;
|
||||
FRemoveEmptyTemplateDirectories: Boolean;
|
||||
FExcludeEmptyTemplateDirectories: Boolean;
|
||||
FSymlinkOption: TFileSourceOperationOptionSymLink;
|
||||
FRecursive: Boolean;
|
||||
FFileChecks: TFindFileChecks;
|
||||
|
|
@ -93,7 +95,7 @@ type
|
|||
property FilesCount: Int64 read FFilesCount;
|
||||
property DirectoriesCount: Int64 read FDirectoriesCount;
|
||||
property ItemsCount: Int64 read GetItemsCount;
|
||||
property RemoveEmptyTemplateDirectories: Boolean read FRemoveEmptyTemplateDirectories write FRemoveEmptyTemplateDirectories;
|
||||
property ExcludeEmptyTemplateDirectories: Boolean read FExcludeEmptyTemplateDirectories write FExcludeEmptyTemplateDirectories;
|
||||
{en
|
||||
Does not take ownership of SearchTemplate and does not free it.
|
||||
}
|
||||
|
|
@ -443,10 +445,12 @@ procedure TFileSystemTreeBuilder.AddDirectory(aFile: TFile; CurrentNode: TFileTr
|
|||
var
|
||||
AddedNode: TFileTreeNode;
|
||||
AddedIndex: Integer;
|
||||
NodeData: TFileTreeNodeData;
|
||||
begin
|
||||
AddedIndex := CurrentNode.AddSubNode(aFile);
|
||||
AddedNode := CurrentNode.SubNodes[AddedIndex];
|
||||
AddedNode.Data := TFileTreeNodeData.Create;
|
||||
NodeData := TFileTreeNodeData.Create;
|
||||
AddedNode.Data := NodeData;
|
||||
|
||||
Inc(FDirectoriesCount);
|
||||
|
||||
|
|
@ -454,16 +458,19 @@ begin
|
|||
begin
|
||||
AddFilesInDirectory(aFile.FullPath + DirectorySeparator, AddedNode);
|
||||
|
||||
if Assigned(FFileTemplate) and FRemoveEmptyTemplateDirectories and
|
||||
if Assigned(FFileTemplate) and FExcludeEmptyTemplateDirectories and
|
||||
(AddedNode.SubNodesCount = 0) then
|
||||
begin
|
||||
CurrentNode.RemoveSubNode(AddedIndex);
|
||||
(CurrentNode.Data as TFileTreeNodeData).SubnodesHaveExclusions := True;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Propagate flag to parent.
|
||||
if (AddedNode.Data as TFileTreeNodeData).SubnodesHaveLinks then
|
||||
// Propagate flags to parent.
|
||||
if NodeData.SubnodesHaveLinks then
|
||||
(CurrentNode.Data as TFileTreeNodeData).SubnodesHaveLinks := True;
|
||||
if NodeData.SubnodesHaveExclusions then
|
||||
(CurrentNode.Data as TFileTreeNodeData).SubnodesHaveExclusions := True;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
|
@ -514,7 +521,10 @@ begin
|
|||
if Matches and (AFile.IsDirectory or AFile.IsLinkToDirectory) then
|
||||
Matches := CheckDirectoryNameRelative(FFileChecks, aFile.FullPath, FRootDir);
|
||||
if not Matches then
|
||||
begin
|
||||
(CurrentNode.Data as TFileTreeNodeData).SubnodesHaveExclusions := True;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
if aFile.IsDirectory then
|
||||
|
|
@ -1105,8 +1115,12 @@ end;
|
|||
function TFileSystemOperationHelper.ProcessDirectory(aNode: TFileTreeNode; AbsoluteTargetFileName: String): Boolean;
|
||||
var
|
||||
bRemoveDirectory: Boolean;
|
||||
NodeData: TFileTreeNodeData;
|
||||
begin
|
||||
bRemoveDirectory := (FMode = fsohmMove);
|
||||
NodeData := aNode.Data as TFileTreeNodeData;
|
||||
|
||||
// If some files will not be moved then source directory cannot be deleted.
|
||||
bRemoveDirectory := (FMode = fsohmMove) and (NodeData.SubnodesHaveExclusions = False);
|
||||
|
||||
case TargetExists(aNode, AbsoluteTargetFileName) of
|
||||
fsoterSkip:
|
||||
|
|
@ -1119,11 +1133,11 @@ begin
|
|||
begin
|
||||
// Try moving whole directory tree. It can be done only if we don't have
|
||||
// to process each subnode: if there are no links, or they're not being
|
||||
// processed and if the files are not being renamed.
|
||||
// processed, if the files are not being renamed or excluded.
|
||||
if (FMode = fsohmMove) and
|
||||
(not FRenamingFiles) and
|
||||
((FCorrectSymlinks = False) or
|
||||
((aNode.Data as TFileTreeNodeData).SubnodesHaveLinks = False)) and
|
||||
((FCorrectSymlinks = False) or (NodeData.SubnodesHaveLinks = False)) and
|
||||
(NodeData.SubnodesHaveExclusions = False) and
|
||||
mbRenameFile(aNode.TheFile.FullPath, AbsoluteTargetFileName) then
|
||||
begin
|
||||
// Success.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue