1 {
2 /***************************************************************************
3 initialsetupdlgs.pas
4 --------------------
5 Contains the dialogs to help users setup basic settings.
6
7
8 ***************************************************************************/
9
10 ***************************************************************************
11 * *
12 * This source is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 * This code is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
20 * General Public License for more details. *
21 * *
22 * A copy of the GNU General Public License is available on the World *
23 * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
24 * obtain it by writing to the Free Software Foundation, *
25 * Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
26 * *
27 ***************************************************************************
28
29 Author: Mattias Gaertner
30
31 Abstract:
32 Contains the dialogs to help users setup basic settings.
33 }
34 unit InitialSetupDlgs;
35
36 {$mode objfpc}{$H+}
37
38 {off $DEFINE VerboseFPCSrcScanThead}
39
40 interface
41
42 uses
43 // RTL + FCL
44 Classes, SysUtils, pkgglobals, fpmkunit,
45 // LCL
46 Forms, Controls, Buttons, Dialogs, Graphics, ComCtrls, ExtCtrls, StdCtrls,
47 // CodeTools
48 FileProcs, CodeToolManager, DefineTemplates,
49 // LazUtils
50 FileUtil, LazUTF8, LazFileUtils, LazStringUtils, LazFileCache, LazLoggerBase,
51 // IdeIntf
52 MacroDefIntf, IDEDialogs, IDEImagesIntf, IDEUtils,
53 // DebuggerIntf
54 DbgIntfDebuggerBase,
55 // LazDebuggerGdbmi
56 GDBMIDebugger,
57 // IDE
58 TransferMacros, LazarusIDEStrConsts, LazConf, EnvironmentOpts,
59 AboutFrm, IDETranslations, BaseBuildManager, InitialSetupProc,
60 {$IF FPC_FULLVERSION>30100}
61 GenerateFppkgConfigurationDlg,
62 {$ENDIF}
63 IDEProcs;
64
65 type
66 TInitialSetupDialog = class;
67
68 { TSearchFpcSourceThread }
69
70 TSearchFpcSourceThread = class(TThread)
71 private
72 fSetupDialog: TInitialSetupDialog;
73 fFPCVer: string;
74 fFoundFPCSrc: TSDFileInfo;
75 {$IFDEF VerboseFPCSrcScanThead}
76 fPath: string;
77 fFileInfo: TSearchRec;
78 procedure Debug;
79 {$ENDIF}
CheckFPCSrcDirnull80 function CheckFPCSrcDir(Dir: string): TSDFileInfo;
81 procedure DoSearch(const APath: String);
82 procedure UpdateFPCSrcDir;
83 procedure Finishing;
84 protected
85 procedure Execute; override;
86 public
87 constructor Create(aSetupDialog: TInitialSetupDialog);
88 destructor Destroy; override;
89 end;
90
91 { TInitialSetupDialog }
92
93 TInitialSetupDialog = class(TForm)
94 BtnPanel: TPanel;
95 CompilerBrowseButton: TButton;
96 CompilerComboBox: TComboBox;
97 CompilerLabel: TLabel;
98 CompilerMemo: TMemo;
99 CompilerTabSheet: TTabSheet;
100 DebuggerBrowseButton: TButton;
101 DebuggerComboBox: TComboBox;
102 DebuggerLabel: TLabel;
103 DebuggerMemo: TMemo;
104 DebuggerTabSheet: TTabSheet;
105 FPCSourcesTabSheet: TTabSheet;
106 FPCSrcDirBrowseButton: TButton;
107 FPCSrcDirComboBox: TComboBox;
108 FPCSrcDirLabel: TLabel;
109 FPCSrcDirMemo: TMemo;
110 ImageList1: TImageList;
111 LazarusTabSheet: TTabSheet;
112 LazDirBrowseButton: TButton;
113 LazDirComboBox: TComboBox;
114 LazDirLabel: TLabel;
115 LazDirMemo: TMemo;
116 MakeExeBrowseButton: TButton;
117 MakeExeComboBox: TComboBox;
118 MakeExeLabel: TLabel;
119 MakeExeMemo: TMemo;
120 MakeExeTabSheet: TTabSheet;
121 PropertiesPageControl: TPageControl;
122 PropertiesTreeView: TTreeView;
123 ScanLabel: TLabel;
124 ScanProgressBar: TProgressBar;
125 Splitter1: TSplitter;
126 StartIDEBitBtn: TBitBtn;
127 StopScanButton: TBitBtn;
128 WelcomePaintBox: TPaintBox;
129 FppkgTabSheet: TTabSheet;
130 FppkgComboBox: TComboBox;
131 FppkgLabel: TLabel;
132 FppkgBrowseButton: TButton;
133 FppkgMemo: TMemo;
134 FppkgWriteConfigButton: TButton;
135 procedure CompilerBrowseButtonClick(Sender: TObject);
136 procedure CompilerComboBoxChange(Sender: TObject);
137 procedure CompilerComboBoxExit(Sender: TObject);
138 procedure DebuggerBrowseButtonClick(Sender: TObject);
139 procedure DebuggerComboBoxChange(Sender: TObject);
140 procedure FormCreate(Sender: TObject);
141 procedure FormDestroy(Sender: TObject);
142 procedure FPCSrcDirBrowseButtonClick(Sender: TObject);
143 procedure FPCSrcDirComboBoxChange(Sender: TObject);
144 procedure LazDirBrowseButtonClick(Sender: TObject);
145 procedure LazDirComboBoxChange(Sender: TObject);
146 procedure MakeExeBrowseButtonClick(Sender: TObject);
147 procedure MakeExeComboBoxChange(Sender: TObject);
148 procedure OnAppActivate(Sender: TObject);
149 procedure PropertiesPageControlChange(Sender: TObject);
150 procedure PropertiesTreeViewSelectionChanged(Sender: TObject);
151 procedure StartIDEBitBtnClick(Sender: TObject);
152 procedure StopScanButtonClick(Sender: TObject);
153 procedure WelcomePaintBoxPaint(Sender: TObject);
154 procedure OnIdle(Sender: TObject; var {%H-}Done: Boolean);
155 procedure FppkgComboBoxChange(Sender: TObject);
156 procedure FppkgBrowseButtonClick(Sender: TObject);
157 procedure FppkgWriteConfigButtonClick(Sender: TObject);
158 private
159 FSkipDebugger: Boolean;
160 FFlags: TSDFlags;
161 FLastParsedLazDir: string;
162 fLastParsedCompiler: string;
163 fLastParsedFPCSrcDir: string;
164 fLastParsedMakeExe: string;
165 fLastParsedDebugger: string;
166 fLastParsedFppkgConfigFile: string;
167 FIdleConnected: boolean;
168 ImgIDError: LongInt;
169 ImgIDWarning: LongInt;
170 FHeadGraphic: TPortableNetworkGraphic;
171 FInitialDebuggerFileName: String;
172 FSelectingPage: boolean;
173 FCandidates: array[TSDFilenameType] of TSDFileInfoList; // list of TSDFileInfo
174 fSearchFpcSourceThread: TSearchFpcSourceThread;
175 procedure UpdateCaptions;
176 procedure SelectPage(const NodeText: string);
SelectDirectorynull177 function SelectDirectory(aTitle: string): string;
SelectDirectorynull178 function SelectDirectory(aTitle: string; aPathFileName: string;
179 aEnvOptParseType: TEnvOptParseType): string; overload;
180 procedure StartFPCSrcThread;
181 procedure UpdateLazarusDirCandidates;
182 procedure UpdateCompilerFilenameCandidates;
183 procedure UpdateFPCSrcDirCandidates;
184 procedure UpdateFPCSrcDirCandidate(aFPCSrcDirInfo: TSDFileInfo);
185 procedure UpdateMakeExeCandidates(aStopIfFits: boolean = False);
186 procedure UpdateDebuggerCandidates;
187 procedure UpdateFppkgCandidates;
188 procedure FillComboboxWithFileInfoList(ABox: TComboBox; List: TSDFileInfoList;
189 ItemIndex: integer = 0);
190 procedure SetIdleConnected(const AValue: boolean);
191 procedure UpdateLazDirNote;
192 procedure UpdateCompilerNote(aQuiet: boolean = False);
193 procedure UpdateFPCSrcDirNote;
194 procedure UpdateMakeExeNote;
195 procedure UpdateDebuggerNote;
196 procedure UpdateFppkgNote;
FirstErrorNodenull197 function FirstErrorNode: TTreeNode;
FirstWarningNodenull198 function FirstWarningNode: TTreeNode;
GetFirstCandidatenull199 function GetFirstCandidate(Candidates: TSDFileInfoList;
200 MinQuality: TSDFilenameQuality = sddqCompatible): TSDFileInfo;
QualityToImgIndexnull201 function QualityToImgIndex(Quality: TSDFilenameQuality): integer;
202 procedure ShowHideScanControls(aShow: Boolean);
203 procedure ThreadTerminated(Sender: TObject); // called in main thread by fSearchFpcSourceThread.OnTerminate
204 procedure TranslateResourceStrings;
205 public
206 TVNodeLazarus: TTreeNode;
207 TVNodeCompiler: TTreeNode;
208 TVNodeFPCSources: TTreeNode;
209 TVNodeMakeExe: TTreeNode;
210 TVNodeDebugger: TTreeNode;
211 TVNodeFppkg: TTreeNode;
212 procedure Init; //Check for config errors, find and show alternatives
213 property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
214 end;
215
216
ShowInitialSetupDialognull217 function ShowInitialSetupDialog: TModalResult;
218
219 // Debugger
220 // Checks a given file to see if it is a valid debugger (only gdb supported for now)
CheckDebuggerQualitynull221 function CheckDebuggerQuality(AFilename: string; out Note: string; ASkip: Boolean = False): TSDFilenameQuality;
222 // Search debugger candidates and add them to list, including quality level
SearchDebuggerCandidatesnull223 function SearchDebuggerCandidates(StopIfFits: boolean): TSDFileInfoList;
224
225 implementation
226
227 const
228 DefaultDebuggerClass: TDebuggerClass = TGDBMIDebugger;
229
230 type
231
232 { TSetupMacros }
233
234 TSetupMacros = class(TTransferMacroList)
235 protected
236 procedure DoSubstitution({%H-}TheMacro: TTransferMacro; const MacroName: string;
237 var s: string; const {%H-}Data: PtrInt; var Handled, {%H-}Abort: boolean;
238 {%H-}Depth: integer); override;
239 public
240 FPCVer: string;
241 LazarusDir: string;
242 end;
243
CheckDebuggerQualitynull244 function CheckDebuggerQuality(AFilename: string; out Note: string;
245 ASkip: Boolean): TSDFilenameQuality;
246 begin
247 Note := '';
248 Result:=sddqCompatible;
249 if ASkip and // assume compatible
250 ( (EnvironmentOptions.CurrentDebuggerPropertiesConfig = nil) or
251 (EnvironmentOptions.CurrentDebuggerPropertiesConfig.DebuggerFilename = AFilename) // unless the user edited the filename
252 )
253 then
254 exit;
255 Result:=sddqInvalid;
256 AFilename:=TrimFilename(AFilename);
257 if not FileExistsCached(AFilename) then
258 begin
259 Note:=lisFileNotFound4;
260 exit;
261 end;
262 if DirPathExistsCached(AFilename) then
263 begin
264 Note:=lisFileIsDirectory;
265 exit;
266 end;
267 if not FileIsExecutableCached(AFilename) then
268 begin
269 Note:=lisFileIsNotAnExecutable;
270 exit;
271 end;
272
273 { We could call gdb and parse the output looking for something like
274 GNU gdb, but that may be going too far. }
275 Note:=lisOk;
276 Result:=sddqCompatible;
277 end;
278
SearchDebuggerCandidatesnull279 function SearchDebuggerCandidates(StopIfFits: boolean): TSDFileInfoList;
280
CheckFilenull281 function CheckFile(AFilename: string; var List: TSDFileInfoList): boolean;
282 var
283 Item: TSDFileInfo;
284 RealFilename: String;
285 begin
286 Result:=false;
287 if AFilename='' then exit;
288 ForcePathDelims(AFilename);
289 // check if already checked
290 if Assigned(List) and List.CaptionExists(AFilename) then exit;
291 RealFilename:=EnvironmentOptions.GetParsedValue(eopDebuggerFilename, AFilename);
292 debugln(['SearchDebuggerCandidates Value=',AFilename,' File=',RealFilename]);
293 if RealFilename='' then exit;
294 // check if exists
295 if not FileExistsCached(RealFilename) then exit;
296 // add to list and check quality
297 if List=nil then
298 List:=TSDFileInfoList.create(true);
299 Item:=List.AddNewItem(RealFilename, AFilename);
300 Item.Quality:=CheckDebuggerQuality(RealFilename, Item.Note);
301 Result:=(Item.Quality=sddqCompatible) and StopIfFits;
302 end;
303
304 const
305 DebuggerFileName='gdb'; //For Windows, .exe will be appended
306 var
307 s, AFilename, XmlClassName, CurDbgClassName: String;
308 Files: TStringList;
309 i: Integer;
310 begin
311 Result:=nil;
312
313 // check current setting
314 if CheckFile(EnvironmentOptions.DebuggerFilename,Result) then exit;
315
316 if EnvironmentOptions.CurrentDebuggerPropertiesConfig <> nil then
317 CurDbgClassName := UpperCase(EnvironmentOptions.CurrentDebuggerPropertiesConfig.ConfigClass)
318 else
319 CurDbgClassName := UpperCase(DefaultDebuggerClass.ClassName);
320
321 // check the primary options
322 XmlClassName :=GetValueFromPrimaryConfig(EnvOptsConfFileName,
323 'EnvironmentOptions/Debugger/Class');
324 if UpperCase(XmlClassName) = CurDbgClassName then begin
325 AFilename:=GetValueFromPrimaryConfig(EnvOptsConfFileName,
326 'EnvironmentOptions/DebuggerFilename/Value');
327 if CheckFile(AFilename,Result) then exit;
328 end;
329
330 // check the secondary options
331 XmlClassName :=GetValueFromSecondaryConfig(EnvOptsConfFileName,
332 'EnvironmentOptions/Debugger/Class');
333 if UpperCase(XmlClassName) = CurDbgClassName then begin
334 AFilename:=GetValueFromSecondaryConfig(EnvOptsConfFileName,
335 'EnvironmentOptions/DebuggerFilename/Value');
336 if CheckFile(AFilename,Result) then exit;
337 end;
338
339 // Check locations proposed by debugger class
340 if EnvironmentOptions.CurrentDebuggerClass <> nil then
341 s := EnvironmentOptions.CurrentDebuggerClass.ExePaths
342 else
343 s := DefaultDebuggerClass.ExePaths;
344 while s <> '' do begin
345 AFilename := GetPart([], [';'], s);
346 if CheckFile(AFilename, Result) then exit;
347 if s <> '' then delete(s, 1, 1);
348 end;
349
350 // Search for gdb
351 // only if TGDBMIDebugger
352 if CurDbgClassName = UpperCase(DefaultDebuggerClass.ClassName) then begin
353
354 // Windows-only locations:
355 if (GetDefaultSrcOSForTargetOS(GetCompiledTargetOS)='win') then begin
356 // check for debugger in fpc.exe directory - could be a lucky shot
357 if CheckFile(GetForcedPathDelims('$Path($(CompPath))/'+DebuggerFileName+GetExecutableExt),Result)
358 then exit;
359 end;
360
361 // check history
362 Files:=EnvironmentOptions.DebuggerFileHistory[CurDbgClassName];
363 if (Files=nil) or (Files.Count=0) then
364 Files:=EnvironmentOptions.DebuggerFileHistory[''];
365 if Files<>nil then
366 for i:=0 to Files.Count-1 do
367 if CheckFile(Files[i],Result) then exit;
368
369 // check PATH
370 AFilename:=DebuggerFileName+GetExecutableExt;
371 if CheckFile(AFilename,Result) then exit;
372 end;
373
374 // There are no common directories apart from the PATH
375 // where gdb would be installed. Otherwise we could do something similar as
376 // in SearchMakeExeCandidates.
377 end;
378
ShowInitialSetupDialognull379 function ShowInitialSetupDialog: TModalResult;
380 var
381 InitialSetupDialog: TInitialSetupDialog;
382 begin
383 InitialSetupDialog:=TInitialSetupDialog.Create(nil);
384 try
385 Application.TaskBarBehavior:=tbMultiButton;
386 InitialSetupDialog.Init;
387 Result:=InitialSetupDialog.ShowModal;
388 finally
389 InitialSetupDialog.Free;
390 Application.TaskBarBehavior:=tbDefault;
391 end;
392 end;
393
394 { TSearchFpcSourceThread }
395
396 constructor TSearchFpcSourceThread.Create(aSetupDialog: TInitialSetupDialog);
397 begin
398 inherited Create(True);
399 FreeOnTerminate:=True;
400 fSetupDialog:=aSetupDialog;
401 end;
402
403 destructor TSearchFpcSourceThread.Destroy;
404 begin
405 inherited Destroy;
406 end;
407
408 procedure TSearchFpcSourceThread.Execute;
409 var
410 RootDir: String;
411 begin
412 // ToDo: RootDir must be changed for Windows and maybe other systems.
413 // GetUserDir returns the user profile dir on Windows.
414 RootDir:=GetUserDir;
415 // Scan directories under root directory.
416 DoSearch(AppendPathDelim(RootDir));
417 if Assigned(fFoundFPCSrc) then
418 Synchronize(@UpdateFPCSrcDir); // Update GUI in main thread.
419 Synchronize(@Finishing);
420 end;
421
TSearchFpcSourceThread.CheckFPCSrcDirnull422 function TSearchFpcSourceThread.CheckFPCSrcDir(Dir: string): TSDFileInfo;
423 var
424 RealDir: String;
425 begin
426 Result:=Nil;
427 RealDir:=TrimFilename(Dir);
428 if RealDir='' then exit;
429 if not DirPathExistsCached(RealDir) then exit; // check if exists
430 Result:=TSDFileInfo.Create;
431 Result.Filename:=RealDir;
432 Result.Caption:=Dir; // check quality
433 Result.Quality:=CheckFPCSrcDirQuality(RealDir, Result.Note, fFPCVer, False);
434 if Result.Quality<>sddqCompatible then // return only exact matches
435 FreeAndNil(Result);
436 end;
437
438 procedure TSearchFpcSourceThread.DoSearch(const APath: String);
439 var
440 PathInfo: TSearchRec;
441 FPCSrc: TSDFileInfo;
442 begin
443 if FindFirstUTF8(APath+AllDirectoryEntriesMask, faDirectory, PathInfo) = 0 then
444 try
445 repeat
446 if Terminated then Break;
447 if (PathInfo.Name='') or (PathInfo.Name[1]='.')
448 or ((PathInfo.Attr and faDirectory) = 0) then Continue;
449 {$IFDEF VerboseFPCSrcScanThead}
450 fPath := APath;
451 fFileInfo := PathInfo;
452 Synchronize(@Debug);
453 {$ENDIF}
454 DoSearch(AppendPathDelim(APath+PathInfo.Name)); // Recursive call
455 FPCSrc:=CheckFPCSrcDir(APath+PathInfo.Name);
456 if Assigned(FPCSrc) then begin
457 fFoundFPCSrc:=FPCSrc; // An exact match was found.
458 Terminate;
459 end;
460 until (FindNextUTF8(PathInfo) <> 0);
461 finally
462 FindCloseUTF8(PathInfo);
463 end;
464 end;
465
466 {$IFDEF VerboseFPCSrcScanThead}
467 procedure TSearchFpcSourceThread.Debug;
468 begin
469 DebugLn(['* TSearchFpcSourceThread.Debug: Path=', fPath, ', Name=', fFileInfo.Name]);
470 end;
471 {$ENDIF}
472
473 procedure TSearchFpcSourceThread.UpdateFPCSrcDir;
474 begin
475 DebugLn(['TSearchFpcSourceThread.UpdateFPCSrcDir']);
476 fSetupDialog.UpdateFPCSrcDirCandidate(fFoundFPCSrc);
477 fSetupDialog.UpdateFPCSrcDirNote;
478 end;
479
480 procedure TSearchFpcSourceThread.Finishing;
481 begin
482 DebugLn(['TSearchFpcSourceThread.Finishing']);
483 fSetupDialog.ShowHideScanControls(False); // Hide scan controls
484 end;
485
486 { TSetupMacros }
487
488 procedure TSetupMacros.DoSubstitution(TheMacro: TTransferMacro;
489 const MacroName: string; var s: string; const Data: PtrInt; var Handled,
490 Abort: boolean; Depth: integer);
491 begin
492 Handled:=true;
493 if CompareText(MacroName,'ENV')=0 then
494 s:=GetEnvironmentVariableUTF8(MacroName)
495 else if CompareText(MacroName,'PrimaryConfigPath')=0 then
496 s:=GetPrimaryConfigPath
497 else if CompareText(MacroName,'SecondaryConfigPath')=0 then
498 s:=GetSecondaryConfigPath
499 else if CompareText(MacroName,'FPCVer')=0 then begin
500 if FPCVer<>'' then
501 s:=FPCVer
502 else
503 s:={$I %FPCVERSION%};
504 end else if CompareText(MacroName,'LazarusDir')=0 then begin
505 if LazarusDir<>'' then
506 s:=LazarusDir
507 else
508 s:='<LazarusDirNotSet>';
509 end else if (CompareText(MacroName,'TargetOS')=0) then
510 s:=GetCompiledTargetOS
511 else if (CompareText(MacroName,'TargetCPU')=0) then
512 s:=GetCompiledTargetCPU
513 else if (CompareText(MacroName,'SrcOS')=0) then
514 s:=GetDefaultSrcOSForTargetOS(GetCompiledTargetOS)
515 else
516 Handled:=false;
517 //debugln(['TSetupMacros.DoSubstitution MacroName=',MacroName,' Value="',s,'"']);
518 end;
519
520 {$R *.lfm}
521
522 { TInitialSetupDialog }
523
524 procedure TInitialSetupDialog.FormCreate(Sender: TObject);
525 begin
526 LazarusTabSheet.Caption:='Lazarus';
527 CompilerTabSheet.Caption:=lisCompiler;
528 FPCSourcesTabSheet.Caption:=lisFPCSources;
529 MakeExeTabSheet.Caption:='Make';
530 DebuggerTabSheet.Caption:=lisDebugger;
531 FppkgTabSheet.Caption := 'Fppkg';
532
533 FHeadGraphic:=TPortableNetworkGraphic.Create;
534 FHeadGraphic.LoadFromResourceName(HInstance, 'ide_icon48x48');
535
536 TVNodeLazarus:=PropertiesTreeView.Items.Add(nil,LazarusTabSheet.Caption);
537 TVNodeCompiler:=PropertiesTreeView.Items.Add(nil,CompilerTabSheet.Caption);
538 TVNodeFPCSources:=PropertiesTreeView.Items.Add(nil,FPCSourcesTabSheet.Caption);
539 TVNodeMakeExe:=PropertiesTreeView.Items.Add(nil,MakeExeTabSheet.Caption);
540 TVNodeDebugger:=PropertiesTreeView.Items.Add(nil,DebuggerTabSheet.Caption);
541 {$IF FPC_FULLVERSION>30100}
542 TVNodeFppkg:=PropertiesTreeView.Items.Add(nil,FppkgTabSheet.Caption);
543 FppkgTabSheet.TabVisible := True;
544 {$ELSE}
545 FppkgTabSheet.TabVisible := False;
546 {$ENDIF FPC_FULLVERSION>30100}
547 ImgIDError := Imagelist1.AddResourceName(HInstance, 'state_error');
548 ImgIDWarning := Imagelist1.AddResourceName(HInstance, 'state_warning');
549
550 IDEImages.AssignImage(StopScanButton, 'menu_stop');
551
552 UpdateCaptions;
553
554 Application.AddOnActivateHandler(@OnAppActivate);
555 end;
556
557 procedure TInitialSetupDialog.CompilerComboBoxChange(Sender: TObject);
558 begin
559 UpdateCompilerNote({Quiet} True);
560 UpdateFPCSrcDirNote;
561 end;
562
563 procedure TInitialSetupDialog.CompilerComboBoxExit(Sender: TObject);
564 begin
565 UpdateCompilerNote({Quiet} False);
566 UpdateFPCSrcDirNote;
567 end;
568
569 procedure TInitialSetupDialog.DebuggerBrowseButtonClick(Sender: TObject);
570 var
571 lExpandedName: string; // Expanded name before Dialog
572 lDirName, lFileName: string;
573 lTitle: string;
574 lChanged: boolean=False;
575 Dlg: TIDEOpenDialog;
576 Filter: String;
577 begin
578 Dlg:=IDEOpenDialogClass.Create(nil);
579 try
580 lTitle := 'gdb'+GetExecutableExt;
581 Dlg.Title := SimpleFormat(lisSelectPathTo, [lTitle]);
582 lExpandedName := EnvironmentOptions.GetParsedValue(eopDebuggerFilename, DebuggerComboBox.Text);
583 lDirName := GetValidDirectory(lExpandedName, {out} lFileName);
584 Dlg.Options := Dlg.Options+[ofFileMustExist];
585 if lFileName='' then
586 lFileName := lTitle;
587 Filter := dlgFilterAll+'|'+GetAllFilesMask;
588 if ExtractFileExt(lFileName)<>'' then
589 Filter := dlgFilterExecutable+'|*'+ExtractFileExt(lFileName)+'|'+Filter;
590 Dlg.Filter := Filter;
591 Dlg.InitialDir := lDirName;
592 Dlg.FileName := lFileName;
593 if not Dlg.Execute then
594 exit;
595 lFileName := CleanAndExpandFilename(Dlg.Filename);
596 lChanged := UpperCase(lExpandedName)<>UpperCase(lFileName);
597 finally
598 Dlg.Free;
599 end;
600 if lChanged then begin // Avoid loosing $(macros)
601 DebuggerComboBox.Text := lFileName;
602 UpdateDebuggerNote;
603 end;
604 end;
605
606 procedure TInitialSetupDialog.DebuggerComboBoxChange(Sender: TObject);
607 begin
608 UpdateDebuggerNote;
609 end;
610
611 procedure TInitialSetupDialog.CompilerBrowseButtonClick(Sender: TObject);
612 var
613 lExpandedName: string; // Expanded name before Dialog
614 lDirName, lFileName: string;
615 lTitle: string;
616 lChanged: boolean=False;
617 Dlg: TIDEOpenDialog;
618 Filter: String;
619 begin
620 Dlg := IDEOpenDialogClass.Create(nil);
621 try
622 lTitle := 'fpc'+GetExecutableExt;
623 Dlg.Title := SimpleFormat(lisSelectPathTo, [lTitle]);
624 lExpandedName := EnvironmentOptions.GetParsedValue(eopCompilerFilename, CompilerComboBox.Text);
625 lDirName := GetValidDirectory(lExpandedName, {out} lFileName);
626 Dlg.Options := Dlg.Options+[ofFileMustExist];
627 if lFileName='' then
628 lFileName := lTitle;
629 Filter := dlgFilterAll+'|'+GetAllFilesMask;
630 if ExtractFileExt(lFileName)<>'' then
631 Filter := dlgFilterExecutable+'|*'+ExtractFileExt(lFileName)+'|'+Filter;
632 Dlg.Filter := Filter;
633 Dlg.InitialDir := lDirName;
634 Dlg.FileName := lFileName;
635 if not Dlg.Execute then
636 exit;
637 lFileName := CleanAndExpandFilename(Dlg.Filename);
638 lChanged := UpperCase(lExpandedName)<>UpperCase(lFileName);
639 finally
640 Dlg.Free;
641 end;
642 if lChanged then begin // Avoid loosing $(macros)
643 CompilerComboBox.Text := lFileName;
644 UpdateCompilerNote;
645 end;
646 end;
647
648 procedure TInitialSetupDialog.FormDestroy(Sender: TObject);
649 var
650 d: TSDFilenameType;
651 begin
652 IdleConnected:=false;
653 if Assigned(fSearchFpcSourceThread) then begin
654 fSearchFpcSourceThread.Terminate;
655 fSearchFpcSourceThread.WaitFor;
656 end;
657 for d:=low(FCandidates) to high(FCandidates) do
658 FreeAndNil(FCandidates[d]);
659 FreeAndNil(FHeadGraphic);
660 end;
661
662 procedure TInitialSetupDialog.FPCSrcDirBrowseButtonClick(Sender: TObject);
663 var
664 Dir: String;
665 begin
666 Dir:=SelectDirectory(lisSelectFPCSourceDirectory, FPCSrcDirComboBox.Text,eopFPCSourceDirectory);
667 if Dir='' then
668 exit;
669 FPCSrcDirComboBox.Text:=Dir;
670 UpdateFPCSrcDirNote;
671 end;
672
673 procedure TInitialSetupDialog.FPCSrcDirComboBoxChange(Sender: TObject);
674 begin
675 UpdateFPCSrcDirNote;
676 end;
677
678 procedure TInitialSetupDialog.LazDirBrowseButtonClick(Sender: TObject);
679 var
680 Dir: String;
681 begin
682 Dir:=SelectDirectory(lisSelectLazarusSourceDirectory,LazDirComboBox.Text,eopLazarusDirectory);
683 if Dir='' then
684 exit;
685 LazDirComboBox.Text:=Dir;
686 UpdateLazDirNote;
687 end;
688
689 procedure TInitialSetupDialog.LazDirComboBoxChange(Sender: TObject);
690 begin
691 UpdateLazDirNote;
692 end;
693
694 procedure TInitialSetupDialog.MakeExeBrowseButtonClick(Sender: TObject);
695 var
696 lExpandedName: string; // Expanded name before Dialog
697 lDirName, lFileName: string;
698 lTitle: string;
699 lChanged: boolean=False;
700 Dlg: TIDEOpenDialog;
701 Filter: String;
702
703 begin
704 Dlg := IDEOpenDialogClass.Create(nil);
705 try
706 lTitle := 'make'+GetExecutableExt;
707 Dlg.Title := SimpleFormat(lisSelectPathTo, [lTitle]);
708 lExpandedName := EnvironmentOptions.GetParsedValue(eopMakeFilename, MakeExeComboBox.Text);
709 lDirName := GetValidDirectory(lExpandedName, {out} lFileName);
710 Dlg.Options := Dlg.Options+[ofFileMustExist];
711 if lFileName='' then
712 lFileName := lTitle;
713 Filter := dlgFilterAll+'|'+GetAllFilesMask;
714 if ExtractFileExt(lFileName)<>'' then
715 Filter := dlgFilterExecutable+'|*'+ExtractFileExt(lFileName)+'|'+Filter;
716 Dlg.Filter := Filter;
717 Dlg.InitialDir := lDirName;
718 Dlg.FileName := lFileName;
719 if not Dlg.Execute then
720 exit;
721 lFileName := CleanAndExpandFilename(Dlg.Filename);
722 lChanged := UpperCase(lExpandedName)<>UpperCase(lFileName);
723 finally
724 Dlg.Free;
725 end;
726 if lChanged then begin // Avoid loosing $(macros)
727 MakeExeComboBox.Text := lFileName;
728 UpdateMakeExeNote;
729 end;
730 end;
731
732 procedure TInitialSetupDialog.MakeExeComboBoxChange(Sender: TObject);
733 begin
734 UpdateMakeExeNote;
735 end;
736
737 procedure TInitialSetupDialog.OnAppActivate(Sender: TObject);
738 begin
739 // switched back from another application
740 InvalidateFileStateCache;
741 end;
742
743 procedure TInitialSetupDialog.PropertiesPageControlChange(Sender: TObject);
744 var
745 s: String;
746 i: Integer;
747 begin
748 if PropertiesPageControl.ActivePage=nil then exit;
749 s:=PropertiesPageControl.ActivePage.Caption;
750 for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do
751 if PropertiesTreeView.Items.TopLvlItems[i].Text=s then
752 PropertiesTreeView.Selected:=PropertiesTreeView.Items.TopLvlItems[i];
753 end;
754
755 procedure TInitialSetupDialog.PropertiesTreeViewSelectionChanged(Sender: TObject);
756 begin
757 if PropertiesTreeView.Selected=nil then
758 SelectPage(TVNodeLazarus.Text)
759 else
760 SelectPage(PropertiesTreeView.Selected.Text);
761 end;
762
763 procedure TInitialSetupDialog.StartIDEBitBtnClick(Sender: TObject);
764 var
765 Node: TTreeNode;
766 s: String;
767 MsgResult: TModalResult;
768 begin
769 Node:=FirstErrorNode;
770 s:='';
771 if Node=TVNodeLazarus then
772 s:=lisWithoutAProperLazarusDirectoryYouWillGetALotOfWarn
773 else if Node=TVNodeCompiler then
774 s:=lisWithoutAProperCompilerTheCodeBrowsingAndCompilingW
775 else if Node=TVNodeFPCSources then
776 s:=lisWithoutTheProperFPCSourcesCodeBrowsingAndCompletio
777 else if Node=TVNodeMakeExe then
778 s:=lisWithoutAProperMakeExecutableTheCompilingOfTheIDEIs
779 else if Node=TVNodeDebugger then
780 s:=lisWithoutAProperDebuggerDebuggingWillBeDisappointing;
781 if s<>'' then begin
782 MsgResult:=MessageDlg(lisCCOWarningCaption, s, mtWarning, [mbIgnore,
783 mbCancel], 0);
784 if MsgResult<>mrIgnore then exit;
785 end;
786
787 s:=LazDirComboBox.Text;
788 if s<>'' then
789 EnvironmentOptions.LazarusDirectory:=s;
790 s:=CompilerComboBox.Text;
791 if s<>'' then
792 EnvironmentOptions.CompilerFilename:=s;
793 s:=FPCSrcDirComboBox.Text;
794 if s<>'' then
795 EnvironmentOptions.FPCSourceDirectory:=s;
796 s:=MakeExeComboBox.Text;
797 if s<>'' then
798 EnvironmentOptions.MakeFilename:=s;
799 if not (FSkipDebugger and (EnvironmentOptions.CurrentDebuggerPropertiesConfig <> nil))
800 then begin
801 s:=DebuggerComboBox.Text;
802 if s<>'' then begin
803 EnvironmentOptions.CurrentDebuggerPropertiesConfig.DebuggerFilename:=s;
804 EnvironmentOptions.SaveDebuggerPropertiesList; // Update XML
805 end;
806 end;
807
808 ModalResult:=mrOk;
809 end;
810
811 procedure TInitialSetupDialog.StopScanButtonClick(Sender: TObject);
812 begin
813 if fSearchFpcSourceThread<>nil then
814 fSearchFpcSourceThread.Terminate;
815 end;
816
817 procedure TInitialSetupDialog.WelcomePaintBoxPaint(Sender: TObject);
818 begin
819 with WelcomePaintBox.Canvas do begin
820 GradientFill(WelcomePaintBox.ClientRect,$854b32,$c88e60,gdHorizontal);
821 Draw(0,WelcomePaintBox.ClientHeight-FHeadGraphic.Height,FHeadGraphic);
822 Font.Color:=clWhite;
823 Font.Height:=30;
824 Brush.Style:=bsClear;
825 TextOut(FHeadGraphic.Width+15, 5, lisConfigureLazarusIDE);
826 end;
827 end;
828
829 procedure TInitialSetupDialog.OnIdle(Sender: TObject; var Done: Boolean);
830 begin
831 if sdfCompilerFilenameNeedsUpdate in FFlags then begin
832 UpdateCompilerFilenameCandidates;
833 UpdateCompilerNote;
834 end else if sdfFPCSrcDirNeedsUpdate in FFlags then begin
835 UpdateFPCSrcDirCandidates;
836 UpdateFPCSrcDirNote;
837 end else if sdfMakeExeFilenameNeedsUpdate in FFlags then begin
838 UpdateMakeExeCandidates;
839 UpdateMakeExeNote;
840 end else if sdfDebuggerFilenameNeedsUpdate in FFlags then begin
841 UpdateDebuggerCandidates;
842 UpdateDebuggerNote;
843 end else if sdfFppkgConfigFileNeedsUpdate in FFlags then begin
844 fLastParsedFppkgConfigFile := ' ';
845 UpdateFppkgCandidates;
846 UpdateFppkgNote;
847 end else
848 IdleConnected:=false;
849 end;
850
851 procedure TInitialSetupDialog.UpdateCaptions;
852 var
853 s: String;
854 begin
855 Caption:=SimpleFormat(lisWelcomeToLazarusIDE, [GetLazarusVersionString]);
856
857 StartIDEBitBtn.Caption:=lisStartIDE;
858
859 LazarusTabSheet.Caption:='Lazarus';
860 CompilerTabSheet.Caption:=lisCompiler;
861 FPCSourcesTabSheet.Caption:=lisFPCSources;
862 MakeExeTabSheet.Caption:='Make';
863 DebuggerTabSheet.Caption:=lisDebugger;
864 FppkgTabSheet.Caption:='Fppkg';
865
866 TVNodeLazarus.Text:=LazarusTabSheet.Caption;
867 TVNodeCompiler.Text:=CompilerTabSheet.Caption;
868 TVNodeFPCSources.Text:=FPCSourcesTabSheet.Caption;
869 TVNodeMakeExe.Text:=MakeExeTabSheet.Caption;
870 TVNodeDebugger.Text:=DebuggerTabSheet.Caption;
871 {$IF FPC_FULLVERSION>30100}
872 TVNodeFppkg.Text:=FppkgTabSheet.Caption;
873 {$ENDIF FPC_FULLVERSION>30100}
874
875 LazDirBrowseButton.Caption:=lisPathEditBrowse;
876 LazDirLabel.Caption:=SimpleFormat(
877 lisTheLazarusDirectoryContainsTheSourcesOfTheIDEAndTh, [PathDelim]);
878
879 FppkgLabel.Caption:=lisFppkgConfiguration;
880 FppkgBrowseButton.Caption:=lisPathEditBrowse;
881 FppkgWriteConfigButton.Caption:=lisCreateFppkgConfig;
882
883 CompilerBrowseButton.Caption:=lisPathEditBrowse;
884 CompilerLabel.Caption:=SimpleFormat(lisTheFreePascalCompilerExecutableTypicallyHasTheName,
885 [DefineTemplates.GetDefaultCompilerFilename,
886 DefineTemplates.GetDefaultCompilerFilename(GetCompiledTargetCPU)]);
887
888 FPCSrcDirBrowseButton.Caption:=lisPathEditBrowse;
889 FPCSrcDirLabel.Caption:=SimpleFormat(lisTheSourcesOfTheFreePascalPackagesAreRequiredForBro,
890 [GetForcedPathDelims('rtl/linux/system.pp')]);
891 ScanLabel.Caption := lisScanning;
892 StopScanButton.Caption:=lisStop;
893
894 MakeExeBrowseButton.Caption:=lisPathEditBrowse;
895 MakeExeLabel.Caption:=SimpleFormat(
896 lisTheMakeExecutableTypicallyHasTheName, ['make'+GetExecutableExt('')]);
897
898 DebuggerBrowseButton.Caption:=lisPathEditBrowse;
899 s:=SimpleFormat(lisTheDebuggerExecutableTypicallyHasTheNamePleaseGive, [
900 'gdb'+GetExecutableExt]);
901 {$IFDEF Windows}
902 s+=' '+lisAUsefulSettingOnWindowsSystemsIsLazarusDirMingwBin;
903 {$ENDIF}
904 DebuggerLabel.Caption:=s;
905 end;
906
907 procedure TInitialSetupDialog.SelectPage(const NodeText: string);
908 var
909 i: Integer;
910 Node: TTreeNode;
911 begin
912 if FSelectingPage then exit;
913 FSelectingPage:=true;
914 try
915 for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do begin
916 Node:=PropertiesTreeView.Items.TopLvlItems[i];
917 if Node.Text=NodeText then begin
918 PropertiesTreeView.Selected:=Node;
919 PropertiesPageControl.ActivePageIndex:=i;
920 break;
921 end;
922 end;
923 finally
924 FSelectingPage:=false;
925 end;
926 end;
927
TInitialSetupDialog.SelectDirectorynull928 function TInitialSetupDialog.SelectDirectory(aTitle: string): string;
929 var
930 DirDlg: TSelectDirectoryDialog;
931 begin
932 Result:='';
933 DirDlg:=TSelectDirectoryDialog.Create(nil);
934 try
935 DirDlg.Title:=aTitle;
936 DirDlg.Options:=DirDlg.Options+[ofPathMustExist,ofFileMustExist];
937 if not DirDlg.Execute then exit;
938 Result:=DirDlg.FileName;
939 finally
940 DirDlg.Free;
941 end;
942 end;
943
TInitialSetupDialog.SelectDirectorynull944 function TInitialSetupDialog.SelectDirectory(aTitle: string;
945 aPathFileName: string; aEnvOptParseType: TEnvOptParseType): string;
946 var
947 DirDlg: TSelectDirectoryDialog;
948 lCurDirName: string;
949 lDirPath: string;
950 lDirName: string;
951 begin
952 Result := '';
953 if aPathFileName='' then
954 case aEnvOptParseType of
955 eopLazarusDirectory: lDirPath := EnvironmentOptions.GetParsedLazarusDirectory;
956 eopFPCSourceDirectory: lDirPath := EnvironmentOptions.GetParsedFPCSourceDirectory;
957 end
958 else
959 lDirPath := EnvironmentOptions.GetParsedValue(eopLazarusDirectory, aPathFileName);
960 lCurDirName := CleanAndExpandFilename(ExcludeTrailingBackSlash(lDirPath));
961 lDirPath := GetValidDirectoryAndFilename(lCurDirName, {out} lDirName);
962 { ~bk
963 if lDirName = '' then begin
964 lDirName := ExtractFileName(lDirPath);
965 lDirPath := ExtractFilePath(lDirPath);
966 end;
967 }
968 lDirPath := ExcludeTrailingBackSlash(lDirPath);
969 DirDlg := TSelectDirectoryDialog.Create(nil);
970 try
971 DirDlg.Title := aTitle;
972 DirDlg.InitialDir := lDirPath;
973 DirDlg.FileName := lDirName;
974 DirDlg.Options := DirDlg.Options + [ofPathMustExist]; // ~bk, ofFileMustExist];
975 if DirDlg.Execute then begin
976 lDirName := CleanAndExpandFilename(DirDlg.FileName);
977 if UpperCase(lCurDirName)<>UpperCase(lDirName) then
978 Result := lDirName;
979 end;
980 finally
981 DirDlg.Free;
982 end;
983 end;
984
985 procedure TInitialSetupDialog.StartFPCSrcThread;
986 begin
987 fSearchFpcSourceThread:=TSearchFpcSourceThread.Create(Self);
988 fSearchFpcSourceThread.OnTerminate:=@ThreadTerminated;
989 fSearchFpcSourceThread.fFPCVer:=GetFPCVer;
990 ShowHideScanControls(True); // Show scan controls while thread is running
991 fSearchFpcSourceThread.Start;
992 end;
993
994 procedure TInitialSetupDialog.UpdateLazarusDirCandidates;
995 var
996 Dirs: TSDFileInfoList;
997 begin
998 Dirs:=SearchLazarusDirectoryCandidates(false);
999 FreeAndNil(FCandidates[sddtLazarusSrcDir]);
1000 FCandidates[sddtLazarusSrcDir]:=Dirs;
1001 FillComboboxWithFileInfoList(LazDirComboBox,Dirs);
1002 end;
1003
1004 procedure TInitialSetupDialog.UpdateCompilerFilenameCandidates;
1005 var
1006 Files: TSDFileInfoList;
1007 begin
1008 Exclude(FFlags,sdfCompilerFilenameNeedsUpdate);
1009 Files:=SearchFPCExeCandidates(false,CodeToolBoss.CompilerDefinesCache.TestFilename);
1010 FreeAndNil(FCandidates[sddtCompilerFilename]);
1011 FCandidates[sddtCompilerFilename]:=Files;
1012 FillComboboxWithFileInfoList(CompilerComboBox,Files);
1013 end;
1014
1015 procedure TInitialSetupDialog.UpdateFPCSrcDirCandidates;
1016 var
1017 Dirs: TSDFileInfoList;
1018 begin
1019 Exclude(FFlags,sdfFPCSrcDirNeedsUpdate);
1020 Dirs:=SearchFPCSrcDirCandidates(false,GetFPCVer);
1021 FreeAndNil(FCandidates[sddtFPCSrcDir]);
1022 FCandidates[sddtFPCSrcDir]:=Dirs;
1023 FillComboboxWithFileInfoList(FPCSrcDirComboBox,Dirs);
1024 end;
1025
1026 procedure TInitialSetupDialog.UpdateFPCSrcDirCandidate(aFPCSrcDirInfo: TSDFileInfo);
1027 var
1028 Dirs: TSDFileInfoList;
1029 begin
1030 Exclude(FFlags,sdfFPCSrcDirNeedsUpdate);
1031 FreeAndNil(FCandidates[sddtFPCSrcDir]);
1032 Dirs:=TSDFileInfoList.Create;
1033 Dirs.Add(aFPCSrcDirInfo);
1034 FCandidates[sddtFPCSrcDir]:=Dirs;
1035 FillComboboxWithFileInfoList(FPCSrcDirComboBox,Dirs);
1036 end;
1037
1038 procedure TInitialSetupDialog.UpdateMakeExeCandidates(aStopIfFits: boolean);
1039 var
1040 Files: TSDFileInfoList;
1041 begin
1042 Exclude(FFlags,sdfMakeExeFilenameNeedsUpdate);
1043 Files:=SearchMakeExeCandidates(aStopIfFits);
1044 FreeAndNil(FCandidates[sddtMakeExeFileName]);
1045 FCandidates[sddtMakeExeFileName]:=Files;
1046 FillComboboxWithFileInfoList(MakeExeComboBox,Files);
1047 end;
1048
1049 procedure TInitialSetupDialog.UpdateDebuggerCandidates;
1050 var
1051 Files: TSDFileInfoList;
1052 begin
1053 Exclude(FFlags,sdfDebuggerFilenameNeedsUpdate);
1054 Files:=SearchDebuggerCandidates(false);
1055 FreeAndNil(FCandidates[sddtDebuggerFilename]);
1056 FCandidates[sddtDebuggerFilename]:=Files;
1057 FillComboboxWithFileInfoList(DebuggerComboBox,Files);
1058 end;
1059
1060 procedure TInitialSetupDialog.FillComboboxWithFileInfoList(ABox: TComboBox;
1061 List: TSDFileInfoList; ItemIndex: integer);
1062 var
1063 sl: TStringList;
1064 i: Integer;
1065 begin
1066 sl:=TStringList.Create;
1067 try
1068 if List<>nil then
1069 for i:=0 to List.Count-1 do
1070 sl.Add(TSDFileInfo(List[i]).Caption);
1071 ABox.Items.Assign(sl);
1072 if (ItemIndex>=0) and (ItemIndex<sl.Count) then
1073 ABox.Text:=sl[ItemIndex]
1074 else if ABox.Text=ABox.Name then
1075 ABox.Text:='';
1076 finally
1077 sl.Free;
1078 end;
1079 end;
1080
1081 procedure TInitialSetupDialog.SetIdleConnected(const AValue: boolean);
1082 begin
1083 if FIdleConnected=AValue then exit;
1084 FIdleConnected:=AValue;
1085 if IdleConnected then
1086 Application.AddOnIdleHandler(@OnIdle)
1087 else
1088 Application.RemoveOnIdleHandler(@OnIdle);
1089 end;
1090
1091 procedure TInitialSetupDialog.UpdateLazDirNote;
1092 var
1093 CurCaption: String;
1094 Note: string;
1095 Quality: TSDFilenameQuality;
1096 s: String;
1097 ImageIndex: Integer;
1098 begin
1099 if csDestroying in ComponentState then exit;
1100 CurCaption:=LazDirComboBox.Text;
1101 CurCaption:=ChompPathDelim(CurCaption);
1102 EnvironmentOptions.LazarusDirectory:=CurCaption;
1103 if FLastParsedLazDir=EnvironmentOptions.GetParsedLazarusDirectory then exit;
1104 FLastParsedLazDir:=EnvironmentOptions.GetParsedLazarusDirectory;
1105 //debugln(['TInitialSetupDialog.UpdateLazDirNote ',FLastParsedLazDir]);
1106 Quality:=CheckLazarusDirectoryQuality(FLastParsedLazDir,Note);
1107 case Quality of
1108 sddqInvalid: s:=lisError;
1109 sddqCompatible: s:='';
1110 else s:=lisWarning;
1111 end;
1112 if EnvironmentOptions.LazarusDirectory<>EnvironmentOptions.GetParsedLazarusDirectory
1113 then
1114 s:=lisDirectory+EnvironmentOptions.GetParsedLazarusDirectory+LineEnding+
1115 LineEnding+s;
1116 LazDirMemo.Text:=s+Note;
1117
1118 ImageIndex:=QualityToImgIndex(Quality);
1119 TVNodeLazarus.ImageIndex:=ImageIndex;
1120 TVNodeLazarus.SelectedIndex:=ImageIndex;
1121
1122 FFlags:=FFlags+[sdfCompilerFilenameNeedsUpdate,sdfFPCSrcDirNeedsUpdate,
1123 sdfMakeExeFilenameNeedsUpdate,sdfDebuggerFilenameNeedsUpdate];
1124 IdleConnected:=true;
1125 end;
1126
1127 procedure TInitialSetupDialog.UpdateCompilerNote(aQuiet: boolean);
1128 var
1129 CurCaption, ParsedC, Note, s: String;
1130 Quality: TSDFilenameQuality;
1131 ImageIndex: Integer;
1132 CfgCache: TPCTargetConfigCache;
1133 begin
1134 if csDestroying in ComponentState then exit;
1135 CurCaption:=CompilerComboBox.Text;
1136 EnvironmentOptions.CompilerFilename:=CurCaption;
1137 ParsedC:=EnvironmentOptions.GetParsedCompilerFilename;
1138 if fLastParsedCompiler=ParsedC then exit;
1139 fLastParsedCompiler:=ParsedC;
1140 Quality:=CheckFPCExeQuality(fLastParsedCompiler,Note,
1141 CodeToolBoss.CompilerDefinesCache.TestFilename);
1142 if Quality=sddqCompatible then
1143 begin
1144 // check compiler again
1145 CfgCache:=CodeToolBoss.CompilerDefinesCache.ConfigCaches.Find(
1146 fLastParsedCompiler,'','','',true);
1147 CfgCache.CompilerDate:=0; // force update
1148 if CfgCache.NeedsUpdate then
1149 CfgCache.Update(CodeToolBoss.CompilerDefinesCache.TestFilename);
1150 BuildBoss.SetBuildTargetIDE(aQuiet);
1151 end;
1152 case Quality of
1153 sddqInvalid: s:=lisError;
1154 sddqCompatible: s:='';
1155 else s:=lisWarning;
1156 end;
1157 ParsedC:=EnvironmentOptions.GetParsedCompilerFilename;
1158 if EnvironmentOptions.CompilerFilename<>ParsedC then
1159 s:=lisFile2+ParsedC+LineEnding+LineEnding+s;
1160 CompilerMemo.Text:=s+Note;
1161
1162 ImageIndex:=QualityToImgIndex(Quality);
1163 TVNodeCompiler.ImageIndex:=ImageIndex;
1164 TVNodeCompiler.SelectedIndex:=ImageIndex;
1165
1166 FFlags:=FFlags+[sdfFPCSrcDirNeedsUpdate,sdfFppkgConfigFileNeedsUpdate,
1167 sdfMakeExeFilenameNeedsUpdate,sdfDebuggerFilenameNeedsUpdate];
1168 IdleConnected:=true;
1169 end;
1170
1171 procedure TInitialSetupDialog.UpdateFPCSrcDirNote;
1172 var
1173 CurCaption: String;
1174 Note: string;
1175 Quality: TSDFilenameQuality;
1176 s: String;
1177 ImageIndex: Integer;
1178 begin
1179 if csDestroying in ComponentState then exit;
1180 CurCaption:=FPCSrcDirComboBox.Text;
1181 CurCaption:=ChompPathDelim(CurCaption);
1182 EnvironmentOptions.FPCSourceDirectory:=CurCaption;
1183 if fLastParsedFPCSrcDir=EnvironmentOptions.GetParsedFPCSourceDirectory then exit;
1184 fLastParsedFPCSrcDir:=EnvironmentOptions.GetParsedFPCSourceDirectory;
1185 //debugln(['TInitialSetupDialog.UpdateFPCSrcDirNote ',fLastParsedFPCSrcDir]);
1186 Quality:=CheckFPCSrcDirQuality(fLastParsedFPCSrcDir,Note,GetFPCVer);
1187 case Quality of
1188 sddqInvalid: s:=lisError;
1189 sddqCompatible: s:='';
1190 else s:=lisWarning;
1191 end;
1192 if EnvironmentOptions.FPCSourceDirectory<>EnvironmentOptions.GetParsedFPCSourceDirectory
1193 then
1194 s:=lisDirectory+EnvironmentOptions.GetParsedFPCSourceDirectory+LineEnding+
1195 LineEnding+s;
1196 s+=Note;
1197 if Quality<>sddqCompatible then
1198 s+=#13+lisYouCanDownloadFPCAndTheFPCSourcesFromHttpSourcefor;
1199 FPCSrcDirMemo.Text:=s;
1200
1201 ImageIndex:=QualityToImgIndex(Quality);
1202 TVNodeFPCSources.ImageIndex:=ImageIndex;
1203 TVNodeFPCSources.SelectedIndex:=ImageIndex;
1204 end;
1205
1206 procedure TInitialSetupDialog.UpdateMakeExeNote;
1207 var
1208 CurCaption: String;
1209 Note: string;
1210 Quality: TSDFilenameQuality;
1211 s: String;
1212 ImageIndex: Integer;
1213 begin
1214 if csDestroying in ComponentState then exit;
1215 CurCaption:=MakeExeComboBox.Text;
1216 EnvironmentOptions.MakeFilename:=CurCaption;
1217 if fLastParsedMakeExe=EnvironmentOptions.GetParsedMakeFilename then exit;
1218 fLastParsedMakeExe:=EnvironmentOptions.GetParsedMakeFilename;
1219 //debugln(['TInitialSetupDialog.UpdateMakeExeNote ',fLastParsedMakeExe]);
1220 Quality:=CheckMakeExeQuality(fLastParsedMakeExe,Note);
1221
1222 case Quality of
1223 sddqInvalid: s:=lisError;
1224 sddqCompatible: s:='';
1225 else s:=lisWarning;
1226 end;
1227 if EnvironmentOptions.MakeFilename<>EnvironmentOptions.GetParsedMakeFilename
1228 then
1229 s:=lisFile2+EnvironmentOptions.GetParsedMakeFilename+LineEnding+
1230 LineEnding+s;
1231 MakeExeMemo.Text:=s+Note;
1232
1233 ImageIndex:=QualityToImgIndex(Quality);
1234 TVNodeMakeExe.ImageIndex:=ImageIndex;
1235 TVNodeMakeExe.SelectedIndex:=ImageIndex;
1236
1237 IdleConnected:=true;
1238 end;
1239
1240 procedure TInitialSetupDialog.UpdateDebuggerNote;
1241 var
1242 CurCaption: String;
1243 Note: string;
1244 Quality: TSDFilenameQuality;
1245 s, ParsedFName: String;
1246 ImageIndex: Integer;
1247 begin
1248 if csDestroying in ComponentState then exit;
1249 CurCaption:=DebuggerComboBox.Text;
1250 ParsedFName := EnvironmentOptions.GetParsedValue(eopDebuggerFilename, CurCaption);
1251 if fLastParsedDebugger=ParsedFName then exit;
1252 fLastParsedDebugger:=ParsedFName;
1253 //debugln(['TInitialSetupDialog.UpdateDebuggerNote ',fLastParsedDebugger]);
1254 Quality:=CheckDebuggerQuality(fLastParsedDebugger,Note, FSkipDebugger);
1255
1256 case Quality of
1257 sddqInvalid: s:=lisError;
1258 sddqCompatible: s:='';
1259 else s:=lisWarning;
1260 end;
1261 if CurCaption<>ParsedFName
1262 then
1263 s:=lisFile2+ParsedFName+LineEnding+
1264 LineEnding+s;
1265 DebuggerMemo.Text:=s+Note;
1266
1267 ImageIndex:=QualityToImgIndex(Quality);
1268 TVNodeDebugger.ImageIndex:=ImageIndex;
1269 TVNodeDebugger.SelectedIndex:=ImageIndex;
1270
1271 IdleConnected:=true;
1272 end;
1273
FirstErrorNodenull1274 function TInitialSetupDialog.FirstErrorNode: TTreeNode;
1275 var
1276 i: Integer;
1277 begin
1278 for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do
1279 begin
1280 Result:=PropertiesTreeView.Items.TopLvlItems[i];
1281 if Result.ImageIndex=ImgIDError then exit;
1282 end;
1283 Result:=FirstWarningNode;
1284 end;
1285
FirstWarningNodenull1286 function TInitialSetupDialog.FirstWarningNode: TTreeNode;
1287 var
1288 i: Integer;
1289 begin
1290 for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do
1291 begin
1292 Result:=PropertiesTreeView.Items.TopLvlItems[i];
1293 if Result.ImageIndex=ImgIDWarning then
1294 exit;
1295 end;
1296 Result:=nil;
1297 end;
1298
GetFirstCandidatenull1299 function TInitialSetupDialog.GetFirstCandidate(Candidates: TSDFileInfoList;
1300 MinQuality: TSDFilenameQuality): TSDFileInfo;
1301 var
1302 i: Integer;
1303 begin
1304 if Candidates<>nil then
1305 for i:=0 to Candidates.Count-1 do begin
1306 Result:=TSDFileInfo(Candidates[i]);
1307 if Result.Quality>=MinQuality then
1308 exit;
1309 end;
1310 Result:=nil;
1311 end;
1312
QualityToImgIndexnull1313 function TInitialSetupDialog.QualityToImgIndex(Quality: TSDFilenameQuality): integer;
1314 begin
1315 if Quality=sddqCompatible then
1316 Result:=-1
1317 else if Quality=sddqWrongMinorVersion then
1318 Result:=ImgIDWarning
1319 else if Quality=sddqIncomplete then
1320 Result:=ImgIDWarning
1321 else if Quality=sddqMakeNotWithFpc then
1322 Result:=ImgIDWarning
1323 else
1324 Result:=ImgIDError;
1325 end;
1326
1327 procedure TInitialSetupDialog.ShowHideScanControls(aShow: Boolean);
1328 begin
1329 // Show ProgressBar and Stop button durin scanning
1330 ScanLabel.Visible:=aShow;
1331 ScanProgressBar.Visible:=aShow;
1332 StopScanButton.Visible:=aShow;
1333 // At the same time disable other GUI controls so a user can not mess with it
1334 StartIDEBitBtn.Enabled:=not aShow;
1335 FPCSrcDirBrowseButton.Enabled:=not aShow;
1336 FPCSrcDirComboBox.Enabled:=not aShow;
1337 // FPCSrcDirMemo.Enabled:=not aShow;
1338 end;
1339
1340 procedure TInitialSetupDialog.ThreadTerminated(Sender: TObject);
1341 begin
1342 debugln(['TInitialSetupDialog.ThreadTerminated ']);
1343 fSearchFpcSourceThread:=nil; // Thread will free itself. Make the variable nil, too.
1344 ShowHideScanControls(false);
1345 end;
1346
1347 procedure TInitialSetupDialog.TranslateResourceStrings;
1348 begin
1349 IDETranslations.TranslateResourceStrings(
1350 EnvironmentOptions.GetParsedLazarusDirectory,
1351 EnvironmentOptions.LanguageID);
1352 UpdateCaptions;
1353 end;
1354
1355 procedure TInitialSetupDialog.Init;
1356 var
1357 Node: TTreeNode;
1358 Candidate: TSDFileInfo;
1359 IsFirstStart: Boolean;
1360 PrimaryFilename: String;
1361 SecondaryFilename: String;
1362 PrimaryEnvs: TStringList;
1363 SecondaryEnvs: TStringList;
1364 begin
1365 IsFirstStart:=not FileExistsCached(EnvironmentOptions.Filename);
1366 if not IsFirstStart then begin
1367 IsFirstStart:= False;
1368 PrimaryFilename:=EnvironmentOptions.Filename;
1369 SecondaryFilename:=AppendPathDelim(GetSecondaryConfigPath)+ExtractFilename(PrimaryFilename);
1370 if FileExistsUTF8(PrimaryFilename)
1371 and FileExistsUTF8(SecondaryFilename) then begin
1372 // compare content of primary and secondary config
1373 PrimaryEnvs:=TStringList.Create;
1374 SecondaryEnvs:=TStringList.Create;
1375 try
1376 PrimaryEnvs.LoadFromFile(PrimaryFilename);
1377 except
1378 on E: Exception do
1379 debugln(['TInitialSetupDialog.Init unable to read "'+PrimaryFilename+'": '+E.Message]);
1380 end;
1381 try
1382 SecondaryEnvs.LoadFromFile(SecondaryFilename);
1383 except
1384 on E: Exception do
1385 debugln(['TInitialSetupDialog.Init unable to read "'+SecondaryFilename+'": '+E.Message]);
1386 end;
1387 // IsFirstStart:=PrimaryEnvs.Text=SecondaryEnvs.Text;
1388 PrimaryEnvs.Free;
1389 SecondaryEnvs.Free;
1390 end;
1391 end
1392 else
1393 IsFirstStart := True;
1394 //debugln(['TInitialSetupDialog.Init IsFirstStart=',IsFirstStart,' ',EnvironmentOptions.Filename]);
1395
1396 // Lazarus directory
1397 UpdateLazarusDirCandidates;
1398 if IsFirstStart
1399 or (not FileExistsCached(EnvironmentOptions.GetParsedLazarusDirectory))
1400 then begin
1401 // first start => choose first best candidate
1402 Candidate:=GetFirstCandidate(FCandidates[sddtLazarusSrcDir]);
1403 if Candidate<>nil then
1404 begin
1405 EnvironmentOptions.LazarusDirectory:=Candidate.Caption;
1406 if Candidate.Quality=sddqCompatible then
1407 TranslateResourceStrings;
1408 end;
1409 end;
1410 LazDirComboBox.Text:=EnvironmentOptions.LazarusDirectory;
1411 FLastParsedLazDir:='. .';
1412 UpdateLazDirNote;
1413
1414 // compiler filename
1415 UpdateCompilerFilenameCandidates;
1416 if IsFirstStart
1417 or (EnvironmentOptions.CompilerFilename='')
1418 or (not FileExistsCached(EnvironmentOptions.GetParsedCompilerFilename))
1419 then begin
1420 // first start => choose first best candidate
1421 Candidate:=GetFirstCandidate(FCandidates[sddtCompilerFilename]);
1422 if Candidate<>nil then
1423 EnvironmentOptions.CompilerFilename:=Candidate.Caption;
1424 end;
1425 CompilerComboBox.Text:=EnvironmentOptions.CompilerFilename;
1426 fLastParsedCompiler:='. .';
1427 UpdateCompilerNote;
1428
1429 // FPC source directory
1430 UpdateFPCSrcDirCandidates;
1431 {$IFDEF DebugSearchFPCSrcThread}
1432 IsFirstStart:=true;
1433 {$ENDIF}
1434 if IsFirstStart or (EnvironmentOptions.FPCSourceDirectory='')
1435 or (not FileExistsCached(EnvironmentOptions.GetParsedFPCSourceDirectory))
1436 then begin
1437 // first start => choose first best candidate
1438 {$IFDEF DebugSearchFPCSrcThread}
1439 Candidate:=nil;
1440 {$ELSE}
1441 Candidate:=GetFirstCandidate(FCandidates[sddtFPCSrcDir]);
1442 {$ENDIF}
1443 if Candidate<>nil then begin
1444 EnvironmentOptions.FPCSourceDirectory:=Candidate.Caption;
1445 end
1446 else begin
1447 // No candidates found => start a thread to scan the file system.
1448 {$IFNDEF LCLCarbon}
1449 // carbon interface does not support Synchronize outside Application.Run
1450 StartFPCSrcThread;
1451 SelectPage(TVNodeFPCSources.Text);
1452 {$ENDIF}
1453 end;
1454 end;
1455 ShowHideScanControls(fSearchFpcSourceThread<>nil);
1456 FPCSrcDirComboBox.Text:=EnvironmentOptions.FPCSourceDirectory;
1457 fLastParsedFPCSrcDir:='. .';
1458 UpdateFPCSrcDirNote;
1459
1460 // Make executable
1461 UpdateMakeExeCandidates({aStopIfFits} True);
1462 if IsFirstStart
1463 or (EnvironmentOptions.MakeFilename='')
1464 or (not FileExistsCached(EnvironmentOptions.GetParsedMakeFilename)) then
1465 begin
1466 // first start => choose first best candidate
1467 Candidate:=GetFirstCandidate(FCandidates[sddtMakeExeFilename]);
1468 if Candidate<>nil then
1469 EnvironmentOptions.MakeFilename:=Candidate.Caption
1470 else begin // second chance => better an incomplete instead of none (especially for windows)
1471 Candidate:=GetFirstCandidate(FCandidates[sddtMakeExeFilename], sddqIncomplete);
1472 if Candidate<>nil then
1473 EnvironmentOptions.MakeFilename:=Candidate.Caption;
1474 end;
1475 end;
1476 MakeExeComboBox.Text:=EnvironmentOptions.MakeFilename;
1477 fLastParsedMakeExe:='. .';
1478 UpdateMakeExeNote;
1479
1480 RegisterDebugger(TGDBMIDebugger); // make sure we can read the config
1481 FSkipDebugger := EnvironmentOptions.HasActiveDebuggerEntry // There is a configured entry. Assume it is right, unless we can prove it is incorrect
1482 and not (
1483 (EnvironmentOptions.CurrentDebuggerPropertiesConfig <> nil) and // The ACTIVE dbg is a known debugger
1484 (EnvironmentOptions.CurrentDebuggerClass <> nil) and // with existing debugger class
1485 (EnvironmentOptions.CurrentDebuggerPropertiesConfig.NeedsExePath) // Does need an exe
1486 );
1487 // Debugger
1488 FInitialDebuggerFileName := EnvironmentOptions.DebuggerFilename;
1489 UpdateDebuggerCandidates;
1490 if (not FSkipDebugger) then begin
1491 if EnvironmentOptions.CurrentDebuggerPropertiesConfig = nil then
1492 EnvironmentOptions.CurrentDebuggerPropertiesConfig :=
1493 EnvironmentOptions.DebuggerPropertiesConfigList.EntryByName('', TGDBMIDebugger.ClassName);
1494 if EnvironmentOptions.CurrentDebuggerPropertiesConfig = nil then
1495 EnvironmentOptions.CurrentDebuggerPropertiesConfig :=
1496 TDebuggerPropertiesConfig.CreateForDebuggerClass(TGDBMIDebugger);
1497 if IsFirstStart or (not FileExistsCached(EnvironmentOptions.GetParsedDebuggerFilename))
1498 then begin
1499 // first start => choose first best candidate
1500 Candidate:=GetFirstCandidate(FCandidates[sddtDebuggerFilename]);
1501 if Candidate<>nil then begin
1502 EnvironmentOptions.CurrentDebuggerPropertiesConfig.DebuggerFilename:=Candidate.Caption;
1503 end;
1504 end;
1505 EnvironmentOptions.SaveDebuggerPropertiesList; // Update XML
1506 end;
1507
1508 DebuggerComboBox.Text:=EnvironmentOptions.DebuggerFilename;
1509 fLastParsedDebugger:='. .';
1510 UpdateDebuggerNote;
1511
1512 // Fppkg
1513 FppkgComboBox.Text := EnvironmentOptions.FppkgConfigFile;
1514 fLastParsedFppkgConfigFile := ' ';
1515 UpdateFppkgCandidates;
1516 UpdateFppkgNote;
1517
1518 // select first error
1519 Node:=FirstErrorNode;
1520 if Node=nil then
1521 Node:=TVNodeLazarus;
1522 PropertiesTreeView.Selected:=Node;
1523 end;
1524
1525 procedure TInitialSetupDialog.UpdateFppkgNote;
1526 var
1527 CurCaption: String;
1528 FppkgMsg, Note: string;
1529 Quality: TSDFilenameQuality;
1530 ConfigFile: string;
1531 {$IF FPC_FULLVERSION>30100}
1532 ImageIndex: Integer;
1533 {$ENDIF}
1534 begin
1535 if csDestroying in ComponentState then exit;
1536 CurCaption:=FppkgComboBox.Text;
1537 EnvironmentOptions.FppkgConfigFile:=CurCaption;
1538 if fLastParsedFppkgConfigFile=EnvironmentOptions.GetParsedFppkgConfig then exit;
1539 fLastParsedFppkgConfigFile:=EnvironmentOptions.GetParsedFppkgConfig;
1540
1541 ConfigFile := fLastParsedFppkgConfigFile;
1542 Quality := CheckFppkgConfigFile(ConfigFile, Note);
1543 if Quality<>sddqCompatible then
1544 begin
1545 Note := lisError + Note + LineEnding;
1546 FppkgWriteConfigButton.Enabled := (Quality=sddqIncomplete);
1547 end
1548 else
1549 begin
1550 Quality := CheckFppkgConfiguration(ConfigFile, FppkgMsg);
1551
1552 if Quality=sddqCompatible then
1553 begin
1554 Note := lisOk;
1555 FppkgWriteConfigButton.Enabled := False;
1556 end
1557 else
1558 begin
1559 Note := lisError + Format(lisIncorrectFppkgConfiguration, [FppkgMsg]) + LineEnding;
1560 Note := Note + LineEnding + lisFppkgFixConfiguration;
1561 FppkgWriteConfigButton.Enabled := True;
1562 end;
1563 end;
1564
1565 FppkgMemo.Text := lisFile2 + ConfigFile + LineEnding + LineEnding + Note;
1566
1567 {$IF FPC_FULLVERSION>30100}
1568 ImageIndex:=QualityToImgIndex(Quality);
1569 TVNodeFppkg.ImageIndex:=ImageIndex;
1570 TVNodeFppkg.SelectedIndex:=ImageIndex;
1571 {$ENDIF FPC_FULLVERSION>30100}
1572
1573 IdleConnected:=true;
1574 end;
1575
1576 procedure TInitialSetupDialog.FppkgComboBoxChange(Sender: TObject);
1577 begin
1578 UpdateFppkgNote;
1579 end;
1580
1581 procedure TInitialSetupDialog.UpdateFppkgCandidates;
1582
SearchFppkgFpcPrefixCandidatesnull1583 function SearchFppkgFpcPrefixCandidates: TSDFileInfoList;
1584
CheckFilenull1585 function CheckFile(AFile: string; var List: TSDFileInfoList): boolean;
1586 var
1587 Item: TSDFileInfo;
1588 begin
1589 Result:=false;
1590 if AFile='' then exit;
1591 ForcePathDelims(AFile);
1592 // check if already checked
1593 if Assigned(List) and List.CaptionExists(AFile) then exit;
1594
1595 if FileExistsUTF8(AFile) then
1596 begin
1597 if List=nil then
1598 List:=TSDFileInfoList.create(true);
1599 Item:=List.AddNewItem(AFile, AFile);
1600 Item.Quality:=sddqCompatible;
1601 Result := True;
1602 end;
1603 end;
1604 begin
1605 Result:=nil;
1606
1607 {$IF FPC_FULLVERSION>30100}
1608 CheckFile(GetFppkgConfigFile(False, False), Result);
1609 CheckFile(GetFppkgConfigFile(False, True), Result);
1610 CheckFile(GetFppkgConfigFile(True, False), Result);
1611 CheckFile(GetFppkgConfigFile(True, True), Result);
1612 {$ENDIF}
1613 end;
1614
1615 var
1616 Files: TSDFileInfoList;
1617 begin
1618 Exclude(FFlags,sdfFppkgConfigFileNeedsUpdate);
1619 Files:=SearchFppkgFpcPrefixCandidates;
1620 FreeAndNil(FCandidates[sddtFppkgFpcPrefix]);
1621 FCandidates[sddtFppkgFpcPrefix]:=Files;
1622 FillComboboxWithFileInfoList(FppkgComboBox,Files,-1);
1623 end;
1624
1625
1626 procedure TInitialSetupDialog.FppkgBrowseButtonClick(Sender: TObject);
1627 var
1628 lExpandedName: string; // Expanded name before Dialog
1629 lDirName, lFileName: string;
1630 lTitle: string;
1631 lChanged: boolean=False;
1632 Dlg: TIDEOpenDialog;
1633 Filter: String;
1634 begin
1635 Dlg:=IDEOpenDialogClass.Create(nil);
1636 try
1637 lTitle:='fppkg.cfg';
1638 Dlg.Title:=SimpleFormat(lisSelectPathTo, [lTitle]);
1639 lExpandedName:=EnvironmentOptions.GetParsedValue(eopFppkgConfigFile, FppkgComboBox.Text);
1640 lDirName := GetValidDirectory(lExpandedName, {out} lFileName);
1641 Dlg.Options:=Dlg.Options+[ofFileMustExist];
1642 if lFileName='' then
1643 lFileName:=lTitle;
1644 Filter:=dlgFilterAll+'|'+GetAllFilesMask;
1645 if ExtractFileExt(lFileName)<>'' then
1646 Filter:=dlgFilterExecutable+'|*'+ExtractFileExt(lFileName)+'|'+Filter;
1647 Dlg.Filter:=Filter;
1648 Dlg.InitialDir:=lDirName;
1649 Dlg.FileName:=lFileName;
1650 if not Dlg.Execute then
1651 exit;
1652 lFileName:=CleanAndExpandFilename(Dlg.Filename);
1653 lChanged := UpperCase(lExpandedName)<>UpperCase(lFileName);
1654 finally
1655 Dlg.Free;
1656 end;
1657 if lChanged then begin // Avoid loosing $(macros)
1658 FppkgComboBox.Text:=lFileName;
1659 UpdateFppkgNote;
1660 end;
1661 end;
1662
1663 procedure TInitialSetupDialog.FppkgWriteConfigButtonClick(Sender: TObject);
1664 {$IF FPC_FULLVERSION>30100}
1665 var
1666 Dialog: TGenerateFppkgConfigurationDialog;
1667 {$ENDIF}
1668 begin
1669 {$IF FPC_FULLVERSION>30100}
1670 Dialog := TGenerateFppkgConfigurationDialog.Create(Self);
1671 try
1672 Dialog.Compiler := fLastParsedCompiler;
1673 if fLastParsedFppkgConfigFile='' then
1674 Dialog.FppkgCfgFilename := GetFppkgConfigFile(False, False)
1675 else
1676 Dialog.FppkgCfgFilename := fLastParsedFppkgConfigFile;
1677 Dialog.ShowModal;
1678 finally
1679 Dialog.Free;
1680 end;
1681
1682 fLastParsedFppkgConfigFile := ' ';
1683 UpdateFppkgNote;
1684 {$ENDIF}
1685 end;
1686
1687 end.
1688
1689