mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
UPD: Rewrite cm_FileSpliter command as TFileSourceOperation
This commit is contained in:
parent
21f507ec5b
commit
e9fda4ec49
12 changed files with 789 additions and 336 deletions
|
|
@ -203,7 +203,7 @@
|
|||
<PackageName Value="viewerpackage"/>
|
||||
</Item7>
|
||||
</RequiredPackages>
|
||||
<Units Count="106">
|
||||
<Units Count="110">
|
||||
<Unit0>
|
||||
<Filename Value="doublecmd.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
|
|
@ -384,6 +384,7 @@
|
|||
<IsPartOfProject Value="True"/>
|
||||
<ComponentName Value="frmSplitter"/>
|
||||
<HasResources Value="True"/>
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
<UnitName Value="fSplitter"/>
|
||||
</Unit23>
|
||||
<Unit24>
|
||||
|
|
@ -858,6 +859,26 @@
|
|||
<ResourceBaseClass Value="Frame"/>
|
||||
<UnitName Value="fWfxPluginCopyMoveOperationOptions"/>
|
||||
</Unit105>
|
||||
<Unit106>
|
||||
<Filename Value="newdesign\ufilesystemcombineoperation.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="uFileSystemCombineOperation"/>
|
||||
</Unit106>
|
||||
<Unit107>
|
||||
<Filename Value="newdesign\ufilesourcecombineoperation.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="uFileSourceCombineOperation"/>
|
||||
</Unit107>
|
||||
<Unit108>
|
||||
<Filename Value="newdesign\ufilesourcesplitoperation.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="uFileSourceSplitOperation"/>
|
||||
</Unit108>
|
||||
<Unit109>
|
||||
<Filename Value="newdesign\ufilesystemsplitoperation.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="uFileSystemSplitOperation"/>
|
||||
</Unit109>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
contributors:
|
||||
|
||||
Copyright (C) 2008-2010 Koblov Alexander (Alexx2000@mail.ru)
|
||||
Copyright (C) 2008-2011 Koblov Alexander (Alexx2000@mail.ru)
|
||||
}
|
||||
|
||||
unit fFileOpDlg;
|
||||
|
|
@ -72,6 +72,7 @@ type
|
|||
procedure InitializeMoveOperation(Operation: TFileSourceOperation);
|
||||
procedure InitializeDeleteOperation(Operation: TFileSourceOperation);
|
||||
procedure InitializeWipeOperation(Operation: TFileSourceOperation);
|
||||
procedure InitializeSplitOperation(Operation: TFileSourceOperation);
|
||||
procedure InitializeCombineOperation(Operation: TFileSourceOperation);
|
||||
procedure InitializeCalcChecksumOperation(Operation: TFileSourceOperation);
|
||||
procedure InitializeTestArchiveOperation(Operation: TFileSourceOperation);
|
||||
|
|
@ -79,6 +80,7 @@ type
|
|||
procedure UpdateMoveOperation(Operation: TFileSourceOperation);
|
||||
procedure UpdateDeleteOperation(Operation: TFileSourceOperation);
|
||||
procedure UpdateWipeOperation(Operation: TFileSourceOperation);
|
||||
procedure UpdateSplitOperation(Operation: TFileSourceOperation);
|
||||
procedure UpdateCombineOperation(Operation: TFileSourceOperation);
|
||||
procedure UpdateCalcChecksumOperation(Operation: TFileSourceOperation);
|
||||
procedure UpdateTestArchiveOperation(Operation: TFileSourceOperation);
|
||||
|
|
@ -107,6 +109,7 @@ uses
|
|||
uFileSourceMoveOperation,
|
||||
uFileSourceDeleteOperation,
|
||||
uFileSourceWipeOperation,
|
||||
uFileSourceSplitOperation,
|
||||
uFileSourceCombineOperation,
|
||||
uFileSourceCalcChecksumOperation,
|
||||
uFileSourceTestArchiveOperation,
|
||||
|
|
@ -225,6 +228,8 @@ begin
|
|||
InitializeDeleteOperation(Operation);
|
||||
fsoWipe:
|
||||
InitializeWipeOperation(Operation);
|
||||
fsoSplit:
|
||||
InitializeSplitOperation(Operation);
|
||||
fsoCombine:
|
||||
InitializeCombineOperation(Operation);
|
||||
fsoCalcChecksum:
|
||||
|
|
@ -333,6 +338,8 @@ begin
|
|||
UpdateDeleteOperation(Operation);
|
||||
fsoWipe:
|
||||
UpdateWipeOperation(Operation);
|
||||
fsoSplit:
|
||||
UpdateSplitOperation(Operation);
|
||||
fsoCombine:
|
||||
UpdateCombineOperation(Operation);
|
||||
fsoCalcChecksum:
|
||||
|
|
@ -508,6 +515,12 @@ begin
|
|||
lblFrom.Caption := rsDlgDeleting;
|
||||
end;
|
||||
|
||||
procedure TfrmFileOp.InitializeSplitOperation(Operation: TFileSourceOperation);
|
||||
begin
|
||||
Caption := rsDlgSplit;
|
||||
InitializeControls([fodl_from_lbl, fodl_to_lbl, fodl_first_pb, fodl_second_pb]);
|
||||
end;
|
||||
|
||||
procedure TfrmFileOp.InitializeCombineOperation(Operation: TFileSourceOperation);
|
||||
begin
|
||||
Caption := rsDlgCombine;
|
||||
|
|
@ -602,6 +615,25 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TfrmFileOp.UpdateSplitOperation(Operation: TFileSourceOperation);
|
||||
var
|
||||
SplitOperation: TFileSourceSplitOperation;
|
||||
SplitStatistics: TFileSourceSplitOperationStatistics;
|
||||
begin
|
||||
SplitOperation := Operation as TFileSourceSplitOperation;
|
||||
SplitStatistics := SplitOperation.RetrieveStatistics;
|
||||
|
||||
with SplitStatistics do
|
||||
begin
|
||||
lblFileNameFrom.Caption := MinimizeFilePath(CurrentFileFrom, lblFileNameFrom.Canvas, lblFileNameFrom.Width);
|
||||
lblFileNameTo.Caption := MinimizeFilePath(CurrentFileTo, lblFileNameTo.Canvas, lblFileNameTo.Width);
|
||||
|
||||
SetProgressBytes(pbFirst, CurrentFileDoneBytes, CurrentFileTotalBytes);
|
||||
SetProgressBytes(pbSecond, DoneBytes, TotalBytes);
|
||||
SetSpeedAndTime(Operation, RemainingTime, cnvFormatFileSize(BytesPerSecond, True) + 'B');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TfrmFileOp.UpdateCombineOperation(Operation: TFileSourceOperation);
|
||||
var
|
||||
CombineOperation: TFileSourceCombineOperation;
|
||||
|
|
|
|||
|
|
@ -1,75 +1,69 @@
|
|||
object frmSplitter: TfrmSplitter
|
||||
Left = 542
|
||||
Height = 302
|
||||
Top = 242
|
||||
Width = 480
|
||||
Left = 283
|
||||
Height = 240
|
||||
Top = 122
|
||||
Width = 399
|
||||
HorzScrollBar.Page = 464
|
||||
HorzScrollBar.Range = 369
|
||||
VertScrollBar.Page = 301
|
||||
VertScrollBar.Range = 227
|
||||
ActiveControl = cmbxSize
|
||||
AutoSize = True
|
||||
Caption = 'Splitter'
|
||||
ClientHeight = 302
|
||||
ClientWidth = 480
|
||||
ChildSizing.LeftRightSpacing = 6
|
||||
ChildSizing.TopBottomSpacing = 6
|
||||
ClientHeight = 240
|
||||
ClientWidth = 399
|
||||
Position = poScreenCenter
|
||||
LCLVersion = '0.9.29'
|
||||
object prgbrDoIt: TProgressBar
|
||||
AnchorSideLeft.Control = Owner
|
||||
AnchorSideRight.Control = Owner
|
||||
AnchorSideRight.Side = asrBottom
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 6
|
||||
Height = 27
|
||||
Top = 269
|
||||
Width = 468
|
||||
Anchors = [akLeft, akRight, akBottom]
|
||||
BorderSpacing.Left = 6
|
||||
BorderSpacing.Right = 6
|
||||
BorderSpacing.Bottom = 6
|
||||
TabOrder = 5
|
||||
end
|
||||
object grbxFile: TGroupBox
|
||||
AnchorSideLeft.Control = Owner
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideBottom.Control = grbxSize
|
||||
AnchorSideRight.Control = btnCancel
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 6
|
||||
Height = 146
|
||||
Top = 0
|
||||
Width = 290
|
||||
Anchors = [akTop, akLeft, akBottom]
|
||||
Height = 118
|
||||
Top = 6
|
||||
Width = 385
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
AutoSize = True
|
||||
BorderSpacing.Left = 6
|
||||
BorderSpacing.Bottom = 6
|
||||
Caption = 'File name'
|
||||
ClientHeight = 127
|
||||
ClientWidth = 286
|
||||
ChildSizing.LeftRightSpacing = 10
|
||||
ChildSizing.TopBottomSpacing = 4
|
||||
ClientHeight = 100
|
||||
ClientWidth = 381
|
||||
TabOrder = 0
|
||||
object lbFileSource: TLabel
|
||||
Left = 6
|
||||
Height = 18
|
||||
Top = 0
|
||||
Width = 71
|
||||
Left = 10
|
||||
Height = 14
|
||||
Top = 4
|
||||
Width = 52
|
||||
Caption = 'File source'
|
||||
ParentColor = False
|
||||
end
|
||||
object lbDirTarget: TLabel
|
||||
AnchorSideTop.Control = edFileSource
|
||||
AnchorSideTop.Side = asrBottom
|
||||
Left = 6
|
||||
Height = 18
|
||||
Top = 73
|
||||
Width = 104
|
||||
BorderSpacing.Top = 22
|
||||
Left = 10
|
||||
Height = 14
|
||||
Top = 55
|
||||
Width = 78
|
||||
BorderSpacing.Top = 12
|
||||
Caption = 'Directory target'
|
||||
ParentColor = False
|
||||
end
|
||||
object edFileSource: TEdit
|
||||
AnchorSideTop.Control = lbFileSource
|
||||
AnchorSideTop.Side = asrBottom
|
||||
Left = 6
|
||||
Height = 27
|
||||
Top = 24
|
||||
Width = 264
|
||||
BorderSpacing.Top = 6
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 10
|
||||
Height = 21
|
||||
Top = 22
|
||||
Width = 360
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
BorderSpacing.Top = 4
|
||||
ReadOnly = True
|
||||
TabOrder = 0
|
||||
end
|
||||
|
|
@ -77,12 +71,12 @@ object frmSplitter: TfrmSplitter
|
|||
AnchorSideTop.Control = lbDirTarget
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = btnFTChoice
|
||||
Left = 6
|
||||
Height = 27
|
||||
Top = 97
|
||||
Width = 234
|
||||
Left = 10
|
||||
Height = 21
|
||||
Top = 73
|
||||
Width = 330
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
BorderSpacing.Top = 6
|
||||
BorderSpacing.Top = 4
|
||||
BorderSpacing.Right = 6
|
||||
TabOrder = 1
|
||||
end
|
||||
|
|
@ -91,9 +85,9 @@ object frmSplitter: TfrmSplitter
|
|||
AnchorSideTop.Control = edDirTarget
|
||||
AnchorSideRight.Control = edFileSource
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 246
|
||||
Left = 346
|
||||
Height = 23
|
||||
Top = 97
|
||||
Top = 73
|
||||
Width = 24
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Left = 4
|
||||
|
|
@ -104,25 +98,32 @@ object frmSplitter: TfrmSplitter
|
|||
end
|
||||
object grbxSize: TGroupBox
|
||||
AnchorSideLeft.Control = Owner
|
||||
AnchorSideRight.Control = grbxWatch
|
||||
AnchorSideTop.Control = grbxFile
|
||||
AnchorSideTop.Side = asrBottom
|
||||
Left = 6
|
||||
Height = 112
|
||||
Top = 152
|
||||
Width = 290
|
||||
Anchors = [akLeft, akRight, akBottom]
|
||||
Height = 103
|
||||
Top = 130
|
||||
Width = 300
|
||||
AutoSize = True
|
||||
BorderSpacing.Left = 6
|
||||
BorderSpacing.Right = 6
|
||||
Caption = 'Size and number of parts'
|
||||
ClientHeight = 93
|
||||
ClientWidth = 286
|
||||
ChildSizing.LeftRightSpacing = 6
|
||||
ChildSizing.TopBottomSpacing = 6
|
||||
ClientHeight = 85
|
||||
ClientWidth = 296
|
||||
Constraints.MinWidth = 300
|
||||
TabOrder = 1
|
||||
object cmbxSize: TComboBox
|
||||
AnchorSideLeft.Control = grbxSize
|
||||
AnchorSideTop.Control = grbxSize
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 6
|
||||
Height = 29
|
||||
Top = 8
|
||||
Width = 262
|
||||
Height = 21
|
||||
Top = 6
|
||||
Width = 276
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
ItemHeight = 0
|
||||
ItemHeight = 13
|
||||
ItemIndex = 0
|
||||
Items.Strings = (
|
||||
'1457664B - 3.5"'
|
||||
|
|
@ -138,28 +139,40 @@ object frmSplitter: TfrmSplitter
|
|||
Text = '1457664B - 3.5"'
|
||||
end
|
||||
object rbtnKiloB: TRadioButton
|
||||
AnchorSideLeft.Control = cmbxSize
|
||||
AnchorSideTop.Control = cmbxSize
|
||||
AnchorSideTop.Side = asrBottom
|
||||
Left = 6
|
||||
Height = 22
|
||||
Top = 39
|
||||
Width = 85
|
||||
Height = 17
|
||||
Top = 33
|
||||
Width = 61
|
||||
BorderSpacing.Top = 6
|
||||
Caption = 'Kilobytes'
|
||||
OnChange = rbtnKiloBChange
|
||||
TabOrder = 1
|
||||
end
|
||||
object rbtnMegaB: TRadioButton
|
||||
Left = 96
|
||||
Height = 22
|
||||
Top = 39
|
||||
Width = 96
|
||||
AnchorSideLeft.Control = rbtnKiloB
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = rbtnKiloB
|
||||
Left = 69
|
||||
Height = 17
|
||||
Top = 33
|
||||
Width = 71
|
||||
BorderSpacing.Left = 2
|
||||
Caption = 'Megabytes'
|
||||
OnChange = rbtnKiloBChange
|
||||
TabOrder = 2
|
||||
end
|
||||
object rbtnGigaB: TRadioButton
|
||||
Left = 192
|
||||
Height = 22
|
||||
Top = 39
|
||||
Width = 90
|
||||
AnchorSideLeft.Control = rbtnMegaB
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = rbtnMegaB
|
||||
Left = 142
|
||||
Height = 17
|
||||
Top = 33
|
||||
Width = 66
|
||||
BorderSpacing.Left = 2
|
||||
Caption = 'Gigabytes'
|
||||
OnChange = rbtnKiloBChange
|
||||
TabOrder = 3
|
||||
|
|
@ -169,12 +182,12 @@ object frmSplitter: TfrmSplitter
|
|||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = rbtnMegaB
|
||||
AnchorSideTop.Side = asrBottom
|
||||
Left = 117
|
||||
Height = 27
|
||||
Top = 63
|
||||
Left = 89
|
||||
Height = 21
|
||||
Top = 58
|
||||
Width = 72
|
||||
BorderSpacing.Left = 4
|
||||
BorderSpacing.Top = 2
|
||||
BorderSpacing.Top = 8
|
||||
OnKeyPress = teNumberPartsKeyPress
|
||||
OnKeyUp = teNumberPartsKeyUp
|
||||
TabOrder = 4
|
||||
|
|
@ -184,83 +197,43 @@ object frmSplitter: TfrmSplitter
|
|||
AnchorSideTop.Control = teNumberParts
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 6
|
||||
Height = 18
|
||||
Top = 67
|
||||
Width = 107
|
||||
Height = 14
|
||||
Top = 61
|
||||
Width = 79
|
||||
Caption = 'Number of parts'
|
||||
ParentColor = False
|
||||
end
|
||||
end
|
||||
object grbxWatch: TGroupBox
|
||||
AnchorSideLeft.Control = grbxFile
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideRight.Control = Owner
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 302
|
||||
Height = 224
|
||||
Top = 0
|
||||
Width = 172
|
||||
Anchors = [akTop, akLeft, akRight, akBottom]
|
||||
BorderSpacing.Left = 6
|
||||
BorderSpacing.Right = 6
|
||||
Caption = 'Watchtower'
|
||||
ClientHeight = 205
|
||||
ClientWidth = 168
|
||||
TabOrder = 2
|
||||
object memWatch: TMemo
|
||||
AnchorSideLeft.Control = grbxWatch
|
||||
AnchorSideTop.Control = grbxWatch
|
||||
AnchorSideRight.Control = grbxWatch
|
||||
AnchorSideRight.Side = asrBottom
|
||||
AnchorSideBottom.Control = grbxWatch
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 4
|
||||
Height = 193
|
||||
Top = 6
|
||||
Width = 160
|
||||
Anchors = [akTop, akLeft, akRight, akBottom]
|
||||
BorderSpacing.Left = 4
|
||||
BorderSpacing.Top = 6
|
||||
BorderSpacing.Right = 4
|
||||
BorderSpacing.Bottom = 6
|
||||
Color = clBlack
|
||||
Font.Color = clYellow
|
||||
Font.Height = 11
|
||||
Font.Name = 'MS Shell Dlg'
|
||||
Font.Pitch = fpVariable
|
||||
ParentFont = False
|
||||
ReadOnly = True
|
||||
ScrollBars = ssAutoBoth
|
||||
TabOrder = 0
|
||||
TabStop = False
|
||||
WordWrap = False
|
||||
end
|
||||
end
|
||||
object btnOK: TButton
|
||||
AnchorSideRight.Control = btnCancel
|
||||
Left = 318
|
||||
AnchorSideRight.Side = asrBottom
|
||||
AnchorSideBottom.Control = btnCancel
|
||||
Left = 316
|
||||
Height = 32
|
||||
Top = 232
|
||||
Top = 163
|
||||
Width = 75
|
||||
Anchors = [akRight, akBottom]
|
||||
BorderSpacing.Right = 6
|
||||
BorderSpacing.Bottom = 6
|
||||
Caption = 'OK'
|
||||
Default = True
|
||||
OnClick = btnOKClick
|
||||
TabOrder = 3
|
||||
ModalResult = 1
|
||||
TabOrder = 2
|
||||
end
|
||||
object btnCancel: TButton
|
||||
AnchorSideRight.Control = grbxWatch
|
||||
AnchorSideLeft.Control = grbxSize
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 399
|
||||
AnchorSideBottom.Control = grbxSize
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 316
|
||||
Height = 32
|
||||
Top = 232
|
||||
Top = 201
|
||||
Width = 75
|
||||
Anchors = [akRight, akBottom]
|
||||
Anchors = [akLeft, akBottom]
|
||||
BorderSpacing.Left = 10
|
||||
Cancel = True
|
||||
Caption = 'Exit'
|
||||
Caption = 'Cancel'
|
||||
ModalResult = 2
|
||||
TabOrder = 4
|
||||
TabOrder = 3
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,6 +9,5 @@ TFRMSPLITTER.RBTNKILOB.CAPTION=Kilobytes
|
|||
TFRMSPLITTER.RBTNMEGAB.CAPTION=Megabytes
|
||||
TFRMSPLITTER.RBTNGIGAB.CAPTION=Gigabytes
|
||||
TFRMSPLITTER.LBLNUMBERPARTS.CAPTION=Number of parts
|
||||
TFRMSPLITTER.GRBXWATCH.CAPTION=Watchtower
|
||||
TFRMSPLITTER.BTNOK.CAPTION=OK
|
||||
TFRMSPLITTER.BTNCANCEL.CAPTION=Exit
|
||||
TFRMSPLITTER.BTNCANCEL.CAPTION=Cancel
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ unit fSplitter;
|
|||
interface
|
||||
|
||||
uses
|
||||
SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls, ComCtrls;
|
||||
SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls, ComCtrls,
|
||||
uFileSource,
|
||||
uFile;
|
||||
|
||||
type
|
||||
|
||||
|
|
@ -34,56 +36,103 @@ type
|
|||
btnFTChoice: TButton;
|
||||
grbxSize: TGroupBox;
|
||||
cmbxSize: TComboBox;
|
||||
grbxWatch: TGroupBox;
|
||||
memWatch: TMemo;
|
||||
btnOK: TButton;
|
||||
btnCancel: TButton;
|
||||
prgbrDoIt: TProgressBar;
|
||||
rbtnKiloB: TRadioButton;
|
||||
rbtnMegaB: TRadioButton;
|
||||
rbtnGigaB: TRadioButton;
|
||||
procedure btnFTChoiceClick(Sender: TObject);
|
||||
procedure btnOKClick(Sender: TObject);
|
||||
procedure cmbxSizeCloseUp(Sender: TObject);
|
||||
procedure cmbxSizeKeyPress(Sender: TObject; var Key: char);
|
||||
procedure cmbxSizeKeyUp(Sender: TObject; var Key: char; Shift: TShiftState);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure rbtnKiloBChange(Sender: TObject);
|
||||
procedure SetNumberOfPart;
|
||||
procedure SetSizeOfPart;
|
||||
procedure teNumberPartsKeyPress(Sender: TObject; var Key: char);
|
||||
procedure teNumberPartsKeyUp(Sender: TObject; var Key: Word;
|
||||
Shift: TShiftState);
|
||||
procedure teNumberPartsKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
|
||||
private
|
||||
{ Private declarations }
|
||||
function StrConvert(str:string):int64;
|
||||
//test for correct file size format;
|
||||
function StrConvert(str: String): Int64;
|
||||
public
|
||||
{ Public declarations }
|
||||
|
||||
end;
|
||||
|
||||
function ShowSplitterFileForm(const sFile: TStringList; const sTargetDir: String): Boolean;
|
||||
|
||||
function ShowSplitterFileForm(aFileSource: IFileSource; var aFile: TFile; const TargetPath: UTF8String): Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.lfm}
|
||||
|
||||
uses
|
||||
LCLProc, uLng, uClassesEx, uOSUtils;
|
||||
LCLProc, uLng, uClassesEx, uOSUtils, uFileProcs, uOperationsManager,
|
||||
uFileSourceSplitOperation, fFileOpDlg, uShowMsg;
|
||||
|
||||
function ShowSplitterFileForm(const sFile: TStringList; const sTargetDir: String): Boolean;
|
||||
function ShowSplitterFileForm(aFileSource: IFileSource; var aFile: TFile; const TargetPath: UTF8String): Boolean;
|
||||
var
|
||||
iVolumeNumber: Integer;
|
||||
iFileSize, iVolumeSize: Int64;
|
||||
Operation: TFileSourceSplitOperation = nil;
|
||||
ProgressDialog: TfrmFileOp;
|
||||
OperationHandle: TOperationHandle;
|
||||
begin
|
||||
with TfrmSplitter.Create(Application) do
|
||||
begin
|
||||
try
|
||||
edFileSource.Text:= sFile[0];
|
||||
edDirTarget.Text:= ExtractFileDir(sTargetDir);
|
||||
edFileSource.Text:= aFile.FullPath;
|
||||
edDirTarget.Text:= TargetPath;
|
||||
SetNumberOfPart;
|
||||
rbtnKiloB.Enabled:=false;
|
||||
rbtnMegaB.Enabled:=false;
|
||||
rbtnGigaB.Enabled:=false;
|
||||
|
||||
// Show form
|
||||
Result:= (ShowModal = mrOK);
|
||||
|
||||
if Result then
|
||||
begin
|
||||
iVolumeSize:= StrConvert(cmbxSize.Text);
|
||||
if iVolumeSize <= 0 then
|
||||
begin
|
||||
msgError(rsSplitErrFileSize); // Incorrect file size format!
|
||||
Exit;
|
||||
end;
|
||||
iFileSize:= mbFileSize(edFileSource.Text);
|
||||
if iVolumeSize >= iFileSize then
|
||||
begin
|
||||
msgError(rsSplitErrSplitFile); // Unable to split the file!
|
||||
Exit;
|
||||
end;
|
||||
if not mbForceDirectory(ExtractFileDir(edDirTarget.Text)) then
|
||||
begin
|
||||
msgError(rsSplitErrDirectory); // Unable to create target directory!
|
||||
Exit;
|
||||
end;
|
||||
iVolumeNumber:= StrToInt(teNumberParts.Text);
|
||||
if (iVolumeNumber = 0) then
|
||||
begin
|
||||
msgError(rsSplitErrSplitFile); // Unable to split the file!
|
||||
Exit;
|
||||
end;
|
||||
if iVolumeNumber > 100 then
|
||||
begin
|
||||
if MessageDlg(Caption, rsSplitMsgManyParts, mtWarning, mbYesNo, 0) <> mrYes then
|
||||
begin
|
||||
Exit; // Too many parts
|
||||
end;
|
||||
end;
|
||||
|
||||
try
|
||||
Operation:= aFileSource.CreateSplitOperation(aFile, edDirTarget.Text) as TFileSourceSplitOperation;
|
||||
if Assigned(Operation) then
|
||||
begin
|
||||
Operation.VolumeSize:= iVolumeSize;
|
||||
Operation.VolumeNumber:= iVolumeNumber;
|
||||
OperationHandle:= OperationsManager.AddOperation(Operation, ossAutoStart);
|
||||
ProgressDialog:= TfrmFileOp.Create(OperationHandle);
|
||||
ProgressDialog.Show;
|
||||
end;
|
||||
finally
|
||||
FreeThenNil(aFile);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Free;
|
||||
end;
|
||||
|
|
@ -181,146 +230,6 @@ begin
|
|||
Result:=iRet;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSplitter.btnOKClick(Sender: TObject);
|
||||
var
|
||||
iFileSize:int64;
|
||||
i,num:integer;
|
||||
fSource: TFileStreamEx = nil;
|
||||
fDest: TFileStreamEx = nil;
|
||||
begin
|
||||
memWatch.Clear;
|
||||
prgbrDoIt.Position:=0;
|
||||
iFileSize:=StrConvert(cmbxSize.Text);
|
||||
if iFileSize<=0 then
|
||||
begin
|
||||
memWatch.Append(rsSplitErrFileSize);
|
||||
//Incorrect file size format!
|
||||
exit;
|
||||
end;
|
||||
if not mbDirectoryExists(edDirTarget.Text) then
|
||||
begin
|
||||
if not mbCreateDir(edDirTarget.Text) then
|
||||
begin
|
||||
memWatch.Append(rsSplitErrDirectory);
|
||||
//Unable to create target directory!
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
if edDirTarget.Text[Length(edDirTarget.Text)]<>PathDelim then
|
||||
edDirTarget.Text:=edDirTarget.Text+PathDelim;
|
||||
|
||||
try
|
||||
fSource:= TFileStreamEx.Create(edFileSource.Text,fmOpenRead);
|
||||
except
|
||||
on E: EFOpenError do
|
||||
begin
|
||||
MessageDlg(Caption, rsMsgErrEOpen + ': ' + E.Message, mtError, [mbOK], 0);
|
||||
Exit;
|
||||
end;
|
||||
on E: EReadError do
|
||||
begin
|
||||
MessageDlg(Caption, rsMsgErrERead + ': ' + E.Message, mtError, [mbOK], 0);
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
try
|
||||
if iFileSize >= fSource.Size then
|
||||
begin
|
||||
memWatch.Append(rsSplitErrSplitFile);
|
||||
//Unable to split the file!
|
||||
exit;
|
||||
end;
|
||||
prgbrDoIt.Max:=(fSource.Size div iFileSize);
|
||||
if prgbrDoIt.Max=0 then
|
||||
begin
|
||||
memWatch.Append(rsSplitErrSplitFile);
|
||||
//Unable to split the file!
|
||||
exit;
|
||||
end;
|
||||
if prgbrDoIt.Max > 100 then
|
||||
begin
|
||||
if MessageDlg(Caption, rsSplitMsgManyParts, mtWarning, mbYesNo, 0) <> mrYes then
|
||||
begin
|
||||
memWatch.Append(rsSplitErrTooManyParts);
|
||||
// Too many parts
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
num:=0;
|
||||
i:=prgbrDoIt.Max;
|
||||
while i>=1 do
|
||||
begin
|
||||
i:=i div 10;
|
||||
inc(num);
|
||||
end;
|
||||
i:=0;
|
||||
while i<=prgbrDoIt.Max-1 do
|
||||
try
|
||||
fDest:=TFileStreamEx.Create(
|
||||
edDirTarget.Text+ExtractFileName(edFileSource.Text)+
|
||||
'.'+Format('%.*d',[num+1,i])+'.split'
|
||||
,fmCreate);
|
||||
try
|
||||
fSource.Seek(iFileSize*i,soFromBeginning);
|
||||
fDest.CopyFrom(fSource,iFileSize);
|
||||
memWatch.Append(rsSplitMsgCreated+' '+
|
||||
edDirTarget.Text+ExtractFileName(edFileSource.Text)+
|
||||
'.'+Format('%.*d',[num+1,i])+'.split'+
|
||||
' ... '+rsSplitMsgSize+' '+
|
||||
IntToStr(iFileSize)+'b');
|
||||
prgbrDoIt.Position:=prgbrDoIt.Position+1;
|
||||
finally
|
||||
FreeThenNil(fDest);
|
||||
end;
|
||||
inc(i);
|
||||
except
|
||||
on E: EFCreateError do
|
||||
begin
|
||||
MessageDlg(Caption, rsMsgErrECreate + ': ' + E.Message, mtError, [mbOK], 0);
|
||||
Exit;
|
||||
end;
|
||||
on E: EWriteError do
|
||||
begin
|
||||
MessageDlg(Caption, rsMsgErrEWrite + ': ' + E.Message, mtError, [mbOK], 0);
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
if (fSource.Position)<fSource.Size then
|
||||
try
|
||||
fDest:=TFileStreamEx.Create(
|
||||
edDirTarget.Text+ExtractFileName(edFileSource.Text)+
|
||||
'.'+Format('%.*d',[num+1,i])+'.split'
|
||||
,fmCreate);
|
||||
try
|
||||
fDest.CopyFrom(fSource,fSource.Size-fSource.Position);
|
||||
memWatch.Append(rsSplitMsgCreated+' '+
|
||||
edDirTarget.Text+ExtractFileName(edFileSource.Text)+
|
||||
'.'+Format('%.*d',[num+1,i])+'.split ... '+
|
||||
rsSplitMsgSize+' '+
|
||||
IntToStr(fSource.Size-(iFileSize*i))+'b');
|
||||
prgbrDoIt.Position:=prgbrDoIt.Position+1;
|
||||
finally
|
||||
FreeThenNil(fDest);
|
||||
end;
|
||||
except
|
||||
on E: EFCreateError do
|
||||
begin
|
||||
MessageDlg(Caption, rsMsgErrECreate + ': ' + E.Message, mtError, [mbOK], 0);
|
||||
Exit;
|
||||
end;
|
||||
on E: EWriteError do
|
||||
begin
|
||||
MessageDlg(Caption, rsMsgErrEWrite + ': ' + E.Message, mtError, [mbOK], 0);
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
FreeThenNil(fSource);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TfrmSplitter.cmbxSizeCloseUp(Sender: TObject);
|
||||
begin
|
||||
SetNumberOfPart;
|
||||
|
|
@ -352,6 +261,13 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TfrmSplitter.FormCreate(Sender: TObject);
|
||||
begin
|
||||
rbtnKiloB.Enabled:= False;
|
||||
rbtnMegaB.Enabled:= False;
|
||||
rbtnGigaB.Enabled:= False;
|
||||
end;
|
||||
|
||||
procedure TfrmSplitter.rbtnKiloBChange(Sender: TObject);
|
||||
begin
|
||||
SetNumberOfPart;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ type
|
|||
TargetPath: String): TFileSourceOperation;
|
||||
function CreateDeleteOperation(var FilesToDelete: TFiles): TFileSourceOperation;
|
||||
function CreateWipeOperation(var FilesToWipe: TFiles): TFileSourceOperation;
|
||||
function CreateSplitOperation(var aSourceFile: TFile;
|
||||
aTargetPath: String): TFileSourceOperation;
|
||||
function CreateCombineOperation(var theSourceFiles: TFiles;
|
||||
aTargetFile: String): TFileSourceOperation;
|
||||
function CreateCreateDirectoryOperation(BasePath: String; DirectoryPath: String): TFileSourceOperation;
|
||||
|
|
@ -221,6 +223,8 @@ type
|
|||
TargetPath: String): TFileSourceOperation; virtual;
|
||||
function CreateDeleteOperation(var FilesToDelete: TFiles): TFileSourceOperation; virtual;
|
||||
function CreateWipeOperation(var FilesToWipe: TFiles): TFileSourceOperation; virtual;
|
||||
function CreateSplitOperation(var aSourceFile: TFile;
|
||||
aTargetPath: String): TFileSourceOperation;
|
||||
function CreateCombineOperation(var theSourceFiles: TFiles;
|
||||
aTargetFile: String): TFileSourceOperation; virtual;
|
||||
function CreateCreateDirectoryOperation(BasePath: String; DirectoryPath: String): TFileSourceOperation; virtual;
|
||||
|
|
@ -614,6 +618,12 @@ begin
|
|||
Result := nil;
|
||||
end;
|
||||
|
||||
function TFileSource.CreateSplitOperation(var aSourceFile: TFile;
|
||||
aTargetPath: String): TFileSourceOperation;
|
||||
begin
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
function TFileSource.CreateCombineOperation(var theSourceFiles: TFiles;
|
||||
aTargetFile: String): TFileSourceOperation;
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ type
|
|||
fsoMove, // Move/rename files within the same file source.
|
||||
fsoDelete,
|
||||
fsoWipe,
|
||||
fsoSplit,
|
||||
fsoCombine,
|
||||
fsoCreateDirectory,
|
||||
//fsoCreateFile,
|
||||
|
|
|
|||
181
src/newdesign/ufilesourcesplitoperation.pas
Normal file
181
src/newdesign/ufilesourcesplitoperation.pas
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
unit uFileSourceSplitOperation;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, syncobjs,
|
||||
uFileSourceOperation,
|
||||
uFileSourceOperationTypes,
|
||||
uFileSource,
|
||||
uFile,
|
||||
uFileSourceCopyOperation;
|
||||
|
||||
type
|
||||
|
||||
TFileSourceSplitOperationStatistics = TFileSourceCopyOperationStatistics;
|
||||
|
||||
{en
|
||||
Operation that split file within the same file source.
|
||||
}
|
||||
TFileSourceSplitOperation = class(TFileSourceOperation)
|
||||
|
||||
private
|
||||
FStatistics: TFileSourceSplitOperationStatistics;
|
||||
FStatisticsAtStartTime: TFileSourceSplitOperationStatistics;
|
||||
FStatisticsLock: TCriticalSection; //<en For synchronizing statistics.
|
||||
FFileSource: IFileSource;
|
||||
FSourceFile: TFile;
|
||||
FTargetPath: String;
|
||||
FVolumeSize: Int64;
|
||||
FVolumeNumber: LongInt;
|
||||
|
||||
protected
|
||||
function GetID: TFileSourceOperationType; override;
|
||||
procedure DoReloadFileSources; override;
|
||||
|
||||
procedure UpdateStatistics(var NewStatistics: TFileSourceSplitOperationStatistics);
|
||||
procedure UpdateStatisticsAtStartTime; override;
|
||||
|
||||
property FileSource: IFileSource read FFileSource;
|
||||
property SourceFile: TFile read FSourceFile;
|
||||
property TargetPath: String read FTargetPath;
|
||||
|
||||
public
|
||||
{en
|
||||
@param(aFileSource
|
||||
File source within which the operation should take place.
|
||||
Class takes ownership of the pointer.)
|
||||
@param(aSourceFile
|
||||
The file which are to be splitted.
|
||||
Class takes ownership of the pointer.)
|
||||
@param(aTargetPath
|
||||
Target path for splitted files.)
|
||||
}
|
||||
constructor Create(aFileSource: IFileSource;
|
||||
var aSourceFile: TFile;
|
||||
aTargetPath: String); virtual reintroduce;
|
||||
|
||||
destructor Destroy; override;
|
||||
|
||||
function RetrieveStatistics: TFileSourceSplitOperationStatistics;
|
||||
|
||||
property VolumeSize: Int64 read FVolumeSize write FVolumeSize;
|
||||
property VolumeNumber: LongInt read FVolumeNumber write FVolumeNumber;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
uDCUtils;
|
||||
|
||||
// -- TFileSourceSplitOperation ------------------------------------------------
|
||||
|
||||
constructor TFileSourceSplitOperation.Create(aFileSource: IFileSource;
|
||||
var aSourceFile: TFile;
|
||||
aTargetPath: String);
|
||||
begin
|
||||
with FStatistics do
|
||||
begin
|
||||
CurrentFileFrom := '';
|
||||
CurrentFileTo := '';
|
||||
|
||||
TotalFiles := 0;
|
||||
DoneFiles := 0;
|
||||
TotalBytes := 0;
|
||||
DoneBytes := 0;
|
||||
CurrentFileTotalBytes := 0;
|
||||
CurrentFileDoneBytes := 0;
|
||||
BytesPerSecond := 0;
|
||||
RemainingTime := 0;
|
||||
end;
|
||||
|
||||
FStatisticsLock := TCriticalSection.Create;
|
||||
|
||||
inherited Create(aFileSource);
|
||||
|
||||
FFileSource := aFileSource;
|
||||
FSourceFile := aSourceFile;
|
||||
aSourceFile := nil;
|
||||
FTargetPath := aTargetPath;
|
||||
end;
|
||||
|
||||
destructor TFileSourceSplitOperation.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
|
||||
if Assigned(FStatisticsLock) then
|
||||
FreeAndNil(FStatisticsLock);
|
||||
if Assigned(FSourceFile) then
|
||||
FreeAndNil(FSourceFile);
|
||||
end;
|
||||
|
||||
procedure TFileSourceSplitOperation.UpdateStatistics(var NewStatistics: TFileSourceSplitOperationStatistics);
|
||||
begin
|
||||
FStatisticsLock.Acquire;
|
||||
try
|
||||
// Check if the value by which we calculate progress and remaining time has changed.
|
||||
if FStatistics.DoneBytes <> NewStatistics.DoneBytes then
|
||||
begin
|
||||
with NewStatistics do
|
||||
begin
|
||||
RemainingTime :=
|
||||
EstimateRemainingTime(FStatisticsAtStartTime.DoneBytes,
|
||||
DoneBytes,
|
||||
TotalBytes,
|
||||
StartTime,
|
||||
SysUtils.Now,
|
||||
BytesPerSecond);
|
||||
|
||||
// Update overall progress.
|
||||
if TotalBytes <> 0 then
|
||||
UpdateProgress((DoneBytes * 100) div TotalBytes);
|
||||
end;
|
||||
end;
|
||||
|
||||
FStatistics := NewStatistics;
|
||||
|
||||
finally
|
||||
FStatisticsLock.Release;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TFileSourceSplitOperation.UpdateStatisticsAtStartTime;
|
||||
begin
|
||||
FStatisticsLock.Acquire;
|
||||
try
|
||||
Self.FStatisticsAtStartTime := Self.FStatistics;
|
||||
finally
|
||||
FStatisticsLock.Release;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TFileSourceSplitOperation.RetrieveStatistics: TFileSourceSplitOperationStatistics;
|
||||
begin
|
||||
// Statistics have to be synchronized because there are multiple values
|
||||
// and they all have to be consistent at every moment.
|
||||
FStatisticsLock.Acquire;
|
||||
try
|
||||
Result := Self.FStatistics;
|
||||
finally
|
||||
FStatisticsLock.Release;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TFileSourceSplitOperation.GetID: TFileSourceOperationType;
|
||||
begin
|
||||
Result := fsoSplit;
|
||||
end;
|
||||
|
||||
procedure TFileSourceSplitOperation.DoReloadFileSources;
|
||||
var
|
||||
Paths: TPathsArray;
|
||||
begin
|
||||
SetLength(Paths, 1);
|
||||
Paths[0] := FTargetPath; // Split target path
|
||||
FFileSource.Reload(Paths);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
|
@ -86,6 +86,8 @@ type
|
|||
TargetPath: String): TFileSourceOperation; override;
|
||||
function CreateDeleteOperation(var FilesToDelete: TFiles): TFileSourceOperation; override;
|
||||
function CreateWipeOperation(var FilesToWipe: TFiles): TFileSourceOperation; override;
|
||||
function CreateSplitOperation(var aSourceFile: TFile;
|
||||
aTargetPath: String): TFileSourceOperation;
|
||||
function CreateCombineOperation(var SourceFiles: TFiles;
|
||||
aTargetFile: String): TFileSourceOperation; override;
|
||||
function CreateCreateDirectoryOperation(BasePath: String; DirectoryPath: String): TFileSourceOperation; override;
|
||||
|
|
@ -123,6 +125,7 @@ uses
|
|||
uFileSystemMoveOperation,
|
||||
uFileSystemDeleteOperation,
|
||||
uFileSystemWipeOperation,
|
||||
uFileSystemSplitOperation,
|
||||
uFileSystemCombineOperation,
|
||||
uFileSystemCreateDirectoryOperation,
|
||||
uFileSystemExecuteOperation,
|
||||
|
|
@ -547,6 +550,7 @@ begin
|
|||
fsoMove,
|
||||
fsoDelete,
|
||||
fsoWipe,
|
||||
fsoSplit,
|
||||
fsoCombine,
|
||||
fsoCreateDirectory,
|
||||
fsoCalcChecksum,
|
||||
|
|
@ -691,6 +695,15 @@ begin
|
|||
Result := TFileSystemWipeOperation.Create(TargetFileSource, FilesToWipe);
|
||||
end;
|
||||
|
||||
function TFileSystemFileSource.CreateSplitOperation(var aSourceFile: TFile;
|
||||
aTargetPath: String): TFileSourceOperation;
|
||||
var
|
||||
SourceFileSource: IFileSource;
|
||||
begin
|
||||
SourceFileSource := Self;
|
||||
Result := TFileSystemSplitOperation.Create(SourceFileSource, aSourceFile, aTargetPath);
|
||||
end;
|
||||
|
||||
function TFileSystemFileSource.CreateCombineOperation(var SourceFiles: TFiles;
|
||||
aTargetFile: String): TFileSourceOperation;
|
||||
var
|
||||
|
|
|
|||
327
src/newdesign/ufilesystemsplitoperation.pas
Normal file
327
src/newdesign/ufilesystemsplitoperation.pas
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
unit uFileSystemSplitOperation;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils,
|
||||
uFileSourceSplitOperation,
|
||||
uFileSource,
|
||||
uFileSourceOperationOptions,
|
||||
uFileSourceOperationUI,
|
||||
uFile,
|
||||
uGlobs, uLog, uClassesEx;
|
||||
|
||||
type
|
||||
|
||||
{ TFileSystemSplitOperation }
|
||||
|
||||
TFileSystemSplitOperation = class(TFileSourceSplitOperation)
|
||||
private
|
||||
FStatistics: TFileSourceSplitOperationStatistics; // local copy of statistics
|
||||
FTargetFile: UTF8String;
|
||||
FBuffer: Pointer;
|
||||
FBufferSize: LongWord;
|
||||
FCheckFreeSpace: Boolean;
|
||||
|
||||
protected
|
||||
function Split(aSourceFileStream: TFileStreamEx; TargetFile: UTF8String): Boolean;
|
||||
procedure ShowError(sMessage: String);
|
||||
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
|
||||
|
||||
public
|
||||
constructor Create(aFileSource: IFileSource;
|
||||
var aSourceFile: TFile;
|
||||
aTargetPath: String); override;
|
||||
|
||||
destructor Destroy; override;
|
||||
|
||||
procedure Initialize; override;
|
||||
procedure MainExecute; override;
|
||||
procedure Finalize; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
uOSUtils, uLng, uFindEx, uFileSystemUtil, LCLProc, uTypes;
|
||||
|
||||
constructor TFileSystemSplitOperation.Create(aFileSource: IFileSource;
|
||||
var aSourceFile: TFile;
|
||||
aTargetPath: String);
|
||||
begin
|
||||
FCheckFreeSpace := True;
|
||||
FTargetFile := aTargetPath + aSourceFile.Name;
|
||||
FBufferSize := gCopyBlockSize;
|
||||
GetMem(FBuffer, FBufferSize);
|
||||
|
||||
inherited Create(aFileSource, aSourceFile, aTargetPath);
|
||||
end;
|
||||
|
||||
destructor TFileSystemSplitOperation.Destroy;
|
||||
begin
|
||||
inherited Destroy;
|
||||
|
||||
if Assigned(FBuffer) then
|
||||
begin
|
||||
FreeMem(FBuffer);
|
||||
FBuffer := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TFileSystemSplitOperation.Initialize;
|
||||
begin
|
||||
// Get initialized statistics; then we change only what is needed.
|
||||
FStatistics := RetrieveStatistics;
|
||||
|
||||
with FStatistics do
|
||||
begin
|
||||
CurrentFileFrom:= SourceFile.FullPath;
|
||||
TotalFiles:= VolumeNumber;
|
||||
TotalBytes:= SourceFile.Size;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TFileSystemSplitOperation.MainExecute;
|
||||
var
|
||||
iExt, CurrentFileIndex: Integer;
|
||||
iTotalDiskSize, iFreeDiskSize: Int64;
|
||||
SourceFileStream: TFileStreamEx = nil;
|
||||
TargetFile: UTF8String;
|
||||
begin
|
||||
try
|
||||
{ Check disk free space }
|
||||
if FCheckFreeSpace = True then
|
||||
begin
|
||||
GetDiskFreeSpace(TargetPath, iFreeDiskSize, iTotalDiskSize);
|
||||
if FStatistics.TotalBytes > iFreeDiskSize then
|
||||
begin
|
||||
AskQuestion('', rsMsgNoFreeSpaceCont, [fsourAbort], fsourAbort, fsourAbort);
|
||||
RaiseAbortOperation;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Open source file
|
||||
SourceFileStream := TFileStreamEx.Create(SourceFile.FullPath, fmOpenRead or fmShareDenyNone);
|
||||
try
|
||||
// Calculate extension length
|
||||
iExt:= 2; // Minimum length 3 symbols
|
||||
CurrentFileIndex:= FStatistics.TotalFiles;
|
||||
while CurrentFileIndex >= 1 do
|
||||
begin
|
||||
CurrentFileIndex:= CurrentFileIndex div 1000;
|
||||
Inc(iExt);
|
||||
end;
|
||||
|
||||
for CurrentFileIndex := 1 to FStatistics.TotalFiles do
|
||||
begin
|
||||
TargetFile:= FTargetFile + ExtensionSeparator + Format('%.*d',[iExt, CurrentFileIndex]);
|
||||
|
||||
with FStatistics do
|
||||
begin
|
||||
// Last file can be smaller then volume size
|
||||
if (TotalBytes - DoneBytes) < VolumeSize then
|
||||
VolumeSize:= TotalBytes - DoneBytes;
|
||||
CurrentFileTo := TargetFile;
|
||||
CurrentFileTotalBytes := VolumeSize;
|
||||
CurrentFileDoneBytes := 0;
|
||||
end;
|
||||
UpdateStatistics(FStatistics);
|
||||
|
||||
// Split with current file
|
||||
if not Split(SourceFileStream, TargetFile) then Break;
|
||||
|
||||
with FStatistics do
|
||||
begin
|
||||
DoneFiles := DoneFiles + 1;
|
||||
UpdateStatistics(FStatistics);
|
||||
end;
|
||||
|
||||
CheckOperationState;
|
||||
end;
|
||||
finally
|
||||
if Assigned(SourceFileStream) then
|
||||
begin
|
||||
FreeAndNil(SourceFileStream);
|
||||
if (FStatistics.DoneBytes <> FStatistics.TotalBytes) then
|
||||
begin
|
||||
for CurrentFileIndex := 1 to FStatistics.TotalFiles do
|
||||
// There was some error, because not all files has been created.
|
||||
// Delete the not completed target files.
|
||||
mbDeleteFile(FTargetFile + ExtensionSeparator + Format('%.*d',[iExt, CurrentFileIndex]));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
except
|
||||
on EFOpenError do
|
||||
begin
|
||||
ShowError(rsMsgLogError + rsMsgErrEOpen + ': ' + SourceFile.FullPath);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TFileSystemSplitOperation.Finalize;
|
||||
begin
|
||||
end;
|
||||
|
||||
function TFileSystemSplitOperation.Split(aSourceFileStream: TFileStreamEx; TargetFile: UTF8String): Boolean;
|
||||
var
|
||||
TargetFileStream: TFileStreamEx = nil; // for safety exception handling
|
||||
iTotalDiskSize, iFreeDiskSize: Int64;
|
||||
bRetryRead, bRetryWrite: Boolean;
|
||||
BytesRead, BytesToRead, BytesWrittenTry, BytesWritten: Int64;
|
||||
TotalBytesToRead: Int64 = 0;
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
BytesToRead := FBufferSize;
|
||||
try
|
||||
try
|
||||
TargetFileStream := TFileStreamEx.Create(TargetFile, fmCreate);
|
||||
|
||||
TotalBytesToRead := VolumeSize;
|
||||
|
||||
while TotalBytesToRead > 0 do
|
||||
begin
|
||||
// Without the following line the reading is very slow
|
||||
// if it tries to read past end of file.
|
||||
if TotalBytesToRead < BytesToRead then
|
||||
BytesToRead := TotalBytesToRead;
|
||||
|
||||
repeat
|
||||
try
|
||||
bRetryRead := False;
|
||||
BytesRead := aSourceFileStream.Read(FBuffer^, BytesToRead);
|
||||
|
||||
if (BytesRead = 0) then
|
||||
Raise EReadError.Create(mbSysErrorMessage(GetLastOSError));
|
||||
|
||||
TotalBytesToRead := TotalBytesToRead - BytesRead;
|
||||
BytesWritten := 0;
|
||||
|
||||
repeat
|
||||
try
|
||||
bRetryWrite := False;
|
||||
BytesWrittenTry := TargetFileStream.Write((FBuffer + BytesWritten)^, BytesRead);
|
||||
BytesWritten := BytesWritten + BytesWrittenTry;
|
||||
if BytesWrittenTry = 0 then
|
||||
begin
|
||||
Raise EWriteError.Create(mbSysErrorMessage(GetLastOSError));
|
||||
end
|
||||
else if BytesWritten < BytesRead then
|
||||
begin
|
||||
bRetryWrite := True; // repeat and try to write the rest
|
||||
end;
|
||||
except
|
||||
on E: EWriteError do
|
||||
begin
|
||||
{ Check disk free space }
|
||||
GetDiskFreeSpace(TargetPath, iFreeDiskSize, iTotalDiskSize);
|
||||
if BytesRead > iFreeDiskSize then
|
||||
begin
|
||||
case AskQuestion(rsMsgNoFreeSpaceRetry, '',
|
||||
[fsourYes, fsourNo],
|
||||
fsourYes, fsourNo) of
|
||||
fsourYes:
|
||||
bRetryWrite := True;
|
||||
fsourNo:
|
||||
RaiseAbortOperation;
|
||||
end; // case
|
||||
end
|
||||
else
|
||||
begin
|
||||
case AskQuestion(rsMsgErrEWrite + ' ' + TargetFile + ':',
|
||||
E.Message,
|
||||
[fsourRetry, fsourSkip, fsourAbort],
|
||||
fsourRetry, fsourSkip) of
|
||||
fsourRetry:
|
||||
bRetryWrite := True;
|
||||
fsourAbort:
|
||||
RaiseAbortOperation;
|
||||
fsourSkip:
|
||||
Exit;
|
||||
end; // case
|
||||
end;
|
||||
|
||||
end; // on do
|
||||
end; // except
|
||||
until not bRetryWrite;
|
||||
except
|
||||
on E: EReadError do
|
||||
begin
|
||||
case AskQuestion(rsMsgErrERead + ' ' + SourceFile.FullPath + ':',
|
||||
E.Message,
|
||||
[fsourRetry, fsourSkip, fsourAbort],
|
||||
fsourRetry, fsourSkip) of
|
||||
fsourRetry:
|
||||
bRetryRead := True;
|
||||
fsourAbort:
|
||||
RaiseAbortOperation;
|
||||
fsourSkip:
|
||||
Exit;
|
||||
end; // case
|
||||
end;
|
||||
end;
|
||||
until not bRetryRead;
|
||||
|
||||
with FStatistics do
|
||||
begin
|
||||
CurrentFileDoneBytes := CurrentFileDoneBytes + BytesRead;
|
||||
DoneBytes := DoneBytes + BytesRead;
|
||||
|
||||
UpdateStatistics(FStatistics);
|
||||
end;
|
||||
|
||||
CheckOperationState; // check pause and stop
|
||||
end; //while
|
||||
|
||||
finally
|
||||
if Assigned(TargetFileStream) then
|
||||
FreeAndNil(TargetFileStream);
|
||||
end;
|
||||
|
||||
Result:= True;
|
||||
|
||||
except
|
||||
on EFCreateError do
|
||||
begin
|
||||
ShowError(rsMsgLogError + rsMsgErrECreate + ': ' + TargetFile);
|
||||
end;
|
||||
on EWriteError do
|
||||
begin
|
||||
ShowError(rsMsgLogError + rsMsgErrEWrite + ': ' + TargetFile);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TFileSystemSplitOperation.ShowError(sMessage: String);
|
||||
begin
|
||||
if gSkipFileOpError then
|
||||
logWrite(Thread, sMessage, lmtError, True)
|
||||
else
|
||||
begin
|
||||
AskQuestion(sMessage, '', [fsourAbort], fsourAbort, fsourAbort);
|
||||
RaiseAbortOperation;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TFileSystemSplitOperation.LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
|
||||
begin
|
||||
case logMsgType of
|
||||
lmtError:
|
||||
if not (log_errors in gLogOptions) then Exit;
|
||||
lmtInfo:
|
||||
if not (log_info in gLogOptions) then Exit;
|
||||
lmtSuccess:
|
||||
if not (log_success in gLogOptions) then Exit;
|
||||
end;
|
||||
|
||||
if logOptions <= gLogOptions then
|
||||
begin
|
||||
logWrite(Thread, sMessage, logMsgType);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
|
@ -2545,7 +2545,6 @@ end;
|
|||
procedure TActs.cm_FileLinker(param:string);
|
||||
var
|
||||
I: Integer;
|
||||
Result: Boolean;
|
||||
aSelectedFiles: TFiles = nil;
|
||||
aFile: TFile;
|
||||
begin
|
||||
|
|
@ -2558,7 +2557,6 @@ begin
|
|||
end;
|
||||
|
||||
try
|
||||
Result:= False;
|
||||
aSelectedFiles := CloneSelectedFiles;
|
||||
|
||||
for I := 0 to aSelectedFiles.Count - 1 do
|
||||
|
|
@ -2583,42 +2581,26 @@ end;
|
|||
|
||||
procedure TActs.cm_FileSpliter(param:string);
|
||||
var
|
||||
sl: TStringList = nil;
|
||||
I: Integer;
|
||||
Result: Boolean;
|
||||
aSelectedFiles: TFiles = nil;
|
||||
aFile: TFile;
|
||||
aFile: TFile = nil;
|
||||
begin
|
||||
with frmMain, frmMain.ActiveFrame do
|
||||
begin
|
||||
// For now only works for FileSystem.
|
||||
if FileSource.IsClass(TFileSystemFileSource) then
|
||||
begin
|
||||
sl:= TStringList.Create;
|
||||
try
|
||||
Result:= False;
|
||||
aSelectedFiles := CloneSelectedFiles;
|
||||
if not (fsoSplit in FileSource.GetOperationsTypes) then
|
||||
begin
|
||||
msgWarning(rsMsgErrNotSupported);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
for I := 0 to aSelectedFiles.Count - 1 do
|
||||
begin
|
||||
aFile := aSelectedFiles[I];
|
||||
if not (aFile.IsDirectory or aFile.IsLinkToDirectory) then
|
||||
sl.Add(CurrentPath + aFile.Name);
|
||||
end;
|
||||
|
||||
if sl.Count > 0 then
|
||||
Result:= ShowSplitterFileForm(sl, NotActiveFrame.CurrentPath);
|
||||
finally
|
||||
FreeThenNil(sl);
|
||||
FreeThenNil(aSelectedFiles);
|
||||
if Result then
|
||||
begin
|
||||
ActiveFrame.Reload;
|
||||
NotActiveFrame.Reload;
|
||||
end;
|
||||
ActiveFrame.SetFocus;
|
||||
end; // try
|
||||
end; // if
|
||||
try
|
||||
aFile := CloneActiveFile;
|
||||
if (not Assigned(aFile)) or (aFile.IsDirectory or aFile.IsLinkToDirectory) then
|
||||
msgWarning(rsMsgInvalidSelection)
|
||||
else
|
||||
ShowSplitterFileForm(FileSource, aFile, NotActiveFrame.CurrentPath);
|
||||
finally
|
||||
FreeThenNil(aFile);
|
||||
end; // try
|
||||
end; // with
|
||||
end;
|
||||
|
||||
|
|
|
|||
|
|
@ -180,7 +180,8 @@ resourcestring
|
|||
rsDlgSpeedTime = 'Speed %s/s, time remaining %s';
|
||||
rsDlgDel = 'Delete file(s)';
|
||||
rsDlgWipe = 'Wipe file(s)';
|
||||
rsDlgCombine = 'Combine files';
|
||||
rsDlgSplit = 'Split';
|
||||
rsDlgCombine = 'Combine';
|
||||
rsDlgCp = 'Copy file(s)';
|
||||
rsDlgMv = 'Move file(s)';
|
||||
rsDlgPack = 'Packing...';
|
||||
|
|
@ -278,10 +279,7 @@ resourcestring
|
|||
rsSplitErrFileSize = 'Incorrect file size format!';
|
||||
rsSplitErrDirectory = 'Unable to create target directory!';
|
||||
rsSplitErrSplitFile = 'Unable to split the file!';
|
||||
rsSplitErrTooManyParts = 'Too many parts!';
|
||||
rsSplitMsgManyParts = 'The number of parts is more than 100! Continue?';
|
||||
rsSplitMsgCreated = 'Created:';
|
||||
rsSplitMsgSize = 'size:';
|
||||
// MultiRename dialog
|
||||
rsMulRenFileNameStyleList = 'No change;UPPERCASE;lowercase;First char uppercase;' +
|
||||
'First Char Of Every Word Uppercase;';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue