{ Intentionally simple DISQLite3 / ClientDataSet demo project.

  Visit the DISQLite3 Internet site for latest information and updates:

    http://www.yunqa.de/delphi/

  Copyright (c) 2005-2009 Ralf Junker, The Delphi Inspiration <delphi@yunqa.de>

------------------------------------------------------------------------------ }

unit DISQLite3_ClientDataSet_Grid_Form_Main;

{$I DI.inc}
{$I DISQLite3.inc}

interface

uses
  Classes, Controls, Forms, StdCtrls, ComCtrls, ExtCtrls, Grids, DBGrids,
  DB, Provider, DBClient,
  DISQLite3Database, DISQLite3DataSet;

type
  TfrmMain = class(TForm)
    DISQLite3Database: TDISQLite3Database;
    DISQLite3UniDirQuery: TDISQLite3UniDirQuery;
    DataSource: TDataSource;
    ClientDataSet: TClientDataSet;
    DataSetProvider: TDataSetProvider;
    pnlNavigation: TPanel;
    DbGrid: TDBGrid;
    btnInsert: TButton;
    btnDelete: TButton;
    StatusBar: TStatusBar;
    btnApplyUpdates: TButton;
    btnCancelUpdates: TButton;
    btnRefresh: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnInsertClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
    procedure ClientDataSet_Modified(DataSet: TDataSet);
    procedure btnCancelUpdatesClick(Sender: TObject);
    procedure btnApplyUpdatesClick(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure btnRefreshClick(Sender: TObject);
    procedure DISqlite3UniDirQueryInitFieldDef(
      const AColumn: TDISQLite3Column; const AFieldDef: TFieldDef);
  end;

const
  APP_TITLE = 'DISQLite3 Demo: ClientDataSet';

var
  frmMain: TfrmMain;

implementation

uses
  SysUtils, Dialogs
  { Compile MidasLib into the application if supported by Delphi version.
    This removes all dependencies against midas.dll and turns projects into
    fully standalone applications. }
  {$IFDEF COMPILER_6_UP}, MidasLib{$ENDIF};

{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  Caption := APP_TITLE;

  { Open the database. }
  DISQLite3Database.DatabaseName := 'Test.db3';
  try
    DISQLite3Database.Open;
  except
    { If database does not yet exist, create it now ... }
    DISQLite3Database.CreateDatabase;
    DISQLite3Database.Execute(
      'CREATE TABLE IF NOT EXISTS Products(' +
      '"ID" INTEGER PRIMARY KEY,' +
      '"Name" TEXT)');
    { ... and add some sample data. }
    DISQLite3Database.Execute('INSERT INTO Products (Name) VALUES (''Software'')');
    DISQLite3Database.Execute('INSERT INTO Products (Name) VALUES (''Hardware'')');
    DISQLite3Database.Execute('INSERT INTO Products (Name) VALUES (''Books'')');
  end;

  { Set the select of the unerlying TDISQLite3UniDirQuery ... }
  DISQLite3UniDirQuery.SelectSQL := 'SELECT Name FROM Products';
  { ... and then open the ClientDataSet. This automatically opens
    the underlying TDISQLite3UniDirQuery as well. }
  ClientDataSet.Open;
end;

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

{ TClientDataSet in D4 does not support WideStrings. This works around this
  problem by changing the ftWideString type to ftString. }

procedure TfrmMain.DISqlite3UniDirQueryInitFieldDef(
  const AColumn: TDISQLite3Column;
  const AFieldDef: TFieldDef);
begin
  {$IFNDEF COMPILER_5_UP}
  if AFieldDef.DataType = ftWideString then
    begin
      AFieldDef.DataType := ftString;
      AFieldDef.Size := 64;
    end;
  {$ENDIF !COMPILER_5_UP}
end;

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

{ All database editing operations now take place on the level of the
  ClientDataSet. The ClientDataSet caches all changes and posts them back to
  TDISQLite3UniDirQuery by calling ClientDataSet.ApplyUpdates. }

procedure TfrmMain.btnInsertClick(Sender: TObject);
begin
  ClientDataSet.Append;
end;

procedure TfrmMain.btnDeleteClick(Sender: TObject);
begin
  ClientDataSet.Delete;
end;

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

{ Callback to update the GUI controls according to the state of the
  ClientDataSet. Again, all operations are on the ClientDataSet level only! }

procedure TfrmMain.ClientDataSet_Modified(DataSet: TDataSet);
var
  ChangesPending: Boolean;
begin
  btnDelete.Enabled :=
    not ClientDataSet.bof or
    not ClientDataSet.EOF;

  ChangesPending := ClientDataSet.ChangeCount > 0;
  btnApplyUpdates.Enabled := ChangesPending;
  btnCancelUpdates.Enabled := ChangesPending;
  btnRefresh.Enabled := not ChangesPending;
  if ChangesPending then
    StatusBar.SimpleText := IntToStr(ClientDataSet.ChangeCount) + ' change(s) pending'
  else
    StatusBar.SimpleText := '';
end;

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

{ The ClientDataSet acts as an intermediate data buffer and caches all user
  changes. Not data is written to the TDISQLite3UniDirQuery until either
  ClientDataSet.ApplyUpdates or ClientDataSet.CancelUpdates is called.

  ClientDataSet.ApplyUpdates tries to flush out any pending updates to the
  TDISQLite3UniDirQuery.

  ClientDataSet.CancelUpdates just cancels any updates, nothing is written
  to TDISQLite3UniDirQuery. }

procedure TfrmMain.btnApplyUpdatesClick(Sender: TObject);
var
  i: Integer;
  s: string;
begin
  i := ClientDataSet.ApplyUpdates(-1);
  if i > 0 then
    s := IntToStr(i) + ' Error(s) during update'
  else
    s := 'Update(s) OK';
  ShowMessage (s);
  ClientDataSet_Modified(nil);
end;

procedure TfrmMain.btnCancelUpdatesClick(Sender: TObject);
begin
  ClientDataSet.CancelUpdates;
  ClientDataSet_Modified(nil);
end;

procedure TfrmMain.btnRefreshClick(Sender: TObject);
begin
  ClientDataSet.Refresh;
end;

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

{ Security-check to prevent users closing the application with updates pending. }

procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := ClientDataSet.ChangeCount = 0;
  if not CanClose then
    ShowMessage('Upddate or cancel pending updates before closing!');
end;


end.

