+ fcl-db tests: GUI test framework: add db connector selector/editor. Addresses issue #23483

git-svn-id: trunk@23162 -
This commit is contained in:
reiniero 2012-12-17 13:15:20 +00:00
parent 83f411adb9
commit 4820160ed1
5 changed files with 854 additions and 5 deletions

2
.gitattributes vendored
View File

@ -2135,6 +2135,8 @@ packages/fcl-db/tests/dbftoolsunit.pas svneol=native#text/plain
packages/fcl-db/tests/dbtestframework.pas svneol=native#text/plain
packages/fcl-db/tests/dbtestframework_gui.lpi svneol=native#text/plain
packages/fcl-db/tests/dbtestframework_gui.lpr svneol=native#text/plain
packages/fcl-db/tests/inieditor.lfm svneol=native#text/plain
packages/fcl-db/tests/inieditor.pas svneol=native#text/plain
packages/fcl-db/tests/memdstoolsunit.pas svneol=native#text/plain
packages/fcl-db/tests/sdfdstoolsunit.pas svneol=native#text/plain
packages/fcl-db/tests/sqldbtoolsunit.pas svneol=native#text/plain

View File

@ -42,16 +42,19 @@
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="3">
<RequiredPackages Count="4">
<Item1>
<PackageName Value="FPCUnitTestRunner"/>
<PackageName Value="SynEdit"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
<PackageName Value="FPCUnitTestRunner"/>
</Item2>
<Item3>
<PackageName Value="FCL"/>
<PackageName Value="LCL"/>
</Item3>
<Item4>
<PackageName Value="FCL"/>
</Item4>
</RequiredPackages>
<Units Count="1">
<Unit0>

View File

@ -10,7 +10,9 @@ program dbtestframework_gui;
// the .ppu files before you can build fcl-db in the regular way. (Using fpmake)
uses
Interfaces, Forms, GuiTestRunner,
Interfaces, Forms,
// GUI:
GuiTestRunner, inieditor,
// Generic DB test framework units
ToolsUnit,
// Connectors for different database-types
@ -30,8 +32,20 @@ uses
{$R *.res}
var
DBSelectForm: TFormIniEditor;
begin
Application.Initialize;
DBSelectForm:=TFormIniEditor.Create(nil);
try
DBSelectForm.INIFile:='database.ini';
DBSelectForm.ProfileSelectSection:='Database';
DBSelectForm.ProfileSelectKey:='type';
// We can ignore resulting db selection as the file is saved already:
DBSelectForm.ShowModal;
finally
DBSelectForm.Free;
end;
Application.CreateForm(TGuiTestRunner, TestRunner);
Application.Run;
end.

View File

@ -0,0 +1,579 @@
object FormIniEditor: TFormIniEditor
Left = 238
Height = 501
Top = 145
Width = 754
Caption = 'Select/edit profile'
ClientHeight = 501
ClientWidth = 754
OnCloseQuery = FormCloseQuery
OnCreate = FormCreate
OnDestroy = FormDestroy
OnDropFiles = FormDropFiles
OnShow = FormShow
LCLVersion = '1.1'
inline SynMemo: TSynMemo
Cursor = crIBeam
Left = 8
Height = 360
Top = 88
Width = 736
Font.Height = -13
Font.Name = 'Courier New'
Font.Pitch = fpFixed
Font.Quality = fqNonAntialiased
ParentColor = False
ParentFont = False
TabOrder = 2
Gutter.Width = 57
Gutter.MouseActions = <>
Highlighter = SynIniHighlighter
Keystrokes = <
item
Command = ecUp
ShortCut = 38
end
item
Command = ecSelUp
ShortCut = 8230
end
item
Command = ecScrollUp
ShortCut = 16422
end
item
Command = ecDown
ShortCut = 40
end
item
Command = ecSelDown
ShortCut = 8232
end
item
Command = ecScrollDown
ShortCut = 16424
end
item
Command = ecLeft
ShortCut = 37
end
item
Command = ecSelLeft
ShortCut = 8229
end
item
Command = ecWordLeft
ShortCut = 16421
end
item
Command = ecSelWordLeft
ShortCut = 24613
end
item
Command = ecRight
ShortCut = 39
end
item
Command = ecSelRight
ShortCut = 8231
end
item
Command = ecWordRight
ShortCut = 16423
end
item
Command = ecSelWordRight
ShortCut = 24615
end
item
Command = ecPageDown
ShortCut = 34
end
item
Command = ecSelPageDown
ShortCut = 8226
end
item
Command = ecPageBottom
ShortCut = 16418
end
item
Command = ecSelPageBottom
ShortCut = 24610
end
item
Command = ecPageUp
ShortCut = 33
end
item
Command = ecSelPageUp
ShortCut = 8225
end
item
Command = ecPageTop
ShortCut = 16417
end
item
Command = ecSelPageTop
ShortCut = 24609
end
item
Command = ecLineStart
ShortCut = 36
end
item
Command = ecSelLineStart
ShortCut = 8228
end
item
Command = ecEditorTop
ShortCut = 16420
end
item
Command = ecSelEditorTop
ShortCut = 24612
end
item
Command = ecLineEnd
ShortCut = 35
end
item
Command = ecSelLineEnd
ShortCut = 8227
end
item
Command = ecEditorBottom
ShortCut = 16419
end
item
Command = ecSelEditorBottom
ShortCut = 24611
end
item
Command = ecToggleMode
ShortCut = 45
end
item
Command = ecCopy
ShortCut = 16429
end
item
Command = ecPaste
ShortCut = 8237
end
item
Command = ecDeleteChar
ShortCut = 46
end
item
Command = ecCut
ShortCut = 8238
end
item
Command = ecDeleteLastChar
ShortCut = 8
end
item
Command = ecDeleteLastChar
ShortCut = 8200
end
item
Command = ecDeleteLastWord
ShortCut = 16392
end
item
Command = ecUndo
ShortCut = 32776
end
item
Command = ecRedo
ShortCut = 40968
end
item
Command = ecLineBreak
ShortCut = 13
end
item
Command = ecSelectAll
ShortCut = 16449
end
item
Command = ecCopy
ShortCut = 16451
end
item
Command = ecBlockIndent
ShortCut = 24649
end
item
Command = ecLineBreak
ShortCut = 16461
end
item
Command = ecInsertLine
ShortCut = 16462
end
item
Command = ecDeleteWord
ShortCut = 16468
end
item
Command = ecBlockUnindent
ShortCut = 24661
end
item
Command = ecPaste
ShortCut = 16470
end
item
Command = ecCut
ShortCut = 16472
end
item
Command = ecDeleteLine
ShortCut = 16473
end
item
Command = ecDeleteEOL
ShortCut = 24665
end
item
Command = ecUndo
ShortCut = 16474
end
item
Command = ecRedo
ShortCut = 24666
end
item
Command = ecGotoMarker0
ShortCut = 16432
end
item
Command = ecGotoMarker1
ShortCut = 16433
end
item
Command = ecGotoMarker2
ShortCut = 16434
end
item
Command = ecGotoMarker3
ShortCut = 16435
end
item
Command = ecGotoMarker4
ShortCut = 16436
end
item
Command = ecGotoMarker5
ShortCut = 16437
end
item
Command = ecGotoMarker6
ShortCut = 16438
end
item
Command = ecGotoMarker7
ShortCut = 16439
end
item
Command = ecGotoMarker8
ShortCut = 16440
end
item
Command = ecGotoMarker9
ShortCut = 16441
end
item
Command = ecSetMarker0
ShortCut = 24624
end
item
Command = ecSetMarker1
ShortCut = 24625
end
item
Command = ecSetMarker2
ShortCut = 24626
end
item
Command = ecSetMarker3
ShortCut = 24627
end
item
Command = ecSetMarker4
ShortCut = 24628
end
item
Command = ecSetMarker5
ShortCut = 24629
end
item
Command = ecSetMarker6
ShortCut = 24630
end
item
Command = ecSetMarker7
ShortCut = 24631
end
item
Command = ecSetMarker8
ShortCut = 24632
end
item
Command = ecSetMarker9
ShortCut = 24633
end
item
Command = EcFoldLevel1
ShortCut = 41009
end
item
Command = EcFoldLevel2
ShortCut = 41010
end
item
Command = EcFoldLevel1
ShortCut = 41011
end
item
Command = EcFoldLevel1
ShortCut = 41012
end
item
Command = EcFoldLevel1
ShortCut = 41013
end
item
Command = EcFoldLevel6
ShortCut = 41014
end
item
Command = EcFoldLevel7
ShortCut = 41015
end
item
Command = EcFoldLevel8
ShortCut = 41016
end
item
Command = EcFoldLevel9
ShortCut = 41017
end
item
Command = EcFoldLevel0
ShortCut = 41008
end
item
Command = EcFoldCurrent
ShortCut = 41005
end
item
Command = EcUnFoldCurrent
ShortCut = 41003
end
item
Command = EcToggleMarkupWord
ShortCut = 32845
end
item
Command = ecNormalSelect
ShortCut = 24654
end
item
Command = ecColumnSelect
ShortCut = 24643
end
item
Command = ecLineSelect
ShortCut = 24652
end
item
Command = ecTab
ShortCut = 9
end
item
Command = ecShiftTab
ShortCut = 8201
end
item
Command = ecMatchBracket
ShortCut = 24642
end
item
Command = ecColSelUp
ShortCut = 40998
end
item
Command = ecColSelDown
ShortCut = 41000
end
item
Command = ecColSelLeft
ShortCut = 40997
end
item
Command = ecColSelRight
ShortCut = 40999
end
item
Command = ecColSelPageDown
ShortCut = 40994
end
item
Command = ecColSelPageBottom
ShortCut = 57378
end
item
Command = ecColSelPageUp
ShortCut = 40993
end
item
Command = ecColSelPageTop
ShortCut = 57377
end
item
Command = ecColSelLineStart
ShortCut = 40996
end
item
Command = ecColSelLineEnd
ShortCut = 40995
end
item
Command = ecColSelEditorTop
ShortCut = 57380
end
item
Command = ecColSelEditorBottom
ShortCut = 57379
end>
MouseActions = <>
MouseSelActions = <>
Lines.Strings = (
''
)
SelectedColor.BackPriority = 50
SelectedColor.ForePriority = 50
SelectedColor.FramePriority = 50
SelectedColor.BoldPriority = 50
SelectedColor.ItalicPriority = 50
SelectedColor.UnderlinePriority = 50
OnStatusChange = SynMemoStatusChange
inline SynLeftGutterPartList1: TSynGutterPartList
object SynGutterMarks1: TSynGutterMarks
Width = 24
MouseActions = <>
end
object SynGutterLineNumber1: TSynGutterLineNumber
Width = 17
MouseActions = <>
MarkupInfo.Background = clBtnFace
MarkupInfo.Foreground = clNone
DigitCount = 2
ShowOnlyLineNumbersMultiplesOf = 1
ZeroStart = False
LeadingZeros = False
end
object SynGutterChanges1: TSynGutterChanges
Width = 4
MouseActions = <>
ModifiedColor = 59900
SavedColor = clGreen
end
object SynGutterSeparator1: TSynGutterSeparator
Width = 2
MouseActions = <>
end
object SynGutterCodeFolding1: TSynGutterCodeFolding
MouseActions = <>
MarkupInfo.Background = clNone
MarkupInfo.Foreground = clGray
MouseActionsExpanded = <>
MouseActionsCollapsed = <>
end
end
end
object FileNameEdit: TFileNameEdit
Left = 56
Height = 23
Top = 24
Width = 368
OnAcceptFileName = FileNameEditAcceptFileName
FilterIndex = 0
HideDirectories = False
ButtonWidth = 23
NumGlyphs = 1
MaxLength = 0
TabOrder = 0
end
object INIFileLabel: TLabel
Left = 8
Height = 15
Top = 24
Width = 34
Caption = 'INI file'
ParentColor = False
end
object ProfileSelect: TComboBox
Left = 56
Height = 23
Hint = 'Choose the profile you want to enable'
Top = 61
Width = 164
ItemHeight = 15
OnSelect = ProfileSelectSelect
Sorted = True
TabOrder = 1
end
object ProfileLabel: TLabel
Left = 8
Height = 15
Top = 64
Width = 34
Caption = 'Profile'
ParentColor = False
end
object OKButton: TButton
Left = 664
Height = 25
Top = 456
Width = 75
Caption = '&OK'
Default = True
ModalResult = 1
TabOrder = 4
end
object CancelButton: TButton
Left = 568
Height = 25
Top = 456
Width = 75
Cancel = True
Caption = '&Cancel'
ModalResult = 2
OnClick = CancelButtonClick
TabOrder = 3
end
object SynIniHighlighter: TSynIniSyn
DefaultFilter = 'INI Files (*.ini)|*.ini'
Enabled = False
CommentAttri.FrameEdges = sfeAround
TextAttri.FrameEdges = sfeAround
SectionAttri.FrameEdges = sfeAround
KeyAttri.FrameEdges = sfeAround
NumberAttri.FrameEdges = sfeAround
SpaceAttri.FrameEdges = sfeAround
StringAttri.FrameEdges = sfeAround
SymbolAttri.FrameEdges = sfeAround
left = 32
top = 456
end
object GUITimer: TIdleTimer
AutoEnabled = True
OnTimer = GUITimerTimer
left = 560
top = 16
end
end

View File

@ -0,0 +1,251 @@
unit inieditor;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls,
Graphics, Dialogs, StdCtrls, EditBtn, ExtCtrls,
IniFiles, lazutf8, SynEdit,SynMemo,{SynEditTypes,}SynHighlighterIni, SynEditTypes;
type
{ TFormIniEditor }
TFormIniEditor = class(TForm)
GUITimer: TIdleTimer;
OKButton: TButton;
CancelButton: TButton;
ProfileSelect: TComboBox;
FileNameEdit: TFileNameEdit;
INIFileLabel: TLabel;
ProfileLabel: TLabel;
SynIniHighlighter: TSynIniSyn;
SynMemo: TSynMemo;
procedure CancelButtonClick(Sender: TObject);
procedure FileNameEditAcceptFileName(Sender: TObject; var Value: String);
procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
procedure FormShow(Sender: TObject);
procedure GUITimerTimer(Sender: TObject);
procedure ProfileSelectSelect(Sender: TObject);
procedure SynMemoStatusChange(Sender: TObject; Changes: TSynStatusChanges);
private
FIniFilename: string;
FIniStream: TMemoryStream;
FMustReloadProfileSelect: boolean;
FSaveChanges: boolean; //If off, don't save any changes (e.g. when canceling form)
FProfileSelectKey: string;
FProfileSelectSection: string;
FProfileSelectValue: string;
procedure LoadGUI(KeepCursorPosition: boolean; LoadSynmemo: boolean; LoadProfileselect: boolean); //Loads GUI elements from backing stream
procedure SetIniFilename(AValue: string); //Loads file into stream
procedure SetProfileSelectKey(AValue: string);
procedure SetProfileSelectSection(AValue: string);
// Saves synmemo contents to memory stream and optionally to file, too
procedure SynMemoSave(AlsoToFile: boolean);
{ private declarations }
public
// File to be edited/viewed:
property INIFile: string read FIniFilename write SetIniFilename;
// Section name where profile selection is to be stored. If nothing, the root/top level will be used
property ProfileSelectSection: string read FProfileSelectSection write SetProfileSelectSection;
// Key to be used for storing selected profile
// If empty, don't use the select profile combobox
property ProfileSelectKey: string read FProfileSelectKey write SetProfileSelectKey;
// The value the user selected
property ProfileSelectValue: string read FProfileSelectValue;
end;
var
Form1: TFormIniEditor;
implementation
{$R *.lfm}
{ TFormIniEditor }
procedure TFormIniEditor.FormDropFiles(Sender: TObject;
const FileNames: array of String);
begin
// Go through property for reload file+reload GUI code
IniFile:=FileNames[0];
end;
procedure TFormIniEditor.FormShow(Sender: TObject);
begin
if FileNameEdit.FileName='' then
FileNameEdit.FileName:=ExpandFileNameUTF8(FIniFilename);
end;
procedure TFormIniEditor.GUITimerTimer(Sender: TObject);
begin
if FMustReloadProfileSelect then
LoadGUI(true,false,true);
end;
procedure TFormIniEditor.ProfileSelectSelect(Sender: TObject);
// Save selected profile
var
MyIniFile: TIniFile;
begin
FProfileSelectValue:=ProfileSelect.Text;
if FProfileSelectValue<>'' then
begin
// Save any changes in synmemo
SynMemoSave(false);
FIniStream.Position:=0; //Load from beginning
MyIniFile := TIniFile.Create(FIniStream, True);
FIniStream.Position:=0; //Needed to save again
try
MyIniFile.WriteString(FProfileSelectSection,FProfileSelectKey,FProfileSelectValue);
finally
MyIniFile.Free;
end;
LoadGUI(true,true,true);
end;
end;
procedure TFormIniEditor.SynMemoStatusChange(Sender: TObject;
Changes: TSynStatusChanges);
begin
// If user edits the profile name directly or edits/deletes/adds
// one of the section names, the combobox will need to be refreshed.
// Pass this on to a timer so it gets done without disturbing the updates
if (FMustReloadProfileSelect=false) and (scModified in Changes) then
begin
//todo: test for section line or key=value
FMustReloadProfileSelect:=true;
end;
end;
procedure TFormIniEditor.LoadGUI(KeepCursorPosition: boolean; LoadSynmemo: boolean; LoadProfileselect: boolean);
var
MyIniFile : TIniFile;
OldPos: TPoint;
ProfIndex: integer;
Sections: TStringList;
begin
SynMemo.BeginUpdate(false);
if LoadSynMemo then
begin
OldPos:=SynMemo.CaretXY;
FIniStream.Position:=0; //Load from beginning
SynMemo.Lines.LoadFromStream(FIniStream);
end;
FIniStream.Position:=0; //Load from beginning
MyIniFile := TIniFile.Create(FIniStream, True);
FIniStream.Position:=0; //In case we want to save
Sections:=TStringList.Create;
try
if LoadProfileselect then
begin
Sections.Sorted:=true;
MyIniFile.ReadSections(Sections);
// Now take out the one where the profile is stored as it will confuse users
if Sections.Find(FProfileSelectSection, ProfIndex) then
Sections.Delete(ProfIndex);
ProfileSelect.Clear;
ProfileSelect.Items.AddStrings(Sections);
FProfileSelectValue:=MyIniFile.ReadString(FProfileSelectSection,FProfileSelectKey,'');
ProfileSelect.Text:=FProfileSelectValue;
FMustReloadProfileSelect:=false;
end;
// restore cursor/caret position
if LoadSynMemo and KeepCursorPosition then
SynMemo.CaretXY:=OldPos;
finally
MyIniFile.Free;
Sections.Free;
SynMemo.EndUpdate;
end;
end;
procedure TFormIniEditor.SetIniFilename(AValue: string);
begin
if FIniFilename=AValue then Exit;
FIniFilename:=AValue;
if FIniFileName<>'' then
begin
try
FIniStream.Clear;
FIniStream.LoadFromFile(FIniFilename);
except
on E: Exception do
ShowMessage('Error loading file '+FIniFilename+': '+E.Message);
end;
LoadGUI(false,true,true);
end;
end;
procedure TFormIniEditor.SetProfileSelectKey(AValue: string);
begin
if FProfileSelectKey=AValue then Exit;
FProfileSelectKey:=AValue;
if (FProfileSelectKey<>'') and (FProfileSelectSection<>'') then
LoadGUI(false,true,true);
end;
procedure TFormIniEditor.SetProfileSelectSection(AValue: string);
begin
if FProfileSelectSection=AValue then Exit;
FProfileSelectSection:=AValue;
if (FProfileSelectKey<>'') and (FProfileSelectSection<>'') then
LoadGUI(false,true,true);
end;
procedure TFormIniEditor.SynMemoSave(AlsoToFile: boolean);
begin
if FSaveChanges then
begin
FIniStream.Clear;
FIniStream.Position:=0; //Save from beginning
SynMemo.Lines.SaveToStream(FiniStream);
FIniStream.Position:=0; //Save from beginning
if AlsoToFile and (FIniFileName<>'') then
FIniStream.SaveToFile(FIniFilename);
end;
end;
procedure TFormIniEditor.CancelButtonClick(Sender: TObject);
begin
FSaveChanges:=false;
end;
procedure TFormIniEditor.FileNameEditAcceptFileName(Sender: TObject;
var Value: String);
begin
// go through the property to load new file
INIFile:=Value;
end;
procedure TFormIniEditor.FormCloseQuery(Sender: TObject; var CanClose: boolean);
begin
// Save any uncommitted changes
//todo: only if dirty synmemo changestamp?; also check if this is best event
SynMemoSave(true);
end;
procedure TFormIniEditor.FormCreate(Sender: TObject);
begin
FIniStream:=TMemoryStream.Create;
FSaveChanges:=true; //allow editing
end;
procedure TFormIniEditor.FormDestroy(Sender: TObject);
begin
FIniStream.Free;
end;
end.