home *** CD-ROM | disk | FTP | other *** search
/ Chip: Shareware for Win 95 / Chip-Shareware-Win95.bin / ostatni / delphi / delphi2 / datetime.exe / 32BIT / STDCOMPS.PAS < prev   
Pascal/Delphi Source File  |  1996-10-14  |  25KB  |  893 lines

  1. unit StdComps;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils, WinTypes, WinProcs, Classes, Graphics, Controls, Messages, Spin,
  7.   Dialogs, Forms, Buttons, ExtCtrls, StdCtrls, DsgnIntf, DB, DBTables;
  8.  
  9. type
  10.   {TComponentButton}
  11.   TComponentButton = class (TWinControl)
  12.   private
  13.     FButton: TTimerSpeedButton;
  14.     FFocusControl: TWinControl;
  15.     FOnClick: TNotifyEvent;
  16.     FOnMouseDown: TMouseEvent;
  17.     FAllowTimer: Boolean;
  18.     {The name of the button in the resource}
  19.     FTimeBtnState: TTimeBtnState;
  20.     function GetGlyph: TBitmap;
  21.     procedure SetGlyph(Value: TBitmap);
  22.     function GetNumGlyphs: Integer;
  23.     procedure SetNumGlyphs(Value: Integer);
  24.     procedure SetAllowTimer(Value: Boolean);
  25.     procedure BtnClick(Sender: TObject);
  26.     procedure BtnMouseDown(Sender: TObject; Button: TMouseButton;
  27.                       Shift: TShiftState; X, Y: Integer);
  28.     procedure AdjustSize (var W: Integer; var H: Integer);
  29.     procedure WMSize(var Message: TWMSize);  message WM_SIZE;
  30.     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  31.     procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  32.     function GetTimeBtnState: TTimeBtnState;
  33.     procedure SetTimeBtnState(Value: TTimeBtnState);
  34.     function GetCaption: string;
  35.     procedure SetCaption(Value: string);
  36.   protected
  37.     procedure Loaded; override;
  38.   public
  39.     constructor Create(AOwner: TComponent; HintStr: String);
  40.     procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  41.     property TimeBtnState: TTimeBtnState read GetTimeBtnState
  42.                                          write SetTimeBtnState;
  43.   published
  44.     property Glyph: TBitmap read GetGlyph write SetGlyph;
  45.     property NumGlyphs: Integer read GetNumGlyphs write SetNumGlyphs;
  46.     property FocusControl: TWinControl read FFocusControl write FFocusControl;
  47.     property OnClick: TNotifyEvent read FOnClick write FOnClick;
  48.     property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;
  49.     property AllowTimer: Boolean read FAllowTimer write SetAllowTimer;
  50.     property BtnCaption: String read GetCaption write SetCaption;
  51.   end;
  52.  
  53.   {TJoins}
  54.   TJoins = class(TPersistent)
  55.   private
  56.     FLeftList: TStringList;
  57.     FRightList: TStringList;
  58.     FLeftSelectedJoins: TStringList;
  59.     FRightSelectedJoins: TStringList;
  60.     FCanSelect: Boolean;
  61.     FDuplicateNames: Boolean;
  62.     FLeftText, FRightText: String;
  63.     {The test above each list box on the form}
  64.   public
  65.     constructor create;
  66.     destructor destroy;
  67.     procedure clear;
  68.     procedure Assign(J: TJoins);
  69.   published
  70.     property LeftList: TStringList read FLeftList write FLeftList;
  71.     property RightList: TStringList read FRightList write FRightList;
  72.     property LeftSelectedJoins: TStringList read FLeftSelectedJoins
  73.                                             write FLeftSelectedJoins;
  74.     property RightSelectedJoins: TStringList read FRightSelectedJoins
  75.                                              write FRightSelectedJoins;
  76.     property CanSelect: Boolean read FCanSelect write FCanSelect;
  77.     property DuplicateNames: Boolean read FDuplicateNames write FDuplicateNames;
  78.     property LeftText: string read FLeftText write FLeftText;
  79.     property RightText: string read FRightText write FRightText;
  80.   end;
  81.  
  82.   {TFormSelJoins}
  83.   TFormSelJoins = class(TForm)
  84.     BtnOK: TBitBtn;
  85.     BtnCancel: TBitBtn;
  86.     Bevel1: TBevel;
  87.     LabelLeft: TLabel;
  88.     LabelRight: TLabel;
  89.     LBJoined: TListBox;
  90.     LabelJoined: TLabel;
  91.     BtnAdd: TBitBtn;
  92.     BtnClear: TBitBtn;
  93.     BtnDelete: TBitBtn;
  94.     LBLeft: TListBox;
  95.     LBRight: TListBox;
  96.     procedure BtnAddClick(Sender: TObject);
  97.     procedure BtnDeleteClick(Sender: TObject);
  98.     procedure BtnClearClick(Sender: TObject);
  99.     procedure FormCreate(Sender: TObject);
  100.     procedure FormDestroy(Sender: TObject);
  101.   private
  102.     LeftStrings: TStringList;
  103.     {The strings in the left list Box}
  104.     RightStrings: TStringList;
  105.     {The strings in the right list Box}
  106.     LeftJoins:  TStringList;
  107.     {The strings on the left side of the joins}
  108.     RightJoins:  TStringList;
  109.     {The strings on the right side of the joins}
  110.     DuplicateNames: Boolean;
  111.     {Indicates if joins can include the same name on both sides.}
  112.     function CheckRecursive(LeftSelected, RightSelected: Integer): Boolean;
  113.     {Returns false if the proposed join is recursive}
  114.     procedure AddJoin(LeftSelected, RightSelected: Integer);
  115.     {Adds a Join}
  116.     Procedure DeleteJoin(Join: Integer);
  117.     {Deletes a Join}
  118.     function FindIndex(Fld: String; LB: TListBox): Integer;
  119.     {Returns the index of Fld in LB}
  120.     procedure AddJoins;
  121.   public
  122.     procedure SetStrings(J: TJoins);
  123.     procedure GetJoins(J: TJoins);
  124.     procedure Clear;
  125.     {Clears strings and joins}
  126.     procedure SetCaptions(LeftCaption, RightCaption: String);
  127.   end;
  128.  
  129.   {TJoinsProperty}
  130.   TJoinsProperty = class(TClassProperty)
  131.   public
  132.     procedure Edit; override;
  133.     function GetAttributes: TPropertyAttributes; override;
  134.   end;
  135.  
  136.  {TAbout}
  137.   TAbout = Class(TComponent)
  138.   private
  139.     DummyData: Integer;
  140.   end;
  141.  
  142.   {TAbout Property}
  143.   TAboutProperty = class(TClassProperty)
  144.   public
  145.     procedure Edit; override;
  146.     function GetAttributes: TPropertyAttributes; override;
  147.   end;
  148.  
  149.   {TAboutBox}
  150.   TAboutBox = class(TForm)
  151.     Panel1: TPanel;
  152.     OKButton: TBitBtn;
  153.     Comments: TLabel;
  154.     Label1: TLabel;
  155.     NBComponent: TNotebook;
  156.     ProgramIcon: TImage;
  157.     Shape1: TShape;
  158.     ProductName: TLabel;
  159.     Version: TLabel;
  160.     Copyright: TLabel;
  161.     Shape2: TShape;
  162.     Image1: TImage;
  163.     Label2: TLabel;
  164.     Label3: TLabel;
  165.     Label4: TLabel;
  166.     Shape3: TShape;
  167.     Image2: TImage;
  168.     Label5: TLabel;
  169.     Label6: TLabel;
  170.     Label7: TLabel;
  171.     Shape4: TShape;
  172.     Image3: TImage;
  173.     Label8: TLabel;
  174.     Label9: TLabel;
  175.     Label10: TLabel;
  176.     Shape5: TShape;
  177.     Image4: TImage;
  178.     Label11: TLabel;
  179.     Label12: TLabel;
  180.     Label13: TLabel;
  181.   private
  182.   public
  183.   end;
  184.  
  185.   {SQl functions}
  186.   TSQLClause = (sqlFields, sqlTables, sqlWhere, sqlOrder);
  187.  
  188.   procedure GetStrPos(S: TStringList; Str: String; var StrLine, StrPos: Integer);
  189.   {Returns the line and position of the word Str in S
  190.    returns zero if not found}
  191.  
  192.   procedure GetFields(DS: TDataSet; var Fields: TStringList);
  193.   {returns the fields in a stringlist}
  194.  
  195.   procedure GetSQLClause(DS: TDataset; ClauseType: TSQLClause;
  196.               var Clause: TStringList);
  197.   {returns the from part of an SQl statement if the dataset is a query,
  198.    or the table name if the dataset is a table.
  199.    Queries must be in the form:
  200.    Select <Fields> from <tables> where <where clause> order by <fields>
  201.    <Where Clause> and <Fields> are optional}
  202.  
  203.   function getDelimeted(SL:TStringList):String;
  204.   {Returns the items in the string list as a string}
  205.  
  206.   procedure Register;
  207.  
  208. implementation
  209. {$R about.dfm}
  210.  
  211. procedure Register;
  212. begin
  213.   RegisterPropertyEditor(TypeInfo(TAbout), nil, '', TAboutProperty);
  214.   RegisterPropertyEditor(TypeInfo(TJoins), nil, '', TJoinsProperty);
  215. end;
  216.  
  217. {********************}
  218. {* TComponentButton *}
  219. {********************}
  220. constructor TComponentButton.Create(AOwner: TComponent; HintStr: String);
  221. var
  222.   BmpName: ARRAY[0..50] of Char;
  223. begin
  224.   inherited Create(AOwner);
  225.   ControlStyle := ControlStyle - [csAcceptsControls, csSetCaption] +
  226.     [csFramed, csOpaque];
  227.  
  228.   FButton := TTimerSpeedButton.Create (Self);
  229.   with FButton do
  230.   begin
  231.     OnClick := BtnClick;
  232.     OnMouseDown := BtnMouseDown;
  233.     Visible := True;
  234.     Enabled := True;
  235.     TimeBtnState := [tbAllowTimer];
  236.     Parent := Self;
  237.     If Length(HintStr) > 0
  238.     then begin
  239.       ShowHint := True;
  240.       Hint := HintStr;
  241.     end;
  242.   end;
  243.  
  244.   Glyph := nil;
  245.   Width := 20;
  246.   Height := 25;
  247. end;
  248.  
  249. procedure TComponentButton.AdjustSize (var W: Integer; var H: Integer);
  250. var
  251.   Y: Integer;
  252. begin
  253.   if (FButton = nil) or (csLoading in ComponentState) then Exit;
  254. {  if W < 15 then W := 15;}
  255.   FButton.SetBounds (0, 0, W, H);
  256. end;
  257.  
  258. procedure TComponentButton.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  259. var
  260.   W, H: Integer;
  261. begin
  262.   W := AWidth;
  263.   H := AHeight;
  264.   AdjustSize (W, H);
  265.   inherited SetBounds (ALeft, ATop, W, H);
  266. end;
  267.  
  268. procedure TComponentButton.WMSize(var Message: TWMSize);
  269. var
  270.   W, H: Integer;
  271. begin
  272.   inherited;
  273.   { check for minimum size }
  274.   W := Width;
  275.   H := Height;
  276.   AdjustSize (W, H);
  277.   if (W <> Width) or (H <> Height) then
  278.     inherited SetBounds(Left, Top, W, H);
  279.   Message.Result := 0;
  280. end;
  281.  
  282. procedure TComponentButton.WMSetFocus(var Message: TWMSetFocus);
  283. begin
  284.   FButton.TimeBtnState := FButton.TimeBtnState + [tbFocusRect];
  285.   FButton.Invalidate;
  286. end;
  287.  
  288. procedure TComponentButton.WMKillFocus(var Message: TWMKillFocus);
  289. begin
  290.   FButton.TimeBtnState := FButton.TimeBtnState - [tbFocusRect];
  291.   FButton.Invalidate;
  292. end;
  293.  
  294. procedure TComponentButton.BtnClick(Sender: TObject);
  295. begin
  296.   if Assigned(FOnClick) then FOnClick(Self);
  297. end;
  298.  
  299. procedure TComponentButton.BtnMouseDown(Sender: TObject; Button: TMouseButton;
  300.                       Shift: TShiftState; X, Y: Integer);
  301. begin
  302.   if Assigned(FOnMouseDown) then FOnMouseDown(Self, Button, Shift, X, Y);
  303. end;
  304.  
  305. procedure TComponentButton.Loaded;
  306. var
  307.   W, H: Integer;
  308. begin
  309.   inherited Loaded;
  310.   W := Width;
  311.   H := Height;
  312.   AdjustSize (W, H);
  313.   if (W <> Width) or (H <> Height) then
  314.     inherited SetBounds (Left, Top, W, H);
  315. end;
  316.  
  317. function TComponentButton.GetGlyph: TBitmap;
  318. begin
  319.   Result := FButton.Glyph;
  320. end;
  321.  
  322. procedure TComponentButton.SetGlyph(Value: TBitmap);
  323. begin
  324.   FButton.Glyph := Value;
  325. end;
  326.  
  327. function TComponentButton.GetNumGlyphs: Integer;
  328. begin
  329.   Result := FButton.NumGlyphs;
  330. end;
  331.  
  332. procedure TComponentButton.SetNumGlyphs(Value: Integer);
  333. begin
  334.   FButton.NumGlyphs := Value;
  335. end;
  336.  
  337. procedure TComponentButton.SetAllowTimer(Value: Boolean);
  338. begin
  339.   FAllowTimer := Value;
  340.   If FAllowTimer
  341.   then FButton.TimeBtnState := FButton.TimeBtnState + [tbAllowTimer]
  342.   else FButton.TimeBtnState := FButton.TimeBtnState - [tbAllowTimer];
  343. end;
  344.  
  345. function TComponentButton.GetTimeBtnState: TTimeBtnState;
  346. begin
  347.   Result := FButton.TimeBtnState;
  348. end;
  349.  
  350. procedure TComponentButton.SetTimeBtnState(Value: TTimeBtnState);
  351. begin
  352.   FButton.TimeBtnState := Value;
  353. end;
  354.  
  355. procedure TComponentButton.SetCaption(Value: string);
  356. begin
  357.   FButton.Caption := Value;
  358. end;
  359.  
  360. function TComponentButton.GetCaption: string;
  361. begin
  362.   Result := FButton.Caption;
  363. end;
  364.  
  365. {*******************}
  366. {*      About      *}
  367. {*******************}
  368.  
  369. {TAboutProperty Implementation}
  370. procedure TAboutProperty.Edit;
  371. var
  372.   Comp: TComponent;
  373.   DummyAbout: TAbout;
  374. begin
  375.   Comp := GetComponent(0);
  376.   with TAboutBox.Create(Application) do
  377.   try
  378.     NBComponent.ActivePage := Comp.ClassName;
  379.     ShowModal;
  380.   finally
  381.     Free;
  382.   end;
  383. end;
  384.  
  385. function TAboutProperty.GetAttributes: TPropertyAttributes;
  386. begin
  387.   Result := [paDialog, paReadOnly];
  388. end;
  389.  
  390. {********************}
  391. {* Joins Components *}
  392. {********************}
  393.  
  394. {TJoins Implementation}
  395. constructor TJoins.create;
  396. begin
  397.   FLeftList := TStringList.Create;
  398.   FRightList := TStringList.Create;
  399.   FLeftSelectedJoins := TStringList.Create;
  400.   FRightSelectedJoins := TStringList.Create;
  401. end;
  402.  
  403. destructor TJoins.destroy;
  404. begin
  405.   FLeftList.Free;
  406.   FRightList.Free;
  407.   FLeftSelectedJoins.Free;
  408.   FRightSelectedJoins.Free;
  409. end;
  410.  
  411. procedure TJoins.clear;
  412. begin
  413.   FLeftList.Clear;
  414.   FRightList.Clear;
  415.   FLeftSelectedJoins.Clear;
  416.   FRightSelectedJoins.Clear;
  417. end;
  418.  
  419. procedure TJoins.Assign(J: TJoins);
  420. begin
  421.   FLeftList.Assign(J.LeftList);
  422.   FRightList.Assign(J.RightList);
  423.   FLeftSelectedJoins.Assign(J.LeftSelectedJoins);
  424.   FRightSelectedJoins.Assign(J.RightSelectedJoins);
  425. end;
  426.  
  427. {TFormSelJoins Implementation}
  428. procedure TFormSelJoins.FormCreate(Sender: TObject);
  429. begin
  430.   LeftStrings := TStringList.Create;
  431.   RightStrings := TStringList.Create;
  432.   LeftJoins := TStringList.Create;
  433.   RightJoins := TStringList.Create;
  434. end;
  435.  
  436. procedure TFormSelJoins.FormDestroy(Sender: TObject);
  437. begin
  438.   LeftStrings.Free;
  439.   RightStrings.Free;
  440.   LeftJoins.Free;
  441.   RightJoins.Free;
  442. end;
  443.  
  444. procedure TFormSelJoins.AddJoin(LeftSelected, RightSelected: Integer);
  445. var
  446.   LeftField, RightField: String;
  447. begin
  448.   LeftField := LBLeft.Items.Strings[LeftSelected];
  449.   RightField := LBRight.Items.Strings[RightSelected];
  450.   LBJoined.Items.Add(LeftField+' -> '+RightField);
  451.   {Delete from source list boxes}
  452.   LBLeft.Items.Delete(LeftSelected);
  453.   LBRight.Items.Delete(RightSelected);
  454.   if DuplicateNames
  455.   then begin
  456.     LBRight.Items.Delete(LeftSelected);
  457.     LBLeft.Items.Delete(RightSelected);
  458.   end;
  459. end;
  460.  
  461. function TFormSelJoins.CheckRecursive(LeftSelected, RightSelected: Integer): Boolean;
  462. {Returns true if not recursive}
  463. var
  464.   LeftField, RightField: String;
  465.   FieldIndex: Integer;
  466.   LeftRecursive, RightRecursive: Boolean;
  467. begin
  468.   LeftField := LBLeft.Items.Strings[LeftSelected];
  469.   RightField := LBRight.Items.Strings[RightSelected];
  470.   {Check Left Recursion}
  471.   LeftRecursive := False;
  472.   For FieldIndex := 0 to RightJoins.Count -1 do
  473.     If LeftField = RightJoins.Strings[FieldIndex]
  474.         then LeftRecursive := True;
  475.   {Check Parent Recursion}
  476.   RightRecursive := False;
  477.   For FieldIndex := 0 to LeftJoins.Count -1 do
  478.     If RightField = LeftJoins.Strings[FieldIndex]
  479.         then RightRecursive := True;
  480.  
  481.   Result := NOT (LeftRecursive OR RightRecursive);
  482. end;
  483.  
  484. Procedure TFormSelJoins.BtnAddClick(Sender: TObject);
  485. var
  486.   SelIndex, LeftSelected, RightSelected: Integer;
  487. begin
  488.   LeftSelected := -1;
  489.   RightSelected := -1;
  490.   For SelIndex := 0 to LBLeft.Items.Count - 1 do
  491.     If LBLeft.Selected[SelIndex] then LeftSelected := SelIndex;
  492.   For SelIndex := 0 to LBRight.Items.Count - 1 do
  493.     If LBRight.Selected[SelIndex] then RightSelected := SelIndex;
  494.   If (LeftSelected > -1) and (RightSelected > -1)
  495.   then begin
  496.     if (LBLeft.Items.Strings[LeftSelected] =
  497.        LBRight.Items.Strings[RightSelected])
  498.        and not DuplicateNames
  499.     then begin
  500.       MessageDlg('Cannot Join a field onto itself', mtWarning, [mbOK], 0);
  501.       exit;
  502.     end;
  503.     {if recursive or duplicate names allowed}
  504.     if CheckRecursive(LeftSelected, RightSelected) or DuplicateNames
  505.     then begin
  506.       {Add to Join lists}
  507.       LeftJoins.Add(LBLeft.Items.Strings[LeftSelected]);
  508.       RightJoins.Add(LBRight.Items.Strings[RightSelected]);
  509.       AddJoin(LeftSelected, RightSelected)
  510.     end
  511.     else MessageDlg('Recursive relationships not allowed', mtWarning, [mbOK], 0);
  512.   end
  513.   else MessageDlg('Select a field from either side first', mtWarning, [mbOK], 0);
  514. end;
  515.  
  516. Procedure TFormSelJoins.DeleteJoin(Join: Integer);
  517. begin
  518.   LBLeft.Items.Add(LeftJoins[Join]);
  519.   LBRight.Items.Add(RightJoins[Join]);
  520.   LeftJoins.Delete(Join);
  521.   RightJoins.Delete(Join);
  522.   LBJoined.Items.Delete(Join);
  523. end;
  524.  
  525. procedure TFormSelJoins.BtnDeleteClick(Sender: TObject);
  526. var
  527.   JoinSelected, SelIndex: Integer;
  528. begin
  529.   {Find ID of Join}
  530.   JoinSelected := -1;
  531.   For SelIndex := 0 to LBJoined.Items.Count - 1 do
  532.     If LBJoined.Selected[SelIndex] then JoinSelected := SelIndex;
  533.  
  534.   {If a join was selected}
  535.   If JoinSelected > -1
  536.   then DeleteJoin(JoinSelected)
  537.   else MessageDlg('Select Join to delete', mtWarning, [mbOK], 0);
  538. end;
  539.  
  540. procedure TFormSelJoins.BtnClearClick(Sender: TObject);
  541. var
  542.   JoinCounter: Integer;
  543. begin
  544.   If MessageDlg('Delete all Joins ?', mtConfirmation, [mbYes, mbNO], 0) = mrYes then
  545.     For JoinCounter := 0 to LBJoined.Items.Count - 1 do
  546.       DeleteJoin(0);
  547. end;
  548.  
  549. function TFormSelJoins.FindIndex(Fld: String; LB: TListBox): Integer;
  550. var
  551.   LBCounter: Integer;
  552. begin
  553.   Result := -1;
  554.   For LBCounter := 0 to LB.Items.Count-1 do
  555.     If Fld = LB.Items.Strings[LBCounter]
  556.     then Result := LBCounter;
  557. end;
  558.  
  559. procedure TFormSelJoins.AddJoins;
  560. var
  561.   JoinCounter, MinJoins, LeftIndex, RightIndex: Integer;
  562. begin
  563.   {Add Links}
  564.   If LeftJoins.Count > RightJoins.Count
  565.   then MinJoins := RightJoins.Count
  566.   else MinJoins := LeftJoins.Count;
  567.   For JoinCounter := 0 to MinJoins-1 do
  568.   begin
  569.      {Get indexes of keys in list boxes}
  570.      LeftIndex := FindIndex(LeftJoins.Strings[JoinCounter], LBLeft);
  571.      RightIndex := FindIndex(RightJoins.Strings[JoinCounter], LBRight);
  572.      {if found, then join}
  573.      If (LeftIndex > -1) and (RightIndex > -1)
  574.      then AddJoin(LeftIndex, RightIndex)
  575.      else MessageDlg('You have changed fields, reselect StdParentChildJoins',
  576.                      mtError, [mbOK], 0);
  577.   end;
  578. end;
  579.  
  580. procedure TFormSelJoins.SetStrings(J: TJoins);
  581. var
  582.   AList: TStringList;
  583. begin
  584.   LeftStrings.Assign(J.LeftList);
  585.   RightStrings.Assign(J.RightList);
  586.   LBLeft.Items.Assign(LeftStrings);
  587.   LBRight.Items.Assign(RightStrings);
  588.   LeftJoins.Assign(J.LeftSelectedJoins);
  589.   RightJoins.Assign(J.RightSelectedJoins);
  590.   AddJoins;
  591.   DuplicateNames := J.DuplicateNames;
  592. end;
  593.  
  594. procedure TFormSelJoins.GetJoins(J: TJoins);
  595. begin
  596.   J.LeftSelectedJoins.Assign(LeftJoins);
  597.   J.RightSelectedJoins.Assign(RightJoins);
  598. end;
  599.  
  600. procedure TFormSelJoins.Clear;
  601. begin
  602.   LeftStrings.Clear;
  603.   RightStrings.Clear;
  604.   LeftJoins.Clear;
  605.   RightJoins.Clear;
  606. end;
  607.  
  608. procedure TFormSelJoins.SetCaptions(LeftCaption, RightCaption: String);
  609. begin
  610.   LabelLeft.Caption := LeftCaption;
  611.   LabelRight.Caption := RightCaption;
  612. end;
  613.  
  614. {TJoinsProperty}
  615. procedure TJoinsProperty.Edit;
  616. var
  617.   FormSelJoins: TFormSelJoins;
  618.   AJoins: TJoins;
  619. begin
  620.   AJoins := TJoins(GetOrdValue);
  621.  
  622.   if AJoins.CanSelect
  623.   then begin
  624.     FormSelJoins := TFormSelJoins.Create(Application);
  625.     with FormSelJoins do
  626.     begin
  627.       SetStrings(AJoins);
  628.       SetCaptions(AJoins.LeftText, AJoins.RightText);
  629.       ShowModal;
  630.       if ModalResult = mrOK
  631.       then GetJoins(AJoins);
  632.       Free;
  633.     end;
  634.     SetOrdValue(LongInt(AJoins));
  635.   end;
  636. end;
  637.  
  638. function TJoinsProperty.GetAttributes: TPropertyAttributes;
  639. begin
  640.   Result := [paDialog, paReadOnly];
  641. end;
  642.  
  643.  
  644. {*****************}
  645. {* SQL functions *}
  646. {*****************}
  647.  
  648. {Error capture routines}
  649. function StrListInit(SL: TStringList): Boolean;
  650. {Returns true is dataset is initialised}
  651. begin
  652.   If SL = nil
  653.   then begin
  654.     MessageDlg('StringList not initialised', mtError, [mbOK], 0);
  655.     Result := False;
  656.   end
  657.   else Result := True;
  658. end;
  659.  
  660. function DSInit(DS: TDataSet): Boolean;
  661. {Returns true is dataset is initialised}
  662. begin
  663.   If DS = nil
  664.   then begin
  665.     MessageDlg('DataSet not initialised', mtError, [mbOK], 0);
  666.     Result := False
  667.   end
  668.   else Result := True;
  669. end;
  670.  
  671. function DSTableOrQuery(DS: TDataSet): Boolean;
  672. {Retuns true if dataset is a table or query }
  673. begin
  674.   If (DS is TTable) or (DS is TQuery)
  675.   then Result := True
  676.   else begin
  677.     MessageDlg('DataSet must be a table or query', mtError, [mbOK], 0);
  678.     Result := False;
  679.   end;
  680. end;
  681.  
  682. {general procedures}
  683. procedure GetQStrPos(Q: TQuery; Str: String; var StrLine, StrPos: Integer);
  684. {Returns the line and position of the word Str in the sql of a query
  685.  returns zero if not found}
  686. var
  687.   L, P: Integer;
  688. begin
  689.   Str := Uppercase(Str);
  690.   StrLine := 0;
  691.   StrPos := 0;
  692.   L := 0;
  693.   While (L < Q.SQL.Count) and (StrLine = 0) do
  694.   begin
  695.     P := Pos(Str, Uppercase(Q.SQL[L]));
  696.     If P > 0
  697.     then begin
  698.       StrLine := L;
  699.       StrPos := P;
  700.     end;
  701.     L := L + 1;
  702.   end;
  703. end;
  704.  
  705. procedure GetBtwLines(Q: TQuery; FromLine, FromPos,
  706.                   ToLine, ToPos: Integer; var Lines: TStringList);
  707. {Returns lines between from line and pos to to line and pos}
  708. var
  709.   LineIndex: Integer;
  710.   S: string;
  711. begin
  712.   if not StrListInit(Lines) then exit;
  713.  
  714.   If ToLine = FromLine
  715.   then S := Copy(Q.SQL[FromLine], FromPos-1, ToPos-FromPos)
  716.   else S := Copy(Q.SQL[FromLine], FromPos-1,
  717.                  length(Q.SQL[FromLine])-FromPos+2);
  718.   If Length(S) > 0 then Lines.Add(S);
  719.  
  720.   For LineIndex := FromLine+1 to ToLine-1 do
  721.     if Length(Q.SQL[LineIndex]) > 0 then Lines.Add(Q.SQL[LineIndex]);
  722.  
  723.   if ToLine > FromLine
  724.   then begin
  725.     S := Copy(Q.SQL[ToLine], 0, ToPos-1);
  726.     If Length(S) > 0 then Lines.Add(S);
  727.   end;
  728. end;
  729.  
  730. function ReplaceStr(var S: String; r: string; b: string): String;
  731. {Returns orderStr with all occurences of r replaced by b}
  732. var
  733.   Finished: Boolean;
  734.   P: Integer;
  735. begin
  736.   Finished := False;
  737.   Result := S;
  738.   While not finished do
  739.   begin
  740.     P := Pos(r, Result);
  741.     if P = 0
  742.     then Finished := True
  743.     else Result := Copy(Result, 0, P-1) + b +
  744.                    Copy(Result, P+Length(r), Length(S));
  745.   end;
  746. end;
  747.  
  748. {Public Methods}
  749.  
  750. procedure GetStrPos(S: TStringList; Str: String; var StrLine, StrPos: Integer);
  751. {Returns the line and position of the word Str in S
  752.  returns zero if not found}
  753. var
  754.   L, P: Integer;
  755. begin
  756.   Str := Uppercase(Str);
  757.   StrLine := 0;
  758.   StrPos := 0;
  759.   L := 0;
  760.   While (L < S.Count) and (StrLine = 0) do
  761.   begin
  762.     P := Pos(Str, Uppercase(S[L]));
  763.     If P > 0
  764.     then begin
  765.       StrLine := L;
  766.       StrPos := P;
  767.     end;
  768.     L := L + 1;
  769.   end;
  770. end;
  771.  
  772. procedure GetFields(DS: TDataSet; var Fields: TStringList);
  773. {returns the fields in a stringlist}
  774. var
  775.   FieldIndex: Integer;
  776. begin
  777.   if not StrListInit(Fields) then exit;
  778.   if not DSInit(DS) then exit;
  779.   If DS.FieldCount = 0 then exit;
  780.   For FieldIndex := 0 to DS.FieldCount-2 do
  781.     Fields.add(DS.Fields[FieldIndex].FieldName+',');
  782.   Fields.add(DS.Fields[DS.FieldCount-1].FieldName);
  783. end;
  784.  
  785. procedure GetSQLClause(DS: TDataset; ClauseType: TSQLClause;
  786.                   var Clause: TStringList);
  787. {returns the ClauseType part of an SQl statement if the dataset is a query,
  788.  or the table name if the dataset is a table
  789.  
  790.  Queries must be in the form:
  791.  Select <Fields> from <tables> where <where clause> order by <fields>
  792.  }
  793. var
  794.   SelectLine, SelectPos, WhereLine, WherePos,
  795.   OrderLine, OrderPos, EndLine, EndPos: Integer;
  796.   OrderStr, TableNameStr: String;
  797.   DotPos: Integer;
  798. Begin
  799.   if not StrListInit(Clause) then exit;
  800.   if not DSInit(DS) then exit;
  801.   if not DSTableOrQuery(DS) then exit;
  802.   Clause.Clear;
  803.  
  804.   If (DS is TTable)
  805.   then
  806.     case ClauseType of
  807.      sqlFields: GetFields(DS, Clause);
  808.      sqlTables:
  809.        begin
  810.          TableNameStr := (DS as TTable).TableName;
  811.          {if non-sql table then return table name}
  812.          DotPos := Pos('.', TableNameStr);
  813.          if DotPos > 0
  814.          then TableNameStr := Copy(TableNameStr, 1, DotPos-1);
  815.          Clause.Add(TableNameStr);
  816.        end;
  817.      sqlOrder:
  818.        begin
  819.          OrderStr := (DS as TTable).IndexFieldNames;
  820.          If Length(OrderStr) > 0
  821.          then Clause.Add(ReplaceStr(OrderStr, ';', ','));
  822.        end;
  823.     end
  824.   else
  825.     {TQuery}
  826.     Case ClauseType of
  827.      sqlFields: GetFields(DS, Clause);
  828.      sqlTables:
  829.      begin
  830.        GetQStrPos((DS as TQuery), 'FROM', SelectLine, SelectPos);
  831.        GetQStrPos((DS as TQuery), 'WHERE', WhereLine, WherePos);
  832.        If WherePos = 0
  833.        then begin
  834.          GetQStrPos((DS as TQuery), 'ORDER BY', OrderLine, OrderPos);
  835.          if OrderPos = 0
  836.          then begin
  837.            EndLine := (DS as TQuery).SQL.Count-1;
  838.            EndPos := length((DS as TQuery).SQL[(DS as TQuery).SQL.Count-1])+2;
  839.            GetBtwLines((DS as TQuery), SelectLine, SelectPos+6,
  840.                            EndLine, EndPos, Clause);
  841.          end
  842.          else GetBtwLines((DS as TQuery), SelectLine, SelectPos+6,
  843.                            OrderLine, OrderPos, Clause);
  844.        end;
  845.        GetBtwLines((DS as TQuery), SelectLine, SelectPos+6,
  846.                            WhereLine, WherePos, Clause);
  847.      end;
  848.      sqlWhere:
  849.      begin
  850.        GetQStrPos((DS as TQuery), 'WHERE', WhereLine, WherePos);
  851.        GetQStrPos((DS as TQuery), 'ORDER BY', OrderLine, OrderPos);
  852.        If WherePos = 0 then exit
  853.        else begin
  854.          if OrderPos = 0
  855.          then begin
  856.            EndLine := (DS as TQuery).SQL.Count-1;
  857.            EndPos := length((DS as TQuery).SQL[(DS as TQuery).SQL.Count-1])+2;
  858.            GetBtwLines((DS as TQuery), WhereLine, WherePos+7,
  859.                            EndLine, EndPos, Clause);
  860.          end
  861.          else GetBtwLines((DS as TQuery), WhereLine, WherePos+7,
  862.                            OrderLine, OrderPos, Clause);
  863.        end;
  864.      end;
  865.      sqlOrder:
  866.      begin
  867.        GetQStrPos((DS as TQuery), 'ORDER BY', OrderLine, OrderPos);
  868.        If OrderPos > 0
  869.        then begin
  870.          EndLine := (DS as TQuery).SQL.Count-1;
  871.          EndPos := length((DS as TQuery).SQL[(DS as TQuery).SQL.Count-1])+2;
  872.          GetBtwLines((DS as TQuery), OrderLine, OrderPos+10,
  873.                            EndLine, EndPos, Clause);
  874.        end;
  875.      end;
  876.   end;
  877. end;
  878.  
  879. function getDelimeted(SL:TStringList):String;
  880. {Returns the items in the string list as a string}
  881. var
  882.   I: Integer;
  883. begin
  884.   Result := '';
  885.   For I := 0 to SL.Count-1 do
  886.   begin
  887.     Result := Result + SL[I];
  888.     If I < SL.count-1 then Result := Result+', ';
  889.   end;
  890. end;
  891.  
  892. end.
  893.