mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-27 17:34:37 +02:00
253 lines
7.3 KiB
ObjectPascal
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.
|
|
|