(*
   fenixsql
   author Alessandro Batisti
   abatisti@tiscali.it
   http://fblib.altervista.org

   file:fsdbconnections.pas

  * 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.

*)

unit fsdbconnections;

interface

uses
  Types,
  Classes, SysUtils,
  Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls, Buttons,
  ZConnection,
  Spin, IniFiles;

type
  TfrmDbConnections = class(TForm)
    btnTest: TBitBtn;
    btnConnect: TBitBtn;
    btnCancel: TBitBtn;
    btnSave: TButton;
    btnDelete: TButton;
    cmbAlias: TComboBox;
    cmbCharacterSet: TComboBox;
    edDatabase: TEdit;

    edHost: TEdit;
    edUser: TEdit;
    edPassword: TEdit;
    edRole: TEdit;
    GroupBox1: TGroupBox;
    GroupBox2: TGroupBox;
    GroupBox3: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    lblDialect: TLabel;
    Label9: TLabel;
    odDBFile: TOpenDialog;
    sePort: TSpinEdit;
    seDialect: TSpinEdit;
    cmbProtocol: TComboBox;
    dbBtn: TButton;
    procedure btnConnectClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure btnTestClick(Sender: TObject);
    procedure edPasswordChange(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure dbBtnClick(Sender: TObject);
    procedure cmbAliasChange(Sender: TObject);
  private
    { private declarations }
    FAlias: string;
    procedure LoadAliasName(const AAlias: string);
    procedure SaveAliasName(const AAlias: string);
    function DeleteAlias(const AAlias: string): boolean; //True if alias deleted
    function ValidateInputTest: boolean;
    function ValidateInputConn: boolean;
  public
    { public declarations }
    property Alias: string read FAlias write FAlias;
  end;

function DbConnection(dbConnecton: TZConnection; var Alias: string): boolean;

implementation

uses
  fsconfig, fsconst,
  ZClasses, ZDbcIntfs, ZDbcDBLib, ZCompatibility;

{$R *.dfm}

//------------------------------------------------------------------------------

function DbConnection(dbConnecton: TZConnection; var Alias: string): boolean;
var
  form: TfrmDbConnections;
begin
  Result := False;
  form := TfrmDbConnections.Create(nil);
  try
    form.Alias := Alias;
    if form.ShowModal = mrOk then
    begin
      Alias := form.cmbAlias.Text;
      with dbConnecton do
      begin
        HostName := form.edHost.Text;
        Database := form.edDatabase.Text;
        User := form.edUser.Text;
        Password := form.edPassword.Text;
        Protocol := form.cmbProtocol.Text;
        Port := form.sePort.Value;
        Properties.Add('Dialect='+intTostr(form.seDialect.Value));
        Properties.Add('CharacterSet='+form.cmbCharacterSet.Text);
        Properties.Add('Role='+form.edRole.Text);
        try
          Connected := True;
        except
          on E: Exception do
          begin
            ShowMessage(E.Message);
          end;
        end;
      end;
      Result := True;
    end;
  finally
    form.Free;
  end;
end;

//------------------------------------------------------------------------------

procedure TfrmDbConnections.FormShow(Sender: TObject);
var
 item: Integer;
  I, J: Integer;
  Drivers: IZCollection;
  Protocols: TStringDynArray;
begin
  cmbProtocol.Clear;
  Drivers := DriverManager.GetDrivers;
  for I := 0 to Drivers.Count - 1 do
  begin
    Protocols := (Drivers.Items[I] as IZDriver).GetSupportedProtocols;
    for J := 0 to High(Protocols) do
      cmbProtocol.Items.Add(Protocols[J]);
  end;
  cmbProtocol.Sorted := True;

   fsconfig.GetAliasNames(cmbAlias.Items);
   if cmbAlias.Items.Count > 0 then
   begin
     item := cmbAlias.Items.IndexOf(Alias);
     if item > -1 then
     begin
      cmbAlias.ItemIndex := item;
      LoadAliasName(cmbAlias.Text);
     end;
   end;
end;

//------------------------------------------------------------------------------

procedure TfrmDbConnections.btnTestClick(Sender: TObject);
var
  dbTest: TZConnection;
begin
  dbTest := TZConnection.Create(self);
  try
    if not ValidateInputTest then Exit;
    with dbTest do
    begin
      Protocol := cmbProtocol.Text;
      User := edUser.Text;
      Password := edPassword.Text;
      HostName := edHost.Text;
      Port := sePort.Value;
      Database := edDatabase.Text;

      Properties.Add('Dialect='+intTostr(seDialect.Value));
      Properties.Add('CharacterSet='+cmbCharacterSet.Text);
      Properties.Add('Role='+edRole.Text);

      try
        dbtest.Connected := True;
        ShowMessage('Connection Ok');
        dbTest.Connected := False;
      except
        on E: Exception do
        begin
          ShowMessage(E.Message);
        end;
      end;
    end;
  finally
    dbTest.Free;
  end;
end;

//------------------------------------------------------------------------------

procedure TfrmDbConnections.cmbAliasChange(Sender: TObject);
begin
  LoadAliasName(cmbAlias.Text);

end;

//------------------------------------------------------------------------------

procedure TfrmDbConnections.dbBtnClick(Sender: TObject);
begin
  with odDBFile do
  begin
    Title := 'Select database file';
    Filter := FILE_DIALOG_FILTER;
    if Execute then
      edDatabase.Text := FileName;
  end;
end;

//------------------------------------------------------------------------------

procedure TfrmDbConnections.LoadAliasName(const AAlias: string);
var
  inifile: TIniFile;
begin
  inifile := TiniFile.Create(GetAliasIniFile);
  try
    if inifile.SectionExists(AAlias) then
    begin
      cmbProtocol.Text := inifile.ReadString(AAlias, 'Protocol', '');;
      edUser.Text := inifile.ReadString(AAlias, 'User', '');
      edRole.Text := inifile.ReadString(AAlias, 'Role', '');
      edPassword.Text := inifile.ReadString(AAlias, 'Password', '');
      edHost.Text := inifile.ReadString(AAlias, 'Host', '');
      seDialect.Value := inifile.ReadInteger(AAlias, 'Dialect', 3);
      sePort.Value := inifile.ReadInteger(AAlias, 'Port', 3050);
      edDatabase.Text := inifile.ReadString(AAlias, 'Database', '');
      cmbCharacterSet.Text := inifile.ReadString(AAlias, 'CharacterSet', 'NONE');
    end;
  finally
    inifile.Free;
  end;
end;

//------------------------------------------------------------------------------

procedure TfrmDbConnections.SaveAliasName(const AAlias: string);
var
  inifile: TIniFile;
begin
  inifile := TiniFile.Create(GetAliasIniFile);
  try
    inifile.WriteString(AAlias,'Protocol',cmbProtocol.Text);
    inifile.WriteString(AAlias,'User',edUser.Text);
    inifile.WriteString(AAlias,'Role',edRole.Text);
    inifile.WriteString(AAlias,'Password',edPassword.Text);
    inifile.WriteString(AAlias,'Host',edHost.Text);
    inifile.WriteInteger(AAlias,'Dialect',seDialect.Value);
    inifile.WriteInteger(AAlias,'Port',sePort.Value);
    inifile.WriteString(AAlias,'Database',edDatabase.Text);
    Inifile.WriteString(AAlias,'CharacterSet',cmbCharacterSet.Text);
    inifile.UpdateFile;
  finally
    inifile.Free;
  end;
end;

//------------------------------------------------------------------------------

function TfrmDbConnections.DeleteAlias(const AAlias: string): boolean;
var
  inifile: TIniFile;
begin
  Result := False;
  inifile := TiniFile.Create(GetAliasIniFile);
  try
    if inifile.SectionExists(AAlias) then
    begin
       Inifile.EraseSection(AAlias);
       inifile.UpdateFile;
       fsconfig.DeleteHistory(AAlias);
       Result := True;
    end;
  finally
    IniFile.Free;
  end;
end;

//------------------------------------------------------------------------------

procedure TfrmDbConnections.edPasswordChange(Sender: TObject);
begin
  btnConnect.Default := edPassword.Text <> '';
end;

//------------------------------------------------------------------------------

procedure TfrmDbConnections.btnConnectClick(Sender: TObject);
begin
  if ValidateInputConn then
  begin
    SaveAliasName(cmbAlias.Text);
    ModalResult := mrOk;
  end;
end;

//------------------------------------------------------------------------------

procedure TfrmDbConnections.btnDeleteClick(Sender: TObject);
begin
  if cmbAlias.Text = '' then Exit;
  if MessageDlg('Delete Alias ' + cmbAlias.Text + #13 + 'Are You sure ?',
      mtConfirmation, [mbYes, mbNo], 0) = mrYes then
  begin
    if self.DeleteAlias(cmbAlias.Text) then
    begin
      cmbAlias.Text := '';
      fsconfig.GetAliasNames(cmbAlias.Items);
    end;
  end;
end;

//------------------------------------------------------------------------------

procedure TfrmDbConnections.btnSaveClick(Sender: TObject);
begin
  if cmbAlias.Text <> ''  then
    SaveAliasName( cmbAlias.Text);
end;

//------------------------------------------------------------------------------

function TfrmDbConnections.ValidateInputTest: boolean;
begin
  Result := False;

  if edDatabase.Text = '' then
  begin
    ShowMessage('"Database" cannot be blank');
    EdDatabase.SetFocus;
    Exit;
  end;

  if edUser.Text = '' then
  begin
    ShowMessage('"User" cannot be blank');
    EdUser.SetFocus;
    Exit;
  end;

  if edPassword.Text = '' then
  begin
    ShowMessage('"Password" cannot be blank');
    EdPassword.SetFocus;
    Exit;
  end;
  Result := True;
end;

//------------------------------------------------------------------------------

function TfrmDbConnections.ValidateInputConn: boolean;
begin
  Result :=  False;
  if cmbAlias.Text = '' then
  begin
    ShowMessage('"Aliases" cannot be blank');
    cmbAlias.SetFocus;
    Exit;
  end;
  Result := ValidateInputTest;
end;


end.

