mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-15 23:09:44 +02:00
954 lines
32 KiB
ObjectPascal
954 lines
32 KiB
ObjectPascal
{
|
|
/***************************************************************************
|
|
inputhistory.pas
|
|
----------------
|
|
|
|
***************************************************************************/
|
|
|
|
***************************************************************************
|
|
* *
|
|
* This source is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This code is distributed in the hope that it will be useful, but *
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
* General Public License for more details. *
|
|
* *
|
|
* A copy of the GNU General Public License is available on the World *
|
|
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
|
* obtain it by writing to the Free Software Foundation, *
|
|
* Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
|
|
* *
|
|
***************************************************************************
|
|
|
|
Author: Mattias Gaertner
|
|
|
|
Abstract:
|
|
History lists for strings and file names.
|
|
}
|
|
unit InputHistory;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
// RTL + LCL
|
|
Classes, SysUtils, Laz_AVL_Tree,
|
|
// LCL
|
|
Dialogs,
|
|
// LazUtils
|
|
LazFileCache, LazFileUtils, LazUTF8, AvgLvlTree, Laz2_XMLCfg,
|
|
// Codetools
|
|
FileProcs,
|
|
// IdeIntf
|
|
ProjectIntf, IDEDialogs,
|
|
// IDE
|
|
DiffPatch, LazConf, IDEProcs;
|
|
|
|
{$ifdef Windows}
|
|
{$define CaseInsensitiveFilenames}
|
|
{$endif}
|
|
|
|
const
|
|
// these are the names of the various history lists in the IDE:
|
|
hlPublishModuleDestDirs = 'PublishModuleDestinationDirectories';
|
|
hlPublishModuleFileFilter = 'PublishModuleFileFilter';
|
|
hlMakeResourceStringSections = 'MakeResourceStringSections';
|
|
hlMakeResourceStringPrefixes = 'MakeResourceStringPrefixes';
|
|
hlMakeResourceStringLengths = 'MakeResourceStringLengths';
|
|
hlCodeToolsDirectories = 'CodeToolsDirectories';
|
|
hlCompilerOptsImExport = 'CompilerOptsImExport';
|
|
hlCleanBuildFileMask = 'CleanBuildFileMask';
|
|
|
|
type
|
|
TFileDialogSettings = record
|
|
InitialDir: string;
|
|
Width: integer;
|
|
Height: integer;
|
|
HistoryList: TStringList;
|
|
MaxHistory: integer;
|
|
end;
|
|
|
|
|
|
{ THistoryList - a TStringList to store a history list }
|
|
|
|
THistoryList = class(TStringList)
|
|
private
|
|
FListType: TRecentListType;
|
|
FMaxCount: integer;
|
|
FName: string;
|
|
procedure SetMaxCount(const AValue: integer);
|
|
procedure SetName(const AValue: string);
|
|
public
|
|
constructor Create(TheListType: TRecentListType);
|
|
destructor Destroy; override;
|
|
function Push(const Entry: string): integer;
|
|
procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
|
|
procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
|
|
procedure AppendEntry(const Entry: string);
|
|
function IndexOf(const S: string): Integer; override;
|
|
public
|
|
property Name: string read FName write SetName;
|
|
property MaxCount: integer read FMaxCount write SetMaxCount;
|
|
property ListType: TRecentListType read FListType;
|
|
end;
|
|
|
|
|
|
{ THistoryLists - list of THistoryList }
|
|
|
|
THistoryLists = class
|
|
private
|
|
FItems: TList;
|
|
function GetItems(Index: integer): THistoryList;
|
|
function GetXMLListPath(const Path: string; i: integer; ALegacyList: Boolean): string;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Clear;
|
|
function Count: integer;
|
|
procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
|
|
procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string; const ALegacyList: Boolean);
|
|
function IndexOfName(const Name: string): integer;
|
|
function GetList(const Name: string;
|
|
CreateIfNotExists: boolean; ListType: TRecentListType): THistoryList;
|
|
procedure Add(const ListName, Entry: string; ListType: TRecentListType);
|
|
property Items[Index: integer]: THistoryList read GetItems;
|
|
end;
|
|
|
|
|
|
{ TInputHistories }
|
|
|
|
TLazFindInFileSearchOption = (
|
|
fifMatchCase,
|
|
fifWholeWord,
|
|
fifRegExpr,
|
|
fifMultiLine,
|
|
fifSearchProject, // search in all project files
|
|
fifSearchProjectGroup,// search in all files of project group
|
|
fifSearchOpen, // search in all open files in editor
|
|
fifSearchActive, // search in active open file in editor
|
|
fifSearchDirectories,// search in directories
|
|
fifIncludeSubDirs,
|
|
fifReplace, // replace and ask user before each replace
|
|
fifReplaceAll // replace without asking user
|
|
);
|
|
TLazFindInFileSearchOptions = set of TLazFindInFileSearchOption;
|
|
|
|
|
|
{ TIHIgnoreIDEQuestionList }
|
|
|
|
TIHIgnoreIDEQuestionList = class(TIgnoreIDEQuestionList)
|
|
private
|
|
FItems: TAvlTree; // tree of TIgnoreIDEQuestionItem
|
|
function FindNode(const Identifier: string): TAvlTreeNode;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Clear;
|
|
function Add(const Identifier: string;
|
|
const Duration: TIgnoreQuestionDuration;
|
|
const Flag: string = ''): TIgnoreIDEQuestionItem; override;
|
|
procedure Delete(const Identifier: string); override;
|
|
function Find(const Identifier: string): TIgnoreIDEQuestionItem; override;
|
|
procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
|
|
procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
|
|
end;
|
|
|
|
TInputHistories = class
|
|
private
|
|
FCleanOutputFileMask: string;
|
|
FCleanSourcesFileMask: string;
|
|
FDiffFlags: TTextDiffFlags;
|
|
FDiffText2: string;
|
|
FDiffText2OnlySelection: boolean;
|
|
FFileDialogSettings: TFileDialogSettings;
|
|
FFilename: string;
|
|
|
|
// Find- and replace-history
|
|
FFindHistory: TStringList;
|
|
FFindInFilesSearchOptions: TLazFindInFileSearchOptions;
|
|
FFindAutoComplete: boolean;
|
|
FIgnores: TIHIgnoreIDEQuestionList;
|
|
FLastConvertDelphiPackage: string;
|
|
FLastConvertDelphiProject: string;
|
|
FLastConvertDelphiUnit: string;
|
|
FViewNeedBuildTarget: string;
|
|
FNewFileType: string;
|
|
FNewProjectType: string;
|
|
FReplaceHistory: TStringList;
|
|
FFindInFilesPathHistory: TStringList;
|
|
FFindInFilesMaskHistory: TStringList;
|
|
FMaxFindHistory: Integer;
|
|
|
|
// various history lists
|
|
FHistoryLists: THistoryLists;
|
|
// file encodings
|
|
fFileEncodings: TStringToStringTree;
|
|
|
|
procedure SetFilename(const AValue: string);
|
|
protected
|
|
procedure LoadSearchOptions(XMLConfig: TXMLConfig; const Path: string); virtual; abstract;
|
|
procedure SaveSearchOptions(XMLConfig: TXMLConfig; const Path: string); virtual; abstract;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Clear;
|
|
procedure Load;
|
|
procedure Save;
|
|
procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
|
|
procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
|
|
procedure SetLazarusDefaultFilename;
|
|
|
|
// Find- and replace-history
|
|
function AddToFindHistory(const AFindStr: string): boolean;
|
|
function AddToReplaceHistory(const AReplaceStr: String): boolean;
|
|
function AddToFindInFilesPathHistory(const APathStr: String): boolean;
|
|
function AddToFindInFilesMaskHistory(const AMaskStr: String): boolean;
|
|
|
|
// filedialog
|
|
procedure ApplyFileDialogSettings(DestDialog: TFileDialog);
|
|
procedure StoreFileDialogSettings(SourceDialog: TFileDialog);
|
|
procedure SetFileDialogSettingsInitialDir(const InitialDir: string);
|
|
function SelectDirectory(const {%H-}Title: string;
|
|
MustExist: boolean = true;
|
|
const InitialDir: string = '';
|
|
const Directory: string = ''): string;
|
|
public
|
|
property Filename: string read FFilename write SetFilename;
|
|
|
|
// Find- and replace-history
|
|
property MaxFindHistory: Integer read FMaxFindHistory write FMaxFindHistory;
|
|
property FindHistory: TStringList read FFindHistory write FFindHistory;
|
|
property ReplaceHistory: TStringList read FReplaceHistory write FReplaceHistory;
|
|
property FindInFilesPathHistory: TStringList read FFindInFilesPathHistory
|
|
write FFindInFilesPathHistory;
|
|
property FindInFilesMaskHistory: TStringList read FFindInFilesMaskHistory
|
|
write FFindInFilesMaskHistory;
|
|
property FindInFilesSearchOptions: TLazFindInFileSearchOptions
|
|
read FFindInFilesSearchOptions write FFindInFilesSearchOptions;
|
|
property FindAutoComplete: boolean read FFindAutoComplete
|
|
write FFindAutoComplete;
|
|
|
|
// filedialogs
|
|
property FileDialogSettings: TFileDialogSettings
|
|
read FFileDialogSettings write FFileDialogSettings;
|
|
property CleanOutputFileMask: string read FCleanOutputFileMask write FCleanOutputFileMask;
|
|
property CleanSourcesFileMask: string read FCleanSourcesFileMask write FCleanSourcesFileMask;
|
|
|
|
// various history lists
|
|
property HistoryLists: THistoryLists read FHistoryLists;
|
|
|
|
// diff dialog
|
|
property DiffFlags: TTextDiffFlags read FDiffFlags write FDiffFlags;
|
|
property DiffText2: string read FDiffText2 write FDiffText2;
|
|
property DiffText2OnlySelection: boolean read FDiffText2OnlySelection
|
|
write FDiffText2OnlySelection;
|
|
// new dialog
|
|
property NewProjectType: string read FNewProjectType write FNewProjectType;
|
|
property NewFileType: string read FNewFileType write FNewFileType;
|
|
|
|
// Delphi conversion
|
|
property LastConvertDelphiProject: string read FLastConvertDelphiProject
|
|
write FLastConvertDelphiProject;
|
|
property LastConvertDelphiPackage: string read FLastConvertDelphiPackage
|
|
write FLastConvertDelphiPackage;
|
|
property LastConvertDelphiUnit: string read FLastConvertDelphiUnit
|
|
write FLastConvertDelphiUnit;
|
|
|
|
// View / internals
|
|
property ViewNeedBuildTarget: string read FViewNeedBuildTarget
|
|
write FViewNeedBuildTarget;
|
|
|
|
// file encodings
|
|
property FileEncodings: TStringToStringTree read fFileEncodings write fFileEncodings;
|
|
|
|
// ignores
|
|
property Ignores: TIHIgnoreIDEQuestionList read FIgnores;
|
|
end;
|
|
|
|
const
|
|
LazFindInFileSearchOptionsDefault = [fifSearchOpen, fifIncludeSubDirs];
|
|
LazFindInFileSearchOptionNames: array[TLazFindInFileSearchOption] of string =(
|
|
'MatchCase',
|
|
'WholeWord',
|
|
'RegExpr',
|
|
'MultiLine',
|
|
'SearchProject',
|
|
'SearchProjectGroup',
|
|
'SearchOpen',
|
|
'SearchCurrent',
|
|
'SearchDirectories',
|
|
'IncludeSubDirs',
|
|
'Replace',
|
|
'ReplaceAll'
|
|
);
|
|
IHIgnoreItemDurationNames: array[TIgnoreQuestionDuration] of string = (
|
|
'IDERestart',
|
|
'24H',
|
|
'Forever'
|
|
);
|
|
|
|
var
|
|
InputHistories: TInputHistories = nil;
|
|
|
|
function CompareIHIgnoreItems(Item1, Item2: Pointer): integer;
|
|
function CompareAnsiStringWithIHIgnoreItem(AString, Item: Pointer): integer;
|
|
|
|
function NameToIHIgnoreItemDuration(const s: string): TIgnoreQuestionDuration;
|
|
|
|
|
|
implementation
|
|
|
|
|
|
const
|
|
DefaultHistoryFile = 'inputhistory.xml';
|
|
InputHistoryVersion = 1;
|
|
DefaultDiffFlags = [tdfIgnoreCase,tdfIgnoreEmptyLineChanges,
|
|
tdfIgnoreLineEnds,tdfIgnoreTrailingSpaces];
|
|
|
|
function CompareIHIgnoreItems(Item1, Item2: Pointer): integer;
|
|
var
|
|
IgnoreItem1: TIgnoreIDEQuestionItem absolute Item1;
|
|
IgnoreItem2: TIgnoreIDEQuestionItem absolute Item2;
|
|
begin
|
|
Result:=SysUtils.CompareText(IgnoreItem1.Identifier,IgnoreItem2.Identifier);
|
|
end;
|
|
|
|
function CompareAnsiStringWithIHIgnoreItem(AString, Item: Pointer): integer;
|
|
var
|
|
IgnoreItem: TIgnoreIDEQuestionItem absolute Item;
|
|
begin
|
|
Result:=SysUtils.CompareText(AnsiString(AString),IgnoreItem.Identifier);
|
|
end;
|
|
|
|
function NameToIHIgnoreItemDuration(const s: string): TIgnoreQuestionDuration;
|
|
begin
|
|
for Result:=low(TIgnoreQuestionDuration) to high(TIgnoreQuestionDuration) do
|
|
if SysUtils.CompareText(IHIgnoreItemDurationNames[Result],s)=0 then exit;
|
|
Result:=iiidIDERestart;
|
|
end;
|
|
|
|
{ TInputHistories }
|
|
|
|
procedure TInputHistories.SetFilename(const AValue: string);
|
|
begin
|
|
FFilename:=AValue;
|
|
end;
|
|
|
|
constructor TInputHistories.Create;
|
|
begin
|
|
inherited Create;
|
|
FFilename:='';
|
|
|
|
// Find- and replace-history
|
|
FMaxFindHistory:=20;
|
|
FFindAutoComplete:=true;
|
|
FFindHistory:=TStringList.Create;
|
|
FReplaceHistory:=TStringList.Create;
|
|
FFindInFilesPathHistory:=TStringList.Create;
|
|
FFindInFilesMaskHistory:=TStringList.Create;
|
|
FFindInFilesSearchOptions:=LazFindInFileSearchOptionsDefault;
|
|
|
|
// file dialog
|
|
FFileDialogSettings.HistoryList:=TStringList.Create;
|
|
FFileDialogSettings.MaxHistory:=20;
|
|
|
|
// various history lists
|
|
FHistoryLists:=THistoryLists.Create;
|
|
fFileEncodings:=TStringToStringTree.Create({$IFDEF CaseInsensitiveFilenames}false{$ELSE}true{$ENDIF});
|
|
FIgnores:=TIHIgnoreIDEQuestionList.Create;
|
|
IgnoreQuestions:=FIgnores;
|
|
|
|
Clear;
|
|
end;
|
|
|
|
destructor TInputHistories.Destroy;
|
|
begin
|
|
IgnoreQuestions:=nil;
|
|
FreeAndNil(FIgnores);
|
|
FreeAndNil(FHistoryLists);
|
|
FreeAndNil(FFileDialogSettings.HistoryList);
|
|
FreeAndNil(FFindHistory);
|
|
FreeAndNil(FReplaceHistory);
|
|
FreeAndNil(FFindInFilesPathHistory);
|
|
FreeAndNil(FFindInFilesMaskHistory);
|
|
FreeAndNil(fFileEncodings);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TInputHistories.Clear;
|
|
begin
|
|
FHistoryLists.Clear;
|
|
FFindHistory.Clear;
|
|
FReplaceHistory.Clear;
|
|
FFindInFilesPathHistory.Clear;
|
|
FFindInFilesMaskHistory.Clear;
|
|
with FFileDialogSettings do begin
|
|
HistoryList.Clear;
|
|
Width:=0;
|
|
Height:=0;
|
|
InitialDir:='';
|
|
end;
|
|
FDiffFlags:=DefaultDiffFlags;
|
|
FDiffText2:='';
|
|
FDiffText2OnlySelection:=false;
|
|
FNewProjectType:='';
|
|
FNewFileType:='';
|
|
FLastConvertDelphiProject:='';
|
|
FLastConvertDelphiUnit:='';
|
|
FCleanOutputFileMask:=DefaultProjectCleanOutputFileMask;
|
|
FCleanSourcesFileMask:=DefaultProjectCleanSourcesFileMask;
|
|
fFileEncodings.Clear;
|
|
FIgnores.Clear;
|
|
end;
|
|
|
|
procedure TInputHistories.LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
|
|
var
|
|
DiffFlag: TTextDiffFlag;
|
|
FIFOption: TLazFindInFileSearchOption;
|
|
begin
|
|
// Find- and replace-history
|
|
FMaxFindHistory:=XMLConfig.GetValue(Path+'Find/History/Max',FMaxFindHistory);
|
|
FFindAutoComplete:=XMLConfig.GetValue(Path+'Find/AutoComplete/Value',FFindAutoComplete);
|
|
LoadRecentList(XMLConfig,FFindHistory,Path+'Find/History/Find/',rltCaseSensitive);
|
|
LoadRecentList(XMLConfig,FReplaceHistory,Path+'Find/History/Replace/',rltCaseSensitive);
|
|
LoadRecentList(XMLConfig,FFindInFilesPathHistory,Path+
|
|
'FindInFiles/History/Paths/',rltFile);
|
|
LoadRecentList(XMLConfig,FFindInFilesMaskHistory,Path+
|
|
'FindInFiles/History/Masks/',rltFile);
|
|
FFindInFilesSearchOptions:=[];
|
|
for FIFOption:=Low(TLazFindInFileSearchOption) to High(TLazFindInFileSearchOption)
|
|
do begin
|
|
if XMLConfig.GetValue(
|
|
Path+'FindInFiles/Options/'+LazFindInFileSearchOptionNames[FIFOption],
|
|
FIFOption in LazFindInFileSearchOptionsDefault)
|
|
then
|
|
Include(FFindInFilesSearchOptions,FIFOption);
|
|
end;
|
|
LoadSearchOptions(XMLConfig, Path); // Search Options depend on SynEdit.
|
|
|
|
// file dialog
|
|
with FFileDialogSettings do begin
|
|
Width:=XMLConfig.GetValue(Path+'FileDialog/Width',0);
|
|
Height:=XMLConfig.GetValue(Path+'FileDialog/Height',0);
|
|
InitialDir:=XMLConfig.GetValue(Path+'FileDialog/InitialDir','');
|
|
MaxHistory:=XMLConfig.GetValue(Path+'FileDialog/MaxHistory',20);
|
|
LoadRecentList(XMLConfig,HistoryList,Path+'FileDialog/HistoryList/',rltFile);
|
|
end;
|
|
FCleanOutputFileMask:=XMLConfig.GetValue(Path+'Clean/OutputFilemask',
|
|
DefaultProjectCleanOutputFileMask);
|
|
FCleanSourcesFileMask:=XMLConfig.GetValue(Path+'Clean/SourcesFilemask',
|
|
DefaultProjectCleanSourcesFileMask);
|
|
// history lists
|
|
FHistoryLists.LoadFromXMLConfig(XMLConfig,Path+'HistoryLists/');
|
|
// diff dialog
|
|
FDiffFlags:=[];
|
|
for DiffFlag:=Low(TTextDiffFlag) to High(TTextDiffFlag) do begin
|
|
if XMLConfig.GetValue(
|
|
Path+'DiffDialog/Options/'+TextDiffFlagNames[DiffFlag],
|
|
DiffFlag in DefaultDiffFlags)
|
|
then
|
|
Include(FDiffFlags,DiffFlag);
|
|
end;
|
|
FDiffText2:=XMLConfig.GetValue(Path+'DiffDialog/Text2/Name','');
|
|
FDiffText2OnlySelection:=
|
|
XMLConfig.GetValue(Path+'DiffDialog/Text2/OnlySelection',false);
|
|
|
|
// new items
|
|
FNewProjectType:=XMLConfig.GetValue(Path+'New/Project/Type','');
|
|
FNewFileType:=XMLConfig.GetValue(Path+'New/File/Type','');
|
|
|
|
// delphi conversion
|
|
FLastConvertDelphiProject:=XMLConfig.GetValue(Path+'Conversion/Delphi/Project','');
|
|
FLastConvertDelphiPackage:=XMLConfig.GetValue(Path+'Conversion/Delphi/Package','');
|
|
FLastConvertDelphiUnit:=XMLConfig.GetValue(Path+'Conversion/Delphi/Unit','');
|
|
|
|
// view internals
|
|
ViewNeedBuildTarget:=XMLConfig.GetValue(Path+'View/NeedBuild/Target','');
|
|
|
|
// encodings
|
|
LoadStringToStringTree(XMLConfig,fFileEncodings,Path+'FileEncodings/');
|
|
|
|
Ignores.LoadFromXMLConfig(XMLConfig,Path+'Ignores/');
|
|
end;
|
|
|
|
procedure TInputHistories.SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
|
|
var
|
|
DiffFlag: TTextDiffFlag;
|
|
FIFOption: TLazFindInFileSearchOption;
|
|
begin
|
|
// Find- and replace-history
|
|
XMLConfig.SetDeleteValue(Path+'Find/History/Max',FMaxFindHistory,20);
|
|
XMLConfig.SetDeleteValue(Path+'Find/AutoComplete/Value',FFindAutoComplete,true);
|
|
SaveRecentList(XMLConfig,FFindHistory,Path+'Find/History/Find/');
|
|
SaveRecentList(XMLConfig,FReplaceHistory,Path+'Find/History/Replace/');
|
|
SaveRecentList(XMLConfig,FFindInFilesPathHistory,Path+
|
|
'FindInFiles/History/Paths/');
|
|
SaveRecentList(XMLConfig,FFindInFilesMaskHistory,Path+
|
|
'FindInFiles/History/Masks/');
|
|
for FIFOption:=Low(TLazFindInFileSearchOption)
|
|
to High(TLazFindInFileSearchOption) do begin
|
|
XMLConfig.SetDeleteValue(
|
|
Path+'FindInFiles/Options/'+LazFindInFileSearchOptionNames[FIFOption],
|
|
FIFOption in FindInFilesSearchOptions,
|
|
FIFOption in LazFindInFileSearchOptionsDefault);
|
|
end;
|
|
SaveSearchOptions(XMLConfig, Path); // Search Options depend on SynEdit.
|
|
|
|
// file dialog
|
|
with FFileDialogSettings do begin
|
|
XMLConfig.SetDeleteValue(Path+'FileDialog/Width',Width,0);
|
|
XMLConfig.SetDeleteValue(Path+'FileDialog/Height',Height,0);
|
|
XMLConfig.SetDeleteValue(Path+'FileDialog/InitialDir',InitialDir,'');
|
|
XMLConfig.SetDeleteValue(Path+'FileDialog/MaxHistory',MaxHistory,20);
|
|
SaveRecentList(XMLConfig,HistoryList,Path+'FileDialog/HistoryList/');
|
|
end;
|
|
XMLConfig.SetDeleteValue(Path+'Clean/OutputFilemask',FCleanOutputFileMask,
|
|
DefaultProjectCleanOutputFileMask);
|
|
XMLConfig.SetDeleteValue(Path+'Clean/SourcesFilemask',FCleanSourcesFileMask,
|
|
DefaultProjectCleanSourcesFileMask);
|
|
// history lists
|
|
FHistoryLists.SaveToXMLConfig(XMLConfig,Path+'HistoryLists/',True);
|
|
// diff dialog
|
|
for DiffFlag:=Low(TTextDiffFlag) to High(TTextDiffFlag) do begin
|
|
XMLConfig.SetDeleteValue(
|
|
Path+'DiffDialog/Options/'+TextDiffFlagNames[DiffFlag],
|
|
DiffFlag in DiffFlags,DiffFlag in DefaultDiffFlags);
|
|
end;
|
|
XMLConfig.SetDeleteValue(Path+'DiffDialog/Text2/Name',FDiffText2,'');
|
|
XMLConfig.SetDeleteValue(Path+'DiffDialog/Text2/OnlySelection',
|
|
FDiffText2OnlySelection,false);
|
|
|
|
// new items
|
|
XMLConfig.SetDeleteValue(Path+'New/Project/Type',FNewProjectType,'');
|
|
XMLConfig.SetDeleteValue(Path+'New/File/Type',FNewFileType,'');
|
|
|
|
// delphi conversion
|
|
XMLConfig.SetDeleteValue(Path+'Conversion/Delphi/Project',
|
|
FLastConvertDelphiProject,'');
|
|
XMLConfig.SetDeleteValue(Path+'Conversion/Delphi/Package',
|
|
FLastConvertDelphiPackage,'');
|
|
XMLConfig.SetDeleteValue(Path+'Conversion/Delphi/Unit',
|
|
FLastConvertDelphiUnit,'');
|
|
|
|
// view internals
|
|
XMLConfig.SetDeleteValue(Path+'View/NeedBuild/Target',ViewNeedBuildTarget,'');
|
|
|
|
// encodings
|
|
SaveStringToStringTree(XMLConfig,fFileEncodings,Path+'FileEncodings/');
|
|
|
|
Ignores.SaveToXMLConfig(XMLConfig,Path+'Ignores/');
|
|
end;
|
|
|
|
procedure TInputHistories.SetLazarusDefaultFilename;
|
|
var
|
|
ConfFileName: string;
|
|
begin
|
|
ConfFileName:=AppendPathDelim(GetPrimaryConfigPath)+DefaultHistoryFile;
|
|
CopySecondaryConfigFile(DefaultHistoryFile);
|
|
FFilename:=ConfFilename;
|
|
end;
|
|
|
|
procedure TInputHistories.Load;
|
|
var
|
|
XMLConfig: TXMLConfig;
|
|
//FileVersion: integer;
|
|
begin
|
|
try
|
|
XMLConfig:=TXMLConfig.Create(FFileName);
|
|
//FileVersion:=XMLConfig.GetValue('InputHistory/Version/Value',0);
|
|
LoadFromXMLConfig(XMLConfig,'InputHistory/');
|
|
XMLConfig.Free;
|
|
except
|
|
on E: Exception do begin
|
|
DebugLn('[TCodeToolsOptions.Load] error reading "',FFilename,'" ',E.Message);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TInputHistories.Save;
|
|
var
|
|
XMLConfig: TXMLConfig;
|
|
begin
|
|
try
|
|
InvalidateFileStateCache;
|
|
XMLConfig:=TXMLConfig.CreateClean(FFileName);
|
|
XMLConfig.SetDeleteValue('InputHistory/Version/Value',InputHistoryVersion,0);
|
|
SaveToXMLConfig(XMLConfig,'InputHistory/');
|
|
XMLConfig.Flush;
|
|
XMLConfig.Free;
|
|
except
|
|
on E: Exception do begin
|
|
DebugLn('[TInputHistories.Save] error writing "',FFilename,'" ',E.Message);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TInputHistories.AddToFindHistory(const AFindStr: string): boolean;
|
|
begin
|
|
Result:=AddToRecentList(AFindStr,FFindHistory,FMaxFindHistory,rltCaseSensitive);
|
|
end;
|
|
|
|
function TInputHistories.AddToReplaceHistory(const AReplaceStr: String): boolean;
|
|
begin
|
|
Result:=AddToRecentList(AReplaceStr,FReplaceHistory,FMaxFindHistory,rltCaseSensitive);
|
|
end;
|
|
|
|
function TInputHistories.AddToFindInFilesPathHistory(const APathStr: String): boolean;
|
|
begin
|
|
Result:= AddToRecentList(APathStr,FFindInFilesPathHistory,FMaxFindHistory,rltFile);
|
|
end;
|
|
|
|
function TInputHistories.AddToFindInFilesMaskHistory(const AMaskStr: String): boolean;
|
|
begin
|
|
Result:= AddToRecentList(AMaskStr,FFindInFilesMaskHistory,FMaxFindHistory,rltFile);
|
|
end;
|
|
|
|
procedure TInputHistories.ApplyFileDialogSettings(DestDialog: TFileDialog);
|
|
begin
|
|
DestDialog.InitialDir:=FFileDialogSettings.InitialDir;
|
|
DestDialog.Width:=FFileDialogSettings.Width;
|
|
DestDialog.Height:=FFileDialogSettings.Height;
|
|
|
|
DestDialog.HistoryList:=FFileDialogSettings.HistoryList;
|
|
end;
|
|
|
|
procedure TInputHistories.StoreFileDialogSettings(SourceDialog: TFileDialog);
|
|
var s: string;
|
|
begin
|
|
FFileDialogSettings.InitialDir:=SourceDialog.InitialDir;
|
|
FFileDialogSettings.Width:=SourceDialog.Width;
|
|
FFileDialogSettings.Height:=SourceDialog.Height;
|
|
s:=ExtractFilePath(FFileDialogSettings.InitialDir);
|
|
if s<>'' then
|
|
AddToRecentList(s,FFileDialogSettings.HistoryList,
|
|
FFileDialogSettings.MaxHistory,rltFile);
|
|
end;
|
|
|
|
procedure TInputHistories.SetFileDialogSettingsInitialDir(const InitialDir: string);
|
|
begin
|
|
FFileDialogSettings.InitialDir := InitialDir;
|
|
end;
|
|
|
|
function TInputHistories.SelectDirectory(const Title: string;
|
|
MustExist: boolean; const InitialDir: string; const Directory: string): string;
|
|
var
|
|
WorkDirectoryDialog: TSelectDirectoryDialog;
|
|
begin
|
|
Result:='';
|
|
WorkDirectoryDialog := TSelectDirectoryDialog.Create(nil);
|
|
try
|
|
ApplyFileDialogSettings(WorkDirectoryDialog);
|
|
if MustExist then
|
|
WorkDirectoryDialog.Options:=WorkDirectoryDialog.Options+[ofFileMustExist];
|
|
if InitialDir <> '' then
|
|
WorkDirectoryDialog.InitialDir := InitialDir;
|
|
if Directory<>'' then
|
|
WorkDirectoryDialog.Filename := Directory;
|
|
if WorkDirectoryDialog.Execute then begin
|
|
Result := WorkDirectoryDialog.Filename;
|
|
end;
|
|
StoreFileDialogSettings(WorkDirectoryDialog);
|
|
finally
|
|
WorkDirectoryDialog.Free;
|
|
end;
|
|
end;
|
|
|
|
{ THistoryList }
|
|
|
|
procedure THistoryList.SetMaxCount(const AValue: integer);
|
|
begin
|
|
if FMaxCount=AValue then exit;
|
|
FMaxCount:=AValue;
|
|
end;
|
|
|
|
procedure THistoryList.SetName(const AValue: string);
|
|
begin
|
|
if FName=AValue then exit;
|
|
FName:=AValue;
|
|
end;
|
|
|
|
constructor THistoryList.Create(TheListType: TRecentListType);
|
|
begin
|
|
FListType:=TheListType;
|
|
FMaxCount:=20;
|
|
end;
|
|
|
|
destructor THistoryList.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function THistoryList.Push(const Entry: string): integer;
|
|
begin
|
|
if Entry<>'' then
|
|
AddToRecentList(Entry,Self,MaxCount,ListType);
|
|
Result:=-1;
|
|
end;
|
|
|
|
procedure THistoryList.LoadFromXMLConfig(XMLConfig: TXMLConfig;
|
|
const Path: string);
|
|
begin
|
|
if FName='' then
|
|
FName:=XMLConfig.GetValue(Path+'Name','');
|
|
FMaxCount:=XMLConfig.GetValue(Path+'MaxCount',MaxCount);
|
|
FListType:=StrToRecentListType(XMLConfig.GetValue(Path+'Type',''));
|
|
LoadRecentList(XMLConfig,Self,Path,ListType);
|
|
end;
|
|
|
|
procedure THistoryList.SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
|
|
begin
|
|
XMLConfig.SetDeleteValue(Path+'Name',Name,'');
|
|
XMLConfig.SetDeleteValue(Path+'Type',RecentListTypeNames[ListType],
|
|
RecentListTypeNames[rltCaseSensitive]);
|
|
XMLConfig.SetDeleteValue(Path+'MaxCount',MaxCount,20);
|
|
SaveRecentList(XMLConfig,Self,Path);
|
|
end;
|
|
|
|
procedure THistoryList.AppendEntry(const Entry: string);
|
|
begin
|
|
if (Count<MaxCount) and (IndexOf(Entry)<0) then
|
|
Add(Entry);
|
|
end;
|
|
|
|
function THistoryList.IndexOf(const S: string): Integer;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i:=0 to Count-1 do
|
|
if CompareRecentListItem(S,Strings[i],ListType) then
|
|
exit(i);
|
|
Result:=-1;
|
|
end;
|
|
|
|
{ THistoryLists }
|
|
|
|
function THistoryLists.GetItems(Index: integer): THistoryList;
|
|
begin
|
|
Result:=THistoryList(FItems[Index]);
|
|
end;
|
|
|
|
function THistoryLists.GetXMLListPath(const Path: string; i: integer;
|
|
ALegacyList: Boolean): string;
|
|
begin
|
|
Result:=Path+TXMLConfig.GetListItemXPath('List', i, ALegacyList, False)+'/';
|
|
end;
|
|
|
|
constructor THistoryLists.Create;
|
|
begin
|
|
FItems:=TList.Create;
|
|
end;
|
|
|
|
destructor THistoryLists.Destroy;
|
|
begin
|
|
Clear;
|
|
FItems.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure THistoryLists.Clear;
|
|
var i: integer;
|
|
begin
|
|
for i:=0 to Count-1 do
|
|
Items[i].Free;
|
|
FItems.Clear;
|
|
end;
|
|
|
|
function THistoryLists.Count: integer;
|
|
begin
|
|
Result:=FItems.Count;
|
|
end;
|
|
|
|
procedure THistoryLists.LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
|
|
var
|
|
MergeCount, i: integer;
|
|
CurList: THistoryList;
|
|
ListName, ListPath: string;
|
|
ListType: TRecentListType;
|
|
IsLegacyList: Boolean;
|
|
begin
|
|
IsLegacyList:=XMLConfig.IsLegacyList(Path);
|
|
MergeCount:=XMLConfig.GetListItemCount(Path, 'List', IsLegacyList);
|
|
for i:=0 to MergeCount-1 do begin
|
|
ListPath:=GetXMLListPath(Path,i,IsLegacyList);
|
|
ListName:=XMLConfig.GetValue(ListPath+'Name','');
|
|
if ListName='' then continue;
|
|
ListType:=StrToRecentListType(XMLConfig.GetValue(ListPath+'Type',''));
|
|
CurList:=GetList(ListName,true,ListType);
|
|
CurList.LoadFromXMLConfig(XMLConfig,ListPath);
|
|
end;
|
|
end;
|
|
|
|
procedure THistoryLists.SaveToXMLConfig(XMLConfig: TXMLConfig;
|
|
const Path: string; const ALegacyList: Boolean);
|
|
var
|
|
i, CurID: integer;
|
|
begin
|
|
XMLConfig.SetListItemCount(Path,Count,ALegacyList);
|
|
CurID:=0;
|
|
for i:=0 to Count-1 do begin
|
|
if Items[i].Count>0 then begin
|
|
Items[i].SaveToXMLConfig(XMLConfig,GetXMLListPath(Path,CurID,ALegacyList));
|
|
inc(CurID);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function THistoryLists.IndexOfName(const Name: string): integer;
|
|
begin
|
|
Result:=Count-1;
|
|
while (Result>=0) and (UTF8CompareLatinTextFast(Items[Result].Name,Name)<>0) do
|
|
dec(Result);
|
|
end;
|
|
|
|
function THistoryLists.GetList(const Name: string; CreateIfNotExists: boolean;
|
|
ListType: TRecentListType): THistoryList;
|
|
var
|
|
i: integer;
|
|
begin
|
|
i:=IndexOfName(Name);
|
|
if i>=0 then
|
|
Result:=Items[i]
|
|
else if CreateIfNotExists then begin
|
|
Result:=THistoryList.Create(ListType);
|
|
Result.Name:=Name;
|
|
FItems.Add(Result);
|
|
end else
|
|
Result:=nil;
|
|
end;
|
|
|
|
procedure THistoryLists.Add(const ListName, Entry: string;
|
|
ListType: TRecentListType);
|
|
begin
|
|
GetList(ListName,true,ListType).Push(Entry);
|
|
end;
|
|
|
|
{ TIHIgnoreIDEQuestionList }
|
|
|
|
function TIHIgnoreIDEQuestionList.FindNode(const Identifier: string): TAvlTreeNode;
|
|
begin
|
|
Result:=FItems.FindKey(Pointer(Identifier),@CompareAnsiStringWithIHIgnoreItem);
|
|
end;
|
|
|
|
constructor TIHIgnoreIDEQuestionList.Create;
|
|
begin
|
|
FItems:=TAvlTree.Create(@CompareIHIgnoreItems);
|
|
end;
|
|
|
|
destructor TIHIgnoreIDEQuestionList.Destroy;
|
|
begin
|
|
FItems.FreeAndClear;
|
|
FreeAndNil(FItems);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TIHIgnoreIDEQuestionList.Clear;
|
|
begin
|
|
FItems.FreeAndClear;
|
|
end;
|
|
|
|
function TIHIgnoreIDEQuestionList.Add(const Identifier: string;
|
|
const Duration: TIgnoreQuestionDuration; const Flag: string): TIgnoreIDEQuestionItem;
|
|
var
|
|
Node: TAvlTreeNode;
|
|
begin
|
|
Node:=FindNode(Identifier);
|
|
if Node<>nil then begin
|
|
Result:=TIgnoreIDEQuestionItem(Node.Data);
|
|
end else begin
|
|
Result:=TIgnoreIDEQuestionItem.Create(Identifier);
|
|
FItems.Add(Result);
|
|
end;
|
|
Result.Duration:=Duration;
|
|
Result.Date:=Now;
|
|
Result.Flag:=Flag;
|
|
end;
|
|
|
|
procedure TIHIgnoreIDEQuestionList.Delete(const Identifier: string);
|
|
var
|
|
Node: TAvlTreeNode;
|
|
begin
|
|
Node:=FindNode(Identifier);
|
|
if Node<>nil then
|
|
FItems.FreeAndDelete(Node);
|
|
end;
|
|
|
|
function TIHIgnoreIDEQuestionList.Find(const Identifier: string): TIgnoreIDEQuestionItem;
|
|
var
|
|
Node: TAvlTreeNode;
|
|
begin
|
|
Node:=FindNode(Identifier);
|
|
if Node<>nil then
|
|
Result:=TIgnoreIDEQuestionItem(Node.Data)
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
|
|
procedure TIHIgnoreIDEQuestionList.LoadFromXMLConfig(XMLConfig: TXMLConfig;
|
|
const Path: string);
|
|
var
|
|
Cnt: longint;
|
|
i: Integer;
|
|
SubPath: String;
|
|
Identifier: String;
|
|
ADate: TDateTime;
|
|
ADuration: TIgnoreQuestionDuration;
|
|
Item: TIgnoreIDEQuestionItem;
|
|
CurNow: TDateTime;
|
|
begin
|
|
Clear;
|
|
CurNow:=Now;
|
|
Cnt:=XMLConfig.GetValue(Path+'Count',0);
|
|
for i:=1 to Cnt do begin
|
|
SubPath:=Path+'Item'+IntToStr(i)+'/';
|
|
Identifier:=XMLConfig.GetValue(SubPath+'Name','');
|
|
if Identifier='' then continue;
|
|
if not CfgStrToDate(XMLConfig.GetValue(SubPath+'Date',''),ADate) then continue;
|
|
ADuration:=NameToIHIgnoreItemDuration(XMLConfig.GetValue(SubPath+'Duration',
|
|
IHIgnoreItemDurationNames[iiid24H]));
|
|
//debugln(['TIHIgnoreIDEQuestionList.LoadFromXMLConfig Identifier="',Identifier,'" Date=',DateTimeToStr(ADate),' Diff=',DateTimeToStr(CurNow-ADate),' Duration=',IHIgnoreItemDurationNames[ADuration]]);
|
|
case ADuration of
|
|
iiidIDERestart: continue;
|
|
iiid24H: if Abs(CurNow-ADate)>1 then continue;
|
|
iiidForever: ;
|
|
end;
|
|
Item:=Add(Identifier,ADuration);
|
|
Item.Date:=ADate;
|
|
Item.Flag:=XMLConfig.GetValue(SubPath+'Flag','');
|
|
end;
|
|
end;
|
|
|
|
procedure TIHIgnoreIDEQuestionList.SaveToXMLConfig(XMLConfig: TXMLConfig;
|
|
const Path: string);
|
|
var
|
|
i: Integer;
|
|
Node: TAvlTreeNode;
|
|
Item: TIgnoreIDEQuestionItem;
|
|
SubPath: String;
|
|
begin
|
|
i:=0;
|
|
Node:=FItems.FindLowest;
|
|
while Node<>nil do begin
|
|
Item:=TIgnoreIDEQuestionItem(Node.Data);
|
|
if (Item.Duration<>iiidIDERestart) and (Item.Identifier<>'') then begin
|
|
inc(i);
|
|
SubPath:=Path+'Item'+IntToStr(i)+'/';
|
|
XMLConfig.SetDeleteValue(SubPath+'Name',Item.Identifier,'');
|
|
XMLConfig.SetDeleteValue(SubPath+'Date',DateToCfgStr(Item.Date),'');
|
|
XMLConfig.SetDeleteValue(SubPath+'Duration',
|
|
IHIgnoreItemDurationNames[Item.Duration],
|
|
IHIgnoreItemDurationNames[iiid24H]);
|
|
XMLConfig.SetDeleteValue(SubPath+'Flag',Item.Flag,'');
|
|
end;
|
|
Node:=FItems.FindSuccessor(Node);
|
|
end;
|
|
XMLConfig.SetDeleteValue(Path+'Count',i,0);
|
|
end;
|
|
|
|
end.
|
|
|