
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6119 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2491 lines
68 KiB
ObjectPascal
2491 lines
68 KiB
ObjectPascal
{*******************************************************}
|
|
{ }
|
|
{ Delphi Visual Component Library }
|
|
{ QBuilder dialog component }
|
|
{ }
|
|
{ Copyright (c) 1996-2003 Sergey Orlik }
|
|
{ }
|
|
{ Written by: }
|
|
{ Sergey Orlik }
|
|
{ product manager }
|
|
{ Russia, C.I.S. and Baltic States (former USSR) }
|
|
{ Borland Moscow office }
|
|
{ Internet: support@fast-report.com, }
|
|
{ sorlik@borland.com }
|
|
{ http://www.fast-report.com }
|
|
{ }
|
|
{ Converted to Lazarus/Free Pascal by Jean Patrick }
|
|
{ Data: 14/02/2013 }
|
|
{ E-mail: jpsoft-sac-pa@hotmail.com }
|
|
{ }
|
|
{ Modifications by Reinier Olislagers, 2014 }
|
|
{*******************************************************}
|
|
|
|
unit QBuilder;
|
|
|
|
{$IFDEF FPC}
|
|
{$MODE Delphi}
|
|
{$ENDIF}
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
|
Buttons, ExtCtrls, StdCtrls, ComCtrls, Menus, CheckLst, Grids,
|
|
DB, DBGrids, LMessages, LCLIntf, LCLType, LCLProc,
|
|
lclplatformdef, //=== ct9999 =========
|
|
GraphType, InterfaceBase;
|
|
|
|
type
|
|
TOQBbutton = (bSelectDBDialog, bOpenDialog, bSaveDialog,
|
|
bRunQuery, bSaveResultsDialog);
|
|
TOQBbuttons = set of TOQBbutton;
|
|
|
|
TOQBEngine = class;
|
|
|
|
{ TOQBuilderDialog }
|
|
|
|
TOQBuilderDialog = class(TComponent)
|
|
private
|
|
FDatabase: string;
|
|
FSystemTables: Boolean;
|
|
FOQBForm: TForm;
|
|
FSQL: TStrings;
|
|
FOQBEngine: TOQBEngine;
|
|
FShowButtons: TOQBbuttons;
|
|
procedure SetOQBEngine(const Value: TOQBEngine);
|
|
protected
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
function Execute: Boolean; virtual;
|
|
property SQL: TStrings read FSQL;
|
|
property SystemTables: Boolean read FSystemTables write FSystemTables default False;
|
|
property Database: string read FDatabase write FDatabase;
|
|
published
|
|
property OQBEngine: TOQBEngine read FOQBEngine write SetOQBEngine;
|
|
property ShowButtons: TOQBbuttons read FShowButtons write FShowButtons
|
|
default [bSelectDBDialog, bOpenDialog, bSaveDialog, bRunQuery, bSaveResultsDialog];
|
|
end;
|
|
|
|
TOQBEngine = class(TComponent)
|
|
private
|
|
FDatabaseName: string;
|
|
FUserName: string;
|
|
FPassword: string;
|
|
FShowSystemTables: Boolean;
|
|
FTableList: TStringList;
|
|
FAliasList: TStringList;
|
|
FFieldList: TStringList;
|
|
FSQL: TStringList;
|
|
FSQLcolumns: TStringList;
|
|
FSQLcolumns_table: TStringList;
|
|
FSQLcolumns_func: TStringList;
|
|
FSQLfrom: TStringList;
|
|
FSQLwhere: TStringList;
|
|
FSQLgroupby: TStringList;
|
|
FSQLorderby: TStringList;
|
|
FUseTableAliases: Boolean;
|
|
FOQBDialog: TOQBuilderDialog;
|
|
procedure SetShowSystemTables(const Value: Boolean);
|
|
protected
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure SetDatabaseName(const Value: string); virtual;
|
|
procedure SetUserName(const Value: string); virtual;
|
|
procedure SetPassword(const Value: string); virtual;
|
|
procedure SetQuerySQL(const Value: string); virtual; abstract;
|
|
procedure GenerateAliases; virtual;
|
|
// Read list of tables (system tables etc) into FTableList
|
|
procedure ReadTableList; virtual; abstract;
|
|
procedure ReadFieldList(const ATableName: string); virtual; abstract;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
function SelectDatabase: Boolean; virtual; abstract;
|
|
function GenerateSQL: string; virtual;
|
|
procedure ClearQuerySQL; virtual; abstract;
|
|
function ResultQuery: TDataSet; virtual; abstract;
|
|
procedure OpenResultQuery; virtual; abstract;
|
|
procedure CloseResultQuery; virtual; abstract;
|
|
procedure SaveResultQueryData; virtual; abstract;
|
|
// All tables in the database
|
|
property TableList: TStringList read FTableList;
|
|
property AliasList: TStringList read FAliasList;
|
|
property FieldList: TStringList read FFieldList;
|
|
property SQL: TStringList read FSQL;
|
|
property SQLcolumns: TStringList read FSQLcolumns;
|
|
property SQLcolumns_table: TStringList read FSQLcolumns_table;
|
|
property SQLcolumns_func: TStringList read FSQLcolumns_func;
|
|
property SQLfrom: TStringList read FSQLfrom;
|
|
property SQLwhere: TStringList read FSQLwhere;
|
|
property SQLgroupby: TStringList read FSQLgroupby;
|
|
property SQLorderby: TStringList read FSQLorderby;
|
|
property UserName: string read FUserName write SetUserName;
|
|
property Password: string read FPassword write SetPassword;
|
|
published
|
|
property DatabaseName: string read FDatabaseName write SetDatabaseName;
|
|
property ShowSystemTables: Boolean read FShowSystemTables write SetShowSystemTables default False;
|
|
property UseTableAliases: Boolean read FUseTableAliases write FUseTableAliases default True;
|
|
end;
|
|
|
|
type
|
|
TArr = array [0..0] of Integer;
|
|
PArr = ^TArr;
|
|
|
|
{ TOQBLbx }
|
|
|
|
TOQBLbx = class(TCheckListBox)
|
|
private
|
|
FArrBold: PArr;
|
|
FLoading: Boolean;
|
|
// procedure CNDrawItem(var Message: TWMDrawItem); message CN_DrawItem;
|
|
procedure WMLButtonDown(var Message: TLMLButtonDblClk); message LM_LBUTTONDOWN;
|
|
procedure WMRButtonDown(var Message: TLMRButtonDblClk); message LM_RBUTTONDOWN;
|
|
function GetCheckW: Integer;
|
|
procedure AllocArrBold;
|
|
procedure SelectItemBold(Item: Integer);
|
|
procedure UnSelectItemBold(Item: Integer);
|
|
function GetItemY(Item: Integer): Integer;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
// procedure ClickCheck; override;
|
|
procedure ItemClick(const AIndex: Integer); override;
|
|
end;
|
|
|
|
TOQBTable = class(TPanel)
|
|
private
|
|
ScreenDC: HDC;
|
|
OldX: Integer;
|
|
OldY: Integer;
|
|
OldLeft: Integer;
|
|
OldTop: Integer;
|
|
ClipRgn: HRGN;
|
|
ClipRect: TRect;
|
|
MoveRect: TRect;
|
|
Moving: Boolean;
|
|
FCloseBtn: TSpeedButton;
|
|
FUnlinkBtn: TSpeedButton;
|
|
FLbx: TOQBLbx;
|
|
FTableName: string;
|
|
FTableAlias: string;
|
|
PopMenu: TPopupMenu;
|
|
procedure WMRButtonDown(var Message: TLMRButtonDblClk); message LM_RBUTTONDOWN;
|
|
function Activate(const ATableName: string; X, Y: Integer): Boolean;
|
|
function GetRowY(FldN: Integer):Integer;
|
|
procedure _CloseBtn(Sender: TObject);
|
|
procedure _UnlinkBtn(Sender: TObject);
|
|
procedure _SelectAll(Sender: TObject);
|
|
procedure _UnSelectAll(Sender: TObject);
|
|
procedure _DragOver(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
procedure _DragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
protected
|
|
procedure SetParent(AParent: TWinControl); override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); override;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); override;
|
|
property Align;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
procedure Paint; override;
|
|
end;
|
|
|
|
{ TOQBLink }
|
|
|
|
TOQBLink = class(TShape)
|
|
private
|
|
Tbl1: TOQBTable;
|
|
Tbl2: TOQBTable;
|
|
FldN1: Integer;
|
|
FldN2: Integer;
|
|
FldNam1: string;
|
|
FldNam2: string;
|
|
FLinkOpt: Integer;
|
|
FLinkType: Integer;
|
|
LnkX: Byte;
|
|
LnkY: Byte;
|
|
Rgn: HRgn;
|
|
PopMenu: TPopupMenu;
|
|
procedure _Click(X, Y: Integer);
|
|
procedure CMHitTest(var Message: TCMHitTest); message CM_HitTest;
|
|
function ControlAtPos(const Pos: TPoint): TControl;
|
|
function PtInRegion(RGN: HRGN; X, Y: Integer) : Boolean;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure WndProc(var Message: TLMessage); override;
|
|
procedure Paint; override;
|
|
end;
|
|
|
|
TOQBArea = class(TScrollBox)
|
|
public
|
|
procedure CreateParams(var Params: TCreateParams); override;
|
|
procedure SetOptions(Sender: TObject);
|
|
procedure InsertTable(X, Y: Integer);
|
|
function InsertLink(_tbl1, _tbl2: TOQBTable; _fldN1, _fldN2: Integer): TOQBLink;
|
|
function FindTable(const TableName: string): TOQBTable;
|
|
function FindLink(Link: TOQBLink): Boolean;
|
|
function FindOtherLink(Link: TOQBLink; Tbl: TOQBTable; FldN: Integer): Boolean;
|
|
procedure ReboundLink(Link: TOQBLink);
|
|
procedure ReboundLinks4Table(ATable: TOQBTable);
|
|
procedure Unlink(Sender: TObject);
|
|
procedure UnlinkTable(ATable: TOQBTable);
|
|
procedure _DragOver(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
procedure _DragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
end;
|
|
|
|
TOQBGrid = class(TStringGrid)
|
|
public
|
|
CurrCol: Integer;
|
|
IsEmpty: Boolean;
|
|
procedure CreateParams(var Params: TCreateParams); override;
|
|
procedure WndProc(var Message: TLMessage); override;
|
|
function MaxSW(const s1, s2: string): Integer;
|
|
procedure InsertDefault(aCol: Integer);
|
|
procedure Insert(aCol: Integer; const aField, aTable: string);
|
|
function FindColumn(const sCol: string): Integer;
|
|
function FindSameColumn(aCol: Integer): Boolean;
|
|
procedure RemoveColumn(aCol: Integer);
|
|
procedure RemoveColumn4Tbl(const Tbl: string);
|
|
procedure ClickCell(X, Y: Integer);
|
|
function SelectCell(ACol, ARow: Integer): Boolean; override;
|
|
procedure _DragOver(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
procedure _DragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
end;
|
|
|
|
TOQBForm = class(TForm)
|
|
QBPanel: TPanel;
|
|
Pages: TPageControl;
|
|
TabColumns: TTabSheet;
|
|
QBTables: TListBox;
|
|
VSplitter: TSplitter;
|
|
mnuTbl: TPopupMenu;
|
|
Remove1: TMenuItem;
|
|
mnuFunc: TPopupMenu;
|
|
Nofunction1: TMenuItem;
|
|
N1: TMenuItem;
|
|
Average1: TMenuItem;
|
|
Count1: TMenuItem;
|
|
Minimum1: TMenuItem;
|
|
Maximum1: TMenuItem;
|
|
Sum1: TMenuItem;
|
|
mnuGroup: TPopupMenu;
|
|
Group1: TMenuItem;
|
|
mnuSort: TPopupMenu;
|
|
Sort1: TMenuItem;
|
|
N2: TMenuItem;
|
|
Ascending1: TMenuItem;
|
|
Descending1: TMenuItem;
|
|
mnuShow: TPopupMenu;
|
|
Show1: TMenuItem;
|
|
HSplitter: TSplitter;
|
|
TabSQL: TTabSheet;
|
|
MemoSQL: TMemo;
|
|
TabResults: TTabSheet;
|
|
ResDBGrid: TDBGrid;
|
|
ResDataSource: TDataSource;
|
|
QBBar: TToolBar;
|
|
btnNew: TToolButton;
|
|
btnOpen: TToolButton;
|
|
btnSave: TToolButton;
|
|
ToolButton1: TToolButton;
|
|
btnTables: TToolButton;
|
|
ToolImages: TImageList;
|
|
btnPages: TToolButton;
|
|
ToolButton2: TToolButton;
|
|
DlgSave: TSaveDialog;
|
|
DlgOpen: TOpenDialog;
|
|
btnDB: TToolButton;
|
|
btnSQL: TToolButton;
|
|
btnResults: TToolButton;
|
|
ToolButton3: TToolButton;
|
|
btnAbout: TToolButton;
|
|
btnSaveResults: TToolButton;
|
|
btnOK: TToolButton;
|
|
btnCancel: TToolButton;
|
|
ToolButton6: TToolButton;
|
|
procedure mnuFunctionClick(Sender: TObject);
|
|
procedure mnuGroupClick(Sender: TObject);
|
|
procedure mnuRemoveClick(Sender: TObject);
|
|
procedure mnuShowClick(Sender: TObject);
|
|
procedure mnuSortClick(Sender: TObject);
|
|
procedure btnNewClick(Sender: TObject);
|
|
procedure btnOpenClick(Sender: TObject);
|
|
procedure btnSaveClick(Sender: TObject);
|
|
procedure btnTablesClick(Sender: TObject);
|
|
procedure btnPagesClick(Sender: TObject);
|
|
procedure btnDBClick(Sender: TObject);
|
|
procedure btnSQLClick(Sender: TObject);
|
|
procedure btnResultsClick(Sender: TObject);
|
|
procedure btnAboutClick(Sender: TObject);
|
|
procedure btnSaveResultsClick(Sender: TObject);
|
|
procedure btnOKClick(Sender: TObject);
|
|
procedure btnCancelClick(Sender: TObject);
|
|
protected
|
|
QBDialog: TOQBuilderDialog;
|
|
QBArea: TOQBArea;
|
|
QBGrid: TOQBGrid;
|
|
procedure CreateParams(var Params: TCreateParams); override;
|
|
procedure ClearAll;
|
|
procedure OpenDatabase;
|
|
procedure SelectDatabase;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{$R QBBUTTON.RES}
|
|
|
|
uses
|
|
QBLnkFrm, QBAbout;
|
|
|
|
{$R *.lfm}
|
|
|
|
resourcestring
|
|
sMainCaption = 'QBuilder';
|
|
sNotValidTableParent = 'Parent must be TScrollBox or its descendant.';
|
|
|
|
const
|
|
cFld = 0;
|
|
cTbl = 1;
|
|
cShow = 2;
|
|
cSort = 3;
|
|
cFunc = 4;
|
|
cGroup = 5;
|
|
|
|
sShow = 'Show';
|
|
sGroup = 'Group';
|
|
sSort: array [1..3] of string =
|
|
('',
|
|
'Asc',
|
|
'Desc');
|
|
sFunc: array [1..6] of string =
|
|
('',
|
|
'Avg',
|
|
'Count',
|
|
'Max',
|
|
'Min',
|
|
'Sum');
|
|
|
|
sLinkOpt: array [0..5] of string =
|
|
('=',
|
|
'<',
|
|
'>',
|
|
'=<',
|
|
'=>',
|
|
'<>');
|
|
|
|
sOuterJoin: array [1..3] of string =
|
|
(' LEFT OUTER JOIN ',
|
|
' RIGHT OUTER JOIN ',
|
|
' FULL OUTER JOIN ');
|
|
|
|
Hand = 15;
|
|
Hand2 = 12;
|
|
|
|
QBSignature = '# QBuilder';
|
|
|
|
|
|
{ TQueryBuilderDialog}
|
|
|
|
constructor TOQBuilderDialog.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
FSystemTables := False;
|
|
FShowButtons := [bSelectDBDialog, bOpenDialog, bSaveDialog,
|
|
bRunQuery, bSaveResultsDialog];
|
|
FSQL := TStringList.Create;
|
|
end;
|
|
|
|
destructor TOQBuilderDialog.Destroy;
|
|
begin
|
|
if FSQL <> nil then
|
|
FSQL.Free;
|
|
FOQBEngine := nil;
|
|
inherited;
|
|
end;
|
|
|
|
function TOQBuilderDialog.Execute: Boolean;
|
|
begin
|
|
Result := False;
|
|
if (not Assigned(FOQBForm)) and Assigned((FOQBEngine)) then
|
|
begin
|
|
TOQBForm(FOQBForm) := TOQBForm.Create(Application);
|
|
TOQBForm(FOQBForm).QBDialog := Self;
|
|
TOQBForm(FOQBForm).btnDB.Visible := bSelectDBDialog in FShowButtons;
|
|
TOQBForm(FOQBForm).btnOpen.Visible := bOpenDialog in FShowButtons;
|
|
TOQBForm(FOQBForm).btnSave.Visible := bSaveDialog in FShowButtons;
|
|
TOQBForm(FOQBForm).btnResults.Visible := bRunQuery in FShowButtons;
|
|
TOQBForm(FOQBForm).btnSaveResults.Visible := bSaveResultsDialog in FShowButtons;
|
|
if OQBEngine.DatabaseName <> EmptyStr then
|
|
TOQBForm(FOQBForm).OpenDatabase else
|
|
TOQBForm(FOQBForm).SelectDatabase;
|
|
|
|
if TOQBForm(FOQBForm).ShowModal = mrOk then
|
|
begin
|
|
FSQL.Assign(TOQBForm(FOQBForm).MemoSQL.Lines);
|
|
Result := True;
|
|
end;
|
|
|
|
OQBEngine.CloseResultQuery;
|
|
FOQBForm.Free;
|
|
FOQBForm := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBuilderDialog.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
inherited;
|
|
if (AComponent = FOQBEngine) and (Operation = opRemove) then
|
|
FOQBEngine := nil;
|
|
end;
|
|
|
|
procedure TOQBuilderDialog.SetOQBEngine(const Value: TOQBEngine);
|
|
begin
|
|
if FOQBEngine <> nil then
|
|
FOQBEngine.FOQBDialog := nil;
|
|
FOQBEngine := Value;
|
|
if FOQBEngine <> nil then
|
|
begin
|
|
FOQBEngine.FOQBDialog := Self;
|
|
FOQBEngine.FreeNotification(Self);
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TOQBEngine }
|
|
|
|
constructor TOQBEngine.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
FShowSystemTables := False;
|
|
FTableList := TStringList.Create;
|
|
FAliasList := TStringList.Create;
|
|
FFieldList := TStringList.Create;
|
|
FSQL := TStringList.Create;
|
|
FSQLcolumns := TStringList.Create;
|
|
FSQLcolumns_table := TStringList.Create;
|
|
FSQLcolumns_func := TStringList.Create;
|
|
FSQLfrom := TStringList.Create;
|
|
FSQLwhere := TStringList.Create;
|
|
FSQLgroupby := TStringList.Create;
|
|
FSQLorderby := TStringList.Create;
|
|
FUseTableAliases := True;
|
|
end;
|
|
|
|
destructor TOQBEngine.Destroy;
|
|
begin
|
|
FSQL.Free;
|
|
FSQLcolumns.Free;
|
|
FSQLcolumns_table.Free;
|
|
FSQLcolumns_func.Free;
|
|
FSQLfrom.Free;
|
|
FSQLwhere.Free;
|
|
FSQLgroupby.Free;
|
|
FSQLorderby.Free;
|
|
FFieldList.Free;
|
|
FAliasList.Free;
|
|
FTableList.Free;
|
|
FreeNotification(Self);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TOQBEngine.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
inherited;
|
|
if (AComponent = FOQBDialog) and (Operation = opRemove) then
|
|
FOQBDialog := nil;
|
|
end;
|
|
|
|
procedure TOQBEngine.SetDatabaseName(const Value: string);
|
|
begin
|
|
TableList.Clear;
|
|
FDatabaseName := Value;
|
|
if ResultQuery.Active then
|
|
ResultQuery.Close;
|
|
end;
|
|
|
|
procedure TOQBEngine.SetUserName(const Value: string);
|
|
begin
|
|
FUserName := Value;
|
|
end;
|
|
|
|
procedure TOQBEngine.SetPassword(const Value: string);
|
|
begin
|
|
FPassword := Value;
|
|
end;
|
|
|
|
procedure TOQBEngine.SetShowSystemTables(const Value: Boolean);
|
|
begin
|
|
if FShowSystemTables <> Value then
|
|
FShowSystemTables := Value;
|
|
end;
|
|
|
|
procedure TOQBEngine.GenerateAliases;
|
|
var
|
|
i, j: Integer;
|
|
s, s1: string;
|
|
begin
|
|
FAliasList.Clear;
|
|
for i := 0 to FTableList.Count - 1 do
|
|
begin
|
|
s := ' ';
|
|
s[1] := FTableList[i][1]; // get the first character [1] of the table name [i]
|
|
if FAliasList.IndexOf(s) = -1 then
|
|
FAliasList.Add(s)
|
|
else
|
|
begin
|
|
j := 1;
|
|
repeat
|
|
Inc(j);
|
|
s1 := s + IntToStr(j);
|
|
until FAliasList.IndexOf(s1) = -1;
|
|
FAliasList.Add(s1);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TOQBEngine.GenerateSQL: string;
|
|
var
|
|
s: string;
|
|
i: Integer;
|
|
begin
|
|
SQL.Clear;
|
|
|
|
s := 'SELECT ';
|
|
for i := 0 to SQLcolumns.Count - 1 do
|
|
begin
|
|
if SQLcolumns_func[i] = EmptyStr then
|
|
s := s + SQLcolumns[i] else
|
|
s := s + SQLcolumns_func[i] + '(' + SQLcolumns[i] + ')';
|
|
if (i < SQLcolumns.Count - 1) then
|
|
s := s + ', ';
|
|
if (Length(s) > 70) or (i = SQLcolumns.Count - 1) then
|
|
begin
|
|
SQL.Add(s);
|
|
s := ' ';
|
|
end;
|
|
end;
|
|
|
|
s := 'FROM ';
|
|
for i := 0 to SQLfrom.Count - 1 do
|
|
begin
|
|
s := s + SQLfrom[i];
|
|
if (i < SQLfrom.Count - 1) then
|
|
s := s + ', ';
|
|
if (Length(s) > 70) or (i = SQLfrom.Count - 1) then
|
|
begin
|
|
SQL.Add(s);
|
|
s := ' ';
|
|
end;
|
|
end;
|
|
|
|
s := 'WHERE ';
|
|
for i := 0 to SQLwhere.Count - 1 do
|
|
begin
|
|
if (i < SQLwhere.Count - 1) then
|
|
s := s + SQLwhere[i] + ' AND ' else
|
|
s := s + SQLwhere[i];
|
|
if (Length(s) > 70) or (i = SQLwhere.Count - 1) then
|
|
begin
|
|
SQL.Add(s);
|
|
s := ' ';
|
|
end;
|
|
end;
|
|
|
|
s := 'GROUP BY ';
|
|
for i := 0 to SQLgroupby.Count - 1 do
|
|
begin
|
|
if (i < SQLgroupby.Count - 1) then
|
|
s := s + SQLgroupby[i] + ', ' else
|
|
s := s + SQLgroupby[i];
|
|
if (Length(s) > 70) or (i = SQLgroupby.Count - 1) then
|
|
begin
|
|
SQL.Add(s);
|
|
s := ' ';
|
|
end;
|
|
end;
|
|
|
|
s := 'ORDER BY ';
|
|
for i := 0 to SQLorderby.Count - 1 do
|
|
begin
|
|
if (i < SQLorderby.Count - 1) then
|
|
s := s + SQLorderby[i] + ', ' else
|
|
s := s + SQLorderby[i];
|
|
if (Length(s) > 70) or (i = SQLorderby.Count - 1) then
|
|
begin
|
|
SQL.Add(s);
|
|
s := ' ';
|
|
end;
|
|
end;
|
|
|
|
Result := SQL.Text;
|
|
end;
|
|
|
|
|
|
{ TOQBLbx }
|
|
|
|
constructor TOQBLbx.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
Style := lbStandard;
|
|
ParentFont := False;
|
|
Font.Style := [];
|
|
Font.Size := 8;
|
|
FArrBold := nil;
|
|
FLoading := False;
|
|
end;
|
|
|
|
destructor TOQBLbx.Destroy;
|
|
begin
|
|
if FArrBold <> nil then
|
|
FreeMem(FArrBold);
|
|
inherited;
|
|
end;
|
|
|
|
function TOQBLbx.GetCheckW: Integer;
|
|
begin
|
|
Result := GetCheckW;
|
|
end;
|
|
|
|
{procedure TOQBLbx.CNDrawItem(var Message: TWMDrawItem);
|
|
begin
|
|
with Message.DrawItemStruct^ do
|
|
begin
|
|
rcItem.Left := rcItem.Left + GetCheckW; //*** check
|
|
Canvas.Font := Font;
|
|
Canvas.Brush := Brush;
|
|
if (Integer(itemID) >= 0) and (Integer(itemID) <= Items.Count - 1) then
|
|
begin
|
|
if (FArrBold <> nil) then
|
|
if FArrBold^[Integer(itemID)] = 1 then
|
|
Canvas.Font.Style := [fsBold];
|
|
DrawItem(itemID, rcItem, []);
|
|
if (FArrBold <> nil) then
|
|
if FArrBold^[Integer(itemID)] = 1 then
|
|
Canvas.Font.Style := [];
|
|
end
|
|
else
|
|
Canvas.FillRect(rcItem);
|
|
end;
|
|
end;}
|
|
|
|
procedure TOQBLbx.WMLButtonDown(var Message: TLMLButtonDblClk);
|
|
begin
|
|
inherited;
|
|
BeginDrag(False);
|
|
end;
|
|
|
|
procedure TOQBLbx.WMRButtonDown(var Message: TLMRButtonDblClk);
|
|
var
|
|
pnt: TPoint;
|
|
begin
|
|
inherited;
|
|
pnt.X := Message.XPos;
|
|
pnt.Y := Message.YPos;
|
|
pnt := ClientToScreen(pnt);
|
|
PopupMenu.Popup(pnt.X, pnt.Y);
|
|
end;
|
|
|
|
{procedure TOQBLbx.ClickCheck;
|
|
var
|
|
iCol: Integer;
|
|
begin
|
|
inherited;
|
|
if FLoading then
|
|
Exit;
|
|
|
|
if Checked[ItemIndex] then
|
|
begin
|
|
TOQBForm(GetParentForm(Self)).QBGrid.Insert(
|
|
TOQBForm(GetParentForm(Self)).QBGrid.ColCount,
|
|
Items[ItemIndex], TOQBTable(Parent).FTableName);
|
|
end
|
|
else
|
|
begin
|
|
iCol := TOQBForm(GetParentForm(Self)).QBGrid.FindColumn(Items[ItemIndex]);
|
|
while iCol <> -1 do
|
|
begin
|
|
TOQBForm(GetParentForm(Self)).QBGrid.RemoveColumn(iCol);
|
|
iCol := TOQBForm(GetParentForm(Self)).QBGrid.FindColumn(Items[ItemIndex]);
|
|
end;
|
|
end;
|
|
|
|
TOQBForm(GetParentForm(Self)).QBGrid.Refresh; // StringGrid bug
|
|
end; }
|
|
|
|
procedure TOQBLbx.ItemClick(const AIndex: Integer);
|
|
var
|
|
iCol: Integer;
|
|
begin
|
|
inherited ItemClick(AIndex);
|
|
if FLoading then
|
|
Exit;
|
|
|
|
if Checked[ItemIndex] then
|
|
begin
|
|
TOQBForm(GetParentForm(Self)).QBGrid.Insert(
|
|
TOQBForm(GetParentForm(Self)).QBGrid.ColCount,
|
|
Items[ItemIndex], TOQBTable(Parent).FTableName);
|
|
end
|
|
else
|
|
begin
|
|
iCol := TOQBForm(GetParentForm(Self)).QBGrid.FindColumn(Items[ItemIndex]);
|
|
while iCol <> -1 do
|
|
begin
|
|
TOQBForm(GetParentForm(Self)).QBGrid.RemoveColumn(iCol);
|
|
iCol := TOQBForm(GetParentForm(Self)).QBGrid.FindColumn(Items[ItemIndex]);
|
|
end;
|
|
end;
|
|
|
|
TOQBForm(GetParentForm(Self)).QBGrid.Refresh; // StringGrid bug
|
|
end;
|
|
|
|
procedure TOQBLbx.AllocArrBold;
|
|
begin
|
|
FArrBold := AllocMem(Items.Count * SizeOf(Integer));
|
|
end;
|
|
|
|
procedure TOQBLbx.SelectItemBold(Item: Integer);
|
|
begin
|
|
if FArrBold <> nil then
|
|
if FArrBold[Item] = 0 then
|
|
FArrBold^[Item] := 1;
|
|
end;
|
|
|
|
procedure TOQBLbx.UnSelectItemBold(Item: Integer);
|
|
begin
|
|
if FArrBold <> nil then
|
|
if FArrBold[Item] = 1 then
|
|
FArrBold^[Item] := 0;
|
|
end;
|
|
|
|
function TOQBLbx.GetItemY(Item: Integer): Integer;
|
|
begin
|
|
Result := Item * ItemHeight + ItemHeight div 2 + 1;
|
|
end;
|
|
|
|
|
|
{ TOQBTable }
|
|
|
|
constructor TOQBTable.Create(AOwner: TComponent);
|
|
var
|
|
mnuArr: array [1..5] of TMenuItem;
|
|
begin
|
|
inherited;
|
|
Visible := False;
|
|
ShowHint := True;
|
|
BevelInner := bvRaised;
|
|
BevelOuter := bvRaised;
|
|
BorderWidth := 1;
|
|
FCloseBtn := TSpeedButton.Create(Self);
|
|
FCloseBtn.Parent := Self;
|
|
FCloseBtn.Hint := 'Close';
|
|
FUnlinkBtn := TSpeedButton.Create(Self);
|
|
FUnlinkBtn.Parent := Self;
|
|
FUnlinkBtn.Hint := 'Unlink all';
|
|
|
|
FLbx := TOQBLbx.Create(Self);
|
|
FLbx.Parent := Self;
|
|
FLbx.Style := lbStandard;
|
|
FLbx.Align := alBottom;
|
|
FLbx.TabStop := False;
|
|
FLbx.Visible := False;
|
|
|
|
mnuArr[1] := NewItem('Select All', 0, False, True, _SelectAll, 0, 'mnuSelectAll');
|
|
mnuArr[2] := NewItem('Unselect All', 0, False, True, _UnSelectAll, 0, 'mnuUnSelectAll');
|
|
mnuArr[3] := NewLine;
|
|
mnuArr[4] := NewItem('Unlink', 0, False, True, _UnlinkBtn, 0, 'mnuUnLink');
|
|
mnuArr[5] := NewItem('Close', 0, False, True, _CloseBtn, 0, 'mnuClose');
|
|
PopMenu := NewPopupMenu(Self, 'mnu', paLeft, False, mnuArr);
|
|
PopMenu.PopupComponent := Self;
|
|
|
|
FLbx.PopupMenu := PopMenu;
|
|
end;
|
|
|
|
procedure TOQBTable.WMRButtonDown(var Message: TLMLButtonDblClk);
|
|
var
|
|
pnt: TPoint;
|
|
begin
|
|
inherited;
|
|
pnt.X := Message.XPos;
|
|
pnt.Y := Message.YPos;
|
|
pnt := ClientToScreen(pnt);
|
|
PopMenu.Popup(pnt.X, pnt.Y);
|
|
end;
|
|
|
|
procedure TOQBTable.Paint;
|
|
begin
|
|
inherited;
|
|
if TOQBForm(GetParentForm(Self)).QBDialog.OQBEngine.UseTableAliases then
|
|
Canvas.TextOut(4, 4, FTableName + ' : ' + FTableAlias) else
|
|
Canvas.TextOut(4, 4, FTableName);
|
|
end;
|
|
|
|
function TOQBTable.GetRowY(FldN: Integer): Integer;
|
|
var
|
|
pnt: TPoint;
|
|
begin
|
|
pnt.X := FLbx.Left;
|
|
pnt.Y := FLbx.Top + FLbx.GetItemY(FldN);
|
|
pnt := Parent.ScreenToClient(ClientToScreen(pnt));
|
|
Result := pnt.Y;
|
|
end;
|
|
|
|
function TOQBTable.Activate(const ATableName: string; X, Y: Integer): Boolean;
|
|
var
|
|
i: Integer;
|
|
W, W1: Integer;
|
|
OQBEngine: TOQBEngine;
|
|
begin
|
|
Result := False;
|
|
Top := Y;
|
|
Left := X;
|
|
Font.Style := [fsBold];
|
|
Font.Size := 8;
|
|
Canvas.Font := Font;
|
|
Hint := ATableName;
|
|
|
|
FTableName := ATableName;
|
|
FTableAlias := TOQBForm(GetParentForm(Self)).QBDialog.FOQBEngine.AliasList[
|
|
TOQBForm(GetParentForm(Self)).QBDialog.FOQBEngine.TableList.IndexOf(ATableName)];
|
|
OQBEngine := TOQBForm(GetParentForm(Self)).QBDialog.FOQBEngine;
|
|
try
|
|
OQBEngine.ReadFieldList(ATableName);
|
|
FLbx.Items.Assign(OQBEngine.FieldList);
|
|
except
|
|
on E: EDatabaseError do
|
|
begin
|
|
ShowMessage(E.Message);
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
FLbx.AllocArrBold;
|
|
FLbx.ParentFont := False;
|
|
FLbx.TabStop := False;
|
|
|
|
case WidgetSet.LCLPlatform of
|
|
lpGtk: FLbx.Height := ((FLbx.ItemHeight + 6) * FLbx.Items.Count) + 4;
|
|
lpGtk2: FLbx.Height := ((FLbx.ItemHeight + 6) * FLbx.Items.Count) + 4;
|
|
lpWin32: FLbx.Height := ((FLbx.ItemHeight + 4) * FLbx.Items.Count) + 4;
|
|
lpCarbon:FLbx.Height := ((FLbx.ItemHeight + 8) * FLbx.Items.Count) + 4;
|
|
lpQT: FLbx.Height := ((FLbx.ItemHeight + 8) * FLbx.Items.Count) + 4;
|
|
lpfpGUI: FLbx.Height := ((FLbx.ItemHeight + 8) * FLbx.Items.Count) + 4;
|
|
else
|
|
FLbx.Height := ((FLbx.ItemHeight + 8) * FLbx.Items.Count) + 4;
|
|
end;
|
|
|
|
Height := FLbx.Height + 22;
|
|
W := 110;
|
|
for i := 0 to FLbx.Items.Count - 1 do
|
|
begin
|
|
W1 := Canvas.TextWidth(FLbx.Items[i]);
|
|
if W < W1 then
|
|
W := W1;
|
|
end;
|
|
Width := W + 20 + 22;//FLbx.GetCheckW; //*** check
|
|
|
|
if TOQBForm(GetParentForm(Self)).QBDialog.OQBEngine.UseTableAliases then
|
|
begin
|
|
if Canvas.TextWidth(FTableName + ' : ' + FTableAlias) > Width - 34 then
|
|
Width := Canvas.TextWidth(FTableName + ' : ' + FTableAlias) + 34
|
|
end
|
|
else if Canvas.TextWidth(FTableName) > Width - 34 then
|
|
Width := Canvas.TextWidth(FTableName) + 34;
|
|
|
|
Color := clForm;
|
|
FLbx.Visible := True;
|
|
FLbx.OnDragOver := _DragOver;
|
|
FLbx.OnDragDrop := _DragDrop;
|
|
FCloseBtn.Top := 4;
|
|
FCloseBtn.Left := Self.ClientWidth - 16;
|
|
FCloseBtn.Width := 12;
|
|
FCloseBtn.Height := 12;
|
|
FCloseBtn.Glyph.LoadFromResourceName(HInstance, 'CLOSEBMP');;
|
|
FCloseBtn.Margin := -1;
|
|
FCloseBtn.Spacing := 0;
|
|
FCloseBtn.OnClick := _CloseBtn;
|
|
FCloseBtn.Visible := True;
|
|
FUnlinkBtn.Top := 4;
|
|
FUnlinkBtn.Left := Self.ClientWidth - 16 - FCloseBtn.Width;
|
|
FUnlinkBtn.Width := 12;
|
|
FUnlinkBtn.Height := 12;
|
|
FUnlinkBtn.Glyph.LoadFromResourceName(HInstance, 'UNLINKBMP');;
|
|
FUnlinkBtn.Margin := -1;
|
|
FUnlinkBtn.Spacing := 0;
|
|
FUnlinkBtn.OnClick := _UnlinkBtn;
|
|
FUnlinkBtn.Visible := True;
|
|
Visible := True;
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TOQBTable._CloseBtn(Sender: TObject);
|
|
begin
|
|
TOQBArea(Parent).UnlinkTable(Self);
|
|
TOQBForm(GetParentForm(Self)).QBGrid.RemoveColumn4Tbl(FTableName);
|
|
Parent.RemoveControl(Self);
|
|
Free;
|
|
end;
|
|
|
|
procedure TOQBTable._UnlinkBtn(Sender: TObject);
|
|
begin
|
|
TOQBArea(Parent).UnlinkTable(Self);
|
|
end;
|
|
|
|
procedure TOQBTable._SelectAll(Sender: TObject);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if FLbx.Items.Count = 1 then
|
|
Exit;
|
|
for i := 1 to (FLbx.Items.Count - 1) do
|
|
begin
|
|
FLbx.Checked[i] := True;
|
|
TOQBForm(GetParentForm(Self)).QBGrid.Insert(
|
|
TOQBForm(GetParentForm(Self)).QBGrid.ColCount,
|
|
FLbx.Items[i], FTableName);
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBTable._UnSelectAll(Sender: TObject);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if FLbx.Items.Count = 1 then
|
|
Exit;
|
|
for i := 1 to (FLbx.Items.Count - 1) do
|
|
begin
|
|
FLbx.Checked[i] := False;
|
|
TOQBForm(GetParentForm(Self)).QBGrid.RemoveColumn4Tbl(FTableName);
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBTable._DragOver(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
begin
|
|
if (Source is TCustomListBox) and (TWinControl(Source).Parent is TOQBTable) then
|
|
Accept := True;
|
|
end;
|
|
|
|
procedure TOQBTable._DragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
var
|
|
nRow: Integer;
|
|
hRow: Integer;
|
|
begin
|
|
if (Source is TCustomListBox) then
|
|
begin
|
|
if (TWinControl(Source).Parent is TOQBTable) then
|
|
begin
|
|
hRow := FLbx.ItemHeight;
|
|
if hRow <> 0 then
|
|
nRow := Y div hRow else
|
|
nRow := 0;
|
|
if nRow > FLbx.Items.Count - 1 then
|
|
nRow := FLbx.Items.Count - 1;
|
|
// handler for target's '*' row
|
|
if nRow = 0 then
|
|
Exit;
|
|
// handler for source's '*' row
|
|
if TOQBTable(TWinControl(Source).Parent).FLbx.ItemIndex = 0 then
|
|
Exit;
|
|
if Source <> FLbx then
|
|
TOQBArea(Parent).InsertLink(
|
|
TOQBTable(TWinControl(Source).Parent), Self,
|
|
TOQBTable(TWinControl(Source).Parent).FLbx.ItemIndex, nRow)
|
|
else if nRow <> FLbx.ItemIndex then
|
|
TOQBArea(Parent).InsertLink(Self, Self, FLbx.ItemIndex, nRow);
|
|
end
|
|
else
|
|
if Source = TOQBForm(GetParentForm(Self)).QBTables then
|
|
begin
|
|
X := X + Left + TWinControl(Sender).Left;
|
|
Y := Y + Top + TWinControl(Sender).Top;
|
|
TOQBArea(Parent).InsertTable(X, Y);
|
|
end;
|
|
end
|
|
end;
|
|
|
|
procedure TOQBTable.SetParent(AParent: TWinControl);
|
|
begin
|
|
if (AParent <> nil) and (not (AParent is TScrollBox)) then
|
|
raise Exception.Create(sNotValidTableParent);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TOQBTable.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited;
|
|
BringToFront;
|
|
if (Button = mbLeft) then
|
|
begin
|
|
SetCapture(Self.Handle);
|
|
ScreenDC := GetDC(0);
|
|
|
|
ClipRect := Bounds(Parent.Left, Parent.Top, Parent.Width, Parent.Height);
|
|
ClipRect.TopLeft := Parent.Parent.ClientToScreen(ClipRect.TopLeft);
|
|
ClipRect.BottomRight := Parent.Parent.ClientToScreen(ClipRect.BottomRight);
|
|
ClipRgn := CreateRectRgn(ClipRect.Left, ClipRect.Top, ClipRect.Right, ClipRect.Bottom);
|
|
SelectClipRgn(ScreenDC, ClipRgn);
|
|
// ClipCursor(@ClipRect);
|
|
OldX := X;
|
|
OldY := Y;
|
|
OldLeft := X;
|
|
OldTop := Y;
|
|
MoveRect := Rect(Self.Left, Self.Top, Self.Left + Self.Width, Self.Top + Self.Height);
|
|
MoveRect.TopLeft := Parent.ClientToScreen(MoveRect.TopLeft);
|
|
MoveRect.BottomRight := Parent.ClientToScreen(MoveRect.BottomRight);
|
|
DrawFocusRect(ScreenDC, MoveRect);
|
|
Moving := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBTable.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited;
|
|
if Moving then
|
|
begin
|
|
DrawFocusRect(ScreenDC, MoveRect);
|
|
OldX := X;
|
|
OldY := Y;
|
|
MoveRect := Rect(Self.Left + OldX - OldLeft, Self.Top + OldY - OldTop,
|
|
Self.Left + Self.Width + OldX - OldLeft, Self.Top + Self.Height + OldY - OldTop);
|
|
MoveRect.TopLeft := Parent.ClientToScreen(MoveRect.TopLeft);
|
|
MoveRect.BottomRight := Parent.ClientToScreen(MoveRect.BottomRight);
|
|
DrawFocusRect(ScreenDC, MoveRect);
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBTable.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited;
|
|
if Button = mbLeft then
|
|
begin
|
|
ReleaseCapture;
|
|
DrawFocusRect(ScreenDC, MoveRect);
|
|
if (Self.Left <> Self.Left + X + OldLeft) or (Self.Top <> Self.Top + Y - OldTop) then
|
|
begin
|
|
Self.Visible := False;
|
|
Self.Left := Self.Left + X - OldLeft;
|
|
Self.Top := Self.Top + Y - OldTop;
|
|
Self.Visible := True;
|
|
end;
|
|
ClipRect := Rect(0, 0, Screen.Width, Screen.Height);
|
|
// ClipCursor(@ClipRect);
|
|
DeleteObject(ClipRgn);
|
|
ReleaseDC(0, ScreenDC);
|
|
Moving := False;
|
|
end;
|
|
|
|
TOQBArea(Parent).ReboundLinks4Table(Self);
|
|
end;
|
|
|
|
{ TOQBLink }
|
|
|
|
constructor TOQBLink.Create(AOwner: TComponent);
|
|
var
|
|
mnuArr: array [1..4] of TMenuItem;
|
|
begin
|
|
inherited;
|
|
ControlStyle := ControlStyle + [csReplicatable];
|
|
Width := 105;
|
|
Height := 105;
|
|
Rgn := CreateRectRgn(0, 0, Hand, Hand);
|
|
mnuArr[1] := NewItem('', 0, False, False, nil, 0, 'mnuLinkName');
|
|
mnuArr[2] := NewLine;
|
|
mnuArr[3] := NewItem('Link options', 0, False, True, TOQBArea(AOwner).SetOptions, 0, 'mnuOptions');
|
|
mnuArr[4] := NewItem('Unlink', 0, False, True, TOQBArea(AOwner).Unlink, 0, 'mnuUnlink');
|
|
PopMenu := NewPopupMenu(Self, 'mnu', paLeft, False, mnuArr);
|
|
PopMenu.PopupComponent := Self;
|
|
end;
|
|
|
|
destructor TOQBLink.Destroy;
|
|
begin
|
|
DeleteObject(Rgn);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TOQBLink.Paint;
|
|
var
|
|
ArrRgn, pntArray: array [1..4] of TPoint;
|
|
ArrCnt: Integer;
|
|
begin
|
|
if tbl1 <> tbl2 then
|
|
begin
|
|
if ((LnkX = 1) and (LnkY = 1)) or ((LnkX = 4) and (LnkY = 2)) then
|
|
begin
|
|
pntArray[1].X := 0;
|
|
pntArray[1].Y := Hand div 2;
|
|
pntArray[2].X := Hand;
|
|
pntArray[2].Y := Hand div 2;
|
|
pntArray[3].X := Width - Hand;
|
|
pntArray[3].Y := Height - Hand div 2;
|
|
pntArray[4].X := Width;
|
|
pntArray[4].Y := Height - Hand div 2;
|
|
ArrRgn[1].X := pntArray[2].X + 5;
|
|
ArrRgn[1].Y := pntArray[2].Y - 5;
|
|
ArrRgn[2].X := pntArray[2].X - 5;
|
|
ArrRgn[2].Y := pntArray[2].Y + 5;
|
|
ArrRgn[3].X := pntArray[3].X - 5;
|
|
ArrRgn[3].Y := pntArray[3].Y + 5;
|
|
ArrRgn[4].X := pntArray[3].X + 5;
|
|
ArrRgn[4].Y := pntArray[3].Y - 5;
|
|
end;
|
|
if Width > Hand + Hand2 then
|
|
begin
|
|
if ((LnkX = 2) and (LnkY = 1)) or ((LnkX = 3) and (LnkY = 2)) then
|
|
begin
|
|
pntArray[1].X := 0;
|
|
pntArray[1].Y := Hand div 2;
|
|
pntArray[2].X := Hand;
|
|
pntArray[2].Y := Hand div 2;
|
|
pntArray[3].X := Width - 5;
|
|
pntArray[3].Y := Height - Hand div 2;
|
|
pntArray[4].X := Width - Hand;
|
|
pntArray[4].Y := Height - Hand div 2;
|
|
ArrRgn[1].X := pntArray[2].X + 5;
|
|
ArrRgn[1].Y := pntArray[2].Y - 5;
|
|
ArrRgn[2].X := pntArray[2].X - 5;
|
|
ArrRgn[2].Y := pntArray[2].Y + 5;
|
|
ArrRgn[3].X := pntArray[3].X - 5;
|
|
ArrRgn[3].Y := pntArray[3].Y + 5;
|
|
ArrRgn[4].X := pntArray[3].X + 5;
|
|
ArrRgn[4].Y := pntArray[3].Y - 5;
|
|
end;
|
|
if ((LnkX = 3) and (LnkY = 1)) or ((LnkX = 2) and (LnkY = 2)) then
|
|
begin
|
|
pntArray[1].X := Width - Hand;
|
|
pntArray[1].Y := Hand div 2;
|
|
pntArray[2].X := Width - 5;
|
|
pntArray[2].Y := Hand div 2;
|
|
pntArray[3].X := Hand;
|
|
pntArray[3].Y := Height - Hand div 2;
|
|
pntArray[4].X := 0;
|
|
pntArray[4].Y := Height - Hand div 2;
|
|
ArrRgn[1].X := pntArray[2].X - 5;
|
|
ArrRgn[1].Y := pntArray[2].Y - 5;
|
|
ArrRgn[2].X := pntArray[2].X + 5;
|
|
ArrRgn[2].Y := pntArray[2].Y + 5;
|
|
ArrRgn[3].X := pntArray[3].X + 5;
|
|
ArrRgn[3].Y := pntArray[3].Y + 5;
|
|
ArrRgn[4].X := pntArray[3].X - 5;
|
|
ArrRgn[4].Y := pntArray[3].Y - 5;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if ((LnkX = 2) and (LnkY = 1)) or ((LnkX = 3) and (LnkY = 2)) or
|
|
((LnkX = 3) and (LnkY = 1)) or ((LnkX = 2) and (LnkY = 2)) then
|
|
begin
|
|
pntArray[1].X := 0;
|
|
pntArray[1].Y := Hand div 2;
|
|
pntArray[2].X := Width - Hand2;
|
|
pntArray[2].Y := Hand div 2;
|
|
pntArray[3].X := Width - Hand2;
|
|
pntArray[3].Y := Height - Hand div 2;
|
|
pntArray[4].X := 0;
|
|
pntArray[4].Y := Height - Hand div 2;
|
|
ArrRgn[1].X := pntArray[2].X - 5;
|
|
ArrRgn[1].Y := pntArray[2].Y - 5;
|
|
ArrRgn[2].X := pntArray[2].X + 5;
|
|
ArrRgn[2].Y := pntArray[2].Y + 5;
|
|
ArrRgn[3].X := pntArray[3].X + 5;
|
|
ArrRgn[3].Y := pntArray[3].Y + 5;
|
|
ArrRgn[4].X := pntArray[3].X - 5;
|
|
ArrRgn[4].Y := pntArray[3].Y - 5;
|
|
end;
|
|
end;
|
|
if ((LnkX = 4) and (LnkY = 1)) or ((LnkX = 1) and (LnkY = 2)) then
|
|
begin
|
|
pntArray[1].X := Width;
|
|
pntArray[1].Y := Hand div 2;
|
|
pntArray[2].X := Width - Hand;
|
|
pntArray[2].Y := Hand div 2;
|
|
pntArray[3].X := Hand;
|
|
pntArray[3].Y := Height - Hand div 2;
|
|
pntArray[4].X := 0;
|
|
pntArray[4].Y := Height - Hand div 2;
|
|
ArrRgn[1].X := pntArray[2].X - 5;
|
|
ArrRgn[1].Y := pntArray[2].Y - 5;
|
|
ArrRgn[2].X := pntArray[2].X + 5;
|
|
ArrRgn[2].Y := pntArray[2].Y + 5;
|
|
ArrRgn[3].X := pntArray[3].X + 5;
|
|
ArrRgn[3].Y := pntArray[3].Y + 5;
|
|
ArrRgn[4].X := pntArray[3].X - 5;
|
|
ArrRgn[4].Y := pntArray[3].Y - 5;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
pntArray[1].X := 0;
|
|
pntArray[1].Y := Hand div 2;
|
|
pntArray[2].X := Hand - 5;
|
|
pntArray[2].Y := Hand div 2;
|
|
pntArray[3].X := Hand - 5;
|
|
pntArray[3].Y := Height - Hand div 2;
|
|
pntArray[4].X := 0;
|
|
pntArray[4].Y := Height - Hand div 2;
|
|
ArrRgn[1].X := pntArray[2].X + 5;
|
|
ArrRgn[1].Y := pntArray[2].Y - 5;
|
|
ArrRgn[2].X := pntArray[2].X - 5;
|
|
ArrRgn[2].Y := pntArray[2].Y + 5;
|
|
ArrRgn[3].X := pntArray[3].X - 5;
|
|
ArrRgn[3].Y := pntArray[3].Y + 5;
|
|
ArrRgn[4].X := pntArray[3].X + 5;
|
|
ArrRgn[4].Y := pntArray[3].Y - 5;
|
|
end;
|
|
|
|
Canvas.PolyLine(pntArray);
|
|
Canvas.Brush := Parent.Brush;
|
|
DeleteObject(Rgn);
|
|
ArrCnt := 4;
|
|
Rgn := CreatePolygonRgn(@ArrRgn, ArrCnt, ALTERNATE);
|
|
end;
|
|
|
|
procedure TOQBLink._Click(X, Y: Integer);
|
|
var
|
|
pnt: TPoint;
|
|
begin
|
|
pnt.X := X;
|
|
pnt.Y := Y;
|
|
pnt := ClientToScreen(pnt);
|
|
PopMenu.Popup(pnt.X, pnt.Y);
|
|
end;
|
|
|
|
procedure TOQBLink.CMHitTest(var Message: TCMHitTest);
|
|
begin
|
|
if PtInRegion(Rgn, Message.XPos, Message.YPos) then
|
|
Message.Result := 1;
|
|
end;
|
|
|
|
function TOQBLink.ControlAtPos(const Pos: TPoint): TControl;
|
|
var
|
|
I: Integer;
|
|
scrnP, P: TPoint;
|
|
begin
|
|
scrnP := ClientToScreen(Pos);
|
|
for I := Parent.ControlCount - 1 downto 0 do
|
|
begin
|
|
Result := Parent.Controls[I];
|
|
if (Result is TOQBLink) and (Result <> Self) then
|
|
with Result do
|
|
begin
|
|
P := Result.ScreenToClient(scrnP);
|
|
if Perform(CM_HITTEST, 0, Integer(PointToSmallPoint(P))) <> 0 then
|
|
Exit;
|
|
end;
|
|
end;
|
|
Result := nil;
|
|
end;
|
|
|
|
function TOQBLink.PtInRegion(RGN: HRGN; X, Y: Integer): Boolean;
|
|
{$IFDEF MSWINDOWS}
|
|
begin
|
|
Result := LCLIntf.PtInRegion(RGN, X, Y);
|
|
{$ELSE}
|
|
var
|
|
APoint : TPoint;
|
|
ARect : TRect;
|
|
begin
|
|
GetRgnBox(RGN, @ARect);
|
|
APoint.X := X;
|
|
APoint.Y := Y;
|
|
Result := LclIntf.PtInRect(ARect, APoint);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TOQBLink.WndProc(var Message: TLMessage);
|
|
begin
|
|
if (Message.Msg = LM_RBUTTONDOWN) or (Message.Msg = LM_LBUTTONDOWN) then
|
|
if not PtInRegion(Rgn, TLMMouse(Message).XPos, TLMMouse(Message).YPos) then
|
|
ControlAtPos(SmallPointToPoint(TLMMouse(Message).Pos)) else
|
|
_Click(TLMMouse(Message).XPos, TLMMouse(Message).YPos);
|
|
inherited;
|
|
end;
|
|
|
|
|
|
{ TOQBArea }
|
|
|
|
procedure TOQBArea.CreateParams(var Params: TCreateParams);
|
|
begin
|
|
inherited;
|
|
OnDragOver := _DragOver;
|
|
OnDragDrop := _DragDrop;
|
|
end;
|
|
|
|
procedure TOQBArea.SetOptions(Sender: TObject);
|
|
var
|
|
AForm: TOQBLinkForm;
|
|
ALink: TOQBLink;
|
|
begin
|
|
if TPopupMenu(Sender).Owner is TOQBLink then
|
|
begin
|
|
ALink := TOQBLink(TPopupMenu(Sender).Owner);
|
|
AForm := TOQBLinkForm.Create(Application);
|
|
AForm.txtTable1.Caption := ALink.tbl1.FTableName;
|
|
AForm.txtCol1.Caption := ALink.fldNam1;
|
|
AForm.txtTable2.Caption := ALink.tbl2.FTableName;
|
|
AForm.txtCol2.Caption := ALink.fldNam2;
|
|
AForm.RadioOpt.ItemIndex := ALink.FLinkOpt;
|
|
AForm.RadioType.ItemIndex := ALink.FLinkType;
|
|
if AForm.ShowModal = mrOk then
|
|
begin
|
|
ALink.FLinkOpt := AForm.RadioOpt.ItemIndex;
|
|
ALink.FLinkType := AForm.RadioType.ItemIndex;
|
|
end;
|
|
AForm.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBArea.InsertTable(X, Y: Integer);
|
|
var
|
|
NewTable: TOQBTable;
|
|
begin
|
|
if FindTable(TOQBForm(GetParentForm(Self)).QBTables.Items[
|
|
TOQBForm(GetParentForm(Self)).QBTables.ItemIndex]) <> nil then
|
|
begin
|
|
ShowMessage('This table is already inserted.');
|
|
Exit;
|
|
end;
|
|
|
|
NewTable := TOQBTable.Create(Self);
|
|
NewTable.Parent := Self;
|
|
try
|
|
NewTable.Activate(TOQBForm(GetParentForm(Self)).QBTables.Items[
|
|
TOQBForm(GetParentForm(Self)).QBTables.ItemIndex], X, Y);
|
|
except
|
|
NewTable.Free;
|
|
end;
|
|
end;
|
|
|
|
function TOQBArea.InsertLink(_tbl1, _tbl2: TOQBTable;
|
|
_fldN1, _fldN2: Integer): TOQBLink;
|
|
begin
|
|
Result := TOQBLink.Create(Self);
|
|
with Result do
|
|
begin
|
|
Parent := Self;
|
|
Application.ProcessMessages; // importante no gtk2
|
|
tbl1 := _tbl1;
|
|
tbl2 := _tbl2;
|
|
fldN1 := _fldN1;
|
|
fldN2 := _fldN2;
|
|
fldNam1 := tbl1.FLbx.Items[fldN1];
|
|
fldNam2 := tbl2.FLbx.Items[fldN2];
|
|
end;
|
|
if FindLink(Result) then
|
|
begin
|
|
ShowMessage('These tables are already linked.');
|
|
Result.Free;
|
|
Result := nil;
|
|
Exit;
|
|
end;
|
|
with Result do
|
|
begin
|
|
tbl1.FLbx.SelectItemBold(fldN1);
|
|
tbl1.FLbx.Refresh;
|
|
tbl2.FLbx.SelectItemBold(fldN2);
|
|
tbl2.FLbx.Refresh;
|
|
OnDragOver := _DragOver;
|
|
OnDragDrop := _DragDrop;
|
|
end;
|
|
ReboundLink(Result);
|
|
Result.Visible := True;
|
|
end;
|
|
|
|
function TOQBArea.FindTable(const TableName: string): TOQBTable;
|
|
var
|
|
i: Integer;
|
|
TempTable: TOQBTable;
|
|
begin
|
|
Result := nil;
|
|
for i := ControlCount - 1 downto 0 do
|
|
if Controls[i] is TOQBTable then
|
|
begin
|
|
TempTable := TOQBTable(Controls[i]);
|
|
if (TempTable.FTableName = TableName) then
|
|
begin
|
|
Result := TempTable;
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TOQBArea.FindLink(Link: TOQBLink): Boolean;
|
|
var
|
|
i: Integer;
|
|
TempLink: TOQBLink;
|
|
begin
|
|
Result := False;
|
|
for i := ControlCount - 1 downto 0 do
|
|
if Controls[i] is TOQBLink then
|
|
begin
|
|
TempLink := TOQBLink(Controls[i]);
|
|
if (TempLink <> Link) then
|
|
if (((TempLink.tbl1 = Link.tbl1) and (TempLink.fldN1 = Link.fldN1)) and
|
|
((TempLink.tbl2 = Link.tbl2) and (TempLink.fldN2 = Link.fldN2))) or
|
|
(((TempLink.tbl1 = Link.tbl2) and (TempLink.fldN1 = Link.fldN2)) and
|
|
((TempLink.tbl2 = Link.tbl1) and (TempLink.fldN2 = Link.fldN1))) then
|
|
begin
|
|
Result := True;
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TOQBArea.FindOtherLink(Link: TOQBLink; Tbl: TOQBTable;
|
|
FldN: Integer): Boolean;
|
|
var
|
|
i: Integer;
|
|
OtherLink: TOQBLink;
|
|
begin
|
|
Result := False;
|
|
for i := ControlCount - 1 downto 0 do
|
|
if Controls[i] is TOQBLink then
|
|
begin
|
|
OtherLink := TOQBLink(Controls[i]);
|
|
if (OtherLink <> Link) then
|
|
if ((OtherLink.tbl1 = Tbl) and (OtherLink.fldN1 = FldN)) or
|
|
((OtherLink.tbl2 = Tbl) and (OtherLink.fldN2 = FldN)) then
|
|
begin
|
|
Result := True;
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBArea.ReboundLink(Link: TOQBLink);
|
|
var
|
|
X1, X2, Y1, Y2: Integer;
|
|
begin
|
|
Link.PopMenu.Items[0].Caption := Link.tbl1.FTableName + ' :: ' +
|
|
Link.tbl2.FTableName;
|
|
with Link do
|
|
begin
|
|
if Tbl1 = Tbl2 then
|
|
begin
|
|
X1 := Tbl1.Left + Tbl1.Width;
|
|
X2 := Tbl1.Left + Tbl1.Width + Hand;
|
|
end
|
|
else
|
|
begin
|
|
if Tbl1.Left < Tbl2.Left then
|
|
begin
|
|
if Tbl1.Left + Tbl1.Width + Hand < Tbl2.Left then
|
|
begin //A
|
|
X1 := Tbl1.Left + Tbl1.Width;
|
|
X2 := Tbl2.Left;
|
|
LnkX := 1;
|
|
end
|
|
else
|
|
begin //B
|
|
if Tbl1.Left + Tbl1.Width > Tbl2.Left + Tbl2.Width then
|
|
begin
|
|
X1 := Tbl2.Left + Tbl2.Width;
|
|
X2 := Tbl1.Left + Tbl1.Width + Hand;
|
|
LnkX := 3;
|
|
end
|
|
else
|
|
begin
|
|
X1 := Tbl1.Left + Tbl1.Width;
|
|
X2 := Tbl2.Left + Tbl2.Width + Hand;
|
|
LnkX := 2;
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if Tbl2.Left + Tbl2.Width + Hand > Tbl1.Left then
|
|
begin //C
|
|
if Tbl2.Left + Tbl2.Width > Tbl1.Left + Tbl1.Width then
|
|
begin
|
|
X1 := Tbl1.Left + Tbl1.Width;
|
|
X2 := Tbl2.Left + Tbl2.Width + Hand;
|
|
LnkX := 2;
|
|
end
|
|
else
|
|
begin
|
|
X1 := Tbl2.Left + Tbl2.Width;
|
|
X2 := Tbl1.Left + Tbl1.Width + Hand;
|
|
LnkX := 3;
|
|
end;
|
|
end
|
|
else
|
|
begin //D
|
|
X1 := Tbl2.Left + Tbl2.Width;
|
|
X2 := Tbl1.Left;
|
|
LnkX := 4;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Y1 := Tbl1.GetRowY(FldN1);
|
|
Y2 := Tbl2.GetRowY(FldN2);
|
|
if Y1 < Y2 then
|
|
begin //M
|
|
Y1 := Tbl1.GetRowY(FldN1) - Hand div 2;
|
|
Y2 := Tbl2.GetRowY(FldN2) + Hand div 2;
|
|
LnkY := 1;
|
|
end
|
|
else
|
|
begin //N
|
|
Y2 := Tbl1.GetRowY(FldN1) + Hand div 2;
|
|
Y1 := Tbl2.GetRowY(FldN2) - Hand div 2;
|
|
LnkY := 2;
|
|
end;
|
|
SetBounds(X1, Y1, X2 - X1, Y2 - Y1);
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBArea.ReboundLinks4Table(ATable: TOQBTable);
|
|
var
|
|
i: Integer;
|
|
Link: TOQBLink;
|
|
begin
|
|
for i := 0 to ControlCount - 1 do
|
|
begin
|
|
if Controls[i] is TOQBLink then
|
|
begin
|
|
Link := TOQBLink(Controls[i]);
|
|
if (Link.Tbl1 = ATable) or (Link.Tbl2 = ATable) then
|
|
ReboundLink(Link);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBArea.Unlink(Sender: TObject);
|
|
var
|
|
Link: TOQBLink;
|
|
begin
|
|
if TPopupMenu(Sender).Owner is TOQBLink then
|
|
begin
|
|
Link := TOQBLink(TPopupMenu(Sender).Owner);
|
|
RemoveControl(Link);
|
|
|
|
if not FindOtherLink(Link, Link.tbl1, Link.fldN1) then
|
|
begin
|
|
Link.tbl1.FLbx.UnSelectItemBold(Link.fldN1);
|
|
Link.tbl1.FLbx.Refresh;
|
|
end;
|
|
if not FindOtherLink(Link, Link.tbl2, Link.fldN2) then
|
|
begin
|
|
Link.tbl2.FLbx.UnSelectItemBold(Link.fldN2);
|
|
Link.tbl2.FLbx.Refresh;
|
|
end;
|
|
|
|
Link.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBArea.UnlinkTable(ATable: TOQBTable);
|
|
var
|
|
i: Integer;
|
|
TempLink: TOQBLink;
|
|
begin
|
|
for i := ControlCount - 1 downto 0 do
|
|
begin
|
|
if Controls[i] is TOQBLink then
|
|
begin
|
|
TempLink := TOQBLink(Controls[i]);
|
|
|
|
if (TempLink.Tbl1 = ATable) or (TempLink.Tbl2 = ATable) then
|
|
begin
|
|
RemoveControl(TempLink);
|
|
if not FindOtherLink(TempLink, TempLink.tbl1, TempLink.fldN1) then
|
|
begin
|
|
TempLink.tbl1.FLbx.UnSelectItemBold(TempLink.fldN1);
|
|
TempLink.tbl1.FLbx.Refresh;
|
|
end;
|
|
if not FindOtherLink(TempLink, TempLink.tbl2, TempLink.fldN2) then
|
|
begin
|
|
TempLink.tbl2.FLbx.UnSelectItemBold(TempLink.fldN2);
|
|
TempLink.tbl2.FLbx.Refresh;
|
|
end;
|
|
|
|
TempLink.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBArea._DragOver(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
begin
|
|
if (Source = TOQBForm(GetParentForm(Self)).QBTables) then
|
|
Accept := True;
|
|
end;
|
|
|
|
procedure TOQBArea._DragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
begin
|
|
if not (Sender is TOQBArea) then
|
|
begin
|
|
X := X + TControl(Sender).Left;
|
|
Y := Y + TControl(Sender).Top;
|
|
end;
|
|
|
|
if Source = TOQBForm(GetParentForm(Self)).QBTables then
|
|
InsertTable(X, Y);
|
|
end;
|
|
|
|
|
|
{ TOQBGrid }
|
|
|
|
procedure TOQBGrid.CreateParams(var Params: TCreateParams);
|
|
begin
|
|
inherited;
|
|
FocusRectVisible := False;
|
|
DefaultColWidth := 64;
|
|
Options := [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine,
|
|
goColSizing, goColMoving];
|
|
ColCount := 2;
|
|
RowCount := 6;
|
|
Height := Parent.ClientHeight;
|
|
// DefaultRowHeight := Parent.Height div (6 + 1) - GridLineWidth;
|
|
DefaultRowHeight := 20;
|
|
Cells[0, cFld] := 'Field';
|
|
Cells[0, cTbl] := 'Table';
|
|
Cells[0, cShow] := 'Show';
|
|
Cells[0, cSort] := 'Sort';
|
|
Cells[0, cFunc] := 'Function';
|
|
Cells[0, cGroup] := 'Group';
|
|
OnDragOver := _DragOver;
|
|
OnDragDrop := _DragDrop;
|
|
IsEmpty := True;
|
|
end;
|
|
|
|
procedure TOQBGrid.WndProc(var Message: TLMessage);
|
|
begin
|
|
if (Message.Msg = LM_RBUTTONDOWN) then
|
|
ClickCell(TLMMouse(Message).XPos, TLMMouse(Message).YPos);
|
|
inherited;
|
|
end;
|
|
|
|
function TOQBGrid.MaxSW(const s1, s2: string): Integer;
|
|
begin
|
|
Result := Canvas.TextWidth(s1);
|
|
if Result < Canvas.TextWidth(s2) then
|
|
Result := Canvas.TextWidth(s2);
|
|
end;
|
|
|
|
procedure TOQBGrid.InsertDefault(aCol: Integer);
|
|
begin
|
|
Cells[aCol, cShow] := sShow;
|
|
Cells[aCol, cSort] := '';
|
|
Cells[aCol, cFunc] := '';
|
|
Cells[aCol, cGroup] := '';
|
|
end;
|
|
|
|
procedure TOQBGrid.Insert(aCol: Integer; const aField, aTable: string);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if IsEmpty then
|
|
begin
|
|
IsEmpty := False;
|
|
aCol := 1;
|
|
Cells[aCol, cFld] := aField;
|
|
Cells[aCol, cTbl] := aTable;
|
|
InsertDefault(aCol);
|
|
end
|
|
else
|
|
begin
|
|
if aCol = -1 then
|
|
begin
|
|
ColCount := ColCount + 1;
|
|
aCol := ColCount - 1;
|
|
Cells[aCol, cFld] := aField;
|
|
Cells[aCol, cTbl] := aTable;
|
|
InsertDefault(aCol);
|
|
end
|
|
else
|
|
begin
|
|
ColCount := ColCount + 1;
|
|
for i := ColCount - 1 downto aCol + 1 do
|
|
MoveColRow(True,i - 1, i);
|
|
Cells[aCol, cFld] := aField;
|
|
Cells[aCol, cTbl] := aTable;
|
|
InsertDefault(aCol);
|
|
end;
|
|
//* Fix StringGrid Bug *
|
|
if aCol > 1 then
|
|
ColWidths[aCol - 1] := MaxSW(Cells[aCol - 1, cFld], Cells[aCol - 1, cTbl]) + 8;
|
|
if aCol < ColCount - 1 then
|
|
ColWidths[aCol + 1] := MaxSW(Cells[aCol + 1, cFld], Cells[aCol + 1, cTbl]) + 8;
|
|
ColWidths[ColCount - 1] := MaxSW(Cells[ColCount - 1, cFld],
|
|
Cells[ColCount - 1, cTbl]) + 8;
|
|
end;
|
|
|
|
ColWidths[aCol] := MaxSW(aTable, aField) + 8;
|
|
end;
|
|
|
|
function TOQBGrid.FindColumn(const sCol: string): Integer;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result := -1;
|
|
for i := 1 to ColCount - 1 do
|
|
if Cells[i, cFld] = sCol then
|
|
begin
|
|
Result := i;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
function TOQBGrid.FindSameColumn(aCol: Integer): Boolean;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result := False;
|
|
for i := 1 to ColCount - 1 do
|
|
if i = aCol then
|
|
Continue
|
|
else if Cells[i, cFld] = Cells[aCol, cFld] then
|
|
begin
|
|
Result := True;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBGrid.RemoveColumn(aCol: Integer);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if (ColCount > 2) then
|
|
DeleteCol(aCol)
|
|
else
|
|
begin
|
|
for i := 0 to RowCount - 1 do
|
|
Cells[1, i] := '';
|
|
IsEmpty := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBGrid.RemoveColumn4Tbl(const Tbl: string);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := ColCount - 1 downto 1 do
|
|
if Cells[i, cTbl] = Tbl then
|
|
RemoveColumn(i);
|
|
end;
|
|
|
|
procedure TOQBGrid.ClickCell(X, Y: Integer);
|
|
var
|
|
P: TPoint;
|
|
mCol, mRow: Integer;
|
|
begin
|
|
MouseToCell(X, Y, mCol, mRow);
|
|
CurrCol := mCol;
|
|
P.X := X;
|
|
P.Y := Y;
|
|
P := ClientToScreen(P);
|
|
if (mCol > 0) and (mCol < ColCount) and (not IsEmpty) then
|
|
begin
|
|
if (Cells[mCol, 0] = '*') and (mRow <> cFld) then
|
|
Exit;
|
|
case mRow of
|
|
cFld:
|
|
TOQBForm(GetParentForm(Self)).mnuTbl.Popup(P.X, P.Y);
|
|
cShow:
|
|
begin
|
|
TOQBForm(GetParentForm(Self)).mnuShow.Items[0].Checked := Cells[mCol, cShow] = sShow;
|
|
TOQBForm(GetParentForm(Self)).mnuShow.Popup(P.X, P.Y);
|
|
end;
|
|
cSort:
|
|
begin
|
|
if Cells[mCol, cSort] = sSort[1] then
|
|
TOQBForm(GetParentForm(Self)).mnuSort.Items[0].Checked := True
|
|
else if Cells[mCol, cSort] = sSort[2] then
|
|
TOQBForm(GetParentForm(Self)).mnuSort.Items[2].Checked := True else
|
|
TOQBForm(GetParentForm(Self)).mnuSort.Items[3].Checked := True;
|
|
TOQBForm(GetParentForm(Self)).mnuSort.Popup(P.X, P.Y);
|
|
end;
|
|
cFunc:
|
|
begin
|
|
if Cells[mCol, cFunc] = sFunc[1] then
|
|
TOQBForm(GetParentForm(Self)).mnuFunc.Items[0].Checked := True
|
|
else if Cells[mCol, cFunc] = sFunc[2] then
|
|
TOQBForm(GetParentForm(Self)).mnuFunc.Items[2].Checked := True
|
|
else if Cells[mCol, cFunc] = sFunc[3] then
|
|
TOQBForm(GetParentForm(Self)).mnuFunc.Items[3].Checked := True
|
|
else if Cells[mCol, cFunc] = sFunc[4] then
|
|
TOQBForm(GetParentForm(Self)).mnuFunc.Items[4].Checked := True
|
|
else if Cells[mCol, cFunc] = sFunc[5] then
|
|
TOQBForm(GetParentForm(Self)).mnuFunc.Items[5].Checked := True
|
|
else
|
|
TOQBForm(GetParentForm(Self)).mnuFunc.Items[6].Checked := True;
|
|
TOQBForm(GetParentForm(Self)).mnuFunc.Popup(P.X, P.Y);
|
|
end;
|
|
cGroup:
|
|
begin
|
|
TOQBForm(GetParentForm(Self)).mnuGroup.Items[0].Checked := Cells[mCol, cGroup] = sGroup;
|
|
TOQBForm(GetParentForm(Self)).mnuGroup.Popup(P.X, P.Y);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TOQBGrid.SelectCell(ACol, ARow: Integer): Boolean;
|
|
begin
|
|
inherited SelectCell(ACol, ARow);
|
|
Result := ARow > cGroup;
|
|
end;
|
|
|
|
procedure TOQBGrid._DragOver(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
begin
|
|
if (Source <> TOQBForm(GetParentForm(Self)).QBTables) then
|
|
Accept := True;
|
|
end;
|
|
|
|
procedure TOQBGrid._DragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
var
|
|
dCol, dRow: Integer;
|
|
begin
|
|
if ((Source is TOQBLbx) and
|
|
(Source <> TOQBForm(GetParentForm(Self)).QBTables)) then
|
|
begin
|
|
TOQBTable(TWinControl(Source).Parent).FLbx.Checked[
|
|
TOQBTable(TWinControl(Source).Parent).FLbx.ItemIndex] := True;//*** check
|
|
MouseToCell(X, Y, dCol, dRow);
|
|
if dCol = 0 then
|
|
Exit;
|
|
Insert(dCol,
|
|
TOQBTable(TWinControl(Source).Parent).FLbx.Items[TOQBTable(TWinControl(Source).Parent).FLbx.ItemIndex],
|
|
TOQBTable(TWinControl(Source).Parent).FTableName);
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TOQBForm }
|
|
|
|
procedure TOQBForm.CreateParams(var Params: TCreateParams);
|
|
begin
|
|
inherited;
|
|
QBArea := TOQBArea.Create(Self);
|
|
QBArea.Parent := QBPanel;
|
|
QBArea.Align := alClient;
|
|
QBArea.Color := $009E9E9E;
|
|
QBGrid := TOQBGrid.Create(Self);
|
|
QBGrid.DefaultRowHeight := 22;
|
|
QBGrid.DefaultColWidth := 150;
|
|
QBGrid.Parent := TabColumns;
|
|
QBGrid.Align := alClient;
|
|
VSplitter.Tag := VSplitter.Left;
|
|
HSplitter.Tag := HSplitter.Top;
|
|
Application.ProcessMessages;
|
|
end;
|
|
|
|
procedure TOQBForm.mnuFunctionClick(Sender: TObject);
|
|
var
|
|
Item: TMenuItem;
|
|
begin
|
|
if Sender is TMenuItem then
|
|
begin
|
|
Item := (Sender as TMenuItem);
|
|
if not Item.Checked then
|
|
begin
|
|
Item.Checked := True;
|
|
QBGrid.Cells[QBGrid.CurrCol, cFunc] := sFunc[Item.Tag];
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBForm.mnuGroupClick(Sender: TObject);
|
|
begin
|
|
if mnuGroup.Items[0].Checked then
|
|
begin
|
|
QBGrid.Cells[QBGrid.CurrCol, cGroup] := '';
|
|
mnuGroup.Items[0].Checked := False;
|
|
end
|
|
else
|
|
begin
|
|
QBGrid.Cells[QBGrid.CurrCol, cGroup] := sGroup;
|
|
mnuGroup.Items[0].Checked := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBForm.mnuRemoveClick(Sender: TObject);
|
|
var
|
|
TempTable: TOQBTable;
|
|
begin
|
|
TempTable := QBArea.FindTable(QBGrid.Cells[QBGrid.CurrCol, cTbl]);
|
|
if not QBGrid.FindSameColumn(QBGrid.CurrCol) then
|
|
TempTable.FLbx.Checked[TempTable.FLbx.Items.IndexOf(QBGrid.Cells[QBGrid.CurrCol, cFld])] := False;
|
|
QBGrid.RemoveColumn(QBGrid.CurrCol);
|
|
QBGrid.Refresh; // fix for StringGrid bug
|
|
end;
|
|
|
|
procedure TOQBForm.mnuShowClick(Sender: TObject);
|
|
begin
|
|
if mnuShow.Items[0].Checked then
|
|
begin
|
|
QBGrid.Cells[QBGrid.CurrCol, cShow] := '';
|
|
mnuShow.Items[0].Checked := False;
|
|
end
|
|
else
|
|
begin
|
|
QBGrid.Cells[QBGrid.CurrCol, cShow] := sShow;
|
|
mnuShow.Items[0].Checked := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBForm.mnuSortClick(Sender: TObject);
|
|
var
|
|
Item: TMenuItem;
|
|
begin
|
|
if Sender is TMenuItem then
|
|
begin
|
|
Item := (Sender as TMenuItem);
|
|
if not Item.Checked then
|
|
begin
|
|
Item.Checked := True;
|
|
QBGrid.Cells[QBGrid.CurrCol, cSort] := sSort[Item.Tag];
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBForm.ClearAll;
|
|
var
|
|
i: Integer;
|
|
TempTable: TOQBTable;
|
|
begin
|
|
for i := QBArea.ControlCount - 1 downto 0 do
|
|
if QBArea.Controls[i] is TOQBTable then
|
|
begin
|
|
TempTable := TOQBTable(QBArea.Controls[i]);
|
|
QBGrid.RemoveColumn4Tbl(TempTable.FTableName);
|
|
TempTable.Free;
|
|
end
|
|
else
|
|
QBArea.Controls[i].Free; // QBLink
|
|
|
|
MemoSQL.Lines.Clear;
|
|
QBDialog.OQBEngine.ResultQuery.Close;
|
|
QBDialog.OQBEngine.ClearQuerySQL;
|
|
Pages.ActivePage := TabColumns;
|
|
end;
|
|
|
|
procedure TOQBForm.btnNewClick(Sender: TObject);
|
|
begin
|
|
ClearAll;
|
|
end;
|
|
|
|
procedure TOQBForm.btnOpenClick(Sender: TObject);
|
|
var
|
|
i, ii, j: Integer;
|
|
s, ss: string;
|
|
TempDatabaseName: string;
|
|
ShowSystemTables: Boolean;
|
|
NewTable: TOQBTable;
|
|
TableName: string;
|
|
X, Y: Integer;
|
|
NewLink: TOQBLink;
|
|
Table1, Table2: TOQBTable;
|
|
FieldN1, FieldN2: Integer;
|
|
ColField, ColTable: string;
|
|
StrList: TStringList;
|
|
|
|
function GetNextVal(var s: string): string;
|
|
var
|
|
p: Integer;
|
|
begin
|
|
Result := EmptyStr;
|
|
p := Pos(',', s);
|
|
if p = 0 then
|
|
begin
|
|
p := Pos(';', s);
|
|
if p = 0 then
|
|
Exit;
|
|
end;
|
|
Result := System.Copy(s, 1, p - 1);
|
|
System.Delete(s, 1, p);
|
|
end;
|
|
|
|
begin
|
|
j := -1;
|
|
if not DlgOpen.Execute then
|
|
Exit;
|
|
StrList := TStringList.Create;
|
|
StrList.LoadFromFile(DlgOpen.FileName);
|
|
if StrList[0] <> QBSignature then
|
|
begin
|
|
ShowMessage('File ' + DlgOpen.FileName + ' is not QBuilder''s query file.');
|
|
StrList.Free;
|
|
Exit;
|
|
end;
|
|
|
|
ClearAll;
|
|
try
|
|
s := StrList[3]; // read options
|
|
if s = '+' then
|
|
WindowState := wsMaximized
|
|
else
|
|
begin
|
|
WindowState := wsNormal;
|
|
Top := StrToInt(GetNextVal(s));
|
|
Left := StrToInt(GetNextVal(s));
|
|
Height := StrToInt(GetNextVal(s));
|
|
Width := StrToInt(GetNextVal(s));
|
|
end;
|
|
|
|
s := StrList[4];
|
|
btnTables.Down := Boolean(StrToInt(GetNextVal(s)));
|
|
VSplitter.Visible := btnTables.Down;
|
|
QBTables.Visible := btnTables.Down;
|
|
QBTables.Width := StrToInt(GetNextVal(s));
|
|
btnPages.Down := Boolean(StrToInt(GetNextVal(s)));
|
|
HSplitter.Visible := btnPages.Down;
|
|
Pages.Visible := btnPages.Down;
|
|
Pages.Height := StrToInt(GetNextVal(s));
|
|
|
|
s := StrList[6]; // read database
|
|
TempDatabaseName := GetNextVal(s);
|
|
ShowSystemTables := Boolean(StrToInt(GetNextVal(s)));
|
|
|
|
QBDialog.OQBEngine.DatabaseName := TempDatabaseName;
|
|
QBDialog.OQBEngine.ShowSystemTables := ShowSystemTables;
|
|
OpenDatabase;
|
|
|
|
for i := 8 to StrList.Count - 1 do // read tables
|
|
begin
|
|
if StrList[i] = '[Links]' then
|
|
begin
|
|
j := i + 1;
|
|
Break;
|
|
end;
|
|
s := StrList[i];
|
|
TableName := GetNextVal(s);
|
|
Y := StrToInt(GetNextVal(s));
|
|
X := StrToInt(GetNextVal(s));
|
|
NewTable := TOQBTable.Create(Self);
|
|
NewTable.Parent := QBArea;
|
|
try
|
|
NewTable.Activate(TableName, X, Y);
|
|
NewTable.FLbx.FLoading := True;
|
|
for ii := 0 to NewTable.FLbx.Items.Count - 1 do
|
|
begin
|
|
ss := GetNextVal(s);
|
|
if ss <> EmptyStr then
|
|
NewTable.FLbx.Checked[ii] := Boolean(StrToInt(ss));
|
|
end;
|
|
NewTable.FLbx.FLoading := False;
|
|
except
|
|
NewTable.Free;
|
|
end;
|
|
end;
|
|
|
|
if j <> -1 then
|
|
for i := j to StrList.Count - 1 do // read links
|
|
begin
|
|
if StrList[i] = '[Columns]' then
|
|
begin
|
|
j := i + 1;
|
|
Break;
|
|
end;
|
|
s := StrList[i];
|
|
ss := GetNextVal(s);
|
|
Table1 := QBArea.FindTable(ss);
|
|
ss := GetNextVal(s);
|
|
FieldN1 := StrToInt(ss);
|
|
ss := GetNextVal(s);
|
|
Table2 := QBArea.FindTable(ss);
|
|
ss := GetNextVal(s);
|
|
FieldN2 := StrToInt(ss);
|
|
NewLink := QBArea.InsertLink(Table1, Table2, FieldN1, FieldN2);
|
|
ss := GetNextVal(s);
|
|
NewLink.FLinkOpt := StrToInt(ss);
|
|
ss := GetNextVal(s);
|
|
NewLink.FLinkType := StrToInt(ss);
|
|
end;
|
|
|
|
if j <> -1 then
|
|
for i := j to StrList.Count - 1 do // read columns
|
|
begin
|
|
if StrList[i] = '[End]' then
|
|
Break;
|
|
s := StrList[i];
|
|
ii := StrToInt(GetNextVal(s));
|
|
ColField := GetNextVal(s);
|
|
ColTable := GetNextVal(s);
|
|
QBGrid.Insert(ii, ColField, ColTable);
|
|
QBGrid.Cells[ii, cShow] := GetNextVal(s);
|
|
QBGrid.Cells[ii, cSort] := GetNextVal(s);
|
|
QBGrid.Cells[ii, cFunc] := GetNextVal(s);
|
|
QBGrid.Cells[ii, cGroup] := GetNextVal(s);
|
|
end;
|
|
|
|
finally
|
|
StrList.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBForm.btnSaveClick(Sender: TObject);
|
|
var
|
|
i, j: Integer;
|
|
s: string;
|
|
TempTable: TOQBTable;
|
|
TempLink: TOQBLink;
|
|
StrList: TStringList;
|
|
begin
|
|
if not DlgSave.Execute then Exit;
|
|
StrList := TStringList.Create;
|
|
StrList.Add(QBSignature);
|
|
StrList.Add('# Don''t change this file !');
|
|
StrList.Add('[Options]');
|
|
if WindowState = wsMaximized then
|
|
s := '+' else
|
|
s := IntToStr(Top) + ',' + IntToStr(Left) + ',' + IntToStr(Height) + ',' +
|
|
IntToStr(Width) + ';';
|
|
StrList.Add(s);
|
|
s := IntToStr(Integer(btnTables.Down)) + ',' + IntToStr(QBTables.Width) +
|
|
',' + IntToStr(Integer(btnPages.Down)) + ',' + IntToStr(Pages.Height) + ';';
|
|
StrList.Add(s);
|
|
|
|
StrList.Add('[Database]');
|
|
s := QBDialog.OQBEngine.DatabaseName + ',' + IntToStr(Integer(QBDialog.OQBEngine.ShowSystemTables)) + ';';
|
|
StrList.Add(s);
|
|
|
|
StrList.Add('[Tables]'); // save tables
|
|
for i := 0 to QBArea.ControlCount - 1 do
|
|
if QBArea.Controls[i] is TOQBTable then
|
|
begin
|
|
TempTable := TOQBTable(QBArea.Controls[i]);
|
|
s := TempTable.FTableName + ',' +
|
|
IntToStr(TempTable.Top + QBArea.VertScrollBar.ScrollPos) + ',' +
|
|
IntToStr(TempTable.Left + QBArea.HorzScrollBar.ScrollPos);
|
|
for j := 0 to TempTable.FLbx.Items.Count - 1 do
|
|
if TempTable.FLbx.Checked[j] then
|
|
s := s + ',1' else
|
|
s := s + ',0';
|
|
s := s + ';';
|
|
StrList.Add(s);
|
|
end;
|
|
|
|
StrList.Add('[Links]'); // save links
|
|
for i := 0 to QBArea.ControlCount - 1 do
|
|
if QBArea.Controls[i] is TOQBLink then
|
|
begin
|
|
TempLink := TOQBLink(QBArea.Controls[i]);
|
|
s := TempLink.Tbl1.FTableName + ',' + IntToStr(TempLink.FldN1) + ',' +
|
|
TempLink.Tbl2.FTableName + ',' + IntToStr(TempLink.FldN2) + ',' +
|
|
IntToStr(TempLink.FLinkOpt) + ',' + IntToStr(TempLink.FLinkType);
|
|
s := s + ';';
|
|
StrList.Add(s);
|
|
end;
|
|
|
|
StrList.Add('[Columns]'); // save columns
|
|
if not QBGrid.IsEmpty then
|
|
for i := 1 to QBGrid.ColCount - 1 do
|
|
begin
|
|
s := IntToStr(i) + ',' + QBGrid.Cells[i, cFld] + ',' + QBGrid.Cells[i, cTbl];
|
|
s := s + ',' + QBGrid.Cells[i, cShow] + ',' + QBGrid.Cells[i, cSort] +
|
|
',' + QBGrid.Cells[i, cFunc] + ',' + QBGrid.Cells[i, cGroup];
|
|
s := s + ';';
|
|
StrList.Add(s);
|
|
end;
|
|
|
|
StrList.Add('[End]'); // end of QBuilder information
|
|
|
|
StrList.SaveToFile(DlgSave.FileName);
|
|
StrList.Free;
|
|
end;
|
|
|
|
procedure TOQBForm.btnTablesClick(Sender: TObject);
|
|
begin
|
|
VSplitter.Visible := TToolButton(Sender).Down;
|
|
QBTables.Visible := TToolButton(Sender).Down;
|
|
if not VSplitter.Visible then
|
|
VSplitter.Tag := VSplitter.Left
|
|
else
|
|
VSplitter.Left := VSplitter.Tag;
|
|
end;
|
|
|
|
procedure TOQBForm.btnPagesClick(Sender: TObject);
|
|
begin
|
|
HSplitter.Visible := TToolButton(Sender).Down;
|
|
Pages.Visible := TToolButton(Sender).Down;
|
|
if not HSplitter.Visible then
|
|
HSplitter.Tag := HSplitter.Top
|
|
else
|
|
HSplitter.Top := HSplitter.Tag;
|
|
end;
|
|
|
|
procedure TOQBForm.OpenDatabase;
|
|
begin
|
|
try
|
|
QBDialog.OQBEngine.ReadTableList;
|
|
QBDialog.OQBEngine.GenerateAliases;
|
|
QBTables.Items.Assign(QBDialog.OQBEngine.TableList);
|
|
ResDataSource.DataSet := QBDialog.OQBEngine.ResultQuery;
|
|
Caption := sMainCaption + ' [' + QBDialog.OQBEngine.DatabaseName + ']';
|
|
except
|
|
// ignore errors
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBForm.SelectDatabase;
|
|
begin
|
|
if QBDialog.OQBEngine.SelectDatabase then
|
|
begin
|
|
ClearAll;
|
|
QBTables.Items.Clear;
|
|
OpenDatabase;
|
|
end
|
|
end;
|
|
|
|
procedure TOQBForm.btnDBClick(Sender: TObject);
|
|
begin
|
|
SelectDatabase;
|
|
end;
|
|
|
|
procedure TOQBForm.btnSQLClick(Sender: TObject);
|
|
var
|
|
Lst, Lst1, Lst2: TStringList; // temporary string lists
|
|
i: Integer;
|
|
s: string;
|
|
tbl1, tbl2: string;
|
|
Link: TOQBLink;
|
|
|
|
function ExtractName(s: string):string;
|
|
var
|
|
p: Integer;
|
|
begin
|
|
Result := s;
|
|
p := Pos('.', s);
|
|
if p = 0 then
|
|
Exit;
|
|
Result := System.Copy(s, 1, p - 1);
|
|
end;
|
|
begin
|
|
if QBGrid.IsEmpty then
|
|
begin
|
|
ShowMessage('Columns are not selected.');
|
|
Exit;
|
|
end;
|
|
Lst := TStringList.Create;
|
|
try
|
|
with QBDialog.OQBEngine do
|
|
begin
|
|
SQLcolumns.Clear;
|
|
SQLcolumns_func.Clear;
|
|
SQLcolumns_table.Clear;
|
|
SQLfrom.Clear;
|
|
SQLwhere.Clear;
|
|
SQLgroupby.Clear;
|
|
SQLorderby.Clear;
|
|
end;
|
|
|
|
// SELECT clause
|
|
with QBGrid do
|
|
begin
|
|
for i := 1 to ColCount - 1 do
|
|
if Cells[i, cShow] = sShow then
|
|
begin
|
|
if QBDialog.OQBEngine.UseTableAliases then
|
|
tbl1 := QBDialog.OQBEngine.AliasList[QBDialog.OQBEngine.TableList.IndexOf(Cells[i, cTbl])]
|
|
else
|
|
tbl1 := Cells[i, cTbl];
|
|
s := tbl1 + '.' + Cells[i, cFld];
|
|
Lst.Add(LowerCase(s));
|
|
if Cells[i, cFunc] <> EmptyStr then
|
|
s := UpperCase(Cells[i, cFunc]) else
|
|
s := EmptyStr;
|
|
if QBDialog.OQBEngine.UseTableAliases then
|
|
QBDialog.OQBEngine.SQLcolumns_table.Add(LowerCase(
|
|
QBDialog.OQBEngine.AliasList[QBDialog.OQBEngine.TableList.IndexOf(Cells[i, cTbl])]))
|
|
else
|
|
QBDialog.OQBEngine.SQLcolumns_table.Add(LowerCase(Cells[i, cTbl]));
|
|
QBDialog.OQBEngine.SQLcolumns_func.Add(s);
|
|
end;
|
|
|
|
if Lst.Count = 0 then
|
|
begin
|
|
ShowMessage('Columns are not selected.');
|
|
Lst.Free;
|
|
Exit;
|
|
end;
|
|
QBDialog.OQBEngine.SQLcolumns.Assign(Lst);
|
|
Lst.Clear;
|
|
end;
|
|
|
|
// FROM clause
|
|
with QBArea do
|
|
begin
|
|
Lst1 := TSTringList.Create; // tables in joins
|
|
Lst2 := TSTringList.Create; // outer joins
|
|
for i := 0 to ControlCount - 1 do // search tables for joins
|
|
if Controls[i] is TOQBLink then
|
|
begin
|
|
Link := TOQBLink(Controls[i]);
|
|
if Link.FLinkType > 0 then
|
|
begin
|
|
if QBDialog.OQBEngine.UseTableAliases then
|
|
begin
|
|
tbl1 := LowerCase(Link.Tbl1.FTableAlias);
|
|
tbl2 := LowerCase(Link.Tbl2.FTableAlias);
|
|
end
|
|
else
|
|
begin
|
|
tbl1 := LowerCase(Link.Tbl1.FTableName);
|
|
tbl2 := LowerCase(Link.Tbl2.FTableName);
|
|
end;
|
|
if Lst1.IndexOf(tbl1) = -1 then
|
|
Lst1.Add(tbl1);
|
|
if Lst1.IndexOf(tbl2) = -1 then
|
|
Lst1.Add(tbl2);
|
|
if QBDialog.OQBEngine.UseTableAliases then
|
|
Lst2.Add(LowerCase(Link.Tbl1.FTableName) + ' ' + tbl1 +
|
|
sOuterJoin[Link.FLinkType] +
|
|
LowerCase(Link.Tbl2.FTableName) + ' ' + tbl2 + ' ON ' +
|
|
tbl1 + '.' + LowerCase(Link.FldNam1) + sLinkOpt[Link.FLinkOpt] +
|
|
tbl2 + '.' + LowerCase(Link.FldNam2))
|
|
else
|
|
Lst2.Add(tbl1 + sOuterJoin[Link.FLinkType] + tbl2 + ' ON ' +
|
|
tbl1 + '.' + LowerCase(Link.FldNam1) +
|
|
sLinkOpt[Link.FLinkOpt] + tbl2 + '.' + LowerCase(Link.FldNam2));
|
|
end;
|
|
end;
|
|
|
|
for i := 0 to ControlCount - 1 do
|
|
if Controls[i] is TOQBTable then
|
|
begin
|
|
if QBDialog.OQBEngine.UseTableAliases then
|
|
tbl1 := LowerCase(TOQBTable(Controls[i]).FTableAlias) else
|
|
tbl1 := LowerCase(TOQBTable(Controls[i]).FTableName);
|
|
if (Lst.IndexOf(tbl1) = -1) and (Lst1.IndexOf(tbl1) = -1) then
|
|
if QBDialog.OQBEngine.UseTableAliases then
|
|
Lst.Add(LowerCase(TOQBTable(Controls[i]).FTableName) + ' ' + tbl1) else
|
|
Lst.Add(tbl1);
|
|
end;
|
|
|
|
Lst1.Free;
|
|
|
|
QBDialog.OQBEngine.SQLfrom.Assign(Lst2);
|
|
QBDialog.OQBEngine.SQLfrom.AddStrings(Lst);
|
|
Lst2.Free;
|
|
Lst.Clear;
|
|
end;
|
|
|
|
// WHERE clause
|
|
with QBArea do
|
|
begin
|
|
for i := 0 to ControlCount - 1 do
|
|
if Controls[i] is TOQBLink then
|
|
begin
|
|
Link := TOQBLink(Controls[i]);
|
|
if Link.FLinkType = 0 then
|
|
begin
|
|
if QBDialog.OQBEngine.UseTableAliases then
|
|
s := Link.tbl1.FTableAlias + '.' + Link.fldNam1 + sLinkOpt[Link.FLinkOpt] +
|
|
Link.tbl2.FTableAlias + '.' + Link.fldNam2
|
|
else
|
|
s := Link.tbl1.FTableName + '.' + Link.fldNam1 + sLinkOpt[Link.FLinkOpt] +
|
|
Link.tbl2.FTableName + '.' + Link.fldNam2;
|
|
|
|
Lst.Add(LowerCase(s));
|
|
end;
|
|
end;
|
|
QBDialog.OQBEngine.SQLwhere.Assign(Lst);
|
|
Lst.Clear;
|
|
end;
|
|
|
|
// GROUP BY clause
|
|
with QBGrid do
|
|
begin
|
|
for i := 1 to ColCount - 1 do
|
|
begin
|
|
if Cells[i, cGroup] <> EmptyStr then
|
|
begin
|
|
if QBDialog.OQBEngine.UseTableAliases then
|
|
tbl1 := QBDialog.OQBEngine.AliasList[QBDialog.OQBEngine.TableList.IndexOf(Cells[i, cTbl])]
|
|
else
|
|
tbl1 := Cells[i, cTbl];
|
|
s := tbl1 + '.' + Cells[i, cFld];
|
|
Lst.Add(LowerCase(s));
|
|
end;
|
|
end;
|
|
QBDialog.OQBEngine.SQLgroupby.Assign(Lst);
|
|
Lst.Clear;
|
|
end;
|
|
|
|
// ORDER BY clause
|
|
with QBGrid do
|
|
begin
|
|
for i := 1 to ColCount - 1 do
|
|
begin
|
|
if Cells[i, cSort] <> EmptyStr then
|
|
begin
|
|
if QBDialog.OQBEngine.UseTableAliases then
|
|
tbl1 := QBDialog.OQBEngine.AliasList[QBDialog.OQBEngine.TableList.IndexOf(Cells[i, cTbl])]
|
|
else
|
|
tbl1 := Cells[i, cTbl];
|
|
// --- to order result set by the result of an aggregate function
|
|
if Cells[i, cFunc] = EmptyStr then
|
|
s := LowerCase(tbl1 + '.' + Cells[i, cFld]) else
|
|
s := IntToStr(i);
|
|
// ---
|
|
|
|
if Cells[i, cSort] = sSort[3] then
|
|
s := s + ' DESC';
|
|
Lst.Add(s);
|
|
end;
|
|
end;
|
|
QBDialog.OQBEngine.SQLorderby.Assign(Lst);
|
|
Lst.Clear;
|
|
end;
|
|
|
|
MemoSQL.Lines.Text := QBDialog.OQBEngine.GenerateSQL;
|
|
Pages.ActivePage := TabSQL;
|
|
finally
|
|
Lst.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TOQBForm.btnResultsClick(Sender: TObject);
|
|
begin
|
|
// We may be able to generate the SQL if the user has
|
|
// visually created one
|
|
if MemoSQL.Lines.Text='' then
|
|
btnSQLClick(Sender);
|
|
QBDialog.OQBEngine.CloseResultQuery; // OQB 4.0a
|
|
QBDialog.OQBEngine.SetQuerySQL(MemoSQL.Lines.Text);
|
|
QBDialog.OQBEngine.OpenResultQuery;
|
|
Pages.ActivePage := TabResults;
|
|
end;
|
|
|
|
procedure TOQBForm.btnAboutClick(Sender: TObject);
|
|
var
|
|
QBAboutForm: TOQBAboutForm;
|
|
begin
|
|
QBAboutForm := TOQBAboutForm.Create(Application);
|
|
QBAboutForm.ShowModal;
|
|
QBAboutForm.Free;
|
|
end;
|
|
|
|
procedure TOQBForm.btnSaveResultsClick(Sender: TObject);
|
|
begin
|
|
QBDialog.OQBEngine.SaveResultQueryData;
|
|
end;
|
|
|
|
procedure TOQBForm.btnOKClick(Sender: TObject);
|
|
begin
|
|
ModalResult := mrOk;
|
|
end;
|
|
|
|
procedure TOQBForm.btnCancelClick(Sender: TObject);
|
|
begin
|
|
ModalResult := mrCancel;
|
|
end;
|
|
|
|
end.
|