unit UViewer;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ImgList, ComCtrls, ToolWin, MRViewer, StdCtrls, db, DBTables,
  ActnList, ExtCtrls, Buttons, IniFiles;

type
  TFormView = class(TForm)
    ToolBar1: TToolBar;
    ImageList: TImageList;
    OpenDialog: TOpenDialog;
    ProgressBar: TProgressBar;
    MRViewer: TMRViewer;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    ToolButton7: TToolButton;
    ActionList: TActionList;
    ActionPreview: TAction;
    ActionPrint: TAction;
    ActionPrintToFile: TAction;
    ActionClose: TAction;
    ActionAbortPrint: TAction;
    Panel1: TPanel;
    Panel2: TPanel;
    Panel3: TPanel;
    LBGroups: TListBox;
    LBReports: TListBox;
    Bevel1: TBevel;
    Label1: TLabel;
    Label2: TLabel;
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    SpeedButton3: TSpeedButton;
    SpeedButton4: TSpeedButton;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton8: TToolButton;
    ActionSave: TAction;
    ActionSetup: TAction;
    Panel4: TPanel;
    CBShowSQL: TCheckBox;
    SaveDialog: TSaveDialog;
    Panel5: TPanel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure ActionCloseExecute(Sender: TObject);
    procedure ActionPreviewExecute(Sender: TObject);
    procedure ActionPrintExecute(Sender: TObject);
    procedure ActionPrintToFileExecute(Sender: TObject);
    procedure ActionAbortPrintExecute(Sender: TObject);
    procedure ActionSetupExecute(Sender: TObject);
    procedure ActionSaveExecute(Sender: TObject);
    procedure SpeedButton1Click(Sender: TObject);
    procedure LBGroupsDblClick(Sender: TObject);
    procedure LBGroupsClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure SpeedButton2Click(Sender: TObject);
    procedure SpeedButton3Click(Sender: TObject);
    procedure SpeedButton4Click(Sender: TObject);
    procedure MRViewerLoadMainSQL(Name: String; var SQL: String;
      var Accept: Boolean);
    procedure LBGroupsDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure LBReportsDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure LBGroupsDragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure LBReportsDragDrop(Sender, Source: TObject; X, Y: Integer);
  private
    { Private declarations }
    DefinitionsDir: string;
    ReportPath: string;

    INI: TMemIniFile;
    Data: TStringList;

    procedure ShowProgress(Position: integer);
    procedure SetActionState(FEnable: Boolean);
    function  GetReportFileName: string;
  public
    { Public declarations }
  end;

var
  FormView: TFormView;

implementation

uses Registry, UPath, UGroupName, USQLChange, Printers;

{$R *.DFM}

//**************************************************************************
// close program
procedure TFormView.ActionCloseExecute(Sender: TObject);
begin
//    ActionSaveExecute(Sender);
    Close;
end;

//**************************************************************************
procedure TFormView.SetActionState(FEnable: Boolean);
begin
    ActionPreview.Enabled     := FEnable;
    ActionPrint.Enabled       := FEnable;
    ActionPrintToFile.Enabled := FEnable;
end;

//**************************************************************************
function TFormView.GetReportFileName: string;
var
  S: TStringList;
begin
    Result := '';
    if (LBGroups.ItemIndex >= 0) and (LBReports.ItemIndex >= 0) then
    begin
       S := Data.Objects[LBGroups.ItemIndex] as TStringList;
       Result := S.Values[S.Names[LBReports.ItemIndex]];
    end;

end;

//**************************************************************************
// Preview report
procedure TFormView.ActionPreviewExecute(Sender: TObject);
begin
    try
       SetActionState(False);
       MRViewer.LoadReport(GetReportFileName);

       MRViewer.Preview;
    finally
       MRViewer.UnLoadReport;
       ProgressBar.Position := 0;
       SetActionState(True);
    end;
end;

type
  TPrinterDevice = class
    Driver, Device, Port: String;
  end;

//**************************************************************************
// Print to printer
procedure TFormView.ActionPrintExecute(Sender: TObject);
var
   PrinterName: string;
begin
    try
       SetActionState(False);
       MRViewer.LoadReport(GetReportFileName);

       with TPrintDialog.Create(Self) do
       try
          FromPage := 1;
          MinPage  := 1;
          ToPage   := 999;
          MaxPage  := 999;
          Options  := [poPageNums];
          Copies   := 1;

          if Execute then
          begin
             with TPrinterDevice(Printer.Printers.Objects[Printer.PrinterIndex]) do
                PrinterName := Device;

             MRViewer.Print(PrinterName, FromPage, ToPage, Copies);
          end
       finally
           Free;
       end;
    finally
       MRViewer.UnLoadReport;
       ProgressBar.Position := 0;
       SetActionState(True);
    end;
end;

//**************************************************************************
// Print to file
procedure TFormView.ActionPrintToFileExecute(Sender: TObject);
begin
    if LBReports.ItemIndex >= 0 then
       if SaveDialog.Execute then
          try
             SetActionState(False);
             MRViewer.LoadReport(GetReportFileName);

             MRViewer.PrintToFile(SaveDialog.FileName);
          finally
             MRViewer.UnLoadReport;
             ProgressBar.Position := 0;
             SetActionState(True);
          end;
end;

//******************************************************************************
// Show prograss bar
procedure TFormView.ShowProgress(Position: integer);
begin
    ProgressBar.Position := Position;
end;

//******************************************************************************
// Abort printing report
procedure TFormView.ActionAbortPrintExecute(Sender: TObject);
begin
    if MRViewer.PrintType <> ptNone then
       if MessageDlg('Abort printing report ?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
          MRViewer.pAbort := True;
end;

//******************************************************************************
procedure TFormView.FormCreate(Sender: TObject);
var
   i, j: integer;
   S, SV: TStringList;
begin
    // read paths from registry
    with TRegistry.create do
    begin
        if OpenKey('\Software\Marshal Report', False) then // podarilo sa otvorit rodicovsky Key
        try
           DefinitionsDir := ReadString('DefPath');
        finally
           CloseKey;
        end;
    end;

    if DefinitionsDir = '' then
       DefinitionsDir := ExtractFilePath(ParamStr(0));

    MRViewer.DefinitionDir := DefinitionsDir;
    MRViewer.OnProgress := ShowProgress;

    // read data
    INI := TMemIniFile.Create(ExtractFilePath(ParamStr(0)) + 'MRE.dat');

    try
        S  := TStringList.Create;
        SV := TStringList.Create;

        Data := TStringList.Create;
        INI.ReadSections(S);

        for i:=0 to S.Count-1 do
        begin
            Data.AddObject(S.Strings[i], TStringList.Create);
            INI.ReadSectionValues(S.Strings[i], SV);
            for j:=1 to SV.Count-1 do
               TStringList(Data.Objects[i]).Add(SV.Strings[j]);
        end;
    finally
        S.Free;
        SV.Free;
    end;

    // modify LBGroups
    for i:=0 to Data.Count-1 do
       LBGroups.Items.Add(Data.Strings[i]);
    if LBGroups.Items.Count > 0 then LBGroups.ItemIndex := 0;
    LBGroupsClick(Sender);
end;

//******************************************************************************
procedure TFormView.FormDestroy(Sender: TObject);
var
  i: integer;
begin
    ActionSaveExecute(Sender);
    
    for i:=0 to Data.Count-1 do
       (Data.Objects[i] as TStringList).Free;

    Data.Free;
    INI.Free;
end;

//******************************************************************************
// setup definitions dir
procedure TFormView.ActionSetupExecute(Sender: TObject);
begin
    with TFormSelectDir.Create(self) do
    try
        DirectoryListBox.Directory := DefinitionsDir;
        if ShowModal = mrOK then
        begin
            DefinitionsDir := DirectoryListBox.Directory;
            if DefinitionsDir[Length(DefinitionsDir)] <> '\' then
               DefinitionsDir := DefinitionsDir + '\';

            with TRegistry.create do
            begin
                if OpenKey('\Software\Marshal Report', True) then // podarilo sa otvorit rodicovsky Key
                try
                   WriteString('DefPath', DefinitionsDir);
                finally
                   CloseKey;
                end;
            end;
        end;
    finally
        Free;
    end;
end;

//******************************************************************************
// Save data to ini file
procedure TFormView.ActionSaveExecute(Sender: TObject);
var
   i, j: integer;
   S: TStringList;
begin
    // prepare dat file
    INI.Clear;
    for i:=0 to Data.Count-1 do
    begin
       INI.WriteString(Data.Strings[i], '.', '.');
       S := Data.Objects[i] as TStringList;
       for j:=0 to S.Count-1 do
          INI.WriteString(Data.Strings[i], S.Names[j], S.Values[S.Names[j]]);
    end;

    INI.UpdateFile;
end;

//******************************************************************************
// Add Group
procedure TFormView.SpeedButton1Click(Sender: TObject);
begin
    with TFormGroupName.Create(self) do
    try
        EditGN.Text := 'New report group';
        if ShowModal = mrOK then
        begin
           LBGroups.ItemIndex := LBGroups.Items.Add(EditGN.Text);
           Data.AddObject(EditGN.Text, TStringList.Create);
           LBGroupsClick(Sender);
        end;
    finally
        Free;
    end;
end;

//******************************************************************************
// Edit group name
procedure TFormView.LBGroupsDblClick(Sender: TObject);
begin
    if LBGroups.ItemIndex > -1 then
        with TFormGroupName.Create(self) do
        try
            EditGN.Text := LBGroups.Items[LBGroups.ItemIndex];
            if ShowModal = mrOK then
            begin
               LBGroups.Items[LBGroups.ItemIndex] := EditGN.Text;
               Data.Strings[LBGroups.ItemIndex] := EditGN.Text;
            end;
        finally
            Free;
        end;
end;

//******************************************************************************
// Change group - modify reports list box
procedure TFormView.LBGroupsClick(Sender: TObject);
var
  S: TStringList;
  i: integer;
begin
    LBReports.Clear;
    if LBGroups.ItemIndex >= 0 then
    begin
        S := Data.Objects[LBGroups.ItemIndex] as TStringList;

        for i:=0 to S.Count-1 do
           LBReports.Items.Add(S.Names[i]);
        if LBReports.Items.Count > 0 then LBReports.ItemIndex := 0;
    end;
end;


//******************************************************************************
// Remove group and all its items
procedure TFormView.SpeedButton2Click(Sender: TObject);
var
   index: integer;
begin
    if LBGroups.ItemIndex >= 0 then
    begin
        index := LBGroups.ItemIndex;
        (Data.Objects[index] as TStringList).Free;
        Data.Delete(index);
        LBGroups.Items.Delete(index);

        if LBGroups.Items.Count = 0 then
           LBGroups.ItemIndex := -1
        else if index >= LBGroups.Items.Count then
           LBGroups.ItemIndex := LBGroups.Items.Count-1
        else
           LBGroups.ItemIndex := index;

        LBGroupsClick(Sender);
    end;
end;

//******************************************************************************
// Add report
procedure TFormView.SpeedButton3Click(Sender: TObject);
var
  S, SL: TStringList;
  RptCaption: string;
begin
    if LBGroups.ItemIndex >= 0 then
    begin
        OpenDialog.InitialDir := ReportPath;
        if OpenDialog.Execute then
        try
           S := TStringList.Create;
           SL := TStringList.Create;

           ReportPath := ExtractFilePath(OpenDialog.FileName);

           S.LoadFromFile(OpenDialog.FileName);
           SL.CommaText := S.Strings[1];
           RptCaption   := SL.Values['ReportName'];

           LBReports.ItemIndex := LBReports.Items.Add(RptCaption);
           (Data.Objects[LBGroups.ItemIndex] as TStringList).Add(RptCaption + '=' + OpenDialog.FileName);
        finally
           SL.Free;
           S.Free;
        end;
    end;
end;

//******************************************************************************
// Remove report
procedure TFormView.SpeedButton4Click(Sender: TObject);
var
   index: integer;
   S: TStringList;
begin
    if (LBReports.ItemIndex >= 0) and (LBGroups.ItemIndex >= 0) then
    begin
        index := LBReports.ItemIndex;
        (Data.Objects[LBGroups.ItemIndex] as TStringList).Delete(index);
        LBReports.Items.Delete(index);

        if LBReports.Items.Count = 0 then
           LBReports.ItemIndex := -1
        else if index >= LBReports.Items.Count then
           LBReports.ItemIndex := LBReports.Items.Count-1
        else
           LBReports.ItemIndex := index;
    end;
end;

//******************************************************************************
// Change Main SQL string
procedure TFormView.MRViewerLoadMainSQL(Name: String; var SQL: String; var Accept: Boolean);
begin
    if CBShowSQL.Checked then
        with TFormSQLChange.Create(self) do
        try
            SQLText.Text := SQL;
            if ShowModal = mrOK then
            begin
               SQL := SQLText.Text;
               Accept := True;
            end;
        finally
            Free;
        end;
end;

//******************************************************************************
// Enable change group order
procedure TFormView.LBGroupsDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
    Accept := False;

    // change groups order
    if Source = LBGroups then
       Accept := True
    // move report to other group
    else if Source= LBReports then
       Accept := True
end;

//******************************************************************************
// Enable change reports order
procedure TFormView.LBReportsDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
    Accept := False;
    if Source = LBReports then
      Accept := True;
end;

//******************************************************************************
// Change groups order
procedure TFormView.LBGroupsDragDrop(Sender, Source: TObject; X,  Y: Integer);
var
  NewIndex, index: integer;
  P: TPoint;
  S: TStringList;
begin
    // change groups order
    if Source = LBGroups then
    begin
        P.X := X; P.Y := Y;
        NewIndex := LBGroups.ItemAtPos(P, True);
        if NewIndex > -1 then
        begin
            Data.Move(LBGroups.ItemIndex, NewIndex);
            LBGroups.Items.Move(LBGroups.ItemIndex, NewIndex);
            LBGroups.ItemIndex := NewIndex;
        end;
    end
    // Move report from one group to other group
    else if Source = LBReports then
    begin
        P.X := X; P.Y := Y;
        NewIndex := LBGroups.ItemAtPos(P, True);
        if NewIndex <> LBGroups.ItemIndex then
            if NewIndex > -1 then
            begin
                index := LBReports.ItemIndex;

                // add report in selected group
                S := Data.Objects[NewIndex] as TStringList;
                S.Add((Data.Objects[LBGroups.ItemIndex] as TStringList).Strings[LBReports.ItemIndex]);
                (Data.Objects[LBGroups.ItemIndex] as TStringList).Delete(LBReports.ItemIndex);

                LBReports.Items.Delete(LBReports.ItemIndex);

                if LBReports.Items.Count = 0 then
                   LBReports.ItemIndex := -1
                else if index >= LBReports.Items.Count then
                   LBReports.ItemIndex := LBReports.Items.Count-1
                else
                   LBReports.ItemIndex := index;
            end;
    end;
end;

//******************************************************************************
// Change reports order
procedure TFormView.LBReportsDragDrop(Sender, Source: TObject; X, Y: Integer);
var
  NewIndex: integer;
  P: TPoint;
  S: TStringList;
begin
    if Source = LBReports then
    begin
        P.X := X; P.Y := Y;
        NewIndex := LBReports.ItemAtPos(P, True);
        if NewIndex > -1 then
        begin
            S := Data.Objects[LBGroups.ItemIndex] as TStringList;
            S.Move(LBReports.ItemIndex, NewIndex);
            LBReports.Items.Move(LBReports.ItemIndex, NewIndex);
            LBReports.ItemIndex := NewIndex;
        end;
    end;
end;

end.
