{ Double Commander ------------------------------------------------------------------------- Window displaying progress for file source operations and queues. Copyright (C) 2008-2015 Alexander Koblov (alexx2000@mail.ru) Copyright (C) 2012 Przemysław Nagay (cobines@gmail.com) 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA } unit fFileOpDlg; {$mode objfpc}{$H+} interface uses SysUtils, Classes, Controls, Forms, StdCtrls, ComCtrls, Buttons, ExtCtrls, KASProgressBar, uOperationsManager, uFileSourceOperation, uFileSourceOperationUI, uOSForms, types; type TFileOpDlgLook = set of (fodl_from_lbl, fodl_to_lbl, fodl_current_pb, fodl_total_pb); TOperationProgressWindowEvent = (opwevOpened, opwevClosed); TOperationProgressWindowEvents = set of TOperationProgressWindowEvent; TOperationProgressWindowEventProc = procedure(OperationHandle: TOperationHandle; Event: TOperationProgressWindowEvent) of object; TOperationProgressWindowOption = (opwoIfExistsBringToFront, opwoStartMinimized); TOperationProgressWindowOptions = set of TOperationProgressWindowOption; { TfrmFileOp } TfrmFileOp = class(TAloneForm) btnCancel: TBitBtn; btnPauseStart: TBitBtn; btnViewOperations: TBitBtn; btnMinimizeToPanel: TBitBtn; lblCurrentOperationText: TLabel; lblEstimated: TLabel; lblFileNameFrom: TLabel; lblFileNameTo: TLabel; lblFrom: TLabel; lblCurrentOperation: TLabel; lblTo: TLabel; pnlQueue: TPanel; pbCurrent: TKASProgressBar; pbTotal: TKASProgressBar; pnlButtons: TPanel; pnlClient: TPanel; pnlFrom: TPanel; pnlTo: TPanel; procedure btnCancelClick(Sender: TObject); procedure btnMinimizeToPanelClick(Sender: TObject); procedure btnPauseStartClick(Sender: TObject); procedure btnViewOperationsClick(Sender: TObject); procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); procedure FormCreate(Sender: TObject); procedure pbCurrentContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); private FOperationHandle: TOperationHandle; FQueueIdentifier: TOperationsManagerQueueIdentifier; FUpdateTimer: TTimer; // 0) then Result := Queue.Items[0].Handle else Result := InvalidOperationHandle; end; class function TfrmFileOp.GetOpenedForm(AOperationHandle: TOperationHandle): TfrmFileOp; var Index: Integer; Item: POpenedForm; begin for Index := 0 to OpenedForms.Count - 1 do begin Item := OpenedForms[Index]; if Item^.OperationHandle = AOperationHandle then Exit(Item^.Form); end; Result := nil; end; class function TfrmFileOp.GetOpenedForm(AQueueIdentifier: TOperationsManagerQueueIdentifier): TfrmFileOp; var Index: Integer; Item: POpenedForm; begin for Index := 0 to OpenedForms.Count - 1 do begin Item := OpenedForms[Index]; if Item^.QueueIdentifier = AQueueIdentifier then Exit(Item^.Form); end; Result := nil; end; constructor TfrmFileOp.Create(OperationHandle: TOperationHandle); var OpManItem: TOperationsManagerItem; begin FOperationHandle := InvalidOperationHandle; inherited Create(Application); AutoSize := True; OpManItem := OperationsManager.GetItemByHandle(OperationHandle); if Assigned(OpManItem) then begin FStopOperationOnClose := True; FOperationHandle := OperationHandle; end else begin CloseDialog; end; end; constructor TfrmFileOp.Create(QueueIdentifier: TOperationsManagerQueueIdentifier); begin Create(GetFirstOperationHandle(QueueIdentifier)); end; destructor TfrmFileOp.Destroy; begin inherited Destroy; FreeAndNil(FUserInterface); end; procedure TfrmFileOp.FinalizeOperation; var OpManItem: TOperationsManagerItem; begin FUpdateTimer.Enabled := False; if FOperationHandle <> InvalidOperationHandle then begin if Assigned(FUserInterface) then begin OpManItem := OperationsManager.GetItemByHandle(FOperationHandle); if Assigned(OpManItem) then OpManItem.Operation.RemoveUserInterface(FUserInterface); end; RemoveFromOpenedForms; FOperationHandle := InvalidOperationHandle; end; end; function TfrmFileOp.CloseQuery: Boolean; begin Result := True; if FStopOperationOnClose then StopOperationOrQueue; end; class procedure TfrmFileOp.AddEventsListener(Events: TOperationProgressWindowEvents; FunctionToCall: TOperationProgressWindowEventProc); var Item: PEventsListItem; Event: TOperationProgressWindowEvent; begin for Event in Events do begin New(Item); Item^.EventFunction := FunctionToCall; EventsListeners[Event].Add(Item); end; end; function TfrmFileOp.AddToOpenedForms(OpManItem: TOperationsManagerItem): Boolean; var Index: Integer; Item: POpenedForm; Found: Boolean = False; begin for Index := 0 to OpenedForms.Count - 1 do begin Item := OpenedForms[Index]; // Check if another form is not already opened for the operation or queue. if (Item^.OperationHandle = FOperationHandle) or (not OpManItem.Queue.IsFree and (Item^.QueueIdentifier = FQueueIdentifier)) then begin Exit(False); end else if Item^.Form = Self then begin Found := True; Break; end; end; if not Found then begin New(Item); OpenedForms.Add(Item); end; Item^.Form := Self; Item^.OperationHandle := FOperationHandle; Item^.QueueIdentifier := FQueueIdentifier; NotifyEvents([opwevOpened]); Result := True; end; class procedure TfrmFileOp.RemoveEventsListener(Events: TOperationProgressWindowEvents; FunctionToCall: TOperationProgressWindowEventProc); var Item: PEventsListItem; Event: TOperationProgressWindowEvent; i: Integer; begin for Event in Events do begin for i := 0 to EventsListeners[Event].Count - 1 do begin Item := PEventsListItem(EventsListeners[Event].Items[i]); if Item^.EventFunction = FunctionToCall then begin EventsListeners[Event].Delete(i); Dispose(Item); Break; // break from one for only end; end; end; end; procedure TfrmFileOp.RemoveFromOpenedForms; var i: Integer; Item: POpenedForm; begin for i := 0 to OpenedForms.Count - 1 do begin Item := OpenedForms[i]; if Item^.Form = Self then begin Dispose(Item); OpenedForms.Delete(i); NotifyEvents([opwevClosed]); Break; end; end; end; class function TfrmFileOp.IsOpenedFor(AOperationHandle: TOperationHandle): Boolean; begin Result := Assigned(GetOpenedForm(AOperationHandle)); end; class function TfrmFileOp.IsOpenedFor(AQueueIdentifier: TOperationsManagerQueueIdentifier): Boolean; begin Result := Assigned(GetOpenedForm(AQueueIdentifier)); end; class procedure TfrmFileOp.ShowFor(AOperationHandle: TOperationHandle; Options: TOperationProgressWindowOptions); var OperationDialog: TfrmFileOp; OpManItem: TOperationsManagerItem; begin OpManItem := OperationsManager.GetItemByHandle(AOperationHandle); if Assigned(OpManItem) then begin if not OpManItem.Queue.IsFree then begin ShowFor(OpManItem.Queue.Identifier, Options); end else begin OperationDialog := GetOpenedForm(AOperationHandle); if Assigned(OperationDialog) then ShowExistingWindow(OperationDialog, Options) else begin OperationDialog := TfrmFileOp.Create(AOperationHandle); ShowNewWindow(OperationDialog, Options); end; end; end; end; class procedure TfrmFileOp.ShowFor(AQueueIdentifier: TOperationsManagerQueueIdentifier; Options: TOperationProgressWindowOptions); var OperationDialog: TfrmFileOp; begin OperationDialog := GetOpenedForm(AQueueIdentifier); if Assigned(OperationDialog) then begin ShowExistingWindow(OperationDialog, Options); end else begin OperationDialog := TfrmFileOp.Create(AQueueIdentifier); ShowNewWindow(OperationDialog, Options); end; end; class procedure TfrmFileOp.ShowExistingWindow(AWindow: TfrmFileOp; Options: TOperationProgressWindowOptions); begin if opwoIfExistsBringToFront in Options then AWindow.ShowOnTop; end; class procedure TfrmFileOp.ShowNewWindow(AWindow: TfrmFileOp; Options: TOperationProgressWindowOptions); begin if opwoStartMinimized in Options then begin {$IF lcl_fullversion >= 093100} // Workaround for bug in Lazarus 0.9.31 #0021603. AWindow.Visible := True; AWindow.WindowState := wsMinimized; {$ELSE} AWindow.WindowState := wsMinimized; AWindow.Visible := True; {$ENDIF} end else AWindow.Show; end; procedure TfrmFileOp.StopOperationOrQueue; var OpManItem: TOperationsManagerItem; begin OpManItem := OperationsManager.GetItemByHandle(FOperationHandle); if Assigned(OpManItem) then begin if OpManItem.Queue.IsFree then OpManItem.Operation.Stop else OpManItem.Queue.Stop; end; end; procedure TfrmFileOp.OnUpdateTimer(Sender: TObject); var OpManItem: TOperationsManagerItem; Queue: TOperationsManagerQueue; begin OpManItem := OperationsManager.GetItemByHandle(FOperationHandle); // Check if operation did not change queues. if Assigned(OpManItem) and (OpManItem.Queue.Identifier <> FQueueIdentifier) then begin Queue := OperationsManager.QueueByIdentifier[FQueueIdentifier]; FinalizeOperation; if Assigned(Queue) and not Queue.IsFree then begin // Queue was begin followed - switch to next operation from that queue. FQueueIdentifier := Queue.Identifier; FOperationHandle := GetFirstOperationHandle(Queue.Identifier); end else begin // Follow the operation to new queue either because previously followed // queue was free-operations queue or old queue was destroyed. FQueueIdentifier := OpManItem.Queue.Identifier; FOperationHandle := OpManItem.Handle; end; if not InitializeOperation then begin CloseDialog; Exit; end; OpManItem := OperationsManager.GetItemByHandle(FOperationHandle); end; // Check if first operation in the queue hasn't changed. if Assigned(OpManItem) and not OpManItem.Queue.IsFree and (GetFirstOperationHandle(FQueueIdentifier) <> FOperationHandle) then begin FinalizeOperation; FOperationHandle := GetFirstOperationHandle(FQueueIdentifier); if not InitializeOperation then begin CloseDialog; Exit; end; OpManItem := OperationsManager.GetItemByHandle(FOperationHandle); end; if Assigned(OpManItem) then begin UpdateOperation(OpManItem); end else // Operation was destroyed begin Queue := OperationsManager.QueueByIdentifier[FQueueIdentifier]; if not Assigned(Queue) or Queue.IsFree then begin // Single operation was being followed and it has finished // or all operations in queue have finished - close window. CloseDialog; end else begin // Queue was begin followed - switch to next operation from that queue. FOperationHandle := GetFirstOperationHandle(FQueueIdentifier); OpManItem := OperationsManager.GetItemByHandle(FOperationHandle); OpManItem.Operation.AddUserInterface(FUserInterface); end; end; end; procedure TfrmFileOp.InitializeControls(OpManItem: TOperationsManagerItem; FileOpDlgLook: TFileOpDlgLook); begin pnlQueue.Visible := not OpManItem.Queue.IsFree; lblFrom.Visible := fodl_from_lbl in FileOpDlgLook; lblFileNameFrom.Visible := lblFrom.Visible; lblTo.Visible := fodl_to_lbl in FileOpDlgLook; lblFileNameTo.Visible := lblTo.Visible; pbCurrent.Visible := fodl_current_pb in FileOpDlgLook; pbTotal.Visible := fodl_total_pb in FileOpDlgLook; pbCurrent.ShowInTaskbar := [fodl_current_pb, fodl_total_pb] * FileOpDlgLook = [fodl_current_pb]; pbTotal.ShowInTaskbar := fodl_total_pb in FileOpDlgLook; lblFileNameFrom.Caption := ''; lblFileNameTo.Caption := ''; lblEstimated.Caption := #32; end; procedure TfrmFileOp.NotifyEvents(Events: TOperationProgressWindowEvents); var Item: PEventsListItem; Event: TOperationProgressWindowEvent; i: Integer; begin for Event in Events do begin for i := 0 to EventsListeners[Event].Count - 1 do begin Item := EventsListeners[Event].Items[i]; Item^.EventFunction(FOperationHandle, Event); end; end; end; procedure TfrmFileOp.SetPauseGlyph; begin dmComData.ImageList.GetBitmap(1, btnPauseStart.Glyph); end; procedure TfrmFileOp.SetPlayGlyph; begin dmComData.ImageList.GetBitmap(0, btnPauseStart.Glyph); end; procedure TfrmFileOp.SetProgressBytes(Operation: TFileSourceOperation; ProgressBar: TKASProgressBar; CurrentBytes: Int64; TotalBytes: Int64); begin if (CurrentBytes = -1) then ProgressBar.Style := pbstMarquee else begin if Operation.State = fsosRunning then ProgressBar.Style := pbstNormal; ProgressBar.SetProgress(CurrentBytes, TotalBytes, cnvFormatFileSize(CurrentBytes, True) + 'B/' + cnvFormatFileSize(TotalBytes, True) + 'B' ); end; end; procedure TfrmFileOp.SetProgressFiles(Operation: TFileSourceOperation; ProgressBar: TKASProgressBar; CurrentFiles: Int64; TotalFiles: Int64); begin if (CurrentFiles = -1) then ProgressBar.Style := pbstMarquee else begin if Operation.State = fsosRunning then ProgressBar.Style := pbstNormal; ProgressBar.SetProgress(CurrentFiles, TotalFiles, cnvFormatFileSize(CurrentFiles, True) + '/' + cnvFormatFileSize(TotalFiles, True) ); end; end; procedure TfrmFileOp.SetSpeedAndTime(Operation: TFileSourceOperation; RemainingTime: TDateTime; Speed: String); var sEstimated: String; begin if Operation.State <> fsosRunning then sEstimated := #32 else begin if RemainingTime > 0 then begin if RemainingTime < 1 then sEstimated := FormatDateTime('HH:MM:SS', RemainingTime) //normal wiev, less than 24 hours of estimated time // if the estimated time is greather (or equal) than 24 hour, there is viewed in modulo 24 else sEstimated := FormatDateTime('d HH:MM:SS', RemainingTime);//by estimation, operation take more than 24 hours //This soulution is not an ideal one (what hapen, in case of more thah 30 d), it may be better to view d days hh:mm:ss (but the word "day" //can be (must be) different in differrent languages and not only in my language is different form for different //count of days (1="den"; 2,3,4="dny"; >5="dnů")) //larger number in hours without conversion to days may be sipmlest to implementation but less clear for ussers //or can you realize, how much time take operation if odhad is for instance 126 hours sEstimated := Format(rsDlgSpeedTime, [Speed, sEstimated]); end else sEstimated := Format(rsDlgSpeed, [Speed]); end; lblEstimated.Caption := sEstimated; end; procedure TfrmFileOp.InitializeCopyOperation(OpManItem: TOperationsManagerItem); begin InitializeControls(OpManItem, [fodl_from_lbl, fodl_to_lbl, fodl_current_pb, fodl_total_pb]); end; procedure TfrmFileOp.InitializeMoveOperation(OpManItem: TOperationsManagerItem); begin InitializeControls(OpManItem, [fodl_from_lbl, fodl_to_lbl, fodl_current_pb, fodl_total_pb]); end; function TfrmFileOp.InitializeOperation: Boolean; var OpManItem: TOperationsManagerItem; begin Result := False; OpManItem := OperationsManager.GetItemByHandle(FOperationHandle); if Assigned(OpManItem) and not OpManItem.Queue.IsFree then begin FOperationHandle := GetFirstOperationHandle(OpManItem.Queue.Identifier); OpManItem := OperationsManager.GetItemByHandle(FOperationHandle); end; if Assigned(OpManItem) then begin FQueueIdentifier := OpManItem.Queue.Identifier; if AddToOpenedForms(OpManItem) then begin if not Assigned(FUserInterface) then FUserInterface := TFileSourceOperationMessageBoxesUI.Create; OpManItem.Operation.AddUserInterface(FUserInterface); ProgressBarStyle:= pbstMarquee; case OpManItem.Operation.ID of fsoCopy, fsoCopyIn, fsoCopyOut: InitializeCopyOperation(OpManItem); fsoMove: InitializeMoveOperation(OpManItem); fsoDelete: InitializeDeleteOperation(OpManItem); fsoWipe: InitializeWipeOperation(OpManItem); fsoSplit: InitializeSplitOperation(OpManItem); fsoCombine: InitializeCombineOperation(OpManItem); fsoCalcChecksum: InitializeCalcChecksumOperation(OpManItem); fsoTestArchive: InitializeTestArchiveOperation(OpManItem); fsoCalcStatistics: InitializeCalcStatisticsOperation(OpManItem); else begin InitializeControls(OpManItem, [fodl_total_pb]); end; end; UpdatePauseStartButton(OpManItem); Caption := EmptyStr; FUpdateTimer.Enabled := True; Result := True; end; end; if not Result then FOperationHandle := InvalidOperationHandle; end; procedure TfrmFileOp.InitializeDeleteOperation(OpManItem: TOperationsManagerItem); begin InitializeControls(OpManItem, [fodl_total_pb]); end; procedure TfrmFileOp.InitializeCalcStatisticsOperation(OpManItem: TOperationsManagerItem); begin InitializeControls(OpManItem, [fodl_from_lbl]); end; procedure TfrmFileOp.InitializeWipeOperation(OpManItem: TOperationsManagerItem); begin InitializeControls(OpManItem, [fodl_current_pb, fodl_total_pb]); end; procedure TfrmFileOp.InitializeSplitOperation(OpManItem: TOperationsManagerItem); begin InitializeControls(OpManItem, [fodl_from_lbl, fodl_to_lbl, fodl_current_pb, fodl_total_pb]); end; procedure TfrmFileOp.InitializeCombineOperation(OpManItem: TOperationsManagerItem); begin InitializeControls(OpManItem, [fodl_from_lbl, fodl_to_lbl, fodl_current_pb, fodl_total_pb]); end; procedure TfrmFileOp.InitializeCalcChecksumOperation(OpManItem: TOperationsManagerItem); begin InitializeControls(OpManItem, [fodl_current_pb, fodl_total_pb]); end; procedure TfrmFileOp.InitializeTestArchiveOperation(OpManItem: TOperationsManagerItem); begin InitializeControls(OpManItem, [fodl_from_lbl, fodl_to_lbl, fodl_current_pb, fodl_total_pb]); end; procedure TfrmFileOp.UpdateCopyOperation(Operation: TFileSourceOperation); var CopyOperation: TFileSourceCopyOperation; CopyStatistics: TFileSourceCopyOperationStatistics; begin CopyOperation := Operation as TFileSourceCopyOperation; CopyStatistics := CopyOperation.RetrieveStatistics; with CopyStatistics do begin lblFileNameFrom.Caption := MinimizeFilePath(CurrentFileFrom, lblFileNameFrom.Canvas, lblFileNameFrom.Width); lblFileNameTo.Caption := MinimizeFilePath(CurrentFileTo, lblFileNameTo.Canvas, lblFileNameTo.Width); SetProgressBytes(Operation, pbCurrent, CurrentFileDoneBytes, CurrentFileTotalBytes); SetProgressBytes(Operation, pbTotal, DoneBytes, TotalBytes); SetSpeedAndTime(Operation, RemainingTime, cnvFormatFileSize(BytesPerSecond, True) + 'B'); end; end; procedure TfrmFileOp.UpdateMoveOperation(Operation: TFileSourceOperation); var MoveOperation: TFileSourceMoveOperation; MoveStatistics: TFileSourceMoveOperationStatistics; begin MoveOperation := Operation as TFileSourceMoveOperation; MoveStatistics := MoveOperation.RetrieveStatistics; with MoveStatistics do begin lblFileNameFrom.Caption := MinimizeFilePath(CurrentFileFrom, lblFileNameFrom.Canvas, lblFileNameFrom.Width); lblFileNameTo.Caption := MinimizeFilePath(CurrentFileTo, lblFileNameTo.Canvas, lblFileNameTo.Width); SetProgressBytes(Operation, pbCurrent, CurrentFileDoneBytes, CurrentFileTotalBytes); SetProgressBytes(Operation, pbTotal, DoneBytes, TotalBytes); SetSpeedAndTime(Operation, RemainingTime, cnvFormatFileSize(BytesPerSecond, True) + 'B'); end; end; procedure TfrmFileOp.UpdateOperation(OpManItem: TOperationsManagerItem); var NewCaption: String; begin case OpManItem.Operation.ID of fsoCopy, fsoCopyIn, fsoCopyOut: UpdateCopyOperation(OpManItem.Operation); fsoMove: UpdateMoveOperation(OpManItem.Operation); fsoDelete: UpdateDeleteOperation(OpManItem.Operation); fsoWipe: UpdateWipeOperation(OpManItem.Operation); fsoSplit: UpdateSplitOperation(OpManItem.Operation); fsoCombine: UpdateCombineOperation(OpManItem.Operation); fsoCalcChecksum: UpdateCalcChecksumOperation(OpManItem.Operation); fsoCalcStatistics: UpdateCalcStatisticsOperation(OpManItem.Operation); fsoTestArchive: UpdateTestArchiveOperation(OpManItem.Operation); else begin // Operation not currently supported for display. // Only show general progress. pbTotal.Position := Round(OpManItem.Operation.Progress * pbTotal.Max); end; end; UpdatePauseStartButton(OpManItem); if OpManItem.Queue.IsFree then begin NewCaption := GetProgressString(OpManItem.Operation.Progress) + ' ' + OpManItem.Operation.GetDescription(fsoddJob) + GetOperationStateString(OpManItem.Operation.State); end else begin if OpManItem.Queue.Paused then NewCaption := '[' + IntToStr(OpManItem.Queue.Count) + '] ' + OpManItem.Queue.GetDescription(False) + GetOperationStateString(fsosPaused) else NewCaption := '[' + IntToStr(OpManItem.Queue.Count) + '] ' + GetProgressString(OpManItem.Operation.Progress) + ' ' + OpManItem.Operation.GetDescription(fsoddJob) + ' - ' + OpManItem.Queue.GetDescription(False); lblCurrentOperationText.Caption := OpManItem.Operation.GetDescription(fsoddJob) + ' ' + GetProgressString(OpManItem.Operation.Progress); end; Caption := NewCaption; end; procedure TfrmFileOp.UpdatePauseStartButton(OpManItem: TOperationsManagerItem); begin if OpManItem.Queue.IsFree then begin case OpManItem.Operation.State of fsosNotStarted, fsosStopped, fsosPaused: begin btnPauseStart.Enabled := True; SetPlayGlyph; end; fsosStarting, fsosStopping, fsosPausing, fsosWaitingForFeedback: begin btnPauseStart.Enabled := False; end; fsosRunning, fsosWaitingForConnection: begin btnPauseStart.Enabled := True; SetPauseGlyph; end; else btnPauseStart.Enabled := False; end; end else begin btnPauseStart.Enabled := True; if OpManItem.Queue.Paused then SetPlayGlyph else SetPauseGlyph; end; end; procedure TfrmFileOp.UpdateDeleteOperation(Operation: TFileSourceOperation); var DeleteOperation: TFileSourceDeleteOperation; DeleteStatistics: TFileSourceDeleteOperationStatistics; begin DeleteOperation := Operation as TFileSourceDeleteOperation; DeleteStatistics := DeleteOperation.RetrieveStatistics; with DeleteStatistics do begin lblFileNameFrom.Caption := MinimizeFilePath(CurrentFile, lblFileNameFrom.Canvas, lblFileNameFrom.Width); SetProgressFiles(Operation, pbTotal, DoneFiles, TotalFiles); SetSpeedAndTime(Operation, RemainingTime, cnvFormatFileSize(FilesPerSecond, True)); end; end; procedure TfrmFileOp.UpdateWipeOperation(Operation: TFileSourceOperation); var WipeOperation: TFileSourceWipeOperation; WipeStatistics: TFileSourceWipeOperationStatistics; begin WipeOperation := Operation as TFileSourceWipeOperation; WipeStatistics := WipeOperation.RetrieveStatistics; with WipeStatistics do begin lblFileNameFrom.Caption := MinimizeFilePath(CurrentFile, lblFileNameFrom.Canvas, lblFileNameFrom.Width); SetProgressBytes(Operation, pbCurrent, CurrentFileDoneBytes, CurrentFileTotalBytes); SetProgressBytes(Operation, pbTotal, DoneBytes, TotalBytes); SetSpeedAndTime(Operation, RemainingTime, cnvFormatFileSize(BytesPerSecond, True) + 'B'); 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(Operation, pbCurrent, CurrentFileDoneBytes, CurrentFileTotalBytes); SetProgressBytes(Operation, pbTotal, DoneBytes, TotalBytes); SetSpeedAndTime(Operation, RemainingTime, cnvFormatFileSize(BytesPerSecond, True) + 'B'); end; end; procedure TfrmFileOp.UpdateCombineOperation(Operation: TFileSourceOperation); var CombineOperation: TFileSourceCombineOperation; CombineStatistics: TFileSourceCombineOperationStatistics; begin CombineOperation := Operation as TFileSourceCombineOperation; CombineStatistics := CombineOperation.RetrieveStatistics; with CombineStatistics do begin lblFileNameFrom.Caption := MinimizeFilePath(CurrentFileFrom, lblFileNameFrom.Canvas, lblFileNameFrom.Width); lblFileNameTo.Caption := MinimizeFilePath(CurrentFileTo, lblFileNameTo.Canvas, lblFileNameTo.Width); SetProgressBytes(Operation, pbCurrent, CurrentFileDoneBytes, CurrentFileTotalBytes); SetProgressBytes(Operation, pbTotal, DoneBytes, TotalBytes); SetSpeedAndTime(Operation, RemainingTime, cnvFormatFileSize(BytesPerSecond, True) + 'B'); end; end; procedure TfrmFileOp.UpdateCalcStatisticsOperation(Operation: TFileSourceOperation); var CalcStatisticsOperation: TFileSourceCalcStatisticsOperation; CalcStatisticsOperationStatistics: TFileSourceCalcStatisticsOperationStatistics; begin CalcStatisticsOperation := Operation as TFileSourceCalcStatisticsOperation; CalcStatisticsOperationStatistics := CalcStatisticsOperation.RetrieveStatistics; with CalcStatisticsOperationStatistics do begin lblFileNameFrom.Caption := MinimizeFilePath(CurrentFile, lblFileNameFrom.Canvas, lblFileNameFrom.Width); SetSpeedAndTime(Operation, 0, cnvFormatFileSize(FilesPerSecond, True)); end; end; procedure TfrmFileOp.UpdateCalcChecksumOperation(Operation: TFileSourceOperation); var CalcChecksumOperation: TFileSourceCalcChecksumOperation; CalcChecksumStatistics: TFileSourceCalcChecksumOperationStatistics; begin CalcChecksumOperation := Operation as TFileSourceCalcChecksumOperation; CalcChecksumStatistics := CalcChecksumOperation.RetrieveStatistics; with CalcChecksumStatistics do begin lblFileNameFrom.Caption := MinimizeFilePath(CurrentFile, lblFileNameFrom.Canvas, lblFileNameFrom.Width); SetProgressBytes(Operation, pbCurrent, CurrentFileDoneBytes, CurrentFileTotalBytes); SetProgressBytes(Operation, pbTotal, DoneBytes, TotalBytes); SetSpeedAndTime(Operation, RemainingTime, cnvFormatFileSize(BytesPerSecond, True) + 'B'); end; end; procedure TfrmFileOp.UpdateTestArchiveOperation(Operation: TFileSourceOperation); var TestArchiveOperation: TFileSourceTestArchiveOperation; TestArchiveStatistics: TFileSourceTestArchiveOperationStatistics; begin TestArchiveOperation := Operation as TFileSourceTestArchiveOperation; TestArchiveStatistics := TestArchiveOperation.RetrieveStatistics; with TestArchiveStatistics do begin lblFileNameFrom.Caption := MinimizeFilePath(ArchiveFile, lblFileNameFrom.Canvas, lblFileNameFrom.Width); lblFileNameTo.Caption := MinimizeFilePath(CurrentFile, lblFileNameTo.Canvas, lblFileNameTo.Width); SetProgressBytes(Operation, pbCurrent, CurrentFileDoneBytes, CurrentFileTotalBytes); SetProgressBytes(Operation, pbTotal, DoneBytes, TotalBytes); SetSpeedAndTime(Operation, RemainingTime, cnvFormatFileSize(BytesPerSecond, True) + 'B'); end; end; function TfrmFileOp.GetProgressBarStyle: TProgressBarStyle; begin if (pbCurrent.Style = pbstMarquee) and (pbTotal.Style = pbstMarquee) then Result:= pbstMarquee else Result:= pbstNormal; end; procedure TfrmFileOp.SetProgressBarStyle(const AValue: TProgressBarStyle); begin pbCurrent.Style:= AValue; pbTotal.Style:= AValue; end; initialization Initialize; finalization Finalize; end.