IDE: messages: moved filters to options

git-svn-id: trunk@45332 -
This commit is contained in:
mattias 2014-06-04 08:38:02 +00:00
parent 2e83e4997e
commit 340073d065
4 changed files with 597 additions and 578 deletions

View File

@ -354,6 +354,7 @@ type
fMsgViewColors: array[TMsgWndColor] of TColor; fMsgViewColors: array[TMsgWndColor] of TColor;
FShowCompileDialog: Boolean; // show dialog during compile FShowCompileDialog: Boolean; // show dialog during compile
FAutoCloseCompileDialog: Boolean; // auto close dialog after succesed compile FAutoCloseCompileDialog: Boolean; // auto close dialog after succesed compile
FMsgViewFilters: TLMsgViewFilters;
// compiler + debugger + lazarus files // compiler + debugger + lazarus files
FParseValues: array[TEnvOptParseType] of TParseString; FParseValues: array[TEnvOptParseType] of TParseString;
@ -736,6 +737,7 @@ type
property MsgViewFilenameStyle: TMsgWndFileNameStyle read FMsgViewFilenameStyle property MsgViewFilenameStyle: TMsgWndFileNameStyle read FMsgViewFilenameStyle
write FMsgViewFilenameStyle; write FMsgViewFilenameStyle;
property MsgViewColors[c: TMsgWndColor]: TColor read GetMsgViewColors write SetMsgViewColors; property MsgViewColors[c: TMsgWndColor]: TColor read GetMsgViewColors write SetMsgViewColors;
property MsgViewFilters: TLMsgViewFilters read FMsgViewFilters write FMsgViewFilters;
// glyphs // glyphs
property ShowButtonGlyphs: TApplicationShowGlyphs read FShowButtonGlyphs write FShowButtonGlyphs; property ShowButtonGlyphs: TApplicationShowGlyphs read FShowButtonGlyphs write FShowButtonGlyphs;
@ -981,6 +983,7 @@ begin
FMsgViewFilenameStyle:=mwfsShort; FMsgViewFilenameStyle:=mwfsShort;
for c:=low(TMsgWndColor) to high(TMsgWndColor) do for c:=low(TMsgWndColor) to high(TMsgWndColor) do
fMsgViewColors[c]:=MsgWndDefaultColors[c]; fMsgViewColors[c]:=MsgWndDefaultColors[c];
FMsgViewFilters:=TLMsgViewFilters.Create(nil);
// glyphs // glyphs
FShowButtonGlyphs := sbgSystem; FShowButtonGlyphs := sbgSystem;
@ -1055,6 +1058,7 @@ var
i: Integer; i: Integer;
begin begin
FreeAndNil(FBuildMatrixOptions); FreeAndNil(FBuildMatrixOptions);
FreeAndNil(FMsgViewFilters);
{$IFDEF EnableNewExtTools} {$IFDEF EnableNewExtTools}
FreeAndNil(fExternalUserTools); FreeAndNil(fExternalUserTools);
{$ELSE} {$ELSE}
@ -1437,6 +1441,7 @@ begin
for mwc:=low(TMsgWndColor) to high(TMsgWndColor) do for mwc:=low(TMsgWndColor) to high(TMsgWndColor) do
fMsgViewColors[mwc]:=XMLConfig.GetValue( fMsgViewColors[mwc]:=XMLConfig.GetValue(
Path+'MsgView/Colors/'+MsgWndColorNames[mwc],MsgWndDefaultColors[mwc]); Path+'MsgView/Colors/'+MsgWndColorNames[mwc],MsgWndDefaultColors[mwc]);
MsgViewFilters.LoadFromXMLConfig(XMLConfig,'MsgView/Filters/');
// glyphs // glyphs
FShowButtonGlyphs := TApplicationShowGlyphs(XMLConfig.GetValue(Path+'ShowButtonGlyphs/Value', FShowButtonGlyphs := TApplicationShowGlyphs(XMLConfig.GetValue(Path+'ShowButtonGlyphs/Value',
@ -1816,6 +1821,7 @@ begin
for mwc:=low(TMsgWndColor) to high(TMsgWndColor) do for mwc:=low(TMsgWndColor) to high(TMsgWndColor) do
XMLConfig.SetDeleteValue(Path+'MsgView/Colors/'+MsgWndColorNames[mwc], XMLConfig.SetDeleteValue(Path+'MsgView/Colors/'+MsgWndColorNames[mwc],
fMsgViewColors[mwc],MsgWndDefaultColors[mwc]); fMsgViewColors[mwc],MsgWndDefaultColors[mwc]);
MsgViewFilters.SaveToXMLConfig(XMLConfig,'MsgView/Filters/');
// glyphs // glyphs
XMLConfig.SetDeleteValue(Path+'ShowButtonGlyphs/Value', XMLConfig.SetDeleteValue(Path+'ShowButtonGlyphs/Value',

View File

@ -39,75 +39,11 @@ uses
SynEditMarks, LResources, Forms, Buttons, ExtCtrls, Controls, LMessages, SynEditMarks, LResources, Forms, Buttons, ExtCtrls, Controls, LMessages,
LCLType, Graphics, LCLIntf, Themes, ImgList, GraphType, Menus, Clipbrd, LCLType, Graphics, LCLIntf, Themes, ImgList, GraphType, Menus, Clipbrd,
Dialogs, StdCtrls, IDEExternToolIntf, IDEImagesIntf, MenuIntf, PackageIntf, Dialogs, StdCtrls, IDEExternToolIntf, IDEImagesIntf, MenuIntf, PackageIntf,
IDECommands, SrcEditorIntf, LazarusIDEStrConsts, EnvironmentOpts, IDECommands, SrcEditorIntf, IDEDialogs, LazarusIDEStrConsts, EnvironmentOpts,
HelpFPCMessages, etSrcEditMarks, etQuickFixes, ExtTools; HelpFPCMessages, etSrcEditMarks, etQuickFixes, ExtTools, IDEOptionDefs;
const const
CustomViewCaption = '------------------------------'; CustomViewCaption = '------------------------------';
type
TLMsgViewFilter = class;
{ TLMVFilterMsgType - read/write by main, read by worker thread }
TLMVFilterMsgType = class
private
FFilter: TLMsgViewFilter;
FIndex: integer;
FMsgID: integer;
FSubTool: string;
procedure SetMsgID(AValue: integer);
procedure SetSubTool(AValue: string);
procedure Changed;
procedure InternalAssign(Src: TLMVFilterMsgType);
public
constructor Create(aFilter: TLMsgViewFilter);
function IsEqual(Src: TLMVFilterMsgType): boolean;
procedure Assign(Src: TLMVFilterMsgType);
property Filter: TLMsgViewFilter read FFilter;
property SubTool: string read FSubTool write SetSubTool;
property MsgID: integer read FMsgID write SetMsgID;
property Index: integer read FIndex;
end;
{ TLMsgViewFilter
Note: The View.Filter is protected by View.Enter/LeaveCriticalSection,
read/write by main thread, read by worker thread.
}
TLMsgViewFilter = class
private
FCaption: string;
FFilterNotesWithoutPos: boolean;
FMinUrgency: TMessageLineUrgency;
FOnChanged: TNotifyEvent;
fFilterMsgTypes: array of TLMVFilterMsgType; // sorted for SubTool, MsgID
function GetFilterMsgTypes(Index: integer): TLMVFilterMsgType; inline;
procedure SetCaption(AValue: string);
procedure SetFilterNotesWithoutPos(AValue: boolean);
procedure SetMinUrgency(AValue: TMessageLineUrgency);
procedure Changed;
procedure UpdateFilterMsgTypeIndex(Item: TLMVFilterMsgType);
public
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure SetToFitsAll;
function IsEqual(Src: TLMsgViewFilter): boolean; // does not check Caption
procedure Assign(Src: TLMsgViewFilter); // does not copy Caption
function LineFits(Line: TMessageLine): boolean; virtual;
property Caption: string read FCaption write SetCaption;
property MinUrgency: TMessageLineUrgency read FMinUrgency write SetMinUrgency;
property FilterNotesWithoutPos: boolean read FFilterNotesWithoutPos write SetFilterNotesWithoutPos;
function FilterMsgTypeCount: integer; inline;
property FilterMsgTypes[Index: integer]: TLMVFilterMsgType read GetFilterMsgTypes;
function AddFilterMsgType(SubTool: string; MsgID: integer): TLMVFilterMsgType;
procedure DeleteFilterMsgType(Index: integer);
procedure ClearFilterMsgTypes;
function IndexOfFilterMsgType(Line: TMessageLine): integer;
property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
procedure ConsistencyCheck;
end;
type type
TMessagesCtrl = class; TMessagesCtrl = class;
@ -199,7 +135,6 @@ type
FAutoScrollToNewMessage: boolean; FAutoScrollToNewMessage: boolean;
FBackgroundColor: TColor; FBackgroundColor: TColor;
FFilenameStyle: TMsgWndFileNameStyle; FFilenameStyle: TMsgWndFileNameStyle;
FFilters: TFPList; // list of TLMsgViewFilter
FHeaderBackground: array[TLMVToolState] of TColor; FHeaderBackground: array[TLMVToolState] of TColor;
FIdleConnected: boolean; FIdleConnected: boolean;
FImageChangeLink: TChangeLink; FImageChangeLink: TChangeLink;
@ -222,7 +157,7 @@ type
FAutoHeaderBackground: TColor; FAutoHeaderBackground: TColor;
procedure CreateSourceMark(MsgLine: TMessageLine; aSynEdit: TSynEdit); procedure CreateSourceMark(MsgLine: TMessageLine; aSynEdit: TSynEdit);
procedure CreateSourceMarks(View: TLMsgWndView; StartLineNumber: Integer); procedure CreateSourceMarks(View: TLMsgWndView; StartLineNumber: Integer);
function GetFilters(Index: integer): TLMsgViewFilter; function GetActiveFilter: TLMsgViewFilter; inline;
function GetHeaderBackground(aToolState: TLMVToolState): TColor; function GetHeaderBackground(aToolState: TLMVToolState): TColor;
function GetSelectedLine: integer; function GetSelectedLine: integer;
function GetUrgencyStyles(Urgency: TMessageLineUrgency function GetUrgencyStyles(Urgency: TMessageLineUrgency
@ -230,9 +165,9 @@ type
function GetViews(Index: integer): TLMsgWndView; function GetViews(Index: integer): TLMsgWndView;
procedure OnViewChanged(Sender: TObject); // (main thread) procedure OnViewChanged(Sender: TObject); // (main thread)
procedure MsgUpdateTimerTimer(Sender: TObject); procedure MsgUpdateTimerTimer(Sender: TObject);
procedure SetActiveFilter(AValue: TLMsgViewFilter); inline;
procedure SetBackgroundColor(AValue: TColor); procedure SetBackgroundColor(AValue: TColor);
procedure SetFilenameStyle(AValue: TMsgWndFileNameStyle); procedure SetFilenameStyle(AValue: TMsgWndFileNameStyle);
procedure SetActiveFilter(AValue: TLMsgViewFilter);
procedure SetHeaderBackground(aToolState: TLMVToolState; AValue: TColor); procedure SetHeaderBackground(aToolState: TLMVToolState; AValue: TColor);
procedure SetIdleConnected(AValue: boolean); procedure SetIdleConnected(AValue: boolean);
procedure SetImages(AValue: TCustomImageList); procedure SetImages(AValue: TCustomImageList);
@ -274,7 +209,6 @@ type
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer
); override; ); override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override; procedure KeyDown(var Key: Word; Shift: TShiftState); override;
function GetDefaultFilterCaption: string;
procedure DoOnShowHint(HintInfo: PHintInfo); override; procedure DoOnShowHint(HintInfo: PHintInfo); override;
procedure DoAllViewsStopped; procedure DoAllViewsStopped;
public public
@ -284,8 +218,6 @@ type
procedure EndUpdate; procedure EndUpdate;
procedure EraseBackground({%H-}DC: HDC); override; procedure EraseBackground({%H-}DC: HDC); override;
procedure ApplyEnvironmentOptions; procedure ApplyEnvironmentOptions;
procedure LoadFromConfig(Cfg: TConfigStorage; FileVersion: integer);
procedure SaveToConfig(Cfg: TConfigStorage);
// views // views
function ViewCount: integer; inline; function ViewCount: integer; inline;
@ -301,12 +233,8 @@ type
function GetLastViewWithContent: TLMsgWndView; function GetLastViewWithContent: TLMsgWndView;
// filter // filter
property ActiveFilter: TLMsgViewFilter read FActiveFilter write SetActiveFilter; property ActiveFilter: TLMsgViewFilter read GetActiveFilter write SetActiveFilter;
function FilterCount: integer; inline; function Filters: TLMsgViewFilters; inline;
property Filters[Index: integer]: TLMsgViewFilter read GetFilters;
function GetFilter(aCaption: string; CreateIfNotExist: boolean): TLMsgViewFilter;
procedure DeleteFilter(Index: integer);
procedure ClearFilters;
// select, search // select, search
function HasSelection: boolean; function HasSelection: boolean;
@ -424,8 +352,6 @@ type
destructor Destroy; override; destructor Destroy; override;
procedure ApplyIDEOptions; procedure ApplyIDEOptions;
procedure LoadFromConfig(Cfg: TConfigStorage; FileVersion: integer);
procedure SaveToConfig(Cfg: TConfigStorage);
// Views // Views
function ViewCount: integer; function ViewCount: integer;
@ -501,9 +427,6 @@ var
procedure RegisterStandardMessagesViewMenuItems; procedure RegisterStandardMessagesViewMenuItems;
function CompareFilterMsgType(FilterMsgType1, FilterMsgType2: Pointer): integer;
function CompareLineAndFilterMsgType(MessageLine1, FilterMsgType1: Pointer): integer;
implementation implementation
procedure RegisterStandardMessagesViewMenuItems; procedure RegisterStandardMessagesViewMenuItems;
@ -573,340 +496,8 @@ begin
MsgShowIDMenuItem:=RegisterIDEMenuCommand(Root, 'ShowID', 'Show Message Type ID'); MsgShowIDMenuItem:=RegisterIDEMenuCommand(Root, 'ShowID', 'Show Message Type ID');
end; end;
function CompareFilterMsgType(FilterMsgType1, FilterMsgType2: Pointer): integer;
var
Item1: TLMVFilterMsgType absolute FilterMsgType1;
Item2: TLMVFilterMsgType absolute FilterMsgType2;
begin
Result:=SysUtils.CompareText(Item1.SubTool,Item2.SubTool);
if Result<>0 then exit;
if Item1.MsgID<Item2.MsgID then
exit(-1)
else if Item1.MsgID>Item2.MsgID then
exit(1);
Result:=0;
end;
function CompareLineAndFilterMsgType(MessageLine1, FilterMsgType1: Pointer
): integer;
var
Line: TMessageLine absolute MessageLine1;
Item: TLMVFilterMsgType absolute FilterMsgType1;
begin
Result:=SysUtils.CompareText(Line.SubTool,Item.SubTool);
if Result<>0 then exit;
if Line.MsgID<Item.MsgID then
exit(-1)
else if Line.MsgID>Item.MsgID then
exit(1);
Result:=0;
end;
{$R *.lfm} {$R *.lfm}
{ TLMVFilterMsgType }
procedure TLMVFilterMsgType.SetMsgID(AValue: integer);
begin
if FMsgID=AValue then Exit;
FMsgID:=AValue;
Changed;
end;
procedure TLMVFilterMsgType.SetSubTool(AValue: string);
begin
if FSubTool=AValue then Exit;
FSubTool:=AValue;
Changed;
end;
procedure TLMVFilterMsgType.Changed;
begin
Filter.UpdateFilterMsgTypeIndex(Self);
Filter.Changed;
end;
procedure TLMVFilterMsgType.InternalAssign(Src: TLMVFilterMsgType);
begin
fSubTool:=Src.SubTool;
fMsgID:=Src.MsgID;
end;
constructor TLMVFilterMsgType.Create(aFilter: TLMsgViewFilter);
begin
FFilter:=aFilter;
end;
function TLMVFilterMsgType.IsEqual(Src: TLMVFilterMsgType): boolean;
begin
if Self=Src then exit(true);
Result:=(SubTool=Src.SubTool)
and (MsgID=Src.MsgID);
end;
procedure TLMVFilterMsgType.Assign(Src: TLMVFilterMsgType);
begin
if IsEqual(Src) then exit;
InternalAssign(Src);
Changed;
end;
{ TLMsgViewFilter }
// inline
function TLMsgViewFilter.FilterMsgTypeCount: integer;
begin
Result:=length(fFilterMsgTypes);
end;
// inline
function TLMsgViewFilter.GetFilterMsgTypes(Index: integer): TLMVFilterMsgType;
begin
Result:=fFilterMsgTypes[Index];
end;
procedure TLMsgViewFilter.SetCaption(AValue: string);
begin
AValue:=UTF8Trim(AValue,[]);
if FCaption=AValue then Exit;
FCaption:=AValue;
end;
procedure TLMsgViewFilter.SetMinUrgency(AValue: TMessageLineUrgency);
begin
if FMinUrgency=AValue then Exit;
FMinUrgency:=AValue;
Changed;
end;
procedure TLMsgViewFilter.SetFilterNotesWithoutPos(AValue: boolean);
begin
if FFilterNotesWithoutPos=AValue then Exit;
FFilterNotesWithoutPos:=AValue;
Changed;
end;
procedure TLMsgViewFilter.Changed;
begin
if Assigned(OnChanged) then
OnChanged(Self);
end;
procedure TLMsgViewFilter.UpdateFilterMsgTypeIndex(Item: TLMVFilterMsgType);
var
OldIndex: Integer;
l: Integer;
r: Integer;
m: Integer;
cmp: Integer;
StartIndex: Integer;
EndIndex: Integer;
NewIndex: Integer;
begin
if FilterMsgTypeCount=1 then exit;
OldIndex:=Item.FIndex;
if (OldIndex>0) and (CompareFilterMsgType(Item,fFilterMsgTypes[OldIndex-1])<0)
then begin
StartIndex:=0;
EndIndex:=OldIndex-1;
end else if (OldIndex<FilterMsgTypeCount-1)
and (CompareFilterMsgType(Item,fFilterMsgTypes[OldIndex+1])>0) then begin
StartIndex:=OldIndex+1;
EndIndex:=FilterMsgTypeCount-1;
end else
exit;
l:=StartIndex;
r:=EndIndex;
m:=0;
cmp:=0;
while l<=r do begin
m:=(l+r) div 2;
cmp:=CompareFilterMsgType(Item,fFilterMsgTypes[m]);
if cmp<0 then
r:=m-1
else if cmp>0 then
l:=m+1
else
break;
end;
if cmp<=0 then
NewIndex:=m
else
NewIndex:=m+1;
if OldIndex<NewIndex then begin
system.Move(fFilterMsgTypes[OldIndex+1],fFilterMsgTypes[OldIndex],
SizeOf(TLMVFilterMsgType)*(NewIndex-OldIndex));
end else if OldIndex>NewIndex then begin
system.Move(fFilterMsgTypes[NewIndex],fFilterMsgTypes[NewIndex+1],
SizeOf(TLMVFilterMsgType)*(OldIndex-NewIndex));
end else
exit;
fFilterMsgTypes[NewIndex]:=Item;
{$IFDEF CheckExtTools}
ConsistencyCheck;
{$ENDIF}
end;
constructor TLMsgViewFilter.Create;
begin
FMinUrgency:=mluHint;
FFilterNotesWithoutPos:=true;
end;
destructor TLMsgViewFilter.Destroy;
begin
ClearFilterMsgTypes;
inherited Destroy;
end;
procedure TLMsgViewFilter.Clear;
begin
MinUrgency:=mluHint;
FilterNotesWithoutPos:=true;
ClearFilterMsgTypes;
end;
procedure TLMsgViewFilter.SetToFitsAll;
begin
MinUrgency:=mluNone;
FilterNotesWithoutPos:=false;
ClearFilterMsgTypes;
end;
function TLMsgViewFilter.IsEqual(Src: TLMsgViewFilter): boolean;
var
i: Integer;
begin
Result:=false;
if Self=Src then exit(true);
if (MinUrgency<>Src.MinUrgency)
or (FilterNotesWithoutPos<>Src.FilterNotesWithoutPos)
or (FilterMsgTypeCount<>Src.FilterMsgTypeCount)
then exit;
for i:=0 to FilterMsgTypeCount-1 do
if not FilterMsgTypes[i].IsEqual(Src.FilterMsgTypes[i]) then exit;
Result:=true;
end;
procedure TLMsgViewFilter.Assign(Src: TLMsgViewFilter);
var
NewCnt: Integer;
OldCnt: Integer;
i: Integer;
begin
if IsEqual(Src) then exit;
fMinUrgency:=Src.MinUrgency;
FFilterNotesWithoutPos:=Src.FilterNotesWithoutPos;
// filter msg type
NewCnt:=Src.FilterMsgTypeCount;
OldCnt:=FilterMsgTypeCount;
for i:=NewCnt to OldCnt-1 do
FreeAndNil(fFilterMsgTypes[i]);
SetLength(fFilterMsgTypes,NewCnt);
for i:=0 to NewCnt-1 do begin
if fFilterMsgTypes[i]=nil then
fFilterMsgTypes[i]:=TLMVFilterMsgType.Create(Self);
fFilterMsgTypes[i].InternalAssign(Src.FilterMsgTypes[i]);
end;
Changed;
end;
function TLMsgViewFilter.LineFits(Line: TMessageLine): boolean;
begin
Result:=false;
if ord(Line.Urgency)<ord(MinUrgency) then exit;
if [mlfHiddenByIDEDirective,mlfFixed]*Line.Flags<>[] then exit;
if FilterNotesWithoutPos and (Line.Urgency<=mluNote)
and ((Line.Filename='') or (Line.Line<1)) then exit;
if IndexOfFilterMsgType(Line)>=0 then exit;
Result:=true;
end;
function TLMsgViewFilter.AddFilterMsgType(SubTool: string;
MsgID: integer): TLMVFilterMsgType;
var
i: Integer;
begin
i:=length(fFilterMsgTypes);
SetLength(fFilterMsgTypes,i+1);
Result:=TLMVFilterMsgType.Create(Self);
fFilterMsgTypes[i]:=Result;
Result.FSubTool:=SubTool;
Result.FMsgID:=MsgID;
UpdateFilterMsgTypeIndex(Result);
Changed;
end;
procedure TLMsgViewFilter.DeleteFilterMsgType(Index: integer);
begin
if (Index<0) or (Index>=FilterMsgTypeCount) then
raise Exception.Create('');
fFilterMsgTypes[Index].Free;
if Index<FilterMsgTypeCount-1 then
system.Move(fFilterMsgTypes[Index+1],fFilterMsgTypes[Index],
SizeOf(TLMVFilterMsgType)*(FilterMsgTypeCount-Index-1));
SetLength(fFilterMsgTypes,length(fFilterMsgTypes)-1);
Changed;
end;
procedure TLMsgViewFilter.ClearFilterMsgTypes;
var
i: Integer;
begin
if FilterMsgTypeCount=0 then exit;
for i:=0 to FilterMsgTypeCount-1 do
fFilterMsgTypes[i].Free;
SetLength(fFilterMsgTypes,0);
Changed;
end;
function TLMsgViewFilter.IndexOfFilterMsgType(Line: TMessageLine): integer;
var
l: Integer;
r: Integer;
m: Integer;
cmp: Integer;
begin
l:=0;
r:=FilterMsgTypeCount-1;
while l<=r do begin
m:=(l+r) div 2;
cmp:=CompareLineAndFilterMsgType(Line,fFilterMsgTypes[m]);
if cmp<0 then
r:=m-1
else if cmp>0 then
l:=m+1
else
exit(m);
end;
Result:=-1;
end;
procedure TLMsgViewFilter.ConsistencyCheck;
procedure E(Msg: string);
begin
raise Exception.Create(Msg);
end;
var
i: Integer;
begin
for i:=0 to FilterMsgTypeCount-2 do begin
if CompareFilterMsgType(fFilterMsgTypes[i],fFilterMsgTypes[i+1])>0 then
E(IntToStr(i));
end;
end;
{ TLMsgWndView } { TLMsgWndView }
procedure TLMsgWndView.OnMarksFixed(ListOfTMessageLine: TFPList); procedure TLMsgWndView.OnMarksFixed(ListOfTMessageLine: TFPList);
@ -1338,9 +929,21 @@ begin
end; end;
// inline // inline
function TMessagesCtrl.FilterCount: integer; function TMessagesCtrl.Filters: TLMsgViewFilters;
begin begin
Result:=FFilters.Count; Result:=EnvironmentOptions.MsgViewFilters;
end;
// inline
function TMessagesCtrl.GetActiveFilter: TLMsgViewFilter;
begin
Result:=Filters.ActiveFilter;
end;
// inline
procedure TMessagesCtrl.SetActiveFilter(AValue: TLMsgViewFilter);
begin
Filters.ActiveFilter:=AValue;
end; end;
function TMessagesCtrl.GetViews(Index: integer): TLMsgWndView; function TMessagesCtrl.GetViews(Index: integer): TLMsgWndView;
@ -1444,20 +1047,6 @@ begin
Invalidate; Invalidate;
end; end;
procedure TMessagesCtrl.SetActiveFilter(AValue: TLMsgViewFilter);
var
i: Integer;
begin
if (AValue=nil) or (ActiveFilter=AValue) then exit;
i:=FFilters.IndexOf(AValue);
if i<0 then begin
if FActiveFilter.IsEqual(AValue) then exit;
FActiveFilter.Assign(AValue);
end else
FActiveFilter:=AValue;
IdleConnected:=true;
end;
procedure TMessagesCtrl.SetHeaderBackground(aToolState: TLMVToolState; procedure TMessagesCtrl.SetHeaderBackground(aToolState: TLMVToolState;
AValue: TColor); AValue: TColor);
begin begin
@ -1724,19 +1313,6 @@ begin
CreateSourceMark(View.Lines[i],nil); CreateSourceMark(View.Lines[i],nil);
end; end;
function TMessagesCtrl.GetFilters(Index: integer): TLMsgViewFilter;
procedure RaiseOutOfBounds;
begin
raise Exception.Create('TMessagesCtrl.GetFilters '+IntToStr(Index)+' out of bounds '+IntToStr(FilterCount));
end;
begin
if (Index<0) or (Index>=FilterCount) then
RaiseOutOfBounds;
Result:=TLMsgViewFilter(fFilters[Index]);
end;
function TMessagesCtrl.GetHeaderBackground(aToolState: TLMVToolState): TColor; function TMessagesCtrl.GetHeaderBackground(aToolState: TLMVToolState): TColor;
begin begin
Result:=FHeaderBackground[aToolState]; Result:=FHeaderBackground[aToolState];
@ -2056,11 +1632,6 @@ begin
end; end;
end; end;
function TMessagesCtrl.GetDefaultFilterCaption: string;
begin
Result:='Default';
end;
procedure TMessagesCtrl.DoOnShowHint(HintInfo: PHintInfo); procedure TMessagesCtrl.DoOnShowHint(HintInfo: PHintInfo);
var var
View: TLMsgWndView; View: TLMsgWndView;
@ -2609,53 +2180,6 @@ begin
Result:=nil; Result:=nil;
end; end;
function TMessagesCtrl.GetFilter(aCaption: string; CreateIfNotExist: boolean
): TLMsgViewFilter;
var
i: Integer;
begin
for i:=0 to FilterCount-1 do begin
Result:=Filters[i];
if SysUtils.CompareText(Result.Caption,aCaption)=0 then exit;
end;
if not CreateIfNotExist then
exit(nil);
Result:=TLMsgViewFilter.Create;
Result.Caption:=aCaption;
Result.OnChanged:=@OnFilterChanged;
FFilters.Add(Result);
end;
procedure TMessagesCtrl.DeleteFilter(Index: integer);
var
CurFilter: TLMsgViewFilter;
begin
CurFilter:=Filters[Index];
if (CurFilter=ActiveFilter) then begin
if FilterCount=1 then begin
CurFilter.Clear;
exit;
end;
if Index>0 then
ActiveFilter:=Filters[0]
else
ActiveFilter:=Filters[1];
end;
FFilters.Delete(Index);
CurFilter.Free;
end;
procedure TMessagesCtrl.ClearFilters;
var
i: Integer;
begin
for i:=FilterCount-1 downto 0 do begin
if Filters[i]=ActiveFilter then continue;
DeleteFilter(i);
end;
ActiveFilter.Clear;
end;
procedure TMessagesCtrl.Select(View: TLMsgWndView; LineNumber: integer; procedure TMessagesCtrl.Select(View: TLMsgWndView; LineNumber: integer;
DoScroll, FullyVisible: boolean); DoScroll, FullyVisible: boolean);
begin begin
@ -2721,11 +2245,8 @@ begin
inherited Create(AOwner); inherited Create(AOwner);
ControlStyle:=ControlStyle-[csCaptureMouse]+[csReflector]; ControlStyle:=ControlStyle-[csCaptureMouse]+[csReflector];
FOptions:=MCDefaultOptions; FOptions:=MCDefaultOptions;
FFilters:=TFPList.Create; Filters.OnChanged:=@OnFilterChanged;
FActiveFilter:=TLMsgViewFilter.Create; FActiveFilter:=Filters[0];
FActiveFilter.Caption:=GetDefaultFilterCaption;
FActiveFilter.OnChanged:=@OnFilterChanged;
FFilters.Add(FActiveFilter);
FViews:=TFPList.Create; FViews:=TFPList.Create;
FUpdateTimer:=TTimer.Create(Self); FUpdateTimer:=TTimer.Create(Self);
FUpdateTimer.Name:='MsgUpdateTimer'; FUpdateTimer.Name:='MsgUpdateTimer';
@ -2752,17 +2273,11 @@ end;
destructor TMessagesCtrl.Destroy; destructor TMessagesCtrl.Destroy;
var var
u: TMessageLineUrgency; u: TMessageLineUrgency;
i: Integer;
begin begin
IdleConnected:=false; IdleConnected:=false;
Images:=nil; Images:=nil;
ClearViews(false); ClearViews(false);
FActiveFilter:=nil;
for i:=0 to FFilters.Count-1 do
TObject(FFilters[i]).Free;
FreeAndNil(FFilters);
FreeAndNil(FViews); FreeAndNil(FViews);
FreeAndNil(FUpdateTimer); FreeAndNil(FUpdateTimer);
FreeAndNil(FImageChangeLink); FreeAndNil(FImageChangeLink);
@ -2810,17 +2325,6 @@ begin
FilenameStyle:=EnvironmentOptions.MsgViewFilenameStyle; FilenameStyle:=EnvironmentOptions.MsgViewFilenameStyle;
end; end;
procedure TMessagesCtrl.LoadFromConfig(Cfg: TConfigStorage; FileVersion: integer
);
begin
end;
procedure TMessagesCtrl.SaveToConfig(Cfg: TConfigStorage);
begin
end;
function TMessagesCtrl.IndexOfView(View: TLMsgWndView): integer; function TMessagesCtrl.IndexOfView(View: TLMsgWndView): integer;
begin begin
Result:=FViews.IndexOf(View); Result:=FViews.IndexOf(View);
@ -3013,7 +2517,7 @@ procedure TMessagesFrame.MsgCtrlPopupMenuPopup(Sender: TObject);
Item: TIDEMenuCommand; Item: TIDEMenuCommand;
Cnt: Integer; Cnt: Integer;
begin begin
Cnt:=MessagesCtrl.FilterCount; Cnt:=MessagesCtrl.Filters.Count;
for i:=0 to Cnt-1 do begin for i:=0 to Cnt-1 do begin
Filter:=MessagesCtrl.Filters[i]; Filter:=MessagesCtrl.Filters[i];
if i>=MsgSelectFilterMenuSection.Count then begin if i>=MsgSelectFilterMenuSection.Count then begin
@ -3185,7 +2689,7 @@ var
Item: TIDEMenuCommand; Item: TIDEMenuCommand;
begin begin
Item:=Sender as TIDEMenuCommand; Item:=Sender as TIDEMenuCommand;
Filter:=MessagesCtrl.GetFilter(Item.Caption,false); Filter:=MessagesCtrl.Filters.GetFilter(Item.Caption,false);
if Filter=nil then exit; if Filter=nil then exit;
MessagesCtrl.ActiveFilter:=Filter; MessagesCtrl.ActiveFilter:=Filter;
end; end;
@ -3481,19 +2985,20 @@ var
aCaption: String; aCaption: String;
i: Integer; i: Integer;
NewFilter: TLMsgViewFilter; NewFilter: TLMsgViewFilter;
Filters: TLMsgViewFilters;
begin begin
aCaption:='Filter'; aCaption:='Filter';
i:=1; i:=1;
while MessagesCtrl.GetFilter(aCaption+IntToStr(i),false)<>nil do Filters:=MessagesCtrl.Filters;
while Filters.GetFilter(aCaption+IntToStr(i),false)<>nil do
inc(i); inc(i);
aCaption:=UTF8Trim(InputBox('Create Filter','Name:',aCaption),[]); aCaption:=UTF8Trim(InputBox('Create Filter','Name:',aCaption),[]);
if aCaption='' then exit; if aCaption='' then exit;
if MessagesCtrl.GetFilter(aCaption,false)<>nil then begin if Filters.GetFilter(aCaption,false)<>nil then begin
// ToDo: use IDEMessageDlg IDEMessageDialog('Filter already exists','A filter with the name "'+aCaption+'" already exists.',mtError,[mbCancel],'');
MessageDlg('Filter already exists','A filter with the name "'+aCaption+'" already exists.',mtError,[mbCancel],'');
exit; exit;
end; end;
NewFilter:=MessagesCtrl.GetFilter(aCaption,true); NewFilter:=Filters.GetFilter(aCaption,true);
NewFilter.Assign(MessagesCtrl.ActiveFilter); NewFilter.Assign(MessagesCtrl.ActiveFilter);
MessagesCtrl.ActiveFilter:=NewFilter; MessagesCtrl.ActiveFilter:=NewFilter;
end; end;
@ -3522,10 +3027,10 @@ var
begin begin
Dlg:=TSaveDialog.Create(nil); Dlg:=TSaveDialog.Create(nil);
try try
// ToDo: initfiledialog
Dlg.Title:='Save messages'; Dlg.Title:='Save messages';
Dlg.FileName:='messages.txt'; Dlg.FileName:='messages.txt';
Dlg.Options:=Dlg.Options+[ofPathMustExist,ofCreatePrompt]; Dlg.Options:=Dlg.Options+[ofPathMustExist,ofCreatePrompt];
InitIDEFileDialog(Dlg);
if not Dlg.Execute then exit; if not Dlg.Execute then exit;
Filename:=TrimAndExpandFilename(Dlg.FileName); Filename:=TrimAndExpandFilename(Dlg.FileName);
if DirPathExistsCached(Filename) then exit; if DirPathExistsCached(Filename) then exit;
@ -3542,12 +3047,12 @@ begin
end; end;
except except
on E: Exception do begin on E: Exception do begin
// ToDo: idemessagedlg IDEMessageDialog('Write Error','Unable to write file "'+Filename+'".',mtError,[mbCancel]);
MessageDlg('Write Error','Unable to write file "'+Filename+'".',mtError,[mbCancel],0);
end; end;
end; end;
finally finally
StoreIDEFileDialog(Dlg);
Dlg.Free; Dlg.Free;
end; end;
end; end;
@ -3565,9 +3070,8 @@ begin
Msg:=IntToStr(length(s) div 1000)+' KB' Msg:=IntToStr(length(s) div 1000)+' KB'
else else
Msg:=IntToStr(length(s) div 1000)+' MB'; Msg:=IntToStr(length(s) div 1000)+' MB';
// ToDo: replace with IDEMessageDlg if IDEMessageDialog('Warning','This will put a lot of text ('+Msg+') on the clipboard.'#13'Proceed?',
if MessageDlg('Warning','This will put a lot of text ('+Msg+') on the clipboard.'#13'Proceed?', mtConfirmation,[mbYes,mbNo])<>mrYes then exit;
mtConfirmation,[mbYes,mbNo],0)<>mrYes then exit;
end; end;
Clipboard.AsText:=s; Clipboard.AsText:=s;
end; end;
@ -3694,17 +3198,6 @@ begin
MessagesCtrl.ApplyEnvironmentOptions; MessagesCtrl.ApplyEnvironmentOptions;
end; end;
procedure TMessagesFrame.LoadFromConfig(Cfg: TConfigStorage;
FileVersion: integer);
begin
MessagesCtrl.LoadFromConfig(Cfg,FileVersion);
end;
procedure TMessagesFrame.SaveToConfig(Cfg: TConfigStorage);
begin
MessagesCtrl.SaveToConfig(Cfg);
end;
function TMessagesFrame.ViewCount: integer; function TMessagesFrame.ViewCount: integer;
begin begin
Result:=MessagesCtrl.ViewCount; Result:=MessagesCtrl.ViewCount;

View File

@ -37,9 +37,6 @@ uses
Forms, Controls, Graphics, Dialogs, LCLProc, etMessageFrame, etSrcEditMarks, Forms, Controls, Graphics, Dialogs, LCLProc, etMessageFrame, etSrcEditMarks,
etQuickFixes; etQuickFixes;
const
MsgWndOptionsFileVersion = 1;
MsgWndOptionsFilename = 'messagesoptions.xml';
type type
{ TMessagesView } { TMessagesView }
@ -83,8 +80,6 @@ type
procedure SourceEditorPopup(MarkLine: TSynEditMarkLine); procedure SourceEditorPopup(MarkLine: TSynEditMarkLine);
// options // options
procedure LoadOptions;
procedure SaveOptions;
procedure ApplyIDEOptions; procedure ApplyIDEOptions;
property DblClickJumps: boolean read GetDblClickJumps write SetDblClickJumps; property DblClickJumps: boolean read GetDblClickJumps write SetDblClickJumps;
property HideMessagesIcons: boolean read GetHideMessagesIcons write SetHideMessagesIcons; property HideMessagesIcons: boolean read GetHideMessagesIcons write SetHideMessagesIcons;
@ -107,8 +102,6 @@ begin
MessagesFrame1.MessagesCtrl.OnOpenMessage:=@OnOpenMessage; MessagesFrame1.MessagesCtrl.OnOpenMessage:=@OnOpenMessage;
ActiveControl:=MessagesFrame1.MessagesCtrl; ActiveControl:=MessagesFrame1.MessagesCtrl;
LoadOptions;
end; end;
procedure TMessagesView.FormDestroy(Sender: TObject); procedure TMessagesView.FormDestroy(Sender: TObject);
@ -169,33 +162,6 @@ begin
MessagesFrame1.SourceEditorPopup(MarkLine); MessagesFrame1.SourceEditorPopup(MarkLine);
end; end;
procedure TMessagesView.LoadOptions;
var
Cfg: TConfigStorage;
FileVersion: Integer;
begin
Cfg:=GetIDEConfigStorage(MsgWndOptionsFilename,true);
try
FileVersion:=Cfg.GetValue('Version',0);
MessagesFrame1.LoadFromConfig(Cfg,FileVersion);
finally
Cfg.Free;
end;
end;
procedure TMessagesView.SaveOptions;
var
Cfg: TConfigStorage;
begin
Cfg:=GetIDEConfigStorage(MsgWndOptionsFilename,false);
try
MessagesFrame1.SaveToConfig(Cfg);
Cfg.SetValue('Version',MsgWndOptionsFileVersion);
finally
Cfg.Free;
end;
end;
procedure TMessagesView.Clear; procedure TMessagesView.Clear;
begin begin
MessagesFrame1.ClearViews(true); MessagesFrame1.ClearViews(true);

View File

@ -33,8 +33,8 @@ interface
uses uses
Classes, SysUtils, types, LCLProc, FileUtil, Laz2_XMLCfg, Classes, SysUtils, types, LCLProc, FileUtil, Laz2_XMLCfg,
Forms, Controls, Buttons, BaseIDEIntf, LazConfigStorage, Forms, Controls, Buttons, BaseIDEIntf, LazConfigStorage, LazUTF8,
IDEWindowIntf, LazConf; IDEWindowIntf, IDEExternToolIntf, LazConf;
type type
{ TXMLOptionsStorage } { TXMLOptionsStorage }
@ -127,6 +127,95 @@ const
'JumpHistory', 'JumpHistory',
'ComponentList' 'ComponentList'
); );
type
TLMsgViewFilter = class;
{ TLMVFilterMsgType - read/write by main, read by worker thread }
TLMVFilterMsgType = class
private
FFilter: TLMsgViewFilter;
FIndex: integer;
FMsgID: integer;
FSubTool: string;
procedure SetMsgID(AValue: integer);
procedure SetSubTool(AValue: string);
procedure Changed;
procedure InternalAssign(Src: TLMVFilterMsgType);
public
constructor Create(aFilter: TLMsgViewFilter);
function IsEqual(Src: TLMVFilterMsgType): boolean;
procedure Assign(Src: TLMVFilterMsgType);
property Filter: TLMsgViewFilter read FFilter;
property SubTool: string read FSubTool write SetSubTool;
property MsgID: integer read FMsgID write SetMsgID;
property Index: integer read FIndex;
end;
{ TLMsgViewFilter
Note: The View.Filter is protected by View.Enter/LeaveCriticalSection,
read/write by main thread, read by worker thread.
}
TLMsgViewFilter = class
private
FCaption: string;
FFilterNotesWithoutPos: boolean;
FMinUrgency: TMessageLineUrgency;
FOnChanged: TNotifyEvent;
fFilterMsgTypes: array of TLMVFilterMsgType; // sorted for SubTool, MsgID
function GetFilterMsgTypes(Index: integer): TLMVFilterMsgType; inline;
procedure SetCaption(AValue: string);
procedure SetFilterNotesWithoutPos(AValue: boolean);
procedure SetMinUrgency(AValue: TMessageLineUrgency);
procedure Changed;
procedure UpdateFilterMsgTypeIndex(Item: TLMVFilterMsgType);
public
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure SetToFitsAll;
function IsEqual(Src: TLMsgViewFilter): boolean; // does not check Caption
procedure Assign(Src: TLMsgViewFilter); // does not copy Caption
function LineFits(Line: TMessageLine): boolean; virtual;
property Caption: string read FCaption write SetCaption;
property MinUrgency: TMessageLineUrgency read FMinUrgency write SetMinUrgency;
property FilterNotesWithoutPos: boolean read FFilterNotesWithoutPos write SetFilterNotesWithoutPos;
function FilterMsgTypeCount: integer; inline;
property FilterMsgTypes[Index: integer]: TLMVFilterMsgType read GetFilterMsgTypes;
function AddFilterMsgType(SubTool: string; MsgID: integer): TLMVFilterMsgType;
procedure DeleteFilterMsgType(Index: integer);
procedure ClearFilterMsgTypes;
function IndexOfFilterMsgType(Line: TMessageLine): integer;
property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
procedure ConsistencyCheck;
end;
{ TLMsgViewFilters }
TLMsgViewFilters = class(TComponent)
private
FActiveFilter: TLMsgViewFilter;
fFilters: TFPList; // list of TLMsgViewFilter
FOnChanged: TNotifyEvent;
function GetFilters(Index: integer): TLMsgViewFilter;
procedure OnFilterChanged(Sender: TObject);
procedure SetActiveFilter(AValue: TLMsgViewFilter);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Clear;
function Count: integer; inline;
property Filters[Index: integer]: TLMsgViewFilter read GetFilters; default;
function GetFilter(aCaption: string; CreateIfNotExist: boolean): TLMsgViewFilter;
procedure Delete(Index: integer);
function IndexOf(Filter: TLMsgViewFilter): integer; inline;
function Add(Filter: TLMsgViewFilter): integer;
procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
property ActiveFilter: TLMsgViewFilter read FActiveFilter write SetActiveFilter;
property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
end;
function CreateNiceWindowPosition(Width, Height: integer): TRect; function CreateNiceWindowPosition(Width, Height: integer): TRect;
function NonModalIDEFormIDToEnum(const FormID: string): TNonModalIDEWindow; function NonModalIDEFormIDToEnum(const FormID: string): TNonModalIDEWindow;
@ -134,6 +223,10 @@ function NonModalIDEFormIDToEnum(const FormID: string): TNonModalIDEWindow;
function GetLazIDEConfigStorage(const Filename: string; LoadFromDisk: Boolean function GetLazIDEConfigStorage(const Filename: string; LoadFromDisk: Boolean
): TConfigStorage; // load errors: raises exceptions ): TConfigStorage; // load errors: raises exceptions
function CompareFilterMsgType(FilterMsgType1, FilterMsgType2: Pointer): integer;
function CompareLineAndFilterMsgType(MessageLine1, FilterMsgType1: Pointer): integer;
implementation implementation
@ -226,6 +319,164 @@ begin
Result:=TXMLOptionsStorage.Create(ConfigFilename,LoadFromDisk); Result:=TXMLOptionsStorage.Create(ConfigFilename,LoadFromDisk);
end; end;
function CompareFilterMsgType(FilterMsgType1, FilterMsgType2: Pointer): integer;
var
Item1: TLMVFilterMsgType absolute FilterMsgType1;
Item2: TLMVFilterMsgType absolute FilterMsgType2;
begin
Result:=SysUtils.CompareText(Item1.SubTool,Item2.SubTool);
if Result<>0 then exit;
if Item1.MsgID<Item2.MsgID then
exit(-1)
else if Item1.MsgID>Item2.MsgID then
exit(1);
Result:=0;
end;
function CompareLineAndFilterMsgType(MessageLine1, FilterMsgType1: Pointer
): integer;
var
Line: TMessageLine absolute MessageLine1;
Item: TLMVFilterMsgType absolute FilterMsgType1;
begin
Result:=SysUtils.CompareText(Line.SubTool,Item.SubTool);
if Result<>0 then exit;
if Line.MsgID<Item.MsgID then
exit(-1)
else if Line.MsgID>Item.MsgID then
exit(1);
Result:=0;
end;
{ TLMsgViewFilters }
// inline
function TLMsgViewFilters.Count: integer;
begin
Result:=FFilters.Count;
end;
// inline
function TLMsgViewFilters.IndexOf(Filter: TLMsgViewFilter): integer;
begin
Result:=fFilters.IndexOf(Filter);
end;
function TLMsgViewFilters.GetFilters(Index: integer): TLMsgViewFilter;
procedure RaiseOutOfBounds;
begin
raise Exception.Create('TLMsgViewFilters.GetFilters '+IntToStr(Index)+' out of bounds '+IntToStr(Count));
end;
begin
if (Index<0) or (Index>=Count) then
RaiseOutOfBounds;
Result:=TLMsgViewFilter(fFilters[Index]);
end;
procedure TLMsgViewFilters.OnFilterChanged(Sender: TObject);
begin
if csDestroying in ComponentState then exit;
if Assigned(OnChanged) then
OnChanged(Self);
end;
procedure TLMsgViewFilters.SetActiveFilter(AValue: TLMsgViewFilter);
var
i: Integer;
begin
if FActiveFilter=AValue then Exit;
i:=IndexOf(AValue);
if i<0 then begin
if FActiveFilter.IsEqual(AValue) then exit;
FActiveFilter.Assign(AValue);
end else
FActiveFilter:=AValue;
OnFilterChanged(AValue);
end;
constructor TLMsgViewFilters.Create(AOwner: TComponent);
begin
inherited;
fFilters:=TFPList.Create;
FActiveFilter:=TLMsgViewFilter.Create;
FActiveFilter.Caption:='Default';
FActiveFilter.OnChanged:=@OnFilterChanged;
fFilters.Add(FActiveFilter);
end;
destructor TLMsgViewFilters.Destroy;
begin
Clear;
ActiveFilter.Free;
FreeAndNil(fFilters);
inherited Destroy;
end;
procedure TLMsgViewFilters.Clear;
var
i: Integer;
begin
ActiveFilter:=Filters[0];
for i:=Count-1 downto 1 do
Delete(i);
Filters[0].Clear;
end;
function TLMsgViewFilters.GetFilter(aCaption: string; CreateIfNotExist: boolean
): TLMsgViewFilter;
var
i: Integer;
begin
for i:=0 to Count-1 do begin
Result:=Filters[i];
if SysUtils.CompareText(Result.Caption,aCaption)=0 then exit;
end;
if not CreateIfNotExist then
exit(nil);
Result:=TLMsgViewFilter.Create;
Result.Caption:=aCaption;
Result.OnChanged:=@OnFilterChanged;
Add(Result);
end;
procedure TLMsgViewFilters.Delete(Index: integer);
var
Filter: TLMsgViewFilter;
begin
if (Index=0) and (Count=1) then begin
ActiveFilter.Clear;
end else begin
Filter:=Filters[Index];
Filter.OnChanged:=nil;
fFilters.Delete(Index);
if ActiveFilter=Filter then
FActiveFilter:=Filters[0];
Filter.Free;
OnFilterChanged(Self);
end;
end;
function TLMsgViewFilters.Add(Filter: TLMsgViewFilter): integer;
begin
Filter.OnChanged:=@OnFilterChanged;
Result:=fFilters.Add(Filter);
OnFilterChanged(Self);
end;
procedure TLMsgViewFilters.LoadFromXMLConfig(XMLConfig: TXMLConfig;
const Path: string);
begin
end;
procedure TLMsgViewFilters.SaveToXMLConfig(XMLConfig: TXMLConfig;
const Path: string);
begin
end;
{ TXMLOptionsStorage } { TXMLOptionsStorage }
function TXMLOptionsStorage.GetFullPathValue(const APath, ADefault: String): String; function TXMLOptionsStorage.GetFullPathValue(const APath, ADefault: String): String;
@ -335,6 +586,309 @@ begin
Result:=FXMLConfig.Filename; Result:=FXMLConfig.Filename;
end; end;
{ TLMVFilterMsgType }
procedure TLMVFilterMsgType.SetMsgID(AValue: integer);
begin
if FMsgID=AValue then Exit;
FMsgID:=AValue;
Changed;
end;
procedure TLMVFilterMsgType.SetSubTool(AValue: string);
begin
if FSubTool=AValue then Exit;
FSubTool:=AValue;
Changed;
end;
procedure TLMVFilterMsgType.Changed;
begin
Filter.UpdateFilterMsgTypeIndex(Self);
Filter.Changed;
end;
procedure TLMVFilterMsgType.InternalAssign(Src: TLMVFilterMsgType);
begin
fSubTool:=Src.SubTool;
fMsgID:=Src.MsgID;
end;
constructor TLMVFilterMsgType.Create(aFilter: TLMsgViewFilter);
begin
FFilter:=aFilter;
end;
function TLMVFilterMsgType.IsEqual(Src: TLMVFilterMsgType): boolean;
begin
if Self=Src then exit(true);
Result:=(SubTool=Src.SubTool)
and (MsgID=Src.MsgID);
end;
procedure TLMVFilterMsgType.Assign(Src: TLMVFilterMsgType);
begin
if IsEqual(Src) then exit;
InternalAssign(Src);
Changed;
end;
{ TLMsgViewFilter }
// inline
function TLMsgViewFilter.FilterMsgTypeCount: integer;
begin
Result:=length(fFilterMsgTypes);
end;
// inline
function TLMsgViewFilter.GetFilterMsgTypes(Index: integer): TLMVFilterMsgType;
begin
Result:=fFilterMsgTypes[Index];
end;
procedure TLMsgViewFilter.SetCaption(AValue: string);
begin
AValue:=UTF8Trim(AValue,[]);
if FCaption=AValue then Exit;
FCaption:=AValue;
end;
procedure TLMsgViewFilter.SetMinUrgency(AValue: TMessageLineUrgency);
begin
if FMinUrgency=AValue then Exit;
FMinUrgency:=AValue;
Changed;
end;
procedure TLMsgViewFilter.SetFilterNotesWithoutPos(AValue: boolean);
begin
if FFilterNotesWithoutPos=AValue then Exit;
FFilterNotesWithoutPos:=AValue;
Changed;
end;
procedure TLMsgViewFilter.Changed;
begin
if Assigned(OnChanged) then
OnChanged(Self);
end;
procedure TLMsgViewFilter.UpdateFilterMsgTypeIndex(Item: TLMVFilterMsgType);
var
OldIndex: Integer;
l: Integer;
r: Integer;
m: Integer;
cmp: Integer;
StartIndex: Integer;
EndIndex: Integer;
NewIndex: Integer;
begin
if FilterMsgTypeCount=1 then exit;
OldIndex:=Item.FIndex;
if (OldIndex>0) and (CompareFilterMsgType(Item,fFilterMsgTypes[OldIndex-1])<0)
then begin
StartIndex:=0;
EndIndex:=OldIndex-1;
end else if (OldIndex<FilterMsgTypeCount-1)
and (CompareFilterMsgType(Item,fFilterMsgTypes[OldIndex+1])>0) then begin
StartIndex:=OldIndex+1;
EndIndex:=FilterMsgTypeCount-1;
end else
exit;
l:=StartIndex;
r:=EndIndex;
m:=0;
cmp:=0;
while l<=r do begin
m:=(l+r) div 2;
cmp:=CompareFilterMsgType(Item,fFilterMsgTypes[m]);
if cmp<0 then
r:=m-1
else if cmp>0 then
l:=m+1
else
break;
end;
if cmp<=0 then
NewIndex:=m
else
NewIndex:=m+1;
if OldIndex<NewIndex then begin
system.Move(fFilterMsgTypes[OldIndex+1],fFilterMsgTypes[OldIndex],
SizeOf(TLMVFilterMsgType)*(NewIndex-OldIndex));
end else if OldIndex>NewIndex then begin
system.Move(fFilterMsgTypes[NewIndex],fFilterMsgTypes[NewIndex+1],
SizeOf(TLMVFilterMsgType)*(OldIndex-NewIndex));
end else
exit;
fFilterMsgTypes[NewIndex]:=Item;
{$IFDEF CheckExtTools}
ConsistencyCheck;
{$ENDIF}
end;
constructor TLMsgViewFilter.Create;
begin
FMinUrgency:=mluHint;
FFilterNotesWithoutPos:=true;
end;
destructor TLMsgViewFilter.Destroy;
begin
ClearFilterMsgTypes;
inherited Destroy;
end;
procedure TLMsgViewFilter.Clear;
begin
MinUrgency:=mluHint;
FilterNotesWithoutPos:=true;
ClearFilterMsgTypes;
end;
procedure TLMsgViewFilter.SetToFitsAll;
begin
MinUrgency:=mluNone;
FilterNotesWithoutPos:=false;
ClearFilterMsgTypes;
end;
function TLMsgViewFilter.IsEqual(Src: TLMsgViewFilter): boolean;
var
i: Integer;
begin
Result:=false;
if Self=Src then exit(true);
if (MinUrgency<>Src.MinUrgency)
or (FilterNotesWithoutPos<>Src.FilterNotesWithoutPos)
or (FilterMsgTypeCount<>Src.FilterMsgTypeCount)
then exit;
for i:=0 to FilterMsgTypeCount-1 do
if not FilterMsgTypes[i].IsEqual(Src.FilterMsgTypes[i]) then exit;
Result:=true;
end;
procedure TLMsgViewFilter.Assign(Src: TLMsgViewFilter);
var
NewCnt: Integer;
OldCnt: Integer;
i: Integer;
begin
if IsEqual(Src) then exit;
fMinUrgency:=Src.MinUrgency;
FFilterNotesWithoutPos:=Src.FilterNotesWithoutPos;
// filter msg type
NewCnt:=Src.FilterMsgTypeCount;
OldCnt:=FilterMsgTypeCount;
for i:=NewCnt to OldCnt-1 do
FreeAndNil(fFilterMsgTypes[i]);
SetLength(fFilterMsgTypes,NewCnt);
for i:=0 to NewCnt-1 do begin
if fFilterMsgTypes[i]=nil then
fFilterMsgTypes[i]:=TLMVFilterMsgType.Create(Self);
fFilterMsgTypes[i].InternalAssign(Src.FilterMsgTypes[i]);
end;
Changed;
end;
function TLMsgViewFilter.LineFits(Line: TMessageLine): boolean;
begin
Result:=false;
if ord(Line.Urgency)<ord(MinUrgency) then exit;
if [mlfHiddenByIDEDirective,mlfFixed]*Line.Flags<>[] then exit;
if FilterNotesWithoutPos and (Line.Urgency<=mluNote)
and ((Line.Filename='') or (Line.Line<1)) then exit;
if IndexOfFilterMsgType(Line)>=0 then exit;
Result:=true;
end;
function TLMsgViewFilter.AddFilterMsgType(SubTool: string;
MsgID: integer): TLMVFilterMsgType;
var
i: Integer;
begin
i:=length(fFilterMsgTypes);
SetLength(fFilterMsgTypes,i+1);
Result:=TLMVFilterMsgType.Create(Self);
fFilterMsgTypes[i]:=Result;
Result.FSubTool:=SubTool;
Result.FMsgID:=MsgID;
UpdateFilterMsgTypeIndex(Result);
Changed;
end;
procedure TLMsgViewFilter.DeleteFilterMsgType(Index: integer);
begin
if (Index<0) or (Index>=FilterMsgTypeCount) then
raise Exception.Create('');
fFilterMsgTypes[Index].Free;
if Index<FilterMsgTypeCount-1 then
system.Move(fFilterMsgTypes[Index+1],fFilterMsgTypes[Index],
SizeOf(TLMVFilterMsgType)*(FilterMsgTypeCount-Index-1));
SetLength(fFilterMsgTypes,length(fFilterMsgTypes)-1);
Changed;
end;
procedure TLMsgViewFilter.ClearFilterMsgTypes;
var
i: Integer;
begin
if FilterMsgTypeCount=0 then exit;
for i:=0 to FilterMsgTypeCount-1 do
fFilterMsgTypes[i].Free;
SetLength(fFilterMsgTypes,0);
Changed;
end;
function TLMsgViewFilter.IndexOfFilterMsgType(Line: TMessageLine): integer;
var
l: Integer;
r: Integer;
m: Integer;
cmp: Integer;
begin
l:=0;
r:=FilterMsgTypeCount-1;
while l<=r do begin
m:=(l+r) div 2;
cmp:=CompareLineAndFilterMsgType(Line,fFilterMsgTypes[m]);
if cmp<0 then
r:=m-1
else if cmp>0 then
l:=m+1
else
exit(m);
end;
Result:=-1;
end;
procedure TLMsgViewFilter.ConsistencyCheck;
procedure E(Msg: string);
begin
raise Exception.Create(Msg);
end;
var
i: Integer;
begin
for i:=0 to FilterMsgTypeCount-2 do begin
if CompareFilterMsgType(fFilterMsgTypes[i],fFilterMsgTypes[i+1])>0 then
E(IntToStr(i));
end;
end;
initialization initialization
DefaultConfigClass:=TXMLOptionsStorage; DefaultConfigClass:=TXMLOptionsStorage;
GetIDEConfigStorage:=@GetLazIDEConfigStorage; GetIDEConfigStorage:=@GetLazIDEConfigStorage;