unit main;

{$mode Delphi}{$H+}

interface

uses
  {$IFNDEF Linux}
  Windows, ShellApi, Messages,
  {$ELSE}
  LCLType, LCLIntf, LMessages, LazHelper,
  {$ENDIF}
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
  Menus, ComCtrls, frxBarcode, frxChBox, frxCross, frxDCtrl, frxGradient,
  frxServerClient, frxChartLaz, frxExportImage, frxExportCSV, frxExportHTML,
  frxExportPDF, frxExportRTF, frxExportText, frxExportXML;

type

  { TMainForm }

  TMainForm = class(TForm)
    Clear1: TMenuItem;
    CloseBtn: TButton;
    ConnectBtn: TButton;
    Description: TMemo;
    ExportBtn: TButton;
    frxBarCodeObject1: TfrxBarCodeObject;
    frxBMPExport1: TfrxBMPExport;
    frxChartObject1: TfrxChartObject;
    frxCheckBoxObject1: TfrxCheckBoxObject;
    frxCrossObject1: TfrxCrossObject;
    frxCSVExport1: TfrxCSVExport;
    frxDialogControls1: TfrxDialogControls;
    frxGradientObject1: TfrxGradientObject;
    frxHTMLExport1: TfrxHTMLExport;
    frxJPEGExport1: TfrxJPEGExport;
    frxPDFExport1: TfrxPDFExport;
    frxReportClient1: TfrxReportClient;
    frxRTFExport1: TfrxRTFExport;
    frxServerConnection1: TfrxServerConnection;
    frxSimpleTextExport1: TfrxSimpleTextExport;
    frxTIFFExport1: TfrxTIFFExport;
    frxXMLExport1: TfrxXMLExport;
    Host: TEdit;
    Image1: TImage;
    ImageList1: TImageList;
    Label1: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Label12: TLabel;
    Label13: TLabel;
    Label14: TLabel;
    Label15: TLabel;
    Label16: TLabel;
    Label17: TLabel;
    Label18: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    Log: TMemo;
    Login: TEdit;
    Panel10: TPanel;
    Panel11: TPanel;
    Panel12: TPanel;
    Panel13: TPanel;
    Panel14: TPanel;
    Panel2: TPanel;
    Panel4: TPanel;
    Panel5: TPanel;
    Password: TEdit;
    PopupMenu1: TPopupMenu;
    Port: TEdit;
    ProxyHost: TEdit;
    ProxyPort: TEdit;
    Rep: TEdit;
    ReportsTree: TTreeView;
    ShowBtn: TButton;
    StopBtn: TButton;
    TestBtn: TButton;
    Threads: TEdit;
    procedure TestBtnClick(Sender: TObject);
    procedure CloseBtnClick(Sender: TObject);
    procedure ShowBtnClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure StopBtnClick(Sender: TObject);
    procedure ListBox1DblClick(Sender: TObject);
    procedure ListBox1KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure Label11Click(Sender: TObject);
    procedure ConnectBtnClick(Sender: TObject);
    procedure Clear1Click(Sender: TObject);
    procedure ReportsTreeChange(Sender: TObject; Node: TTreeNode);
    procedure ReportsTreeCustomDrawItem(Sender: TCustomTreeView;
      Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
    procedure ExportBtnClick(Sender: TObject);
  private
    ThreadList: TList;
    ReportsList: TStringList;
    procedure ClearThreads;
  end;

  TfrxClientTestThread = class (TThread)
  protected
    procedure Execute; override;
  private
    CountRep: Integer;
    ErrorsCount: Integer;
    Log: TMemo;
    ThreadID: Integer;
    FConnection: TfrxServerConnection;
    FRepName: String;
    procedure AppendLog;
    procedure FinishLog;
  public
    Report: TfrxReportClient;
    Done: Boolean;
    constructor Create(C: TfrxServerConnection; RepName: String;
        Id: Integer; Rep: Integer; L: TMemo);
  end;

var
  MainForm: TMainForm;

implementation

{$R *.lfm}

procedure TMainForm.TestBtnClick(Sender: TObject);
var
  i, j, k: Integer;
  Thread: TfrxClientTestThread;
  s: String;
begin
  frxServerConnection1.Host := Host.Text;
  frxServerConnection1.Port := StrToInt(Port.Text);
  frxServerConnection1.Login := Login.Text;
  frxServerConnection1.Password := Password.Text;
  if (Length(ProxyHost.Text) > 0) then
  begin
    frxServerConnection1.ProxyHost := ProxyHost.Text;
    frxServerConnection1.ProxyPort := StrToInt(ProxyPort.Text);
  end;
  ClearThreads;
  j := StrToInt(Threads.Text);
  k := StrToInt(Rep.Text);
  i := Integer(ReportsTree.Selected.Data);
  if i <> -1 then
  begin
    Log.Lines.Add('Start test');
    s := ReportsList[i + 1];
    for i := 1 to j do
    begin
      Thread := TfrxClientTestThread.Create(frxServerConnection1, s, i, k, Log);
      ThreadList.Add(Thread);
    end;
  end;
end;

procedure TMainForm.CloseBtnClick(Sender: TObject);
begin
  Close;
end;

procedure TMainForm.ShowBtnClick(Sender: TObject);
var
  t: Cardinal;
  tf: Double;
  i: Integer;
begin
  frxServerConnection1.Host := Host.Text;
  frxServerConnection1.Port := StrToInt(Port.Text);
  frxServerConnection1.Login := Login.Text;
  frxServerConnection1.Password := Password.Text;
  if (Length(ProxyHost.Text) > 0) then
  begin
    frxServerConnection1.ProxyHost := ProxyHost.Text;
    frxServerConnection1.ProxyPort := StrToInt(ProxyPort.Text);
  end;
  i := Integer(ReportsTree.Selected.Data);
  if i <> -1 then
  begin
    frxReportClient1.LoadFromFile(ReportsList[i + 1]);
    t := GetTickCount;
    if frxReportClient1.PrepareReport then
    begin
      tf := (GetTickCount - t) / 1000;
      Log.Lines.Add(frxReportClient1.ReportName +
        ' Time=' + FloatToStr(tf) + ' Size=' + IntToStr(frxReportClient1.Client.StreamSize));
      frxReportClient1.ShowPreparedReport;
    end;
    Log.Lines.AddStrings(frxReportClient1.Errors);
  end;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Label14.Caption := #194#174;
  Label15.Caption := #194#169 + Label15.Caption;
  ThreadList := TList.Create;
  ReportsList := TStringList.Create;
  {$IFDEF LCLGTK2}
  //Ñlient can be threaded, but that requires gdk_threads_init.
  //Modal forms break after gdk_threads_init.
  //So testing in threads is removed.
  Label1.Visible  := False;
  Label6.Visible  := False;
  Label18.Visible := False;
  Threads.Visible := False;
  Rep.Visible     := False;
  TestBtn.Visible := False;
  StopBtn.Visible := False;
  Panel4.Width := 78;
  {$ENDIF}
end;

procedure TMainForm.ClearThreads;
var
  i: Integer;
begin
  for i := 0 to ThreadList.Count - 1 do
    if Assigned(TfrxClientTestThread(ThreadList[i])) then
    begin
      TfrxClientTestThread(ThreadList[i]).Terminate;
      TfrxClientTestThread(ThreadList[i]).Free;
    end;
  ThreadList.Clear;
end;

procedure TMainForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  ReportsList.Free;
  ClearThreads;
  ThreadList.Free;
end;

procedure TMainForm.StopBtnClick(Sender: TObject);
begin
  ClearThreads;
end;

procedure TMainForm.ListBox1DblClick(Sender: TObject);
begin
  ShowBtnClick(Sender);
end;

procedure TMainForm.ListBox1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = 13 then
    ShowBtnClick(Sender);
end;

procedure TMainForm.Label11Click(Sender: TObject);
begin
  {$IFNDEF Linux}
  ShellExecute(GetDesktopWindow, 'open', PChar(Label11.Caption), nil, nil, SW_SHOW);
  {$ELSE}
  LCLIntf.OpenURL(Label11.Caption);
  {$ENDIF}
end;

procedure TMainForm.ConnectBtnClick(Sender: TObject);
var
  t: Cardinal;
  tf: Double;
  s, s1: String;
  AccessFlag: Boolean;
  i: Integer;
  Node: TTreeNode;
  TopNode: TTreeNode;
  OldName: String;

begin
  ReportsTree.Items.Clear;
  ReportsList.Clear;
  Log.Clear;

  frxServerConnection1.Host := Host.Text;
  frxServerConnection1.Port := StrToInt(Port.Text);
  frxServerConnection1.Login := Login.Text;
  frxServerConnection1.Password := Password.Text;
  if (Length(ProxyHost.Text) > 0) then
  begin
    frxServerConnection1.ProxyHost := ProxyHost.Text;
    frxServerConnection1.ProxyPort := StrToInt(ProxyPort.Text);
  end;
  t := GetTickCount;
  Log.Lines.Text := Log.Lines.Text +
    frxReportClient1.GetServerVariable('SERVER_NAME');
  tf := (GetTickCount - t) / 1000;
  if frxReportClient1.Errors.Count = 0 then
  begin
    Log.Lines.Text := Log.Lines.Text +
      'Version: ' + frxReportClient1.GetServerVariable('SERVER_SOFTWARE');
    Log.Lines.Text := Log.Lines.Text +
      'From: ' + frxReportClient1.GetServerVariable('SERVER_LAST_UPDATE');
    Log.Lines.Text := Log.Lines.Text +
      'Uptime: ' + frxReportClient1.GetServerVariable('SERVER_UPTIME');
    Log.Lines.Add('Ping:' + FloatToStr(tf) + 'ms.');
  end;
  Log.Lines.AddStrings(frxReportClient1.Errors);

  AccessFlag :=  frxReportClient1.Errors.Count = 0;

  if AccessFlag then
  begin
    ReportsList.Text := frxReportClient1.GetServerVariable('SERVER_REPORTS_LIST');
    if ReportsList.Count > 0 then
    begin
      ReportsTree.Items.BeginUpdate;
      TopNode := nil;
      Oldname := '';
      for i := 0 to (ReportsList.Count div 3) - 1 do
      begin
        s := ReportsList[(i * 3) + 1];
        s := StringReplace(StringReplace(s, ExtractFileName(s), '', []), '\', ' ', [rfReplaceAll]);
        if s <> OldName then
        begin
          if s = '' then
            s1 := 'Reports'
          else
            s1 := s;
          Node := ReportsTree.Items.AddChild(nil, s1);
          Node.Data := Pointer(-1);
          Node.ImageIndex := 0;
          TopNode := Node;
          OldName := s;
        end;
        Node := ReportsTree.Items.AddChild(TopNode, ReportsList[i * 3]);
        Node.Data := Pointer((i * 3));
        Node.ImageIndex := 1;
      end;
      ReportsTree.Items.EndUpdate;
      ReportsTree.TopItem := ReportsTree.Items[0];
      ReportsTree.Selected := ReportsTree.Items[0];
      ReportsTree.SetFocus;
    end else
      Log.Lines.Add('Nothing reports is available or information restricted.');
  end;
end;

procedure TMainForm.Clear1Click(Sender: TObject);
begin
  Log.Clear;
end;

procedure TMainForm.ReportsTreeChange(Sender: TObject; Node: TTreeNode);
var
  i: Integer;
begin
  i := Integer(Node.Data);
  if i <> -1 then
    Description.Text := ReportsList[i + 2]
  else
    Description.Text := Node.Text;
  ShowBtn.Enabled := i <> -1;
  ExportBtn.Enabled := ShowBtn.Enabled;
  TestBtn.Enabled := ShowBtn.Enabled;
end;

procedure TMainForm.ReportsTreeCustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  if Node.Count <> 0 then
    ReportsTree.Canvas.Font.Style := [fsBold];
end;

procedure TMainForm.ExportBtnClick(Sender: TObject);
var
  t: Cardinal;
  tf: Double;
  i: Integer;
begin
  frxServerConnection1.Host := Host.Text;
  frxServerConnection1.Port := StrToInt(Port.Text);
  frxServerConnection1.Login := Login.Text;
  frxServerConnection1.Password := Password.Text;
  if (Length(ProxyHost.Text) > 0) then
  begin
    frxServerConnection1.ProxyHost := ProxyHost.Text;
    frxServerConnection1.ProxyPort := StrToInt(ProxyPort.Text);
  end;
  i := Integer(ReportsTree.Selected.Data);
  if i <> -1 then
  begin
    frxReportClient1.LoadFromFile(ReportsList[i + 1]);
    t := GetTickCount;
    if frxReportClient1.PrepareReport then
    begin
      tf := (GetTickCount - t) / 1000;
      Log.Lines.Add(frxReportClient1.ReportName +
        ' Time=' + FloatToStr(tf) + ' Size=' + IntToStr(frxReportClient1.Client.StreamSize));
      frxReportClient1.Export(frxPDFExport1);
    end;
    Log.Lines.AddStrings(frxReportClient1.Errors);
  end;
end;

{ TfrxClientTestThread }

constructor TfrxClientTestThread.Create(C: TfrxServerConnection; RepName: String;
    Id: Integer; Rep: Integer; L: TMemo);
begin
  inherited Create(True);
  ErrorsCount := 0;
  ThreadId := Id;
  CountRep := Rep;
  FConnection := C;
  FRepName := RepName;
  Log := L;
  Done := False;
  Resume;
end;

procedure TfrxClientTestThread.Execute;
var
 i: Integer;
begin
  Done := False;
  Report := TfrxReportClient.Create(nil);
  Report.EngineOptions.EnableThreadSafe := True;
  Report.ShowProgress := False;
  Report.EngineOptions.SilentMode := True;
  Report.Connection := FConnection;
  Report.ReportName := FRepName;
  i := 0;
  while (i < CountRep) and (not Terminated) do
  begin
    Report.Clear;
    Report.PrepareReport;
    Synchronize(AppendLog);
    ErrorsCount := ErrorsCount + Report.Errors.Count;
    Inc(i);
  end;
  Synchronize(FinishLog);
  Report.Free;
  Done := True;
end;

procedure TfrxClientTestThread.AppendLog;
begin
  if Assigned(Log) and (Report.Errors.Count > 0) then
  begin
    Log.Lines.Add('Thread#' + IntToStr(ThreadID));
    Log.Lines.AddStrings(Report.Errors);
  end;
end;

procedure TfrxClientTestThread.FinishLog;
begin
  if Assigned(Log) and (not Terminated) then
    Log.Lines.Add('Thread#' + IntToStr(ThreadID) + ' finished. Errors:' + IntToStr(ErrorsCount));
end;

end.

