Ignore:
Timestamp:
Sep 10, 2022, 6:54:43 PM (2 years ago)
Author:
chronos
Message:
  • Modified: CoolTranslator replaced by Common package.
  • Modified: Update common package.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Packages/Common/UJobProgressView.pas

    r15 r25  
    11unit UJobProgressView;
    2 
    3 {$MODE Delphi}
    42
    53interface
     
    75uses
    86  SysUtils, Variants, Classes, Graphics, Controls, Forms, Syncobjs,
    9   Dialogs, ComCtrls, StdCtrls, ExtCtrls, Contnrs, UThreading,
     7  Dialogs, ComCtrls, StdCtrls, ExtCtrls, Generics.Collections, UThreading, Math,
    108  DateUtils;
    119
     
    1311  EstimatedTimeShowTreshold = 4;
    1412  EstimatedTimeShowTresholdTotal = 1;
    15   MemoLogHeight = 200;
    1613  UpdateInterval = 100; // ms
    1714
     
    2421    FLock: TCriticalSection;
    2522    FOnChange: TNotifyEvent;
     23    FText: string;
    2624    FValue: Integer;
    2725    FMax: Integer;
    2826    procedure SetMax(const AValue: Integer);
     27    procedure SetText(AValue: string);
    2928    procedure SetValue(const AValue: Integer);
    3029  public
     
    3534    property Value: Integer read FValue write SetValue;
    3635    property Max: Integer read FMax write SetMax;
     36    property Text: string read FText write SetText;
    3737    property OnChange: TNotifyEvent read FOnChange write FOnChange;
    3838  end;
     
    6969  end;
    7070
     71  TJobs = class(TObjectList<TJob>)
     72  end;
     73
    7174  TJobThread = class(TListedThread)
    7275    procedure Execute; override;
     
    8083  TFormJobProgressView = class(TForm)
    8184    ImageList1: TImageList;
     85    LabelText: TLabel;
    8286    Label2: TLabel;
    8387    LabelOperation: TLabel;
     
    8690    ListViewJobs: TListView;
    8791    MemoLog: TMemo;
     92    PanelText: TPanel;
    8893    PanelProgressTotal: TPanel;
    8994    PanelOperationsTitle: TPanel;
     
    9499    ProgressBarTotal: TProgressBar;
    95100    TimerUpdate: TTimer;
     101    procedure FormHide(Sender: TObject);
     102    procedure FormShow(Sender: TObject);
     103    procedure ReloadJobList;
    96104    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    97     procedure FormDestroy(Sender: TObject);
    98105    procedure ListViewJobsData(Sender: TObject; Item: TListItem);
    99106    procedure TimerUpdateTimer(Sender: TObject);
    100107    procedure FormCreate(Sender: TObject);
    101108    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
     109    procedure UpdateHeight;
    102110  public
    103111    JobProgressView: TJobProgressView;
     
    118126    TotalStartTime: TDateTime;
    119127    Log: TStringList;
     128    FForm: TFormJobProgressView;
    120129    procedure SetTerminate(const AValue: Boolean);
    121130    procedure UpdateProgress;
    122     procedure ReloadJobList;
    123     procedure StartJobs;
    124     procedure UpdateHeight;
    125131    procedure JobProgressChange(Sender: TObject);
    126132  public
    127     Form: TFormJobProgressView;
    128     Jobs: TObjectList; // TListObject<TJob>
     133    Jobs: TJobs;
    129134    CurrentJob: TJob;
    130135    CurrentJobIndex: Integer;
     
    132137    destructor Destroy; override;
    133138    procedure Clear;
    134     procedure AddJob(Title: string; Method: TJobProgressViewMethod;
    135       NoThreaded: Boolean = False; WaitFor: Boolean = False);
    136     procedure Start(AAutoClose: Boolean = True);
     139    function AddJob(Title: string; Method: TJobProgressViewMethod;
     140      NoThreaded: Boolean = False; WaitFor: Boolean = False): TJob;
     141    procedure Start;
    137142    procedure Stop;
    138143    procedure TermSleep(Delay: Integer);
     144    property Form: TFormJobProgressView read FForm;
    139145    property Terminate: Boolean read FTerminate write SetTerminate;
    140146  published
     
    156162  SExecuted = 'Executed';
    157163
     164
    158165implementation
    159166
     
    166173  STotalEstimatedTime = 'Total estimated time: %s';
    167174  SFinished = 'Finished';
    168   SOperations = 'Operations';
    169175
    170176procedure Register;
     
    172178  RegisterComponents('Common', [TJobProgressView]);
    173179end;
     180
     181{ TJobThread }
    174182
    175183procedure TJobThread.Execute;
     
    190198end;
    191199
    192 procedure TJobProgressView.AddJob(Title: string; Method: TJobProgressViewMethod;
    193   NoThreaded: Boolean = False; WaitFor: Boolean = False);
     200{ TFormJobProgressView }
     201
     202procedure TFormJobProgressView.UpdateHeight;
    194203var
    195   NewJob: TJob;
    196 begin
    197   NewJob := TJob.Create;
    198   NewJob.ProgressView := Self;
    199   NewJob.Title := Title;
    200   NewJob.Method := Method;
    201   NewJob.NoThreaded := NoThreaded;
    202   NewJob.WaitFor := WaitFor;
    203   NewJob.Progress.Max := 100;
    204   NewJob.Progress.Reset;
    205   NewJob.Progress.OnChange := JobProgressChange;
    206   Jobs.Add(NewJob);
     204  H: Integer;
     205  PanelOperationsVisible: Boolean;
     206  PanelOperationsHeight: Integer;
     207  PanelProgressVisible: Boolean;
     208  PanelProgressTotalVisible: Boolean;
     209  PanelLogVisible: Boolean;
     210  MemoLogHeight: Integer = 200;
     211  I: Integer;
     212  ItemRect: TRect;
     213  MaxH: Integer;
     214begin
     215    H := PanelOperationsTitle.Height;
     216    PanelOperationsVisible := JobProgressView.Jobs.Count > 0;
     217    if PanelOperationsVisible <> PanelOperations.Visible then
     218      PanelOperations.Visible := PanelOperationsVisible;
     219    if ListViewJobs.Items.Count > 0 then begin
     220      Maxh := 0;
     221      for I := 0 to ListViewJobs.Items.Count - 1 do
     222      begin
     223        ItemRect := ListViewJobs.Items[i].DisplayRect(drBounds);
     224        Maxh := Max(Maxh, ItemRect.Top + (ItemRect.Bottom - ItemRect.Top));
     225      end;
     226      PanelOperationsHeight := Scale96ToScreen(12) + Maxh;
     227    end else PanelOperationsHeight := Scale96ToScreen(8);
     228    if PanelOperationsHeight <> PanelOperations.Height then
     229      PanelOperations.Height := PanelOperationsHeight;
     230    if PanelOperationsVisible then
     231      H := H + PanelOperations.Height;
     232
     233    PanelProgressVisible := (JobProgressView.Jobs.Count > 0) and not JobProgressView.Finished;
     234    if PanelProgressVisible <> PanelProgress.Visible then
     235      PanelProgress.Visible := PanelProgressVisible;
     236    if PanelProgressVisible then
     237      H := H + PanelProgress.Height;
     238    PanelProgressTotalVisible := (JobProgressView.Jobs.Count > 1) and not JobProgressView.Finished;
     239    if PanelProgressTotalVisible <> PanelProgressTotal.Visible then
     240      PanelProgressTotal.Visible := PanelProgressTotalVisible;
     241    if PanelProgressTotalVisible then
     242      H := H + PanelProgressTotal.Height;
     243    Constraints.MinHeight := H;
     244    PanelLogVisible := MemoLog.Lines.Count > 0;
     245    if PanelLogVisible <> PanelLog.Visible then
     246      PanelLog.Visible := PanelLogVisible;
     247    if PanelLogVisible then
     248      H := H + Scale96ToScreen(MemoLogHeight);
     249    if PanelText.Visible then
     250      H := H + PanelText.Height;
     251    if Height <> H then begin
     252      Height := H;
     253      Top := (Screen.Height - H) div 2;
     254    end;
     255end;
     256
     257procedure TFormJobProgressView.TimerUpdateTimer(Sender: TObject);
     258var
     259  ProgressBarPartVisible: Boolean;
     260  ProgressBarTotalVisible: Boolean;
     261begin
     262  JobProgressView.UpdateProgress;
     263  if Visible and (not ProgressBarPart.Visible) and
     264  Assigned(JobProgressView.CurrentJob) and
     265  (JobProgressView.CurrentJob.Progress.Value > 0) then begin
     266    ProgressBarPartVisible := True;
     267    if ProgressBarPartVisible <> ProgressBarPart.Visible then
     268      ProgressBarPart.Visible := ProgressBarPartVisible;
     269    ProgressBarTotalVisible := True;
     270    if ProgressBarTotalVisible <> ProgressBarTotal.Visible then
     271      ProgressBarTotal.Visible := ProgressBarTotalVisible;
     272  end;
     273  if not Visible then begin
     274    TimerUpdate.Interval := UpdateInterval;
     275    if not JobProgressView.OwnerDraw then Show;
     276  end;
     277  if Assigned(JobProgressView.CurrentJob) then begin
     278    LabelText.Caption := JobProgressView.CurrentJob.Progress.Text;
     279    if LabelText.Caption <> '' then begin
     280      PanelText.Visible := True;
     281      UpdateHeight;
     282    end;
     283  end;
     284end;
     285
     286procedure TFormJobProgressView.ListViewJobsData(Sender: TObject; Item: TListItem);
     287begin
     288  if (Item.Index >= 0) and (Item.Index < JobProgressView.Jobs.Count) then
     289  with JobProgressView.Jobs[Item.Index] do begin
     290    Item.Caption := Title;
     291    if Item.Index = JobProgressView.CurrentJobIndex then Item.ImageIndex := 1
     292      else if Finished then Item.ImageIndex := 0
     293      else Item.ImageIndex := 2;
     294    Item.Data := JobProgressView.Jobs[Item.Index];
     295  end;
     296end;
     297
     298procedure TFormJobProgressView.FormClose(Sender: TObject;
     299  var CloseAction: TCloseAction);
     300begin
     301end;
     302
     303procedure TFormJobProgressView.FormCreate(Sender: TObject);
     304begin
     305  Caption := SPleaseWait;
     306  try
     307    //Animate1.FileName := ExtractFileDir(UTF8Encode(Application.ExeName)) +
     308    //  DirectorySeparator + 'horse.avi';
     309    //Animate1.Active := True;
     310  except
     311
     312  end;
     313end;
     314
     315procedure TFormJobProgressView.ReloadJobList;
     316begin
     317  // Workaround for not showing first line
     318  //Form.ListViewJobs.Items.Count := Jobs.Count + 1;
     319  //Form.ListViewJobs.Refresh;
     320
     321  if ListViewJobs.Items.Count <> JobProgressView.Jobs.Count then
     322    ListViewJobs.Items.Count := JobProgressView.Jobs.Count;
     323  ListViewJobs.Refresh;
     324  Application.ProcessMessages;
     325  UpdateHeight;
     326end;
     327
     328procedure TFormJobProgressView.FormShow(Sender: TObject);
     329begin
     330  ReloadJobList;
     331end;
     332
     333procedure TFormJobProgressView.FormHide(Sender: TObject);
     334begin
     335  JobProgressView.Jobs.Clear;
     336  ReloadJobList;
     337end;
     338
     339procedure TFormJobProgressView.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
     340begin
     341  CanClose := JobProgressView.Finished;
     342  JobProgressView.Terminate := True;
     343  Caption := SPleaseWait + STerminate;
     344end;
     345
     346
     347{ TJobProgressView }
     348
     349function TJobProgressView.AddJob(Title: string; Method: TJobProgressViewMethod;
     350  NoThreaded: Boolean = False; WaitFor: Boolean = False): TJob;
     351begin
     352  Result := TJob.Create;
     353  Result.ProgressView := Self;
     354  Result.Title := Title;
     355  Result.Method := Method;
     356  Result.NoThreaded := NoThreaded;
     357  Result.WaitFor := WaitFor;
     358  Result.Progress.Max := 100;
     359  Result.Progress.Reset;
     360  Result.Progress.OnChange := JobProgressChange;
     361  Jobs.Add(Result);
    207362  //ReloadJobList;
    208363end;
    209364
    210 procedure TJobProgressView.Start(AAutoClose: Boolean = True);
    211 begin
    212   AutoClose := AAutoClose;
    213   StartJobs;
    214 end;
    215 
    216 procedure TJobProgressView.StartJobs;
     365procedure TJobProgressView.Start;
    217366var
    218367  I: Integer;
     
    229378    Form.MemoLog.Clear;
    230379
     380    Form.PanelText.Visible := False;
    231381    Form.LabelEstimatedTimePart.Visible := False;
    232382    Form.LabelEstimatedTimeTotal.Visible := False;
     
    249399    I := 0;
    250400    while I < Jobs.Count do
    251     with TJob(Jobs[I]) do begin
     401    with Jobs[I] do begin
    252402      CurrentJobIndex := I;
    253       CurrentJob := TJob(Jobs[I]);
     403      CurrentJob := Jobs[I];
    254404      JobProgressChange(Self);
    255405      StartTime := Now;
     
    258408      Form.ProgressBarPart.Visible := False;
    259409      //Show;
    260       ReloadJobList;
     410      Form.ReloadJobList;
    261411      Application.ProcessMessages;
    262412      if NoThreaded then begin
     
    264414        Method(CurrentJob);
    265415      end else begin
     416        Thread := TJobThread.Create(True);
    266417        try
    267           Thread := TJobThread.Create(True);
    268418          with Thread do begin
    269419            FreeOnTerminate := False;
     
    296446    //if Visible then Hide;
    297447    Form.MemoLog.Lines.Assign(Log);
    298     if (Form.MemoLog.Lines.Count = 0) and AutoClose then begin
     448    if (Form.MemoLog.Lines.Count = 0) and FAutoClose then begin
    299449      Form.Hide;
    300450    end;
    301     Clear;
     451    if not Form.Visible then Clear;
    302452    Form.Caption := SFinished;
    303453    //LabelEstimatedTimePart.Visible := False;
    304454    Finished := True;
    305455    CurrentJobIndex := -1;
    306     ReloadJobList;
    307   end;
    308 end;
    309 
    310 procedure TJobProgressView.UpdateHeight;
    311 var
    312   H: Integer;
    313   PanelOperationsVisible: Boolean;
    314   PanelOperationsHeight: Integer;
    315   PanelProgressVisible: Boolean;
    316   PanelProgressTotalVisible: Boolean;
    317   PanelLogVisible: Boolean;
    318 begin
    319   with Form do begin
    320   H := PanelOperationsTitle.Height;
    321   PanelOperationsVisible := Jobs.Count > 0;
    322   if PanelOperationsVisible <> PanelOperations.Visible then
    323     PanelOperations.Visible := PanelOperationsVisible;
    324   PanelOperationsHeight := 8 + 18 * Jobs.Count;
    325   if PanelOperationsHeight <> PanelOperations.Height then
    326     PanelOperations.Height := PanelOperationsHeight;
    327   if PanelOperationsVisible then
    328     H := H + PanelOperations.Height;
    329 
    330   PanelProgressVisible := (Jobs.Count > 0) and not Finished;
    331   if PanelProgressVisible <> PanelProgress.Visible then
    332     PanelProgress.Visible := PanelProgressVisible;
    333   if PanelProgressVisible then
    334     H := H + PanelProgress.Height;
    335   PanelProgressTotalVisible := (Jobs.Count > 1) and not Finished;
    336   if PanelProgressTotalVisible <> PanelProgressTotal.Visible then
    337     PanelProgressTotal.Visible := PanelProgressTotalVisible;
    338   if PanelProgressTotalVisible then
    339     H := H + PanelProgressTotal.Height;
    340   Constraints.MinHeight := H;
    341   PanelLogVisible := MemoLog.Lines.Count > 0;
    342   if PanelLogVisible <> PanelLog.Visible then
    343     PanelLog.Visible := PanelLogVisible;
    344   if PanelLogVisible then
    345     H := H + MemoLogHeight;
    346   if Height <> H then Height := H;
     456    Form.ReloadJobList;
    347457  end;
    348458end;
     
    352462  if Assigned(FOnOwnerDraw) then
    353463    FOnOwnerDraw(Self);
    354 end;
    355 
    356 procedure TFormJobProgressView.TimerUpdateTimer(Sender: TObject);
    357 var
    358   ProgressBarPartVisible: Boolean;
    359   ProgressBarTotalVisible: Boolean;
    360 begin
    361   JobProgressView.UpdateProgress;
    362   if Visible and (not ProgressBarPart.Visible) and
    363   Assigned(JobProgressView.CurrentJob) and
    364   (JobProgressView.CurrentJob.Progress.Value > 0) then begin
    365     ProgressBarPartVisible := True;
    366     if ProgressBarPartVisible <> ProgressBarPart.Visible then
    367       ProgressBarPart.Visible := ProgressBarPartVisible;
    368     ProgressBarTotalVisible := True;
    369     if ProgressBarTotalVisible <> ProgressBarTotal.Visible then
    370       ProgressBarTotal.Visible := ProgressBarTotalVisible;
    371   end;
    372   if not Visible then begin
    373     TimerUpdate.Interval := UpdateInterval;
    374     if not JobProgressView.OwnerDraw then Show;
    375   end;
    376 end;
    377 
    378 procedure TFormJobProgressView.FormDestroy(Sender:TObject);
    379 begin
    380 end;
    381 
    382 procedure TFormJobProgressView.ListViewJobsData(Sender: TObject; Item: TListItem);
    383 begin
    384   if (Item.Index >= 0) and (Item.Index < JobProgressView.Jobs.Count) then
    385   with TJob(JobProgressView.Jobs[Item.Index]) do begin
    386     Item.Caption := Title;
    387     if Item.Index = JobProgressView.CurrentJobIndex then Item.ImageIndex := 1
    388       else if Finished then Item.ImageIndex := 0
    389       else Item.ImageIndex := 2;
    390     Item.Data := JobProgressView.Jobs[Item.Index];
    391   end;
    392 end;
    393 
    394 procedure TFormJobProgressView.FormClose(Sender: TObject;
    395   var CloseAction: TCloseAction);
    396 begin
    397   ListViewJobs.Clear;
    398 end;
    399 
    400 procedure TFormJobProgressView.FormCreate(Sender: TObject);
    401 begin
    402   Caption := SPleaseWait;
    403   try
    404     //Animate1.FileName := ExtractFileDir(UTF8Encode(Application.ExeName)) +
    405     //  DirectorySeparator + 'horse.avi';
    406     //Animate1.Active := True;
    407   except
    408 
    409   end;
    410464end;
    411465
     
    428482end;
    429483
    430 procedure TFormJobProgressView.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    431 begin
    432   CanClose := JobProgressView.Finished;
    433   JobProgressView.Terminate := True;
    434   Caption := SPleaseWait + STerminate;
    435 end;
    436 
    437484procedure TJobProgressView.SetTerminate(const AValue: Boolean);
    438485var
     
    441488  if AValue = FTerminate then Exit;
    442489  for I := 0 to Jobs.Count - 1 do
    443     TJob(Jobs[I]).Terminate := AValue;
     490    Jobs[I].Terminate := AValue;
    444491  FTerminate := AValue;
    445492end;
     
    490537end;
    491538
    492 procedure TJobProgressView.ReloadJobList;
    493 begin
    494   UpdateHeight;
    495   // Workaround for not showing first line
    496   Form.ListViewJobs.Items.Count := Jobs.Count + 1;
    497   Form.ListViewJobs.Refresh;
    498 
    499   if Form.ListViewJobs.Items.Count <> Jobs.Count then
    500     Form.ListViewJobs.Items.Count := Jobs.Count;
    501   Form.ListViewJobs.Refresh;
    502   //Application.ProcessMessages;
    503 end;
    504 
    505539constructor TJobProgressView.Create(TheOwner: TComponent);
    506540begin
    507541  inherited;
    508542  if not (csDesigning in ComponentState) then begin
    509     Form := TFormJobProgressView.Create(Self);
    510     Form.JobProgressView := Self;
    511   end;
    512   Jobs := TObjectList.Create;
     543    FForm := TFormJobProgressView.Create(Self);
     544    FForm.JobProgressView := Self;
     545  end;
     546  Jobs := TJobs.Create;
    513547  Log := TStringList.Create;
    514548  //PanelOperationsTitle.Height := 80;
    515   ShowDelay := 0; //1000; // ms
     549  AutoClose := True;
     550  ShowDelay := 0;
    516551end;
    517552
     
    519554begin
    520555  Jobs.Clear;
     556  Log.Clear;
    521557  //ReloadJobList;
    522558end;
     
    528564  inherited;
    529565end;
     566
     567{ TProgress }
    530568
    531569procedure TProgress.SetMax(const AValue: Integer);
     
    536574    if FMax < 1 then FMax := 1;
    537575    if FValue >= FMax then FValue := FMax;
     576  finally
     577    FLock.Release;
     578  end;
     579end;
     580
     581procedure TProgress.SetText(AValue: string);
     582begin
     583  try
     584    FLock.Acquire;
     585    if FText = AValue then Exit;
     586    FText := AValue;
    538587  finally
    539588    FLock.Release;
     
    563612end;
    564613
    565 { TProgress }
    566 
    567614procedure TProgress.Increment;
    568615begin
    569   try
    570     FLock.Acquire;
     616  FLock.Acquire;
     617  try
    571618    Value := Value + 1;
    572619  finally
     
    577624procedure TProgress.Reset;
    578625begin
    579   try
    580     FLock.Acquire;
     626  FLock.Acquire;
     627  try
    581628    FValue := 0;
    582629  finally
     
    594641begin
    595642  FLock.Free;
    596   inherited Destroy;
     643  inherited;
    597644end;
    598645
     
    625672destructor TJob.Destroy;
    626673begin
    627   Progress.Free;
     674  FreeAndNil(Progress);
    628675  inherited;
    629676end;
Note: See TracChangeset for help on using the changeset viewer.