Implement query helpers: Columns, SQL functions and SQL keywords, presented in a listbox where they can be doubleclicked or dragged to insert into query-memo.

As a benefit, function.txt is read into 3 stringlists at startup now: Names, Declarations and Descriptions. Used in SynCompletionProposal and to fill the above mentioned helpers-list.

Also fixes a minor issue in SynMemoQueryDragOver using an unset "Accept" var.
This commit is contained in:
Ansgar Becker
2007-07-01 23:29:42 +00:00
parent 134f23e82c
commit 5cbebfe42c
3 changed files with 179 additions and 33 deletions

View File

@ -908,7 +908,7 @@ object MDIChild: TMDIChild
object SynMemoQuery: TSynMemo object SynMemoQuery: TSynMemo
Left = 0 Left = 0
Top = 0 Top = 0
Width = 496 Width = 336
Height = 96 Height = 96
SingleLineMode = False SingleLineMode = False
Align = alClient Align = alClient
@ -959,6 +959,48 @@ object MDIChild: TMDIChild
end> end>
AddedKeystrokes = <> AddedKeystrokes = <>
end end
object pnlQueryHelpers: TPanel
Left = 336
Top = 0
Width = 160
Height = 96
Align = alRight
BevelOuter = bvNone
TabOrder = 1
object tabsetQueryHelpers: TTabSet
Left = 0
Top = 72
Width = 160
Height = 24
Align = alBottom
AutoScroll = False
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
ParentShowHint = False
ShowHint = False
Style = tsModernTabs
Tabs.Strings = (
'Cols'
'SQL fn'
'SQL kw')
TabIndex = 0
OnChange = tabsetQueryHelpersChange
end
object lboxQueryHelpers: TListBox
Left = 0
Top = 0
Width = 160
Height = 72
Align = alClient
DragMode = dmAutomatic
ItemHeight = 13
TabOrder = 1
OnDblClick = lboxQueryHelpersDblClick
end
end
end end
object gridQuery: TSMDBGrid object gridQuery: TSMDBGrid
Left = 0 Left = 0

View File

@ -21,7 +21,7 @@ uses
ZAbstractRODataset, ZConnection, ZAbstractRODataset, ZConnection,
ZSqlMonitor, ZPlainMySqlDriver, EDBImage, ZAbstractDataset, ZDbcLogging, ZSqlMonitor, ZPlainMySqlDriver, EDBImage, ZAbstractDataset, ZDbcLogging,
SynCompletionProposal, HeidiComp, SynEditMiscClasses, MysqlQuery, SynCompletionProposal, HeidiComp, SynEditMiscClasses, MysqlQuery,
MysqlQueryThread, queryprogress, communication, MysqlConn, smdbgrid; MysqlQueryThread, queryprogress, communication, MysqlConn, smdbgrid, Tabs;
type type
@ -267,6 +267,12 @@ type
btnUnsafeEdit: TToolButton; btnUnsafeEdit: TToolButton;
btnColumnSelection: TSpeedButton; btnColumnSelection: TSpeedButton;
btnAltTerminator: TToolButton; btnAltTerminator: TToolButton;
pnlQueryHelpers: TPanel;
tabsetQueryHelpers: TTabSet;
lboxQueryHelpers: TListBox;
procedure lboxQueryHelpersDblClick(Sender: TObject);
procedure tabsetQueryHelpersChange(Sender: TObject; NewTab: Integer;
var AllowChange: Boolean);
procedure btnTableViewDataClick(Sender: TObject); procedure btnTableViewDataClick(Sender: TObject);
procedure btnDbViewDataClick(Sender: TObject); procedure btnDbViewDataClick(Sender: TObject);
procedure btnColumnSelectionClick(Sender: TObject); procedure btnColumnSelectionClick(Sender: TObject);
@ -1730,6 +1736,8 @@ end;
Occurs when active tab has changed. Occurs when active tab has changed.
} }
procedure TMDIChild.pcChange(Sender: TObject); procedure TMDIChild.pcChange(Sender: TObject);
var
dummy : Boolean;
begin begin
tabFilter.tabVisible := (PageControlMain.ActivePage = tabData); tabFilter.tabVisible := (PageControlMain.ActivePage = tabData);
@ -1739,10 +1747,14 @@ begin
if (PageControlMain.ActivePage = tabData) and (not dataselected) then if (PageControlMain.ActivePage = tabData) and (not dataselected) then
viewdata(self); viewdata(self);
if PageControlMain.ActivePage = tabQuery then if PageControlMain.ActivePage = tabQuery then
begin
if ActualDatabase <> '' then if ActualDatabase <> '' then
pnlQueryTop.Caption := 'SQL-Query on Database ' + ActualDatabase + ':' pnlQueryTop.Caption := 'SQL-Query on Database ' + ActualDatabase + ':'
else else
pnlQueryTop.Caption := 'SQL-Query on Host ' + FConn.MysqlParams.Host + ':'; pnlQueryTop.Caption := 'SQL-Query on Host ' + FConn.MysqlParams.Host + ':';
// Manually invoke OnChange event of tabset to fill helper list with data
tabsetQueryHelpers.OnChange( Sender, tabsetQueryHelpers.TabIndex, dummy);
end;
// Move focus to relevant controls in order for them to receive keyboard events. // Move focus to relevant controls in order for them to receive keyboard events.
if PageControlMain.ActivePage = tabDatabase then ListTables.SetFocus; if PageControlMain.ActivePage = tabDatabase then ListTables.SetFocus;
@ -2905,8 +2917,6 @@ procedure TMDIChild.SynCompletionProposal1Execute(Kind: TSynCompletionType;
var CanExecute: Boolean); var CanExecute: Boolean);
var var
i,j,c,t : Integer; i,j,c,t : Integer;
functionname : String;
functiondecl : String;
tn, child : TTreeNode; tn, child : TTreeNode;
sql, tmpsql, kw : String; sql, tmpsql, kw : String;
keywords, tables : TStringList; keywords, tables : TStringList;
@ -3069,15 +3079,10 @@ begin
end; end;
// Add functions // Add functions
for i := 0 to MainForm.sqlfunctionlist.Count - 1 do for i := 0 to MainForm.SQLFunctionNames.Count - 1 do
begin begin
functionname := Copy(MainForm.sqlfunctionlist[i], 0, Pos('(', MainForm.sqlfunctionlist[i])-1); SynCompletionProposal1.InsertList.Add( MainForm.SQLFunctionNames[i] + MainForm.SQLFunctionDeclarations[i] );
if Pos( '|', MainForm.sqlfunctionlist[i] ) > 0 then SynCompletionProposal1.ItemList.Add( '\hspace{2}\color{'+ColorToString(SynSQLSyn1.FunctionAttri.Foreground)+'}function\color{clWindowText}\column{}' + MainForm.SQLFunctionNames[i] + '\style{-B}' + MainForm.SQLFunctionDeclarations[i] );
functiondecl := Copy(MainForm.sqlfunctionlist[i], Length(functionname)+1, Pos( '|', MainForm.sqlfunctionlist[i] )-Length(functionname)-1)
else
functiondecl := Copy(MainForm.sqlfunctionlist[i], Length(functionname)+1, Length(MainForm.sqlfunctionlist[i]) );
SynCompletionProposal1.InsertList.Add( functionname + functiondecl );
SynCompletionProposal1.ItemList.Add( '\hspace{2}\color{'+ColorToString(SynSQLSyn1.FunctionAttri.Foreground)+'}function\color{clWindowText}\column{}' + functionname + '\style{-B}' + functiondecl );
end; end;
// Add keywords // Add keywords
@ -4099,10 +4104,13 @@ end;
procedure TMDIChild.SynMemoQueryDragOver(Sender, Source: TObject; X, procedure TMDIChild.SynMemoQueryDragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean); Y: Integer; State: TDragState; var Accept: Boolean);
var
src : TControl;
begin begin
// dragging an object over the query-memo // dragging an object over the query-memo
if (Source as TControl).Parent = DBTree then src := Source as TControl;
accept := true; // Accepting drag's from DBTree and QueryHelpers
Accept := (src = DBTree) or (src = lboxQueryHelpers);
// set x-position of cursor // set x-position of cursor
SynMemoQuery.CaretX := (x - SynMemoQuery.Gutter.Width) div SynMemoQuery.CharWidth - 1 + SynMemoQuery.LeftChar; SynMemoQuery.CaretX := (x - SynMemoQuery.Gutter.Width) div SynMemoQuery.CharWidth - 1 + SynMemoQuery.LeftChar;
// set y-position of cursor // set y-position of cursor
@ -4114,10 +4122,24 @@ end;
procedure TMDIChild.SynMemoQueryDragDrop(Sender, Source: TObject; X, procedure TMDIChild.SynMemoQueryDragDrop(Sender, Source: TObject; X,
Y: Integer); Y: Integer);
var
src : TControl;
Text : String;
begin begin
// dropping a TTreeNode into the query-memo // dropping a TTreeNode into the query-memo
SynMemoQuery.UndoList.AddGroupBreak; SynMemoQuery.UndoList.AddGroupBreak;
SynMemoQuery.SelText := DBTree.Selected.Text; src := Source as TControl;
// Check for allowed controls as source has already
// been performed in OnDragOver. So, only do typecasting here.
if src is TTreeView then
begin
Text := (src as TTreeView).Selected.Text;
end
else if src is TListBox then
begin
Text := (src as TListBox).Items[(src as TListBox).ItemIndex];
end;
SynMemoQuery.SelText := Text;
SynMemoQuery.UndoList.AddGroupBreak; SynMemoQuery.UndoList.AddGroupBreak;
end; end;
@ -5320,6 +5342,68 @@ begin
end; end;
{**
Tabset right to query-memo was clicked
}
procedure TMDIChild.tabsetQueryHelpersChange(Sender: TObject; NewTab: Integer;
var AllowChange: Boolean);
var
i : Integer;
begin
// Leaving early if method was invoked manually without changing
// the tabIndex while listbox is already filled
if (NewTab = tabsetQueryHelpers.TabIndex) and (lboxQueryHelpers.Items.Count > 0) then
exit;
lboxQueryHelpers.Items.BeginUpdate;
lboxQueryHelpers.Items.Clear;
// By default sorted alpabetically
lboxQueryHelpers.Sorted := True;
case NewTab of
0: // Cols
begin
// Keep native order of columns
lboxQueryHelpers.Sorted := False;
for i := 0 to ListColumns.Items.Count - 1 do
begin
lboxQueryHelpers.Items.Add(ListColumns.Items[i].Caption);
end;
end;
1: // SQL functions
begin
for i := 0 to Mainform.SQLFunctionNames.Count - 1 do
begin
lboxQueryHelpers.Items.Add( Mainform.SQLFunctionNames[i] + Mainform.SQLFunctionDeclarations[i] );
end;
end;
2: // SQL keywords
begin
lboxQueryHelpers.Items := MYSQL_KEYWORDS;
lboxQueryHelpers.Sorted := True;
end;
end;
lboxQueryHelpers.Items.EndUpdate;
end;
{**
Insert string from listbox with query helpers into SQL
memo at doubleclick
}
procedure TMDIChild.lboxQueryHelpersDblClick(Sender: TObject);
begin
SynMemoQuery.SelText := lboxQueryHelpers.Items[lboxQueryHelpers.ItemIndex];
end;
end. end.

View File

@ -229,7 +229,9 @@ type
NativeFieldTypes : Boolean; NativeFieldTypes : Boolean;
LanguageOffset : Integer; LanguageOffset : Integer;
DataNullBackground : TColor; DataNullBackground : TColor;
sqlfunctionlist : TStringList; SQLFunctionNames,
SQLFunctionDeclarations,
SQLFunctionDescriptions : TStringList;
function GetRegValue( valueName: String; defaultValue: Integer; key: String = '' ) : Integer; Overload; function GetRegValue( valueName: String; defaultValue: Integer; key: String = '' ) : Integer; Overload;
function GetRegValue( valueName: String; defaultValue: Boolean; key: String = '' ) : Boolean; Overload; function GetRegValue( valueName: String; defaultValue: Boolean; key: String = '' ) : Boolean; Overload;
procedure SaveRegValue( valueName: String; value: Integer; key: String = '' ); Overload; procedure SaveRegValue( valueName: String; value: Integer; key: String = '' ); Overload;
@ -432,7 +434,10 @@ var
ws : String; ws : String;
mi : TMenuItem; mi : TMenuItem;
f : TextFile; f : TextFile;
functionname, functionhint : String; FunctionLine,
FunctionName,
FunctionDeclaration,
FunctionDescription : String;
i, pipeposition : Integer; i, pipeposition : Integer;
begin begin
caption := APPNAME; caption := APPNAME;
@ -499,28 +504,40 @@ begin
AssignFile(f, ExtractFilePath(paramstr(0)) + 'function.txt'); AssignFile(f, ExtractFilePath(paramstr(0)) + 'function.txt');
Reset(f); Reset(f);
i := 1; i := 1;
SQLFunctionNames := TStringList.Create;
SQLFunctionDeclarations := TStringList.Create;
SQLFunctionDescriptions := TStringList.Create;
while not eof(f) do while not eof(f) do
begin begin
functionname := ''; FunctionName := '';
Readln(f, functionname); FunctionDeclaration := '';
pipeposition := pos('|', functionname); FunctionDescription := '';
if pipeposition > 0 then // read hint Readln(f, FunctionLine);
begin
if sqlfunctionlist = nil then if (length(FunctionLine) > 0) and (FunctionLine[1] <> '#') then
sqlfunctionlist := TStringList.Create;
sqlfunctionlist.Add( trim(functionname) );
functionhint := copy(functionname, 0, pipeposition-1) + ' - ' + copy(functionname, pipeposition+1, length(functionname)-1);
functionname := copy(functionname, 0, pos('(', functionname)-1);
end else
functionhint := '';
if (functionname[1] <> '#') and (length(trim(functionname)) > 0) then
begin begin
FunctionName := FunctionLine;
if pos('(', FunctionName) > 0 then
FunctionName := copy(FunctionName, 0, pos('(', FunctionName)-1);
FunctionName := trim(FunctionName);
FunctionDeclaration := Copy(FunctionLine, 0, Pos( ')', FunctionLine ) );
FunctionDeclaration := Copy(FunctionDeclaration, Pos( '(', FunctionDeclaration ), Length(FunctionDeclaration) );
pipeposition := pos('|', FunctionLine);
if pipeposition > 0 then // read hint
begin
FunctionDescription := copy(FunctionLine, 0, pipeposition-1) + ' - ' + copy(FunctionLine, pipeposition+1, length(FunctionLine)-1);
FunctionDescription := trim(FunctionDescription);
end;
mi := TMenuItem.Create(self); mi := TMenuItem.Create(self);
mi.Caption := trim(functionname); mi.Caption := FunctionName;
mi.Hint := trim(functionhint); mi.Hint := FunctionDescription;
mi.OnClick := insertFunction; mi.OnClick := insertFunction;
if functionname[1] <> ' ' then // build submenu
if FunctionLine[1] <> ' ' then // build submenu
begin begin
SQLfunctions.Items.add(mi); SQLfunctions.Items.add(mi);
inc(i); inc(i);
@ -528,6 +545,9 @@ begin
begin begin
SQLfunctions.Items[i+11].OnClick := nil; // deactivate parent Menuitem SQLfunctions.Items[i+11].OnClick := nil; // deactivate parent Menuitem
SQLfunctions.Items[i+11].Add(mi); SQLfunctions.Items[i+11].Add(mi);
SQLFunctionNames.Add(FunctionName);
SQLFunctionDeclarations.Add(FunctionDeclaration);
SQLFunctionDescriptions.Add(FunctionDescription);
end; end;
end; end;
end; end;