doublecmd/src/fmultirename.pas
2026-05-08 20:00:35 +03:00

3085 lines
106 KiB
ObjectPascal

{
Double Commander
-------------------------------------------------------------------------
Multi-Rename Tool dialog window
Copyright (C) 2007-2025 Alexander Koblov (alexx2000@mail.ru)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Original comment:
----------------------------
Seksi Commander
----------------------------
Licence : GNU GPL v 2.0
Author : Pavel Letko (letcuv@centrum.cz)
Advanced multi rename tool
contributors:
Copyright (C) 2007-2018 Alexander Koblov (alexx2000@mail.ru)
}
unit fMultiRename;
{$mode objfpc}{$H+}
interface
uses
//Lazarus, Free-Pascal, etc.
LazUtf8, SysUtils, Classes, Graphics, Forms, StdCtrls, Menus, Controls,
LCLType, StringHashList, Grids, ExtCtrls, Buttons, ActnList, EditBtn,
KASButton, KASToolPanel,
//DC
DCXmlConfig, uOSForms, uRegExprW, uFileProperty, uFormCommands,
uFileSourceSetFilePropertyOperation, DCStringHashListUtf8, uClassesEx, uFile,
uFileSource, DCClassesUtf8, uHotkeyManager;
const
HotkeysCategoryMultiRename = 'MultiRename'; // <--Not displayed to user, stored in .scf (Shortcut Configuration File)
type
{ TMultiRenamePreset }
TMultiRenamePreset = class(TObject)
private
FPresetName: string;
FFileName: string;
FExtension: string;
FFileNameStyle: integer;
FExtensionStyle: integer;
FFind: string;
FReplace: string;
FRepExt: Boolean;
FRegExp: boolean;
FUseSubs: boolean;
FCaseSens: Boolean;
FOnlyFirst: Boolean;
FCounter: string;
FInterval: string;
FWidth: integer;
FLog: boolean;
FLogFile: string;
FLogAppend: boolean;
public
property PresetName: string read FPresetName write FPresetName;
property FileName: string read FFileName write FFileName;
property Extension: string read FExtension write FExtension;
property FileNameStyle: integer read FFileNameStyle write FFileNameStyle;
property ExtensionStyle: integer read FExtensionStyle write FExtensionStyle;
property Find: string read FFind write FFind;
property Replace: string read FReplace write FReplace;
property RepExt: boolean read FRepExt write FRepExt;
property RegExp: boolean read FRegExp write FRegExp;
property UseSubs: boolean read FUseSubs write FUseSubs;
property CaseSens: Boolean read FCaseSens write FCaseSens;
property OnlyFirst: Boolean read FOnlyFirst write FOnlyFirst;
property Counter: string read FCounter write FCounter;
property Interval: string read FInterval write FInterval;
property Width: integer read FWidth write FWidth;
property Log: boolean read FLog write FLog;
property LogFile: string read FLogFile write FLogFile;
property LogAppend: boolean read FLogAppend write FLogAppend;
constructor Create;
destructor Destroy; override;
end;
{ TMultiRenamePresetList }
TMultiRenamePresetList = class(TList)
private
function GetMultiRenamePreset(Index: integer): TMultiRenamePreset;
public
property MultiRenamePreset[Index: integer]: TMultiRenamePreset read GetMultiRenamePreset;
procedure Delete(Index: integer);
procedure Clear; override;
function Find(sPresetName: string): integer;
end;
{ tTargetForMask }
//Used to indicate of a mask is used for the "Filename" or the "Extension".
tTargetForMask = (tfmFilename, tfmExtension);
{ tRenameMaskToUse }
//Used as a parameter type to indicate the kind of field the mask is related to.
tRenameMaskToUse = (rmtuFilename, rmtuExtension, rmtuCounter, rmtuDate, rmtuTime, rmtuPlugins);
{ tSourceOfInformation }
tSourceOfInformation = (soiFilename, soiExtension, soiCounter, soiGUID, soiVariable, soiDate, soiTime, soiPlugins, soiFullName, soiPath);
{ tMenuActionStyle }
//Used to help to group common or similar action done for each mask.
tMenuActionStyle = (masStraight, masXCharacters, masXYCharacters, masAskVariable, masDirectorySelector);
{ TfrmMultiRename }
TfrmMultiRename = class(TAloneForm, IFormCommands)
cbCaseSens: TCheckBox;
cbRegExp: TCheckBox;
cbUseSubs: TCheckBox;
cbOnlyFirst: TCheckBox;
cbRepExt: TCheckBox;
pnlFindReplace: TPanel;
pnlButtons: TPanel;
StringGrid: TStringGrid;
pnlOptions: TPanel;
pnlOptionsLeft: TPanel;
gbMaska: TGroupBox;
lbName: TLabel;
cbName: TComboBox;
btnAnyNameMask: TKASButton;
cbNameMaskStyle: TComboBox;
lbExt: TLabel;
cbExt: TComboBox;
btnAnyExtMask: TKASButton;
cmbExtensionStyle: TComboBox;
gbPresets: TGroupBox;
cbPresets: TComboBox;
btnPresets: TKASButton;
spltMainSplitter: TSplitter;
pnlOptionsRight: TKASToolPanel;
gbFindReplace: TGroupBox;
lbFind: TLabel;
edFind: TEdit;
lbReplace: TLabel;
edReplace: TEdit;
gbCounter: TGroupBox;
lbStNb: TLabel;
edPoc: TEdit;
lbInterval: TLabel;
edInterval: TEdit;
lbWidth: TLabel;
cmbxWidth: TComboBox;
btnRestore: TBitBtn;
btnRename: TBitBtn;
btnConfig: TBitBtn;
btnEditor: TBitBtn;
btnClose: TBitBtn;
cbLog: TCheckBox;
cbLogAppend: TCheckBox;
fneRenameLogFileFilename: TFileNameEdit;
btnRelativeRenameLogFile: TSpeedButton;
btnViewRenameLogFile: TSpeedButton;
mmMainMenu: TMainMenu;
miActions: TMenuItem;
miResetAll: TMenuItem;
miEditor: TMenuItem;
miLoadNamesFromFile: TMenuItem;
miEditNames: TMenuItem;
miEditNewNames: TMenuItem;
miSeparator1: TMenuItem;
miConfiguration: TMenuItem;
miSeparator2: TMenuItem;
miRename: TMenuItem;
miClose: TMenuItem;
pmPresets: TPopupMenu;
pmFloatingMainMaskMenu: TPopupMenu;
pmDynamicMasks: TPopupMenu;
pmEditDirect: TPopupMenu;
mnuLoadFromFile: TMenuItem;
mnuEditNames: TMenuItem;
mnuEditNewNames: TMenuItem;
pmPathToBeRelativeToHelper: TPopupMenu;
actList: TActionList;
actResetAll: TAction;
actInvokeEditor: TAction;
actLoadNamesFromFile: TAction;
actLoadNamesFromClipboard: TAction;
actEditNames: TAction;
actEditNewNames: TAction;
actConfig: TAction;
actRename: TAction;
actClose: TAction;
actShowPresetsMenu: TAction;
actDropDownPresetList: TAction;
actLoadLastPreset: TAction;
actLoadPreset: TAction;
actLoadPreset1: TAction;
actLoadPreset2: TAction;
actLoadPreset3: TAction;
actLoadPreset4: TAction;
actLoadPreset5: TAction;
actLoadPreset6: TAction;
actLoadPreset7: TAction;
actLoadPreset8: TAction;
actLoadPreset9: TAction;
actSavePreset: TAction;
actSavePresetAs: TAction;
actRenamePreset: TAction;
actDeletePreset: TAction;
actSortPresets: TAction;
actAnyNameMask: TAction;
actNameNameMask: TAction;
actExtNameMask: TAction;
actDateNameMask: TAction;
actTimeNameMask: TAction;
actCtrNameMask: TAction;
actPlgnNameMask: TAction;
actClearNameMask: TAction;
actAnyExtMask: TAction;
actNameExtMask: TAction;
actExtExtMask: TAction;
actDateExtMask: TAction;
actTimeExtMask: TAction;
actCtrExtMask: TAction;
actPlgnExtMask: TAction;
actClearExtMask: TAction;
actInvokeRelativePath: TAction;
actViewRenameLogFile: TAction;
procedure FormCreate({%H-}Sender: TObject);
procedure FormCloseQuery({%H-}Sender: TObject; var CanClose: boolean);
procedure FormClose({%H-}Sender: TObject; var CloseAction: TCloseAction);
procedure FormShow(Sender: TObject);
procedure StringGridKeyDown({%H-}Sender: TObject; var Key: word; Shift: TShiftState);
procedure StringGridMouseDown({%H-}Sender: TObject; Button: TMouseButton; {%H-}Shift: TShiftState; X, Y: integer);
procedure StringGridMouseUp({%H-}Sender: TObject; Button: TMouseButton; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: integer);
procedure StringGridSelection({%H-}Sender: TObject; {%H-}aCol, aRow: integer);
procedure StringGridTopLeftChanged({%H-}Sender: TObject);
procedure cbNameStyleChange({%H-}Sender: TObject);
procedure cbPresetsChange({%H-}Sender: TObject);
procedure cbPresetsCloseUp({%H-}Sender: TObject);
procedure edFindChange({%H-}Sender: TObject);
procedure edReplaceChange({%H-}Sender: TObject);
procedure cbRegExpChange({%H-}Sender: TObject);
procedure edPocChange({%H-}Sender: TObject);
procedure edIntervalChange({%H-}Sender: TObject);
procedure cbLogClick({%H-}Sender: TObject);
procedure actExecute(Sender: TObject);
procedure actInvokeRelativePathExecute(Sender: TObject);
private
IniPropStorage: TIniPropStorageEx;
FCommands: TFormCommands;
FActuallyRenamingFile: boolean;
FSourceRow: integer;
FMoveRow: boolean;
FFileSource: IFileSource;
FFiles: TFiles;
FNewNames: TStringHashListUtf8;
FOldNames: TStringHashListUtf8;
FNames: TStringList;
FslVariableNames, FslVariableValues, FslVariableSuggestionName, FslVariableSuggestionValue: TStringList;
FRegExp: TRegExprW;
FFindText: TStringList;
FReplaceText: TStringList;
FPluginDispatcher: tTargetForMask;
FMultiRenamePresetList: TMultiRenamePresetList;
FParamPresetToLoadOnStart: string;
FLastPreset: string;
FbRememberLog, FbRememberAppend: boolean;
FsRememberRenameLogFilename: string;
FLog: TStringListEx;
property Commands: TFormCommands read FCommands implements IFormCommands;
procedure RestoreProperties(Sender: TObject);
procedure SetConfigurationState(bConfigurationSaved: boolean);
function GetPresetNameForCommand(const Params: array of string): string;
procedure LoadPresetsXml(AConfig: TXmlConfig);
function isOkToLosePresetModification: boolean;
procedure SavePreset(PresetName: string);
procedure SavePresetsXml(AConfig: TXmlConfig);
procedure SavePresets;
procedure DeletePreset(PresetName: string);
procedure FillPresetsList(const WantedSelectedPresetName: string = '');
procedure RefreshActivePresetCommands;
procedure InitializeMaskHelper;
procedure PopulateMainMenu;
procedure PopulateFilenameMenu(AMenuSomething: TComponent);
procedure PopulateExtensionMenu(AMenuSomething: TComponent);
procedure BuildMaskMenu(AMenuSomething: TComponent; iTarget: tTargetForMask; iMenuTypeMask: tRenameMaskToUse);
procedure BuildPresetsMenu(AMenuSomething: TComponent);
procedure BuildMenuAndPopup(iTarget: tTargetForMask; iMenuTypeMask: tRenameMaskToUse);
function GetMaskCategoryName(aRenameMaskToUse: tRenameMaskToUse): string;
function GetImageIndexCategoryName(aRenameMaskToUse: tRenameMaskToUse): integer;
function GetCategoryAction(TargetForMask: tTargetForMask; aRenameMask: tRenameMaskToUse): TAction;
function AppendSubMenuToThisMenu(ATargetMenu: TMenuItem; sCaption: string; iImageIndex: integer): TMenuItem;
function AppendActionMenuToThisMenu(ATargetMenu: TMenuItem; paramAction: TAction): TMenuItem;
procedure MenuItemXCharactersMaskClick(Sender: TObject);
procedure MenuItemVariableMaskClick(Sender: TObject);
procedure MenuItemStraightMaskClick(Sender: TObject);
procedure MenuItemDirectorySelectorMaskClick(Sender: TObject);
procedure PopupDynamicMenuAtThisControl(APopUpMenu: TPopupMenu; AControl: TControl);
procedure miPluginClick(Sender: TObject);
procedure InsertMask(const Mask: string; edChoose: TComboBox);
procedure InsertMask(const Mask: string; TargetForMask: tTargetForMask);
function sReplace(sMask: string; ItemNr: integer): string;
function sReplaceXX(const sFormatStr, sOrig: string): string;
function sReplaceVariable(const sFormatStr: string): string;
function sReplaceBadChars(const sPath: string): string;
function IsLetter(AChar: AnsiChar): boolean;
function ApplyStyle(InputString: string; Style: integer): string;
function FirstCharToUppercaseUTF8(InputString: string): string;
function FirstCharOfFirstWordToUppercaseUTF8(InputString: string): string;
function FirstCharOfEveryWordToUppercaseUTF8(InputString: string): string;
procedure LoadNamesFromList(const AFileList: TStrings);
procedure LoadNamesFromFile(const AFileName: string);
function FreshText(ItemIndex: integer): string;
function sHandleFormatString(const sFormatStr: string; ItemNr: integer): string;
procedure SetFilePropertyResult(Index: integer; aFile: TFile; aTemplate: TFileProperty; Result: TSetFilePropertyResult);
procedure SetOutputGlobalRenameLogFilename;
public
{ Public declarations }
constructor Create(TheOwner: TComponent); override; //Not used for actual renaming file. Present there just for the "TfrmOptionsHotkeys.FillCommandList" function who need to create the form in memory to extract internal commands from it.
constructor Create(TheOwner: TComponent; aFileSource: IFileSource; var aFiles: TFiles; const paramPreset: string); reintroduce;
destructor Destroy; override;
published
procedure cm_ResetAll(const Params: array of string);
procedure cm_InvokeEditor(const {%H-}Params: array of string);
procedure cm_LoadNamesFromFile(const {%H-}Params: array of string);
procedure cm_LoadNamesFromClipboard(const {%H-}Params: array of string);
procedure cm_EditNames(const {%H-}Params: array of string);
procedure cm_EditNewNames(const {%H-}Params: array of string);
procedure cm_Config(const {%H-}Params: array of string);
procedure cm_Rename(const {%H-}Params: array of string);
procedure cm_Close(const {%H-}Params: array of string);
procedure cm_ShowPresetsMenu(const {%H-}Params: array of string);
procedure cm_DropDownPresetList(const {%H-}Params: array of string);
procedure cm_LoadPreset(const Params: array of string);
procedure cm_LoadLastPreset(const {%H-}Params: array of string);
procedure cm_LoadPreset1(const {%H-}Params: array of string);
procedure cm_LoadPreset2(const {%H-}Params: array of string);
procedure cm_LoadPreset3(const {%H-}Params: array of string);
procedure cm_LoadPreset4(const {%H-}Params: array of string);
procedure cm_LoadPreset5(const {%H-}Params: array of string);
procedure cm_LoadPreset6(const {%H-}Params: array of string);
procedure cm_LoadPreset7(const {%H-}Params: array of string);
procedure cm_LoadPreset8(const {%H-}Params: array of string);
procedure cm_LoadPreset9(const {%H-}Params: array of string);
procedure cm_SavePreset(const Params: array of string);
procedure cm_SavePresetAs(const Params: array of string);
procedure cm_RenamePreset(const Params: array of string);
procedure cm_DeletePreset(const Params: array of string);
procedure cm_SortPresets(const Params: array of string);
procedure cm_AnyNameMask(const {%H-}Params: array of string);
procedure cm_NameNameMask(const {%H-}Params: array of string);
procedure cm_ExtNameMask(const {%H-}Params: array of string);
procedure cm_CtrNameMask(const {%H-}Params: array of string);
procedure cm_DateNameMask(const {%H-}Params: array of string);
procedure cm_TimeNameMask(const {%H-}Params: array of string);
procedure cm_PlgnNameMask(const {%H-}Params: array of string);
procedure cm_ClearNameMask(const {%H-}Params: array of string);
procedure cm_AnyExtMask(const {%H-}Params: array of string);
procedure cm_NameExtMask(const {%H-}Params: array of string);
procedure cm_ExtExtMask(const {%H-}Params: array of string);
procedure cm_CtrExtMask(const {%H-}Params: array of string);
procedure cm_DateExtMask(const {%H-}Params: array of string);
procedure cm_TimeExtMask(const {%H-}Params: array of string);
procedure cm_PlgnExtMask(const {%H-}Params: array of string);
procedure cm_ClearExtMask(const {%H-}Params: array of string);
procedure cm_ViewRenameLogFile(const {%H-}Params: array of string);
end;
{initialization function}
function ShowMultiRenameForm(aFileSource: IFileSource; var aFiles: TFiles; const PresetToLoad: string = ''): boolean;
implementation
{$R *.lfm}
uses
//Lazarus, Free-Pascal, etc.
Dialogs, Math, Clipbrd,
//DC
fMain, uFileSourceOperation, uOperationsManager, uOSUtils, uDCUtils, uDebug,
DCOSUtils, DCStrUtils, uLng, uGlobs, uSpecialDir, uFileProcs, uShowForm,
fSelectTextRange, fSelectPathRange, uShowMsg, uFileFunctions, dmCommonData,
fMultiRenameWait, fSortAnything, DCConvertEncoding;
type
tMaskHelper = record
sMenuItem: string;
sKeyword: string;
MenuActionStyle: tMenuActionStyle;
iMenuType: tRenameMaskToUse;
iSourceOfInformation: tSourceOfInformation;
end;
const
sPresetsSection = 'MultiRenamePresets';
sLASTPRESET = '{BC322BF1-2185-47F6-9F99-D27ED1E23E53}';
sFRESHMASKS = '{40422152-9D05-469E-9B81-791AF8C369D8}';
iTARGETMASK = $00000001;
sREFRESHCOMMANDS = 'refreshcommands';
sDEFAULTLOGFILENAME = 'default.log';
CONFIG_NOTSAVED = False;
CONFIG_SAVED = True;
NBMAXHELPERS = 30;
var
//Sequence of operation to add a new mask:
// 1. Add its entry below in the "MaskHelpers" array.
// 2. Go immediately set its translatable string for the user in the function "InitializeMaskHelper" and the text in unit "uLng".
// 3. When editing "InitializeMaskHelper", make sure to update the TWO columns of indexes.
// 4. In the procedure "BuildMaskMenu", there is good chance you need to associated to the "AMenuItem.OnClick" the correct function based on "MaskHelpers[iSeekIndex].MenuActionStyle".
// 5. If it's a NEW procedure, you'll need to write it. You may check "MenuItemXCharactersMaskClick" for inspiration.
// 6. There is good chance you need to edit "sHandleFormatString" to add your new mask and action to do with it.
MaskHelpers: array[0..pred(NBMAXHELPERS)] of tMaskHelper =
(
(sMenuItem: ''; sKeyword: '[N]'; MenuActionStyle: masStraight; iMenuType: rmtuFilename; iSourceOfInformation: soiFilename),
(sMenuItem: ''; sKeyword: '[Nx]'; MenuActionStyle: masXCharacters; iMenuType: rmtuFilename; iSourceOfInformation: soiFilename),
(sMenuItem: ''; sKeyword: '[Nx:y]'; MenuActionStyle: masXYCharacters; iMenuType: rmtuFilename; iSourceOfInformation: soiFilename),
(sMenuItem: ''; sKeyword: '[A]'; MenuActionStyle: masStraight; iMenuType: rmtuFilename; iSourceOfInformation: soiFullName),
(sMenuItem: ''; sKeyword: '[Ax:y]'; MenuActionStyle: masXYCharacters; iMenuType: rmtuFilename; iSourceOfInformation: soiFullName),
(sMenuItem: ''; sKeyword: '[P]'; MenuActionStyle: masDirectorySelector; iMenuType: rmtuFilename; iSourceOfInformation: soiPath),
(sMenuItem: ''; sKeyword: '[E]'; MenuActionStyle: masStraight; iMenuType: rmtuExtension; iSourceOfInformation: soiExtension),
(sMenuItem: ''; sKeyword: '[Ex]'; MenuActionStyle: masXCharacters; iMenuType: rmtuExtension; iSourceOfInformation: soiExtension),
(sMenuItem: ''; sKeyword: '[Ex:y]'; MenuActionStyle: masXYCharacters; iMenuType: rmtuExtension; iSourceOfInformation: soiExtension),
(sMenuItem: ''; sKeyword: '[C]'; MenuActionStyle: masStraight; iMenuType: rmtuCounter; iSourceOfInformation: soiCounter),
(sMenuItem: ''; sKeyword: '[G]'; MenuActionStyle: masStraight; iMenuType: rmtuCounter; iSourceOfInformation: soiGUID),
(sMenuItem: ''; sKeyword: '[V:x]'; MenuActionStyle: masAskVariable; iMenuType: rmtuCounter; iSourceOfInformation: soiVariable),
(sMenuItem: ''; sKeyword: '[Y]'; MenuActionStyle: masStraight; iMenuType: rmtuDate; iSourceOfInformation: soiDate),
(sMenuItem: ''; sKeyword: '[YYYY]'; MenuActionStyle: masStraight; iMenuType: rmtuDate; iSourceOfInformation: soiDate),
(sMenuItem: ''; sKeyword: '[M]'; MenuActionStyle: masStraight; iMenuType: rmtuDate; iSourceOfInformation: soiDate),
(sMenuItem: ''; sKeyword: '[MM]'; MenuActionStyle: masStraight; iMenuType: rmtuDate; iSourceOfInformation: soiDate),
(sMenuItem: ''; sKeyword: '[MMM]'; MenuActionStyle: masStraight; iMenuType: rmtuDate; iSourceOfInformation: soiDate),
(sMenuItem: ''; sKeyword: '[MMMM]'; MenuActionStyle: masStraight; iMenuType: rmtuDate; iSourceOfInformation: soiDate),
(sMenuItem: ''; sKeyword: '[D]'; MenuActionStyle: masStraight; iMenuType: rmtuDate; iSourceOfInformation: soiDate),
(sMenuItem: ''; sKeyword: '[DD]'; MenuActionStyle: masStraight; iMenuType: rmtuDate; iSourceOfInformation: soiDate),
(sMenuItem: ''; sKeyword: '[DDD]'; MenuActionStyle: masStraight; iMenuType: rmtuDate; iSourceOfInformation: soiDate),
(sMenuItem: ''; sKeyword: '[DDDD]'; MenuActionStyle: masStraight; iMenuType: rmtuDate; iSourceOfInformation: soiDate),
(sMenuItem: ''; sKeyword: '[YYYY]-[MM]-[DD]'; MenuActionStyle: masStraight; iMenuType: rmtuDate; iSourceOfInformation: soiDate),
(sMenuItem: ''; sKeyword: '[h]'; MenuActionStyle: masStraight; iMenuType: rmtuTime; iSourceOfInformation: soiTime),
(sMenuItem: ''; sKeyword: '[hh]'; MenuActionStyle: masStraight; iMenuType: rmtuTime; iSourceOfInformation: soiTime),
(sMenuItem: ''; sKeyword: '[n]'; MenuActionStyle: masStraight; iMenuType: rmtuTime; iSourceOfInformation: soiTime),
(sMenuItem: ''; sKeyword: '[nn]'; MenuActionStyle: masStraight; iMenuType: rmtuTime; iSourceOfInformation: soiTime),
(sMenuItem: ''; sKeyword: '[s]'; MenuActionStyle: masStraight; iMenuType: rmtuTime; iSourceOfInformation: soiTime),
(sMenuItem: ''; sKeyword: '[ss]'; MenuActionStyle: masStraight; iMenuType: rmtuTime; iSourceOfInformation: soiTime),
(sMenuItem: ''; sKeyword: '[hh]-[nn]-[ss]'; MenuActionStyle: masStraight; iMenuType: rmtuTime; iSourceOfInformation: soiTime)
);
{ TMultiRenamePreset.Create }
constructor TMultiRenamePreset.Create;
begin
FPresetName := '';
FFileName := '[N]';
FExtension := '[E]';
FFileNameStyle := 0;
FExtensionStyle := 0;
FFind := '';
FReplace := '';
FRepExt := True;
FRegExp := False;
FUseSubs := False;
FCaseSens := False;
FOnlyFirst := False;
FCounter := '1';
FInterval := '1';
FWidth := 0;
FLog := False;
FLogFile := '';
FLogAppend := False;
end;
{ TMultiRenamePreset.Destory }
// Not so necessary, but useful with a breakpoint to validate object is really free from memory when deleting an element from the list of clearing that list.
destructor TMultiRenamePreset.Destroy;
begin
inherited Destroy;
end;
{ TMultiRenamePresetList.GetMultiRenamePreset }
function TMultiRenamePresetList.GetMultiRenamePreset(Index: integer): TMultiRenamePreset;
begin
Result := TMultiRenamePreset(Items[Index]);
end;
{ TMultiRenamePresetList.Delete }
procedure TMultiRenamePresetList.Delete(Index: integer);
begin
TMultiRenamePreset(Items[Index]).Free;
inherited Delete(Index);
end;
{ TMultiRenamePresetList.Clear }
procedure TMultiRenamePresetList.Clear;
var
Index: integer;
begin
for Index := pred(Count) downto 0 do
TMultiRenamePreset(Items[Index]).Free;
inherited Clear;
end;
{ TMultiRenamePresetList.Find }
function TMultiRenamePresetList.Find(sPresetName: string): integer;
var
iSeeker: integer = 0;
begin
Result := -1;
while (Result = -1) and (iSeeker < Count) do
if SameText(sPresetName, MultiRenamePreset[iSeeker].PresetName) then
Result := iSeeker
else
Inc(iSeeker);
end;
{ TfrmMultiRename.Create }
//Not used for actual renaming file.
//Present there just for the "TfrmOptionsHotkeys.FillCommandList" function who need to create the form in memory to extract internal commands from it.
constructor TfrmMultiRename.Create(TheOwner: TComponent);
var
FDummyFiles: TFiles;
begin
FDummyFiles := TFiles.Create(''); //Will be self destroyed by the "TfrmMultiRename" object itself.
Create(TheOwner, nil, FDummyFiles, '');
end;
{ TfrmMultiRename.Create }
constructor TfrmMultiRename.Create(TheOwner: TComponent; aFileSource: IFileSource; var aFiles: TFiles; const paramPreset: string);
begin
FActuallyRenamingFile := False;
FRegExp := TRegExprW.Create;
FNames := TStringList.Create;
FFindText := TStringList.Create;
FFindText.StrictDelimiter := True;
FFindText.Delimiter := '|';
FReplaceText := TStringList.Create;
FReplaceText.StrictDelimiter := True;
FReplaceText.Delimiter := '|';
FMultiRenamePresetList := TMultiRenamePresetList.Create;
FNewNames := TStringHashListUtf8.Create(FileNameCaseSensitive);
FOldNames := TStringHashListUtf8.Create(FileNameCaseSensitive);
FslVariableNames := TStringList.Create;
FslVariableValues := TStringList.Create;
FslVariableSuggestionName := TStringList.Create;
FslVariableSuggestionValue := TStringList.Create;
FFileSource := aFileSource;
FFiles := aFiles;
aFiles := nil;
FSourceRow := -1;
FMoveRow := False;
FParamPresetToLoadOnStart := paramPreset;
inherited Create(TheOwner);
FCommands := TFormCommands.Create(Self, actList);
end;
{ TfrmMultiRename.Destroy }
destructor TfrmMultiRename.Destroy;
begin
inherited Destroy;
FMultiRenamePresetList.Clear;
FreeAndNil(FMultiRenamePresetList);
FreeAndNil(FNewNames);
FreeAndNil(FOldNames);
FreeAndNil(FslVariableNames);
FreeAndNil(FslVariableValues);
FreeAndNil(FslVariableSuggestionName);
FreeAndNil(FslVariableSuggestionValue);
FreeAndNil(FFiles);
FreeAndNil(FNames);
FreeAndNil(FRegExp);
FreeAndNil(FFindText);
FreeAndNil(FReplaceText);
end;
{ TfrmMultiRename.FormCreate }
procedure TfrmMultiRename.FormCreate({%H-}Sender: TObject);
var
HMMultiRename: THMForm;
begin
// Localize File name style ComboBox
ParseLineToList(rsMulRenFileNameStyleList, cbNameMaskStyle.Items);
ParseLineToList(rsMulRenFileNameStyleList, cmbExtensionStyle.Items);
InitializeMaskHelper;
// Set row count
StringGrid.RowCount := FFiles.Count + 1;
StringGrid.FocusRectVisible := False;
// Initialize property storage
IniPropStorage := InitPropStorage(Self);
IniPropStorage.OnRestoreProperties := @RestoreProperties;
IniPropStorage.StoredValues.Add.DisplayName := 'lsvwFile_Columns.Item0_Width';
IniPropStorage.StoredValues.Add.DisplayName := 'lsvwFile_Columns.Item1_Width';
IniPropStorage.StoredValues.Add.DisplayName := 'lsvwFile_Columns.Item2_Width';
if gMulRenShowMenuBarOnTop then
Menu := mmMainMenu
else
Menu := nil;
if not gIconsInMenus then
begin
mmMainMenu.Images := nil;
pmDynamicMasks.Images := nil;
pmEditDirect.Images := nil;
pmPresets.Images := nil;
end;
HMMultiRename := HotMan.Register(Self, HotkeysCategoryMultiRename);
HMMultiRename.RegisterActionList(actList);
cbExt.Items.Assign(glsRenameExtMaskHistory);
cbName.Items.Assign(glsRenameNameMaskHistory);
// Set default values for controls.
cm_ResetAll([sREFRESHCOMMANDS + '=0']);
// Initialize presets.
LoadPresetsXml(gConfig);
if (FParamPresetToLoadOnStart <> '') and (FMultiRenamePresetList.Find(FParamPresetToLoadOnStart) <> -1) then
begin
FillPresetsList(FParamPresetToLoadOnStart);
end
else
begin
case gMulRenLaunchBehavior of
mrlbLastMaskUnderLastOne: FillPresetsList(sLASTPRESET);
mrlbLastPreset: FillPresetsList(FLastPreset);
mrlbFreshNew: FillPresetsList(sFRESHMASKS);
end;
end;
PopulateMainMenu;
gSpecialDirList.PopulateMenuWithSpecialDir(pmPathToBeRelativeToHelper, mp_PATHHELPER, nil);
FPluginDispatcher := tfmFilename;
end;
{ TfrmMultiRename.FormCloseQuery }
procedure TfrmMultiRename.FormCloseQuery(Sender: TObject; var CanClose: boolean);
begin
if not isOkToLosePresetModification then
CanClose := False;
end;
{ TfrmMultiRename.FormClose }
procedure TfrmMultiRename.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
SavePreset(sLASTPRESET);
glsRenameExtMaskHistory.Assign(cbExt.Items);
glsRenameNameMaskHistory.Assign(cbName.Items);
CloseAction := caFree;
with StringGrid.Columns do
begin
IniPropStorage.StoredValue['lsvwFile_Columns.Item0_Width'] := IntToStr(Items[0].Width);
IniPropStorage.StoredValue['lsvwFile_Columns.Item1_Width'] := IntToStr(Items[1].Width);
IniPropStorage.StoredValue['lsvwFile_Columns.Item2_Width'] := IntToStr(Items[2].Width);
end;
end;
procedure TfrmMultiRename.FormShow(Sender: TObject);
var
APoint: TPoint;
begin
{$IF DEFINED(LCLQT5)}
gbPresets.Constraints.MaxHeight:= cbPresets.Height + (gbPresets.Height - gbPresets.ClientHeight) +
gbPresets.ChildSizing.TopBottomSpacing * 2;
{$ENDIF}
APoint:= TPoint.Create(cbUseSubs.Left, 0);
fneRenameLogFileFilename.BorderSpacing.Left:= gbFindReplace.ClientToParent(APoint, pnlOptionsRight).X;
end;
{ TfrmMultiRename.StringGridKeyDown }
procedure TfrmMultiRename.StringGridKeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
var
tmpFile: TFile;
DestRow: integer;
begin
DestRow := StringGrid.Row;
if (Shift = []) then
begin
if Key = VK_DELETE then
begin
FFiles.Delete(DestRow - 1);
StringGrid.RowCount:= StringGrid.RowCount - 1;
if FFiles.Count = 0 then
begin
OnCloseQuery:= nil;
Close;
end
else begin
StringGridTopLeftChanged(StringGrid);
end;
end;
end;
if (Shift = [ssShift]) then
begin
case Key of
VK_UP:
begin
DestRow := StringGrid.Row - 1;
end;
VK_DOWN:
begin
DestRow := StringGrid.Row + 1;
end;
end;
if (DestRow <> StringGrid.Row) and (0 < DestRow) and (DestRow < StringGrid.RowCount) then
begin
tmpFile := FFiles.Items[DestRow - 1];
FFiles.Items[DestRow - 1] := FFiles.Items[StringGrid.Row - 1];
FFiles.Items[StringGrid.Row - 1] := tmpFile;
StringGridTopLeftChanged(StringGrid);
end;
end;
end;
{ TfrmMultiRename.StringGridMouseDown }
procedure TfrmMultiRename.StringGridMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
var
SourceCol: integer = 0;
begin
if (Button = mbLeft) then
begin
StringGrid.MouseToCell(X, Y, SourceCol, FSourceRow);
if (FSourceRow > 0) then
begin
FMoveRow := True;
end;
end;
end;
{ TfrmMultiRename.StringGridMouseUp }
procedure TfrmMultiRename.StringGridMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
begin
if Button = mbLeft then
begin
FMoveRow := False;
end;
end;
{ TfrmMultiRename.StringGridSelection }
procedure TfrmMultiRename.StringGridSelection(Sender: TObject; aCol, aRow: integer);
var
tmpFile: TFile;
begin
if FMoveRow and (aRow <> FSourceRow) then
begin
tmpFile := FFiles.Items[aRow - 1];
FFiles.Items[aRow - 1] := FFiles.Items[FSourceRow - 1];
FFiles.Items[FSourceRow - 1] := tmpFile;
FSourceRow := aRow;
StringGridTopLeftChanged(StringGrid);
end;
end;
{ TfrmMultiRename.StringGridTopLeftChanged }
procedure TfrmMultiRename.StringGridTopLeftChanged(Sender: TObject);
var
I, iRowCount: integer;
begin
iRowCount := StringGrid.TopRow + StringGrid.VisibleRowCount;
if iRowCount > FFiles.Count then
iRowCount := FFiles.Count;
for I := StringGrid.TopRow to iRowCount do
begin
StringGrid.Cells[0, I] := FFiles[I - 1].Name;
StringGrid.Cells[1, I] := FreshText(I - 1);
StringGrid.Cells[2, I] := FFiles[I - 1].Path;
end;
end;
{ TfrmMultiRename.cbNameStyleChange }
procedure TfrmMultiRename.cbNameStyleChange(Sender: TObject);
begin
StringGridTopLeftChanged(StringGrid);
if ActiveControl <> cbPresets then
SetConfigurationState(CONFIG_NOTSAVED);
end;
{ TfrmMultiRename.cbPresetsChange }
procedure TfrmMultiRename.cbPresetsChange(Sender: TObject);
begin
if cbPresets.ItemIndex <> 0 then
cm_LoadPreset(['name=' + cbPresets.Items.Strings[cbPresets.ItemIndex]])
else
cm_LoadPreset(['name=' + sLASTPRESET]);
RefreshActivePresetCommands;
end;
{ TfrmMultiRename.cbPresetsCloseUp }
procedure TfrmMultiRename.cbPresetsCloseUp(Sender: TObject);
begin
if cbName.Enabled and gbMaska.Enabled then ActiveControl := cbName;
cbName.SelStart := UTF8Length(cbName.Text);
end;
{ TfrmMultiRename.edFindChange }
procedure TfrmMultiRename.edFindChange(Sender: TObject);
begin
if cbRegExp.Checked then
FRegExp.Expression := CeUtf8ToUtf16(edFind.Text)
else
begin
FFindText.DelimitedText := edFind.Text;
end;
SetConfigurationState(CONFIG_NOTSAVED);
StringGridTopLeftChanged(StringGrid);
end;
{ TfrmMultiRename.edReplaceChange }
procedure TfrmMultiRename.edReplaceChange(Sender: TObject);
begin
if not cbRegExp.Checked then
begin
FReplaceText.DelimitedText := edReplace.Text;
end;
SetConfigurationState(CONFIG_NOTSAVED);
StringGridTopLeftChanged(StringGrid);
end;
{ TfrmMultiRename.cbRegExpChange }
procedure TfrmMultiRename.cbRegExpChange(Sender: TObject);
begin
if cbRegExp.Checked then
cbUseSubs.Checked := boolean(cbUseSubs.Tag)
else
begin
cbUseSubs.Tag := integer(cbUseSubs.Checked);
cbUseSubs.Checked := False;
end;
cbUseSubs.Enabled := cbRegExp.Checked;
edFindChange(edFind);
edReplaceChange(edReplace);
end;
{ TfrmMultiRename.edPocChange }
procedure TfrmMultiRename.edPocChange(Sender: TObject);
var
c: integer;
begin
c := StrToIntDef(edPoc.Text, maxint);
if c = MaxInt then
with edPoc do //editbox only for numbers
begin
Text := '1';
SelectAll;
end;
SetConfigurationState(CONFIG_NOTSAVED);
StringGridTopLeftChanged(StringGrid);
end;
{ TfrmMultiRename.edIntervalChange }
procedure TfrmMultiRename.edIntervalChange(Sender: TObject);
var
c: integer;
begin
c := StrToIntDef(edInterval.Text, maxint);
if c = MaxInt then
with edInterval do //editbox only for numbers
begin
Text := '1';
SelectAll;
end;
SetConfigurationState(CONFIG_NOTSAVED);
StringGridTopLeftChanged(StringGrid);
end;
{ TfrmMultiRename.cbLogClick }
procedure TfrmMultiRename.cbLogClick(Sender: TObject);
begin
fneRenameLogFileFilename.Enabled := cbLog.Checked;
actInvokeRelativePath.Enabled := cbLog.Checked;
actViewRenameLogFile.Enabled := cbLog.Checked;
cbLogAppend.Enabled := cbLog.Checked;
SetConfigurationState(CONFIG_NOTSAVED);
end;
{ TfrmMultiRename.actExecute }
procedure TfrmMultiRename.actExecute(Sender: TObject);
var
cmd: string;
begin
cmd := (Sender as TAction).Name;
cmd := 'cm_' + Copy(cmd, 4, Length(cmd) - 3);
Commands.ExecuteCommand(cmd, []);
end;
{ TfrmMultiRename.actInvokeRelativePathExecute }
procedure TfrmMultiRename.actInvokeRelativePathExecute(Sender: TObject);
begin
fneRenameLogFileFilename.SetFocus;
gSpecialDirList.SetSpecialDirRecipientAndItsType(fneRenameLogFileFilename, pfFILE);
pmPathToBeRelativeToHelper.PopUp(Mouse.CursorPos.X, Mouse.CursorPos.Y);
end;
{ TfrmMultiRename.RestoreProperties }
procedure TfrmMultiRename.RestoreProperties(Sender: TObject);
begin
with StringGrid.Columns do
begin
Items[0].Width := StrToIntDef(IniPropStorage.StoredValue['lsvwFile_Columns.Item0_Width'], Items[0].Width);
Items[1].Width := StrToIntDef(IniPropStorage.StoredValue['lsvwFile_Columns.Item1_Width'], Items[1].Width);
Items[2].Width := StrToIntDef(IniPropStorage.StoredValue['lsvwFile_Columns.Item2_Width'], Items[2].Width);
end;
end;
{ TfrmMultiRename.SetConfigurationState }
procedure TfrmMultiRename.SetConfigurationState(bConfigurationSaved: boolean);
begin
if not cbPresets.DroppedDown then
begin
if bConfigurationSaved or (cbPresets.ItemIndex > 0) then
begin
if cbPresets.Enabled <> bConfigurationSaved then
begin
cbPresets.Enabled := bConfigurationSaved;
end;
end;
end;
end;
{ TfrmMultiRename.GetPresetNameForCommand }
// Wanted preset may be given via "name=presetname" or via "index=indexno".
function TfrmMultiRename.GetPresetNameForCommand(const Params: array of string): string;
var
Param, sValue: string;
iIndex: integer;
begin
Result := '';
for Param in Params do
begin
if GetParamValue(Param, 'name', sValue) then
Result := sValue
else
if GetParamValue(Param, 'index', sValue) then
begin
iIndex := StrToIntDef(sValue, -1);
if (iIndex >= 0) and (iIndex < cbPresets.items.Count) then
if iIndex = 0 then
Result := sLASTPRESET
else
Result := cbPresets.Items.Strings[iIndex];
end;
end;
end;
{ TfrmMultiRename.LoadPresetsXml }
procedure TfrmMultiRename.LoadPresetsXml(AConfig: TXmlConfig);
var
PresetName: string;
AMultiRenamePreset: TMultiRenamePreset;
ANode: TXmlNode;
PresetIndex: integer;
begin
FMultiRenamePresetList.Clear;
ANode := AConfig.FindNode(AConfig.RootNode, sPresetsSection);
FLastPreset := AConfig.GetValue(ANode, 'LastPreset', sLASTPRESET);
ANode := AConfig.FindNode(ANode, 'Presets');
if Assigned(ANode) then
begin
ANode := ANode.FirstChild;
while Assigned(ANode) do
begin
if ANode.CompareName('Preset') = 0 then
begin
if AConfig.TryGetValue(ANode, 'Name', PresetName) then
begin
if FMultiRenamePresetList.Find(PresetName) = -1 then //Make sure we don't load preset with the same name.
begin
AMultiRenamePreset := TMultiRenamePreset.Create;
AMultiRenamePreset.PresetName := PresetName;
FMultiRenamePresetList.Add(AMultiRenamePreset);
AMultiRenamePreset.FileName := AConfig.GetValue(ANode, 'Filename', '[N]');
AMultiRenamePreset.Extension := AConfig.GetValue(ANode, 'Extension', '[E]');
AMultiRenamePreset.FileNameStyle := AConfig.GetValue(ANode, 'FilenameStyle', 0);
AMultiRenamePreset.ExtensionStyle := AConfig.GetValue(ANode, 'ExtensionStyle', 0);
if AConfig.TryGetAttr(ANode, 'Find/Value', PresetName) then
AMultiRenamePreset.Find := PresetName
else begin
AMultiRenamePreset.Find := AConfig.GetValue(ANode, 'Find', '');
end;
if AConfig.TryGetAttr(ANode, 'Replace/Value', PresetName) then
AMultiRenamePreset.Replace := PresetName
else begin
AMultiRenamePreset.Replace := AConfig.GetValue(ANode, 'Replace', '');
end;
AMultiRenamePreset.RepExt := AConfig.GetValue(ANode, 'RepExt', True);
AMultiRenamePreset.RegExp := AConfig.GetValue(ANode, 'RegExp', False);
AMultiRenamePreset.UseSubs := AConfig.GetValue(ANode, 'UseSubs', False);
AMultiRenamePreset.CaseSens := AConfig.GetValue(ANode, 'CaseSensitive', False);
AMultiRenamePreset.OnlyFirst := AConfig.GetValue(ANode, 'OnlyFirst', False);
AMultiRenamePreset.Counter := AConfig.GetValue(ANode, 'Counter', '1');
AMultiRenamePreset.Interval := AConfig.GetValue(ANode, 'Interval', '1');
AMultiRenamePreset.Width := AConfig.GetValue(ANode, 'Width', 0);
AMultiRenamePreset.Log := AConfig.GetValue(ANode, 'Log/Enabled', False);
AMultiRenamePreset.LogAppend := AConfig.GetValue(ANode, 'Log/Append', False);
AMultiRenamePreset.LogFile := AConfig.GetValue(ANode, 'Log/File', '');
end;
end
else
DCDebug('Invalid entry in configuration: ' + AConfig.GetPathFromNode(ANode) + '.');
end;
ANode := ANode.NextSibling;
end;
end;
//Make sure the "sLASTPRESET" is at position 0.
PresetIndex := FMultiRenamePresetList.Find(sLASTPRESET);
if PresetIndex <> 0 then
begin
if PresetIndex <> -1 then
begin
//If it's present but not at zero, move it to 0.
FMultiRenamePresetList.Move(PresetIndex, 0);
end
else
begin
AMultiRenamePreset := TMultiRenamePreset.Create;
AMultiRenamePreset.PresetName := sLASTPRESET;
FMultiRenamePresetList.Insert(0, AMultiRenamePreset);
end;
end;
end;
{ TfrmMultiRename.isOkToLosePresetModification }
function TfrmMultiRename.isOkToLosePresetModification: boolean;
var
MyMsgResult: TMyMsgResult;
begin
Result := False;
if (cbPresets.ItemIndex <= 0) or (cbPresets.Enabled) or (not Visible) then
Result := True
else
begin
case gMulRenExitModifiedPreset of
mrempIgnoreSaveLast:
begin
Result := True;
end;
mrempSaveAutomatically:
begin
if cbPresets.ItemIndex > 0 then
cm_SavePreset(['name=' + cbPresets.Items.Strings[cbPresets.ItemIndex]]);
Result := True;
end;
mrempPromptUser:
begin
MyMsgResult := msgYesNoCancel(Format(rsMulRenSaveModifiedPreset, [cbPresets.Items.Strings[cbPresets.ItemIndex]]), msmbCancel);
case MyMsgResult of
mmrYes:
begin
cm_SavePreset([]);
Result := True;
end;
mmrNo: Result := True;
mmrCancel: ;
end;
end;
end;
end;
end;
{ TfrmMultiRename.SavePreset }
procedure TfrmMultiRename.SavePreset(PresetName: string);
var
PresetIndex: integer;
AMultiRenamePresetObject: TMultiRenamePreset;
begin
if PresetName <> '' then
begin
PresetIndex := FMultiRenamePresetList.Find(PresetName);
if PresetIndex = -1 then
begin
AMultiRenamePresetObject := TMultiRenamePreset.Create;
AMultiRenamePresetObject.PresetName := PresetName;
PresetIndex := FMultiRenamePresetList.Add(AMultiRenamePresetObject);
end;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].FileName := cbName.Text;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Extension := cbExt.Text;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].FileNameStyle := cbNameMaskStyle.ItemIndex;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].ExtensionStyle := cmbExtensionStyle.ItemIndex;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Find := edFind.Text;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Replace := edReplace.Text;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].RepExt := cbRepExt.Checked;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].RegExp := cbRegExp.Checked;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].UseSubs := cbUseSubs.Checked;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].CaseSens := cbCaseSens.Checked;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].OnlyFirst := cbOnlyFirst.Checked;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Counter := edPoc.Text;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Interval := edInterval.Text;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Width := cmbxWidth.ItemIndex;
case gMulRenSaveRenamingLog of
mrsrlPerPreset:
begin
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Log := cbLog.Checked;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].LogFile := fneRenameLogFileFilename.FileName;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].LogAppend := cbLogAppend.Checked;
end;
mrsrlAppendSameLog:
begin
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Log := FbRememberLog;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].LogAppend := FbRememberAppend;
FMultiRenamePresetList.MultiRenamePreset[PresetIndex].LogFile := FsRememberRenameLogFilename;
end;
end;
SavePresets;
end;
end;
{ TfrmMultiRename.SavePresetsXml }
procedure TfrmMultiRename.SavePresetsXml(AConfig: TXmlConfig);
var
i: integer;
ANode, SubNode: TXmlNode;
begin
ANode := AConfig.FindNode(AConfig.RootNode, sPresetsSection, True);
AConfig.ClearNode(ANode);
if cbPresets.ItemIndex = 0 then
AConfig.SetValue(ANode, 'LastPreset', sLASTPRESET)
else
AConfig.SetValue(ANode, 'LastPreset', cbPresets.Items.Strings[cbPresets.ItemIndex]);
ANode := AConfig.FindNode(ANode, 'Presets', True);
for i := 0 to pred(FMultiRenamePresetList.Count) do
begin
SubNode := AConfig.AddNode(ANode, 'Preset');
AConfig.AddValue(SubNode, 'Name', FMultiRenamePresetList.MultiRenamePreset[i].PresetName);
AConfig.AddValue(SubNode, 'Filename', FMultiRenamePresetList.MultiRenamePreset[i].FileName);
AConfig.AddValue(SubNode, 'Extension', FMultiRenamePresetList.MultiRenamePreset[i].Extension);
AConfig.AddValue(SubNode, 'FilenameStyle', FMultiRenamePresetList.MultiRenamePreset[i].FileNameStyle);
AConfig.AddValue(SubNode, 'ExtensionStyle', FMultiRenamePresetList.MultiRenamePreset[i].ExtensionStyle);
AConfig.SetAttr(SubNode, 'Find/Value', FMultiRenamePresetList.MultiRenamePreset[i].Find);
AConfig.SetAttr(SubNode, 'Replace/Value', FMultiRenamePresetList.MultiRenamePreset[i].Replace);
AConfig.AddValue(SubNode, 'RepExt', FMultiRenamePresetList.MultiRenamePreset[i].RepExt);
AConfig.AddValue(SubNode, 'RegExp', FMultiRenamePresetList.MultiRenamePreset[i].RegExp);
AConfig.AddValue(SubNode, 'UseSubs', FMultiRenamePresetList.MultiRenamePreset[i].UseSubs);
AConfig.AddValue(SubNode, 'CaseSensitive', FMultiRenamePresetList.MultiRenamePreset[i].CaseSens);
AConfig.AddValue(SubNode, 'OnlyFirst', FMultiRenamePresetList.MultiRenamePreset[i].OnlyFirst);
AConfig.AddValue(SubNode, 'Counter', FMultiRenamePresetList.MultiRenamePreset[i].Counter);
AConfig.AddValue(SubNode, 'Interval', FMultiRenamePresetList.MultiRenamePreset[i].Interval);
AConfig.AddValue(SubNode, 'Width', FMultiRenamePresetList.MultiRenamePreset[i].Width);
AConfig.SetValue(SubNode, 'Log/Enabled', FMultiRenamePresetList.MultiRenamePreset[i].Log);
AConfig.SetValue(SubNode, 'Log/Append', FMultiRenamePresetList.MultiRenamePreset[i].LogAppend);
AConfig.SetValue(SubNode, 'Log/File', FMultiRenamePresetList.MultiRenamePreset[i].LogFile);
end;
end;
{ TfrmMultiRename.SavePresets }
procedure TfrmMultiRename.SavePresets;
begin
SavePresetsXml(gConfig);
gConfig.Save;
end;
{ TfrmMultiRename.DeletePreset }
procedure TfrmMultiRename.DeletePreset(PresetName: string);
var
PresetIndex: integer;
begin
if PresetName <> '' then
begin
PresetIndex := FMultiRenamePresetList.Find(PresetName);
if PresetIndex <> -1 then
begin
FMultiRenamePresetList.Delete(PresetIndex);
SavePresets;
end;
end;
end;
{ TfrmMultiRename.FillPresetsList }
//We fill the preset drop list with the element in memory.
//If it's specified when called, will attempt to load the specified preset in parameter.
//If it's not specified, will attempt to re-select the one that was initially selected.
//If nothing is still selected, we'll select the [Last One].
procedure TfrmMultiRename.FillPresetsList(const WantedSelectedPresetName: string = '');
var
i: integer;
sRememberSelection, PresetName: string;
begin
sRememberSelection := '';
if WantedSelectedPresetName <> '' then
sRememberSelection := WantedSelectedPresetName;
if sRememberSelection = '' then
if cbPresets.ItemIndex <> -1 then
if cbPresets.ItemIndex < cbPresets.Items.Count then
sRememberSelection := cbPresets.Items.Strings[cbPresets.ItemIndex];
cbPresets.Clear;
cbPresets.Items.Add(rsMulRenLastPreset);
for i := 0 to pred(FMultiRenamePresetList.Count) do
begin
PresetName := FMultiRenamePresetList.MultiRenamePreset[i].PresetName;
if (PresetName <> sLASTPRESET) then
if cbPresets.Items.IndexOf(PresetName) = -1 then
cbPresets.Items.Add(PresetName);
end;
if (WantedSelectedPresetName = sLASTPRESET) or (WantedSelectedPresetName = sFRESHMASKS) then
cbPresets.ItemIndex := 0
else
if sRememberSelection <> '' then
if cbPresets.Items.IndexOf(sRememberSelection) <> -1 then
cbPresets.ItemIndex := cbPresets.Items.IndexOf(sRememberSelection);
if cbPresets.ItemIndex = -1 then
if cbPresets.Items.Count > 0 then
cbPresets.ItemIndex := 0;
if WantedSelectedPresetName <> sFRESHMASKS then
begin
cbPresetsChange(cbPresets);
RefreshActivePresetCommands;
end;
end;
{ TfrmMultiRename.RefreshActivePresetCommands }
procedure TfrmMultiRename.RefreshActivePresetCommands;
begin
//"Load last preset" is always available since it's the [Last One].
actLoadPreset1.Enabled := (cbPresets.Items.Count > 1) and (cbPresets.Enabled);
actLoadPreset2.Enabled := (cbPresets.Items.Count > 2) and (cbPresets.Enabled);
actLoadPreset3.Enabled := (cbPresets.Items.Count > 3) and (cbPresets.Enabled);
actLoadPreset4.Enabled := (cbPresets.Items.Count > 4) and (cbPresets.Enabled);
actLoadPreset5.Enabled := (cbPresets.Items.Count > 5) and (cbPresets.Enabled);
actLoadPreset6.Enabled := (cbPresets.Items.Count > 6) and (cbPresets.Enabled);
actLoadPreset7.Enabled := (cbPresets.Items.Count > 7) and (cbPresets.Enabled);
actLoadPreset8.Enabled := (cbPresets.Items.Count > 8) and (cbPresets.Enabled);
actLoadPreset9.Enabled := (cbPresets.Items.Count > 9) and (cbPresets.Enabled);
actSavePreset.Enabled := (cbPresets.ItemIndex > 0);
//"Save as is always available so we may save the [Last One]
actRenamePreset.Enabled := (cbPresets.ItemIndex > 0);
actDeletePreset.Enabled := (cbPresets.ItemIndex > 0);
end;
{ TfrmMultiRename.InitializeMaskHelper }
procedure TfrmMultiRename.InitializeMaskHelper;
begin
if MaskHelpers[00].sMenuItem = '' then //"MaskHelpers" are no tin the object but generic, so we just need to initialize once.
begin
MaskHelpers[00].sMenuItem := MaskHelpers[00].sKeyword + ' ' + rsMulRenMaskName;
MaskHelpers[01].sMenuItem := MaskHelpers[01].sKeyword + ' ' + rsMulRenMaskCharAtPosX;
MaskHelpers[02].sMenuItem := MaskHelpers[02].sKeyword + ' ' + rsMulRenMaskCharAtPosXtoY;
MaskHelpers[03].sMenuItem := MaskHelpers[03].sKeyword + ' ' + rsMulRenMaskFullName;
MaskHelpers[04].sMenuItem := MaskHelpers[04].sKeyword + ' ' + rsMulRenMaskFullNameCharAtPosXtoY;
MaskHelpers[05].sMenuItem := MaskHelpers[05].sKeyword + ' ' + rsMulRenMaskParent;
MaskHelpers[06].sMenuItem := MaskHelpers[06].sKeyword + ' ' + rsMulRenMaskExtension;
MaskHelpers[07].sMenuItem := MaskHelpers[07].sKeyword + ' ' + rsMulRenMaskCharAtPosX;
MaskHelpers[08].sMenuItem := MaskHelpers[08].sKeyword + ' ' + rsMulRenMaskCharAtPosXtoY;
MaskHelpers[09].sMenuItem := MaskHelpers[09].sKeyword + ' ' + rsMulRenMaskCounter;
MaskHelpers[10].sMenuItem := MaskHelpers[10].sKeyword + ' ' + rsMulRenMaskGUID;
MaskHelpers[11].sMenuItem := MaskHelpers[11].sKeyword + ' ' + rsMulRenMaskVarOnTheFly;
MaskHelpers[12].sMenuItem := MaskHelpers[12].sKeyword + ' ' + rsMulRenMaskYear2Digits;
MaskHelpers[13].sMenuItem := MaskHelpers[13].sKeyword + ' ' + rsMulRenMaskYear4Digits;
MaskHelpers[14].sMenuItem := MaskHelpers[14].sKeyword + ' ' + rsMulRenMaskMonth;
MaskHelpers[15].sMenuItem := MaskHelpers[15].sKeyword + ' ' + rsMulRenMaskMonth2Digits;
MaskHelpers[16].sMenuItem := MaskHelpers[16].sKeyword + ' ' + rsMulRenMaskMonthAbrev;
MaskHelpers[17].sMenuItem := MaskHelpers[17].sKeyword + ' ' + rsMulRenMaskMonthComplete;
MaskHelpers[18].sMenuItem := MaskHelpers[18].sKeyword + ' ' + rsMulRenMaskDay;
MaskHelpers[19].sMenuItem := MaskHelpers[19].sKeyword + ' ' + rsMulRenMaskDay2Digits;
MaskHelpers[20].sMenuItem := MaskHelpers[20].sKeyword + ' ' + rsMulRenMaskDOWAbrev;
MaskHelpers[21].sMenuItem := MaskHelpers[21].sKeyword + ' ' + rsMulRenMaskDOWComplete;
MaskHelpers[22].sMenuItem := MaskHelpers[22].sKeyword + ' ' + rsMulRenMaskCompleteDate;
MaskHelpers[23].sMenuItem := MaskHelpers[23].sKeyword + ' ' + rsMulRenMaskHour;
MaskHelpers[24].sMenuItem := MaskHelpers[24].sKeyword + ' ' + rsMulRenMaskHour2Digits;
MaskHelpers[25].sMenuItem := MaskHelpers[25].sKeyword + ' ' + rsMulRenMaskMin;
MaskHelpers[26].sMenuItem := MaskHelpers[26].sKeyword + ' ' + rsMulRenMaskMin2Digits;
MaskHelpers[27].sMenuItem := MaskHelpers[27].sKeyword + ' ' + rsMulRenMaskSec;
MaskHelpers[28].sMenuItem := MaskHelpers[28].sKeyword + ' ' + rsMulRenMaskSec2Digits;
MaskHelpers[29].sMenuItem := MaskHelpers[29].sKeyword + ' ' + rsMulRenMaskCompleteTime;
end;
end;
{ TfrmMultiRename.PopulateMainMenu }
// This main menu is not essential.
// But it does not occupy a lot of pixels and may benefit to user to help to both discover and remember the keyboard shortcut by visualizing them.
// Also, we populate it run-time to save work to valuable translators so they won't have to re-translate the same strings or to validate copies.
procedure TfrmMultiRename.PopulateMainMenu;
var
miPresets, miMasks, miSubMasks: TMenuItem;
begin
btnAnyNameMask.Action := actAnyNameMask;
btnAnyNameMask.Caption := '...';
btnAnyNameMask.Width := fneRenameLogFileFilename.ButtonWidth;
btnAnyExtMask.Action := actAnyExtMask;
btnAnyExtMask.Caption := '...';
btnAnyExtMask.Width := fneRenameLogFileFilename.ButtonWidth;
btnRelativeRenameLogFile.Action := actInvokeRelativePath;
btnRelativeRenameLogFile.Caption := '';
btnRelativeRenameLogFile.Width := fneRenameLogFileFilename.ButtonWidth;
btnRelativeRenameLogFile.Hint := actInvokeRelativePath.Caption;
btnViewRenameLogFile.Action := actViewRenameLogFile;
btnViewRenameLogFile.Caption := '';
btnViewRenameLogFile.Width := fneRenameLogFileFilename.ButtonWidth;
btnViewRenameLogFile.Hint := actViewRenameLogFile.Caption;
btnPresets.Action := actShowPresetsMenu;
btnPresets.Caption := '';
btnPresets.Hint := actShowPresetsMenu.Caption;
btnPresets.Constraints.MinWidth := fneRenameLogFileFilename.ButtonWidth;
miPresets := TMenuItem.Create(mmMainMenu);
miPresets.Caption := gbPresets.Caption;
mmMainMenu.Items.Add(miPresets);
BuildPresetsMenu(miPresets);
BuildPresetsMenu(pmPresets);
miMasks := TMenuItem.Create(mmMainMenu);
miMasks.Caption := gbMaska.Caption;
mmMainMenu.Items.Add(miMasks);
//We add the sub-menu for the filename masks
miSubMasks := TMenuItem.Create(miMasks);
miSubMasks.Caption := lbName.Caption;
miSubMasks.ImageIndex := GetImageIndexCategoryName(rmtuFilename);
miMasks.Add(miSubMasks);
PopulateFilenameMenu(miSubMasks);
//We add the sub-menu for the filename masks
miSubMasks := TMenuItem.Create(miMasks);
miSubMasks.Caption := lbExt.Caption;
miSubMasks.ImageIndex := GetImageIndexCategoryName(rmtuExtension);
miMasks.Add(miSubMasks);
PopulateExtensionMenu(miSubMasks);
end;
{ TfrmMultiRename.PopulateFilenameMenu }
procedure TfrmMultiRename.PopulateFilenameMenu(AMenuSomething: TComponent);
var
localMenuItem, miSubMenu, miMenuItem: TMenuItem;
begin
if AMenuSomething.ClassType = TPopupMenu then
localMenuItem := TPopupMenu(AMenuSomething).Items
else if AMenuSomething.ClassType = TMenuItem then
begin
localMenuItem := TMenuItem(AMenuSomething);
miMenuItem := TMenuItem.Create(localMenuItem);
miMenuItem.Action := actAnyNameMask;
localMenuItem.Add(miMenuItem);
miMenuItem := TMenuItem.Create(localMenuItem);
miMenuItem.Caption := '-';
localMenuItem.Add(miMenuItem);
end
else
exit;
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuFilename), GetImageIndexCategoryName(rmtuFilename));
BuildMaskMenu(miSubMenu, tfmFilename, rmtuFilename);
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuExtension), GetImageIndexCategoryName(rmtuExtension));
BuildMaskMenu(miSubMenu, tfmFilename, rmtuExtension);
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuCounter), GetImageIndexCategoryName(rmtuCounter));
BuildMaskMenu(miSubMenu, tfmFilename, rmtuCounter);
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuDate), GetImageIndexCategoryName(rmtuDate));
BuildMaskMenu(miSubMenu, tfmFilename, rmtuDate);
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuTime), GetImageIndexCategoryName(rmtuTime));
BuildMaskMenu(miSubMenu, tfmFilename, rmtuTime);
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuPlugins), GetImageIndexCategoryName(rmtuPlugins));
BuildMaskMenu(miSubMenu, tfmFilename, rmtuPlugins);
AppendSubMenuToThisMenu(localMenuItem, '-', -1);
AppendActionMenuToThisMenu(localMenuItem, actClearNameMask);
AppendActionMenuToThisMenu(localMenuItem, actResetAll);
end;
{ TfrmMultiRename.PopulateExtensionMenu }
procedure TfrmMultiRename.PopulateExtensionMenu(AMenuSomething: TComponent);
var
localMenuItem, miSubMenu, miMenuItem: TMenuItem;
begin
if AMenuSomething.ClassType = TPopupMenu then
localMenuItem := TPopupMenu(AMenuSomething).Items
else if AMenuSomething.ClassType = TMenuItem then
begin
localMenuItem := TMenuItem(AMenuSomething);
miMenuItem := TMenuItem.Create(localMenuItem);
miMenuItem.Action := actAnyExtMask;
localMenuItem.Add(miMenuItem);
miMenuItem := TMenuItem.Create(localMenuItem);
miMenuItem.Caption := '-';
localMenuItem.Add(miMenuItem);
end
else
exit;
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuFilename), GetImageIndexCategoryName(rmtuFilename));
BuildMaskMenu(miSubMenu, tfmExtension, rmtuFilename);
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuExtension), GetImageIndexCategoryName(rmtuExtension));
BuildMaskMenu(miSubMenu, tfmExtension, rmtuExtension);
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuCounter), GetImageIndexCategoryName(rmtuCounter));
BuildMaskMenu(miSubMenu, tfmExtension, rmtuCounter);
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuDate), GetImageIndexCategoryName(rmtuDate));
BuildMaskMenu(miSubMenu, tfmExtension, rmtuDate);
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuTime), GetImageIndexCategoryName(rmtuTime));
BuildMaskMenu(miSubMenu, tfmExtension, rmtuTime);
miSubMenu := AppendSubMenuToThisMenu(localMenuItem, GetMaskCategoryName(rmtuPlugins), GetImageIndexCategoryName(rmtuPlugins));
BuildMaskMenu(miSubMenu, tfmExtension, rmtuPlugins);
AppendSubMenuToThisMenu(localMenuItem, '-', -1);
AppendActionMenuToThisMenu(localMenuItem, actClearExtMask);
AppendActionMenuToThisMenu(localMenuItem, actResetAll);
end;
{ TfrmMultiRename.BuildMaskMenu }
procedure TfrmMultiRename.BuildMaskMenu(AMenuSomething: TComponent; iTarget: tTargetForMask; iMenuTypeMask: tRenameMaskToUse);
var
iSeekIndex: integer;
AMenuItem, localMenuItem: TMenuItem;
actCategoryActionToAdd: TAction = nil;
begin
if AMenuSomething.ClassType = TPopupMenu then
localMenuItem := TPopupMenu(AMenuSomething).Items
else if AMenuSomething.ClassType = TMenuItem then
localMenuItem := TMenuItem(AMenuSomething)
else
exit;
localMenuItem.Clear;
if AMenuSomething.ClassType = TMenuItem then
begin
actCategoryActionToAdd := GetCategoryAction(iTarget, iMenuTypeMask);
if actCategoryActionToAdd <> nil then
begin
AMenuItem := TMenuItem.Create(AMenuSomething);
AMenuItem.Action := actCategoryActionToAdd;
localMenuItem.Add(AMenuItem);
AMenuItem := TMenuItem.Create(AMenuSomething);
AMenuItem.Caption := '-';
localMenuItem.Add(AMenuItem);
end;
end;
for iSeekIndex := 0 to pred(NBMAXHELPERS) do
begin
if MaskHelpers[iSeekIndex].iMenuType = iMenuTypeMask then
begin
AMenuItem := TMenuItem.Create(AMenuSomething);
AMenuItem.Caption := MaskHelpers[iSeekIndex].sMenuItem;
AMenuItem.Tag := (iSeekIndex shl 16) or Ord(iTarget);
AMenuItem.Hint := MaskHelpers[iSeekIndex].sKeyword;
AMenuItem.ImageIndex := GetImageIndexCategoryName(MaskHelpers[iSeekIndex].iMenuType);
case MaskHelpers[iSeekIndex].MenuActionStyle of
masStraight: AMenuItem.OnClick := @MenuItemStraightMaskClick;
masXCharacters, masXYCharacters: AMenuItem.OnClick := @MenuItemXCharactersMaskClick;
masAskVariable: AMenuItem.OnClick := @MenuItemVariableMaskClick;
masDirectorySelector: AMenuItem.OnClick := @MenuItemDirectorySelectorMaskClick;
end;
localMenuItem.Add(AMenuItem);
end;
end;
if rmtuPlugins = iMenuTypeMask then
begin
FPluginDispatcher := iTarget;
FillContentFieldMenu(AMenuSomething, @miPluginClick); //No need to clear "pmDynamicMasks" because "FillContentFieldMenu" do it itself.
if AMenuSomething.ClassType = TMenuItem then
begin
//We need to add the mask category menu item at the end since "FillContentFieldMenu" clears our "pmDynamicMasks".
AMenuItem := TMenuItem.Create(AMenuSomething);
AMenuItem.Caption := '-';
localMenuItem.Insert(0, AMenuItem);
AMenuItem := TMenuItem.Create(AMenuSomething);
AMenuItem.Action := actCategoryActionToAdd;
localMenuItem.Insert(0, AMenuItem);
end;
end;
end;
{ TfrmMultiRename.BuildPresetsMenu }
procedure TfrmMultiRename.BuildPresetsMenu(AMenuSomething: TComponent);
var
localMenuItem: TMenuItem;
begin
if AMenuSomething.ClassType = TPopupMenu then
localMenuItem := TPopupMenu(AMenuSomething).Items
else if AMenuSomething.ClassType = TMenuItem then
begin
localMenuItem := TMenuItem(AMenuSomething);
AppendActionMenuToThisMenu(localMenuItem, actShowPresetsMenu);
AppendSubMenuToThisMenu(localMenuItem, '-', -1);
end
else
exit;
AppendActionMenuToThisMenu(localMenuItem, actDropDownPresetList);
AppendSubMenuToThisMenu(localMenuItem, '-', -1);
AppendActionMenuToThisMenu(localMenuItem, actLoadLastPreset);
AppendActionMenuToThisMenu(localMenuItem, actLoadPreset1);
AppendActionMenuToThisMenu(localMenuItem, actLoadPreset2);
AppendActionMenuToThisMenu(localMenuItem, actLoadPreset3);
AppendActionMenuToThisMenu(localMenuItem, actLoadPreset4);
AppendActionMenuToThisMenu(localMenuItem, actLoadPreset5);
AppendActionMenuToThisMenu(localMenuItem, actLoadPreset6);
AppendActionMenuToThisMenu(localMenuItem, actLoadPreset7);
AppendActionMenuToThisMenu(localMenuItem, actLoadPreset8);
AppendActionMenuToThisMenu(localMenuItem, actLoadPreset9);
AppendSubMenuToThisMenu(localMenuItem, '-', -1);
AppendActionMenuToThisMenu(localMenuItem, actSavePreset);
AppendActionMenuToThisMenu(localMenuItem, actSavePresetAs);
AppendActionMenuToThisMenu(localMenuItem, actRenamePreset);
AppendActionMenuToThisMenu(localMenuItem, actDeletePreset);
AppendActionMenuToThisMenu(localMenuItem, actSortPresets);
end;
{ TfrmMultiRename.BuildMenuAndPopup }
procedure TfrmMultiRename.BuildMenuAndPopup(iTarget: tTargetForMask; iMenuTypeMask: tRenameMaskToUse);
begin
BuildMaskMenu(pmDynamicMasks, iTarget, iMenuTypeMask);
case iTarget of
tfmFilename: PopupDynamicMenuAtThisControl(pmDynamicMasks, cbName);
tfmExtension: PopupDynamicMenuAtThisControl(pmDynamicMasks, cbExt);
end;
end;
{ TfrmMultiRename.GetMaskCategoryName }
function TfrmMultiRename.GetMaskCategoryName(aRenameMaskToUse: tRenameMaskToUse): string;
begin
Result := '';
case aRenameMaskToUse of
rmtuFilename: Result := rsMulRenFilename;
rmtuExtension: Result := rsMulRenExtension;
rmtuCounter: Result := rsMulRenCounter;
rmtuDate: Result := rsMulRenDate;
rmtuTime: Result := rsMulRenTime;
rmtuPlugins: Result := rsMulRenPlugins;
end;
end;
{ TfrmMultiRename.GetImageIndexCategoryName }
function TfrmMultiRename.GetImageIndexCategoryName(aRenameMaskToUse: tRenameMaskToUse): integer;
begin
Result := -1;
case aRenameMaskToUse of
rmtuFilename: Result := 20;
rmtuExtension: Result := 21;
rmtuCounter: Result := 22;
rmtuDate: Result := 23;
rmtuTime: Result := 24;
rmtuPlugins: Result := 25;
end;
end;
{ TfrmMultiRename.GetCategoryAction }
function TfrmMultiRename.GetCategoryAction(TargetForMask: tTargetForMask; aRenameMask: tRenameMaskToUse): TAction;
begin
Result := nil;
case TargetForMask of
tfmFilename:
begin
case aRenameMask of
rmtuFilename: Result := actNameNameMask;
rmtuExtension: Result := actExtNameMask;
rmtuCounter: Result := actCtrNameMask;
rmtuDate: Result := actDateNameMask;
rmtuTime: Result := actTimeNameMask;
rmtuPlugins: Result := actPlgnNameMask;
end;
end;
tfmExtension:
begin
case aRenameMask of
rmtuFilename: Result := actNameExtMask;
rmtuExtension: Result := actExtExtMask;
rmtuCounter: Result := actCtrExtMask;
rmtuDate: Result := actDateExtMask;
rmtuTime: Result := actTimeExtMask;
rmtuPlugins: Result := actPlgnExtMask;
end;
end;
end;
end;
{ TfrmMultiRename.AppendSubMenuToThisMenu }
function TfrmMultiRename.AppendSubMenuToThisMenu(ATargetMenu: TMenuItem; sCaption: string; iImageIndex: integer): TMenuItem;
begin
Result := TMenuItem.Create(ATargetMenu);
Result.ImageIndex := iImageIndex;
if sCaption <> '' then
Result.Caption := sCaption;
ATargetMenu.Add(Result);
end;
{ TfrmMultiRename.AppendActionMenuToThisMenu }
function TfrmMultiRename.AppendActionMenuToThisMenu(ATargetMenu: TMenuItem; paramAction: TAction): TMenuItem;
begin
Result := TMenuItem.Create(ATargetMenu);
Result.Action := paramAction;
ATargetMenu.Add(Result);
end;
{ TfrmMultiRename.MenuItemXCharactersMaskClick }
procedure TfrmMultiRename.MenuItemXCharactersMaskClick(Sender: TObject);
var
sSourceToSelectFromText, sPrefix: string;
sResultingMaskValue: string = '';
iMaskHelperIndex: integer;
begin
iMaskHelperIndex := TMenuItem(Sender).Tag shr 16;
if iMaskHelperIndex < length(MaskHelpers) then
begin
sSourceToSelectFromText := '';
case MaskHelpers[iMaskHelperIndex].iSourceOfInformation of
soiFilename:
begin
sSourceToSelectFromText := FFiles[pred(StringGrid.Row)].NameNoExt;
sPrefix := 'N';
end;
soiExtension:
begin
sSourceToSelectFromText := FFiles[pred(StringGrid.Row)].Extension;
sPrefix := 'E';
end;
soiFullName:
begin
sSourceToSelectFromText := FFiles[pred(StringGrid.Row)].FullPath;
sPrefix := 'A';
end;
end;
if ShowSelectTextRangeDlg(Self, Caption, sSourceToSelectFromText, sPrefix, sResultingMaskValue) then
InsertMask(sResultingMaskValue, tTargetForMask(TMenuItem(Sender).Tag and iTARGETMASK));
end;
end;
{ TfrmMultiRename.MenuItemDirectorySelectorMaskClick }
procedure TfrmMultiRename.MenuItemDirectorySelectorMaskClick(Sender: TObject);
var
sSourceToSelectFromText, sPrefix: string;
sResultingMaskValue: string = '';
iMaskHelperIndex: integer;
begin
iMaskHelperIndex := TMenuItem(Sender).Tag shr 16;
if iMaskHelperIndex < length(MaskHelpers) then
begin
sSourceToSelectFromText := '';
case MaskHelpers[iMaskHelperIndex].iSourceOfInformation of
soiPath:
begin
sSourceToSelectFromText := FFiles[pred(StringGrid.Row)].Path;
sPrefix := 'P';
end;
end;
if ShowSelectPathRangeDlg(Self, Caption, sSourceToSelectFromText, sPrefix, sResultingMaskValue) then
InsertMask(sResultingMaskValue, tTargetForMask(TMenuItem(Sender).Tag and iTARGETMASK));
end;
end;
{ TfrmMultiRename.MenuItemVariableMaskClick }
procedure TfrmMultiRename.MenuItemVariableMaskClick(Sender: TObject);
var
sVariableName: string;
begin
sVariableName := rsSimpleWordVariable;
if InputQuery(rsMulRenDefineVariableName, rsMulRenEnterNameForVar, sVariableName) then
begin
if sVariableName = '' then
sVariableName := rsSimpleWordVariable;
InsertMask('[V:' + sVariableName + ']', tTargetForMask(TMenuItem(Sender).Tag and iTARGETMASK));
end;
end;
{ TfrmMultiRename.MenuItemStraightMaskClick }
procedure TfrmMultiRename.MenuItemStraightMaskClick(Sender: TObject);
var
sMaks: string;
begin
sMaks := TMenuItem(Sender).Hint;
case tTargetForMask(TMenuItem(Sender).Tag and iTARGETMASK) of
tfmFilename:
begin
InsertMask(sMaks, cbName);
cbName.SetFocus;
end;
tfmExtension:
begin
InsertMask(sMaks, cbExt);
cbExt.SetFocus;
end;
end;
end;
{ TfrmMultiRename.PopupDynamicMenuAtThisControl }
procedure TfrmMultiRename.PopupDynamicMenuAtThisControl(APopUpMenu: TPopupMenu; AControl: TControl);
var
PopupPoint: TPoint;
begin
PopupPoint := AControl.Parent.ClientToScreen(Point(AControl.Left + AControl.Width - 5, AControl.Top + AControl.Height - 5));
APopUpMenu.PopUp(PopupPoint.X, PopupPoint.Y);
end;
{ TfrmMultiRename.miPluginClick }
procedure TfrmMultiRename.miPluginClick(Sender: TObject);
var
sMask: string;
MenuItem: TMenuItem absolute Sender;
begin
case MenuItem.Tag of
0:
begin
sMask := '[=DC().' + MenuItem.Hint + '{}]';
end;
1:
begin
sMask := '[=Plugin(' + MenuItem.Parent.Caption + ').' + MenuItem.Hint + '{}]';
end;
2:
begin
sMask := '[=Plugin(' + MenuItem.Parent.Parent.Caption + ').' + MenuItem.Parent.Hint + '{' + MenuItem.Hint + '}]';
end;
3:
begin
sMask := '[=DC().' + MenuItem.Parent.Hint + '{' + MenuItem.Hint + '}]';
end;
end;
case FPluginDispatcher of
tfmFilename:
begin
InsertMask(sMask, cbName);
cbName.SetFocus;
end;
tfmExtension:
begin
InsertMask(sMask, cbExt);
cbExt.SetFocus;
end;
end;
end;
{ TfrmMultiRename.InsertMask }
procedure TfrmMultiRename.InsertMask(const Mask: string; edChoose: TComboBox);
var
sTmp, sInitialString: string;
I: integer;
begin
sInitialString := edChoose.Text;
if edChoose.SelLength > 0 then
edChoose.SelText := Mask // Replace selected text
else
begin
sTmp := edChoose.Text;
I := edChoose.SelStart + 1; // Insert on current position
UTF8Insert(Mask, sTmp, I);
Inc(I, UTF8Length(Mask));
edChoose.Text := sTmp;
edChoose.SelStart := I - 1;
end;
if sInitialString <> edChoose.Text then
cbNameStyleChange(edChoose);
end;
{ TfrmMultiRename.InsertMask }
procedure TfrmMultiRename.InsertMask(const Mask: string; TargetForMask: tTargetForMask);
begin
case TargetForMask of
tfmFilename:
begin
InsertMask(Mask, cbName);
cbName.SetFocus;
end;
tfmExtension:
begin
InsertMask(Mask, cbExt);
cbExt.SetFocus;
end;
end;
end;
{TfrmMultiRename.sReplace }
function TfrmMultiRename.sReplace(sMask: string; ItemNr: integer): string;
var
iStart, iEnd: integer;
begin
Result := '';
while Length(sMask) > 0 do
begin
iStart := Pos('[', sMask);
if iStart > 0 then
begin
iEnd := Pos(']', sMask, iStart + 1);
if iEnd > 0 then
begin
Result := Result + Copy(sMask, 1, iStart - 1) +
sHandleFormatString(Copy(sMask, iStart + 1, iEnd - iStart - 1), ItemNr);
Delete(sMask, 1, iEnd);
end
else
Break;
end
else
Break;
end;
Result := Result + sMask;
end;
{ TfrmMultiRename.sReplaceXX }
function TfrmMultiRename.sReplaceXX(const sFormatStr, sOrig: string): string;
var
iFrom, iTo, iDelim: integer;
begin
if Length(sFormatStr) = 1 then
Result := sOrig
else
begin
iDelim := Pos(':', sFormatStr);
if iDelim = 0 then
begin
iDelim := Pos(',', sFormatStr);
// Not found
if iDelim = 0 then
begin
iFrom := StrToIntDef(Copy(sFormatStr, 2, MaxInt), 1);
if iFrom < 0 then
iFrom := sOrig.Length + iFrom + 1;
iTo := iFrom;
end
// Range e.g. N1,3 (from 1, 3 symbols)
else
begin
iFrom := StrToIntDef(Copy(sFormatStr, 2, iDelim - 2), 1);
iDelim := Abs(StrToIntDef(Copy(sFormatStr, iDelim + 1, MaxSmallint), MaxSmallint));
if iFrom >= 0 then
iTo := iDelim + iFrom - 1
else
begin
iTo := sOrig.Length + iFrom + 1;
iFrom := Max(iTo - iDelim + 1, 1);
end;
end;
end
// Range e.g. N1:2 (from 1 to 2)
else
begin
iFrom := StrToIntDef(Copy(sFormatStr, 2, iDelim - 2), 1);
if iFrom < 0 then
iFrom := sOrig.Length + iFrom + 1;
iTo := StrToIntDef(Copy(sFormatStr, iDelim + 1, MaxSmallint), MaxSmallint);
if iTo < 0 then
iTo := sOrig.Length + iTo + 1;
;
if iTo < iFrom then
begin
iDelim := iTo;
iTo := iFrom;
iFrom := iDelim;
end;
end;
Result := UTF8Copy(sOrig, iFrom, iTo - iFrom + 1);
end;
end;
{ TfrmMultiRename.sReplaceVariable }
function TfrmMultiRename.sReplaceVariable(const sFormatStr: string): string;
var
iDelim, iVariableIndex, iVariableSuggestionIndex: integer;
sVariableName: string = '';
sVariableValue: string = '';
begin
Result := '';
iDelim := Pos(':', sFormatStr);
if iDelim <> 0 then
sVariableName := copy(sFormatStr, succ(iDelim), length(sFormatStr) - iDelim)
else
sVariableName := rsSimpleWordVariable;
iVariableIndex := FslVariableNames.IndexOf(sVariableName);
if iVariableIndex = -1 then
begin
iVariableSuggestionIndex := FslVariableSuggestionName.IndexOf(sVariableName);
if iVariableSuggestionIndex <> -1 then
sVariableValue := FslVariableSuggestionValue.Strings[iVariableSuggestionIndex]
else
sVariableValue := sVariableName;
if InputQuery(rsMulRenDefineVariableValue, Format(rsMulRenEnterValueForVar, [sVariableName]), sVariableValue) then
begin
FslVariableNames.Add(sVariableName);
iVariableIndex := FslVariableValues.Add(sVariableValue);
if iVariableSuggestionIndex = -1 then
begin
FslVariableSuggestionName.Add(sVariableName);
FslVariableSuggestionValue.Add(sVariableValue);
end;
end
else
begin
FActuallyRenamingFile := False;
exit;
end;
end;
Result := FslVariableValues.Strings[iVariableIndex];
end;
{ TfrmMultiRename.sReplaceBadChars }//Replace bad path chars in string
function TfrmMultiRename.sReplaceBadChars(const sPath: string): string;
const
{$IFDEF MSWINDOWS}
ForbiddenChars: set of char = ['<', '>', ':', '"', '/', '\', '|', '?', '*'];
{$ELSE}
ForbiddenChars: set of char = ['/'];
{$ENDIF}
var
Index: integer;
begin
Result := '';
for Index := 1 to Length(sPath) do
if not (sPath[Index] in ForbiddenChars) then
Result += sPath[Index]
else
Result += gMulRenInvalidCharReplacement;
end;
{ TfrmMultiRename.IsLetter }
function TfrmMultiRename.IsLetter(AChar: AnsiChar): boolean;
begin
Result := // Ascii letters
((AChar < #128) and
(((AChar >= 'a') and (AChar <= 'z')) or
((AChar >= 'A') and (AChar <= 'Z')))) or
// maybe Ansi or UTF8
(AChar >= #128);
end;
{ TfrmMultiRename.ApplyStyle }
// Applies style (uppercase, lowercase, etc.) to a string.
function TfrmMultiRename.ApplyStyle(InputString: string; Style: integer): string;
begin
case Style of
1: Result := UTF8UpperCase(InputString);
2: Result := UTF8LowerCase(InputString);
3: Result := FirstCharOfFirstWordToUppercaseUTF8(InputString);
4: Result := FirstCharOfEveryWordToUppercaseUTF8(InputString);
else
Result := InputString;
end;
end;
{ TfrmMultiRename.FirstCharToUppercaseUTF8 }
// Changes first char to uppercase and the rest to lowercase
function TfrmMultiRename.FirstCharToUppercaseUTF8(InputString: string): string;
var
FirstChar: string;
begin
if UTF8Length(InputString) > 0 then
begin
Result := UTF8LowerCase(InputString);
FirstChar := UTF8Copy(Result, 1, 1);
UTF8Delete(Result, 1, 1);
Result := UTF8UpperCase(FirstChar) + Result;
end
else
Result := '';
end;
{ TfrmMultiRename.FirstCharOfFirstWordToUppercaseUTF8 }
// Changes first char of first word to uppercase and the rest to lowercase
function TfrmMultiRename.FirstCharOfFirstWordToUppercaseUTF8(InputString: string): string;
var
SeparatorPos: integer;
begin
InputString := UTF8LowerCase(InputString);
Result := '';
// Search for first letter.
for SeparatorPos := 1 to Length(InputString) do
if IsLetter(InputString[SeparatorPos]) then
break;
Result := Copy(InputString, 1, SeparatorPos - 1) + FirstCharToUppercaseUTF8(Copy(InputString, SeparatorPos, Length(InputString) - SeparatorPos + 1));
end;
{ TfrmMultiRename.FirstCharOfEveryWordToUppercaseUTF8 }
// Changes first char of every word to uppercase and the rest to lowercase
function TfrmMultiRename.FirstCharOfEveryWordToUppercaseUTF8(InputString: string): string;
var
SeparatorPos: integer;
begin
InputString := UTF8LowerCase(InputString);
Result := '';
while InputString <> '' do
begin
// Search for first non-letter (word separator).
for SeparatorPos := 1 to Length(InputString) do
if not IsLetter(InputString[SeparatorPos]) then
break;
Result := Result + FirstCharToUppercaseUTF8(Copy(InputString, 1, SeparatorPos));
Delete(InputString, 1, SeparatorPos);
end;
end;
procedure TfrmMultiRename.LoadNamesFromList(const AFileList: TStrings);
begin
if AFileList.Count <> FFiles.Count then
begin
msgError(Format(rsMulRenWrongLinesNumber, [AFileList.Count, FFiles.Count]));
end
else
begin
FNames.Assign(AFileList);
gbMaska.Enabled := False;
gbPresets.Enabled := False;
gbCounter.Enabled := False;
StringGridTopLeftChanged(StringGrid);
end;
end;
{ TfrmMultiRename.LoadNamesFromFile }
procedure TfrmMultiRename.LoadNamesFromFile(const AFileName: string);
var
AFileList: TStringListEx;
begin
AFileList := TStringListEx.Create;
try
AFileList.LoadFromFile(AFileName);
LoadNamesFromList(AFileList);
except
on E: Exception do
msgError(E.Message);
end;
AFileList.Free;
end;
{ TfrmMultiRename.FreshText }
function TfrmMultiRename.FreshText(ItemIndex: integer): string;
var
I: integer;
bError: boolean;
wsText: UnicodeString;
wsReplace: UnicodeString;
Flags: TReplaceFlags = [];
sTmpName, sTmpExt: string;
begin
bError := False;
if FNames.Count > 0 then
Result := FNames[ItemIndex]
else
begin
// Use mask
sTmpName := sReplace(cbName.Text, ItemIndex);
sTmpExt := sReplace(cbExt.Text, ItemIndex);
// Join
Result := sTmpName;
if sTmpExt <> '' then
Result := Result + '.' + sTmpExt;
end;
// Find and replace
if (edFind.Text <> '') then
begin
if cbRepExt.Checked then
sTmpName := Result
else begin
sTmpExt := ExtractFileExt(Result);
sTmpName := Copy(Result, 1, Length(Result) - Length(sTmpExt));
end;
if cbRegExp.Checked then
try
wsText:= CeUtf8ToUtf16(sTmpName);
wsReplace:= CeUtf8ToUtf16(edReplace.Text);
FRegExp.ModifierI := not cbCaseSens.Checked;
if not cbOnlyFirst.Checked then
begin
sTmpName := CeUtf16ToUtf8(FRegExp.Replace(wsText, wsReplace, cbUseSubs.Checked));
end
else if FRegExp.Exec(wsText) then
begin
Delete(wsText, FRegExp.MatchPos[0], FRegExp.MatchLen[0]);
if cbUseSubs.Checked then
Insert(FRegExp.Substitute(wsReplace), wsText, FRegExp.MatchPos[0])
else begin
Insert(wsReplace, wsText, FRegExp.MatchPos[0]);
end;
sTmpName:= CeUtf16ToUtf8(wsText);
end;
except
Result := rsMsgErrRegExpSyntax;
bError := True;
end
else begin
if not cbOnlyFirst.Checked then
Flags:= [rfReplaceAll];
if not cbCaseSens.Checked then
Flags+= [rfIgnoreCase];
// Many at once, split find and replace by |
if (FReplaceText.Count = 0) then
FReplaceText.Add('');
for I := 0 to FFindText.Count - 1 do
sTmpName := UTF8StringReplace(sTmpName, FFindText[I], FReplaceText[Min(I, FReplaceText.Count - 1)], Flags);
end;
if not bError then
begin
if cbRepExt.Checked then
Result := sTmpName
else begin
Result := sTmpName + sTmpExt;
end;
end;
end;
if not bError then
begin
// File name style
sTmpExt := ExtractFileExt(Result);
sTmpName := Copy(Result, 1, Length(Result) - Length(sTmpExt));
sTmpName := ApplyStyle(sTmpName, cbNameMaskStyle.ItemIndex);
sTmpExt := ApplyStyle(sTmpExt, cmbExtensionStyle.ItemIndex);
Result := sTmpName + sTmpExt;
end;
actRename.Enabled := not bError;
if bError then
begin
edFind.Color := clRed;
edFind.Font.Color := clWhite;
end
else
begin
edFind.Color := clDefault;
edFind.Font.Color := clDefault;
end;
end;
{ TfrmMultiRename.sHandleFormatString }
function TfrmMultiRename.sHandleFormatString(const sFormatStr: string; ItemNr: integer): string;
var
aFile: TFile;
Index: int64;
Counter: int64;
Dirs: TStringArray;
begin
Result := '';
if Length(sFormatStr) > 0 then
begin
aFile := FFiles[ItemNr];
case sFormatStr[1] of
'[', ']':
begin
Result := sFormatStr;
end;
'N':
begin
Result := sReplaceXX(sFormatStr, aFile.NameNoExt);
end;
'E':
begin
Result := sReplaceXX(sFormatStr, aFile.Extension);
end;
'A':
begin
Result := sReplaceBadChars(sReplaceXX(sFormatStr, aFile.FullPath));
end;
'G':
begin
Result := GuidToString(DCGetNewGUID);
end;
'V':
begin
if FActuallyRenamingFile then
Result := sReplaceVariable(sFormatStr)
else
Result := '[' + sFormatStr + ']';
end;
'C':
begin
// Check for start value after C, e.g. C12
if not TryStrToInt64(Copy(sFormatStr, 2, MaxInt), Index) then
Index := StrToInt64Def(edPoc.Text, 1);
Counter := Index + StrToInt64Def(edInterval.Text, 1) * ItemNr;
Result := Format('%.' + cmbxWidth.Items[cmbxWidth.ItemIndex] + 'd', [Counter]);
end;
'P': // sub path index
begin
Index := StrToIntDef(Copy(sFormatStr, 2, MaxInt), 0);
Dirs := (aFile.Path + ' ').Split([PathDelim]);
Dirs[High(Dirs)] := EmptyStr;
if Index < 0 then
Result := Dirs[Max(0, High(Dirs) + Index)]
else
Result := Dirs[Min(Index, High(Dirs))];
end;
'=':
begin
Result := sReplaceBadChars(FormatFileFunction(UTF8Copy(sFormatStr, 2, UTF8Length(sFormatStr) - 1), FFiles.Items[ItemNr], FFileSource, True));
end;
else
begin
// Assume it is date/time formatting string ([h][n][s][Y][M][D]).
with FFiles.Items[ItemNr] do
if fpModificationTime in SupportedProperties then
try
Result := SysToUTF8(FormatDateTime(sFormatStr, ModificationTime));
except
Result := sFormatStr;
end;
end;
end;
end;
end;
{ TfrmMultiRename.SetFilePropertyResult }
procedure TfrmMultiRename.SetFilePropertyResult(Index: integer; aFile: TFile; aTemplate: TFileProperty; Result: TSetFilePropertyResult);
var
sFilenameForLog, S: string;
begin
with TFileNameProperty(aTemplate) do
begin
if cbLog.Checked then
if gMulRenFilenameWithFullPathInLog then
sFilenameForLog := aFile.FullPath
else
sFilenameForLog := aFile.Name;
case Result of
sfprSuccess:
begin
S := 'OK ' + sFilenameForLog + ' -> ' + Value;
if Index < FFiles.Count then
FFiles[Index].Name := Value // Write new name to the file object
else
begin
Index := StrToInt(aFile.Extension);
FFiles[Index].Name := Value; // Write new name to the file object
end;
end;
sfprError: S := 'FAILED ' + sFilenameForLog + ' -> ' + Value;
sfprSkipped: S := 'SKIPPED ' + sFilenameForLog + ' -> ' + Value;
end;
end;
if cbLog.Checked then
FLog.Add(S);
end;
{ TfrmMultiRename.SetOutputGlobalRenameLogFilename }
procedure TfrmMultiRename.SetOutputGlobalRenameLogFilename;
begin
if gMultRenDailyIndividualDirLog then
fneRenameLogFileFilename.FileName := mbExpandFileName(ExtractFilePath(gMulRenLogFilename) + IncludeTrailingPathDelimiter(EnvVarTodaysDate) + ExtractFilename(gMulRenLogFilename))
else
fneRenameLogFileFilename.FileName := gMulRenLogFilename;
end;
{ TfrmMultiRename.cm_ResetAll }
procedure TfrmMultiRename.cm_ResetAll(const Params: array of string);
var
Param: string;
bNeedRefreshActivePresetCommands: boolean = True;
begin
for Param in Params do
GetParamBoolValue(Param, sREFRESHCOMMANDS, bNeedRefreshActivePresetCommands);
cbName.Text := '[N]';
cbName.SelStart := UTF8Length(cbName.Text);
cbExt.Text := '[E]';
cbExt.SelStart := UTF8Length(cbExt.Text);
edFind.Text := '';
edReplace.Text := '';
cbRepExt.Checked := True;
cbRegExp.Checked := False;
cbUseSubs.Checked := False;
cbCaseSens.Checked := False;
cbOnlyFirst.Checked := False;
cbNameMaskStyle.ItemIndex := 0;
cmbExtensionStyle.ItemIndex := 0;
edPoc.Text := '1';
edInterval.Text := '1';
cmbxWidth.ItemIndex := 0;
case gMulRenSaveRenamingLog of
mrsrlPerPreset:
begin
cbLog.Checked := False;
cbLog.Enabled := True;
cbLogAppend.Checked := False;
fneRenameLogFileFilename.Enabled := cbLog.Checked;
actInvokeRelativePath.Enabled := cbLog.Checked;
actViewRenameLogFile.Enabled := cbLog.Checked;
cbLogAppend.Enabled := cbLog.Checked;
if (FFiles.Count > 0) then
fneRenameLogFileFilename.FileName := FFiles[0].Path + sDEFAULTLOGFILENAME
else
fneRenameLogFileFilename.FileName := sDEFAULTLOGFILENAME;
end;
mrsrlAppendSameLog:
begin
cbLog.Checked := True;
cbLog.Enabled := False;
cbLogAppend.Checked := True;
cbLogAppend.Enabled := False;
fneRenameLogFileFilename.Enabled := False;
SetOutputGlobalRenameLogFilename;
actInvokeRelativePath.Enabled := False;
actViewRenameLogFile.Enabled := cbLog.Checked;
end;
end;
cbPresets.Text := '';
FNames.Clear;
gbMaska.Enabled := True;
gbPresets.Enabled := True;
cbPresets.ItemIndex := 0;
gbCounter.Enabled := True;
StringGridTopLeftChanged(StringGrid);
if bNeedRefreshActivePresetCommands then
RefreshActivePresetCommands;
end;
{ TfrmMultiRename.cm_InvokeEditor }
procedure TfrmMultiRename.cm_InvokeEditor(const {%H-}Params: array of string);
begin
DCPlaceCursorNearControlIfNecessary(btnEditor);
pmEditDirect.PopUp;
end;
{ TfrmMultiRename.cm_LoadNamesFromFile }
procedure TfrmMultiRename.cm_LoadNamesFromFile(const {%H-}Params: array of string);
begin
dmComData.OpenDialog.FileName := EmptyStr;
dmComData.OpenDialog.Filter := AllFilesMask;
if dmComData.OpenDialog.Execute then
LoadNamesFromFile(dmComData.OpenDialog.FileName);
end;
procedure TfrmMultiRename.cm_LoadNamesFromClipboard(
const Params: array of string);
var
AFileList: TStringListEx;
begin
AFileList := TStringListEx.Create;
try
AFileList.Text := Clipboard.AsText;
LoadNamesFromList(AFileList);
except
on E: Exception do
msgError(E.Message);
end;
AFileList.Free;
end;
{ TfrmMultiRename.cm_EditNames }
procedure TfrmMultiRename.cm_EditNames(const {%H-}Params: array of string);
var
I: integer;
AFileName: string;
AFileList: TStringListEx;
begin
AFileList := TStringListEx.Create;
AFileName := GetTempFolderDeletableAtTheEnd;
AFileName := GetTempName(AFileName, 'txt');
if FNames.Count > 0 then
AFileList.Assign(FNames)
else
begin
for I := 0 to FFiles.Count - 1 do
AFileList.Add(FFiles[I].Name);
end;
try
AFileList.SaveToFile(AFileName);
try
if ShowMultiRenameWaitForm(AFileName, Self) then
LoadNamesFromFile(AFileName);
finally
mbDeleteFile(AFileName);
end;
except
on E: Exception do
msgError(E.Message);
end;
AFileList.Free;
end;
{ TfrmMultiRename.cm_EditNewNames }
procedure TfrmMultiRename.cm_EditNewNames(const {%H-}Params: array of string);
var
sFileName: string;
iIndexFile: integer;
AFileList: TStringListEx;
begin
AFileList := TStringListEx.Create;
try
for iIndexFile := 0 to pred(FFiles.Count) do
AFileList.Add(FreshText(iIndexFile));
sFileName := GetTempName(GetTempFolderDeletableAtTheEnd, 'txt');
try
AFileList.SaveToFile(sFileName);
try
if ShowMultiRenameWaitForm(sFileName, Self) then
LoadNamesFromFile(sFileName);
finally
mbDeleteFile(sFileName);
end;
except
on E: Exception do
msgError(E.Message);
end;
finally
AFileList.Free;
end;
end;
{ TfrmMultiRename.cm_Config }
procedure TfrmMultiRename.cm_Config(const {%H-}Params: array of string);
begin
frmMain.Commands.cm_Options(['TfrmOptionsMultiRename']);
end;
{ TfrmMultiRename.cm_Rename }
procedure TfrmMultiRename.cm_Rename(const {%H-}Params: array of string);
var
AFile: TFile;
NewName: string;
I, J, K: integer;
TempFiles: TStringList;
OldFiles, NewFiles: TFiles;
AutoRename: boolean = False;
Operation: TFileSourceOperation;
theNewProperties: TFileProperties;
LogFileStream: TFileStream;
begin
FActuallyRenamingFile := True;
try
if cbLog.Checked then
begin
if fneRenameLogFileFilename.FileName = EmptyStr then
fneRenameLogFileFilename.FileName := FFiles[0].Path + sDEFAULTLOGFILENAME;
mbForceDirectory(ExtractFileDir(mbExpandFileName(fneRenameLogFileFilename.FileName)));
FLog := TStringListEx.Create;
if cbLogAppend.Checked then
FLog.Add(';' + DateTimeToStr(Now) + ' - ' + rsMulRenLogStart);
end;
OldFiles := FFiles.Clone;
TempFiles := TStringList.Create;
NewFiles := TFiles.Create(EmptyStr);
FslVariableNames.Clear;
FslVariableValues.Clear; //We don't clear the "Suggestion" parts because we may re-use them as their original values if we ever re-do rename pass witht he same instance.
// OldNames
FOldNames.Clear;
for I := 0 to OldFiles.Count - 1 do
FOldNames.Add(OldFiles[I].Name, Pointer(PtrInt(I)));
try
FNewNames.Clear;
for I := 0 to FFiles.Count - 1 do
begin
AFile := TFile.Create(EmptyStr);
AFile.Name := FreshText(I);
//In "FreshText", if there was a "Variable on the fly / [V:Hint]" and the user aborted it, the "FActuallyRenamingFile" will be cleared and so we abort the actual renaming process.
if not FActuallyRenamingFile then
Exit;
// Checking duplicates
NewName := FFiles[I].Path + AFile.Name;
J := FNewNames.Find(NewName);
if J < 0 then
FNewNames.Add(NewName)
else
begin
if not AutoRename then
begin
if MessageDlg(rsMulRenWarningDuplicate + LineEnding +
NewName + LineEnding + LineEnding + rsMulRenAutoRename,
mtWarning, [mbYes, mbAbort], 0, mbAbort) <> mrYes then
Exit;
AutoRename := True;
end;
K := 1;
while J >= 0 do
begin
NewName := FFiles[I].Path + AFile.NameNoExt + ' (' + IntToStr(K) + ')';
if AFile.Extension <> '' then
NewName := NewName + ExtensionSeparator + AFile.Extension;
J := FNewNames.Find(NewName);
Inc(K);
end;
FNewNames.Add(NewName);
AFile.Name := ExtractFileName(NewName);
end;
// Avoid collisions with OldNames
J := FOldNames.Find(AFile.Name);
if (J >= 0) and (PtrUInt(FOldNames.List[J]^.Data) <> I) then
begin
NewName := AFile.Name;
// Generate temp file name, save file index as extension
AFile.FullPath := GetTempName(FFiles[I].Path, IntToStr(I));
TempFiles.AddObject(NewName, AFile.Clone);
end;
NewFiles.Add(AFile);
end;
// Rename temp files back
if TempFiles.Count > 0 then
begin
for I := 0 to TempFiles.Count - 1 do
begin
// Temp file name
OldFiles.Add(TFile(TempFiles.Objects[I]));
// Real new file name
AFile := TFile.Create(EmptyStr);
AFile.Name := TempFiles[I];
NewFiles.Add(AFile);
end;
end;
// Rename files
FillChar({%H-}theNewProperties, SizeOf(TFileProperties), 0);
Operation := FFileSource.CreateSetFilePropertyOperation(OldFiles, theNewProperties);
if Assigned(Operation) then
begin
with Operation as TFileSourceSetFilePropertyOperation do
begin
SetTemplateFiles(NewFiles);
OnSetFilePropertyResult := @SetFilePropertyResult;
end;
OperationsManager.AddOperationModal(Operation);
end;
InsertFirstItem(cbExt.Text, cbExt);
InsertFirstItem(cbName.Text, cbName);
finally
if cbLog.Checked then
begin
try
if (cbLogAppend.Checked) and (FileExists(mbExpandFileName(fneRenameLogFileFilename.FileName))) then
begin
LogFileStream := TFileStream.Create(mbExpandFileName(fneRenameLogFileFilename.FileName), fmOpenWrite);
try
LogFileStream.Seek(0, soEnd);
FLog.SaveToStream(LogFileStream);
finally
LogFileStream.Free;
end;
end
else
begin
FLog.SaveToFile(mbExpandFileName(fneRenameLogFileFilename.FileName));
end;
except
on E: Exception do
msgError(E.Message);
end;
FLog.Free;
end;
OldFiles.Free;
NewFiles.Free;
TempFiles.Free;
end;
finally
FActuallyRenamingFile := False;
end;
StringGridTopLeftChanged(StringGrid);
end;
{ TfrmMultiRename.cm_Close }
procedure TfrmMultiRename.cm_Close(const {%H-}Params: array of string);
begin
Close;
end;
{ TfrmMultiRename.cm_ShowPresetsMenu }
procedure TfrmMultiRename.cm_ShowPresetsMenu(const {%H-}Params: array of string);
begin
PopupDynamicMenuAtThisControl(pmPresets, btnPresets);
end;
{ TfrmMultiRename.cm_DropDownPresetList }
procedure TfrmMultiRename.cm_DropDownPresetList(const {%H-}Params: array of string);
begin
if (not cbPresets.CanFocus) and (not cbPresets.Enabled) then
if isOkToLosePresetModification = True then
cbPresets.Enabled := True;
if cbPresets.CanFocus then
begin
cbPresets.SetFocus;
cbPresets.DroppedDown := True;
end;
end;
{ TfrmMultiRename.cm_LoadPreset }
procedure TfrmMultiRename.cm_LoadPreset(const Params: array of string);
var
sPresetName: string;
PresetIndex: integer;
begin
if isOkToLosePresetModification then
begin
//1.Get the preset name from the parameters.
sPresetName := GetPresetNameForCommand(Params);
//2.Make sure we got something.
if sPresetName <> '' then
begin
//3.Make sure it is in our list.
PresetIndex := FMultiRenamePresetList.Find(sPresetName);
if PresetIndex <> -1 then
begin
cbName.Text := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].FileName;
cbName.SelStart := UTF8Length(cbName.Text);
cbExt.Text := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Extension;
cbExt.SelStart := UTF8Length(cbExt.Text);
cbNameMaskStyle.ItemIndex := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].FileNameStyle;
cmbExtensionStyle.ItemIndex := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].ExtensionStyle;
edFind.Text := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Find;
edReplace.Text := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Replace;
cbRepExt.Checked := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].RepExt;
cbRegExp.Checked := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].RegExp;
cbUseSubs.Checked := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].UseSubs;
cbCaseSens.Checked := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].CaseSens;
cbOnlyFirst.Checked := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].OnlyFirst;
edPoc.Text := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Counter;
edInterval.Text := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Interval;
cmbxWidth.ItemIndex := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Width;
case gMulRenSaveRenamingLog of
mrsrlPerPreset:
begin
cbLog.Checked := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Log;
cbLogAppend.Checked := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].LogAppend;
fneRenameLogFileFilename.FileName := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].LogFile;
end;
mrsrlAppendSameLog:
begin
FbRememberLog := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].Log;
FbRememberAppend := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].LogAppend;
FsRememberRenameLogFilename := FMultiRenamePresetList.MultiRenamePreset[PresetIndex].LogFile;
SetOutputGlobalRenameLogFilename;
end;
end;
//4.Preserved the last loaded setup.
FLastPreset := sPresetName;
//5.Refresh the whole thing.
edFindChange(edFind);
edReplaceChange(edReplace);
//6.We might come here with parameter "index=x" so make sure we switch also the preset combo box to the same index.
if PresetIndex >= cbPresets.Items.Count then
PresetIndex := 0;
if cbPresets.ItemIndex <> PresetIndex then
cbPresets.ItemIndex := PresetIndex;
//7.Since we've load the setup, activate things so we may change setup if necessary.
SetConfigurationState(CONFIG_SAVED);
//8. If we're from anything else the preset droplist itself, let's go to focus on the name ready to edit it if necessary..
if (ActiveControl <> cbPresets) and (ActiveControl <> cbName) and (cbName.Enabled and gbMaska.Enabled) then
begin
ActiveControl := cbName;
cbName.SelStart := UTF8Length(cbName.Text);
end;
end;
end;
end;
end;
{ TfrmMultiRename.cm_LoadLastPreset }
procedure TfrmMultiRename.cm_LoadLastPreset(const Params: array of string);
begin
cm_LoadPreset(['index=0']);
end;
{ TfrmMultiRename.cm_LoadPreset1 }
procedure TfrmMultiRename.cm_LoadPreset1(const Params: array of string);
begin
cm_LoadPreset(['index=1']);
end;
{ TfrmMultiRename.cm_LoadPreset2 }
procedure TfrmMultiRename.cm_LoadPreset2(const Params: array of string);
begin
cm_LoadPreset(['index=2']);
end;
{ TfrmMultiRename.cm_LoadPreset3 }
procedure TfrmMultiRename.cm_LoadPreset3(const Params: array of string);
begin
cm_LoadPreset(['index=3']);
end;
{ TfrmMultiRename.cm_LoadPreset4 }
procedure TfrmMultiRename.cm_LoadPreset4(const Params: array of string);
begin
cm_LoadPreset(['index=4']);
end;
{ TfrmMultiRename.cm_LoadPreset5 }
procedure TfrmMultiRename.cm_LoadPreset5(const Params: array of string);
begin
cm_LoadPreset(['index=5']);
end;
{ TfrmMultiRename.cm_LoadPreset6 }
procedure TfrmMultiRename.cm_LoadPreset6(const Params: array of string);
begin
cm_LoadPreset(['index=6']);
end;
{ TfrmMultiRename.cm_LoadPreset7 }
procedure TfrmMultiRename.cm_LoadPreset7(const Params: array of string);
begin
cm_LoadPreset(['index=7']);
end;
{ TfrmMultiRename.cm_LoadPreset8 }
procedure TfrmMultiRename.cm_LoadPreset8(const Params: array of string);
begin
cm_LoadPreset(['index=8']);
end;
{ TfrmMultiRename.cm_LoadPreset9 }
procedure TfrmMultiRename.cm_LoadPreset9(const Params: array of string);
begin
cm_LoadPreset(['index=9']);
end;
{ TfrmMultiRename.cm_SavePreset }
procedure TfrmMultiRename.cm_SavePreset(const Params: array of string);
begin
if cbPresets.ItemIndex > 0 then
begin
SavePreset(cbPresets.Items.Strings[cbPresets.ItemIndex]);
SetConfigurationState(CONFIG_SAVED);
end;
end;
{ TfrmMultiRename.cm_SavePresetAs }
procedure TfrmMultiRename.cm_SavePresetAs(const Params: array of string);
var
sNameForPreset: string;
bKeepGoing: boolean;
begin
sNameForPreset := GetPresetNameForCommand(Params);
if sNameForPreset <> '' then
begin
bKeepGoing := True;
end
else
begin
if (FLastPreset = '') or (FLastPreset = sLASTPRESET) then
sNameForPreset := rsMulRenDefaultPresetName
else
sNameForPreset := FLastPreset;
bKeepGoing := InputQuery(Caption, rsMulRenPromptForSavedPresetName, sNameForPreset);
if bKeepGoing then bKeepGoing := (sNameForPreset <> '');
end;
if bKeepGoing and (sNameForPreset <> FLastPreset) then
if FMultiRenamePresetList.Find(sNameForPreset) <> -1 then
if not msgYesNo(Format(rsMsgPresetAlreadyExists, [sNameForPreset]), msmbNo) then
bKeepGoing := False;
if bKeepGoing then
begin
SavePreset(sNameForPreset);
if cbPresets.Items.IndexOf(sNameForPreset) = -1 then
begin
cbPresets.Items.Add(sNameForPreset);
end;
if cbPresets.ItemIndex <> cbPresets.Items.IndexOf(sNameForPreset) then
cbPresets.ItemIndex := cbPresets.Items.IndexOf(sNameForPreset);
SetConfigurationState(CONFIG_SAVED);
RefreshActivePresetCommands;
end;
end;
{ TfrmMultiRename.cm_RenamePreset }
// It also allow the at the same time to rename for changing case like "audio files" to "Audio Files".
procedure TfrmMultiRename.cm_RenamePreset(const Params: array of string);
var
sCurrentName, sNewName: string;
PresetIndex: integer;
bKeepGoing: boolean;
begin
sCurrentName := cbPresets.Items.Strings[cbPresets.ItemIndex];
sNewName := sCurrentName;
bKeepGoing := InputQuery(Caption, rsMulRenPromptNewPresetName, sNewName);
if bKeepGoing and (sNewName <> '') and (sCurrentName <> sNewName) then
begin
PresetIndex := FMultiRenamePresetList.Find(sNewName);
if (PresetIndex = -1) or (SameText(sCurrentName, sNewName)) then
begin
if SameText(FMultiRenamePresetList.MultiRenamePreset[cbPresets.ItemIndex].PresetName, cbPresets.Items.Strings[cbPresets.ItemIndex]) then
begin
FMultiRenamePresetList.MultiRenamePreset[cbPresets.ItemIndex].PresetName := sNewName;
cbPresets.Items.Strings[cbPresets.ItemIndex] := sNewName;
end;
end
else
begin
if msgYesNo(rsMulRenPromptNewNameExists, msmbNo) then
begin
if SameText(FMultiRenamePresetList.MultiRenamePreset[PresetIndex].PresetName, cbPresets.Items.Strings[PresetIndex]) and SameText(FMultiRenamePresetList.MultiRenamePreset[cbPresets.ItemIndex].PresetName, cbPresets.Items.Strings[cbPresets.ItemIndex]) then
begin
FMultiRenamePresetList.MultiRenamePreset[cbPresets.ItemIndex].PresetName := sNewName;
cbPresets.Items.Strings[cbPresets.ItemIndex] := sNewName;
cbPresets.Items.Delete(PresetIndex);
FMultiRenamePresetList.Delete(PresetIndex);
end;
end;
end;
end;
end;
{ TfrmMultiRename.cm_DeletePreset }
procedure TfrmMultiRename.cm_DeletePreset(const Params: array of string);
var
Index: integer;
sPresetName: string;
begin
sPresetName := GetPresetNameForCommand(Params);
if sPresetName = '' then
if cbPresets.ItemIndex > 0 then
sPresetName := cbPresets.Items.Strings[cbPresets.ItemIndex];
if sPresetName <> '' then
begin
if msgYesNo(Format(rsMsgPresetConfigDelete, [sPresetName]), msmbNo) then
begin
DeletePreset(sPresetName);
Index := cbPresets.Items.IndexOf(sPresetName);
if Index = cbPresets.ItemIndex then
cbPresets.ItemIndex := 0;
if Index <> -1 then
cbPresets.Items.Delete(Index);
FillPresetsList;
end;
end;
end;
{ TfrmMultiRename.cm_SortPresets }
procedure TfrmMultiRename.cm_SortPresets(const Params: array of string);
var
slLocalPresets: TStringList;
iSeeker, iPresetIndex: integer;
begin
if isOkToLosePresetModification then
begin
if FMultiRenamePresetList.Count > 1 then
begin
slLocalPresets := TStringList.Create;
try
for iSeeker := 1 to pred(FMultiRenamePresetList.Count) do
slLocalPresets.Add(FMultiRenamePresetList.MultiRenamePreset[iSeeker].PresetName);
if HaveUserSortThisList(Self, rsMulRenSortingPresets, slLocalPresets) = mrOk then
begin
for iSeeker := 0 to pred(slLocalPresets.Count) do
begin
iPresetIndex := FMultiRenamePresetList.Find(slLocalPresets.Strings[iSeeker]);
if succ(iSeeker) <> iPresetIndex then
FMultiRenamePresetList.Move(iPresetIndex, succ(iSeeker));
end;
FillPresetsList(cbPresets.Items.Strings[cbPresets.ItemIndex]);
end;
finally
slLocalPresets.Free;
end;
end;
end;
end;
{ TfrmMultiRename.cm_AnyNameMask }
procedure TfrmMultiRename.cm_AnyNameMask(const {%H-}Params: array of string);
begin
pmFloatingMainMaskMenu.Items.Clear;
PopulateFilenameMenu(pmFloatingMainMaskMenu);
PopupDynamicMenuAtThisControl(pmFloatingMainMaskMenu, btnAnyNameMask);
end;
{ TfrmMultiRename.cm_NameNameMask }
procedure TfrmMultiRename.cm_NameNameMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmFilename, rmtuFilename);
end;
{ TfrmMultiRename.cm_ExtNameMask }
procedure TfrmMultiRename.cm_ExtNameMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmFilename, rmtuExtension);
end;
{ TfrmMultiRename.cm_CtrNameMask }
procedure TfrmMultiRename.cm_CtrNameMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmFilename, rmtuCounter);
end;
{ TfrmMultiRename.cm_DateNameMask }
procedure TfrmMultiRename.cm_DateNameMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmFilename, rmtuDate);
end;
{ TfrmMultiRename.cm_TimeNameMask }
procedure TfrmMultiRename.cm_TimeNameMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmFilename, rmtuTime);
end;
{ TfrmMultiRename.cm_PlgnNameMask }
procedure TfrmMultiRename.cm_PlgnNameMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmFilename, rmtuPlugins);
end;
{ TfrmMultiRename.cm_ClearNameMask }
procedure TfrmMultiRename.cm_ClearNameMask(const {%H-}Params: array of string);
begin
cbName.Text := '';
cbNameStyleChange(cbExt);
if cbName.CanFocus then
cbName.SetFocus;
end;
{ TfrmMultiRename.cm_AnyExtMask }
procedure TfrmMultiRename.cm_AnyExtMask(const {%H-}Params: array of string);
begin
pmFloatingMainMaskMenu.Items.Clear;
PopulateExtensionMenu(pmFloatingMainMaskMenu);
PopupDynamicMenuAtThisControl(pmFloatingMainMaskMenu, btnAnyExtMask);
end;
{ TfrmMultiRename.cm_NameExtMask }
procedure TfrmMultiRename.cm_NameExtMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmExtension, rmtuFilename);
end;
{ TfrmMultiRename.cm_ExtExtMask }
procedure TfrmMultiRename.cm_ExtExtMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmExtension, rmtuExtension);
end;
{ TfrmMultiRename.cm_CtrExtMask }
procedure TfrmMultiRename.cm_CtrExtMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmExtension, rmtuCounter);
end;
{ TfrmMultiRename.cm_DateExtMask }
procedure TfrmMultiRename.cm_DateExtMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmExtension, rmtuDate);
end;
{ TfrmMultiRename.cm_TimeExtMask }
procedure TfrmMultiRename.cm_TimeExtMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmExtension, rmtuTime);
end;
{ TfrmMultiRename.cm_PlgnExtMask }
procedure TfrmMultiRename.cm_PlgnExtMask(const {%H-}Params: array of string);
begin
BuildMenuAndPopup(tfmExtension, rmtuPlugins);
end;
{ TfrmMultiRename.cm_ClearExtMask }
procedure TfrmMultiRename.cm_ClearExtMask(const {%H-}Params: array of string);
begin
cbExt.Text := '';
cbNameStyleChange(cbExt);
if cbExt.CanFocus then cbExt.SetFocus;
end;
{ TfrmMultiRename.cm_ViewRenameLogFile }
procedure TfrmMultiRename.cm_ViewRenameLogFile(const {%H-}Params: array of string);
var
sRenameLogFilename: string;
begin
sRenameLogFilename := mbExpandFileName(fneRenameLogFileFilename.FileName);
if FileExists(sRenameLogFilename) then
ShowViewerByGlob(sRenameLogFilename)
else
MsgError(Format(rsMsgFileNotFound, [sRenameLogFilename]));
end;
{ ShowMultiRenameForm }
// Will be in fact the lone function called externally to launch a MultiRename dialog.
function ShowMultiRenameForm(aFileSource: IFileSource; var aFiles: TFiles; const PresetToLoad: string = ''): boolean;
begin
Result := True;
try
with TfrmMultiRename.Create(Application, aFileSource, aFiles, PresetToLoad) do
begin
Show;
end;
except
Result := False;
end;
end;
initialization
TFormCommands.RegisterCommandsForm(TfrmMultiRename, HotkeysCategoryMultiRename, @rsHotkeyCategoryMultiRename);
end.