1 {
2  ***************************************************************************
3  *                                                                         *
4  *   This source is free software; you can redistribute it and/or modify   *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This code is distributed in the hope that it will be useful, but      *
10  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
12  *   General Public License for more details.                              *
13  *                                                                         *
14  *   A copy of the GNU General Public License is available on the World    *
15  *   Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also      *
16  *   obtain it by writing to the Free Software Foundation,                 *
17  *   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.   *
18  *                                                                         *
19  ***************************************************************************
20 
21  Author: Mattias Gaertner
22 
23  Abstract:
24    IDE dialog showing stats about the IDE.
25 }
26 unit IDEInfoDlg;
27 
28 {$mode objfpc}{$H+}
29 
30 interface
31 
32 uses
33   Classes, SysUtils, LazFileUtils, LazUTF8,
34   CodeToolManager, DefineTemplates, LinkScanner,
35   Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
36   LCLProc, ButtonPanel, LazHelpHTML, LazHelpIntf,
37   IDEHelpIntf, IDEWindowIntf, LazIDEIntf, IDEExternToolIntf,
38   EnvironmentOpts, AboutFrm, LazConf, LazarusIDEStrConsts, Project,
39   SourceEditor, InitialSetupProc, PackageSystem, PackageDefs;
40 
41 type
42 
43   { TIDEInfoDialog }
44 
45   TIDEInfoDialog = class(TForm)
46     ButtonPanel1: TButtonPanel;
47     ExtToolMemo: TMemo;
48     GeneralMemo: TMemo;
49     HelpMemo: TMemo;
50     ModifiedMemo: TMemo;
51     PageControl1: TPageControl;
52     GeneralTabSheet: TTabSheet;
53     ModifiedTabSheet: TTabSheet;
54     HelpTabSheet: TTabSheet;
55     ExtToolTabSheet: TTabSheet;
56     procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
57     procedure FormCreate(Sender: TObject);
58   private
59     // general
60     procedure GatherIDEVersion(sl: TStrings);
61     procedure GatherParameters(sl: TStrings);
62     procedure GatherEnvironmentVars(sl: TStrings);
63     procedure GatherGlobalOptions(sl: TStrings);
64     // modified
65     procedure GatherModifiedProject(AProject: TProject; sl: TStrings);
66     procedure GatherModifiedPackages(sl: TStrings);
67     procedure GatherModifiedSourceEditor(sl: TStrings);
68     // help
69     procedure GatherHelpDatabases(sl: TStrings);
70     procedure GatherHelpViewers(sl: TStrings);
71     procedure GatherHelpDB(Prefix: string; const HelpDB: THelpDatabase; const sl: TStrings);
72     procedure GatherHelpViewer(Prefix: string; const Viewer: THelpViewer; const sl: TStrings);
73     // external tools
74     procedure GatherExternalTools(sl: TStrings);
75   public
76     procedure UpdateGeneralMemo;
77     procedure UpdateModifiedMemo;
78     procedure UpdateHelpMemo;
79     procedure UpdateExternalTools;
80   end;
81 
82 var
83   IDEInfoDialog: TIDEInfoDialog;
84 
ShowIDEInfonull85 function ShowIDEInfo: TModalResult;
86 
87 
88 implementation
89 
ShowIDEInfonull90 function ShowIDEInfo: TModalResult;
91 var
92   Dlg: TIDEInfoDialog;
93 begin
94   Dlg:=TIDEInfoDialog.Create(nil);
95   try
96     Result:=Dlg.ShowModal;
97   finally
98     Dlg.Free;
99   end;
100 end;
101 
102 {$R *.lfm}
103 
104 { TIDEInfoDialog }
105 
106 procedure TIDEInfoDialog.FormCreate(Sender: TObject);
107 begin
108   Caption:=lisIDEInfoInformationAboutTheIDE;
109 
110   UpdateGeneralMemo;
111   UpdateModifiedMemo;
112   UpdateHelpMemo;
113   UpdateExternalTools;
114   PageControl1.PageIndex:=0;
115   IDEDialogLayoutList.ApplyLayout(Self);
116 end;
117 
118 procedure TIDEInfoDialog.FormClose(Sender: TObject;
119   var CloseAction: TCloseAction);
120 begin
121   IDEDialogLayoutList.SaveLayout(Self);
122 end;
123 
124 procedure TIDEInfoDialog.GatherHelpDB(Prefix: string;
125   const HelpDB: THelpDatabase; const sl: TStrings);
126 var
127   DBIRegExprMessage: THelpDBIRegExprMessage;
128   DBISourceDirectories: THelpDBISourceDirectories;
129   DBISourceDirectory: THelpDBISourceDirectory;
130   DBISourceFile: THelpDBISourceFile;
131   DBItem: THelpDBItem;
132   i: Integer;
133   HTMLHelp: THTMLHelpDatabase;
134 begin
135   sl.Add(Prefix+DbgSName(HelpDB));
136   sl.Add(Prefix+'ID='+HelpDB.ID);
137   sl.Add(Prefix+'LocalizedName='+dbgstr(HelpDB.GetLocalizedName));
138   if HelpDB.BasePathObject<>nil then
139     sl.Add(Prefix+'BasePathObject='+DbgSName(HelpDB.BasePathObject));
140   sl.Add(Prefix+'Registered='+dbgs(HelpDB.Registered));
141   if HelpDB.SupportedMimeTypes<>nil then begin
142     sl.Add(Prefix+'SupportedMimeTypes: '+IntToStr(HelpDB.SupportedMimeTypes.Count));
143     for i:=0 to HelpDB.SupportedMimeTypes.Count-1 do
144       sl.Add(Prefix+'  '+HelpDB.SupportedMimeTypes[i]);
145   end;
146   if HelpDB is THTMLHelpDatabase then begin
147     HTMLHelp:=THTMLHelpDatabase(HelpDB);
148     sl.Add(Prefix+'BaseURL='+dbgstr(HTMLHelp.BaseURL));
149     if HTMLHelp.BaseURL='' then
150       sl.Add(Prefix+'DefaultBaseURL='+dbgstr(HTMLHelp.DefaultBaseURL));
151     sl.Add(Prefix+'KeywordPrefix='+dbgstr(HTMLHelp.KeywordPrefix));
152   end;
153 
154   // registered items
155   sl.Add(Prefix+'Items:');
156   for i:=0 to HelpDB.RegisteredItemCount-1 do begin
157     DBItem:=HelpDB.GetRegisteredItem(i);
158     sl.Add(Prefix+'  '+IntToStr(i+1)+'/'+IntToStr(HelpDB.RegisteredItemCount)+': '+DbgSName(
159       DBItem));
160     if DBItem is THelpDBISourceFile then begin
161       DBISourceFile:=THelpDBISourceFile(DBItem);
162       sl.Add(Prefix+'    Filename='+DBISourceFile.Filename);
163       sl.Add(Prefix+'    FullFilename='+DBISourceFile.GetFullFilename);
164       sl.Add(Prefix+'    BasePath='+DBISourceFile.GetBasePath);
165       if DBISourceFile is THelpDBISourceDirectory then begin
166         DBISourceDirectory:=THelpDBISourceDirectory(DBISourceFile);
167         sl.Add(Prefix+'    FileMask='+DBISourceDirectory.FileMask);
168         sl.Add(Prefix+'    WithSubDirectories='+dbgs(DBISourceDirectory.
169           WithSubDirectories));
170         if DBISourceDirectory is THelpDBISourceDirectories then begin
171           DBISourceDirectories:=THelpDBISourceDirectories(DBISourceDirectory);
172           sl.Add(Prefix+'    BaseDirectory='+DBISourceDirectories.BaseDirectory);
173         end;
174       end;
175     end else if DBItem is THelpDBIClass then begin
176       sl.Add(Prefix+'    Class='+DbgSName(THelpDBIClass(DBItem)));
177     end else if DBItem is THelpDBIRegExprMessage then begin
178       DBIRegExprMessage:=THelpDBIRegExprMessage(DBItem);
179       sl.Add(Prefix+'    Expression='+DBIRegExprMessage.Expression);
180       sl.Add(Prefix+'    ModifierStr='+DBIRegExprMessage.ModifierStr);
181     end;
182   end;
183   sl.Add('');
184 end;
185 
186 procedure TIDEInfoDialog.GatherHelpViewer(Prefix: string;
187   const Viewer: THelpViewer; const sl: TStrings);
188 var
189   i: Integer;
190 begin
191   sl.Add(Prefix+DbgSName(Viewer));
192   sl.Add(Prefix+'StorageName='+Viewer.StorageName);
193   sl.Add(Prefix+'ParameterHelp='+Viewer.ParameterHelp);
194   sl.Add(Prefix+'LocalizedName='+dbgstr(Viewer.GetLocalizedName));
195   if Viewer.SupportedMimeTypes<>nil then begin
196     sl.Add(Prefix+'SupportedMimeTypes: '+IntToStr(Viewer.SupportedMimeTypes.Count));
197     for i:=0 to Viewer.SupportedMimeTypes.Count-1 do
198       sl.Add(Prefix+'  '+Viewer.SupportedMimeTypes[i]);
199   end;
200   sl.Add('');
201 end;
202 
203 procedure TIDEInfoDialog.GatherExternalTools(sl: TStrings);
204 var
205   i, j: Integer;
206   Tool: TAbstractExternalTool;
207   View: TExtToolView;
208   Parser: TExtToolParser;
209 begin
210   sl.Add('External Tools: '+IntToStr(ExternalToolList.Count));
211   for i:=0 to ExternalToolList.Count-1 do begin
212     Tool:=ExternalToolList[i];
213     sl.Add('Tool '+IntToStr(i)+'/'+IntToStr(ExternalToolList.Count)
214       +' ParserCount='+IntToStr(Tool.ParserCount)+' ViewCount='+IntToStr(Tool.ViewCount));
215     sl.Add('  Stage='+dbgs(Tool.Stage));
216     sl.Add('  Process.Active='+dbgs(Tool.Process.Active));
217     sl.Add('  Process.Executable='+AnsiQuotedStr(Tool.Process.Executable,'"'));
218     sl.Add('  Process.CurrentDirectory='+AnsiQuotedStr(Tool.Process.CurrentDirectory,'"'));
219     sl.Add('  Process.Running='+dbgs(Tool.Process.Running));
220     sl.Add('  CmdLineParams='+AnsiQuotedStr(Tool.CmdLineParams,'"'));
221     sl.Add('  ErrorMessage='+AnsiQuotedStr(Tool.ErrorMessage,'"'));
222     sl.Add('  ExitCode='+IntToStr(Tool.ExitCode));
223     sl.Add('  ExitStatus='+IntToStr(Tool.ExitStatus));
224     sl.Add('  Terminated='+dbgs(Tool.Terminated));
225     sl.Add('  ReadStdOutBeforeErr='+dbgs(Tool.ReadStdOutBeforeErr));
226     sl.Add('  WorkerDirectory='+AnsiQuotedStr(Tool.WorkerDirectory,'"'));
227 
228     for j:=0 to Tool.ViewCount-1 do begin
229       Parser:=Tool.Parsers[j];
230       sl.Add('   Parser '+IntToStr(j)+'/'+IntToStr(Tool.ParserCount)+' '+Parser.ClassName);
231     end;
232 
233     for j:=0 to Tool.ViewCount-1 do begin
234       View:=Tool.Views[j];
235       sl.Add('   View '+IntToStr(j)+'/'+IntToStr(Tool.ViewCount)+' '+AnsiQuotedStr(View.Caption,'"'));
236     end;
237     sl.Add('');
238   end;
239 end;
240 
241 procedure TIDEInfoDialog.GatherIDEVersion(sl: TStrings);
242 begin
243   sl.Add('Lazarus version: '+GetLazarusVersionString);
244   sl.Add('Lazarus revision: '+LazarusRevisionStr);
245   sl.Add('Lazarus build date: '+{$I %date%});
246   sl.Add('Lazarus was compiled for '+GetCompiledTargetCPU+'-'+GetCompiledTargetOS);
247   sl.Add('Lazarus was compiled with FPC '+{$I %FPCVERSION%});
248   sl.Add('');
249 end;
250 
251 procedure TIDEInfoDialog.GatherParameters(sl: TStrings);
252 var
253   i: Integer;
254 begin
255   sl.Add('Working directory='+GetCurrentDirUTF8);
256   sl.Add('Application.ExeName='+Application.ExeName);
257   sl.Add('');
258   sl.add('Parameters:');
259   for i:=0 to Paramcount do
260     sl.Add(ParamStrUTF8(i));
261   sl.Add('');
262 end;
263 
264 procedure TIDEInfoDialog.GatherEnvironmentVars(sl: TStrings);
265 var
266   i: Integer;
267   TempList: TStringListUTF8Fast;
268 begin
269   sl.Add('Environment variables:');
270   TempList:=TStringListUTF8Fast.Create;
271   for i:=0 to GetEnvironmentVariableCount-1 do
272     TempList.Add(GetEnvironmentStringUTF8(i));
273   TempList.Sort;
274   sl.AddStrings(TempList);
275   TempList.free;
276   sl.Add('');
277 end;
278 
279 procedure TIDEInfoDialog.GatherGlobalOptions(sl: TStrings);
280 var
281   CfgCache: TPCTargetConfigCache;
282   Note, aFilename: string;
283   CompilerKind: TPascalCompiler;
284 begin
285   sl.add('Global IDE options:');
286   sl.Add('Primary config directory='+GetPrimaryConfigPath);
287   sl.Add('Secondary config directory='+GetSecondaryConfigPath);
288 
289   sl.Add('LazarusDirectory='+EnvironmentOptions.LazarusDirectory);
290   sl.Add('Real LazarusDirectory='+EnvironmentOptions.GetParsedLazarusDirectory);
291   if CheckLazarusDirectoryQuality(EnvironmentOptions.GetParsedLazarusDirectory,Note)<>sddqCompatible
292   then
293     sl.Add('WARNING: '+Note);
294 
295   sl.Add('Default CompilerFilename='+EnvironmentOptions.CompilerFilename);
296   sl.Add('Real Default CompilerFilename='+EnvironmentOptions.GetParsedCompilerFilename);
297   if CheckFPCExeQuality(EnvironmentOptions.GetParsedCompilerFilename,Note,
298                        CodeToolBoss.CompilerDefinesCache.TestFilename)<>sddqCompatible
299   then
300     sl.Add('WARNING: '+Note);
301 
302   if Project1<>nil then begin
303     sl.Add('Project CompilerFilename='+Project1.CompilerOptions.CompilerPath);
304     aFilename:=LazarusIDE.GetCompilerFilename;
305     sl.Add('Real Project CompilerFilename='+aFilename);
306     IsCompilerExecutable(aFilename,Note,CompilerKind,true);
307     if CompilerKind=pcPas2js then begin
308       if CheckPas2jsQuality(aFilename,Note,
309                            CodeToolBoss.CompilerDefinesCache.TestFilename)<>sddqCompatible
310       then
311         sl.Add('WARNING: '+Note);
312     end else begin
313       if CheckFPCExeQuality(aFilename,Note,
314                            CodeToolBoss.CompilerDefinesCache.TestFilename)<>sddqCompatible
315       then
316         sl.Add('WARNING: '+Note);
317     end;
318   end;
319 
320   sl.Add('CompilerMessagesFilename='+EnvironmentOptions.CompilerMessagesFilename);
321   sl.Add('Real CompilerMessagesFilename='+EnvironmentOptions.GetParsedCompilerMessagesFilename);
322 
323   sl.Add('FPC source directory='+EnvironmentOptions.FPCSourceDirectory);
324   sl.Add('Real FPC source directory='+EnvironmentOptions.GetParsedFPCSourceDirectory);
325   CfgCache:=CodeToolBoss.CompilerDefinesCache.ConfigCaches.Find(
326     LazarusIDE.GetFPCompilerFilename,'','','',true);
327   if CheckFPCSrcDirQuality(EnvironmentOptions.GetParsedFPCSourceDirectory,Note,
328     CfgCache.GetFPCVer)<>sddqCompatible
329   then
330     sl.Add('WARNING: '+Note);
331 
332   sl.Add('Test directory='+EnvironmentOptions.TestBuildDirectory);
333   sl.Add('Real Test directory='+EnvironmentOptions.GetParsedTestBuildDirectory);
334   sl.Add('');
335 end;
336 
337 procedure TIDEInfoDialog.GatherModifiedProject(AProject: TProject; sl: TStrings);
338 var
339   aFile: TUnitInfo;
340   HeaderWritten: Boolean;
341   s: String;
342   i: Integer;
343 begin
344   // summary
345   if AProject.Modified then
346     sl.Add('Project.Modified');
347   if AProject.SessionModified then
348     sl.Add('Project.SessionModified');
349   if Project1.SomethingModified(true,false) then
350     sl.Add('Project.SomethingModified Data');
351   if Project1.SomethingModified(false,true) then
352     sl.Add('Project.SomethingModified Session');
353   if SourceEditorManager.SomethingModified(false) then
354     sl.Add('SourceEditorManager.SomethingModified');
355   if AProject.BuildModes.IsModified(false) then
356     sl.Add('Project.BuildModes.IsModified data');
357   if AProject.BuildModes.SharedMatrixOptions.Modified then
358     sl.Add('Project.BuildModes.SharedMatrixOptions.Modified');
359   if AProject.BuildModes.IsModified(true) then
360     sl.Add('Project.BuildModes.IsModified session');
361   if AProject.BuildModes.SessionMatrixOptions.Modified then
362     sl.Add('Project.BuildModes.SessionMatrixOptions.Modified');
363   for i:=0 to AProject.BuildModes.Count-1 do
364     if AProject.BuildModes[i].Modified then
365       sl.Add('Project.BuildModes['+dbgs(i)+'].Name='+AProject.BuildModes[i].Name+' InSession='+dbgs(AProject.BuildModes[i].InSession));
366   sl.Add('');
367 
368   // details
369   HeaderWritten:=false;
370   aFile:=AProject.FirstPartOfProject;
371   while aFile<>nil do begin
372     if aFile.Modified or aFile.SessionModified
373     or ((aFile.Source<>nil) and aFile.Source.Modified)
374     then begin
375       if not HeaderWritten then begin
376         sl.Add('Project units:');
377         HeaderWritten:=true;
378       end;
379       s:=aFile.GetShortFilename(true);
380       if aFile.Modified then
381         s:=s+' Modified';
382       if aFile.SessionModified then
383         s:=s+' SessionModified';
384       if (aFile.Source<>nil) and (aFile.Source.Modified) then
385         s:=s+' Source.Modified';
386       sl.Add(s);
387     end;
388     aFile:=aFile.NextPartOfProject;
389   end;
390   if HeaderWritten then
391     sl.Add('');
392 end;
393 
394 procedure TIDEInfoDialog.GatherModifiedPackages(sl: TStrings);
395 var
396   i: Integer;
397   Pkg: TLazPackage;
398   HeaderWritten: Boolean;
399 begin
400   HeaderWritten:=false;
401   for i:=0 to PackageGraph.Count-1 do begin
402     Pkg:=PackageGraph[i];
403     if Pkg.Modified then begin
404       if not HeaderWritten then begin
405         HeaderWritten:=true;
406         sl.Add('Packages:');
407       end;
408       sl.Add(Pkg.Name);
409     end;
410   end;
411   if HeaderWritten then
412     sl.Add('');
413 end;
414 
415 procedure TIDEInfoDialog.GatherModifiedSourceEditor(sl: TStrings);
416 var
417   HeaderWritten: Boolean;
418   i: Integer;
419   SrcEdit: TSourceEditor;
420 begin
421   HeaderWritten:=false;
422   if SourceEditorManager.SomethingModified(false) then begin
423     sl.Add('Source Editor:');
424     for i:=0 to SourceEditorManager.SourceEditorCount-1 do
425     begin
426       SrcEdit:=SourceEditorManager.SourceEditors[i];
427       if not SrcEdit.Modified then continue;
428       sl.Add('  '+SrcEdit.Filename+' Component='+dbgs(SrcEdit.EditorComponent.Modified));
429     end;
430   end;
431   if HeaderWritten then
432     sl.Add('');
433 end;
434 
435 procedure TIDEInfoDialog.GatherHelpDatabases(sl: TStrings);
436 var
437   i: Integer;
438 begin
439   sl.Add('LazarusHelp='+DbgSName(LazarusHelp));
440   sl.Add('HelpDatabases='+DbgSName(HelpDatabases));
441   for i:=0 to HelpDatabases.Count-1 do begin
442     sl.Add('DB '+IntToStr(i+1)+'/'+IntToStr(HelpDatabases.Count));
443     GatherHelpDB('  ',HelpDatabases.Items[i],sl);
444   end;
445 end;
446 
447 procedure TIDEInfoDialog.GatherHelpViewers(sl: TStrings);
448 var
449   i: Integer;
450 begin
451   sl.Add('HelpViewers='+DbgSName(HelpViewers));
452   for i:=0 to HelpViewers.Count-1 do begin
453     sl.Add('DB '+IntToStr(i+1)+'/'+IntToStr(HelpViewers.Count));
454     GatherHelpViewer('  ',HelpViewers.Items[i],sl);
455   end;
456 end;
457 
458 procedure TIDEInfoDialog.UpdateGeneralMemo;
459 var
460   sl: TStringList;
461 begin
462   sl:=TStringList.Create;
463   try
464     GatherIDEVersion(sl);
465     GatherGlobalOptions(sl);
466     GatherParameters(sl);
467     GatherEnvironmentVars(sl);
468     GeneralMemo.Lines.Assign(sl);
469   finally
470     sl.Free;
471   end;
472 end;
473 
474 procedure TIDEInfoDialog.UpdateModifiedMemo;
475 var
476   sl: TStringList;
477 begin
478   sl:=TStringList.Create;
479   try
480     GatherModifiedProject(Project1,sl);
481     GatherModifiedPackages(sl);
482     GatherModifiedSourceEditor(sl);
483     ModifiedMemo.Lines.Assign(sl);
484   finally
485     sl.Free;
486   end;
487 end;
488 
489 procedure TIDEInfoDialog.UpdateHelpMemo;
490 var
491   sl: TStringList;
492 begin
493   sl:=TStringList.Create;
494   try
495     GatherHelpDatabases(sl);
496     GatherHelpViewers(sl);
497     HelpMemo.Lines.Assign(sl);
498   finally
499     sl.Free;
500   end;
501 end;
502 
503 procedure TIDEInfoDialog.UpdateExternalTools;
504 var
505   sl: TStringList;
506 begin
507   sl:=TStringList.Create;
508   try
509     GatherExternalTools(sl);
510     ExtToolMemo.Lines.Assign(sl);
511   finally
512     sl.Free;
513   end;
514 end;
515 
516 end.
517 
518