ADD: delete dialog - Wipe option + context menu; wipe now offers Trash/Delete/Wipe

This commit is contained in:
heredie 2026-05-22 12:11:28 -06:00
commit f741daf548
4 changed files with 102 additions and 39 deletions

View file

@ -34,7 +34,7 @@ inherited frmDeleteDlg: TfrmDeleteDlg
ShowAccelChar = False
WordWrap = True
end
object chkUseTrash: TCheckBox[1]
object rbTrash: TRadioButton[1]
AnchorSideLeft.Control = pnlContent
AnchorSideTop.Control = lblMessage
AnchorSideTop.Side = asrBottom
@ -46,7 +46,35 @@ inherited frmDeleteDlg: TfrmDeleteDlg
Caption = 'Move to &Recycle Bin'
TabOrder = 1
Visible = False
OnChange = chkUseTrashChange
OnChange = rbModeChange
end
object rbDelete: TRadioButton[2]
AnchorSideLeft.Control = pnlContent
AnchorSideTop.Control = rbTrash
AnchorSideTop.Side = asrBottom
Left = 0
Height = 23
Top = 24
Width = 399
Anchors = [akTop, akLeft]
Caption = 'Delete &permanently'
TabOrder = 2
Visible = False
OnChange = rbModeChange
end
object rbWipe: TRadioButton[3]
AnchorSideLeft.Control = pnlContent
AnchorSideTop.Control = rbDelete
AnchorSideTop.Side = asrBottom
Left = 0
Height = 23
Top = 47
Width = 399
Anchors = [akTop, akLeft]
Caption = '&Wipe (secure erase)'
TabOrder = 3
Visible = False
OnChange = rbModeChange
end
end
inherited pnlButtons: TPanel

View file

@ -9,23 +9,27 @@ uses
Buttons, Menus, StdCtrls, fButtonForm, uOperationsManager, uFileSource;
type
TDeleteMode = (dmTrash, dmDelete, dmWipe);
{ TfrmDeleteDlg }
TfrmDeleteDlg = class(TfrmButtonForm)
chkUseTrash: TCheckBox;
rbTrash: TRadioButton;
rbDelete: TRadioButton;
rbWipe: TRadioButton;
lblMessage: TLabel;
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure chkUseTrashChange(Sender: TObject);
procedure rbModeChange(Sender: TObject);
private
FMsgTrash: String;
FMsgNoTrash: String;
FMessages: array[TDeleteMode] of String;
public
{ public declarations }
end;
function ShowDeleteDialog(TheOwner: TComponent; const Message: String; FileSource: IFileSource; out QueueId: TOperationsManagerQueueIdentifier): Boolean; overload;
function ShowDeleteDialog(TheOwner: TComponent; const TrashMessage, NoTrashMessage: String; FileSource: IFileSource; out QueueId: TOperationsManagerQueueIdentifier; var UseTrash: Boolean): Boolean; overload;
function ShowDeleteDialog(TheOwner: TComponent; const TrashMessage, DeleteMessage, WipeMessage: String;
FileSource: IFileSource; out QueueId: TOperationsManagerQueueIdentifier;
ShowTrash, ShowWipe: Boolean; var DeleteMode: TDeleteMode): Boolean; overload;
implementation
@ -45,23 +49,33 @@ begin
end;
end;
function ShowDeleteDialog(TheOwner: TComponent; const TrashMessage, NoTrashMessage: String;
function ShowDeleteDialog(TheOwner: TComponent; const TrashMessage, DeleteMessage, WipeMessage: String;
FileSource: IFileSource; out QueueId: TOperationsManagerQueueIdentifier;
var UseTrash: Boolean): Boolean;
ShowTrash, ShowWipe: Boolean; var DeleteMode: TDeleteMode): Boolean;
begin
with TfrmDeleteDlg.Create(TheOwner, FileSource) do
begin
Caption:= Application.Title;
FMsgTrash:= TrashMessage;
FMsgNoTrash:= NoTrashMessage;
chkUseTrash.Visible:= True;
chkUseTrash.Checked:= UseTrash;
if UseTrash then
lblMessage.Caption:= TrashMessage
else
lblMessage.Caption:= NoTrashMessage;
FMessages[dmTrash] := TrashMessage;
FMessages[dmDelete] := DeleteMessage;
FMessages[dmWipe] := WipeMessage;
rbTrash.Visible := ShowTrash;
rbDelete.Visible := True;
rbWipe.Visible := ShowWipe;
// Set initial selection; fall back to dmDelete if the preferred mode is unavailable
case DeleteMode of
dmTrash: if ShowTrash then rbTrash.Checked := True else rbDelete.Checked := True;
dmWipe: if ShowWipe then rbWipe.Checked := True else rbDelete.Checked := True;
else rbDelete.Checked := True;
end;
lblMessage.Caption:= FMessages[DeleteMode];
Result:= ShowModal = mrOK;
if Result then UseTrash:= chkUseTrash.Checked;
if Result then
begin
if rbTrash.Checked then DeleteMode := dmTrash
else if rbWipe.Checked then DeleteMode := dmWipe
else DeleteMode := dmDelete;
end;
QueueId:= QueueIdentifier;
Free;
end;
@ -81,12 +95,14 @@ begin
end;
end;
procedure TfrmDeleteDlg.chkUseTrashChange(Sender: TObject);
procedure TfrmDeleteDlg.rbModeChange(Sender: TObject);
var
Mode: TDeleteMode;
begin
if chkUseTrash.Checked then
lblMessage.Caption:= FMsgTrash
else
lblMessage.Caption:= FMsgNoTrash;
if rbTrash.Checked then Mode := dmTrash
else if rbWipe.Checked then Mode := dmWipe
else Mode := dmDelete;
lblMessage.Caption := FMessages[Mode];
end;
end.

View file

@ -2943,6 +2943,9 @@ object frmMain: TfrmMain
object mnuContextRenameOnly: TMenuItem
Action = actRenameOnly
end
object mnuContextWipe: TMenuItem
Action = actWipe
end
object mnuContextDelete: TMenuItem
Action = actDelete
end

View file

@ -2592,13 +2592,15 @@ var
theFilesToDelete: TFiles;
// 12.05.2009 - if delete to trash, then show another messages
MsgDelSel, MsgDelFlDr : string;
MsgTrash, MsgNoTrash: String;
MsgTrash, MsgNoTrash, MsgWipe: String;
Operation: TFileSourceOperation;
bRecycle: Boolean;
bConfirmation, HasConfirmationParam: Boolean;
Confirmed: Boolean;
Param, ParamTrashCan: String;
BoolValue: Boolean;
TrashAvailable: Boolean;
TrashAvailable, WipeAvailable: Boolean;
DeleteMode: TDeleteMode;
QueueId: TOperationsManagerQueueIdentifier = FreeOperationsQueueId;
begin
with frmMain.ActiveFrame do
@ -2641,6 +2643,7 @@ begin
// Save parameter for later use
TrashAvailable := FileSource.IsClass(TFileSystemFileSource) and
mbCheckTrash(CurrentPath);
WipeAvailable := fsoWipe in FileSource.GetOperationsTypes;
BoolValue := bRecycle;
if bRecycle then
@ -2679,9 +2682,10 @@ begin
if (theFilesToDelete.Count = 0) then Exit;
if (theFilesToDelete.Count = 1) then
begin
MsgTrash := Format(rsMsgDelSelT, [theFilesToDelete[0].Name]);
MsgNoTrash := Format(rsMsgDelSel, [theFilesToDelete[0].Name]);
Message := Format(MsgDelSel, [theFilesToDelete[0].Name]);
MsgTrash := Format(rsMsgDelSelT, [theFilesToDelete[0].Name]);
MsgNoTrash := Format(rsMsgDelSel, [theFilesToDelete[0].Name]);
MsgWipe := Format(rsMsgWipeSel, [theFilesToDelete[0].Name]);
Message := Format(MsgDelSel, [theFilesToDelete[0].Name]);
end
else begin
// Build the file list suffix once and share it across all message variants
@ -2691,11 +2695,21 @@ begin
if theFilesToDelete.Count > 5 then Message += LineEnding + '...';
MsgTrash := Format(rsMsgDelFlDrT, [theFilesToDelete.Count]) + Message;
MsgNoTrash := Format(rsMsgDelFlDr, [theFilesToDelete.Count]) + Message;
MsgWipe := Format(rsMsgWipeFlDr, [theFilesToDelete.Count]) + Message;
Message := Format(MsgDelFlDr, [theFilesToDelete.Count]) + Message;
end;
if (bConfirmation = False) or
(TrashAvailable and ShowDeleteDialog(frmMain, MsgTrash, MsgNoTrash, FileSource, QueueId, bRecycle)) or
((not TrashAvailable) and ShowDeleteDialog(frmMain, Message, FileSource, QueueId)) then
// Default delete mode based on current recycle setting
if bRecycle then DeleteMode := dmTrash else DeleteMode := dmDelete;
// Show confirmation dialog; choose extended or simple variant based on available modes
if not bConfirmation then
Confirmed := True
else if TrashAvailable or WipeAvailable then
Confirmed := ShowDeleteDialog(frmMain, MsgTrash, MsgNoTrash, MsgWipe,
FileSource, QueueId,
TrashAvailable, WipeAvailable, DeleteMode)
else
Confirmed := ShowDeleteDialog(frmMain, Message, FileSource, QueueId);
if Confirmed then
begin
// Restore focus to main window after confirmation dialog closes
if bConfirmation and frmMain.ActiveFrame.CanSetFocus then
@ -2730,25 +2744,27 @@ begin
end;
end;
Operation := FileSource.CreateDeleteOperation(theFilesToDelete);
if Assigned(Operation) then
// Dispatch to wipe or delete based on dialog choice
if DeleteMode = dmWipe then
Operation := FileSource.CreateWipeOperation(theFilesToDelete)
else
begin
bRecycle := (DeleteMode = dmTrash);
Operation := FileSource.CreateDeleteOperation(theFilesToDelete);
// Special case for filesystem - 'recycle' parameter.
if Operation is TFileSystemDeleteOperation then
if Assigned(Operation) and (Operation is TFileSystemDeleteOperation) then
with Operation as TFileSystemDeleteOperation do
begin
// 30.04.2009 - передаем параметр корзины в поток.
Recycle := bRecycle;
end;
// Start operation.
OperationsManager.AddOperation(Operation, QueueId, False);
end
else
begin
msgWarning(rsMsgNotImplemented);
end;
if Assigned(Operation) then
// Start operation.
OperationsManager.AddOperation(Operation, QueueId, False)
else
msgWarning(rsMsgNotImplemented);
end;
finally