/ide/initialsetupdlgs.pas

http://github.com/graemeg/lazarus · Pascal · 1333 lines · 1099 code · 125 blank · 109 comment · 144 complexity · a4a8e2c55d6bee42d9c3583263315442 MD5 · raw file

  1. {
  2. /***************************************************************************
  3. initialsetupdlgs.pas
  4. --------------------
  5. Contains the dialogs to help users setup basic settings.
  6. ***************************************************************************/
  7. ***************************************************************************
  8. * *
  9. * This source is free software; you can redistribute it and/or modify *
  10. * it under the terms of the GNU General Public License as published by *
  11. * the Free Software Foundation; either version 2 of the License, or *
  12. * (at your option) any later version. *
  13. * *
  14. * This code is distributed in the hope that it will be useful, but *
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of *
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
  17. * General Public License for more details. *
  18. * *
  19. * A copy of the GNU General Public License is available on the World *
  20. * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
  21. * obtain it by writing to the Free Software Foundation, *
  22. * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  23. * *
  24. ***************************************************************************
  25. Author: Mattias Gaertner
  26. Abstract:
  27. Contains the dialogs to help users setup basic settings.
  28. }
  29. unit InitialSetupDlgs;
  30. {$mode objfpc}{$H+}
  31. {off $DEFINE VerboseFPCSrcScanThead}
  32. interface
  33. uses
  34. // RTL + FCL + LCL
  35. Classes, SysUtils,
  36. Forms, Controls, Buttons, Dialogs, Graphics, ComCtrls, ExtCtrls, StdCtrls, LCLProc,
  37. // CodeTools
  38. FileProcs, CodeToolManager, DefineTemplates,
  39. // LazUtils
  40. FileUtil, LazUTF8, LazUTF8Classes, LazFileUtils, LazFileCache, LazLogger,
  41. // Other
  42. MacroDefIntf, GDBMIDebugger, DbgIntfDebuggerBase,
  43. TransferMacros, LazarusIDEStrConsts, LazConf, EnvironmentOpts,
  44. AboutFrm, IDETranslations, BaseBuildManager, InitialSetupProc;
  45. type
  46. TInitialSetupDialog = class;
  47. { TSearchFpcSourceThread }
  48. TSearchFpcSourceThread = class(TThread)
  49. private
  50. fSetupDialog: TInitialSetupDialog;
  51. fFPCVer: string;
  52. fFoundFPCSrc: TSDFileInfo;
  53. {$IFDEF VerboseFPCSrcScanThead}
  54. fPath: string;
  55. fFileInfo: TSearchRec;
  56. procedure Debug;
  57. {$ENDIF}
  58. function CheckFPCSrcDir(Dir: string): TSDFileInfo;
  59. procedure DoSearch(const APath: String);
  60. procedure UpdateFPCSrcDir;
  61. procedure Finishing;
  62. protected
  63. procedure Execute; override;
  64. public
  65. constructor Create(aSetupDialog: TInitialSetupDialog);
  66. destructor Destroy; override;
  67. end;
  68. { TInitialSetupDialog }
  69. TInitialSetupDialog = class(TForm)
  70. BtnPanel: TPanel;
  71. CompilerBrowseButton: TButton;
  72. CompilerComboBox: TComboBox;
  73. CompilerLabel: TLabel;
  74. CompilerMemo: TMemo;
  75. CompilerTabSheet: TTabSheet;
  76. DebuggerBrowseButton: TButton;
  77. DebuggerComboBox: TComboBox;
  78. DebuggerLabel: TLabel;
  79. DebuggerMemo: TMemo;
  80. DebuggerTabSheet: TTabSheet;
  81. FPCSourcesTabSheet: TTabSheet;
  82. FPCSrcDirBrowseButton: TButton;
  83. FPCSrcDirComboBox: TComboBox;
  84. FPCSrcDirLabel: TLabel;
  85. FPCSrcDirMemo: TMemo;
  86. ImageList1: TImageList;
  87. LazarusTabSheet: TTabSheet;
  88. LazDirBrowseButton: TButton;
  89. LazDirComboBox: TComboBox;
  90. LazDirLabel: TLabel;
  91. LazDirMemo: TMemo;
  92. MakeExeBrowseButton: TButton;
  93. MakeExeComboBox: TComboBox;
  94. MakeExeLabel: TLabel;
  95. MakeExeMemo: TMemo;
  96. MakeExeTabSheet: TTabSheet;
  97. PropertiesPageControl: TPageControl;
  98. PropertiesTreeView: TTreeView;
  99. ScanLabel: TLabel;
  100. ScanProgressBar: TProgressBar;
  101. Splitter1: TSplitter;
  102. StartIDEBitBtn: TBitBtn;
  103. StopScanButton: TBitBtn;
  104. WelcomePaintBox: TPaintBox;
  105. procedure CompilerBrowseButtonClick(Sender: TObject);
  106. procedure CompilerComboBoxChange(Sender: TObject);
  107. procedure DebuggerBrowseButtonClick(Sender: TObject);
  108. procedure DebuggerComboBoxChange(Sender: TObject);
  109. procedure FormCreate(Sender: TObject);
  110. procedure FormDestroy(Sender: TObject);
  111. procedure FPCSrcDirBrowseButtonClick(Sender: TObject);
  112. procedure FPCSrcDirComboBoxChange(Sender: TObject);
  113. procedure LazDirBrowseButtonClick(Sender: TObject);
  114. procedure LazDirComboBoxChange(Sender: TObject);
  115. procedure MakeExeBrowseButtonClick(Sender: TObject);
  116. procedure MakeExeComboBoxChange(Sender: TObject);
  117. procedure OnAppActivate(Sender: TObject);
  118. procedure PropertiesPageControlChange(Sender: TObject);
  119. procedure PropertiesTreeViewSelectionChanged(Sender: TObject);
  120. procedure StartIDEBitBtnClick(Sender: TObject);
  121. procedure StopScanButtonClick(Sender: TObject);
  122. procedure WelcomePaintBoxPaint(Sender: TObject);
  123. procedure OnIdle(Sender: TObject; var {%H-}Done: Boolean);
  124. private
  125. FFlags: TSDFlags;
  126. FLastParsedLazDir: string;
  127. fLastParsedCompiler: string;
  128. fLastParsedFPCSrcDir: string;
  129. fLastParsedMakeExe: string;
  130. fLastParsedDebugger: string;
  131. FIdleConnected: boolean;
  132. ImgIDError: LongInt;
  133. ImgIDWarning: LongInt;
  134. FHeadGraphic: TPortableNetworkGraphic;
  135. FInitialDebuggerFileName: String;
  136. FSelectingPage: boolean;
  137. FCandidates: array[TSDFilenameType] of TSDFileInfoList; // list of TSDFileInfo
  138. fSearchFpcSourceThread: TSearchFpcSourceThread;
  139. procedure UpdateCaptions;
  140. procedure SelectPage(const NodeText: string);
  141. function SelectDirectory(aTitle: string): string;
  142. procedure StartFPCSrcThread;
  143. procedure UpdateLazarusDirCandidates;
  144. procedure UpdateCompilerFilenameCandidates;
  145. procedure UpdateFPCSrcDirCandidates;
  146. procedure UpdateFPCSrcDirCandidate(aFPCSrcDirInfo: TSDFileInfo);
  147. procedure UpdateMakeExeCandidates;
  148. procedure UpdateDebuggerCandidates;
  149. procedure FillComboboxWithFileInfoList(ABox: TComboBox; List: TSDFileInfoList;
  150. ItemIndex: integer = 0);
  151. procedure SetIdleConnected(const AValue: boolean);
  152. procedure UpdateLazDirNote;
  153. procedure UpdateCompilerNote;
  154. procedure UpdateFPCSrcDirNote;
  155. procedure UpdateMakeExeNote;
  156. procedure UpdateDebuggerNote;
  157. function FirstErrorNode: TTreeNode;
  158. function GetFPCVer: string;
  159. function GetFirstCandidate(Candidates: TSDFileInfoList;
  160. MinQuality: TSDFilenameQuality = sddqCompatible): TSDFileInfo;
  161. function QualityToImgIndex(Quality: TSDFilenameQuality): integer;
  162. procedure ShowHideScanControls(aShow: Boolean);
  163. procedure ThreadTerminated(Sender: TObject); // called in main thread by fSearchFpcSourceThread.OnTerminate
  164. procedure TranslateResourceStrings;
  165. public
  166. TVNodeLazarus: TTreeNode;
  167. TVNodeCompiler: TTreeNode;
  168. TVNodeFPCSources: TTreeNode;
  169. TVNodeMakeExe: TTreeNode;
  170. TVNodeDebugger: TTreeNode;
  171. procedure Init; //Check for config errors, find and show alternatives
  172. property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
  173. end;
  174. function ShowInitialSetupDialog: TModalResult;
  175. // Debugger
  176. // Checks a given file to see if it is a valid debugger (only gdb supported for now)
  177. function CheckDebuggerQuality(AFilename: string; out Note: string): TSDFilenameQuality;
  178. // Search debugger candidates and add them to list, including quality level
  179. function SearchDebuggerCandidates(StopIfFits: boolean): TSDFileInfoList;
  180. implementation
  181. const
  182. DefaultDebuggerClass: TDebuggerClass = TGDBMIDebugger;
  183. type
  184. { TSetupMacros }
  185. TSetupMacros = class(TTransferMacroList)
  186. protected
  187. procedure DoSubstitution({%H-}TheMacro: TTransferMacro; const MacroName: string;
  188. var s: string; const {%H-}Data: PtrInt; var Handled, {%H-}Abort: boolean;
  189. {%H-}Depth: integer); override;
  190. public
  191. FPCVer: string;
  192. LazarusDir: string;
  193. end;
  194. function CheckDebuggerQuality(AFilename: string; out Note: string): TSDFilenameQuality;
  195. begin
  196. Result:=sddqInvalid;
  197. AFilename:=TrimFilename(AFilename);
  198. if not FileExistsCached(AFilename) then
  199. begin
  200. Note:=lisFileNotFound4;
  201. exit;
  202. end;
  203. if DirPathExistsCached(AFilename) then
  204. begin
  205. Note:=lisFileIsDirectory;
  206. exit;
  207. end;
  208. if not FileIsExecutableCached(AFilename) then
  209. begin
  210. Note:=lisFileIsNotAnExecutable;
  211. exit;
  212. end;
  213. { We could call gdb and parse the output looking for something like
  214. GNU gdb, but that may be going too far. }
  215. Note:=lisOk;
  216. Result:=sddqCompatible;
  217. end;
  218. function SearchDebuggerCandidates(StopIfFits: boolean): TSDFileInfoList;
  219. function CheckFile(AFilename: string; var List: TSDFileInfoList): boolean;
  220. var
  221. Item: TSDFileInfo;
  222. RealFilename: String;
  223. begin
  224. Result:=false;
  225. if AFilename='' then exit;
  226. ForcePathDelims(AFilename);
  227. // check if already checked
  228. if Assigned(List) and List.CaptionExists(AFilename) then exit;
  229. EnvironmentOptions.DebuggerFilename:=AFilename;
  230. RealFilename:=EnvironmentOptions.GetParsedDebuggerFilename;
  231. debugln(['SearchDebuggerCandidates Value=',AFilename,' File=',RealFilename]);
  232. if RealFilename='' then exit;
  233. // check if exists
  234. if not FileExistsCached(RealFilename) then exit;
  235. // add to list and check quality
  236. if List=nil then
  237. List:=TSDFileInfoList.create(true);
  238. Item:=List.AddNewItem(RealFilename, AFilename);
  239. Item.Quality:=CheckDebuggerQuality(RealFilename, Item.Note);
  240. Result:=(Item.Quality=sddqCompatible) and StopIfFits;
  241. end;
  242. const
  243. DebuggerFileName='gdb'; //For Windows, .exe will be appended
  244. var
  245. OldDebuggerFilename: String;
  246. s, AFilename: String;
  247. Files: TStringList;
  248. i: Integer;
  249. begin
  250. Result:=nil;
  251. OldDebuggerFilename:=EnvironmentOptions.DebuggerFilename;
  252. try
  253. // check current setting
  254. if CheckFile(EnvironmentOptions.DebuggerFilename,Result) then exit;
  255. // check the primary options
  256. AFilename:=GetValueFromPrimaryConfig(EnvOptsConfFileName,
  257. 'EnvironmentOptions/DebuggerFilename/Value');
  258. if CheckFile(AFilename,Result) then exit;
  259. // check the secondary options
  260. AFilename:=GetValueFromSecondaryConfig(EnvOptsConfFileName,
  261. 'EnvironmentOptions/DebuggerFilename/Value');
  262. if CheckFile(AFilename,Result) then exit;
  263. // Check locations proposed by debugger class
  264. s := DefaultDebuggerClass.ExePaths;
  265. while s <> '' do begin
  266. AFilename := GetPart([], [';'], s);
  267. if CheckFile(AFilename, Result) then exit;
  268. if s <> '' then delete(s, 1, 1);
  269. end;
  270. // Windows-only locations:
  271. if (GetDefaultSrcOSForTargetOS(GetCompiledTargetOS)='win') then begin
  272. // check for debugger in fpc.exe directory - could be a lucky shot
  273. if CheckFile(SetDirSeparators('$Path($(CompPath))/'+DebuggerFileName+GetExecutableExt),Result)
  274. then exit;
  275. end;
  276. // check history
  277. Files:=EnvironmentOptions.DebuggerFileHistory;
  278. if Files<>nil then
  279. for i:=0 to Files.Count-1 do
  280. if CheckFile(Files[i],Result) then exit;
  281. // check PATH
  282. AFilename:=DebuggerFileName+GetExecutableExt;
  283. if CheckFile(AFilename,Result) then exit;
  284. // There are no common directories apart from the PATH
  285. // where gdb would be installed. Otherwise we could do something similar as
  286. // in SearchMakeExeCandidates.
  287. finally
  288. EnvironmentOptions.DebuggerFilename:=OldDebuggerFilename;
  289. end;
  290. end;
  291. function ShowInitialSetupDialog: TModalResult;
  292. var
  293. InitialSetupDialog: TInitialSetupDialog;
  294. begin
  295. InitialSetupDialog:=TInitialSetupDialog.Create(nil);
  296. try
  297. Application.TaskBarBehavior:=tbMultiButton;
  298. InitialSetupDialog.Init;
  299. Result:=InitialSetupDialog.ShowModal;
  300. finally
  301. InitialSetupDialog.Free;
  302. Application.TaskBarBehavior:=tbDefault;
  303. end;
  304. end;
  305. { TSearchFpcSourceThread }
  306. constructor TSearchFpcSourceThread.Create(aSetupDialog: TInitialSetupDialog);
  307. begin
  308. inherited Create(True);
  309. FreeOnTerminate:=True;
  310. fSetupDialog:=aSetupDialog;
  311. end;
  312. destructor TSearchFpcSourceThread.Destroy;
  313. begin
  314. inherited Destroy;
  315. end;
  316. procedure TSearchFpcSourceThread.Execute;
  317. var
  318. RootDir: String;
  319. begin
  320. // ToDo: RootDir must be changed for Windows and maybe other systems.
  321. // GetUserDir returns the user profile dir on Windows.
  322. RootDir:=GetUserDir;
  323. // Scan directories under root directory.
  324. DoSearch(AppendPathDelim(RootDir));
  325. if Assigned(fFoundFPCSrc) then
  326. Synchronize(@UpdateFPCSrcDir); // Update GUI in main thread.
  327. Synchronize(@Finishing);
  328. end;
  329. function TSearchFpcSourceThread.CheckFPCSrcDir(Dir: string): TSDFileInfo;
  330. var
  331. RealDir: String;
  332. begin
  333. Result:=Nil;
  334. RealDir:=TrimFilename(Dir);
  335. if RealDir='' then exit;
  336. if not DirPathExistsCached(RealDir) then exit; // check if exists
  337. Result:=TSDFileInfo.Create;
  338. Result.Filename:=RealDir;
  339. Result.Caption:=Dir; // check quality
  340. Result.Quality:=CheckFPCSrcDirQuality(RealDir, Result.Note, fFPCVer, False);
  341. if Result.Quality<>sddqCompatible then // return only exact matches
  342. FreeAndNil(Result);
  343. end;
  344. procedure TSearchFpcSourceThread.DoSearch(const APath: String);
  345. var
  346. PathInfo: TSearchRec;
  347. FPCSrc: TSDFileInfo;
  348. begin
  349. if FindFirstUTF8(APath+AllDirectoryEntriesMask, faDirectory, PathInfo) = 0 then
  350. try
  351. repeat
  352. if Terminated then Break;
  353. if (PathInfo.Name='') or (PathInfo.Name[1]='.')
  354. or ((PathInfo.Attr and faDirectory) = 0) then Continue;
  355. {$IFDEF VerboseFPCSrcScanThead}
  356. fPath := APath;
  357. fFileInfo := PathInfo;
  358. Synchronize(@Debug);
  359. {$ENDIF}
  360. DoSearch(AppendPathDelim(APath+PathInfo.Name)); // Recursive call
  361. FPCSrc:=CheckFPCSrcDir(APath+PathInfo.Name);
  362. if Assigned(FPCSrc) then begin
  363. fFoundFPCSrc:=FPCSrc; // An exact match was found.
  364. Terminate;
  365. end;
  366. until (FindNextUTF8(PathInfo) <> 0);
  367. finally
  368. FindCloseUTF8(PathInfo);
  369. end;
  370. end;
  371. {$IFDEF VerboseFPCSrcScanThead}
  372. procedure TSearchFpcSourceThread.Debug;
  373. begin
  374. DebugLn(['* TSearchFpcSourceThread.Debug: Path=', fPath, ', Name=', fFileInfo.Name]);
  375. end;
  376. {$ENDIF}
  377. procedure TSearchFpcSourceThread.UpdateFPCSrcDir;
  378. begin
  379. DebugLn(['TSearchFpcSourceThread.UpdateFPCSrcDir']);
  380. fSetupDialog.UpdateFPCSrcDirCandidate(fFoundFPCSrc);
  381. fSetupDialog.UpdateFPCSrcDirNote;
  382. end;
  383. procedure TSearchFpcSourceThread.Finishing;
  384. begin
  385. DebugLn(['TSearchFpcSourceThread.Finishing']);
  386. fSetupDialog.ShowHideScanControls(False); // Hide scan controls
  387. end;
  388. { TSetupMacros }
  389. procedure TSetupMacros.DoSubstitution(TheMacro: TTransferMacro;
  390. const MacroName: string; var s: string; const Data: PtrInt; var Handled,
  391. Abort: boolean; Depth: integer);
  392. begin
  393. Handled:=true;
  394. if CompareText(MacroName,'ENV')=0 then
  395. s:=GetEnvironmentVariableUTF8(MacroName)
  396. else if CompareText(MacroName,'PrimaryConfigPath')=0 then
  397. s:=GetPrimaryConfigPath
  398. else if CompareText(MacroName,'SecondaryConfigPath')=0 then
  399. s:=GetSecondaryConfigPath
  400. else if CompareText(MacroName,'FPCVer')=0 then begin
  401. if FPCVer<>'' then
  402. s:=FPCVer
  403. else
  404. s:={$I %FPCVERSION%};
  405. end else if CompareText(MacroName,'LazarusDir')=0 then begin
  406. if LazarusDir<>'' then
  407. s:=LazarusDir
  408. else
  409. s:='<LazarusDirNotSet>';
  410. end else if (CompareText(MacroName,'TargetOS')=0) then
  411. s:=GetCompiledTargetOS
  412. else if (CompareText(MacroName,'TargetCPU')=0) then
  413. s:=GetCompiledTargetCPU
  414. else if (CompareText(MacroName,'SrcOS')=0) then
  415. s:=GetDefaultSrcOSForTargetOS(GetCompiledTargetOS)
  416. else
  417. Handled:=false;
  418. //debugln(['TSetupMacros.DoSubstitution MacroName=',MacroName,' Value="',s,'"']);
  419. end;
  420. {$R *.lfm}
  421. { TInitialSetupDialog }
  422. procedure TInitialSetupDialog.FormCreate(Sender: TObject);
  423. begin
  424. LazarusTabSheet.Caption:='Lazarus';
  425. CompilerTabSheet.Caption:=lisCompiler;
  426. FPCSourcesTabSheet.Caption:=lisFPCSources;
  427. MakeExeTabSheet.Caption:='Make';
  428. DebuggerTabSheet.Caption:=lisDebugger;
  429. FHeadGraphic:=TPortableNetworkGraphic.Create;
  430. FHeadGraphic.LoadFromResourceName(HInstance, 'ide_icon48x48');
  431. TVNodeLazarus:=PropertiesTreeView.Items.Add(nil,LazarusTabSheet.Caption);
  432. TVNodeCompiler:=PropertiesTreeView.Items.Add(nil,CompilerTabSheet.Caption);
  433. TVNodeFPCSources:=PropertiesTreeView.Items.Add(nil,FPCSourcesTabSheet.Caption);
  434. TVNodeMakeExe:=PropertiesTreeView.Items.Add(nil,MakeExeTabSheet.Caption);
  435. TVNodeDebugger:=PropertiesTreeView.Items.Add(nil,DebuggerTabSheet.Caption);
  436. ImgIDError := Imagelist1.AddResourceName(HInstance, 'state_error');
  437. ImgIDWarning := Imagelist1.AddResourceName(HInstance, 'state_warning');
  438. StopScanButton.LoadGlyphFromResourceName(HInstance, 'menu_stop');
  439. UpdateCaptions;
  440. Application.AddOnActivateHandler(@OnAppActivate);
  441. end;
  442. procedure TInitialSetupDialog.CompilerComboBoxChange(Sender: TObject);
  443. begin
  444. UpdateCompilerNote;
  445. UpdateFPCSrcDirNote;
  446. end;
  447. procedure TInitialSetupDialog.DebuggerBrowseButtonClick(Sender: TObject);
  448. var
  449. Filename: String;
  450. Dlg: TOpenDialog;
  451. Filter: String;
  452. begin
  453. Dlg:=TOpenDialog.Create(nil);
  454. try
  455. Filename:='gdb'+GetExecutableExt;
  456. Dlg.Title:=SimpleFormat(lisSelectPathTo, [Filename]);
  457. Dlg.Options:=Dlg.Options+[ofFileMustExist];
  458. Filter:=dlgFilterAll+'|'+GetAllFilesMask;
  459. if ExtractFileExt(Filename)<>'' then
  460. Filter:=dlgFilterExecutable+'|*'+ExtractFileExt(Filename)+'|'+Filter;
  461. Dlg.Filter:=Filter;
  462. if not Dlg.Execute then exit;
  463. Filename:=Dlg.FileName;
  464. finally
  465. Dlg.Free;
  466. end;
  467. DebuggerComboBox.Text:=Filename;
  468. UpdateDebuggerNote;
  469. end;
  470. procedure TInitialSetupDialog.DebuggerComboBoxChange(Sender: TObject);
  471. begin
  472. UpdateDebuggerNote;
  473. end;
  474. procedure TInitialSetupDialog.CompilerBrowseButtonClick(Sender: TObject);
  475. var
  476. Filename: String;
  477. Dlg: TOpenDialog;
  478. Filter: String;
  479. begin
  480. Dlg:=TOpenDialog.Create(nil);
  481. try
  482. Filename:='fpc'+GetExecutableExt;
  483. Dlg.Title:=SimpleFormat(lisSelectPathTo, [Filename]);
  484. Dlg.Options:=Dlg.Options+[ofFileMustExist];
  485. Filter:=dlgFilterAll+'|'+GetAllFilesMask;
  486. if ExtractFileExt(Filename)<>'' then
  487. Filter:=dlgFilterExecutable+'|*'+ExtractFileExt(Filename)+'|'+Filter;
  488. Dlg.Filter:=Filter;
  489. if not Dlg.Execute then exit;
  490. Filename:=Dlg.FileName;
  491. finally
  492. Dlg.Free;
  493. end;
  494. CompilerComboBox.Text:=Filename;
  495. UpdateCompilerNote;
  496. end;
  497. procedure TInitialSetupDialog.FormDestroy(Sender: TObject);
  498. var
  499. d: TSDFilenameType;
  500. begin
  501. IdleConnected:=false;
  502. if Assigned(fSearchFpcSourceThread) then begin
  503. fSearchFpcSourceThread.Terminate;
  504. fSearchFpcSourceThread.WaitFor;
  505. end;
  506. for d:=low(FCandidates) to high(FCandidates) do
  507. FreeAndNil(FCandidates[d]);
  508. FreeAndNil(FHeadGraphic);
  509. end;
  510. procedure TInitialSetupDialog.FPCSrcDirBrowseButtonClick(Sender: TObject);
  511. var
  512. Dir: String;
  513. begin
  514. Dir:=SelectDirectory(lisSelectFPCSourceDirectory);
  515. if Dir='' then exit;
  516. FPCSrcDirComboBox.Text:=Dir;
  517. UpdateFPCSrcDirNote;
  518. end;
  519. procedure TInitialSetupDialog.FPCSrcDirComboBoxChange(Sender: TObject);
  520. begin
  521. UpdateFPCSrcDirNote;
  522. end;
  523. procedure TInitialSetupDialog.LazDirBrowseButtonClick(Sender: TObject);
  524. var
  525. Dir: String;
  526. begin
  527. Dir:=SelectDirectory(lisSelectLazarusSourceDirectory);
  528. if Dir='' then exit;
  529. LazDirComboBox.Text:=Dir;
  530. UpdateLazDirNote;
  531. end;
  532. procedure TInitialSetupDialog.LazDirComboBoxChange(Sender: TObject);
  533. begin
  534. UpdateLazDirNote;
  535. end;
  536. procedure TInitialSetupDialog.MakeExeBrowseButtonClick(Sender: TObject);
  537. var
  538. Filename: String;
  539. Dlg: TOpenDialog;
  540. Filter: String;
  541. begin
  542. Dlg:=TOpenDialog.Create(nil);
  543. try
  544. Filename:='make'+GetExecutableExt;
  545. Dlg.Title:=SimpleFormat(lisSelectPathTo, [Filename]);
  546. Dlg.Options:=Dlg.Options+[ofFileMustExist];
  547. Filter:=dlgFilterAll+'|'+GetAllFilesMask;
  548. if ExtractFileExt(Filename)<>'' then
  549. Filter:=dlgFilterExecutable+'|*'+ExtractFileExt(Filename)+'|'+Filter;
  550. Dlg.Filter:=Filter;
  551. if not Dlg.Execute then exit;
  552. Filename:=Dlg.FileName;
  553. finally
  554. Dlg.Free;
  555. end;
  556. MakeExeComboBox.Text:=Filename;
  557. UpdateMakeExeNote;
  558. end;
  559. procedure TInitialSetupDialog.MakeExeComboBoxChange(Sender: TObject);
  560. begin
  561. UpdateMakeExeNote;
  562. end;
  563. procedure TInitialSetupDialog.OnAppActivate(Sender: TObject);
  564. begin
  565. // switched back from another application
  566. InvalidateFileStateCache;
  567. end;
  568. procedure TInitialSetupDialog.PropertiesPageControlChange(Sender: TObject);
  569. var
  570. s: String;
  571. i: Integer;
  572. begin
  573. if PropertiesPageControl.ActivePage=nil then exit;
  574. s:=PropertiesPageControl.ActivePage.Caption;
  575. for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do
  576. if PropertiesTreeView.Items.TopLvlItems[i].Text=s then
  577. PropertiesTreeView.Selected:=PropertiesTreeView.Items.TopLvlItems[i];
  578. end;
  579. procedure TInitialSetupDialog.PropertiesTreeViewSelectionChanged(Sender: TObject);
  580. begin
  581. if PropertiesTreeView.Selected=nil then
  582. SelectPage(TVNodeLazarus.Text)
  583. else
  584. SelectPage(PropertiesTreeView.Selected.Text);
  585. end;
  586. procedure TInitialSetupDialog.StartIDEBitBtnClick(Sender: TObject);
  587. var
  588. Node: TTreeNode;
  589. s: String;
  590. MsgResult: TModalResult;
  591. begin
  592. Node:=FirstErrorNode;
  593. s:='';
  594. if Node=TVNodeLazarus then
  595. s:=lisWithoutAProperLazarusDirectoryYouWillGetALotOfWarn
  596. else if Node=TVNodeCompiler then
  597. s:=lisWithoutAProperCompilerTheCodeBrowsingAndCompilingW
  598. else if Node=TVNodeFPCSources then
  599. s:=lisWithoutTheProperFPCSourcesCodeBrowsingAndCompletio
  600. else if Node=TVNodeMakeExe then
  601. s:=lisWithoutAProperMakeExecutableTheCompilingOfTheIDEIs
  602. else if Node=TVNodeDebugger then
  603. s:=lisWithoutAProperDebuggerDebuggingWillBeDisappointing;
  604. if s<>'' then begin
  605. MsgResult:=MessageDlg(lisCCOWarningCaption, s, mtWarning, [mbIgnore,
  606. mbCancel], 0);
  607. if MsgResult<>mrIgnore then exit;
  608. end;
  609. s:=LazDirComboBox.Text;
  610. if s<>'' then
  611. EnvironmentOptions.LazarusDirectory:=s;
  612. s:=CompilerComboBox.Text;
  613. if s<>'' then
  614. EnvironmentOptions.CompilerFilename:=s;
  615. s:=FPCSrcDirComboBox.Text;
  616. if s<>'' then
  617. EnvironmentOptions.FPCSourceDirectory:=s;
  618. s:=MakeExeComboBox.Text;
  619. if s<>'' then
  620. EnvironmentOptions.MakeFilename:=s;
  621. s:=DebuggerComboBox.Text;
  622. if s<>'' then begin
  623. EnvironmentOptions.DebuggerFilename:=s;
  624. if s <> FInitialDebuggerFileName then
  625. EnvironmentOptions.DebuggerConfig.DebuggerClass := 'TGDBMIDebugger';
  626. end;
  627. ModalResult:=mrOk;
  628. end;
  629. procedure TInitialSetupDialog.StopScanButtonClick(Sender: TObject);
  630. begin
  631. if fSearchFpcSourceThread<>nil then
  632. fSearchFpcSourceThread.Terminate;
  633. end;
  634. procedure TInitialSetupDialog.WelcomePaintBoxPaint(Sender: TObject);
  635. begin
  636. with WelcomePaintBox.Canvas do begin
  637. GradientFill(WelcomePaintBox.ClientRect,$854b32,$c88e60,gdHorizontal);
  638. Draw(0,WelcomePaintBox.ClientHeight-FHeadGraphic.Height,FHeadGraphic);
  639. Font.Color:=clWhite;
  640. Font.Height:=30;
  641. Brush.Style:=bsClear;
  642. TextOut(FHeadGraphic.Width+15, 5, lisConfigureLazarusIDE);
  643. end;
  644. end;
  645. procedure TInitialSetupDialog.OnIdle(Sender: TObject; var Done: Boolean);
  646. begin
  647. if sdfCompilerFilenameNeedsUpdate in FFlags then begin
  648. UpdateCompilerFilenameCandidates;
  649. UpdateCompilerNote;
  650. end else if sdfFPCSrcDirNeedsUpdate in FFlags then begin
  651. UpdateFPCSrcDirCandidates;
  652. UpdateFPCSrcDirNote;
  653. end else if sdfMakeExeFilenameNeedsUpdate in FFlags then begin
  654. UpdateMakeExeCandidates;
  655. UpdateMakeExeNote;
  656. end else if sdfDebuggerFilenameNeedsUpdate in FFlags then begin
  657. UpdateDebuggerCandidates;
  658. UpdateDebuggerNote;
  659. end else
  660. IdleConnected:=false;
  661. end;
  662. procedure TInitialSetupDialog.UpdateCaptions;
  663. var
  664. s: String;
  665. begin
  666. Caption:=SimpleFormat(lisWelcomeToLazarusIDE, [GetLazarusVersionString]);
  667. StartIDEBitBtn.Caption:=lisStartIDE;
  668. LazarusTabSheet.Caption:='Lazarus';
  669. CompilerTabSheet.Caption:=lisCompiler;
  670. FPCSourcesTabSheet.Caption:=lisFPCSources;
  671. MakeExeTabSheet.Caption:='Make';
  672. DebuggerTabSheet.Caption:=lisDebugger;
  673. TVNodeLazarus.Text:=LazarusTabSheet.Caption;
  674. TVNodeCompiler.Text:=CompilerTabSheet.Caption;
  675. TVNodeFPCSources.Text:=FPCSourcesTabSheet.Caption;
  676. TVNodeMakeExe.Text:=MakeExeTabSheet.Caption;
  677. TVNodeDebugger.Text:=DebuggerTabSheet.Caption;
  678. LazDirBrowseButton.Caption:=lisPathEditBrowse;
  679. LazDirLabel.Caption:=SimpleFormat(
  680. lisTheLazarusDirectoryContainsTheSourcesOfTheIDEAndTh, [PathDelim]);
  681. CompilerBrowseButton.Caption:=lisPathEditBrowse;
  682. CompilerLabel.Caption:=SimpleFormat(lisTheFreePascalCompilerExecutableTypicallyHasTheName,
  683. [DefineTemplates.GetDefaultCompilerFilename,
  684. DefineTemplates.GetDefaultCompilerFilename(GetCompiledTargetCPU)]);
  685. FPCSrcDirBrowseButton.Caption:=lisPathEditBrowse;
  686. FPCSrcDirLabel.Caption:=SimpleFormat(lisTheSourcesOfTheFreePascalPackagesAreRequiredForBro,
  687. [SetDirSeparators('rtl/linux/system.pp')]);
  688. ScanLabel.Caption := lisScanning;
  689. StopScanButton.Caption:=lisStop;
  690. MakeExeBrowseButton.Caption:=lisPathEditBrowse;
  691. MakeExeLabel.Caption:=SimpleFormat(
  692. lisTheMakeExecutableTypicallyHasTheName, ['make'+GetExecutableExt('')]);
  693. DebuggerBrowseButton.Caption:=lisPathEditBrowse;
  694. s:=SimpleFormat(lisTheDebuggerExecutableTypicallyHasTheNamePleaseGive, [
  695. 'gdb'+GetExecutableExt]);
  696. {$IFDEF Windows}
  697. s+=' '+lisAUsefulSettingOnWindowsSystemsIsLazarusDirMingwBin;
  698. {$ENDIF}
  699. DebuggerLabel.Caption:=s;
  700. end;
  701. procedure TInitialSetupDialog.SelectPage(const NodeText: string);
  702. var
  703. i: Integer;
  704. Node: TTreeNode;
  705. begin
  706. if FSelectingPage then exit;
  707. FSelectingPage:=true;
  708. try
  709. for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do begin
  710. Node:=PropertiesTreeView.Items.TopLvlItems[i];
  711. if Node.Text=NodeText then begin
  712. PropertiesTreeView.Selected:=Node;
  713. PropertiesPageControl.ActivePageIndex:=i;
  714. break;
  715. end;
  716. end;
  717. finally
  718. FSelectingPage:=false;
  719. end;
  720. end;
  721. function TInitialSetupDialog.SelectDirectory(aTitle: string): string;
  722. var
  723. DirDlg: TSelectDirectoryDialog;
  724. begin
  725. Result:='';
  726. DirDlg:=TSelectDirectoryDialog.Create(nil);
  727. try
  728. DirDlg.Title:=aTitle;
  729. DirDlg.Options:=DirDlg.Options+[ofPathMustExist,ofFileMustExist];
  730. if not DirDlg.Execute then exit;
  731. Result:=DirDlg.FileName;
  732. finally
  733. DirDlg.Free;
  734. end;
  735. end;
  736. procedure TInitialSetupDialog.StartFPCSrcThread;
  737. begin
  738. fSearchFpcSourceThread:=TSearchFpcSourceThread.Create(Self);
  739. fSearchFpcSourceThread.OnTerminate:=@ThreadTerminated;
  740. fSearchFpcSourceThread.fFPCVer:=GetFPCVer;
  741. ShowHideScanControls(True); // Show scan controls while thread is running
  742. fSearchFpcSourceThread.Start;
  743. end;
  744. procedure TInitialSetupDialog.UpdateLazarusDirCandidates;
  745. var
  746. Dirs: TSDFileInfoList;
  747. begin
  748. Dirs:=SearchLazarusDirectoryCandidates(false);
  749. FreeAndNil(FCandidates[sddtLazarusSrcDir]);
  750. FCandidates[sddtLazarusSrcDir]:=Dirs;
  751. FillComboboxWithFileInfoList(LazDirComboBox,Dirs);
  752. end;
  753. procedure TInitialSetupDialog.UpdateCompilerFilenameCandidates;
  754. var
  755. Files: TSDFileInfoList;
  756. begin
  757. Exclude(FFlags,sdfCompilerFilenameNeedsUpdate);
  758. Files:=SearchCompilerCandidates(false,CodeToolBoss.FPCDefinesCache.TestFilename);
  759. FreeAndNil(FCandidates[sddtCompilerFilename]);
  760. FCandidates[sddtCompilerFilename]:=Files;
  761. FillComboboxWithFileInfoList(CompilerComboBox,Files);
  762. end;
  763. procedure TInitialSetupDialog.UpdateFPCSrcDirCandidates;
  764. var
  765. Dirs: TSDFileInfoList;
  766. begin
  767. Exclude(FFlags,sdfFPCSrcDirNeedsUpdate);
  768. Dirs:=SearchFPCSrcDirCandidates(false,GetFPCVer);
  769. FreeAndNil(FCandidates[sddtFPCSrcDir]);
  770. FCandidates[sddtFPCSrcDir]:=Dirs;
  771. FillComboboxWithFileInfoList(FPCSrcDirComboBox,Dirs);
  772. end;
  773. procedure TInitialSetupDialog.UpdateFPCSrcDirCandidate(aFPCSrcDirInfo: TSDFileInfo);
  774. var
  775. Dirs: TSDFileInfoList;
  776. begin
  777. Exclude(FFlags,sdfFPCSrcDirNeedsUpdate);
  778. FreeAndNil(FCandidates[sddtFPCSrcDir]);
  779. Dirs:=TSDFileInfoList.Create;
  780. Dirs.Add(aFPCSrcDirInfo);
  781. FCandidates[sddtFPCSrcDir]:=Dirs;
  782. FillComboboxWithFileInfoList(FPCSrcDirComboBox,Dirs);
  783. end;
  784. procedure TInitialSetupDialog.UpdateMakeExeCandidates;
  785. var
  786. Files: TSDFileInfoList;
  787. begin
  788. Exclude(FFlags,sdfMakeExeFilenameNeedsUpdate);
  789. Files:=SearchMakeExeCandidates(false);
  790. FreeAndNil(FCandidates[sddtMakeExeFileName]);
  791. FCandidates[sddtMakeExeFileName]:=Files;
  792. FillComboboxWithFileInfoList(MakeExeComboBox,Files);
  793. end;
  794. procedure TInitialSetupDialog.UpdateDebuggerCandidates;
  795. var
  796. Files: TSDFileInfoList;
  797. begin
  798. Exclude(FFlags,sdfDebuggerFilenameNeedsUpdate);
  799. Files:=SearchDebuggerCandidates(false);
  800. FreeAndNil(FCandidates[sddtDebuggerFilename]);
  801. FCandidates[sddtDebuggerFilename]:=Files;
  802. FillComboboxWithFileInfoList(DebuggerComboBox,Files);
  803. end;
  804. procedure TInitialSetupDialog.FillComboboxWithFileInfoList(ABox: TComboBox;
  805. List: TSDFileInfoList; ItemIndex: integer);
  806. var
  807. sl: TStringList;
  808. i: Integer;
  809. begin
  810. sl:=TStringList.Create;
  811. try
  812. if List<>nil then
  813. for i:=0 to List.Count-1 do
  814. sl.Add(TSDFileInfo(List[i]).Caption);
  815. ABox.Items.Assign(sl);
  816. if (ItemIndex>=0) and (ItemIndex<sl.Count) then
  817. ABox.Text:=sl[ItemIndex]
  818. else if ABox.Text=ABox.Name then
  819. ABox.Text:='';
  820. finally
  821. sl.Free;
  822. end;
  823. end;
  824. procedure TInitialSetupDialog.SetIdleConnected(const AValue: boolean);
  825. begin
  826. if FIdleConnected=AValue then exit;
  827. FIdleConnected:=AValue;
  828. if IdleConnected then
  829. Application.AddOnIdleHandler(@OnIdle)
  830. else
  831. Application.RemoveOnIdleHandler(@OnIdle);
  832. end;
  833. procedure TInitialSetupDialog.UpdateLazDirNote;
  834. var
  835. CurCaption: String;
  836. Note: string;
  837. Quality: TSDFilenameQuality;
  838. s: String;
  839. ImageIndex: Integer;
  840. begin
  841. if csDestroying in ComponentState then exit;
  842. CurCaption:=LazDirComboBox.Text;
  843. CurCaption:=ChompPathDelim(CurCaption);
  844. EnvironmentOptions.LazarusDirectory:=CurCaption;
  845. if FLastParsedLazDir=EnvironmentOptions.GetParsedLazarusDirectory then exit;
  846. FLastParsedLazDir:=EnvironmentOptions.GetParsedLazarusDirectory;
  847. //debugln(['TInitialSetupDialog.UpdateLazDirNote ',FLastParsedLazDir]);
  848. Quality:=CheckLazarusDirectoryQuality(FLastParsedLazDir,Note);
  849. case Quality of
  850. sddqInvalid: s:=lisError;
  851. sddqCompatible: s:='';
  852. else s:=lisWarning;
  853. end;
  854. if EnvironmentOptions.LazarusDirectory<>EnvironmentOptions.GetParsedLazarusDirectory
  855. then
  856. s:=lisDirectory+EnvironmentOptions.GetParsedLazarusDirectory+LineEnding+
  857. LineEnding+s;
  858. LazDirMemo.Text:=s+Note;
  859. ImageIndex:=QualityToImgIndex(Quality);
  860. TVNodeLazarus.ImageIndex:=ImageIndex;
  861. TVNodeLazarus.SelectedIndex:=ImageIndex;
  862. FFlags:=FFlags+[sdfCompilerFilenameNeedsUpdate,sdfFPCSrcDirNeedsUpdate,
  863. sdfMakeExeFilenameNeedsUpdate,sdfDebuggerFilenameNeedsUpdate];
  864. IdleConnected:=true;
  865. end;
  866. procedure TInitialSetupDialog.UpdateCompilerNote;
  867. var
  868. CurCaption: String;
  869. Note: string;
  870. Quality: TSDFilenameQuality;
  871. s: String;
  872. ImageIndex: Integer;
  873. CfgCache: TFPCTargetConfigCache;
  874. begin
  875. if csDestroying in ComponentState then exit;
  876. CurCaption:=CompilerComboBox.Text;
  877. EnvironmentOptions.CompilerFilename:=CurCaption;
  878. if fLastParsedCompiler=EnvironmentOptions.GetParsedCompilerFilename then exit;
  879. fLastParsedCompiler:=EnvironmentOptions.GetParsedCompilerFilename;
  880. //debugln(['TInitialSetupDialog.UpdateCompilerNote ',fLastParsedCompiler]);
  881. Quality:=CheckCompilerQuality(fLastParsedCompiler,Note,
  882. CodeToolBoss.FPCDefinesCache.TestFilename);
  883. if Quality<>sddqInvalid then begin
  884. CodeToolBoss.FPCDefinesCache.ConfigCaches.Find(
  885. fLastParsedCompiler,'','','',true);
  886. // check compiler again
  887. CfgCache:=CodeToolBoss.FPCDefinesCache.ConfigCaches.Find(
  888. fLastParsedCompiler,'','','',true);
  889. CfgCache.Update(CodeToolBoss.FPCDefinesCache.TestFilename);
  890. BuildBoss.SetBuildTargetIDE;
  891. end;
  892. case Quality of
  893. sddqInvalid: s:=lisError;
  894. sddqCompatible: s:='';
  895. else s:=lisWarning;
  896. end;
  897. if EnvironmentOptions.CompilerFilename<>EnvironmentOptions.GetParsedCompilerFilename
  898. then
  899. s:=lisFile2+EnvironmentOptions.GetParsedCompilerFilename+LineEnding+
  900. LineEnding+s;
  901. CompilerMemo.Text:=s+Note;
  902. ImageIndex:=QualityToImgIndex(Quality);
  903. TVNodeCompiler.ImageIndex:=ImageIndex;
  904. TVNodeCompiler.SelectedIndex:=ImageIndex;
  905. FFlags:=FFlags+[sdfFPCSrcDirNeedsUpdate,
  906. sdfMakeExeFilenameNeedsUpdate,sdfDebuggerFilenameNeedsUpdate];
  907. IdleConnected:=true;
  908. end;
  909. procedure TInitialSetupDialog.UpdateFPCSrcDirNote;
  910. var
  911. CurCaption: String;
  912. Note: string;
  913. Quality: TSDFilenameQuality;
  914. s: String;
  915. ImageIndex: Integer;
  916. begin
  917. if csDestroying in ComponentState then exit;
  918. CurCaption:=FPCSrcDirComboBox.Text;
  919. CurCaption:=ChompPathDelim(CurCaption);
  920. EnvironmentOptions.FPCSourceDirectory:=CurCaption;
  921. if fLastParsedFPCSrcDir=EnvironmentOptions.GetParsedFPCSourceDirectory then exit;
  922. fLastParsedFPCSrcDir:=EnvironmentOptions.GetParsedFPCSourceDirectory;
  923. //debugln(['TInitialSetupDialog.UpdateFPCSrcDirNote ',fLastParsedFPCSrcDir]);
  924. Quality:=CheckFPCSrcDirQuality(fLastParsedFPCSrcDir,Note,GetFPCVer);
  925. case Quality of
  926. sddqInvalid: s:=lisError;
  927. sddqCompatible: s:='';
  928. else s:=lisWarning;
  929. end;
  930. if EnvironmentOptions.FPCSourceDirectory<>EnvironmentOptions.GetParsedFPCSourceDirectory
  931. then
  932. s:=lisDirectory+EnvironmentOptions.GetParsedFPCSourceDirectory+LineEnding+
  933. LineEnding+s;
  934. s+=Note;
  935. if Quality<>sddqCompatible then
  936. s+=#13+lisYouCanDownloadFPCAndTheFPCSourcesFromHttpSourcefor;
  937. FPCSrcDirMemo.Text:=s;
  938. ImageIndex:=QualityToImgIndex(Quality);
  939. TVNodeFPCSources.ImageIndex:=ImageIndex;
  940. TVNodeFPCSources.SelectedIndex:=ImageIndex;
  941. end;
  942. procedure TInitialSetupDialog.UpdateMakeExeNote;
  943. var
  944. CurCaption: String;
  945. Note: string;
  946. Quality: TSDFilenameQuality;
  947. s: String;
  948. ImageIndex: Integer;
  949. begin
  950. if csDestroying in ComponentState then exit;
  951. CurCaption:=MakeExeComboBox.Text;
  952. EnvironmentOptions.MakeFilename:=CurCaption;
  953. if fLastParsedMakeExe=EnvironmentOptions.GetParsedMakeFilename then exit;
  954. fLastParsedMakeExe:=EnvironmentOptions.GetParsedMakeFilename;
  955. //debugln(['TInitialSetupDialog.UpdateMakeExeNote ',fLastParsedMakeExe]);
  956. Quality:=CheckMakeExeQuality(fLastParsedMakeExe,Note);
  957. case Quality of
  958. sddqInvalid: s:=lisError;
  959. sddqCompatible: s:='';
  960. else s:=lisWarning;
  961. end;
  962. if EnvironmentOptions.MakeFilename<>EnvironmentOptions.GetParsedMakeFilename
  963. then
  964. s:=lisFile2+EnvironmentOptions.GetParsedMakeFilename+LineEnding+
  965. LineEnding+s;
  966. MakeExeMemo.Text:=s+Note;
  967. ImageIndex:=QualityToImgIndex(Quality);
  968. TVNodeMakeExe.ImageIndex:=ImageIndex;
  969. TVNodeMakeExe.SelectedIndex:=ImageIndex;
  970. IdleConnected:=true;
  971. end;
  972. procedure TInitialSetupDialog.UpdateDebuggerNote;
  973. var
  974. CurCaption: String;
  975. Note: string;
  976. Quality: TSDFilenameQuality;
  977. s: String;
  978. ImageIndex: Integer;
  979. begin
  980. if csDestroying in ComponentState then exit;
  981. CurCaption:=DebuggerComboBox.Text;
  982. EnvironmentOptions.DebuggerFilename:=CurCaption;
  983. if fLastParsedDebugger=EnvironmentOptions.GetParsedDebuggerFilename then exit;
  984. fLastParsedDebugger:=EnvironmentOptions.GetParsedDebuggerFilename;
  985. //debugln(['TInitialSetupDialog.UpdateDebuggerNote ',fLastParsedDebugger]);
  986. Quality:=CheckDebuggerQuality(fLastParsedDebugger,Note);
  987. case Quality of
  988. sddqInvalid: s:=lisError;
  989. sddqCompatible: s:='';
  990. else s:=lisWarning;
  991. end;
  992. if EnvironmentOptions.DebuggerFilename<>EnvironmentOptions.GetParsedDebuggerFilename
  993. then
  994. s:=lisFile2+EnvironmentOptions.GetParsedDebuggerFilename+LineEnding+
  995. LineEnding+s;
  996. DebuggerMemo.Text:=s+Note;
  997. ImageIndex:=QualityToImgIndex(Quality);
  998. TVNodeDebugger.ImageIndex:=ImageIndex;
  999. TVNodeDebugger.SelectedIndex:=ImageIndex;
  1000. IdleConnected:=true;
  1001. end;
  1002. function TInitialSetupDialog.FirstErrorNode: TTreeNode;
  1003. var
  1004. i: Integer;
  1005. begin
  1006. for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do
  1007. begin
  1008. Result:=PropertiesTreeView.Items.TopLvlItems[i];
  1009. if Result.ImageIndex=ImgIDError then exit;
  1010. end;
  1011. Result:=nil;
  1012. end;
  1013. function TInitialSetupDialog.GetFPCVer: string;
  1014. begin
  1015. Result:='$(FPCVer)';
  1016. GlobalMacroList.SubstituteStr(Result);
  1017. end;
  1018. function TInitialSetupDialog.GetFirstCandidate(Candidates: TSDFileInfoList;
  1019. MinQuality: TSDFilenameQuality): TSDFileInfo;
  1020. var
  1021. i: Integer;
  1022. begin
  1023. if Candidates<>nil then
  1024. for i:=0 to Candidates.Count-1 do begin
  1025. Result:=TSDFileInfo(Candidates[i]);
  1026. if Result.Quality>=MinQuality then
  1027. exit;
  1028. end;
  1029. Result:=nil;
  1030. end;
  1031. function TInitialSetupDialog.QualityToImgIndex(Quality: TSDFilenameQuality): integer;
  1032. begin
  1033. if Quality=sddqCompatible then
  1034. Result:=-1
  1035. else if Quality=sddqWrongMinorVersion then
  1036. Result:=ImgIDWarning
  1037. else if Quality=sddqIncomplete then
  1038. Result:=ImgIDWarning
  1039. else
  1040. Result:=ImgIDError;
  1041. end;
  1042. procedure TInitialSetupDialog.ShowHideScanControls(aShow: Boolean);
  1043. begin
  1044. // Show ProgressBar and Stop button durin scanning
  1045. ScanLabel.Visible:=aShow;
  1046. ScanProgressBar.Visible:=aShow;
  1047. StopScanButton.Visible:=aShow;
  1048. // At the same time disable other GUI controls so a user can not mess with it
  1049. StartIDEBitBtn.Enabled:=not aShow;
  1050. FPCSrcDirBrowseButton.Enabled:=not aShow;
  1051. FPCSrcDirComboBox.Enabled:=not aShow;
  1052. // FPCSrcDirMemo.Enabled:=not aShow;
  1053. end;
  1054. procedure TInitialSetupDialog.ThreadTerminated(Sender: TObject);
  1055. begin
  1056. debugln(['TInitialSetupDialog.ThreadTerminated ']);
  1057. fSearchFpcSourceThread:=nil; // Thread will free itself. Make the variable nil, too.
  1058. ShowHideScanControls(false);
  1059. end;
  1060. procedure TInitialSetupDialog.TranslateResourceStrings;
  1061. begin
  1062. IDETranslations.TranslateResourceStrings(
  1063. EnvironmentOptions.GetParsedLazarusDirectory,
  1064. EnvironmentOptions.LanguageID);
  1065. UpdateCaptions;
  1066. end;
  1067. procedure TInitialSetupDialog.Init;
  1068. var
  1069. Node: TTreeNode;
  1070. Candidate: TSDFileInfo;
  1071. IsFirstStart: Boolean;
  1072. PrimaryFilename: String;
  1073. SecondaryFilename: String;
  1074. PrimaryEnvs: TStringListUTF8;
  1075. SecondaryEnvs: TStringListUTF8;
  1076. begin
  1077. IsFirstStart:=not FileExistsCached(EnvironmentOptions.Filename);
  1078. if not IsFirstStart then begin
  1079. PrimaryFilename:=EnvironmentOptions.Filename;
  1080. SecondaryFilename:=AppendPathDelim(GetSecondaryConfigPath)+ExtractFilename(PrimaryFilename);
  1081. if FileExistsUTF8(PrimaryFilename)
  1082. and FileExistsUTF8(SecondaryFilename) then begin
  1083. // compare content of primary and secondary config
  1084. PrimaryEnvs:=TStringListUTF8.Create;
  1085. SecondaryEnvs:=TStringListUTF8.Create;
  1086. try
  1087. PrimaryEnvs.LoadFromFile(PrimaryFilename);
  1088. except
  1089. on E: Exception do
  1090. debugln(['TInitialSetupDialog.Init unable to read "'+PrimaryFilename+'": '+E.Message]);
  1091. end;
  1092. try
  1093. SecondaryEnvs.LoadFromFile(SecondaryFilename);
  1094. except
  1095. on E: Exception do
  1096. debugln(['TInitialSetupDialog.Init unable to read "'+SecondaryFilename+'": '+E.Message]);
  1097. end;
  1098. IsFirstStart:=PrimaryEnvs.Text=SecondaryEnvs.Text;
  1099. PrimaryEnvs.Free;
  1100. SecondaryEnvs.Free;
  1101. end;
  1102. end;
  1103. //debugln(['TInitialSetupDialog.Init IsFirstStart=',IsFirstStart,' ',EnvironmentOptions.Filename]);
  1104. // Lazarus directory
  1105. UpdateLazarusDirCandidates;
  1106. if IsFirstStart
  1107. or (not FileExistsCached(EnvironmentOptions.GetParsedLazarusDirectory))
  1108. then begin
  1109. // first start => choose first best candidate
  1110. Candidate:=GetFirstCandidate(FCandidates[sddtLazarusSrcDir]);
  1111. if Candidate<>nil then
  1112. begin
  1113. EnvironmentOptions.LazarusDirectory:=Candidate.Caption;
  1114. if Candidate.Quality=sddqCompatible then
  1115. TranslateResourceStrings;
  1116. end;
  1117. end;
  1118. LazDirComboBox.Text:=EnvironmentOptions.LazarusDirectory;
  1119. FLastParsedLazDir:='. .';
  1120. UpdateLazDirNote;
  1121. // compiler filename
  1122. UpdateCompilerFilenameCandidates;
  1123. if IsFirstStart
  1124. or (EnvironmentOptions.CompilerFilename='')
  1125. or (not FileExistsCached(EnvironmentOptions.GetParsedCompilerFilename))
  1126. then begin
  1127. // first start => choose first best candidate
  1128. Candidate:=GetFirstCandidate(FCandidates[sddtCompilerFilename]);
  1129. if Candidate<>nil then
  1130. EnvironmentOptions.CompilerFilename:=Candidate.Caption;
  1131. end;
  1132. CompilerComboBox.Text:=EnvironmentOptions.CompilerFilename;
  1133. fLastParsedCompiler:='. .';
  1134. UpdateCompilerNote;
  1135. // FPC source directory
  1136. UpdateFPCSrcDirCandidates;
  1137. {$IFDEF DebugSearchFPCSrcThread}
  1138. IsFirstStart:=true;
  1139. {$ENDIF}
  1140. if IsFirstStart or (EnvironmentOptions.FPCSourceDirectory='')
  1141. or (not FileExistsCached(EnvironmentOptions.GetParsedFPCSourceDirectory))
  1142. then begin
  1143. // first start => choose first best candidate
  1144. {$IFDEF DebugSearchFPCSrcThread}
  1145. Candidate:=nil;
  1146. {$ELSE}
  1147. Candidate:=GetFirstCandidate(FCandidates[sddtFPCSrcDir]);
  1148. {$ENDIF}
  1149. if Candidate<>nil then begin
  1150. EnvironmentOptions.FPCSourceDirectory:=Candidate.Caption;
  1151. end
  1152. else begin
  1153. // No candidates found => start a thread to scan the file system.
  1154. {$IFNDEF LCLCarbon}
  1155. // carbon interface does not support Synchronize outside Application.Run
  1156. StartFPCSrcThread;
  1157. SelectPage(TVNodeFPCSources.Text);
  1158. {$ENDIF}
  1159. end;
  1160. end;
  1161. ShowHideScanControls(fSearchFpcSourceThread<>nil);
  1162. FPCSrcDirComboBox.Text:=EnvironmentOptions.FPCSourceDirectory;
  1163. fLastParsedFPCSrcDir:='. .';
  1164. UpdateFPCSrcDirNote;
  1165. // Make executable
  1166. UpdateMakeExeCandidates;
  1167. if IsFirstStart
  1168. or (EnvironmentOptions.MakeFilename='')
  1169. or (not FileExistsCached(EnvironmentOptions.GetParsedMakeFilename)) then
  1170. begin
  1171. // first start => choose first best candidate
  1172. Candidate:=GetFirstCandidate(FCandidates[sddtMakeExeFilename]);
  1173. if Candidate<>nil then
  1174. EnvironmentOptions.MakeFilename:=Candidate.Caption
  1175. else begin // second chance => better an incomplete instead of none (especially for windows)
  1176. Candidate:=GetFirstCandidate(FCandidates[sddtMakeExeFilename], sddqIncomplete);
  1177. if Candidate<>nil then
  1178. EnvironmentOptions.MakeFilename:=Candidate.Caption;
  1179. end;
  1180. end;
  1181. MakeExeComboBox.Text:=EnvironmentOptions.MakeFilename;
  1182. fLastParsedMakeExe:='. .';
  1183. UpdateMakeExeNote;
  1184. // Debugger
  1185. FInitialDebuggerFileName := EnvironmentOptions.DebuggerFilename;
  1186. UpdateDebuggerCandidates;
  1187. if IsFirstStart or (not FileExistsCached(EnvironmentOptions.GetParsedDebuggerFilename))
  1188. then begin
  1189. // first start => choose first best candidate
  1190. Candidate:=GetFirstCandidate(FCandidates[sddtDebuggerFilename]);
  1191. if Candidate<>nil then
  1192. EnvironmentOptions.DebuggerFilename:=Candidate.Caption;
  1193. end;
  1194. DebuggerComboBox.Text:=EnvironmentOptions.DebuggerFilename;
  1195. fLastParsedDebugger:='. .';
  1196. UpdateDebuggerNote;
  1197. // select first error
  1198. Node:=FirstErrorNode;
  1199. if Node=nil then
  1200. Node:=TVNodeLazarus;
  1201. PropertiesTreeView.Selected:=Node;
  1202. end;
  1203. end.