doublecmd/src/fcopymovedlg.pas

483 lines
14 KiB
ObjectPascal

{
Double Commander
-------------------------------------------------------------------------
Dialog window when copying/moving files confirming filenames and other options
Copyright (C) 2009-2019 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/>.
}
unit fCopyMoveDlg;
{$mode objfpc}{$H+}
interface
uses
SysUtils, Classes, Controls, Forms, StdCtrls, Buttons, ExtCtrls, Menus,
ActnList, KASPathEdit, uFileSource, uFileViewNotebook, uFileSourceOperation,
uFileSourceOperationOptionsUI, uOperationsManager, uFormCommands;
type
TCopyMoveDlgType = (cmdtCopy, cmdtMove);
TCurrentCopyDlgNameSelectionStep = (ccdnssWholeCompleteFilename, ccdnssJustFilenameNoExt, ccdnssJustFilenameWithExt, ccdnssJustExtension, ccdnssJustPath, ccdnssInvalid); //Note: ccdnssInvalid *must* be the last one.
{ TfrmCopyDlg }
TfrmCopyDlg = class(TForm, IFormCommands)
btnCancel: TBitBtn;
btnOK: TBitBtn;
btnAddToQueue: TBitBtn;
btnOptions: TButton;
btnSaveOptions: TButton;
edtDst: TKASPathEdit;
grpOptions: TGroupBox;
lblCopySrc: TLabel;
mnuQueue2: TMenuItem;
mnuQueue3: TMenuItem;
mnuQueue4: TMenuItem;
mnuQueue5: TMenuItem;
mnuQueue1: TMenuItem;
mnuNewQueue: TMenuItem;
pmQueuePopup: TPopupMenu;
pnlButtons: TPanel;
pnlOptions: TPanel;
pnlSelector: TPanel;
btnCreateSpecialQueue: TBitBtn;
procedure btnCreateSpecialQueueClick(Sender: TObject);
procedure btnOKClick(Sender: TObject);
procedure btnOptionsClick(Sender: TObject);
procedure btnSaveOptionsClick(Sender: TObject);
procedure btnStartModeClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormPaint(Sender: TObject);
procedure frmCopyDlgShow(Sender: TObject);
procedure mnuNewQueueClick(Sender: TObject);
procedure mnuQueueNumberClick(Sender: TObject);
procedure pnlOptionsResize(Sender: TObject);
private
FCommands: TFormCommands;
FDialogType: TCopyMoveDlgType;
noteb: TFileViewNotebook;
FFileSource: IFileSource;
FOperationOptionsUIClass: TFileSourceOperationOptionsUIClass;
FOperationOptionsUI: TFileSourceOperationOptionsUI;
FCurrentCopyDlgNameSelectionStep: TCurrentCopyDlgNameSelectionStep;
function GetQueueIdentifier: TOperationsManagerQueueIdentifier;
procedure SetQueueIdentifier(AValue: TOperationsManagerQueueIdentifier);
function ShowTabsSelector: integer;
procedure TabsSelector(Sender: TObject);
procedure TabsSelectorMouseDown(Sender: TObject; {%H-}Button: TMouseButton;
{%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
procedure ShowOptions(bShow: Boolean);
procedure UpdateSize;
property {%H-}Commands: TFormCommands read FCommands implements IFormCommands;
public
constructor Create(TheOwner: TComponent; DialogType: TCopyMoveDlgType;
AFileSource: IFileSource;
AOperationOptionsUIClass: TFileSourceOperationOptionsUIClass); reintroduce;
constructor Create(TheOwner: TComponent); override;
procedure SetOperationOptions(Operation: TFileSourceOperation);
property QueueIdentifier: TOperationsManagerQueueIdentifier read GetQueueIdentifier write SetQueueIdentifier;
published
procedure cm_AddToQueue(const Params: array of String);
procedure cm_ToggleSelectionInName(const {%H-}Params: array of string);
end;
implementation
{$R *.lfm}
uses
LazUTF8, fMain, LCLType, LCLVersion, uGlobs, uLng, uHotkeyManager, DCStrUtils;
const
HotkeysCategory = 'Copy/Move Dialog';
var
FQueueIdentifier: TOperationsManagerQueueIdentifier = SingleQueueId;
constructor TfrmCopyDlg.Create(TheOwner: TComponent; DialogType: TCopyMoveDlgType;
AFileSource: IFileSource;
AOperationOptionsUIClass: TFileSourceOperationOptionsUIClass);
begin
FDialogType := DialogType;
FFileSource := AFileSource;
FOperationOptionsUIClass := AOperationOptionsUIClass;
FCommands := TFormCommands.Create(Self);
inherited Create(TheOwner);
end;
constructor TfrmCopyDlg.Create(TheOwner: TComponent);
begin
Create(TheOwner, cmdtCopy, nil, nil);
end;
procedure TfrmCopyDlg.SetOperationOptions(Operation: TFileSourceOperation);
begin
if Assigned(FOperationOptionsUI) then
FOperationOptionsUI.SetOperationOptions(Operation);
end;
procedure TfrmCopyDlg.cm_AddToQueue(const Params: array of String);
var
Value: Integer;
sQueueId: String;
begin
if FQueueIdentifier = ModalQueueId then Exit;
if GetParamValue(Params, 'queueid', sQueueId) and TryStrToInt(sQueueId, Value) then
begin
if Value < 0 then
mnuNewQueue.Click
else
FQueueIdentifier := Value
end
else
FQueueIdentifier := SingleQueueId;
ModalResult := btnAddToQueue.ModalResult;
end;
{ TfrmCopyDlg.cm_ToggleSelectionInName }
procedure TfrmCopyDlg.cm_ToggleSelectionInName(const Params: array of string);
var
iInitialStart, iInitialLength, iFullLength, iPath, iExtension, iSelStart, iSelLenght: integer;
begin
iFullLength := UTF8Length(edtDst.Text);
iPath := UTF8Length(ExtractFilePath(edtDst.Text));
iExtension := UTF8Length(ExtractFileExt(edtDst.Text));
iInitialStart := edtDst.SelStart;
iInitialLength := edtDst.SelLength;
repeat
FCurrentCopyDlgNameSelectionStep := TCurrentCopyDlgNameSelectionStep((ord(FCurrentCopyDlgNameSelectionStep)+1) mod ord(ccdnssInvalid));
case FCurrentCopyDlgNameSelectionStep of
ccdnssJustFilenameNoExt:
begin
iSelStart := iPath;
iSelLenght := iFullLength - (iPath+iExtension);
end;
ccdnssJustFilenameWithExt:
begin
iSelStart := iPath;
iSelLenght := iFullLength - iPath;
end;
ccdnssJustExtension:
begin
iSelStart := succ(iPath + (iFullLength - (iPath+iExtension)));
iSelLenght := pred(iExtension);
end;
ccdnssJustPath:
begin
iSelStart := 0;
iSelLenght := pred(iPath);
end;
else //Which includes also "ccdnssWholeCompleteFilename".
begin
iSelStart := 0;
iSelLenght := iFullLength;
end;
end;
until ((iSelStart <> iInitialStart) OR (iInitialLength <> iSelLenght)) AND (iSelLenght > 0);
edtDst.SelStart := iSelStart;
edtDst.SelLength := iSelLenght;
end;
procedure TfrmCopyDlg.TabsSelector(Sender: TObject);
begin
edtDst.Text := noteb[(Sender as TButton).tag].CurrentPath;
end;
procedure TfrmCopyDlg.TabsSelectorMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
edtDst.Text := noteb[(Sender as TButton).tag].CurrentPath;
end;
function TfrmCopyDlg.ShowTabsSelector: integer;
var
btnS, btnL: TButton;
i, tc: PtrInt;
st: TStringList;
s: String;
begin
noteb := frmMain.NotActiveNotebook;
if noteb.PageCount = 1 then
begin
Result:=0;
exit;
end;
tc := noteb.PageCount;
st := TStringList.Create;
try
for i:=0 to tc-1 do
if noteb.View[i].Visible then
begin
s:=noteb[i].CurrentPath;
if st.IndexOf(s)=-1 then
begin
st.Add(s);
st.Objects[st.Count-1]:=TObject(i);
end;
end;
tc := st.Count;
btnL := nil;
if tc>10 then tc:=10;
for i:=0 to tc-1 do
begin
btnS:= TButton.Create(Self);
btnS.TabOrder:= i;
btns.Parent:=pnlSelector;
btns.Tag:=PtrInt(st.Objects[i]);
if i < 9 then
btns.Caption := IntToStr(i+1) + ' - ' + noteb.Page[PtrInt(st.Objects[i])].Caption
else
btns.Caption := '0 - ' + noteb.Page[PtrInt(st.Objects[i])].Caption;
btnS.OnClick := @TabsSelector;
btnS.OnMouseDown := @TabsSelectorMouseDown;
btns.AutoSize:=True;
btns.Left := 0;
btns.Top := 0;
btns.Anchors :=[akLeft,akTop,akBottom];
btns.Visible := True;
if btnL <> nil then
begin
btns.AnchorSideLeft.Control := btnL;
btns.AnchorSideLeft.Side := asrRight;
end;
btnL := btnS;
if (Self.Width < (btnL.Left+btnL.Width+200)) then // 200 = Ok + Cancel
Self.Width := (btnL.Left+btnL.Width+200);
end;
finally
st.Free;
end;
end;
function TfrmCopyDlg.GetQueueIdentifier: TOperationsManagerQueueIdentifier;
begin
Result:= FQueueIdentifier;
end;
procedure TfrmCopyDlg.SetQueueIdentifier(AValue: TOperationsManagerQueueIdentifier);
begin
FQueueIdentifier:= AValue;
end;
procedure TfrmCopyDlg.frmCopyDlgShow(Sender: TObject);
begin
case FDialogType of
cmdtCopy:
begin
Caption := rsDlgCp;
end;
cmdtMove:
begin
Caption := rsDlgMv;
end;
end;
if gShowCopyTabSelectPanel then
ShowTabsSelector;
edtDst.SelectAll;
FCurrentCopyDlgNameSelectionStep := ccdnssWholeCompleteFilename;
edtDst.SetFocus;
btnCreateSpecialQueue.Left:= btnAddToQueue.BoundsRect.Right;
end;
procedure TfrmCopyDlg.mnuNewQueueClick(Sender: TObject);
begin
FQueueIdentifier := OperationsManager.GetNewQueueIdentifier;
ModalResult := btnAddToQueue.ModalResult;
end;
procedure TfrmCopyDlg.mnuQueueNumberClick(Sender: TObject);
var
NewQueueNumber: TOperationsManagerQueueIdentifier;
begin
if TryStrToInt(Copy((Sender as TMenuItem).Name, 9, 1), NewQueueNumber) then
begin
FQueueIdentifier := NewQueueNumber;
ModalResult := btnAddToQueue.ModalResult;
end;
end;
procedure TfrmCopyDlg.pnlOptionsResize(Sender: TObject);
begin
UpdateSize;
end;
procedure TfrmCopyDlg.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if gShowCopyTabSelectPanel and (Integer(Key) - VK_1 < pnlSelector.ControlCount) then
begin
if (ssAlt in Shift) or (edtDst.Focused = False) then
begin
if (Key >= VK_1) and (Key <= VK_9) then
begin
TButton(pnlSelector.Controls[Key - VK_1]).Click;
Key := 0;
end;
if (Key = VK_0) and (pnlSelector.ControlCount = 10) then
begin
TButton(pnlSelector.Controls[9]).Click;
Key := 0;
end;
end;
end;
{$IF lcl_fullversion < 093100}
case Key of
VK_ESCAPE: // Must handle before drag manager. Lazarus bug 0020676.
begin
ModalResult := mrCancel;
Key := 0;
end;
end;
{$ENDIF}
end;
procedure TfrmCopyDlg.FormPaint(Sender: TObject);
begin
OnPaint := nil;
AutoSize := False;
Constraints.MinWidth := 0;
end;
procedure TfrmCopyDlg.btnCreateSpecialQueueClick(Sender: TObject);
begin
btnCreateSpecialQueue.PopupMenu.PopUp;
end;
procedure TfrmCopyDlg.btnOKClick(Sender: TObject);
begin
if FQueueIdentifier <> ModalQueueId then
FQueueIdentifier := FreeOperationsQueueId;
end;
procedure TfrmCopyDlg.btnOptionsClick(Sender: TObject);
begin
Constraints.MinWidth := Width;
ShowOptions(not pnlOptions.Visible);
btnOptions.Enabled := not btnOptions.Enabled;
ClientWidth := pnlOptions.Width + ChildSizing.LeftRightSpacing * 2;
pnlOptions.Anchors := pnlOptions.Anchors + [akRight];
MoveToDefaultPosition;
Constraints.MinWidth := 0;
end;
procedure TfrmCopyDlg.btnSaveOptionsClick(Sender: TObject);
begin
if Assigned(FOperationOptionsUI) then
FOperationOptionsUI.SaveOptions;
end;
procedure TfrmCopyDlg.btnStartModeClick(Sender: TObject);
begin
btnOK.PopupMenu.PopUp;
end;
procedure TfrmCopyDlg.FormCreate(Sender: TObject);
var
HMForm: THMForm;
Hotkey: THotkey;
begin
Constraints.MinWidth := Width;
pnlSelector.Visible := gShowCopyTabSelectPanel;
btnOK.Caption := rsDlgOpStart;
if FQueueIdentifier <= FreeOperationsQueueId then FQueueIdentifier:= SingleQueueId;
btnAddToQueue.Caption:= btnAddToQueue.Caption + ' #' + IntToStr(FQueueIdentifier);
// Fix align of options panel and dialog size at start.
if not pnlSelector.Visible then
pnlOptions.Top := pnlOptions.Top -
(pnlSelector.Height +
pnlSelector.BorderSpacing.Top +
pnlSelector.BorderSpacing.Bottom);
// Operation options.
if Assigned(FOperationOptionsUIClass) then
begin
FOperationOptionsUI := FOperationOptionsUIClass.Create(Self, FFileSource);
FOperationOptionsUI.Parent := grpOptions;
FOperationOptionsUI.Align := alClient;
end
else
btnOptions.Visible := False;
ShowOptions(False);
HMForm := HotMan.Register(Self, HotkeysCategory);
Hotkey := HMForm.Hotkeys.FindByCommand('cm_AddToQueue');
if Assigned(Hotkey) then
btnAddToQueue.Caption := btnAddToQueue.Caption + ' (' + ShortcutsToText(Hotkey.Shortcuts) + ')';
end;
procedure TfrmCopyDlg.FormDestroy(Sender: TObject);
begin
HotMan.UnRegister(Self);
end;
procedure TfrmCopyDlg.ShowOptions(bShow: Boolean);
begin
pnlOptions.Visible := bShow;
UpdateSize;
end;
procedure TfrmCopyDlg.UpdateSize;
begin
if pnlOptions.Visible then
Self.Height := pnlOptions.Top + pnlOptions.Height +
pnlOptions.BorderSpacing.Top + pnlOptions.BorderSpacing.Bottom
else
Self.Height := pnlOptions.Top;
end;
initialization
TFormCommands.RegisterCommandsForm(TfrmCopyDlg, HotkeysCategory, @rsHotkeyCategoryCopyMoveDialog);
end.