fpc/packages/fcl-db/tests/inieditor.pas
2013-08-22 11:07:39 +00:00

253 lines
7.3 KiB
ObjectPascal

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;
Label1: TLabel;
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.