mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-06 18:24:26 +08:00
Issue #1482: enable SQL help window
This commit is contained in:
@ -229,6 +229,13 @@
|
||||
<Filename Value="source\jsonregistry.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="source\sqlhelp.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<ComponentName Value="frmSQLhelp"/>
|
||||
<HasResources Value="True"/>
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
</Unit>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
@ -19,7 +19,7 @@ uses
|
||||
dbstructures.sqlite, change_password, loginform, data_sorting, extra_controls,
|
||||
column_selection, loaddata, csv_detector, createdatabase, editvar, copytable,
|
||||
exportgrid, usermanager, selectdbobject, reformatter, searchreplace,
|
||||
connections, jsonregistry {, printlist (EnablePrint not defined) }
|
||||
connections, jsonregistry, sqlhelp {, printlist (EnablePrint not defined) }
|
||||
;
|
||||
|
||||
{$R *.res}
|
||||
|
@ -1415,7 +1415,7 @@ implementation
|
||||
|
||||
uses
|
||||
FileInfo, winpeimagereader, elfreader, machoreader, About, data_sorting, column_selection, loaddata, editvar,
|
||||
copytable, csv_detector, exportgrid, usermanager, selectdbobject, reformatter, connections;
|
||||
copytable, csv_detector, exportgrid, usermanager, selectdbobject, reformatter, connections, sqlhelp;
|
||||
|
||||
{$R *.lfm}
|
||||
|
||||
@ -4903,10 +4903,10 @@ end;
|
||||
procedure TMainform.CallSQLHelpWithKeyword( keyword: String );
|
||||
begin
|
||||
if FActiveDbObj.Connection.Has(frHelpKeyword) then begin
|
||||
{if not Assigned(SqlHelpDialog) then
|
||||
if not Assigned(SqlHelpDialog) then
|
||||
SqlHelpDialog := TfrmSQLhelp.Create(Self);
|
||||
SqlHelpDialog.Show;
|
||||
SqlHelpDialog.Keyword := keyword;}
|
||||
SqlHelpDialog.Keyword := keyword;
|
||||
end else
|
||||
ErrorDialog(_('SQL help not available.'), f_('HELP <keyword> requires %s or newer.', ['MySQL 4.1']));
|
||||
end;
|
||||
@ -13273,10 +13273,10 @@ begin
|
||||
Editors.Add(frmPreferences.SynMemoSQLSample);}
|
||||
if Assigned(FCreateDatabaseDialog) then
|
||||
Editors.Add(FCreateDatabaseDialog.SynMemoCreateCode);
|
||||
{if SqlHelpDialog <> nil then begin
|
||||
if SqlHelpDialog <> nil then begin
|
||||
Editors.Add(SqlHelpDialog.memoDescription);
|
||||
Editors.Add(SqlHelpDialog.MemoExample);
|
||||
end;}
|
||||
end;
|
||||
{if Assigned(FTableToolsDialog) then
|
||||
Editors.Add(FTableToolsDialog.SynMemoFindText);}
|
||||
if Assigned(frmCsvDetector) then
|
||||
|
339
source/sqlhelp.lfm
Normal file
339
source/sqlhelp.lfm
Normal file
@ -0,0 +1,339 @@
|
||||
object frmSQLhelp: TfrmSQLhelp
|
||||
Left = 0
|
||||
Height = 444
|
||||
Top = 0
|
||||
Width = 728
|
||||
BorderWidth = 10
|
||||
Caption = 'Integrated SQL-help'
|
||||
ClientHeight = 444
|
||||
ClientWidth = 728
|
||||
Color = clBtnFace
|
||||
DesignTimePPI = 120
|
||||
FormStyle = fsStayOnTop
|
||||
OnClose = FormClose
|
||||
OnCreate = FormCreate
|
||||
OnShow = FormShow
|
||||
object pnlMain: TPanel
|
||||
Left = 10
|
||||
Height = 382
|
||||
Top = 10
|
||||
Width = 708
|
||||
Align = alClient
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 382
|
||||
ClientWidth = 708
|
||||
ParentBackground = False
|
||||
TabOrder = 0
|
||||
object Splitter1: TSplitter
|
||||
Cursor = crSizeWE
|
||||
Left = 191
|
||||
Height = 382
|
||||
Top = 0
|
||||
Width = 10
|
||||
end
|
||||
object pnlLeft: TPanel
|
||||
Left = 0
|
||||
Height = 382
|
||||
Top = 0
|
||||
Width = 191
|
||||
Align = alLeft
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 382
|
||||
ClientWidth = 191
|
||||
ParentBackground = False
|
||||
TabOrder = 0
|
||||
object editFilter: TEditButton
|
||||
Left = 0
|
||||
Height = 28
|
||||
Top = 0
|
||||
Width = 191
|
||||
Align = alTop
|
||||
ButtonWidth = 29
|
||||
Images = MainForm.ImageListIcons8
|
||||
ImageIndex = 193
|
||||
MaxLength = 0
|
||||
NumGlyphs = 1
|
||||
OnButtonClick = editFilterRightButtonClick
|
||||
OnChange = editFilterChange
|
||||
PasswordChar = #0
|
||||
TabOrder = 0
|
||||
TextHint = 'Filter'
|
||||
end
|
||||
object treeTopics: TLazVirtualStringTree
|
||||
Left = 0
|
||||
Height = 354
|
||||
Top = 28
|
||||
Width = 191
|
||||
Align = alClient
|
||||
Constraints.MinWidth = 38
|
||||
Header.AutoSizeIndex = 0
|
||||
Header.Columns = <>
|
||||
Header.MainColumn = -1
|
||||
Images = MainForm.ImageListIcons8
|
||||
TabOrder = 1
|
||||
TreeOptions.PaintOptions = [toHotTrack, toShowButtons, toShowDropmark, toShowRoot, toShowTreeLines, toThemeAware, toUseBlendedImages, toUseExplorerTheme, toHideTreeLinesIfThemed]
|
||||
OnFocusChanged = treeTopicsFocusChanged
|
||||
OnFreeNode = treeTopicsFreeNode
|
||||
OnGetText = treeTopicsGetText
|
||||
OnGetImageIndex = treeTopicsGetImageIndex
|
||||
OnGetNodeDataSize = treeTopicsGetNodeDataSize
|
||||
OnInitChildren = treeTopicsInitChildren
|
||||
OnInitNode = treeTopicsInitNode
|
||||
end
|
||||
end
|
||||
object pnlRight: TPanel
|
||||
Left = 201
|
||||
Height = 382
|
||||
Top = 0
|
||||
Width = 507
|
||||
Align = alClient
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 382
|
||||
ClientWidth = 507
|
||||
ParentBackground = False
|
||||
TabOrder = 1
|
||||
object Splitter2: TSplitter
|
||||
Cursor = crVSplit
|
||||
Left = 0
|
||||
Height = 10
|
||||
Top = 212
|
||||
Width = 507
|
||||
Align = alTop
|
||||
ResizeAnchor = akTop
|
||||
end
|
||||
object lblDescription: TLabel
|
||||
Left = 0
|
||||
Height = 20
|
||||
Top = 1
|
||||
Width = 507
|
||||
Align = alTop
|
||||
Caption = 'Description:'
|
||||
end
|
||||
object lblKeyword: TLabel
|
||||
Left = 0
|
||||
Height = 1
|
||||
Top = 0
|
||||
Width = 507
|
||||
Align = alTop
|
||||
ShowAccelChar = False
|
||||
end
|
||||
object lblExample: TLabel
|
||||
Left = 0
|
||||
Height = 20
|
||||
Top = 222
|
||||
Width = 507
|
||||
Align = alTop
|
||||
Caption = 'Example:'
|
||||
end
|
||||
inline memoDescription: TSynEdit
|
||||
Left = 0
|
||||
Height = 191
|
||||
Top = 21
|
||||
Width = 507
|
||||
Align = alTop
|
||||
Constraints.MinHeight = 38
|
||||
Font.Height = -16
|
||||
Font.Name = 'Courier New'
|
||||
Font.Pitch = fpFixed
|
||||
Font.Quality = fqNonAntialiased
|
||||
ParentColor = False
|
||||
ParentFont = False
|
||||
TabOrder = 0
|
||||
OnKeyDown = memosKeyDown
|
||||
Gutter.Visible = False
|
||||
Gutter.Width = 72
|
||||
Gutter.MouseActions = <>
|
||||
RightGutter.Width = 0
|
||||
RightGutter.MouseActions = <>
|
||||
Keystrokes = <>
|
||||
MouseActions = <>
|
||||
MouseTextActions = <>
|
||||
MouseSelActions = <>
|
||||
Options = [eoAutoIndent, eoGroupUndo, eoShowScrollHint, eoSmartTabs, eoTabsToSpaces, eoDragDropEditing]
|
||||
MouseOptions = [emDragDropEditing]
|
||||
VisibleSpecialChars = [vscSpace, vscTabAtLast]
|
||||
ReadOnly = True
|
||||
RightEdge = 0
|
||||
SelectedColor.BackPriority = 50
|
||||
SelectedColor.ForePriority = 50
|
||||
SelectedColor.FramePriority = 50
|
||||
SelectedColor.BoldPriority = 50
|
||||
SelectedColor.ItalicPriority = 50
|
||||
SelectedColor.UnderlinePriority = 50
|
||||
SelectedColor.StrikeOutPriority = 50
|
||||
BracketHighlightStyle = sbhsBoth
|
||||
BracketMatchColor.Background = clNone
|
||||
BracketMatchColor.Foreground = clNone
|
||||
BracketMatchColor.Style = [fsBold]
|
||||
FoldedCodeColor.Background = clNone
|
||||
FoldedCodeColor.Foreground = clGray
|
||||
FoldedCodeColor.FrameColor = clGray
|
||||
MouseLinkColor.Background = clNone
|
||||
MouseLinkColor.Foreground = clBlue
|
||||
LineHighlightColor.Background = clNone
|
||||
LineHighlightColor.Foreground = clNone
|
||||
inline SynLeftGutterPartList1: TSynGutterPartList
|
||||
object SynGutterMarks1: TSynGutterMarks
|
||||
Width = 30
|
||||
MouseActions = <>
|
||||
end
|
||||
object SynGutterLineNumber1: TSynGutterLineNumber
|
||||
Width = 21
|
||||
MouseActions = <>
|
||||
MarkupInfo.Background = clBtnFace
|
||||
MarkupInfo.Foreground = clNone
|
||||
DigitCount = 2
|
||||
ShowOnlyLineNumbersMultiplesOf = 1
|
||||
ZeroStart = False
|
||||
LeadingZeros = False
|
||||
end
|
||||
object SynGutterChanges1: TSynGutterChanges
|
||||
Width = 5
|
||||
MouseActions = <>
|
||||
ModifiedColor = 59900
|
||||
SavedColor = clGreen
|
||||
end
|
||||
object SynGutterSeparator1: TSynGutterSeparator
|
||||
Width = 3
|
||||
MouseActions = <>
|
||||
MarkupInfo.Background = clWhite
|
||||
MarkupInfo.Foreground = clGray
|
||||
end
|
||||
object SynGutterCodeFolding1: TSynGutterCodeFolding
|
||||
Width = 13
|
||||
MouseActions = <>
|
||||
MarkupInfo.Background = clNone
|
||||
MarkupInfo.Foreground = clGray
|
||||
MouseActionsExpanded = <>
|
||||
MouseActionsCollapsed = <>
|
||||
end
|
||||
end
|
||||
end
|
||||
inline MemoExample: TSynEdit
|
||||
Left = 0
|
||||
Height = 140
|
||||
Top = 242
|
||||
Width = 507
|
||||
Align = alClient
|
||||
Constraints.MinHeight = 38
|
||||
Font.Height = -16
|
||||
Font.Name = 'Courier New'
|
||||
Font.Pitch = fpFixed
|
||||
Font.Quality = fqNonAntialiased
|
||||
ParentColor = False
|
||||
ParentFont = False
|
||||
TabOrder = 1
|
||||
OnKeyDown = memosKeyDown
|
||||
Gutter.Visible = False
|
||||
Gutter.Width = 72
|
||||
Gutter.MouseActions = <>
|
||||
RightGutter.Width = 0
|
||||
RightGutter.MouseActions = <>
|
||||
Keystrokes = <>
|
||||
MouseActions = <>
|
||||
MouseTextActions = <>
|
||||
MouseSelActions = <>
|
||||
Options = [eoAutoIndent, eoGroupUndo, eoShowScrollHint, eoSmartTabs, eoTabsToSpaces, eoDragDropEditing]
|
||||
MouseOptions = [emDragDropEditing]
|
||||
VisibleSpecialChars = [vscSpace, vscTabAtLast]
|
||||
ReadOnly = True
|
||||
RightEdge = 0
|
||||
SelectedColor.BackPriority = 50
|
||||
SelectedColor.ForePriority = 50
|
||||
SelectedColor.FramePriority = 50
|
||||
SelectedColor.BoldPriority = 50
|
||||
SelectedColor.ItalicPriority = 50
|
||||
SelectedColor.UnderlinePriority = 50
|
||||
SelectedColor.StrikeOutPriority = 50
|
||||
BracketHighlightStyle = sbhsBoth
|
||||
BracketMatchColor.Background = clNone
|
||||
BracketMatchColor.Foreground = clNone
|
||||
BracketMatchColor.Style = [fsBold]
|
||||
FoldedCodeColor.Background = clNone
|
||||
FoldedCodeColor.Foreground = clGray
|
||||
FoldedCodeColor.FrameColor = clGray
|
||||
MouseLinkColor.Background = clNone
|
||||
MouseLinkColor.Foreground = clBlue
|
||||
LineHighlightColor.Background = clNone
|
||||
LineHighlightColor.Foreground = clNone
|
||||
inline SynLeftGutterPartList1: TSynGutterPartList
|
||||
object SynGutterMarks1: TSynGutterMarks
|
||||
Width = 30
|
||||
MouseActions = <>
|
||||
end
|
||||
object SynGutterLineNumber1: TSynGutterLineNumber
|
||||
Width = 21
|
||||
MouseActions = <>
|
||||
MarkupInfo.Background = clBtnFace
|
||||
MarkupInfo.Foreground = clNone
|
||||
DigitCount = 2
|
||||
ShowOnlyLineNumbersMultiplesOf = 1
|
||||
ZeroStart = False
|
||||
LeadingZeros = False
|
||||
end
|
||||
object SynGutterChanges1: TSynGutterChanges
|
||||
Width = 5
|
||||
MouseActions = <>
|
||||
ModifiedColor = 59900
|
||||
SavedColor = clGreen
|
||||
end
|
||||
object SynGutterSeparator1: TSynGutterSeparator
|
||||
Width = 3
|
||||
MouseActions = <>
|
||||
MarkupInfo.Background = clWhite
|
||||
MarkupInfo.Foreground = clGray
|
||||
end
|
||||
object SynGutterCodeFolding1: TSynGutterCodeFolding
|
||||
Width = 13
|
||||
MouseActions = <>
|
||||
MarkupInfo.Background = clNone
|
||||
MarkupInfo.Foreground = clGray
|
||||
MouseActionsExpanded = <>
|
||||
MouseActionsCollapsed = <>
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
object pnlBottom: TPanel
|
||||
Left = 10
|
||||
Height = 42
|
||||
Top = 392
|
||||
Width = 708
|
||||
Align = alBottom
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 42
|
||||
ClientWidth = 708
|
||||
ParentBackground = False
|
||||
TabOrder = 1
|
||||
object btnSearchOnline: TSpeedButton
|
||||
Left = 444
|
||||
Height = 31
|
||||
Top = 8
|
||||
Width = 129
|
||||
Anchors = [akTop, akRight]
|
||||
Caption = 'Search online'
|
||||
Images = MainForm.ImageListIcons8
|
||||
ImageIndex = 69
|
||||
OnClick = ButtonOnlinehelpClick
|
||||
end
|
||||
object ButtonClose: TButton
|
||||
Left = 580
|
||||
Height = 31
|
||||
Top = 8
|
||||
Width = 128
|
||||
Anchors = [akTop, akRight]
|
||||
Cancel = True
|
||||
Caption = 'Close'
|
||||
Default = True
|
||||
TabOrder = 0
|
||||
OnClick = ButtonCloseClick
|
||||
end
|
||||
end
|
||||
object timerSearch: TTimer
|
||||
Interval = 500
|
||||
OnTimer = DoSearch
|
||||
Left = 10
|
||||
Top = 400
|
||||
end
|
||||
end
|
427
source/sqlhelp.pas
Normal file
427
source/sqlhelp.pas
Normal file
@ -0,0 +1,427 @@
|
||||
unit sqlhelp;
|
||||
|
||||
{$mode delphi}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls,
|
||||
Buttons, SynEdit, SynEditHighlighter, extra_controls,
|
||||
laz.VirtualTrees, Graphics, EditBtn,
|
||||
dbconnection;
|
||||
|
||||
type
|
||||
|
||||
{ TfrmSQLhelp }
|
||||
|
||||
TfrmSQLhelp = class(TExtForm)
|
||||
//URIOpenerDescription: TSynURIOpener;
|
||||
//URIHighlighter: TSynURISyn;
|
||||
//URIOpenerExample: TSynURIOpener;
|
||||
btnSearchOnline: TSpeedButton;
|
||||
ButtonClose: TButton;
|
||||
pnlBottom: TPanel;
|
||||
pnlMain: TPanel;
|
||||
pnlLeft: TPanel;
|
||||
treeTopics: TLazVirtualStringTree;
|
||||
editFilter: TEditButton;
|
||||
pnlRight: TPanel;
|
||||
Splitter2: TSplitter;
|
||||
Splitter1: TSplitter;
|
||||
lblDescription: TLabel;
|
||||
lblKeyword: TLabel;
|
||||
memoDescription: TSynEdit;
|
||||
lblExample: TLabel;
|
||||
MemoExample: TSynEdit;
|
||||
timerSearch: TTimer;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure memosKeyDown(Sender: TObject; var Key: Word;
|
||||
Shift: TShiftState);
|
||||
procedure ButtonOnlinehelpClick(Sender: TObject);
|
||||
procedure ButtonCloseClick(Sender: TObject);
|
||||
procedure DoSearch(Sender: TObject);
|
||||
procedure treeTopicsGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
|
||||
procedure treeTopicsInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode;
|
||||
var InitialStates: TVirtualNodeInitStates);
|
||||
procedure treeTopicsInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
var ChildCount: Cardinal);
|
||||
procedure treeTopicsGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
|
||||
procedure treeTopicsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
|
||||
procedure treeTopicsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
procedure treeTopicsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Column: TColumnIndex);
|
||||
procedure editFilterChange(Sender: TObject);
|
||||
procedure editFilterRightButtonClick(Sender: TObject);
|
||||
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
procedure FormShow(Sender: TObject);
|
||||
|
||||
private
|
||||
{ Private declarations }
|
||||
FConnection: TDBConnection;
|
||||
FKeyword: String;
|
||||
FRootTopics: TDBQuery;
|
||||
function GetHelpResult(Node: PVirtualNode): TDBQuery;
|
||||
procedure SetKeyword(Value: String);
|
||||
public
|
||||
{ Public declarations }
|
||||
property Keyword: String read FKeyword write SetKeyword;
|
||||
end;
|
||||
|
||||
var
|
||||
SqlHelpDialog: TfrmSQLhelp; // global var, so we can apply settings via SetupSynEditors
|
||||
|
||||
const
|
||||
DEFAULT_WINDOW_CAPTION : String = 'Integrated SQL-help' ;
|
||||
ICONINDEX_CATEGORY_CLOSED : Integer = 66;
|
||||
ICONINDEX_CATEGORY_OPENED : Integer = 67;
|
||||
ICONINDEX_HELPITEM : Integer = 68;
|
||||
|
||||
implementation
|
||||
|
||||
uses apphelpers, main;
|
||||
|
||||
{$I const.inc}
|
||||
|
||||
{$R *.lfm}
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.FormCreate(Sender: TObject);
|
||||
begin
|
||||
// Set window-layout
|
||||
lblKeyword.Font.Style := [fsBold];
|
||||
Caption := DEFAULT_WINDOW_CAPTION;
|
||||
FixVT(treeTopics);
|
||||
HasSizeGrip := True;
|
||||
|
||||
treeTopics.Clear;
|
||||
FreeAndNil(FRootTopics);
|
||||
FConnection := MainForm.ActiveConnection;
|
||||
FRootTopics := FConnection.GetResults('HELP '+FConnection.EscapeString('CONTENTS'));
|
||||
treeTopics.RootNodeCount := FRootTopics.RecordCount;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
begin
|
||||
AppSettings.WriteInt(asSQLHelpWindowLeft, Left );
|
||||
AppSettings.WriteInt(asSQLHelpWindowTop, Top );
|
||||
AppSettings.WriteIntDpiAware(asSQLHelpWindowWidth, Self, Width);
|
||||
AppSettings.WriteIntDpiAware(asSQLHelpWindowHeight, Self, Height);
|
||||
AppSettings.WriteIntDpiAware(asSQLHelpPnlLeftWidth, Self, pnlLeft.Width);
|
||||
AppSettings.WriteIntDpiAware(asSQLHelpPnlRightTopHeight, Self, memoDescription.Height);
|
||||
Action := caFree;
|
||||
SqlHelpDialog := nil;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Column: TColumnIndex);
|
||||
var
|
||||
Results: TDBQuery;
|
||||
VT: TVirtualStringTree;
|
||||
begin
|
||||
// Topic selected
|
||||
VT := Sender as TVirtualStringTree;
|
||||
if not Assigned(VT.FocusedNode) then
|
||||
Exit;
|
||||
if VT.HasChildren[VT.FocusedNode] then
|
||||
Exit;
|
||||
FKeyword := VT.Text[VT.FocusedNode, VT.FocusedColumn];
|
||||
lblKeyword.Caption := Copy(FKeyword, 0, 100);
|
||||
MemoDescription.Lines.Clear;
|
||||
MemoExample.Lines.Clear;
|
||||
Caption := DEFAULT_WINDOW_CAPTION;
|
||||
|
||||
if FKeyword <> '' then try
|
||||
Screen.Cursor := crHourglass;
|
||||
Results := FConnection.GetResults('HELP '+FConnection.EscapeString(FKeyword));
|
||||
Caption := Caption + ' - ' + FKeyword;
|
||||
MemoDescription.Text := fixNewlines(Results.Col('description', True));
|
||||
MemoExample.Text := fixNewlines(Results.Col('example', True));
|
||||
finally
|
||||
FreeAndNil(Results);
|
||||
Screen.Cursor := crDefault;
|
||||
end;
|
||||
|
||||
// Show the user if topic is (not) available
|
||||
if memoDescription.GetTextLen = 0 then
|
||||
memoDescription.Text := _('No help available for this keyword or no keyword was selected.');
|
||||
if memoExample.GetTextLen = 0 then
|
||||
memoExample.Text := _('No example available or no keyword was selected.');
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
var
|
||||
Results: PDBQuery;
|
||||
begin
|
||||
// Node gets destroyed - free memory used for bound SQL result
|
||||
Results := Sender.GetNodeData(Node);
|
||||
if Assigned(Results^) then
|
||||
Results^.Free;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex);
|
||||
begin
|
||||
// Return open or closed book icon for folders, or document icon for topics
|
||||
if not (Kind in [ikNormal, ikSelected]) then
|
||||
Exit;
|
||||
if Sender.HasChildren[Node] then begin
|
||||
if Sender.Expanded[Node] then
|
||||
ImageIndex := ICONINDEX_CATEGORY_OPENED
|
||||
else
|
||||
ImageIndex := ICONINDEX_CATEGORY_CLOSED;
|
||||
end else
|
||||
ImageIndex := ICONINDEX_HELPITEM;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsGetNodeDataSize(Sender: TBaseVirtualTree;
|
||||
var NodeDataSize: Integer);
|
||||
begin
|
||||
// We bind one TDBQuery to a node
|
||||
NodeDataSize := SizeOf(TDBQuery);
|
||||
end;
|
||||
|
||||
|
||||
function TfrmSQLhelp.GetHelpResult(Node: PVirtualNode): TDBQuery;
|
||||
var
|
||||
P: PDBQuery;
|
||||
begin
|
||||
// Find right result set for given node
|
||||
if treeTopics.GetNodeLevel(Node) = 0 then
|
||||
Result := FRootTopics
|
||||
else begin
|
||||
P := treeTopics.GetNodeData(Node.Parent);
|
||||
Result := P^;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
|
||||
var
|
||||
Results: TDBQuery;
|
||||
begin
|
||||
// Ask result set for node text
|
||||
Results := GetHelpResult(Node);
|
||||
Results.RecNo := Node.Index;
|
||||
CellText := Results.Col('name');
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
var ChildCount: Cardinal);
|
||||
var
|
||||
Results: PDBQuery;
|
||||
VT: TVirtualStringTree;
|
||||
begin
|
||||
// Return number of children for folder
|
||||
VT := Sender as TVirtualStringTree;
|
||||
Results := VT.GetNodeData(Node);
|
||||
Results^ := FConnection.GetResults('HELP '+FConnection.EscapeString(VT.Text[Node, VT.Header.MainColumn]));
|
||||
ChildCount := Results.RecordCount;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsInitNode(Sender: TBaseVirtualTree; ParentNode,
|
||||
Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
|
||||
var
|
||||
Results: TDBQuery;
|
||||
ThisFolder, PrevFolder: String;
|
||||
N: PVirtualNode;
|
||||
VT: TVirtualStringTree;
|
||||
RecursionAlarm: Boolean;
|
||||
begin
|
||||
// Display plus button for nodes which are folders
|
||||
VT := Sender as TVirtualStringTree;
|
||||
Results := GetHelpResult(Node);
|
||||
Results.RecNo := Node.Index;
|
||||
if Results.Col('is_it_category', True) = 'Y' then begin
|
||||
// Some random server versions have duplicated category names in help tables, which would cause
|
||||
// infinite tree recursion, e.g. for "Polygon properties" > "Contents". Do not display these
|
||||
// duplicates as folder
|
||||
RecursionAlarm := False;
|
||||
ThisFolder := Results.Col('name');
|
||||
N := VT.GetPreviousInitialized(Node);
|
||||
while Assigned(N) do begin
|
||||
PrevFolder := VT.Text[N, VT.Header.MainColumn];
|
||||
if VT.HasChildren[N] and ((ThisFolder=PrevFolder) or (ThisFolder='Contents')) then begin
|
||||
RecursionAlarm := True;
|
||||
break;
|
||||
end;
|
||||
N := VT.GetPreviousInitialized(N);
|
||||
end;
|
||||
if not RecursionAlarm then
|
||||
Include(InitialStates, ivsHasChildren);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.ButtonCloseClick(Sender: TObject);
|
||||
begin
|
||||
Close;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.FormShow(Sender: TObject);
|
||||
begin
|
||||
Top := AppSettings.ReadInt(asSQLHelpWindowTop);
|
||||
Left := AppSettings.ReadInt(asSQLHelpWindowLeft);
|
||||
Width := AppSettings.ReadIntDpiAware(asSQLHelpWindowWidth, Self);
|
||||
Height := AppSettings.ReadIntDpiAware(asSQLHelpWindowHeight, Self);
|
||||
MakeFullyVisible;
|
||||
|
||||
pnlLeft.Width := AppSettings.ReadIntDpiAware(asSQLHelpPnlLeftWidth, Self);
|
||||
memoDescription.Height := AppSettings.ReadIntDpiAware(asSQLHelpPnlRightTopHeight, Self);
|
||||
// Apply themed colors in OnShow, not OnCreate, as a check with <> nil returns false otherwise
|
||||
MainForm.SetupSynEditors(Self);
|
||||
// These SynMemo's don't have any (SQL) highligher, so we have to assign correct colors for basic text
|
||||
memoDescription.Font.Color := GetThemeColor(clWindowText);
|
||||
MemoExample.Font.Color := GetThemeColor(clWindowText);
|
||||
editFilter.SetFocus;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.ButtonOnlinehelpClick(Sender: TObject);
|
||||
begin
|
||||
// Link/redirect to mysql.com for further help
|
||||
ShellExec(APPDOMAIN + 'sqlhelp.php?mysqlversion='+inttostr(FConnection.ServerVersionInt)+
|
||||
'&keyword='+EncodeURLParam(keyword));
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.memosKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
||||
begin
|
||||
// Esc pressed - close form.
|
||||
// Seems that if we're in a memo, the ButtonClose.Cancel=True doesn't have an effect
|
||||
//if Key = VK_ESCAPE then
|
||||
// Close;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.SetKeyword(Value: string);
|
||||
var
|
||||
VT: TVirtualStringTree;
|
||||
Node: PVirtualNode;
|
||||
Results: TDBQuery;
|
||||
SearchNoInit: Boolean;
|
||||
begin
|
||||
// Find keyword in tree
|
||||
FKeyword := Value;
|
||||
if FKeyword = '' then
|
||||
Exit;
|
||||
Results := FConnection.GetResults('HELP '+FConnection.EscapeString(FKeyword));
|
||||
while not Results.Eof do begin
|
||||
if Results.Col('is_it_category', true) = 'N' then begin
|
||||
FKeyword := Results.Col('name');
|
||||
break;
|
||||
end;
|
||||
Results.Next;
|
||||
end;
|
||||
FreeAndNil(Results);
|
||||
|
||||
VT := treeTopics;
|
||||
if (not Assigned(VT.FocusedNode)) // No node selected
|
||||
or VT.HasChildren[VT.FocusedNode] // Selected node is a folder, not a document
|
||||
or (VT.Text[VT.FocusedNode, VT.Header.MainColumn] <> FKeyword) // Node is not the right one
|
||||
then begin
|
||||
// Start searching in initialized nodes, to minimize number of "HELP xyz" queries in certain cases
|
||||
Node := VT.GetFirst;
|
||||
SearchNoInit := False;
|
||||
while Assigned(Node) do begin
|
||||
if (not VT.HasChildren[Node]) and (UpperCase(VT.Text[Node, VT.Header.MainColumn]) = UpperCase(FKeyword)) then begin
|
||||
SelectNode(VT, Node);
|
||||
break;
|
||||
end;
|
||||
if not SearchNoInit then begin
|
||||
Node := VT.GetNextInitialized(Node);
|
||||
if not Assigned(Node) then begin
|
||||
SearchNoInit := True;
|
||||
Node := VT.GetFirst;
|
||||
end;
|
||||
end;
|
||||
if SearchNoInit then
|
||||
Node := VT.GetNext(Node);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.editFilterChange(Sender: TObject);
|
||||
begin
|
||||
timerSearch.Enabled := False;
|
||||
timerSearch.Enabled := True;
|
||||
editFilter.Button.Enabled := Trim(editFilter.Text) <> '';
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.editFilterRightButtonClick(Sender: TObject);
|
||||
begin
|
||||
editFilter.Clear;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.DoSearch(Sender: TObject);
|
||||
var
|
||||
Node: PVirtualNode;
|
||||
Search: String;
|
||||
Vis: Boolean;
|
||||
|
||||
function HasVisibleChildItems(Node: PVirtualNode): Boolean;
|
||||
var
|
||||
N: PVirtualNode;
|
||||
begin
|
||||
N := treeTopics.GetFirstChild(Node);
|
||||
Result := False;
|
||||
while Assigned(N) do begin
|
||||
if treeTopics.HasChildren[N] then
|
||||
Result := HasVisibleChildItems(N)
|
||||
else
|
||||
Result := treeTopics.IsVisible[N];
|
||||
if Result then
|
||||
Exit;
|
||||
N := treeTopics.GetNextSibling(N);
|
||||
end;
|
||||
end;
|
||||
begin
|
||||
// Apply filter text
|
||||
Screen.Cursor := crHourglass;
|
||||
treeTopics.BeginUpdate;
|
||||
timerSearch.Enabled := False;
|
||||
Search := Trim(editFilter.Text);
|
||||
if Search = '' then begin
|
||||
// Show all items
|
||||
Node := treeTopics.GetFirstInitialized;
|
||||
while Assigned(Node) do begin
|
||||
treeTopics.IsVisible[Node] := True;
|
||||
Node := treeTopics.GetNextInitialized(Node);
|
||||
end;
|
||||
end else begin
|
||||
// Hide non matching child items
|
||||
Node := treeTopics.GetFirst;
|
||||
while Assigned(Node) do begin
|
||||
if not treeTopics.HasChildren[Node] then
|
||||
treeTopics.IsVisible[Node] := Pos(UpperCase(Search), UpperCase(treeTopics.Text[Node, treeTopics.Header.MainColumn])) > 0;
|
||||
Node := treeTopics.GetNext(Node);
|
||||
end;
|
||||
// Hide empty folders
|
||||
Node := treeTopics.GetFirst;
|
||||
while Assigned(Node) do begin
|
||||
if treeTopics.HasChildren[Node] then begin
|
||||
Vis := HasVisibleChildItems(Node);
|
||||
treeTopics.Expanded[Node] := Vis;
|
||||
treeTopics.IsVisible[Node] := Vis;
|
||||
end;
|
||||
Node := treeTopics.GetNext(Node);
|
||||
end;
|
||||
end;
|
||||
treeTopics.EndUpdate;
|
||||
Screen.Cursor := crDefault;
|
||||
end;
|
||||
|
||||
end.
|
Reference in New Issue
Block a user