1 {
2  ***************************************************************************
3  *                                                                         *
4  *   This source is free software; you can redistribute it and/or modify   *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This code is distributed in the hope that it will be useful, but      *
10  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
12  *   General Public License for more details.                              *
13  *                                                                         *
14  *   A copy of the GNU General Public License is available on the World    *
15  *   Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also      *
16  *   obtain it by writing to the Free Software Foundation,                 *
17  *   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.   *
18  *                                                                         *
19  ***************************************************************************
20 
21   Abstract:
22     Dialog to clean up a project and its packages and to compile the project.
23 }
24 unit BuildProjectDlg;
25 
26 {$mode objfpc}{$H+}
27 
28 interface
29 
30 uses
31   Classes, SysUtils, Math, Laz_AVL_Tree,
32   // LCL
33   Forms, Controls, Dialogs, ButtonPanel, StdCtrls, ComCtrls, Masks, LCLIntf,
34   // LazUtils
35   LazFileUtils, LazFileCache, LazStringUtils, AvgLvlTree,
36   // codetools
37   FileProcs, CodeToolManager, DirectoryCacher,
38   // IDEIntf
39   IDEDialogs, IDEImagesIntf, PackageIntf,
40   // IDE
41   PackageDefs, PackageSystem, InputHistory, LazarusIDEStrConsts, Project,
42   EnvironmentOpts, IDEProcs;
43 
44 type
45   TBuildProjectDialogItem = class
46   public
47     IsDirectory: boolean;
48     Filename: string;
49   end;
50 
51   { TCleanBuildProjectDialog }
52 
53   TCleanBuildProjectDialog = class(TForm)
54     ButtonPanel1: TButtonPanel;
55     DeleteButton: TButton;
56     PkgOutCheckBox: TCheckBox;
57     PkgOutMaskComboBox: TComboBox;
58     PkgSrcCheckBox: TCheckBox;
59     PkgSrcMaskComboBox: TComboBox;
60     PreviewLabel: TLabel;
61     FilesTreeView: TTreeView;
62     ProjOutCheckBox: TCheckBox;
63     ProjOutMaskComboBox: TComboBox;
64     ProjSrcCheckBox: TCheckBox;
65     ProjSrcMaskComboBox: TComboBox;
66     procedure ButtonPanel1OKButtonClick(Sender: TObject);
67     procedure DeleteButtonClick(Sender: TObject);
68     procedure FilesTreeViewMouseDown(Sender: TObject; Button: TMouseButton;
69       Shift: TShiftState; X, Y: Integer);
70     procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
71     procedure FormCreate(Sender: TObject);
72     procedure FormDestroy(Sender: TObject);
73     procedure FormResize(Sender: TObject);
74     procedure HelpButtonClick(Sender: TObject);
75     procedure PkgOutCheckBoxChange(Sender: TObject);
76     procedure PkgSrcCheckBoxChange(Sender: TObject);
77     procedure ProjOutCheckBoxChange(Sender: TObject);
78     procedure ProjOutMaskComboBoxChange(Sender: TObject);
79     procedure ProjSrcCheckBoxChange(Sender: TObject);
80   private
81     ImageIndexDirectory: Integer;
82     ImageIndexFile: Integer;
83     FIdleConnected: boolean;
84     procedure SetIdleConnected(const AValue: boolean);
85     procedure OnIdle(Sender: TObject; var {%H-}Done: Boolean);
86   private
87     FProject: TProject;
88     FUpdateNeeded: boolean;
89     procedure ClearFilesTreeView;
90     procedure UpdateFilesTreeView(Immediately: boolean = false);
91     procedure AddProjOutDirectory;
92     procedure AddProjSrcDirectories;
93     procedure AddPkgOutDirectories;
94     procedure AddPkgSrcDirectory;
95     procedure AddDirectory(aTVPath, aDirectory, aFileMask: string);
96     procedure AddDirectories(aTVPath, aSearchPath, aFileMask: string);
GetAllFilesFromTreenull97     function GetAllFilesFromTree: TFilenameToStringTree;
DeleteFilesnull98     function DeleteFiles: TModalResult;
99     property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
100   public
101     procedure Init(AProject: TProject);
102   end;
103 
ShowBuildProjectDialognull104 function ShowBuildProjectDialog(AProject: TProject): TModalResult;
105 
106 implementation
107 
ShowBuildProjectDialognull108 function ShowBuildProjectDialog(AProject: TProject): TModalResult;
109 var
110   CleanBuildProjectDialog: TCleanBuildProjectDialog;
111 begin
112   CleanBuildProjectDialog:=TCleanBuildProjectDialog.Create(nil);
113   try
114     CleanBuildProjectDialog.Init(AProject);
115     Result:=CleanBuildProjectDialog.ShowModal;
116   finally
117     CleanBuildProjectDialog.Free;
118   end;
119 end;
120 
121 {$R *.lfm}
122 
123 { TCleanBuildProjectDialog }
124 
125 procedure TCleanBuildProjectDialog.FormCreate(Sender: TObject);
126 begin
127   Caption:=lisCleanUpAndBuildProject;
128 
129   ProjOutCheckBox.Caption:=lisProjectOutputDirectory;
130   ProjSrcCheckBox.Caption:=lisProjectSourceDirectories;
131   PkgOutCheckBox.Caption:=lisPackageOutputDirectories;
132   PkgSrcCheckBox.Caption:=lisPackageSourceDirectories;
133   PreviewLabel.Caption:=lisTheseFilesWillBeDeleted;
134 
135   ButtonPanel1.OKButton.Caption:=lisCleanUpAndBuild;
136   ButtonPanel1.HelpButton.Caption:=lisMenuHelp;
137   ButtonPanel1.CancelButton.Caption:=lisCancel;
138 
139   DeleteButton.Caption:=lisDelete;
140 
141   FilesTreeView.Images:=IDEImages.Images_16;
142   ImageIndexDirectory := IDEImages.LoadImage('pkg_files');
143   ImageIndexFile := IDEImages.LoadImage('laz_delete');
144 
145   ButtonPanel1.OKButton.ModalResult:=mrNone;
146 end;
147 
148 procedure TCleanBuildProjectDialog.FormDestroy(Sender: TObject);
149 begin
150   ClearFilesTreeView;
151   FProject:=nil;
152   IdleConnected:=false;
153 end;
154 
155 procedure TCleanBuildProjectDialog.FormClose(Sender: TObject;
156   var CloseAction: TCloseAction);
157 
158   procedure StoreCombo(AComboBox: TComboBox);
159   begin
160     // store all masks into one history list
161     ProjOutMaskComboBox.AddHistoryItem(AComboBox.Text,30,true,false);
162   end;
163 
164 begin
165   EnvironmentOptions.CleanBuildProjOut:=ProjOutCheckBox.Checked;
166   EnvironmentOptions.CleanBuildProjSrc:=ProjSrcCheckBox.Checked;
167   EnvironmentOptions.CleanBuildPkgOut :=PkgOutCheckBox.Checked;
168   EnvironmentOptions.CleanBuildPkgSrc :=PkgSrcCheckBox.Checked;
169 
170   FProject.CleanOutputFileMask:=ProjOutMaskComboBox.Text;
171   FProject.CleanSourcesFileMask:=ProjSrcMaskComboBox.Text;
172   InputHistories.CleanOutputFileMask:=PkgOutMaskComboBox.Text;
173   InputHistories.CleanSourcesFileMask:=PkgSrcMaskComboBox.Text;
174 
175   // combine history lists
176   StoreCombo(ProjOutMaskComboBox);
177   StoreCombo(ProjSrcMaskComboBox);
178   StoreCombo(PkgOutMaskComboBox);
179   StoreCombo(PkgSrcMaskComboBox);
180   InputHistories.HistoryLists.GetList(hlCleanBuildFileMask,true,
181     rltFile).Assign(ProjOutMaskComboBox.Items);
182 end;
183 
184 procedure TCleanBuildProjectDialog.ButtonPanel1OKButtonClick(Sender: TObject);
185 begin
186   if DeleteFiles<>mrOk then exit;
187   ModalResult:=mrOk;
188 end;
189 
190 procedure TCleanBuildProjectDialog.DeleteButtonClick(Sender: TObject);
191 begin
192   DeleteFiles;
193 end;
194 
195 procedure TCleanBuildProjectDialog.FilesTreeViewMouseDown(Sender: TObject;
196   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
197 var
198   Node: TTreeNode;
199   Item: TBuildProjectDialogItem;
200   Filename: String;
201 begin
202   Node:=FilesTreeView.GetNodeAt(X,Y);
203   if Node=nil then exit;
204   if (Button=mbLeft) and (ssDouble in Shift) and (Node.Data<>nil) then begin
205     Item:=TBuildProjectDialogItem(Node.Data);
206     Filename:=Item.Filename;
207     if Item.IsDirectory then exit;
208     Filename:=ExtractFilePath(Filename);
209     Filename:=ChompPathDelim(Filename);
210     debugln(['TBuildProjectDialog.FilesTreeViewMouseDown Filename="',Filename,'"']);
211     if FilenameIsAbsolute(Filename) then
212       OpenURL('file://'+StringReplace(Filename,'\','/',[rfReplaceAll]));
213   end;
214 end;
215 
216 procedure TCleanBuildProjectDialog.FormResize(Sender: TObject);
217 var
218   r: Integer;
219 begin
220   r:=ProjOutCheckBox.Left
221     +Max(Max(ProjOutCheckBox.Width,ProjSrcCheckBox.Width),
222          Max(PkgOutCheckBox.Width,PkgSrcCheckBox.Width));
223   ProjOutMaskComboBox.Left:=r+10;
224 end;
225 
226 procedure TCleanBuildProjectDialog.HelpButtonClick(Sender: TObject);
227 begin
228   OpenUrl('http://wiki.freepascal.org/IDE_Window:_Clean_up_build_files_dialog');
229 end;
230 
231 procedure TCleanBuildProjectDialog.PkgOutCheckBoxChange(Sender: TObject);
232 begin
233   PkgOutMaskComboBox.Enabled:=PkgOutCheckBox.Checked;
234   UpdateFilesTreeView;
235 end;
236 
237 procedure TCleanBuildProjectDialog.PkgSrcCheckBoxChange(Sender: TObject);
238 begin
239   PkgSrcMaskComboBox.Enabled:=PkgSrcCheckBox.Checked;
240   UpdateFilesTreeView;
241 end;
242 
243 procedure TCleanBuildProjectDialog.ProjOutCheckBoxChange(Sender: TObject);
244 begin
245   ProjOutMaskComboBox.Enabled:=ProjOutCheckBox.Checked;
246   UpdateFilesTreeView;
247 end;
248 
249 procedure TCleanBuildProjectDialog.ProjOutMaskComboBoxChange(Sender: TObject);
250 begin
251   UpdateFilesTreeView;
252 end;
253 
254 procedure TCleanBuildProjectDialog.ProjSrcCheckBoxChange(Sender: TObject);
255 begin
256   ProjSrcMaskComboBox.Enabled:=ProjSrcCheckBox.Checked;
257   UpdateFilesTreeView;
258 end;
259 
260 procedure TCleanBuildProjectDialog.SetIdleConnected(const AValue: boolean);
261 begin
262   if FIdleConnected=AValue then exit;
263   FIdleConnected:=AValue;
264   if IdleConnected then
265     Application.AddOnIdleHandler(@OnIdle)
266   else
267     Application.RemoveOnIdleHandler(@OnIdle);
268 end;
269 
270 procedure TCleanBuildProjectDialog.OnIdle(Sender: TObject; var Done: Boolean);
271 begin
272   if FProject=nil then exit;
273   if not FUpdateNeeded then exit;
274   IdleConnected:=false;
275   UpdateFilesTreeView(true);
276 end;
277 
278 procedure TCleanBuildProjectDialog.ClearFilesTreeView;
279 var
280   Node: TTreeNode;
281 begin
282   Node:=FilesTreeView.Items.GetFirstNode;
283   while Node<>nil do begin
284     if (Node.Data<>nil) then
285       TObject(Node.Data).Free;
286     Node:=Node.GetNext;
287   end;
288   FilesTreeView.Items.Clear;
289 end;
290 
291 procedure TCleanBuildProjectDialog.UpdateFilesTreeView(Immediately: boolean);
292 
CreateTVChildCountsnull293   function CreateTVChildCounts(TVNode: TTreeNode): integer;
294   var
295     ChildNode: TTreeNode;
296   begin
297     Result:=0;
298     if TVNode=nil then exit;
299     ChildNode:=TVNode.GetFirstChild;
300     while ChildNode<>nil do begin
301       inc(Result,CreateTVChildCounts(ChildNode));
302       ChildNode:=ChildNode.GetNextSibling;
303     end;
304     if (Result=0) and (TVNode.Count>0) then
305       // has children, but no grand children => is a directory
306       inc(Result,TVNode.Count);
307     if Result>0 then
308       TVNode.Text:=Format(lisCBPFiles, [TVNode.Text, IntToStr(Result)]);
309   end;
310 
311 var
312   i: Integer;
313   TVNode: TTreeNode;
314 begin
315   if not Immediately then begin
316     FUpdateNeeded:=true;
317     IdleConnected:=true;
318     exit;
319   end;
320   FUpdateNeeded:=false;
321 
322   FilesTreeView.BeginUpdate;
323   ClearFilesTreeView;
324   if FProject<>nil then begin
325     if ProjOutCheckBox.Checked then AddProjOutDirectory;
326     if ProjSrcCheckBox.Checked then AddProjSrcDirectories;
327     if PkgOutCheckBox.Checked then AddPkgOutDirectories;
328     if PkgSrcCheckBox.Checked then AddPkgSrcDirectory;
329   end;
330   for i:=0 to FilesTreeView.Items.TopLvlCount-1 do begin
331     TVNode:=FilesTreeView.Items.TopLvlItems[i];
332     CreateTVChildCounts(TVNode);
333     TVNode.Expand(true);
334   end;
335   FilesTreeView.EndUpdate;
336 end;
337 
338 procedure TCleanBuildProjectDialog.AddProjOutDirectory;
339 begin
340   AddDirectory(lisProjectOutputDirectory,
341     FProject.CompilerOptions.GetUnitOutputDirectory(false),
342     ProjOutMaskComboBox.Text);
343 end;
344 
345 procedure TCleanBuildProjectDialog.AddProjSrcDirectories;
346 begin
347   AddDirectories(lisProjectOutputDirectory,
348     FProject.SourceDirectories.CreateSearchPathFromAllFiles,
349     ProjSrcMaskComboBox.Text);
350 end;
351 
352 procedure TCleanBuildProjectDialog.AddPkgOutDirectories;
353 var
354   List: TFPList;
355   i: Integer;
356   Pkg: TLazPackage;
357 begin
358   List:=nil;
359   try
360     PackageGraph.GetAllRequiredPackages(nil,FProject.FirstRequiredDependency,
361       List,[pirSkipDesignTimeOnly]);
362     if List=nil then exit;
363     for i:=0 to List.Count-1 do begin
364       Pkg:=TLazPackage(List[i]);
365       if Pkg.AutoUpdate=pupManually then continue;
366       AddDirectory(Pkg.Name,Pkg.CompilerOptions.GetUnitOutputDirectory(false),
367         PkgOutMaskComboBox.Text);
368     end;
369   finally
370     List.Free;
371   end;
372 end;
373 
374 procedure TCleanBuildProjectDialog.AddPkgSrcDirectory;
375 var
376   List: TFPList;
377   i: Integer;
378   Pkg: TLazPackage;
379 begin
380   List:=nil;
381   try
382     PackageGraph.GetAllRequiredPackages(nil,FProject.FirstRequiredDependency,
383       List);
384     if List=nil then exit;
385     for i:=0 to List.Count-1 do begin
386       Pkg:=TLazPackage(List[i]);
387       AddDirectories(Pkg.Name,Pkg.SourceDirectories.CreateSearchPathFromAllFiles,
388         PkgSrcMaskComboBox.Text);
389     end;
390   finally
391     List.Free;
392   end;
393 end;
394 
395 procedure TCleanBuildProjectDialog.AddDirectory(aTVPath, aDirectory,
396   aFileMask: string);
397 var
398   Cache: TCTDirectoryCache;
399   Files: TStrings;
400   TVFiles: TStringList;
401   MaskList: TMaskList;
402   p: SizeInt;
403   NodeText: String;
404   TVNode: TTreeNode;
405   ParentTVNode: TTreeNode;
406   i: Integer;
407   Item: TBuildProjectDialogItem;
408 begin
409   //debugln(['TBuildProjectDialog.AddDirectory aTVPath="',aTVPath,'" aDirectory="',aDirectory,'" aFileMask="',aFileMask,'"']);
410   aDirectory:=ChompPathDelim(aDirectory);
411   if (aDirectory='') or (aFileMask='')
412   or (not FilenameIsAbsolute(aDirectory))
413   or (not DirPathExistsCached(aDirectory))
414   then exit;
415   // get directory listing from cache
416   Cache:=CodeToolBoss.DirectoryCachePool.GetCache(aDirectory,true,false);
417   if Cache=nil then exit;
418   Files:=TStringList.Create;
419   TVFiles:=TStringList.Create;
420   MaskList:=TMaskList.Create(aFileMask,';');
421   try
422     if MaskList.Count=0 then exit;
423     Cache.GetFiles(Files,false);
424 
425     //debugln(['TBuildProjectDialog.AddDirectory AllFiles="',Files.Text,'"']);
426     // filter files
427     for i:=0 to Files.Count-1 do
428       if MaskList.Matches(Files[i]) then
429         TVFiles.Add(Files[i]);
430     //debugln(['TBuildProjectDialog.AddDirectory FilteredFiles="',TVFiles.Text,'"']);
431     if TVFiles.Count=0 then exit;
432 
433     // create tree node for aTVPath
434     ParentTVNode:=nil;
435     p:=System.Pos('/',aTVPath);
436     if p>0 then begin
437       NodeText:=copy(aTVPath,1,p-1);
438       Delete(aTVPath,1,p);
439     end else begin
440       NodeText:=aTVPath;
441     end;
442     if ParentTVNode=nil then
443       TVNode:=FilesTreeView.Items.FindTopLvlNode(NodeText)
444     else
445       TVNode:=ParentTVNode.FindNode(NodeText);
446     if TVNode=nil then
447       TVNode:=FilesTreeView.Items.AddChild(ParentTVNode,NodeText);
448     TVNode.ImageIndex:=ImageIndexDirectory;
449     TVNode.SelectedIndex:=ImageIndexDirectory;
450     ParentTVNode:=TVNode;
451 
452     // create tree node for directory
453     NodeText:=FProject.GetShortFilename(aDirectory,true);
454     TVNode:=ParentTVNode.GetFirstChild;
455     while (TVNode<>nil) and (CompareFilenames(TVNode.Text,NodeText)<0) do
456       TVNode:=TVNode.GetNextSibling;
457     if TVNode=nil then
458       TVNode:=FilesTreeView.Items.AddChild(ParentTVNode,NodeText)
459     else if (CompareFilenames(TVNode.Text,NodeText)<>0) then
460       TVNode:=FilesTreeView.Items.Add(TVNode,NodeText);
461     if TVNode.Data=nil then begin
462       Item:=TBuildProjectDialogItem.Create;
463       Item.IsDirectory:=true;
464       Item.Filename:=aDirectory;
465       TVNode.Data:=Item;
466     end;
467     TVNode.ImageIndex:=ImageIndexDirectory;
468     TVNode.SelectedIndex:=ImageIndexDirectory;
469     ParentTVNode:=TVNode;
470 
471     // add files
472     aDirectory:=AppendPathDelim(aDirectory);
473     for i:=0 to TVFiles.Count-1 do begin
474       Item:=TBuildProjectDialogItem.Create;
475       Item.Filename:=aDirectory+TVFiles[i];
476       TVNode:=FilesTreeView.Items.AddChildObject(ParentTVNode,TVFiles[i],Item);
477       TVNode.ImageIndex:=ImageIndexFile;
478       TVNode.SelectedIndex:=ImageIndexFile;
479     end;
480   finally
481     MaskList.Free;
482     Files.Free;
483     TVFiles.Free;
484   end;
485 end;
486 
487 procedure TCleanBuildProjectDialog.AddDirectories(aTVPath, aSearchPath,
488   aFileMask: string);
489 var
490   Directory: String;
491   p: Integer;
492 begin
493   p:=1;
494   while p<=length(aSearchPath) do begin
495     Directory:=TrimFilename(GetNextDelimitedItem(aSearchPath,';',p));
496     if FilenameIsAbsolute(Directory) then
497       AddDirectory(aTVPath,Directory,aFileMask);
498   end;
499 end;
500 
GetAllFilesFromTreenull501 function TCleanBuildProjectDialog.GetAllFilesFromTree: TFilenameToStringTree;
502 var
503   Node: TTreeNode;
504   Item: TBuildProjectDialogItem;
505 begin
506   Result:=TFilenameToStringTree.Create(false);
507   Node:=FilesTreeView.Items.GetFirstNode;
508   while Node<>nil do begin
509     if (Node.Data<>nil) and (TObject(Node.Data) is TBuildProjectDialogItem) then
510     begin
511       Item:=TBuildProjectDialogItem(Node.Data);
512       if not Item.IsDirectory then
513         Result[Item.Filename]:='1';
514     end;
515     Node:=Node.GetNext;
516   end;
517 end;
518 
DeleteFilesnull519 function TCleanBuildProjectDialog.DeleteFiles: TModalResult;
520 var
521   Files: TFilenameToStringTree;
522   Node: TAVLTreeNode;
523   Item: PStringToStringItem;
524   MaskList: TMaskList;
525   Filename: String;
526   SourceFiles: TStringList;
527   Quiet: Boolean;
528 begin
529   Files:=GetAllFilesFromTree;
530   MaskList:=TMaskList.Create('*.pas;*.pp;*.p;*.inc;*.lpr;*.lpi;*.lps;*.lpk',';');
531   SourceFiles:=TStringList.Create;
532   try
533     // warn before deleting sources
534     Node:=Files.Tree.FindLowest;
535     while Node<>nil do begin
536       Item:=PStringToStringItem(Node.Data);
537       Filename:=Item^.Name;
538       if MaskList.Matches(ExtractFilename(Filename)) then
539         SourceFiles.Add(Filename);
540       Node:=Files.Tree.FindSuccessor(Node);
541     end;
542     if SourceFiles.Count>0 then begin
543       Result:=IDEMessageDialog(lisCCOWarningCaption,
544         Format(lisCBPReallyDeleteSourceFiles, [IntToStr(SourceFiles.Count),
545           LineEnding+LineEnding, copy(SourceFiles.Text, 1, 1000)]),
546         mtWarning, [mbYes, mbNo]);
547       if Result<>mrYes then exit(mrCancel);
548     end;
549 
550     // delete
551     Node:=Files.Tree.FindLowest;
552     Quiet:=false;
553     while Node<>nil do begin
554       Item:=PStringToStringItem(Node.Data);
555       Node:=Files.Tree.FindSuccessor(Node);
556       Filename:=Item^.Name;
557       //debugln(['TBuildProjectDialog.DeleteFiles ',Filename,' ',FileExistsUTF8(Filename)]);
558       repeat
559         if FileExistsUTF8(Filename) and (not DeleteFileUTF8(Filename))
560         and (not Quiet) then begin
561           Result:=IDEQuestionDialog(lisDeleteFileFailed,
562               Format(lisPkgMangUnableToDeleteFile, [Filename]),
563               mtError, [mrRetry,
564                         mrCancel,
565                         mrNo, lisCCOSkip,
566                         mrNoToAll, lisSkipErrors]);
567           if Result=mrNoToAll then begin
568             Quiet:=true;
569             break;
570           end;
571           if Result=mrNo then break;
572           if Result<>mrRetry then exit(mrCancel);
573         end else break;
574       until false;
575     end;
576 
577     Result:=mrOk;
578   finally
579     InvalidateFileStateCache;
580     UpdateFilesTreeView;
581     SourceFiles.Free;
582     MaskList.Free;
583     Files.Free;
584   end;
585 end;
586 
587 procedure TCleanBuildProjectDialog.Init(AProject: TProject);
588 var
589   List: THistoryList;
590 begin
591   List:=InputHistories.HistoryLists.GetList(hlCleanBuildFileMask,true,rltFile);
592   ProjOutMaskComboBox.Items.Assign(List);
593   ProjOutMaskComboBox.Text:=AProject.CleanOutputFileMask;
594   ProjSrcMaskComboBox.Items.Assign(List);
595   ProjSrcMaskComboBox.Text:=AProject.CleanSourcesFileMask;
596   PkgOutMaskComboBox.Items.Assign(List);
597   PkgOutMaskComboBox.Text:=InputHistories.CleanOutputFileMask;
598   PkgSrcMaskComboBox.Items.Assign(List);
599   PkgSrcMaskComboBox.Text:=InputHistories.CleanSourcesFileMask;
600 
601   ProjOutCheckBox.Checked:=EnvironmentOptions.CleanBuildProjOut;
602   ProjSrcCheckBox.Checked:=EnvironmentOptions.CleanBuildProjSrc;
603   PkgOutCheckBox.Checked :=EnvironmentOptions.CleanBuildPkgOut;
604   PkgSrcCheckBox.Checked :=EnvironmentOptions.CleanBuildPkgSrc;
605 
606   if AProject.CompilerOptions.UnitOutputDirectory='' then begin
607     ProjOutCheckBox.Enabled:=false;
608     ProjOutCheckBox.Checked:=false;
609     ProjOutMaskComboBox.Enabled:=false;
610   end;
611 
612   FProject:=AProject;
613   UpdateFilesTreeView;
614 end;
615 
616 end.
617 
618