ADD: Find duplicate files options

This commit is contained in:
Alexander Koblov 2019-12-04 17:31:15 +00:00
commit d46ad32dfd
4 changed files with 194 additions and 8 deletions

View file

@ -18,7 +18,7 @@ object frmFindDlg: TfrmFindDlg
Position = poScreenCenter
SessionProperties = 'Height;Left;Top;Width;WindowState'
ShowInTaskBar = stAlways
LCLVersion = '1.8.4.0'
LCLVersion = '2.0.7.0'
object pnlFindFile: TPanel
Left = 3
Height = 443
@ -905,6 +905,82 @@ object frmFindDlg: TfrmFindDlg
OnClick = btnAttrsHelpClick
TabOrder = 18
end
object chkDuplicates: TCheckBox
AnchorSideLeft.Control = edtAttrib
AnchorSideTop.Control = Bevel3
AnchorSideTop.Side = asrBottom
Left = 3
Height = 19
Top = 263
Width = 122
BorderSpacing.Top = 12
Caption = 'Find du&plicate files:'
OnChange = chkDuplicatesChange
TabOrder = 19
end
object pnlDuplicates: TPanel
AnchorSideLeft.Control = chkDuplicates
AnchorSideTop.Control = chkDuplicates
AnchorSideTop.Side = asrBottom
Left = 11
Height = 19
Top = 282
Width = 259
AutoSize = True
BorderSpacing.Left = 8
BevelOuter = bvNone
ChildSizing.HorizontalSpacing = 8
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 3
ClientHeight = 19
ClientWidth = 259
Enabled = False
TabOrder = 20
object chkDuplicateName: TCheckBox
Left = 0
Height = 19
Top = 0
Width = 81
Caption = 'same name'
OnChange = chkDuplicateNameChange
TabOrder = 0
end
object chkDuplicateSize: TCheckBox
Left = 89
Height = 19
Top = 0
Width = 70
Caption = 'same size'
OnChange = chkDuplicateSizeChange
TabOrder = 1
end
object chkDuplicateContent: TCheckBox
Left = 167
Height = 19
Top = 0
Width = 92
Caption = 'same content'
OnChange = chkDuplicateContentChange
TabOrder = 2
end
end
object Bevel3: TBevel
AnchorSideLeft.Control = tsAdvanced
AnchorSideTop.Control = edtAttrib
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = tsAdvanced
AnchorSideRight.Side = asrBottom
Left = 6
Height = 4
Top = 247
Width = 740
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6
BorderSpacing.Top = 12
BorderSpacing.Right = 6
Shape = bsTopLine
Style = bsRaised
end
end
object tsPlugins: TTabSheet
Caption = 'Plugins'

View file

@ -36,6 +36,10 @@
{"hash":193032515,"name":"tfrmfinddlg.lblattributes.caption","sourcebytes":[65,116,116,114,105,38,98,117,116,101,115],"value":"Attri&butes"},
{"hash":173988,"name":"tfrmfinddlg.btnaddattribute.caption","sourcebytes":[38,65,100,100],"value":"&Add"},
{"hash":2812976,"name":"tfrmfinddlg.btnattrshelp.caption","sourcebytes":[38,72,101,108,112],"value":"&Help"},
{"hash":39455530,"name":"tfrmfinddlg.chkduplicates.caption","sourcebytes":[70,105,110,100,32,100,117,38,112,108,105,99,97,116,101,32,102,105,108,101,115,58],"value":"Find du&plicate files:"},
{"hash":58146741,"name":"tfrmfinddlg.chkduplicatename.caption","sourcebytes":[115,97,109,101,32,110,97,109,101],"value":"same name"},
{"hash":58194565,"name":"tfrmfinddlg.chkduplicatesize.caption","sourcebytes":[115,97,109,101,32,115,105,122,101],"value":"same size"},
{"hash":266181940,"name":"tfrmfinddlg.chkduplicatecontent.caption","sourcebytes":[115,97,109,101,32,99,111,110,116,101,110,116],"value":"same content"},
{"hash":121364483,"name":"tfrmfinddlg.tsplugins.caption","sourcebytes":[80,108,117,103,105,110,115],"value":"Plugins"},
{"hash":125449178,"name":"tfrmfinddlg.cbuseplugin.caption","sourcebytes":[38,85,115,101,32,115,101,97,114,99,104,32,112,108,117,103,105,110,58],"value":"&Use search plugin:"},
{"hash":91471358,"name":"tfrmfinddlg.frmcontentplugins.headercontrol.sections[0].text","sourcebytes":[80,108,117,103,105,110],"value":"Plugin"},

View file

@ -66,6 +66,7 @@ type
actStart: TAction;
actList: TActionList;
Bevel2: TBevel;
Bevel3: TBevel;
btnAddAttribute: TButton;
btnAttrsHelp: TButton;
btnClose: TButton;
@ -100,6 +101,10 @@ type
cbTextRegExp: TCheckBox;
cbFindInArchive: TCheckBox;
cbOpenedTabs: TCheckBox;
chkDuplicateContent: TCheckBox;
chkDuplicateSize: TCheckBox;
chkDuplicateName: TCheckBox;
chkDuplicates: TCheckBox;
chkHex: TCheckBox;
cmbExcludeDirectories: TComboBoxWithDelItems;
cmbNotOlderThanUnit: TComboBox;
@ -133,6 +138,7 @@ type
miShowInEditor: TMenuItem;
miShowAllFound: TMenuItem;
miRemoveFromLlist: TMenuItem;
pnlDuplicates: TPanel;
pnlDirectoriesDepth: TPanel;
pnlLoadSaveBottomButtons: TPanel;
pnlLoadSaveBottom: TPanel;
@ -211,6 +217,10 @@ type
procedure cbRegExpChange(Sender: TObject);
procedure cbTextRegExpChange(Sender: TObject);
procedure cbSelectedFilesChange(Sender: TObject);
procedure chkDuplicateContentChange(Sender: TObject);
procedure chkDuplicateNameChange(Sender: TObject);
procedure chkDuplicatesChange(Sender: TObject);
procedure chkDuplicateSizeChange(Sender: TObject);
procedure chkHexChange(Sender: TObject);
procedure cmbEncodingSelect(Sender: TObject);
procedure cbFindTextChange(Sender: TObject);
@ -301,6 +311,7 @@ type
procedure OnAddAttribute(Sender: TObject);
function InvalidRegExpr(AChecked: boolean; const ARegExpr: string): boolean;
procedure SetWindowCaption(AWindowCaptionStyle: byte);
function ObjectType(Index: Integer): TCheckBoxState;
function GetFileMask: String;
public
FoundedStringCopy: TStringList;
@ -376,9 +387,10 @@ implementation
uses
LCLProc, LCLType, LConvEncoding, StrUtils, HelpIntfs, fViewer, fMain,
uLng, uGlobs, uShowForm, uDCUtils, uFileSource, uFileSourceUtil,
uSearchResultFileSource, uFile,
uSearchResultFileSource, uFile, uFileProperty, uColumnsFileView,
uFileViewNotebook, uKeyboard, uOSUtils, uArchiveFileSourceUtil,
DCOSUtils, RegExpr, uDebug, uShowMsg, uConvEncoding;
DCOSUtils, RegExpr, uDebug, uShowMsg, uConvEncoding, uColumns,
uFileFunctions;
const
TimeUnitToComboIndex: array[TTimeUnit] of integer = (0, 1, 2, 3, 4, 5, 6);
@ -1014,6 +1026,34 @@ begin
cmbFindPathStart.Enabled := not cbSelectedFiles.Checked;
end;
procedure TfrmFindDlg.chkDuplicateContentChange(Sender: TObject);
begin
if chkDuplicateContent.Checked then chkDuplicateSize.Checked:= True;
chkDuplicateNameChange(chkDuplicateName);
end;
procedure TfrmFindDlg.chkDuplicateNameChange(Sender: TObject);
begin
if not (chkDuplicateName.Checked or chkDuplicateSize.Checked) then
chkDuplicates.Checked:= False;
end;
procedure TfrmFindDlg.chkDuplicatesChange(Sender: TObject);
begin
pnlDuplicates.Enabled:= chkDuplicates.Checked;
if chkDuplicates.Checked then
begin
if not (chkDuplicateName.Checked or chkDuplicateSize.Checked) then
chkDuplicateName.Checked:= True;
end;
end;
procedure TfrmFindDlg.chkDuplicateSizeChange(Sender: TObject);
begin
if not chkDuplicateSize.Checked then chkDuplicateContent.Checked:= False;
chkDuplicateNameChange(chkDuplicateName);
end;
procedure TfrmFindDlg.chkHexChange(Sender: TObject);
begin
if chkHex.Checked then
@ -1124,6 +1164,11 @@ begin
NotContainingText := cbNotContainingText.Checked;
TextRegExp := cbTextRegExp.Checked;
TextEncoding := cmbEncoding.Text;
{ Duplicates }
Duplicates:= chkDuplicates.Checked;
DuplicateName:= chkDuplicateName.Checked;
DuplicateSize:= chkDuplicateSize.Checked;
DuplicateContent:= chkDuplicateContent.Checked;
{ Plugins }
SearchPlugin := cmbPlugin.Text;
frmContentPlugins.Save(FindOptions);
@ -1608,7 +1653,7 @@ begin
if pgcSearch.ActivePage = tsResults then
if lsFoundedFiles.ItemIndex <> -1 then
begin
if (lsFoundedFiles.Items.Objects[lsFoundedFiles.ItemIndex] <> nil) then
if (ObjectType(lsFoundedFiles.ItemIndex) = cbChecked) then
msgError(rsMsgErrNotSupported)
else
ShowViewerByGlob(lsFoundedFiles.Items[lsFoundedFiles.ItemIndex]);
@ -1621,7 +1666,7 @@ begin
if pgcSearch.ActivePage = tsResults then
if lsFoundedFiles.ItemIndex <> -1 then
begin
if (lsFoundedFiles.Items.Objects[lsFoundedFiles.ItemIndex] <> nil) then
if (ObjectType(lsFoundedFiles.ItemIndex) = cbChecked) then
msgError(rsMsgErrNotSupported)
else
ShowEditorByGlob(lsFoundedFiles.Items[lsFoundedFiles.ItemIndex]);
@ -1640,7 +1685,7 @@ begin
try
StopSearch;
TargetFile := lsFoundedFiles.Items[lsFoundedFiles.ItemIndex];
if (lsFoundedFiles.Items.Objects[lsFoundedFiles.ItemIndex] <> nil) then
if (ObjectType(lsFoundedFiles.ItemIndex) = cbChecked) then
begin
ArchiveFile := ExtractWord(1, TargetFile, [ReversePathDelim]);
TargetFile := PathDelim + ExtractWord(2, TargetFile, [ReversePathDelim]);
@ -1674,6 +1719,8 @@ end;
{ TfrmFindDlg.cm_FeedToListbox }
procedure TfrmFindDlg.cm_FeedToListbox(const Params: array of string);
const
PluginDuplicate = 'Plugin().Duplicate{}';
var
I: integer;
sFileName: string;
@ -1682,6 +1729,9 @@ var
aFile: TFile;
Notebook: TFileViewNotebook;
NewPage: TFileViewPage;
DCFunc: String;
AProperty: TFileVariantProperty;
ANewSet: TPanelColumnsClass;
begin
StopSearch;
@ -1691,6 +1741,12 @@ begin
sFileName := lsFoundedFiles.Items[I];
try
aFile := TFileSystemFileSource.CreateFileFromFile(sFileName);
if FLastSearchTemplate.SearchRecord.Duplicates then
begin
AProperty:= TFileVariantProperty.Create(PluginDuplicate);
AProperty.Value:= IntPtr(lsFoundedFiles.Items.Objects[I]);
aFile.Properties[fpVariant]:= AProperty;
end;
FileList.AddSubNode(aFile);
except
on EFileNotFound do ;
@ -1705,6 +1761,27 @@ begin
// Add new tab for search results.
Notebook := frmMain.ActiveNotebook;
NewPage := Notebook.NewPage(Notebook.ActiveView);
if FLastSearchTemplate.SearchRecord.Duplicates then
begin
if not (NewPage.FileView is TColumnsFileView) then
begin
frmMain.Commands.cm_ColumnsView([]);
end;
ANewSet:= TPanelColumnsClass.Create;
DCFunc := '[' + sFuncTypeDC + '().%s{}]';
I:= Notebook.ActiveView.ClientWidth;
ANewSet.Add(rsFuncName, Format(DCFunc, [TFileFunctionStrings[fsfName]]), I * 40 div 100, taLeftJustify);
ANewSet.Add(rsFuncGroup, '[' + PluginDuplicate + ']', I * 20 div 100, taCenter);
ANewSet.Add(rsFuncPath, Format(DCFunc, [TFileFunctionStrings[fsfPath]]), I * 40 div 100, taLeftJustify);
TColumnsFileView(NewPage.FileView).isSlave:= True;
TColumnsFileView(NewPage.FileView).ActiveColmSlave:= ANewSet;
TColumnsFileView(NewPage.FileView).UpdateColumnsView;
end;
NewPage.FileView.AddFileSource(SearchResultFS, SearchResultFS.GetRootDir);
NewPage.FileView.FlatView := True;
NewPage.MakeActive;
@ -1882,6 +1959,20 @@ begin
Caption := sBuildingCaptionName;
end;
function TfrmFindDlg.ObjectType(Index: Integer): TCheckBoxState;
var
ATemp: TObject;
AValue: PtrInt absolute ATemp;
begin
ATemp:= lsFoundedFiles.Items.Objects[Index];
if (ATemp) = nil then
Result:= cbUnchecked
else if (AValue = High(PtrInt)) then
Result:= cbChecked
else
Result:= cbGrayed;
end;
function TfrmFindDlg.GetFileMask: String;
begin
if Length(cmbFindFileMask.Text) = 0 then
@ -2061,6 +2152,11 @@ begin
cbNotContainingText.Checked := NotContainingText;
cbTextRegExp.Checked := TextRegExp;
cmbEncoding.Text := TextEncoding;
// duplicates
chkDuplicates.Checked := Duplicates;
chkDuplicateName.Checked := DuplicateName;
chkDuplicateSize.Checked := DuplicateSize;
chkDuplicateContent.Checked := DuplicateContent;
// plugins
cmbPlugin.Text := SearchPlugin;
frmContentPlugins.Load(Template);
@ -2410,8 +2506,8 @@ procedure TfrmFindDlg.PopupMenuFindPopup(Sender: TObject);
begin
if (lsFoundedFiles.ItemIndex <> -1) then
begin
miShowInViewer.Enabled:= (lsFoundedFiles.Items.Objects[lsFoundedFiles.ItemIndex] = nil);
miShowInEditor.Enabled:= (lsFoundedFiles.Items.Objects[lsFoundedFiles.ItemIndex] = nil);
miShowInViewer.Enabled:= (ObjectType(lsFoundedFiles.ItemIndex) <> cbChecked);
miShowInEditor.Enabled:= (ObjectType(lsFoundedFiles.ItemIndex) <> cbChecked);
end;
end;

View file

@ -778,6 +778,11 @@ procedure TColumnsFileView.SetColumnSet(const AName: String);
begin
if ColSet.Items.IndexOf(AName) >= 0 then
begin
if Assigned(ActiveColmSlave) then
begin
isSlave:= False;
FreeAndNil(ActiveColmSlave);
end;
ActiveColm:= AName;
UpdateColumnsView;
RedrawFiles;
@ -794,6 +799,11 @@ begin
else
begin
ActiveColm:=ColSet.Items[(Sender as TMenuItem).Tag];
if Assigned(ActiveColmSlave) then
begin
isSlave:= False;
FreeAndNil(ActiveColmSlave);
end;
UpdateColumnsView;
RedrawFiles;
end;