1 /*
2 * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3 * http://www.gnu.org/licenses/gpl-3.0.html
4 *
5 * $Revision: 11883 $
6 * $Id: compileroptionsdlg.cpp 11883 2019-10-26 09:11:12Z fuscated $
7 * $HeadURL: svn://svn.code.sf.net/p/codeblocks/code/branches/release-20.xx/src/plugins/compilergcc/compileroptionsdlg.cpp $
8 */
9
10 #include <sdk.h>
11 #include <prep.h>
12 #ifndef CB_PRECOMP
13 #include <algorithm>
14 #include <wx/arrstr.h>
15 #include <wx/button.h>
16 #include <wx/checkbox.h>
17 #include <wx/checklst.h>
18 #include <wx/choice.h>
19 #include <wx/event.h>
20 #include <wx/filename.h>
21 #include <wx/listbox.h>
22 #include <wx/menu.h>
23 #include <wx/notebook.h>
24 #include <wx/stattext.h>
25 #include <wx/sizer.h>
26 #include <wx/spinctrl.h>
27 #include <wx/textdlg.h>
28 #include <wx/treectrl.h>
29 #include <wx/xrc/xmlres.h>
30
31 #include "compiler.h"
32 #include "compilerfactory.h"
33 #include "configmanager.h"
34 #include "globals.h"
35 #include "macrosmanager.h"
36 #include "manager.h"
37 #include "logmanager.h"
38 #include "projectmanager.h"
39 #endif
40 #include <wx/filedlg.h>
41 #include <wx/propgrid/propgrid.h>
42 #include <wx/xml/xml.h>
43
44 #include "advancedcompileroptionsdlg.h"
45 #include "annoyingdialog.h"
46 #include "cbexception.h"
47 #include "compilergcc.h"
48 #include "compileroptionsdlg.h"
49 #include "debuggermanager.h"
50 #include "editpathdlg.h"
51 #include "editpairdlg.h"
52 #include "compilerflagdlg.h"
53
54 // TO DO : - add/edit/delete compiler : applies directly , so no cancel out (change this behaviour)
55 // - compiler change of project/target -> check if the policy is still sound (both should have the same compiler)
56 // - compiler change of project/target -> all options should be removed : different compiler is different options
57 // - directory add/edit and library add/edit : check if it already existed
58
59 BEGIN_EVENT_TABLE(CompilerOptionsDlg, wxPanel)
60 EVT_UPDATE_UI( XRCID("btnEditDir"), CompilerOptionsDlg::OnUpdateUI)
61 EVT_UPDATE_UI( XRCID("btnDelDir"), CompilerOptionsDlg::OnUpdateUI)
62 EVT_UPDATE_UI( XRCID("btnClearDir"), CompilerOptionsDlg::OnUpdateUI)
63 EVT_UPDATE_UI( XRCID("btnCopyDirs"), CompilerOptionsDlg::OnUpdateUI)
64 EVT_UPDATE_UI( XRCID("btnMoveDirUp"), CompilerOptionsDlg::OnUpdateUI)
65 EVT_UPDATE_UI( XRCID("btnMoveDirDown"), CompilerOptionsDlg::OnUpdateUI)
66 EVT_UPDATE_UI( XRCID("btnEditVar"), CompilerOptionsDlg::OnUpdateUI)
67 EVT_UPDATE_UI( XRCID("btnDeleteVar"), CompilerOptionsDlg::OnUpdateUI)
68 EVT_UPDATE_UI( XRCID("btnClearVar"), CompilerOptionsDlg::OnUpdateUI)
69 EVT_UPDATE_UI( XRCID("cmbCompilerPolicy"), CompilerOptionsDlg::OnUpdateUI)
70 EVT_UPDATE_UI( XRCID("cmbLinkerPolicy"), CompilerOptionsDlg::OnUpdateUI)
71 EVT_UPDATE_UI( XRCID("cmbIncludesPolicy"), CompilerOptionsDlg::OnUpdateUI)
72 EVT_UPDATE_UI( XRCID("cmbLibDirsPolicy"), CompilerOptionsDlg::OnUpdateUI)
73 EVT_UPDATE_UI( XRCID("cmbResDirsPolicy"), CompilerOptionsDlg::OnUpdateUI)
74 EVT_UPDATE_UI( XRCID("btnSetDefaultCompiler"), CompilerOptionsDlg::OnUpdateUI)
75 EVT_UPDATE_UI( XRCID("btnAddCompiler"), CompilerOptionsDlg::OnUpdateUI)
76 EVT_UPDATE_UI( XRCID("btnRenameCompiler"), CompilerOptionsDlg::OnUpdateUI)
77 EVT_UPDATE_UI( XRCID("btnDelCompiler"), CompilerOptionsDlg::OnUpdateUI)
78 EVT_UPDATE_UI( XRCID("btnResetCompiler"), CompilerOptionsDlg::OnUpdateUI)
79 EVT_UPDATE_UI( XRCID("btnAddLib"), CompilerOptionsDlg::OnUpdateUI)
80 EVT_UPDATE_UI( XRCID("btnEditLib"), CompilerOptionsDlg::OnUpdateUI)
81 EVT_UPDATE_UI( XRCID("btnDelLib"), CompilerOptionsDlg::OnUpdateUI)
82 EVT_UPDATE_UI( XRCID("btnClearLib"), CompilerOptionsDlg::OnUpdateUI)
83 EVT_UPDATE_UI( XRCID("btnCopyLibs"), CompilerOptionsDlg::OnUpdateUI)
84 EVT_UPDATE_UI( XRCID("btnMoveLibUp"), CompilerOptionsDlg::OnUpdateUI)
85 EVT_UPDATE_UI( XRCID("btnMoveLibDown"), CompilerOptionsDlg::OnUpdateUI)
86 EVT_UPDATE_UI( XRCID("txtMasterPath"), CompilerOptionsDlg::OnUpdateUI)
87 EVT_UPDATE_UI( XRCID("btnMasterPath"), CompilerOptionsDlg::OnUpdateUI)
88 EVT_UPDATE_UI( XRCID("btnExtraAdd"), CompilerOptionsDlg::OnUpdateUI)
89 EVT_UPDATE_UI( XRCID("btnExtraEdit"), CompilerOptionsDlg::OnUpdateUI)
90 EVT_UPDATE_UI( XRCID("btnExtraDelete"), CompilerOptionsDlg::OnUpdateUI)
91 EVT_UPDATE_UI( XRCID("btnExtraClear"), CompilerOptionsDlg::OnUpdateUI)
92 EVT_UPDATE_UI( XRCID("txtCcompiler"), CompilerOptionsDlg::OnUpdateUI)
93 EVT_UPDATE_UI( XRCID("btnCcompiler"), CompilerOptionsDlg::OnUpdateUI)
94 EVT_UPDATE_UI( XRCID("txtCPPcompiler"), CompilerOptionsDlg::OnUpdateUI)
95 EVT_UPDATE_UI( XRCID("btnCPPcompiler"), CompilerOptionsDlg::OnUpdateUI)
96 EVT_UPDATE_UI( XRCID("txtLinker"), CompilerOptionsDlg::OnUpdateUI)
97 EVT_UPDATE_UI( XRCID("btnLinker"), CompilerOptionsDlg::OnUpdateUI)
98 EVT_UPDATE_UI( XRCID("txtLibLinker"), CompilerOptionsDlg::OnUpdateUI)
99 EVT_UPDATE_UI( XRCID("btnLibLinker"), CompilerOptionsDlg::OnUpdateUI)
100 EVT_UPDATE_UI( XRCID("cmbDebugger"), CompilerOptionsDlg::OnUpdateUI)
101 EVT_UPDATE_UI( XRCID("txtResComp"), CompilerOptionsDlg::OnUpdateUI)
102 EVT_UPDATE_UI( XRCID("btnResComp"), CompilerOptionsDlg::OnUpdateUI)
103 EVT_UPDATE_UI( XRCID("txtMake"), CompilerOptionsDlg::OnUpdateUI)
104 EVT_UPDATE_UI( XRCID("btnMake"), CompilerOptionsDlg::OnUpdateUI)
105 EVT_UPDATE_UI( XRCID("cmbCompiler"), CompilerOptionsDlg::OnUpdateUI)
106 EVT_UPDATE_UI( XRCID("btnIgnoreAdd"), CompilerOptionsDlg::OnUpdateUI)
107 EVT_UPDATE_UI( XRCID("btnIgnoreRemove"), CompilerOptionsDlg::OnUpdateUI)
108 //
109 EVT_TREE_SEL_CHANGED( XRCID("tcScope"), CompilerOptionsDlg::OnTreeSelectionChange)
110 EVT_TREE_SEL_CHANGING( XRCID("tcScope"), CompilerOptionsDlg::OnTreeSelectionChanging)
111 EVT_CHOICE( XRCID("cmbCategory"), CompilerOptionsDlg::OnCategoryChanged)
112 EVT_CHOICE( XRCID("cmbCompiler"), CompilerOptionsDlg::OnCompilerChanged)
113 EVT_LISTBOX_DCLICK( XRCID("lstVars"), CompilerOptionsDlg::OnEditVarClick)
114 EVT_BUTTON( XRCID("btnSetDefaultCompiler"), CompilerOptionsDlg::OnSetDefaultCompilerClick)
115 EVT_BUTTON( XRCID("btnAddCompiler"), CompilerOptionsDlg::OnAddCompilerClick)
116 EVT_BUTTON( XRCID("btnRenameCompiler"), CompilerOptionsDlg::OnEditCompilerClick)
117 EVT_BUTTON( XRCID("btnDelCompiler"), CompilerOptionsDlg::OnRemoveCompilerClick)
118 EVT_BUTTON( XRCID("btnResetCompiler"), CompilerOptionsDlg::OnResetCompilerClick)
119 EVT_BUTTON( XRCID("btnAddDir"), CompilerOptionsDlg::OnAddDirClick)
120 EVT_BUTTON( XRCID("btnEditDir"), CompilerOptionsDlg::OnEditDirClick)
121 EVT_LISTBOX_DCLICK( XRCID("lstIncludeDirs"), CompilerOptionsDlg::OnEditDirClick)
122 EVT_LISTBOX_DCLICK( XRCID("lstLibDirs"), CompilerOptionsDlg::OnEditDirClick)
123 EVT_LISTBOX_DCLICK( XRCID("lstResDirs"), CompilerOptionsDlg::OnEditDirClick)
124 EVT_BUTTON( XRCID("btnDelDir"), CompilerOptionsDlg::OnRemoveDirClick)
125 EVT_BUTTON( XRCID("btnClearDir"), CompilerOptionsDlg::OnClearDirClick)
126 EVT_BUTTON( XRCID("btnCopyDirs"), CompilerOptionsDlg::OnCopyDirsClick)
127 EVT_BUTTON( XRCID("btnAddLib"), CompilerOptionsDlg::OnAddLibClick)
128 EVT_BUTTON( XRCID("btnEditLib"), CompilerOptionsDlg::OnEditLibClick)
129 EVT_LISTBOX_DCLICK( XRCID("lstLibs"), CompilerOptionsDlg::OnEditLibClick)
130 EVT_BUTTON( XRCID("btnDelLib"), CompilerOptionsDlg::OnRemoveLibClick)
131 EVT_BUTTON( XRCID("btnClearLib"), CompilerOptionsDlg::OnClearLibClick)
132 EVT_BUTTON( XRCID("btnCopyLibs"), CompilerOptionsDlg::OnCopyLibsClick)
133 EVT_LISTBOX_DCLICK( XRCID("lstExtraPaths"), CompilerOptionsDlg::OnEditExtraPathClick)
134 EVT_BUTTON( XRCID("btnExtraAdd"), CompilerOptionsDlg::OnAddExtraPathClick)
135 EVT_BUTTON( XRCID("btnExtraEdit"), CompilerOptionsDlg::OnEditExtraPathClick)
136 EVT_BUTTON( XRCID("btnExtraDelete"), CompilerOptionsDlg::OnRemoveExtraPathClick)
137 EVT_BUTTON( XRCID("btnExtraClear"), CompilerOptionsDlg::OnClearExtraPathClick)
138 EVT_BUTTON( XRCID("btnMoveLibUp"), CompilerOptionsDlg::OnMoveLibUpClick)
139 EVT_BUTTON( XRCID("btnMoveLibDown"), CompilerOptionsDlg::OnMoveLibDownClick)
140 EVT_BUTTON( XRCID("btnMoveDirUp"), CompilerOptionsDlg::OnMoveDirUpClick)
141 EVT_BUTTON( XRCID("btnMoveDirDown"), CompilerOptionsDlg::OnMoveDirDownClick)
142 EVT_BUTTON( XRCID("btnAddVar"), CompilerOptionsDlg::OnAddVarClick)
143 EVT_BUTTON( XRCID("btnEditVar"), CompilerOptionsDlg::OnEditVarClick)
144 EVT_BUTTON( XRCID("btnDeleteVar"), CompilerOptionsDlg::OnRemoveVarClick)
145 EVT_BUTTON( XRCID("btnClearVar"), CompilerOptionsDlg::OnClearVarClick)
146 EVT_BUTTON( XRCID("btnMasterPath"), CompilerOptionsDlg::OnMasterPathClick)
147 EVT_BUTTON( XRCID("btnAutoDetect"), CompilerOptionsDlg::OnAutoDetectClick)
148 EVT_BUTTON( XRCID("btnCcompiler"), CompilerOptionsDlg::OnSelectProgramClick)
149 EVT_BUTTON( XRCID("btnCPPcompiler"), CompilerOptionsDlg::OnSelectProgramClick)
150 EVT_BUTTON( XRCID("btnLinker"), CompilerOptionsDlg::OnSelectProgramClick)
151 EVT_BUTTON( XRCID("btnLibLinker"), CompilerOptionsDlg::OnSelectProgramClick)
152 EVT_BUTTON( XRCID("btnResComp"), CompilerOptionsDlg::OnSelectProgramClick)
153 EVT_BUTTON( XRCID("btnMake"), CompilerOptionsDlg::OnSelectProgramClick)
154 EVT_BUTTON( XRCID("btnAdvanced"), CompilerOptionsDlg::OnAdvancedClick)
155 EVT_BUTTON( XRCID("btnIgnoreAdd"), CompilerOptionsDlg::OnIgnoreAddClick)
156 EVT_BUTTON( XRCID("btnIgnoreRemove"), CompilerOptionsDlg::OnIgnoreRemoveClick)
157 EVT_CHOICE( XRCID("cmbCompilerPolicy"), CompilerOptionsDlg::OnDirty)
158 EVT_CHOICE( XRCID("cmbLinkerPolicy"), CompilerOptionsDlg::OnDirty)
159 EVT_CHOICE( XRCID("cmbIncludesPolicy"), CompilerOptionsDlg::OnDirty)
160 EVT_CHOICE( XRCID("cmbLibDirsPolicy"), CompilerOptionsDlg::OnDirty)
161 EVT_CHOICE( XRCID("cmbResDirsPolicy"), CompilerOptionsDlg::OnDirty)
162 EVT_CHOICE( XRCID("cmbLogging"), CompilerOptionsDlg::OnDirty)
163 EVT_CHOICE( XRCID("chLinkerExe"), CompilerOptionsDlg::OnDirty)
164 EVT_CHECKBOX( XRCID("chkAlwaysRunPost"), CompilerOptionsDlg::OnDirty)
165 EVT_CHECKBOX( XRCID("chkNonPlatComp"), CompilerOptionsDlg::OnDirty)
166 EVT_TEXT( XRCID("txtCompilerOptions"), CompilerOptionsDlg::OnDirty)
167 EVT_TEXT( XRCID("txtResourceCompilerOptions"), CompilerOptionsDlg::OnDirty)
168 EVT_TEXT( XRCID("txtCompilerDefines"), CompilerOptionsDlg::OnDirty)
169 EVT_TEXT( XRCID("txtLinkerOptions"), CompilerOptionsDlg::OnDirty)
170 EVT_TEXT( XRCID("txtCmdBefore"), CompilerOptionsDlg::OnDirty)
171 EVT_TEXT( XRCID("txtCmdAfter"), CompilerOptionsDlg::OnDirty)
172 EVT_TEXT( XRCID("txtMasterPath"), CompilerOptionsDlg::OnDirty)
173 EVT_TEXT( XRCID("txtCcompiler"), CompilerOptionsDlg::OnDirty)
174 EVT_TEXT( XRCID("txtCPPcompiler"), CompilerOptionsDlg::OnDirty)
175 EVT_TEXT( XRCID("txtLinker"), CompilerOptionsDlg::OnDirty)
176 EVT_TEXT( XRCID("txtLibLinker"), CompilerOptionsDlg::OnDirty)
177 EVT_TEXT( XRCID("txtResComp"), CompilerOptionsDlg::OnDirty)
178 EVT_TEXT( XRCID("txtMake"), CompilerOptionsDlg::OnDirty)
179 EVT_TEXT( XRCID("txtMakeCmd_Build"), CompilerOptionsDlg::OnDirty)
180 EVT_TEXT( XRCID("txtMakeCmd_Compile"), CompilerOptionsDlg::OnDirty)
181 EVT_TEXT( XRCID("txtMakeCmd_Clean"), CompilerOptionsDlg::OnDirty)
182 // EVT_TEXT( XRCID("txtMakeCmd_DistClean"), CompilerOptionsDlg::OnDirty)
183 EVT_TEXT( XRCID("txtMakeCmd_AskRebuildNeeded"), CompilerOptionsDlg::OnDirty)
184 // EVT_TEXT( XRCID("txtMakeCmd_SilentBuild"), CompilerOptionsDlg::OnDirty)
185 EVT_CHAR_HOOK(CompilerOptionsDlg::OnMyCharHook)
186
187 EVT_PG_CHANGED( XRCID("pgCompilerFlags"), CompilerOptionsDlg::OnOptionChanged)
188 EVT_PG_RIGHT_CLICK( XRCID("pgCompilerFlags"), CompilerOptionsDlg::OnFlagsPopup)
189 EVT_PG_DOUBLE_CLICK( XRCID("pgCompilerFlags"), CompilerOptionsDlg::OnOptionDoubleClick)
190 END_EVENT_TABLE()
191
192 class ScopeTreeData : public wxTreeItemData
193 {
194 public:
ScopeTreeData(cbProject * project,ProjectBuildTarget * target)195 ScopeTreeData(cbProject* project, ProjectBuildTarget* target){ m_Project = project; m_Target = target; }
GetProject()196 cbProject* GetProject(){ return m_Project; }
GetTarget()197 ProjectBuildTarget* GetTarget(){ return m_Target; }
198 private:
199 cbProject* m_Project;
200 ProjectBuildTarget* m_Target;
201 };
202
203 struct DebuggerClientData : wxClientData
204 {
DebuggerClientDataDebuggerClientData205 DebuggerClientData(const wxString &s) : string(s) {}
206 wxString string;
207 };
208
209 struct VariableListClientData : wxClientData
210 {
VariableListClientDataVariableListClientData211 VariableListClientData(const wxString &key, const wxString &value) : key(key), value(value) {}
212 wxString key, value;
213 };
214
215 /*
216 CompilerOptions can exist on 3 different levels :
217 Level 1 : compiler level
218 - the options exist on the global level of the compiler
219 Level 2 : project level
220 - the options exist on the level of the project
221 Level 3 : the target level
222 - the options exist on the level of the target
223 */
224
CompilerOptionsDlg(wxWindow * parent,CompilerGCC * compiler,cbProject * project,ProjectBuildTarget * target)225 CompilerOptionsDlg::CompilerOptionsDlg(wxWindow* parent, CompilerGCC* compiler, cbProject* project, ProjectBuildTarget* target) :
226 m_FlagsPG(nullptr),
227 m_Compiler(compiler),
228 m_CurrentCompilerIdx(0),
229 m_pProject(project),
230 m_pTarget(target),
231 m_bDirty(false),
232 m_BuildingTree(false)
233 {
234 wxXmlResource::Get()->LoadPanel(this, parent, _T("dlgCompilerOptions"));
235
236 m_FlagsPG = new wxPropertyGrid(this, XRCID("pgCompilerFlags"), wxDefaultPosition, wxDefaultSize,
237 wxTAB_TRAVERSAL|wxPG_SPLITTER_AUTO_CENTER);
238 m_FlagsPG->SetExtraStyle(wxPG_EX_HELP_AS_TOOLTIPS);
239 m_FlagsPG->SetColumnProportion(0, 70);
240 m_FlagsPG->SetColumnProportion(1, 30);
241
242 m_FlagsPG->SetMinSize(wxSize(400, 400));
243 wxXmlResource::Get()->AttachUnknownControl(wxT("pgCompilerFlags"), m_FlagsPG);
244
245 if (m_pProject)
246 {
247 bool hasBuildScripts = m_pProject->GetBuildScripts().GetCount() != 0;
248 if (!hasBuildScripts)
249 {
250 // look in targets
251 for (int x = 0; x < m_pProject->GetBuildTargetsCount(); ++x)
252 {
253 ProjectBuildTarget* curr_target = m_pProject->GetBuildTarget(x);
254 hasBuildScripts = curr_target->GetBuildScripts().GetCount() != 0;
255 if (hasBuildScripts)
256 break;
257 }
258 }
259
260 XRCCTRL(*this, "lblBuildScriptsNote", wxStaticText)->Show(hasBuildScripts);
261 }
262
263 wxTreeCtrl* tree = XRCCTRL(*this, "tcScope", wxTreeCtrl);
264 wxSizer* sizer = tree->GetContainingSizer();
265 wxNotebook* nb = XRCCTRL(*this, "nbMain", wxNotebook);
266 if (!m_pProject)
267 {
268 // global settings
269 SetLabel(_("Compiler Settings"));
270 sizer->Show(tree,false);
271 sizer->Detach(tree);
272 nb->DeletePage(6); // remove "Make" page
273 nb->DeletePage(3); // remove "Commands" page
274 }
275 else
276 {
277 // project settings
278 nb->DeletePage(8); // remove "Other settings" page
279 nb->DeletePage(7); // remove "Build options" page
280 nb->DeletePage(4); // remove "Toolchain executables" page
281
282 // remove "Compiler" buttons
283 wxWindow* win = XRCCTRL(*this, "btnAddCompiler", wxButton);
284 wxSizer* sizer2 = win->GetContainingSizer();
285 sizer2->Clear(true);
286 sizer2->Layout();
287
288 // disable "Make" elements, if project is not using custom makefile
289 bool en = project->IsMakefileCustom();
290 XRCCTRL(*this, "txtMakeCmd_Build", wxTextCtrl)->Enable(en);
291 XRCCTRL(*this, "txtMakeCmd_Compile", wxTextCtrl)->Enable(en);
292 XRCCTRL(*this, "txtMakeCmd_Clean", wxTextCtrl)->Enable(en);
293 XRCCTRL(*this, "txtMakeCmd_DistClean", wxTextCtrl)->Enable(en);
294 XRCCTRL(*this, "txtMakeCmd_AskRebuildNeeded", wxTextCtrl)->Enable(en);
295 XRCCTRL(*this, "txtMakeCmd_SilentBuild", wxTextCtrl)->Enable(en);
296 }
297
298 // let's start filling in all the panels of the configuration dialog
299 // there are compiler dependent settings and compiler independent settings
300
301 // compiler independent (so settings these ones is sufficient)
302 DoFillOthers();
303 DoFillTree();
304 int compilerIdx = CompilerFactory::GetCompilerIndex(CompilerFactory::GetDefaultCompilerID());
305 if (m_pTarget)
306 compilerIdx = CompilerFactory::GetCompilerIndex(m_pTarget->GetCompilerID());
307 else if (m_pProject)
308 compilerIdx = CompilerFactory::GetCompilerIndex(m_pProject->GetCompilerID());
309 if ((m_pTarget || m_pProject) && compilerIdx == -1)
310 { // unknown user compiler
311 // similar code can be found @ OnTreeSelectionChange()
312 // see there for more info : duplicate code now, since here we still need
313 // to fill in the compiler list for the choice control, where in
314 // OnTreeSelectionChange we just need to set an entry
315 // TODO : make 1 help method out of this, with some argument indicating
316 // to fill the choice list, or break it in 2 methods with the list filling in between them
317 // or maybe time will bring even brighter ideas
318 wxString CompilerId = m_pTarget?m_pTarget->GetCompilerID():m_pProject->GetCompilerID();
319 wxString msg;
320 msg.Printf(_("The defined compiler cannot be located (ID: %s).\n"
321 "Please choose the compiler you want to use instead and click \"OK\".\n"
322 "If you click \"Cancel\", the project/target will remain configured for\n"
323 "that compiler and consequently can not be configured and will not be built."),
324 CompilerId.wx_str());
325 Compiler* comp = 0;
326 if ((m_pTarget && m_pTarget->SupportsCurrentPlatform()) || (!m_pTarget && m_pProject))
327 comp = CompilerFactory::SelectCompilerUI(msg);
328
329 if (comp)
330 { // a new compiler was chosen, proceed as if the user manually selected another compiler
331 // that means set the compiler selection list accordingly
332 // and go directly to (On)CompilerChanged
333 int NewCompilerIdx = CompilerFactory::GetCompilerIndex(comp);
334 DoFillCompilerSets(NewCompilerIdx);
335 wxCommandEvent Dummy;
336 OnCompilerChanged(Dummy);
337 }
338 else
339 { // the user cancelled and wants to keep the compiler
340 DoFillCompilerSets(compilerIdx);
341 if (nb)
342 nb->Disable();
343 }
344 }
345 else
346 {
347 if (!CompilerFactory::GetCompiler(compilerIdx))
348 compilerIdx = 0;
349 DoFillCompilerSets(compilerIdx);
350 m_Options = CompilerFactory::GetCompiler(compilerIdx)->GetOptions();
351 m_CurrentCompilerIdx = compilerIdx;
352 // compiler dependent settings
353 DoFillCompilerDependentSettings();
354 }
355 if (m_pTarget && m_pTarget->GetTargetType() == ttCommandsOnly)
356 {
357 // disable pages for commands only target
358 nb->GetPage(0)->Disable(); // Compiler settings
359 nb->GetPage(1)->Disable(); // Linker settings
360 nb->GetPage(2)->Disable(); // Search directories
361 nb->GetPage(5)->Disable(); // "Make" commands
362 nb->SetSelection(3); // Pre/post build steps
363 }
364 else
365 nb->SetSelection(0);
366 sizer->Layout();
367 Layout();
368 GetSizer()->Layout();
369 GetSizer()->SetSizeHints(this);
370 #ifdef __WXMAC__
371 // seems it's not big enough on the Apple/Mac : hacking time
372 int min_width, min_height;
373 GetSize(&min_width, &min_height);
374 this->SetSizeHints(min_width+140,min_height,-1,-1);
375 #endif
376 this->SetSize(-1, -1, 0, 0);
377 // disable some elements, if project is using custom makefile
378 // we do this after the layout is done, so the resulting dialog has always the same size
379 if (project && project->IsMakefileCustom())
380 {
381 nb->RemovePage(2); // remove "Search directories" page
382 nb->RemovePage(1); // remove "Linker settings" page
383 nb->RemovePage(0); // remove "Compiler settings" page
384 XRCCTRL(*this, "tabCompiler", wxPanel)->Show(false);
385 XRCCTRL(*this, "tabLinker", wxPanel)->Show(false);
386 XRCCTRL(*this, "tabDirs", wxPanel)->Show(false);
387 }
388
389 Fit();
390 } // constructor
391
~CompilerOptionsDlg()392 CompilerOptionsDlg::~CompilerOptionsDlg()
393 {
394 //dtor
395 }
396
DoFillCompilerSets(int compilerIdx)397 void CompilerOptionsDlg::DoFillCompilerSets(int compilerIdx)
398 {
399 wxChoice* cmb = XRCCTRL(*this, "cmbCompiler", wxChoice);
400 cmb->Clear();
401 for (unsigned int i = 0; i < CompilerFactory::GetCompilersCount(); ++i)
402 {
403 cmb->Append(CompilerFactory::GetCompiler(i)->GetName());
404 }
405
406 // int compilerIdx = CompilerFactory::GetCompilerIndex(CompilerFactory::GetDefaultCompilerID());
407 // if (m_pTarget)
408 // compilerIdx = CompilerFactory::GetCompilerIndex(m_pTarget->GetCompilerID());
409 // else if (m_pProject)
410 // compilerIdx = CompilerFactory::GetCompilerIndex(m_pProject->GetCompilerID());
411
412 // if (!CompilerFactory::GetCompiler(compilerIdx))
413 // compilerIdx = 0;
414 // m_Options = CompilerFactory::GetCompiler(compilerIdx)->GetOptions();
415 if (compilerIdx != -1)
416 cmb->SetSelection(compilerIdx);
417
418 // m_CurrentCompilerIdx = compilerIdx;
419 } // DoFillCompilerSets
420
DoFillCompilerDependentSettings()421 void CompilerOptionsDlg::DoFillCompilerDependentSettings()
422 {
423 DoFillCompilerPrograms(); // the programs executable's ...
424 DoLoadOptions();
425 DoFillVars();
426 // by the way we listen to changes in the textctrl, we also end up in the callbacks as
427 // a result of wxTextCtrl::SetValue, the preceding called methods did some of those -> reset dirty flag
428 m_bDirty = false;
429 m_bFlagsDirty = false;
430 } // DoFillCompilerDependentSettings
431
DoSaveCompilerDependentSettings()432 void CompilerOptionsDlg::DoSaveCompilerDependentSettings()
433 {
434 DoSaveCompilerPrograms();
435 DoSaveOptions();
436 DoSaveVars();
437 if (m_bFlagsDirty)
438 DoSaveCompilerDefinition();
439 ProjectTargetCompilerAdjust();
440 m_bDirty = false;
441 m_bFlagsDirty = false;
442 } // DoSaveCompilerDependentSettings
443
ArrayString2ListBox(const wxArrayString & array,wxListBox * control)444 inline void ArrayString2ListBox(const wxArrayString& array, wxListBox* control)
445 {
446 control->Clear();
447 int count = array.GetCount();
448 for (int i = 0; i < count; ++i)
449 {
450 if (!array[i].IsEmpty())
451 control->Append(array[i]);
452 }
453 } // ArrayString2ListBox
454
ListBox2ArrayString(wxArrayString & array,const wxListBox * control)455 inline void ListBox2ArrayString(wxArrayString& array, const wxListBox* control)
456 {
457 array.Clear();
458 int count = control->GetCount();
459 for (int i = 0; i < count; ++i)
460 {
461 wxString tmp = control->GetString(i);
462 if (!tmp.IsEmpty())
463 array.Add(tmp);
464 }
465 } // ListBox2ArrayString
466
DoFillCompilerPrograms()467 void CompilerOptionsDlg::DoFillCompilerPrograms()
468 {
469 if (m_pProject)
470 return; // no "Programs" page
471
472 const Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
473 if (!compiler)
474 return;
475 const CompilerPrograms& progs = compiler->GetPrograms();
476
477 XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->SetValue(compiler->GetMasterPath());
478 XRCCTRL(*this, "txtCcompiler", wxTextCtrl)->SetValue(progs.C);
479 XRCCTRL(*this, "txtCPPcompiler", wxTextCtrl)->SetValue(progs.CPP);
480 XRCCTRL(*this, "txtLinker", wxTextCtrl)->SetValue(progs.LD);
481 XRCCTRL(*this, "txtLibLinker", wxTextCtrl)->SetValue(progs.LIB);
482 wxChoice *cmbDebugger = XRCCTRL(*this, "cmbDebugger", wxChoice);
483 if (cmbDebugger)
484 {
485 cmbDebugger->Clear();
486 // Add an invalid debugger entry and store the old value in the client data, so no user settings are changed.
487 cmbDebugger->Append(_("--- Invalid debugger ---"), new DebuggerClientData(progs.DBGconfig));
488 cmbDebugger->SetSelection(0);
489
490 const DebuggerManager::RegisteredPlugins &plugins = Manager::Get()->GetDebuggerManager()->GetAllDebuggers();
491 for (DebuggerManager::RegisteredPlugins::const_iterator it = plugins.begin(); it != plugins.end(); ++it)
492 {
493 const DebuggerManager::PluginData &data = it->second;
494 for (DebuggerManager::ConfigurationVector::const_iterator itConf = data.GetConfigurations().begin();
495 itConf != data.GetConfigurations().end();
496 ++itConf)
497 {
498 const wxString &def = it->first->GetSettingsName() + wxT(":") + (*itConf)->GetName();
499 int index = cmbDebugger->Append(it->first->GetGUIName() + wxT(" : ") + (*itConf)->GetName(),
500 new DebuggerClientData(def));
501 if (def == progs.DBGconfig)
502 cmbDebugger->SetSelection(index);
503 }
504 }
505 }
506
507 XRCCTRL(*this, "txtResComp", wxTextCtrl)->SetValue(progs.WINDRES);
508 XRCCTRL(*this, "txtMake", wxTextCtrl)->SetValue(progs.MAKE);
509
510 const wxArrayString& extraPaths = compiler->GetExtraPaths();
511 ArrayString2ListBox(extraPaths, XRCCTRL(*this, "lstExtraPaths", wxListBox));
512 } // DoFillCompilerPrograms
513
DoFillVars()514 void CompilerOptionsDlg::DoFillVars()
515 {
516 wxListBox* lst = XRCCTRL(*this, "lstVars", wxListBox);
517 if (!lst)
518 return;
519 lst->Clear();
520 const StringHash* vars = 0;
521 const CompileOptionsBase* base = GetVarsOwner();
522 if (base)
523 {
524 vars = &base->GetAllVars();
525 }
526 if (!vars)
527 return;
528 for (StringHash::const_iterator it = vars->begin(); it != vars->end(); ++it)
529 {
530 wxString text = it->first + _T(" = ") + it->second;
531 lst->Append(text, new VariableListClientData(it->first, it->second));
532 }
533 } // DoFillVars
534
DoFillOthers()535 void CompilerOptionsDlg::DoFillOthers()
536 {
537 if (m_pProject)
538 return; // projects don't have Other tab
539
540 wxCheckBox* chk = XRCCTRL(*this, "chkIncludeFileCwd", wxCheckBox);
541 if (chk)
542 chk->SetValue(Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/include_file_cwd"), false));
543
544 chk = XRCCTRL(*this, "chkIncludePrjCwd", wxCheckBox);
545 if (chk)
546 chk->SetValue(Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/include_prj_cwd"), false));
547
548 chk = XRCCTRL(*this, "chkSkipIncludeDeps", wxCheckBox);
549 if (chk)
550 chk->SetValue(Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/skip_include_deps"), false));
551
552 chk = XRCCTRL(*this, "chkSaveHtmlLog", wxCheckBox);
553 if (chk)
554 chk->SetValue(Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/save_html_build_log"), false));
555
556 chk = XRCCTRL(*this, "chkFullHtmlLog", wxCheckBox);
557 if (chk)
558 chk->SetValue(Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/save_html_build_log/full_command_line"), false));
559
560 chk = XRCCTRL(*this, "chkBuildProgressBar", wxCheckBox);
561 if (chk)
562 chk->SetValue(Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/build_progress/bar"), false));
563
564 chk = XRCCTRL(*this, "chkBuildProgressPerc", wxCheckBox);
565 if (chk)
566 chk->SetValue(Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/build_progress/percentage"), false));
567
568 wxSpinCtrl* spn = XRCCTRL(*this, "spnParallelProcesses", wxSpinCtrl);
569 if (spn)
570 spn->SetValue(Manager::Get()->GetConfigManager(_T("compiler"))->ReadInt(_T("/parallel_processes"), 0));
571
572 spn = XRCCTRL(*this, "spnMaxErrors", wxSpinCtrl);
573 if (spn)
574 {
575 spn->SetRange(0, 1000);
576 spn->SetValue(Manager::Get()->GetConfigManager(_T("compiler"))->ReadInt(_T("/max_reported_errors"), 50));
577 }
578
579 chk = XRCCTRL(*this, "chkRebuildSeperately", wxCheckBox);
580 if (chk)
581 chk->SetValue(Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/rebuild_seperately"), false));
582
583 wxListBox* lst = XRCCTRL(*this, "lstIgnore", wxListBox);
584 if (lst)
585 {
586 wxArrayString IgnoreOutput;
587 IgnoreOutput = Manager::Get()->GetConfigManager(_T("compiler"))->ReadArrayString(_T("/ignore_output"));
588 ArrayString2ListBox(IgnoreOutput, lst);
589 }
590
591 chk = XRCCTRL(*this, "chkNonPlatComp", wxCheckBox);
592 if (chk)
593 chk->SetValue(Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/non_plat_comp"), false));
594 } // DoFillOthers
595
DoFillTree()596 void CompilerOptionsDlg::DoFillTree()
597 {
598 m_BuildingTree = true;
599 wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
600 tc->DeleteAllItems();
601
602 wxTreeItemId root;
603 wxTreeItemId selectedItem;
604
605 if (!m_pProject)
606 {
607 // global settings
608 root = tc->AddRoot(_("Global options"), -1, -1);
609 selectedItem = root;
610 }
611 else
612 {
613 // project settings
614 // in case you wonder : the delete of data will be done by the wxTreeCtrl
615 ScopeTreeData* data = new ScopeTreeData(m_pProject, 0L);
616 root = tc->AddRoot(m_pProject->GetTitle(), -1, -1, data);
617 selectedItem = root;
618 for (int x = 0; x < m_pProject->GetBuildTargetsCount(); ++x)
619 {
620 ProjectBuildTarget* target = m_pProject->GetBuildTarget(x);
621 data = new ScopeTreeData(m_pProject, target);
622 wxTreeItemId targetItem = tc->AppendItem(root, target->GetTitle(), -1, -1, data);
623 if (target == m_pTarget)
624 selectedItem = targetItem;
625 }
626 }
627 // normally the target should be found in the targets of the project
628 // in case it is not, we will reset m_pTarget to 0 (in sync with tree selection)
629 if (selectedItem == root)
630 m_pTarget = 0;
631
632 tc->Expand(root);
633 tc->SelectItem(selectedItem);
634 m_BuildingTree = false;
635 } // DoFillTree
636
DoFillOptions()637 void CompilerOptionsDlg::DoFillOptions()
638 {
639 m_FlagsPG->Freeze();
640 m_FlagsPG->Clear();
641 typedef std::map<wxString, wxPropertyCategory*> MapCategories;
642 MapCategories categories;
643
644 // If there is a "General" category make sure it is added first.
645 for (size_t i = 0; i < m_Options.GetCount(); ++i)
646 {
647 const CompOption* option = m_Options.GetOption(i);
648 if (option->category == wxT("General"))
649 {
650 wxPropertyCategory *categoryProp = new wxPropertyCategory(option->category);
651 m_FlagsPG->Append(categoryProp);
652 categories[option->category] = categoryProp;
653 break;
654 }
655 }
656
657 // Add all flags and categories to the property grid
658 for (size_t i = 0; i < m_Options.GetCount(); ++i)
659 {
660 const CompOption* option = m_Options.GetOption(i);
661 wxPropertyCategory *categoryProp = nullptr;
662 MapCategories::iterator itCat = categories.find(option->category);
663 if (itCat != categories.end())
664 categoryProp = itCat->second;
665 else
666 {
667 categoryProp = new wxPropertyCategory(option->category);
668 m_FlagsPG->Append(categoryProp);
669 categories[option->category] = categoryProp;
670 }
671
672 wxPGProperty *prop = new wxBoolProperty(option->name, wxPG_LABEL, option->enabled);
673 m_FlagsPG->AppendIn(categoryProp, prop);
674 m_FlagsPG->SetPropertyAttribute(prop, wxPG_BOOL_USE_CHECKBOX, true, wxPG_RECURSE);
675 }
676
677 wxPGProperty *root = m_FlagsPG->GetRoot();
678 if (root)
679 {
680 unsigned count = root->GetChildCount();
681 for (unsigned ii = 0; ii < count; ++ii)
682 #if wxCHECK_VERSION(3, 0, 0)
683 m_FlagsPG->SortChildren(root->Item(ii), wxPG_RECURSE);
684 #else
685 m_FlagsPG->Sort(root->Item(ii));
686 #endif
687 }
688 m_FlagsPG->Thaw();
689 } // DoFillOptions
690
TextToOptions()691 void CompilerOptionsDlg::TextToOptions()
692 {
693 // disable all options
694 for (size_t n = 0; n < m_Options.GetCount(); ++n)
695 {
696 if (CompOption* copt = m_Options.GetOption(n))
697 copt->enabled = false;
698 }
699
700 wxString rest;
701
702 Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
703
704 XRCCTRL(*this, "txtCompilerDefines", wxTextCtrl)->Clear();
705 unsigned int i = 0;
706 while (i < m_CompilerOptions.GetCount())
707 {
708 wxString opt = m_CompilerOptions.Item(i);
709 opt = opt.Strip(wxString::both);
710 CompOption* copt = m_Options.GetOptionByOption(opt);
711 if (copt)
712 {
713 // Manager::Get()->GetLogManager()->DebugLog("Enabling option %s", copt->option.c_str());
714 copt->enabled = true;
715 m_CompilerOptions.RemoveAt(i, 1);
716 }
717 else if (compiler && opt.StartsWith(compiler->GetSwitches().defines, &rest))
718 {
719 // definition
720 XRCCTRL(*this, "txtCompilerDefines", wxTextCtrl)->AppendText(rest);
721 XRCCTRL(*this, "txtCompilerDefines", wxTextCtrl)->AppendText(_T("\n"));
722 m_CompilerOptions.RemoveAt(i, 1);
723 }
724 else
725 ++i;
726 }
727 i = 0;
728 while (i < m_LinkerOptions.GetCount())
729 {
730 wxString opt = m_LinkerOptions.Item(i);
731 opt = opt.Strip(wxString::both);
732 CompOption* copt = m_Options.GetOptionByAdditionalLibs(opt);
733 if (copt)
734 {
735 // Manager::Get()->GetLogManager()->DebugLog("Enabling option %s", copt->option.c_str());
736 copt->enabled = true;
737 m_LinkerOptions.RemoveAt(i, 1);
738 }
739 else
740 ++i;
741 }
742
743 XRCCTRL(*this, "lstLibs", wxListBox)->Clear();
744 for (unsigned int j = 0; j < m_LinkLibs.GetCount(); ++j)
745 XRCCTRL(*this, "lstLibs", wxListBox)->Append(m_LinkLibs[j]);
746
747 m_LinkLibs.Clear();
748 } // TextToOptions
749
ArrayString2TextCtrl(const wxArrayString & array,wxTextCtrl * control)750 inline void ArrayString2TextCtrl(const wxArrayString& array, wxTextCtrl* control)
751 {
752 control->Clear();
753 int count = array.GetCount();
754 for (int i = 0; i < count; ++i)
755 {
756 if (!array[i].IsEmpty())
757 {
758 control->AppendText(array[i]);
759 control->AppendText(_T('\n'));
760 }
761 }
762 } // ArrayString2TextCtrl
763
DoGetCompileOptions(wxArrayString & array,const wxTextCtrl * control)764 inline void DoGetCompileOptions(wxArrayString& array, const wxTextCtrl* control)
765 {
766 /* NOTE (mandrav#1#): Under Gnome2, wxTextCtrl::GetLineLength() returns always 0,
767 so wxTextCtrl::GetLineText() is always empty...
768 Now, we 're breaking up by newlines. */
769 array.Clear();
770 #if 1
771 wxString tmp = control->GetValue();
772 int nl = tmp.Find(_T('\n'));
773 wxString line;
774 if (nl == -1)
775 {
776 line = tmp;
777 tmp = _T("");
778 }
779 else
780 line = tmp.Left(nl);
781 while (nl != -1 || !line.IsEmpty())
782 {
783 // Manager::Get()->GetLogManager()->DebugLog("%s text=%s", control->GetName().c_str(), line.c_str());
784 if (!line.IsEmpty())
785 {
786 // just to make sure..
787 line.Replace(_T("\r"), _T(" "), true); // remove CRs
788 line.Replace(_T("\n"), _T(" "), true); // remove LFs
789 array.Add(line.Strip(wxString::both));
790 }
791 tmp.Remove(0, nl + 1);
792 nl = tmp.Find(_T('\n'));
793 if (nl == -1)
794 {
795 line = tmp;
796 tmp = _T("");
797 }
798 else
799 line = tmp.Left(nl);
800 }
801 #else
802 int count = control->GetNumberOfLines();
803 for (int i = 0; i < count; ++i)
804 {
805 wxString tmp = control->GetLineText(i);
806 if (!tmp.IsEmpty())
807 {
808 tmp.Replace(_T("\r"), _T(" "), true); // remove CRs
809 tmp.Replace(_T("\n"), _T(" "), true); // remove LFs
810 array.Add(tmp.Strip(wxString::both));
811 }
812 }
813 #endif
814 } // DoGetCompileOptions
815
DoLoadOptions()816 void CompilerOptionsDlg::DoLoadOptions()
817 {
818 wxArrayString CommandsBeforeBuild;
819 wxArrayString CommandsAfterBuild;
820 bool AlwaysUsePost = false;
821 wxArrayString IncludeDirs;
822 wxArrayString LibDirs;
823 wxArrayString ResDirs;
824
825 if (!m_pProject && !m_pTarget)
826 {
827 // global options
828 const Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
829 if (compiler)
830 {
831 IncludeDirs = compiler->GetIncludeDirs();
832 ResDirs = compiler->GetResourceIncludeDirs();
833 LibDirs = compiler->GetLibDirs();
834 m_CompilerOptions = compiler->GetCompilerOptions();
835 m_ResourceCompilerOptions = compiler->GetResourceCompilerOptions();
836 m_LinkerOptions = compiler->GetLinkerOptions();
837 m_LinkLibs = compiler->GetLinkLibs();
838
839 wxChoice* cmbLogging = XRCCTRL(*this, "cmbLogging", wxChoice);
840 if (cmbLogging)
841 cmbLogging->SetSelection((int)compiler->GetSwitches().logging);
842
843 wxChoice *cmbLinkerExe = XRCCTRL(*this, "chLinkerExe", wxChoice);
844 cmbLinkerExe->Show(false);
845 wxStaticText *txtLinkerExe = XRCCTRL(*this, "txtLinkerExe", wxStaticText);
846 txtLinkerExe->Show(false);
847 }
848 }
849 else
850 {
851 if (!m_pTarget)
852 {
853 // project options
854 SetLabel(_("Project build options"));
855 IncludeDirs = m_pProject->GetIncludeDirs();
856 ResDirs = m_pProject->GetResourceIncludeDirs();
857 LibDirs = m_pProject->GetLibDirs();
858 m_CompilerOptions = m_pProject->GetCompilerOptions();
859 m_ResourceCompilerOptions = m_pProject->GetResourceCompilerOptions();
860 m_LinkerOptions = m_pProject->GetLinkerOptions();
861 m_LinkLibs = m_pProject->GetLinkLibs();
862
863 CommandsAfterBuild = m_pProject->GetCommandsAfterBuild();
864 CommandsBeforeBuild = m_pProject->GetCommandsBeforeBuild();
865 AlwaysUsePost = m_pProject->GetAlwaysRunPostBuildSteps();
866
867 XRCCTRL(*this, "txtMakeCmd_Build", wxTextCtrl)->SetValue(m_pProject->GetMakeCommandFor(mcBuild));
868 XRCCTRL(*this, "txtMakeCmd_Compile", wxTextCtrl)->SetValue(m_pProject->GetMakeCommandFor(mcCompileFile));
869 XRCCTRL(*this, "txtMakeCmd_Clean", wxTextCtrl)->SetValue(m_pProject->GetMakeCommandFor(mcClean));
870 XRCCTRL(*this, "txtMakeCmd_DistClean", wxTextCtrl)->SetValue(m_pProject->GetMakeCommandFor(mcDistClean));
871 XRCCTRL(*this, "txtMakeCmd_AskRebuildNeeded", wxTextCtrl)->SetValue(m_pProject->GetMakeCommandFor(mcAskRebuildNeeded));
872 XRCCTRL(*this, "txtMakeCmd_SilentBuild", wxTextCtrl)->SetValue(m_pProject->GetMakeCommandFor(mcSilentBuild));
873 }
874 else
875 {
876 // target options
877 SetLabel(_("Target build options: ") + m_pTarget->GetTitle());
878 IncludeDirs = m_pTarget->GetIncludeDirs();
879 ResDirs = m_pTarget->GetResourceIncludeDirs();
880 LibDirs = m_pTarget->GetLibDirs();
881 m_CompilerOptions = m_pTarget->GetCompilerOptions();
882 m_ResourceCompilerOptions = m_pTarget->GetResourceCompilerOptions();
883 m_LinkerOptions = m_pTarget->GetLinkerOptions();
884 m_LinkLibs = m_pTarget->GetLinkLibs();
885 CommandsAfterBuild = m_pTarget->GetCommandsAfterBuild();
886 CommandsBeforeBuild = m_pTarget->GetCommandsBeforeBuild();
887 AlwaysUsePost = m_pTarget->GetAlwaysRunPostBuildSteps();
888 XRCCTRL(*this, "cmbCompilerPolicy", wxChoice)->SetSelection(m_pTarget->GetOptionRelation(ortCompilerOptions));
889 XRCCTRL(*this, "cmbLinkerPolicy", wxChoice)->SetSelection(m_pTarget->GetOptionRelation(ortLinkerOptions));
890 XRCCTRL(*this, "cmbIncludesPolicy", wxChoice)->SetSelection(m_pTarget->GetOptionRelation(ortIncludeDirs));
891 XRCCTRL(*this, "cmbLibDirsPolicy", wxChoice)->SetSelection(m_pTarget->GetOptionRelation(ortLibDirs));
892 XRCCTRL(*this, "cmbResDirsPolicy", wxChoice)->SetSelection(m_pTarget->GetOptionRelation(ortResDirs));
893
894 XRCCTRL(*this, "txtMakeCmd_Build", wxTextCtrl)->SetValue(m_pTarget->GetMakeCommandFor(mcBuild));
895 XRCCTRL(*this, "txtMakeCmd_Compile", wxTextCtrl)->SetValue(m_pTarget->GetMakeCommandFor(mcCompileFile));
896 XRCCTRL(*this, "txtMakeCmd_Clean", wxTextCtrl)->SetValue(m_pTarget->GetMakeCommandFor(mcClean));
897 XRCCTRL(*this, "txtMakeCmd_DistClean", wxTextCtrl)->SetValue(m_pTarget->GetMakeCommandFor(mcDistClean));
898 XRCCTRL(*this, "txtMakeCmd_AskRebuildNeeded", wxTextCtrl)->SetValue(m_pTarget->GetMakeCommandFor(mcAskRebuildNeeded));
899 XRCCTRL(*this, "txtMakeCmd_SilentBuild", wxTextCtrl)->SetValue(m_pTarget->GetMakeCommandFor(mcSilentBuild));
900
901 const LinkerExecutableOption linkerExecutable = m_pTarget->GetLinkerExecutable();
902 XRCCTRL(*this, "chLinkerExe", wxChoice)->SetSelection(int(linkerExecutable));
903 }
904 }
905 TextToOptions();
906
907 DoFillOptions();
908 ArrayString2ListBox(IncludeDirs, XRCCTRL(*this, "lstIncludeDirs", wxListBox));
909 ArrayString2ListBox(LibDirs, XRCCTRL(*this, "lstLibDirs", wxListBox));
910 ArrayString2ListBox(ResDirs, XRCCTRL(*this, "lstResDirs", wxListBox));
911 ArrayString2TextCtrl(m_CompilerOptions, XRCCTRL(*this, "txtCompilerOptions", wxTextCtrl));
912 ArrayString2TextCtrl(m_ResourceCompilerOptions, XRCCTRL(*this, "txtResourceCompilerOptions", wxTextCtrl));
913 ArrayString2TextCtrl(m_LinkerOptions, XRCCTRL(*this, "txtLinkerOptions", wxTextCtrl));
914
915 // only if "Commands" page exists
916 if (m_pProject)
917 {
918 ArrayString2TextCtrl(CommandsBeforeBuild, XRCCTRL(*this, "txtCmdBefore", wxTextCtrl));
919 ArrayString2TextCtrl(CommandsAfterBuild, XRCCTRL(*this, "txtCmdAfter", wxTextCtrl));
920 XRCCTRL(*this, "chkAlwaysRunPost", wxCheckBox)->SetValue(AlwaysUsePost);
921 }
922 } // DoLoadOptions
923
OptionsToText()924 void CompilerOptionsDlg::OptionsToText()
925 {
926 wxArrayString array;
927 DoGetCompileOptions(array, XRCCTRL(*this, "txtCompilerDefines", wxTextCtrl));
928
929 int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxChoice)->GetSelection();
930 const Compiler* compiler = CompilerFactory::GetCompiler(compilerIdx);
931
932 for (unsigned int i = 0; i < array.GetCount(); ++i)
933 {
934 if (!array[i].IsEmpty())
935 {
936 if (array[i].StartsWith(compiler ? compiler->GetSwitches().genericSwitch : _T("-")))
937 {
938 if (m_CompilerOptions.Index(array[i]) == wxNOT_FOUND)
939 m_CompilerOptions.Add(array[i]);
940 }
941 else
942 {
943 if (compiler && m_CompilerOptions.Index(compiler->GetSwitches().defines + array[i]) == wxNOT_FOUND)
944 m_CompilerOptions.Add(compiler->GetSwitches().defines + array[i]);
945 }
946 }
947 }
948
949 wxArrayString compilerOpConflicts;
950 wxArrayString linkerOpConflicts;
951 for (size_t i = 0; i < m_Options.GetCount(); ++i)
952 {
953 CompOption* copt = m_Options.GetOption(i);
954 if (copt->enabled)
955 {
956 if (!copt->option.Trim().IsEmpty()) // don't add empty options
957 m_CompilerOptions.Insert(copt->option, 0);
958
959 if (!copt->additionalLibs.Trim().IsEmpty())
960 {
961 if (m_LinkerOptions.Index(copt->additionalLibs) == wxNOT_FOUND)
962 m_LinkerOptions.Insert(copt->additionalLibs, 0);
963 }
964 }
965 else
966 {
967 // mark items for removal
968 if (m_CompilerOptions.Index(copt->option) != wxNOT_FOUND)
969 compilerOpConflicts.Add(copt->option);
970 if (m_LinkerOptions.Index(copt->additionalLibs) != wxNOT_FOUND)
971 linkerOpConflicts.Add(copt->additionalLibs);
972 }
973 }
974
975 if (!compilerOpConflicts.IsEmpty() || !linkerOpConflicts.IsEmpty())
976 {
977 wxString msg = _("The compiler flags\n ")
978 + GetStringFromArray(compilerOpConflicts, wxT("\n "))
979 + GetStringFromArray(linkerOpConflicts, wxT("\n "));
980 msg.RemoveLast(2); // remove two trailing spaces
981 msg += _("were stated in 'Other Options' but unchecked in 'Compiler Flags'.\n"
982 "Do you want to enable these flags?");
983 AnnoyingDialog dlg(_("Enable compiler flags?"), msg, wxART_QUESTION,
984 AnnoyingDialog::YES_NO, AnnoyingDialog::rtNO);
985 if (dlg.ShowModal() == AnnoyingDialog::rtNO)
986 {
987 // for disabled options, remove relative text option *and*
988 // relative linker option
989 for (size_t i = 0; i < compilerOpConflicts.GetCount(); ++i)
990 m_CompilerOptions.Remove(compilerOpConflicts[i]);
991 for (size_t i = 0; i < linkerOpConflicts.GetCount(); ++i)
992 m_LinkerOptions.Remove(linkerOpConflicts[i]);
993 }
994 }
995
996 // linker options and libs
997 wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
998 for (size_t i = 0; i < lstLibs->GetCount(); ++i)
999 m_LinkLibs.Add(lstLibs->GetString(i));
1000 } // OptionsToText
1001
DoSaveOptions()1002 void CompilerOptionsDlg::DoSaveOptions()
1003 {
1004 wxArrayString IncludeDirs;
1005 wxArrayString LibDirs;
1006 wxArrayString ResDirs;
1007 ListBox2ArrayString(IncludeDirs, XRCCTRL(*this, "lstIncludeDirs", wxListBox));
1008 ListBox2ArrayString(LibDirs, XRCCTRL(*this, "lstLibDirs", wxListBox));
1009 ListBox2ArrayString(ResDirs, XRCCTRL(*this, "lstResDirs", wxListBox));
1010 DoGetCompileOptions(m_CompilerOptions, XRCCTRL(*this, "txtCompilerOptions", wxTextCtrl));
1011 DoGetCompileOptions(m_ResourceCompilerOptions, XRCCTRL(*this, "txtResourceCompilerOptions", wxTextCtrl));
1012 DoGetCompileOptions(m_LinkerOptions, XRCCTRL(*this, "txtLinkerOptions", wxTextCtrl));
1013 OptionsToText();
1014
1015 if (!m_pProject && !m_pTarget)
1016 {
1017 // global options
1018 Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
1019 if (compiler)
1020 {
1021 compiler->SetIncludeDirs(IncludeDirs);
1022 compiler->SetLibDirs(LibDirs);
1023 compiler->SetResourceIncludeDirs(ResDirs);
1024 compiler->SetCompilerOptions(m_CompilerOptions);
1025 compiler->SetResourceCompilerOptions(m_ResourceCompilerOptions);
1026 compiler->SetLinkerOptions(m_LinkerOptions);
1027 compiler->SetLinkLibs(m_LinkLibs);
1028
1029 wxChoice* cmb = XRCCTRL(*this, "cmbLogging", wxChoice);
1030 if (cmb)
1031 {
1032 CompilerSwitches switches = compiler->GetSwitches();
1033 switches.logging = (CompilerLoggingType)cmb->GetSelection();
1034 compiler->SetSwitches(switches);
1035 }
1036 }
1037 }
1038 else
1039 {
1040 // only if "Commands" page exists
1041 wxArrayString CommandsBeforeBuild;
1042 wxArrayString CommandsAfterBuild;
1043 bool AlwaysUsePost = false;
1044 if (m_pProject)
1045 {
1046 AlwaysUsePost = XRCCTRL(*this, "chkAlwaysRunPost", wxCheckBox)->GetValue();
1047 DoGetCompileOptions(CommandsBeforeBuild, XRCCTRL(*this, "txtCmdBefore", wxTextCtrl));
1048 DoGetCompileOptions(CommandsAfterBuild, XRCCTRL(*this, "txtCmdAfter", wxTextCtrl));
1049 }
1050 if (!m_pTarget)
1051 {
1052 // project options
1053 m_pProject->SetIncludeDirs(IncludeDirs);
1054 m_pProject->SetResourceIncludeDirs(ResDirs);
1055 m_pProject->SetLibDirs(LibDirs);
1056 m_pProject->SetCompilerOptions(m_CompilerOptions);
1057 m_pProject->SetResourceCompilerOptions(m_ResourceCompilerOptions);
1058 m_pProject->SetLinkerOptions(m_LinkerOptions);
1059 m_pProject->SetLinkLibs(m_LinkLibs);
1060 m_pProject->SetCommandsBeforeBuild(CommandsBeforeBuild);
1061 m_pProject->SetCommandsAfterBuild(CommandsAfterBuild);
1062 m_pProject->SetAlwaysRunPostBuildSteps(AlwaysUsePost);
1063
1064 m_pProject->SetMakeCommandFor(mcBuild, XRCCTRL(*this, "txtMakeCmd_Build", wxTextCtrl)->GetValue());
1065 m_pProject->SetMakeCommandFor(mcCompileFile, XRCCTRL(*this, "txtMakeCmd_Compile", wxTextCtrl)->GetValue());
1066 m_pProject->SetMakeCommandFor(mcClean, XRCCTRL(*this, "txtMakeCmd_Clean", wxTextCtrl)->GetValue());
1067 m_pProject->SetMakeCommandFor(mcDistClean, XRCCTRL(*this, "txtMakeCmd_DistClean", wxTextCtrl)->GetValue());
1068 m_pProject->SetMakeCommandFor(mcAskRebuildNeeded, XRCCTRL(*this, "txtMakeCmd_AskRebuildNeeded", wxTextCtrl)->GetValue());
1069 // m_pProject->SetMakeCommandFor(mcSilentBuild, XRCCTRL(*this, "txtMakeCmd_SilentBuild", wxTextCtrl)->GetValue());
1070 m_pProject->SetMakeCommandFor(mcSilentBuild, XRCCTRL(*this, "txtMakeCmd_Build", wxTextCtrl)->GetValue() + _T(" > $(CMD_NULL)"));
1071 }
1072 else
1073 {
1074 // target options
1075 m_pTarget->SetIncludeDirs(IncludeDirs);
1076 m_pTarget->SetResourceIncludeDirs(ResDirs);
1077 m_pTarget->SetLibDirs(LibDirs);
1078 m_pTarget->SetCompilerOptions(m_CompilerOptions);
1079 m_pTarget->SetResourceCompilerOptions(m_ResourceCompilerOptions);
1080 m_pTarget->SetLinkerOptions(m_LinkerOptions);
1081 m_pTarget->SetLinkLibs(m_LinkLibs);
1082
1083 {
1084 int value = XRCCTRL(*this, "chLinkerExe", wxChoice)->GetSelection();
1085 LinkerExecutableOption linkerExe;
1086 if (value >= 0 && value < int(LinkerExecutableOption::Last))
1087 linkerExe = LinkerExecutableOption(value);
1088 else
1089 linkerExe = LinkerExecutableOption::AutoDetect;
1090 m_pTarget->SetLinkerExecutable(linkerExe);
1091 }
1092
1093 m_pTarget->SetOptionRelation(ortCompilerOptions, OptionsRelation(XRCCTRL(*this, "cmbCompilerPolicy", wxChoice)->GetSelection()));
1094 m_pTarget->SetOptionRelation(ortLinkerOptions, OptionsRelation(XRCCTRL(*this, "cmbLinkerPolicy", wxChoice)->GetSelection()));
1095 m_pTarget->SetOptionRelation(ortIncludeDirs, OptionsRelation(XRCCTRL(*this, "cmbIncludesPolicy", wxChoice)->GetSelection()));
1096 m_pTarget->SetOptionRelation(ortLibDirs, OptionsRelation(XRCCTRL(*this, "cmbLibDirsPolicy", wxChoice)->GetSelection()));
1097 m_pTarget->SetOptionRelation(ortResDirs, OptionsRelation(XRCCTRL(*this, "cmbResDirsPolicy", wxChoice)->GetSelection()));
1098 m_pTarget->SetCommandsBeforeBuild(CommandsBeforeBuild);
1099 m_pTarget->SetCommandsAfterBuild(CommandsAfterBuild);
1100 m_pTarget->SetAlwaysRunPostBuildSteps(AlwaysUsePost);
1101
1102 m_pTarget->SetMakeCommandFor(mcBuild, XRCCTRL(*this, "txtMakeCmd_Build", wxTextCtrl)->GetValue());
1103 m_pTarget->SetMakeCommandFor(mcCompileFile, XRCCTRL(*this, "txtMakeCmd_Compile", wxTextCtrl)->GetValue());
1104 m_pTarget->SetMakeCommandFor(mcClean, XRCCTRL(*this, "txtMakeCmd_Clean", wxTextCtrl)->GetValue());
1105 m_pTarget->SetMakeCommandFor(mcDistClean, XRCCTRL(*this, "txtMakeCmd_DistClean", wxTextCtrl)->GetValue());
1106 m_pTarget->SetMakeCommandFor(mcAskRebuildNeeded, XRCCTRL(*this, "txtMakeCmd_AskRebuildNeeded", wxTextCtrl)->GetValue());
1107 // m_pTarget->SetMakeCommandFor(mcSilentBuild, XRCCTRL(*this, "txtMakeCmd_SilentBuild", wxTextCtrl)->GetValue());
1108 m_pTarget->SetMakeCommandFor(mcSilentBuild, XRCCTRL(*this, "txtMakeCmd_Build", wxTextCtrl)->GetValue() + _T(" > $(CMD_NULL)"));
1109 }
1110 }
1111 } // DoSaveOptions
1112
DoSaveCompilerPrograms()1113 void CompilerOptionsDlg::DoSaveCompilerPrograms()
1114 {
1115 Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
1116 if (m_pProject || !compiler) // no "Programs" page or no compiler
1117 return;
1118
1119 CompilerPrograms progs;
1120 wxString masterPath = XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->GetValue();
1121 progs.C = (XRCCTRL(*this, "txtCcompiler", wxTextCtrl)->GetValue()).Trim();
1122 progs.CPP = (XRCCTRL(*this, "txtCPPcompiler", wxTextCtrl)->GetValue()).Trim();
1123 progs.LD = (XRCCTRL(*this, "txtLinker", wxTextCtrl)->GetValue()).Trim();
1124 progs.LIB = (XRCCTRL(*this, "txtLibLinker", wxTextCtrl)->GetValue()).Trim();
1125 progs.WINDRES = (XRCCTRL(*this, "txtResComp", wxTextCtrl)->GetValue()).Trim();
1126 progs.MAKE = (XRCCTRL(*this, "txtMake", wxTextCtrl)->GetValue()).Trim();
1127 wxChoice *cmbDebugger = XRCCTRL(*this, "cmbDebugger", wxChoice);
1128 if (cmbDebugger)
1129 {
1130 int index = cmbDebugger->GetSelection();
1131 const DebuggerClientData* data = static_cast<const DebuggerClientData*>(cmbDebugger->GetClientObject(index));
1132 progs.DBGconfig = data->string;
1133 }
1134 compiler->SetPrograms(progs);
1135 compiler->SetMasterPath(masterPath);
1136 // and the extra paths
1137 wxListBox* control = XRCCTRL(*this, "lstExtraPaths", wxListBox);
1138 if (control)
1139 {
1140 // get all listBox entries in array String
1141 wxArrayString extraPaths;
1142 ListBox2ArrayString(extraPaths, control);
1143 compiler->SetExtraPaths(extraPaths);
1144 }
1145 } // DoSaveCompilerPrograms
1146
DoSaveVars()1147 void CompilerOptionsDlg::DoSaveVars()
1148 {
1149 CompileOptionsBase* pBase = GetVarsOwner();
1150 if (pBase)
1151 {
1152 // let's process all the stored CustomVarActions
1153 for (unsigned int idxAction = 0; idxAction < m_CustomVarActions.size(); ++idxAction)
1154 {
1155 CustomVarAction Action = m_CustomVarActions[idxAction];
1156 switch(Action.m_Action)
1157 {
1158 case CVA_Add:
1159 pBase->SetVar(Action.m_Key, Action.m_KeyValue);
1160 break;
1161 case CVA_Edit:
1162 {
1163 // first split up the KeyValue
1164 wxString NewKey = Action.m_KeyValue.BeforeFirst(_T('=')).Trim(true).Trim(false);
1165 wxString NewValue = Action.m_KeyValue.AfterFirst(_T('=')).Trim(true).Trim(false);
1166 if (Action.m_Key != NewKey)
1167 { // the key name changed
1168 pBase->UnsetVar(Action.m_Key);
1169 }
1170 pBase->SetVar(NewKey, NewValue);
1171 break;
1172 }
1173 case CVA_Remove:
1174 pBase->UnsetVar(Action.m_Key);
1175 break;
1176 default:
1177 break;
1178 } // end switch
1179 } // end for : idx : idxAction
1180 m_CustomVarActions.clear();
1181 }
1182 } // DoSaveVars
1183
DoSaveCompilerDefinition()1184 void CompilerOptionsDlg::DoSaveCompilerDefinition()
1185 {
1186 wxXmlNode* root = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("CodeBlocks_compiler_options"));
1187 Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
1188 const wxString name = wxT("name");
1189 const wxString value = wxT("value");
1190 wxXmlNode* node = new wxXmlNode(root, wxXML_ELEMENT_NODE, wxT("Program"));
1191 node->AddAttribute(name, wxT("C"));
1192 node->AddAttribute(value, compiler->GetPrograms().C);
1193 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Program")));
1194 node = node->GetNext();
1195 node->AddAttribute(name, wxT("CPP"));
1196 node->AddAttribute(value, compiler->GetPrograms().CPP);
1197 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Program")));
1198 node = node->GetNext();
1199 node->AddAttribute(name, wxT("LD"));
1200 node->AddAttribute(value, compiler->GetPrograms().LD);
1201 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Program")));
1202 node = node->GetNext();
1203 node->AddAttribute(name, wxT("DBGconfig"));
1204 node->AddAttribute(value, compiler->GetPrograms().DBGconfig);
1205 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Program")));
1206 node = node->GetNext();
1207 node->AddAttribute(name, wxT("LIB"));
1208 node->AddAttribute(value, compiler->GetPrograms().LIB);
1209 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Program")));
1210 node = node->GetNext();
1211 node->AddAttribute(name, wxT("WINDRES"));
1212 node->AddAttribute(value, compiler->GetPrograms().WINDRES);
1213 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Program")));
1214 node = node->GetNext();
1215 node->AddAttribute(name, wxT("MAKE"));
1216 node->AddAttribute(value, compiler->GetPrograms().MAKE);
1217
1218
1219 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1220 node = node->GetNext();
1221 node->AddAttribute(name, wxT("includeDirs"));
1222 node->AddAttribute(value, compiler->GetSwitches().includeDirs);
1223 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1224 node = node->GetNext();
1225 node->AddAttribute(name, wxT("libDirs"));
1226 node->AddAttribute(value, compiler->GetSwitches().libDirs);
1227 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1228 node = node->GetNext();
1229 node->AddAttribute(name, wxT("linkLibs"));
1230 node->AddAttribute(value, compiler->GetSwitches().linkLibs);
1231 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1232 node = node->GetNext();
1233 node->AddAttribute(name, wxT("defines"));
1234 node->AddAttribute(value, compiler->GetSwitches().defines);
1235 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1236 node = node->GetNext();
1237 node->AddAttribute(name, wxT("genericSwitch"));
1238 node->AddAttribute(value, compiler->GetSwitches().genericSwitch);
1239 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1240 node = node->GetNext();
1241 node->AddAttribute(name, wxT("objectExtension"));
1242 node->AddAttribute(value, compiler->GetSwitches().objectExtension);
1243 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1244 node = node->GetNext();
1245 node->AddAttribute(name, wxT("forceFwdSlashes"));
1246 node->AddAttribute(value, (compiler->GetSwitches().forceFwdSlashes ? wxT("true") : wxT("false")));
1247 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1248 node = node->GetNext();
1249 node->AddAttribute(name, wxT("forceLinkerUseQuotes"));
1250 node->AddAttribute(value, (compiler->GetSwitches().forceLinkerUseQuotes ? wxT("true") : wxT("false")));
1251 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1252 node = node->GetNext();
1253 node->AddAttribute(name, wxT("forceCompilerUseQuotes"));
1254 node->AddAttribute(value, (compiler->GetSwitches().forceCompilerUseQuotes ? wxT("true") : wxT("false")));
1255 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1256 node = node->GetNext();
1257 node->AddAttribute(name, wxT("needDependencies"));
1258 node->AddAttribute(value, (compiler->GetSwitches().needDependencies ? wxT("true") : wxT("false")));
1259 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1260 node = node->GetNext();
1261 node->AddAttribute(name, wxT("logging"));
1262 if (compiler->GetSwitches().logging == CompilerSwitches::defaultLogging)
1263 node->AddAttribute(value, wxT("default"));
1264 else if (compiler->GetSwitches().logging == clogFull)
1265 node->AddAttribute(value, wxT("full"));
1266 else if (compiler->GetSwitches().logging == clogSimple)
1267 node->AddAttribute(value, wxT("simple"));
1268 else if (compiler->GetSwitches().logging == clogNone)
1269 node->AddAttribute(value, wxT("none"));
1270 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1271 node = node->GetNext();
1272 node->AddAttribute(name, wxT("libPrefix"));
1273 node->AddAttribute(value, compiler->GetSwitches().libPrefix);
1274 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1275 node = node->GetNext();
1276 node->AddAttribute(name, wxT("libExtension"));
1277 node->AddAttribute(value, compiler->GetSwitches().libExtension);
1278 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1279 node = node->GetNext();
1280 node->AddAttribute(name, wxT("linkerNeedsLibPrefix"));
1281 node->AddAttribute(value, (compiler->GetSwitches().linkerNeedsLibPrefix ? wxT("true") : wxT("false")));
1282 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1283 node = node->GetNext();
1284 node->AddAttribute(name, wxT("linkerNeedsLibExtension"));
1285 node->AddAttribute(value, (compiler->GetSwitches().linkerNeedsLibExtension ? wxT("true") : wxT("false")));
1286 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1287 node = node->GetNext();
1288 node->AddAttribute(name, wxT("linkerNeedsPathResolved"));
1289 node->AddAttribute(value, (compiler->GetSwitches().linkerNeedsPathResolved ? wxT("true") : wxT("false")));
1290 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1291 node = node->GetNext();
1292 node->AddAttribute(name, wxT("supportsPCH"));
1293 node->AddAttribute(value, (compiler->GetSwitches().supportsPCH ? wxT("true") : wxT("false")));
1294 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1295 node = node->GetNext();
1296 node->AddAttribute(name, wxT("PCHExtension"));
1297 node->AddAttribute(value, compiler->GetSwitches().PCHExtension);
1298 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1299 node = node->GetNext();
1300 node->AddAttribute(name, wxT("UseFlatObjects"));
1301 node->AddAttribute(value, (compiler->GetSwitches().UseFlatObjects ? wxT("true") : wxT("false")));
1302 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1303 node = node->GetNext();
1304 node->AddAttribute(name, wxT("UseFullSourcePaths"));
1305 node->AddAttribute(value, (compiler->GetSwitches().UseFullSourcePaths ? wxT("true") : wxT("false")));
1306 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1307 node = node->GetNext();
1308 node->AddAttribute(name, wxT("includeDirSeparator"));
1309 node->AddAttribute(value, compiler->GetSwitches().includeDirSeparator);
1310 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1311 node = node->GetNext();
1312 node->AddAttribute(name, wxT("libDirSeparator"));
1313 node->AddAttribute(value, compiler->GetSwitches().libDirSeparator);
1314 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1315 node = node->GetNext();
1316 node->AddAttribute(name, wxT("objectSeparator"));
1317 node->AddAttribute(value, compiler->GetSwitches().objectSeparator);
1318 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1319 node = node->GetNext();
1320 node->AddAttribute(name, wxT("statusSuccess"));
1321 node->AddAttribute(value, wxString::Format(wxT("%d"), compiler->GetSwitches().statusSuccess));
1322 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Switch")));
1323 node = node->GetNext();
1324 node->AddAttribute(name, wxT("Use83Paths"));
1325 node->AddAttribute(value, (compiler->GetSwitches().Use83Paths ? wxT("true") : wxT("false")));
1326
1327 for (size_t i = 0; i < m_Options.GetCount(); ++i)
1328 {
1329 CompOption* opt = m_Options.GetOption(i);
1330 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Option")));
1331 node = node->GetNext();
1332 wxString oName;
1333 opt->name.EndsWith(wxT("[") + opt->option + wxT("]"), &oName);
1334 if (oName == wxEmptyString)
1335 opt->name.EndsWith(wxT("[") + opt->additionalLibs + wxT("]"), &oName);
1336 if (oName == wxEmptyString)
1337 oName = opt->name;
1338 node->AddAttribute(name, oName.Trim());
1339 if (opt->option != wxEmptyString)
1340 node->AddAttribute(wxT("option"), opt->option);
1341 if (opt->category != wxT("General"))
1342 node->AddAttribute(wxT("category"), opt->category);
1343 if (opt->additionalLibs != wxEmptyString)
1344 node->AddAttribute(wxT("additionalLibs"), opt->additionalLibs);
1345 if (opt->checkAgainst != wxEmptyString)
1346 {
1347 node->AddAttribute(wxT("checkAgainst"), opt->checkAgainst);
1348 node->AddAttribute(wxT("checkMessage"), opt->checkMessage);
1349 }
1350 if (opt->supersedes != wxEmptyString)
1351 node->AddAttribute(wxT("supersedes"), opt->supersedes);
1352 if (opt->exclusive)
1353 node->AddAttribute(wxT("exclusive"), wxT("true"));
1354 }
1355
1356 for (int i = 0; i < ctCount; ++i)
1357 {
1358 const CompilerToolsVector& vec = compiler->GetCommandToolsVector((CommandType)i);
1359 wxString op;
1360 if (i == ctCompileObjectCmd)
1361 op = wxT("CompileObject");
1362 else if (i == ctGenDependenciesCmd)
1363 op = wxT("GenDependencies");
1364 else if (i == ctCompileResourceCmd)
1365 op = wxT("CompileResource");
1366 else if (i == ctLinkExeCmd)
1367 op = wxT("LinkExe");
1368 else if (i == ctLinkConsoleExeCmd)
1369 op = wxT("LinkConsoleExe");
1370 else if (i == ctLinkDynamicCmd)
1371 op = wxT("LinkDynamic");
1372 else if (i == ctLinkStaticCmd)
1373 op = wxT("LinkStatic");
1374 else if (i == ctLinkNativeCmd)
1375 op = wxT("LinkNative");
1376 for (size_t j = 0; j < vec.size(); ++j)
1377 {
1378 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Command")));
1379 node = node->GetNext();
1380 node->AddAttribute(name, op);
1381 node->AddAttribute(value, vec[j].command);
1382 if (!vec[j].extensions.IsEmpty())
1383 node->AddAttribute(wxT("ext"), GetStringFromArray(vec[j].extensions, DEFAULT_ARRAY_SEP, false));
1384 if (!vec[j].generatedFiles.IsEmpty())
1385 node->AddAttribute(wxT("gen"), GetStringFromArray(vec[j].generatedFiles, DEFAULT_ARRAY_SEP, false));
1386 }
1387 }
1388
1389 const RegExArray& regexes = compiler->GetRegExArray();
1390 for (size_t i = 0; i < regexes.size(); ++i)
1391 {
1392 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("RegEx")));
1393 node = node->GetNext();
1394 node->AddAttribute(name, regexes[i].desc);
1395 wxString tp;
1396 if (regexes[i].lt == cltNormal)
1397 tp = wxT("normal");
1398 else if (regexes[i].lt == cltWarning)
1399 tp = wxT("warning");
1400 else if (regexes[i].lt == cltError)
1401 tp = wxT("error");
1402 else if (regexes[i].lt == cltInfo)
1403 tp = wxT("info");
1404 node->AddAttribute(wxT("type"), tp);
1405 tp = wxString::Format(wxT("%d;%d;%d"), regexes[i].msg[0], regexes[i].msg[1], regexes[i].msg[2]);
1406 tp.Replace(wxT(";0"), wxEmptyString);
1407 node->AddAttribute(wxT("msg"), tp);
1408 if (regexes[i].filename != 0)
1409 node->AddAttribute(wxT("file"), wxString::Format(wxT("%d"), regexes[i].filename));
1410 if (regexes[i].line != 0)
1411 node->AddAttribute(wxT("line"), wxString::Format(wxT("%d"), regexes[i].line));
1412 tp = regexes[i].GetRegExString();
1413 tp.Replace(wxT("\t"), wxT("\\t"));
1414 node->AddChild(new wxXmlNode(wxXML_CDATA_SECTION_NODE, wxEmptyString, tp));
1415 }
1416
1417 if (!compiler->GetCOnlyFlags().IsEmpty())
1418 {
1419 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Sort")));
1420 node = node->GetNext();
1421 node->AddAttribute(wxT("CFlags"), compiler->GetCOnlyFlags());
1422 }
1423 if (!compiler->GetCPPOnlyFlags().IsEmpty())
1424 {
1425 node->SetNext(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Sort")));
1426 node = node->GetNext();
1427 node->AddAttribute(wxT("CPPFlags"), compiler->GetCPPOnlyFlags());
1428 }
1429
1430 wxXmlDocument doc;
1431 doc.SetVersion(wxT("1.0"));
1432 doc.SetRoot(root);
1433 if (!wxDirExists(ConfigManager::GetFolder(sdDataUser) + wxT("/compilers")))
1434 wxMkdir(ConfigManager::GetFolder(sdDataUser) + wxT("/compilers"));
1435 doc.Save(ConfigManager::GetFolder(sdDataUser) + wxT("/compilers/options_") + compiler->GetID() + wxT(".xml"));
1436
1437 // update the in-memory cache
1438 compiler->SetOptions(m_Options);
1439 } // DoSaveCompilerDefinition
1440
1441 // events
1442
OnDirty(cb_unused wxCommandEvent & event)1443 void CompilerOptionsDlg::OnDirty(cb_unused wxCommandEvent& event)
1444 {
1445 m_bDirty = true;
1446 } // OnDirty
1447
ProjectTargetCompilerAdjust()1448 void CompilerOptionsDlg::ProjectTargetCompilerAdjust()
1449 { // note this can also be called when on global compiler level, won't do anything (well reset a member which has
1450 // no use in this case)
1451 // check if the compilerID needs to be updated
1452 if (m_pTarget)
1453 { // target was the (tree) selection
1454 if (!m_NewProjectOrTargetCompilerId.IsEmpty() && m_pTarget->GetCompilerID() != m_NewProjectOrTargetCompilerId)
1455 {
1456 m_pTarget->SetCompilerID(m_NewProjectOrTargetCompilerId);
1457 cbMessageBox(_("You changed the compiler used for this target.\n"
1458 "It is recommended that you fully rebuild this target, "
1459 "otherwise linking errors might occur..."),
1460 _("Notice"),
1461 wxICON_EXCLAMATION);
1462 }
1463 }
1464 else if (m_pProject)
1465 { // the project was the (tree) selection
1466 if (!m_NewProjectOrTargetCompilerId.IsEmpty() && m_pProject->GetCompilerID() != m_NewProjectOrTargetCompilerId)
1467 { // should be project then
1468 m_pProject->SetCompilerID(m_NewProjectOrTargetCompilerId);
1469 UpdateCompilerForTargets(m_CurrentCompilerIdx);
1470 cbMessageBox(_("You changed the compiler used for this project.\n"
1471 "It is recommended that you fully rebuild this project, "
1472 "otherwise linking errors might occur..."),
1473 _("Notice"),
1474 wxICON_EXCLAMATION);
1475 }
1476 }
1477 m_NewProjectOrTargetCompilerId = wxEmptyString;
1478 } // ProjectTargetCompilerAdjust
1479
OnTreeSelectionChange(wxTreeEvent & event)1480 void CompilerOptionsDlg::OnTreeSelectionChange(wxTreeEvent& event)
1481 {
1482 if (m_BuildingTree)
1483 return;
1484 wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
1485 ScopeTreeData* data = (ScopeTreeData*)tc->GetItemData(event.GetItem());
1486 if (!data)
1487 return;
1488 int compilerIdx = data->GetTarget() ? CompilerFactory::GetCompilerIndex(data->GetTarget()->GetCompilerID()) :
1489 (data->GetProject() ? CompilerFactory::GetCompilerIndex(data->GetProject()->GetCompilerID()) :
1490 XRCCTRL(*this, "cmbCompiler", wxChoice)->GetSelection());
1491 // in order to support projects/targets which have an unknown "user compiler", that is on the current
1492 // system that compiler is not (or no longer) installed, we should check the compilerIdx, in such a case it will
1493 // be '-1' [NOTE : maybe to the check already on the Id ?]
1494 // we then allow the user to make a choice :
1495 // a) adjust to another compiler
1496 // b) leave that compiler --> no settings can be set then (done by disabling the notebook,
1497 // as a consequence might need to be re-enabled when another target/project is chosen in the tree)
1498 if (compilerIdx != -1)
1499 {
1500 wxNotebook* nb = XRCCTRL(*this, "nbMain", wxNotebook);
1501 XRCCTRL(*this, "cmbCompiler", wxChoice)->SetSelection(compilerIdx);
1502 // we don't update the compiler index yet, we leave that to CompilerChanged();
1503 m_pTarget = data->GetTarget();
1504 if (m_pTarget && !m_pTarget->SupportsCurrentPlatform())
1505 {
1506 if (nb)
1507 nb->Disable();
1508 }
1509 else
1510 {
1511 if (nb)
1512 {
1513 // enable/disable invalid pages for commands only target
1514 const bool cmd = (m_pTarget && m_pTarget->GetTargetType() == ttCommandsOnly);
1515 int pageOffset;
1516 if (!m_pProject->IsMakefileCustom())
1517 {
1518 nb->GetPage(0)->Enable(!cmd); // Compiler settings
1519 nb->GetPage(1)->Enable(!cmd); // Linker settings
1520 nb->GetPage(2)->Enable(!cmd); // Search directories
1521 pageOffset = 3;
1522 }
1523 else
1524 pageOffset = 0;
1525 nb->GetPage(pageOffset + 2)->Enable(!cmd); // "Make" commands
1526 if ( cmd
1527 && nb->GetSelection() != pageOffset // Pre/post build steps
1528 && nb->GetSelection() != pageOffset + 1 ) // Custom variables
1529 {
1530 nb->SetSelection(pageOffset);
1531 }
1532
1533 nb->Enable();
1534 }
1535 // the new selection might have a different compiler settings and/or even a different compiler
1536 // load all those new settings
1537 m_CurrentCompilerIdx = compilerIdx;
1538 Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
1539 if (compiler)
1540 m_Options = compiler->GetOptions();
1541 DoFillCompilerDependentSettings();
1542 }
1543 }
1544 else
1545 {
1546 m_pTarget = data->GetTarget();
1547 wxString CompilerId = m_pTarget?m_pTarget->GetCompilerID():data->GetProject()->GetCompilerID();
1548 wxString msg;
1549 msg.Printf(_("The defined compiler cannot be located (ID: %s).\n"
1550 "Please choose the compiler you want to use instead and click \"OK\".\n"
1551 "If you click \"Cancel\", the project/target will remain configured for that compiler and consequently can not be configured and will not be built."),
1552 CompilerId.wx_str());
1553 Compiler* compiler = 0;
1554 if (m_pTarget && m_pTarget->SupportsCurrentPlatform())
1555 compiler = CompilerFactory::SelectCompilerUI(msg);
1556
1557 if (compiler)
1558 { // a new compiler was chosen, proceed as if the user manually selected another compiler
1559 // that means set the compiler selection list accordingly
1560 // and go directly to (On)CompilerChanged
1561 int NewCompilerIdx = CompilerFactory::GetCompilerIndex(compiler);
1562 XRCCTRL(*this, "cmbCompiler", wxChoice)->SetSelection(NewCompilerIdx);
1563 wxCommandEvent Dummy;
1564 OnCompilerChanged(Dummy);
1565 }
1566 else
1567 { // the user cancelled and wants to keep the compiler
1568 if (wxNotebook* nb = XRCCTRL(*this, "nbMain", wxNotebook))
1569 nb->Disable();
1570 }
1571 }
1572
1573 {
1574 const bool show = (m_pTarget != nullptr);
1575
1576 // Hide linker executable because it doesn't make sense to change it in the project.
1577 wxChoice *cmbLinkerExe = XRCCTRL(*this, "chLinkerExe", wxChoice);
1578 cmbLinkerExe->Show(show);
1579 wxStaticText *txtLinkerExe = XRCCTRL(*this, "txtLinkerExe", wxStaticText);
1580 txtLinkerExe->Show(show);
1581 }
1582 } // OnTreeSelectionChange
1583
OnTreeSelectionChanging(wxTreeEvent & event)1584 void CompilerOptionsDlg::OnTreeSelectionChanging(wxTreeEvent& event)
1585 {
1586 if (m_BuildingTree)
1587 return;
1588 wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
1589 ScopeTreeData* data = (ScopeTreeData*)tc->GetItemData(event.GetOldItem());
1590 if (data && (m_bDirty || m_bFlagsDirty))
1591 { // data : should always be the case, since on global compiler level, there's no tree
1592 // when changes are made prompt the user if these changes should be applied
1593 // YES -> do the changes
1594 // NO -> no changes, just switch
1595 // CANCEL : don't switch
1596
1597 AnnoyingDialog dlg(_("Project/Target change with changed settings"),
1598 _("You have changed some settings. Do you want these settings saved ?\n\n"
1599 "Yes : will apply the changes\n"
1600 "No : will undo the changes\n"
1601 "Cancel : will revert your selection in the project/target tree"),
1602 wxART_QUESTION,
1603 AnnoyingDialog::YES_NO_CANCEL);
1604
1605 switch(dlg.ShowModal())
1606 {
1607 case AnnoyingDialog::rtYES :
1608 DoSaveCompilerDependentSettings();
1609 break;
1610 case AnnoyingDialog::rtCANCEL :
1611 event.Veto();
1612 break;
1613 case AnnoyingDialog::rtNO :
1614 default:
1615 {
1616 m_bDirty = false;
1617 m_bFlagsDirty = false;
1618 }
1619 break;
1620 } // end switch
1621 }
1622 } // OnTreeSelectionChanging
1623
OnCompilerChanged(cb_unused wxCommandEvent & event)1624 void CompilerOptionsDlg::OnCompilerChanged(cb_unused wxCommandEvent& event)
1625 {
1626 // when changes are made prompt the user if these changes should be applied
1627 // YES -> do the changes
1628 // NO -> no changes, just switch
1629 // CANCEL : don't switch
1630 bool bChanged = true;
1631 if (m_bDirty || m_bFlagsDirty)
1632 {
1633 switch(cbMessageBox(_("You have changed some settings. Do you want these settings saved ?\n\n"
1634 "Yes : will apply the changes\n"
1635 "No : will undo the changes\n"
1636 "Cancel : will revert your compiler change."),
1637 _("Compiler change with changed settings"),
1638 wxICON_EXCLAMATION|wxYES|wxNO|wxCANCEL))
1639 {
1640 case wxID_CANCEL :
1641 XRCCTRL(*this, "cmbCompiler", wxChoice)->SetSelection(m_CurrentCompilerIdx);
1642 bChanged = false;
1643 break;
1644 case wxID_YES :
1645 DoSaveCompilerDependentSettings();
1646 break;
1647 case wxID_NO :
1648 default:
1649 m_bDirty = false;
1650 m_bFlagsDirty = false;
1651 break;
1652 } // end switch
1653 }
1654 if (bChanged)
1655 {
1656 CompilerChanged();
1657 if (m_pProject)
1658 { // in case of project/target --> dirty
1659 m_bDirty = true;
1660 }
1661 }
1662 } // OnCompilerChanged
1663
CompilerChanged()1664 void CompilerOptionsDlg::CompilerChanged()
1665 {
1666 m_CurrentCompilerIdx = XRCCTRL(*this, "cmbCompiler", wxChoice)->GetSelection();
1667 // in case we are not on the global level (== project/target) we need to remember this switch
1668 // so that on "SAVE" time we can adjust the project/target with it's new compiler
1669 // SAVE time for this particular setting means (Apply or TreeSelection change
1670 // not compiler change since we could (re)change the compiler of that project/target
1671 if (m_pProject)
1672 {
1673 m_NewProjectOrTargetCompilerId = CompilerFactory::GetCompiler(m_CurrentCompilerIdx)->GetID();
1674 }
1675 //load the new options (== options of the new selected compiler)
1676 Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
1677 if (compiler)
1678 m_Options = compiler->GetOptions();
1679 DoFillCompilerDependentSettings();
1680 } // CompilerChanged
1681
UpdateCompilerForTargets(int compilerIdx)1682 void CompilerOptionsDlg::UpdateCompilerForTargets(int compilerIdx)
1683 {
1684 int ret = cbMessageBox(_("You have changed the compiler used for the project.\n"
1685 "Do you want to use the same compiler for all the project's build targets too?"),
1686 _("Question"),
1687 wxICON_QUESTION | wxYES_NO);
1688 if (ret == wxID_YES)
1689 {
1690 for (int i = 0; i < m_pProject->GetBuildTargetsCount(); ++i)
1691 {
1692 ProjectBuildTarget* target = m_pProject->GetBuildTarget(i);
1693 Compiler* compiler = CompilerFactory::GetCompiler(compilerIdx);
1694 if (compiler)
1695 target->SetCompilerID(compiler->GetID());
1696 }
1697 }
1698 } // UpdateCompilerForTargets
1699
AutoDetectCompiler()1700 void CompilerOptionsDlg::AutoDetectCompiler()
1701 {
1702 Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
1703 if (!compiler)
1704 return;
1705
1706 wxString backup = XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->GetValue();
1707 wxArrayString ExtraPathsBackup = compiler->GetExtraPaths();
1708
1709 wxArrayString empty;
1710 compiler->SetExtraPaths(empty);
1711
1712 switch (compiler->AutoDetectInstallationDir())
1713 {
1714 case adrDetected:
1715 {
1716 wxString msg;
1717 msg.Printf(_("Auto-detected installation path of \"%s\"\nin \"%s\""), compiler->GetName().wx_str(), compiler->GetMasterPath().wx_str());
1718 cbMessageBox(msg);
1719 }
1720 break;
1721
1722 case adrGuessed:
1723 {
1724 wxString msg;
1725 msg.Printf(_("Could not auto-detect installation path of \"%s\"...\n"
1726 "Do you want to use this compiler's default installation directory?"),
1727 compiler->GetName().wx_str());
1728 if (cbMessageBox(msg, _("Confirmation"), wxICON_QUESTION | wxYES_NO) == wxID_NO)
1729 {
1730 compiler->SetMasterPath(backup);
1731 compiler->SetExtraPaths(ExtraPathsBackup);
1732 }
1733 }
1734 break;
1735
1736 default:
1737 break;
1738 }
1739 XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->SetValue(compiler->GetMasterPath());
1740 XRCCTRL(*this, "lstExtraPaths", wxListBox)->Clear();
1741 const wxArrayString& extraPaths = CompilerFactory::GetCompiler(m_CurrentCompilerIdx)->GetExtraPaths();
1742 ArrayString2ListBox(extraPaths, XRCCTRL(*this, "lstExtraPaths", wxListBox));
1743 m_bDirty = true;
1744 } // AutoDetectCompiler
1745
GetDirsListBox()1746 wxListBox* CompilerOptionsDlg::GetDirsListBox()
1747 {
1748 wxNotebook* nb = XRCCTRL(*this, "nbDirs", wxNotebook);
1749 if (!nb)
1750 return 0;
1751 switch (nb->GetSelection())
1752 {
1753 case 0: // compiler dirs
1754 return XRCCTRL(*this, "lstIncludeDirs", wxListBox);
1755 case 1: // linker dirs
1756 return XRCCTRL(*this, "lstLibDirs", wxListBox);
1757 case 2: // resource compiler dirs
1758 return XRCCTRL(*this, "lstResDirs", wxListBox);
1759 default: break;
1760 }
1761 return 0;
1762 } // GetDirsListBox
1763
GetVarsOwner()1764 CompileOptionsBase* CompilerOptionsDlg::GetVarsOwner()
1765 {
1766 return m_pTarget ? m_pTarget
1767 : (m_pProject ? m_pProject
1768 : (CompileOptionsBase*)(CompilerFactory::GetCompiler(m_CurrentCompilerIdx)));
1769 } // GetVarsOwner
1770
OnCategoryChanged(cb_unused wxCommandEvent & event)1771 void CompilerOptionsDlg::OnCategoryChanged(cb_unused wxCommandEvent& event)
1772 { // reshow the compiler options, but with different filter (category) applied
1773 DoFillOptions();
1774 } // OnCategoryChanged
1775
OnOptionChanged(wxPropertyGridEvent & event)1776 void CompilerOptionsDlg::OnOptionChanged(wxPropertyGridEvent& event)
1777 {
1778 wxPGProperty* property = event.GetProperty();
1779 if (!property)
1780 return;
1781 // Make sure the property is bool. Other properties are ignored for now.
1782 if (!property->IsKindOf(CLASSINFO(wxBoolProperty)))
1783 return;
1784 CompOption* option = m_Options.GetOptionByName(property->GetLabel());
1785 wxVariant value = property->GetValue();
1786 if (value.IsNull() || !option)
1787 return;
1788 option->enabled = value.GetBool();
1789 if (option->enabled)
1790 {
1791 if (!option->checkAgainst.IsEmpty())
1792 {
1793 wxArrayString check = GetArrayFromString(option->checkAgainst, wxT(" "));
1794 for (size_t i = 0; i < check.Count(); ++i)
1795 {
1796 CompOption* against = m_Options.GetOptionByOption(check[i]);
1797 if (!against)
1798 against = m_Options.GetOptionByAdditionalLibs(check[i]);
1799 if (against && against->enabled)
1800 {
1801 wxString message = (option->checkMessage.IsEmpty() ?
1802 wxT("\"") + option->name + _("\" conflicts with \"") + against->name + wxT("\".") :
1803 option->checkMessage );
1804 AnnoyingDialog dlg(_("Compiler options conflict"),
1805 message,
1806 wxART_INFORMATION,
1807 AnnoyingDialog::OK);
1808 dlg.ShowModal();
1809 break;
1810 }
1811 }
1812 }
1813 if (option->supersedes != wxEmptyString)
1814 {
1815 wxArrayString supersede = GetArrayFromString(option->supersedes, wxT(" "));
1816 for (size_t i = 0; i < supersede.Count(); ++i)
1817 {
1818 for (size_t j = 0; j < m_Options.GetCount(); ++j)
1819 {
1820 if (option != m_Options.GetOption(j) &&
1821 (supersede[i] == m_Options.GetOption(j)->option ||
1822 supersede[i] == m_Options.GetOption(j)->additionalLibs))
1823 {
1824 m_Options.GetOption(j)->enabled = false;
1825 }
1826 }
1827
1828 for (wxPropertyGridIterator it = m_FlagsPG->GetIterator(); !it.AtEnd(); ++it)
1829 {
1830 wxPGProperty* p = *it;
1831 if (p->IsCategory() || p == property)
1832 continue;
1833 if (p->GetLabel().EndsWith(wxT("[") + supersede[i] + wxT("]")))
1834 m_FlagsPG->SetPropertyValue(p, false);
1835 }
1836 }
1837 }
1838 if (option->exclusive)
1839 {
1840 for (size_t i = 0; i < m_Options.GetCount(); ++i)
1841 {
1842 if (option != m_Options.GetOption(i) &&
1843 option->category == m_Options.GetOption(i)->category)
1844 {
1845 m_Options.GetOption(i)->enabled = false;
1846 }
1847 }
1848 for (wxPropertyGridIterator it = m_FlagsPG->GetIterator(); !it.AtEnd(); ++it)
1849 {
1850 wxPGProperty* p = *it;
1851 if (p->IsCategory() || p == property)
1852 continue;
1853 CompOption* opt = m_Options.GetOptionByName(p->GetLabel());
1854 if (option != opt && option->category == opt->category)
1855 m_FlagsPG->SetPropertyValue(p, false);
1856 }
1857 }
1858 }
1859 m_bDirty = true;
1860 }
1861
1862 // some handlers for adding/editing/removing/clearing of include/libraries/resources directories
OnAddDirClick(cb_unused wxCommandEvent & event)1863 void CompilerOptionsDlg::OnAddDirClick(cb_unused wxCommandEvent& event)
1864 {
1865 EditPathDlg dlg(this,
1866 m_pProject ? m_pProject->GetBasePath() : _T(""),
1867 m_pProject ? m_pProject->GetBasePath() : _T(""),
1868 _("Add directory"));
1869
1870 PlaceWindow(&dlg);
1871 if (dlg.ShowModal() == wxID_OK)
1872 {
1873 wxString path = dlg.GetPath();
1874
1875 wxListBox* control = GetDirsListBox();
1876 if (control)
1877 {
1878 control->Append(path);
1879 m_bDirty = true;
1880 }
1881 }
1882 } // OnAddDirClick
1883
OnEditDirClick(cb_unused wxCommandEvent & event)1884 void CompilerOptionsDlg::OnEditDirClick(cb_unused wxCommandEvent& event)
1885 {
1886 wxListBox* control = GetDirsListBox();
1887 wxArrayInt selections;
1888 if (!control || control->GetSelections(selections) < 1)
1889 return;
1890
1891 if (selections.GetCount()>1)
1892 {
1893 cbMessageBox(_("Please select only one directory you would like to edit."),
1894 _("Error"), wxICON_ERROR);
1895 return;
1896 }
1897
1898 EditPathDlg dlg(this,
1899 control->GetString(selections[0]),
1900 m_pProject ? m_pProject->GetBasePath() : _T(""),
1901 _("Edit directory"));
1902
1903 PlaceWindow(&dlg);
1904 if (dlg.ShowModal() == wxID_OK)
1905 {
1906 wxString path = dlg.GetPath();
1907 control->SetString(selections[0], path);
1908 m_bDirty = true;
1909 }
1910 } // OnEditDirClick
1911
OnRemoveDirClick(cb_unused wxCommandEvent & event)1912 void CompilerOptionsDlg::OnRemoveDirClick(cb_unused wxCommandEvent& event)
1913 {
1914 wxListBox* control = GetDirsListBox();
1915 wxArrayInt selections;
1916 if (!control || control->GetSelections(selections) < 1)
1917 return;
1918
1919 if (cbMessageBox(_("Remove selected folders from the list?"),
1920 _("Confirmation"),
1921 wxOK | wxCANCEL | wxICON_QUESTION) == wxID_OK)
1922 {
1923 std::sort(selections.begin(), selections.end());
1924 for (unsigned int i=selections.GetCount(); i>0; --i)
1925 control->Delete(selections[i-1]);
1926 m_bDirty = true;
1927 }
1928 } // OnRemoveDirClick
1929
OnClearDirClick(cb_unused wxCommandEvent & event)1930 void CompilerOptionsDlg::OnClearDirClick(cb_unused wxCommandEvent& event)
1931 {
1932 wxListBox* control = GetDirsListBox();
1933 if (!control || control->GetCount() == 0)
1934 return;
1935
1936 if (cbMessageBox(_("Remove all directories from the list?"),
1937 _("Confirmation"),
1938 wxOK | wxCANCEL | wxICON_QUESTION) == wxID_OK)
1939 {
1940 control->Clear();
1941 m_bDirty = true;
1942 }
1943 } // OnClearDirClick
1944
OnCopyDirsClick(cb_unused wxCommandEvent & event)1945 void CompilerOptionsDlg::OnCopyDirsClick(cb_unused wxCommandEvent& event)
1946 {
1947 if (!m_pProject)
1948 return;
1949
1950 wxListBox* control = GetDirsListBox();
1951 wxArrayInt selections;
1952 if (!control || control->GetSelections(selections) < 1)
1953 return;
1954
1955 wxArrayString choices;
1956 choices.Add(m_pProject->GetTitle());
1957 for (int i = 0; i < m_pProject->GetBuildTargetsCount(); ++i)
1958 {
1959 ProjectBuildTarget* bt = m_pProject->GetBuildTarget(i);
1960 choices.Add(bt->GetTitle());
1961 }
1962
1963 const wxArrayInt &sel = cbGetMultiChoiceDialog(_("Please select which target to copy these directories to:"),
1964 _("Copy directories"), choices, this);
1965 if (sel.empty())
1966 return;
1967
1968 wxNotebook* nb = XRCCTRL(*this, "nbDirs", wxNotebook);
1969 int notebookPage = nb->GetSelection();
1970
1971 for (wxArrayInt::const_iterator itr = sel.begin(); itr != sel.end(); ++itr)
1972 {
1973 CompileOptionsBase* base;
1974 if((*itr) == 0)
1975 base = m_pProject; // "copy to project"
1976 else
1977 base = m_pProject->GetBuildTarget((*itr) - 1);
1978
1979 if (!base)
1980 {
1981 Manager::Get()->GetLogManager()->LogWarning(_T("Could not get build target in CompilerOptionsDlg::OnCopyLibsClick"));
1982 continue;
1983 }
1984
1985 for (size_t i = 0; i < selections.GetCount(); ++i)
1986 {
1987 switch (notebookPage)
1988 {
1989 case 0: // compiler dirs
1990 base->AddIncludeDir(control->GetString(selections[i]));
1991 break;
1992 case 1: // linker dirs
1993 base->AddLibDir(control->GetString(selections[i]));
1994 break;
1995 case 2: // resource compiler dirs
1996 base->AddResourceIncludeDir(control->GetString(selections[i]));
1997 break;
1998 default:
1999 break;
2000 }
2001 }
2002 }
2003 } // OnCopyDirsClick
2004
QuoteString(wxString & value,const wxString & caption)2005 static void QuoteString(wxString &value, const wxString &caption)
2006 {
2007 if (NeedQuotes(value))
2008 {
2009 AnnoyingDialog dlgQuestion(caption, wxT("Variable quote string"),
2010 _("The value contains spaces or strange characters. Do you want to quote it?"),
2011 wxART_QUESTION, AnnoyingDialog::YES_NO, AnnoyingDialog::rtSAVE_CHOICE,
2012 _("&Quote"), _("&Leave unquoted"));
2013 if (dlgQuestion.ShowModal() == AnnoyingDialog::rtYES)
2014 ::QuoteStringIfNeeded(value);
2015 }
2016 }
2017
OnAddVarClick(cb_unused wxCommandEvent & event)2018 void CompilerOptionsDlg::OnAddVarClick(cb_unused wxCommandEvent& event)
2019 {
2020 wxString key;
2021 wxString value;
2022 EditPairDlg dlg(this, key, value, _("Add new variable"), EditPairDlg::bmBrowseForDirectory);
2023 PlaceWindow(&dlg);
2024 if (dlg.ShowModal() == wxID_OK)
2025 {
2026 key.Trim(true).Trim(false);
2027 value.Trim(true).Trim(false);
2028 QuoteString(value, _("Add variable quote string"));
2029 CustomVarAction Action = {CVA_Add, key, value};
2030 m_CustomVarActions.push_back(Action);
2031 XRCCTRL(*this, "lstVars", wxListBox)->Append(key + _T(" = ") + value, new VariableListClientData(key, value));
2032 m_bDirty = true;
2033 }
2034 } // OnAddVarClick
2035
OnEditVarClick(cb_unused wxCommandEvent & event)2036 void CompilerOptionsDlg::OnEditVarClick(cb_unused wxCommandEvent& event)
2037 {
2038 wxListBox *list = XRCCTRL(*this, "lstVars", wxListBox);
2039 int sel = list->GetSelection();
2040 if (sel == -1)
2041 return;
2042
2043 VariableListClientData *data = static_cast<VariableListClientData*>(list->GetClientObject(sel));
2044 wxString key = data->key;
2045 wxString value = data->value;
2046
2047 EditPairDlg dlg(this, key, value, _("Edit variable"), EditPairDlg::bmBrowseForDirectory);
2048 PlaceWindow(&dlg);
2049 if (dlg.ShowModal() == wxID_OK)
2050 {
2051 key.Trim(true).Trim(false);
2052 value.Trim(true).Trim(false);
2053 QuoteString(value, _("Edit variable quote string"));
2054
2055 if (value != data->value || key != data->key)
2056 { // something has changed
2057 CustomVarAction Action = {CVA_Edit, data->key, key + _T(" = ") + value};
2058 m_CustomVarActions.push_back(Action);
2059 list->SetString(sel, key + _T(" = ") + value);
2060 data->key = key;
2061 data->value = value;
2062 m_bDirty = true;
2063 }
2064 }
2065 } // OnEditVarClick
2066
OnRemoveVarClick(cb_unused wxCommandEvent & event)2067 void CompilerOptionsDlg::OnRemoveVarClick(cb_unused wxCommandEvent& event)
2068 {
2069 wxListBox *list = XRCCTRL(*this, "lstVars", wxListBox);
2070 int sel = list->GetSelection();
2071 if (sel == -1)
2072 return;
2073 const wxString &key = static_cast<VariableListClientData*>(list->GetClientObject(sel))->key;
2074 if (key.IsEmpty())
2075 return;
2076
2077 if (cbMessageBox(_("Are you sure you want to delete this variable?"),
2078 _("Confirmation"),
2079 wxYES_NO | wxICON_QUESTION) == wxID_YES)
2080 {
2081 CustomVarAction Action = {CVA_Remove, key, wxEmptyString};
2082 m_CustomVarActions.push_back(Action);
2083 list->Delete(sel);
2084 m_bDirty = true;
2085 }
2086 } // OnRemoveVarClick
2087
OnClearVarClick(cb_unused wxCommandEvent & event)2088 void CompilerOptionsDlg::OnClearVarClick(cb_unused wxCommandEvent& event)
2089 {
2090 wxListBox* lstVars = XRCCTRL(*this, "lstVars", wxListBox);
2091 if (lstVars->IsEmpty())
2092 return;
2093
2094 if (cbMessageBox(_("Are you sure you want to clear all variables?"),
2095 _("Confirmation"),
2096 wxYES | wxNO | wxICON_QUESTION) == wxID_YES)
2097 {
2098 // Unset all variables of lstVars
2099 for (size_t i=0; i < lstVars->GetCount(); ++i)
2100 {
2101 const wxString &key = static_cast<VariableListClientData*>(lstVars->GetClientObject(i))->key;
2102 if (!key.IsEmpty())
2103 {
2104 CustomVarAction Action = {CVA_Remove, key, wxEmptyString};
2105 m_CustomVarActions.push_back(Action);
2106 }
2107 }
2108 lstVars->Clear();
2109 m_bDirty = true;
2110 }
2111 } // OnClearVarClick
2112
OnSetDefaultCompilerClick(cb_unused wxCommandEvent & event)2113 void CompilerOptionsDlg::OnSetDefaultCompilerClick(cb_unused wxCommandEvent& event)
2114 {
2115 wxChoice* cmb = XRCCTRL(*this, "cmbCompiler", wxChoice);
2116 int idx = cmb->GetSelection();
2117 CompilerFactory::SetDefaultCompiler(idx);
2118 wxString msg;
2119 Compiler* compiler = CompilerFactory::GetDefaultCompiler();
2120 #if wxCHECK_VERSION(3, 0, 0)
2121 msg.Printf(_("%s is now selected as the default compiler for new projects"), compiler ? compiler->GetName().wx_str() : _("[invalid]").wx_str());
2122 #else
2123 msg.Printf(_("%s is now selected as the default compiler for new projects"), compiler ? compiler->GetName().c_str() : _("[invalid]"));
2124 #endif
2125 cbMessageBox(msg);
2126 } // OnSetDefaultCompilerClick
2127
OnAddCompilerClick(cb_unused wxCommandEvent & event)2128 void CompilerOptionsDlg::OnAddCompilerClick(cb_unused wxCommandEvent& event)
2129 {
2130 if (m_bDirty)
2131 { // changes had been made to the current selected compiler
2132 switch(cbMessageBox(_("You have changed some settings. Do you want these settings saved ?\n\n"
2133 "Yes : will apply the changes\n"
2134 "No : will undo the changes\n"
2135 "Cancel : will cancel your compiler addition."),
2136 _("Compiler change with changed settings"),
2137 wxICON_EXCLAMATION|wxYES|wxNO|wxCANCEL))
2138 {
2139 case wxID_CANCEL :
2140 return;
2141 break;
2142 case wxID_YES :
2143 DoSaveCompilerDependentSettings();
2144 break;
2145 case wxID_NO :
2146 default:
2147 // we don't clear the dirty flag yet (in case something goes wrong with the compiler copy we need to reload the
2148 // 'selected compiler' options omitting the current 'No'-ed changes
2149 break;
2150 } // end switch
2151 }
2152 wxChoice* cmb = 0;
2153 cmb = XRCCTRL(*this, "cmbCompiler", wxChoice);
2154 wxString value = cbGetTextFromUser(_("Please enter the new compiler's name:"),
2155 _("Add new compiler"),
2156 _("Copy of ") + CompilerFactory::GetCompiler(m_CurrentCompilerIdx)->GetName());
2157 if (!value.IsEmpty())
2158 {
2159 // make a copy of current compiler
2160 Compiler* newC = 0;
2161 try
2162 {
2163 newC = CompilerFactory::CreateCompilerCopy(CompilerFactory::GetCompiler(m_CurrentCompilerIdx), value);
2164 }
2165 catch (cbException& e)
2166 {
2167 // usually throws because of non-unique ID
2168 e.ShowErrorMessage(false);
2169 newC = 0; // just to be sure
2170 }
2171
2172 if (!newC)
2173 {
2174 cbMessageBox(_("The new compiler could not be created.\n(maybe a compiler with the same name already exists?)"),
2175 _("Error"), wxICON_ERROR);
2176 return;
2177 }
2178 else
2179 {
2180 m_CurrentCompilerIdx = CompilerFactory::GetCompilerIndex(newC);
2181
2182 cmb->Append(value);
2183 cmb->SetSelection(cmb->GetCount() - 1);
2184 // refresh settings in dialog
2185 DoFillCompilerDependentSettings();
2186 cbMessageBox(_("The new compiler has been added! Don't forget to update the \"Toolchain executables\" page..."));
2187 }
2188 }
2189 if (m_bDirty)
2190 { // something went wrong -> reload current settings omitting the NO-ed changes
2191 m_bDirty = false;
2192 CompilerChanged();
2193 }
2194 } // OnAddCompilerClick
2195
OnEditCompilerClick(cb_unused wxCommandEvent & event)2196 void CompilerOptionsDlg::OnEditCompilerClick(cb_unused wxCommandEvent& event)
2197 {
2198 wxChoice* cmb = XRCCTRL(*this, "cmbCompiler", wxChoice);
2199 wxString value = cbGetTextFromUser(_("Please edit the compiler's name:"), _("Rename compiler"), cmb->GetStringSelection());
2200 if (!value.IsEmpty())
2201 {
2202 Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
2203 if (compiler)
2204 compiler->SetName(value);
2205 cmb->SetString(m_CurrentCompilerIdx, value);
2206 cmb->SetSelection(m_CurrentCompilerIdx);
2207 }
2208 } // OnEditCompilerClick
2209
OnRemoveCompilerClick(cb_unused wxCommandEvent & event)2210 void CompilerOptionsDlg::OnRemoveCompilerClick(cb_unused wxCommandEvent& event)
2211 {
2212 if (cbMessageBox(_("Are you sure you want to remove this compiler?"),
2213 _("Confirmation"),
2214 wxYES | wxNO| wxICON_QUESTION | wxNO_DEFAULT) == wxID_YES)
2215 {
2216 wxChoice* cmb = XRCCTRL(*this, "cmbCompiler", wxChoice);
2217 int compilerIdx = m_CurrentCompilerIdx;
2218 CompilerFactory::RemoveCompiler(CompilerFactory::GetCompiler(compilerIdx));
2219 cmb->Delete(compilerIdx);
2220 while (compilerIdx >= (int)(cmb->GetCount()))
2221 --compilerIdx;
2222 cmb->SetSelection(compilerIdx);
2223 m_CurrentCompilerIdx = compilerIdx;
2224 DoFillCompilerDependentSettings();
2225 }
2226 } // OnRemoveCompilerClick
2227
OnResetCompilerClick(cb_unused wxCommandEvent & event)2228 void CompilerOptionsDlg::OnResetCompilerClick(cb_unused wxCommandEvent& event)
2229 {
2230 if (cbMessageBox(_("Reset this compiler's settings to the defaults?"),
2231 _("Confirmation"),
2232 wxYES | wxNO| wxICON_QUESTION | wxNO_DEFAULT) == wxID_YES)
2233 if (cbMessageBox(_("Reset this compiler's settings to the defaults?\n"
2234 "\nAre you REALLY sure?"),
2235 _("Confirmation"),
2236 wxYES | wxNO| wxICON_QUESTION | wxNO_DEFAULT) == wxID_YES)
2237 {
2238 Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
2239 if (compiler)
2240 {
2241 const wxString file = wxT("/compilers/options_") + compiler->GetID() + wxT(".xml");
2242 if ( wxFileExists(ConfigManager::GetDataFolder(true) + file)
2243 && wxFileExists(ConfigManager::GetDataFolder(false) + file) )
2244 {
2245 wxRemoveFile(ConfigManager::GetDataFolder(false) + file);
2246 }
2247 compiler->Reset();
2248 }
2249 // run auto-detection
2250 AutoDetectCompiler();
2251 CompilerFactory::SaveSettings();
2252 // refresh settings in dialog
2253 DoFillCompilerDependentSettings();
2254 }
2255 } // OnResetCompilerClick
2256
2257 // 4 handlers for the adding/editing/removing/clearing of Linker Libs
OnAddLibClick(cb_unused wxCommandEvent & event)2258 void CompilerOptionsDlg::OnAddLibClick(cb_unused wxCommandEvent& event)
2259 {
2260 wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
2261
2262 EditPathDlg dlg(this,
2263 _T(""),
2264 m_pProject ? m_pProject->GetBasePath() : _T(""),
2265 _("Add library"),
2266 _("Choose library to link"),
2267 false,
2268 true,
2269 _("Library files (*.a, *.so, *.lib, *.dylib, *.bundle)|*.a;*.so;*.lib;*.dylib;*.bundle|All files (*)|*"));
2270
2271 PlaceWindow(&dlg);
2272 if (dlg.ShowModal() == wxID_OK)
2273 {
2274 wxArrayString paths = GetArrayFromString(dlg.GetPath());
2275 for (size_t i = 0; i < paths.GetCount(); ++i)
2276 lstLibs->Append(paths[i]);
2277 m_bDirty = true;
2278 }
2279 } // OnAddLibClick
2280
OnEditLibClick(cb_unused wxCommandEvent & event)2281 void CompilerOptionsDlg::OnEditLibClick(cb_unused wxCommandEvent& event)
2282 {
2283 wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
2284 if (!lstLibs)
2285 return;
2286
2287 wxArrayInt sels;
2288 int num = lstLibs->GetSelections(sels);
2289 if (num<1)
2290 {
2291 cbMessageBox(_("Please select a library you wish to edit."),
2292 _("Error"), wxICON_ERROR);
2293 }
2294 else if (num == 1)
2295 {
2296 EditPathDlg dlg(this,
2297 lstLibs->GetString(sels[0]),
2298 m_pProject ? m_pProject->GetBasePath() : _T(""),
2299 _("Edit library"),
2300 _("Choose library to link"),
2301 false,
2302 false,
2303 _("Library files (*.a, *.so, *.lib, *.dylib, *.bundle)|*.a;*.so;*.lib;*.dylib;*.bundle|All files (*)|*"));
2304
2305 PlaceWindow(&dlg);
2306 if (dlg.ShowModal() == wxID_OK)
2307 {
2308 lstLibs->SetString(sels[0], dlg.GetPath());
2309 m_bDirty = true;
2310 }
2311 }
2312 else
2313 {
2314 cbMessageBox(_("Please select only *one* library you wish to edit."),
2315 _("Error"), wxICON_ERROR);
2316 }
2317 } // OnEditLibClick
2318
OnRemoveLibClick(cb_unused wxCommandEvent & event)2319 void CompilerOptionsDlg::OnRemoveLibClick(cb_unused wxCommandEvent& event)
2320 {
2321 wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
2322 if (!lstLibs)
2323 return;
2324
2325 wxArrayInt sels;
2326 int num = lstLibs->GetSelections(sels);
2327 if (num == 1) // mimic old behaviour
2328 {
2329 if (cbMessageBox(_("Remove library '")+lstLibs->GetString(sels[0])+_("' from the list?"),
2330 _("Confirmation"), wxICON_QUESTION | wxOK | wxCANCEL) == wxID_OK)
2331 {
2332 lstLibs->Delete(sels[0]);
2333 m_bDirty = true;
2334 }
2335 }
2336 else if (num > 1)
2337 {
2338 wxString msg; msg.Printf(_("Remove all (%d) selected libraries from the list?"), num);
2339 if (cbMessageBox(msg, _("Confirmation"), wxICON_QUESTION | wxOK | wxCANCEL) == wxID_OK)
2340 {
2341 // remove starting with the last lib. otherwise indices will change
2342 for (size_t i = sels.GetCount(); i>0; --i)
2343 lstLibs->Delete(sels[i-1]);
2344 m_bDirty = true;
2345 }
2346 }
2347 // else: No lib selected
2348 } // OnRemoveLibClick
2349
OnClearLibClick(cb_unused wxCommandEvent & event)2350 void CompilerOptionsDlg::OnClearLibClick(cb_unused wxCommandEvent& event)
2351 {
2352 wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
2353 if (!lstLibs || lstLibs->GetCount() == 0)
2354 return;
2355 if (cbMessageBox(_("Remove all libraries from the list?"), _("Confirmation"), wxICON_QUESTION | wxOK | wxCANCEL) == wxID_OK)
2356 {
2357 lstLibs->Clear();
2358 m_bDirty = true;
2359 }
2360 } // OnClearLibClick
2361
OnCopyLibsClick(cb_unused wxCommandEvent & event)2362 void CompilerOptionsDlg::OnCopyLibsClick(cb_unused wxCommandEvent& event)
2363 {
2364 if (!m_pProject)
2365 return;
2366 wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
2367 if (!lstLibs || lstLibs->GetCount() == 0)
2368 return;
2369
2370 wxArrayString choices;
2371 choices.Add(m_pProject->GetTitle());
2372 for (int i = 0; i < m_pProject->GetBuildTargetsCount(); ++i)
2373 {
2374 ProjectBuildTarget* bt = m_pProject->GetBuildTarget(i);
2375 choices.Add(bt->GetTitle());
2376 }
2377
2378 const wxArrayInt &sel = cbGetMultiChoiceDialog(_("Please select which target to copy these libraries to:"),
2379 _("Copy libraries"), choices, this);
2380 if (sel.empty())
2381 return;
2382
2383 for (wxArrayInt::const_iterator itr = sel.begin(); itr != sel.end(); ++itr)
2384 {
2385 CompileOptionsBase* base;
2386 if((*itr) == 0)
2387 base = m_pProject; // "copy to project"
2388 else
2389 base = m_pProject->GetBuildTarget((*itr) - 1);
2390
2391 if (!base)
2392 {
2393 Manager::Get()->GetLogManager()->LogWarning(_T("Could not get build target in CompilerOptionsDlg::OnCopyLibsClick"));
2394 continue;
2395 }
2396
2397 for (size_t i = 0; i < lstLibs->GetCount(); ++i)
2398 {
2399 if (lstLibs->IsSelected(i))
2400 base->AddLinkLib(lstLibs->GetString(i));
2401 }
2402 }
2403 } // OnCopyLibsClick
2404
OnAddExtraPathClick(cb_unused wxCommandEvent & event)2405 void CompilerOptionsDlg::OnAddExtraPathClick(cb_unused wxCommandEvent& event)
2406 {
2407 EditPathDlg dlg(this, _T(""), _T(""), _("Add directory"));
2408
2409 PlaceWindow(&dlg);
2410 if (dlg.ShowModal() == wxID_OK)
2411 {
2412 wxListBox* control = XRCCTRL(*this, "lstExtraPaths", wxListBox);
2413 if (control)
2414 {
2415 wxString path = dlg.GetPath();
2416
2417 // get all listBox entries in array String
2418 wxArrayString extraPaths;
2419 ListBox2ArrayString(extraPaths, control);
2420 if (extraPaths.Index(path) != wxNOT_FOUND)
2421 {
2422 cbMessageBox(_("Path already in extra paths list!"), _("Warning"), wxICON_WARNING);
2423 }
2424 else
2425 {
2426 control->Append(path);
2427 m_bDirty = true;
2428 }
2429 }
2430 }
2431 } // OnAddExtraPathClick
2432
OnEditExtraPathClick(cb_unused wxCommandEvent & event)2433 void CompilerOptionsDlg::OnEditExtraPathClick(cb_unused wxCommandEvent& event)
2434 {
2435 wxListBox* control = XRCCTRL(*this, "lstExtraPaths", wxListBox);
2436 if (!control || control->GetSelection() < 0)
2437 return;
2438
2439 wxFileName dir(control->GetString(control->GetSelection()) + wxFileName::GetPathSeparator());
2440 wxString initial = control->GetString(control->GetSelection()); // might be a macro
2441 if (dir.DirExists())
2442 initial = dir.GetPath(wxPATH_GET_VOLUME);
2443
2444 EditPathDlg dlg(this, initial, _T(""), _("Edit directory"));
2445
2446 PlaceWindow(&dlg);
2447 if (dlg.ShowModal() == wxID_OK)
2448 {
2449 wxString path = dlg.GetPath();
2450
2451 // get all listBox entries in array String
2452 wxArrayString extraPaths;
2453 ListBox2ArrayString(extraPaths, control);
2454 if (extraPaths.Index(path) != wxNOT_FOUND)
2455 {
2456 cbMessageBox(_("Path already in extra paths list!"), _("Warning"), wxICON_WARNING);
2457 }
2458 else
2459 {
2460 control->SetString(control->GetSelection(), path);
2461 m_bDirty = true;
2462 }
2463 }
2464 } // OnEditExtraPathClick
2465
OnRemoveExtraPathClick(cb_unused wxCommandEvent & event)2466 void CompilerOptionsDlg::OnRemoveExtraPathClick(cb_unused wxCommandEvent& event)
2467 {
2468 wxListBox* control = XRCCTRL(*this, "lstExtraPaths", wxListBox);
2469 if (!control || control->GetSelection() < 0)
2470 return;
2471 control->Delete(control->GetSelection());
2472 m_bDirty = true;
2473 } // OnRemoveExtraPathClick
2474
OnClearExtraPathClick(cb_unused wxCommandEvent & event)2475 void CompilerOptionsDlg::OnClearExtraPathClick(cb_unused wxCommandEvent& event)
2476 {
2477 wxListBox* control = XRCCTRL(*this, "lstExtraPaths", wxListBox);
2478 if (!control || control->IsEmpty())
2479 return;
2480
2481 if (cbMessageBox(_("Remove all extra paths from the list?"), _("Confirmation"), wxICON_QUESTION | wxOK | wxCANCEL) == wxID_OK)
2482 {
2483 control->Clear();
2484 m_bDirty = true;
2485 }
2486 } // OnClearExtraPathClick
2487
OnIgnoreAddClick(cb_unused wxCommandEvent & event)2488 void CompilerOptionsDlg::OnIgnoreAddClick(cb_unused wxCommandEvent& event)
2489 {
2490 wxListBox* list = XRCCTRL(*this, "lstIgnore", wxListBox);
2491 wxTextCtrl* text = XRCCTRL(*this, "txtIgnore", wxTextCtrl);
2492
2493 wxString ignore_str = text->GetValue().Trim();
2494 if ( (ignore_str.Len()>0)
2495 && (list->FindString(ignore_str)==wxNOT_FOUND) )
2496 {
2497 list->Append(ignore_str);
2498 m_bDirty = true;
2499 }
2500 } // OnIgnoreAddClick
2501
OnIgnoreRemoveClick(cb_unused wxCommandEvent & event)2502 void CompilerOptionsDlg::OnIgnoreRemoveClick(cb_unused wxCommandEvent& event)
2503 {
2504 wxListBox* list = XRCCTRL(*this, "lstIgnore", wxListBox);
2505 if (!list || list->IsEmpty())
2506 return;
2507
2508 int selection = list->GetSelection();
2509 if (selection!=wxNOT_FOUND)
2510 {
2511 list->Delete(selection);
2512 m_bDirty = true;
2513 }
2514 } // OnIgnoreRemoveClick
2515
OnMoveLibUpClick(cb_unused wxCommandEvent & event)2516 void CompilerOptionsDlg::OnMoveLibUpClick(cb_unused wxCommandEvent& event)
2517 {
2518 wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
2519 if (!lstLibs)
2520 return;
2521
2522 wxArrayInt sels;
2523 int num = lstLibs->GetSelections(sels);
2524 if (num == 0)
2525 return;
2526
2527 // moving upwards: need to start from the first element
2528 // starting at second element, the first one cannot be moved upwards
2529 for (size_t i=1; i<lstLibs->GetCount(); ++i)
2530 {
2531 // do not move upwards if the lib before is selected, too
2532 if (lstLibs->IsSelected(i) && !lstLibs->IsSelected(i-1))
2533 {
2534 wxString lib = lstLibs->GetString(i);
2535 lstLibs->Delete(i);
2536
2537 lstLibs->InsertItems(1, &lib, i - 1);
2538 lstLibs->SetSelection(i - 1);
2539
2540 m_bDirty = true;
2541 }
2542 }
2543 } // OnMoveLibUpClick
2544
OnMoveLibDownClick(cb_unused wxCommandEvent & event)2545 void CompilerOptionsDlg::OnMoveLibDownClick(cb_unused wxCommandEvent& event)
2546 {
2547 wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
2548 if (!lstLibs)
2549 return;
2550
2551 wxArrayInt sels;
2552 int num = lstLibs->GetSelections(sels);
2553 if (num == 0)
2554 return;
2555
2556 // moving downwards: need to start from the last element
2557 // starting at pre-last element, the last one cannot be moved downwards
2558 for (size_t i=lstLibs->GetCount()-1; i>0; --i)
2559 {
2560 // do not move downwards if the lib after is selected, too
2561 // notice here: as started with index+1 (due to GetCount)...
2562 // ... subtract 1 all the way to achieve the real index operated on
2563 if (lstLibs->IsSelected(i-1) && !lstLibs->IsSelected(i))
2564 {
2565 wxString lib = lstLibs->GetString(i-1);
2566 lstLibs->Delete(i-1);
2567
2568 lstLibs->InsertItems(1, &lib, i);
2569 lstLibs->SetSelection(i);
2570
2571 m_bDirty = true;
2572 }
2573 }
2574 } // OnMoveLibDownClick
2575
OnMoveDirUpClick(cb_unused wxCommandEvent & event)2576 void CompilerOptionsDlg::OnMoveDirUpClick(cb_unused wxCommandEvent& event)
2577 {
2578 wxListBox* lst = GetDirsListBox();
2579 wxArrayInt sels;
2580 if (!lst || lst->GetSelections(sels) < 1)
2581 return;
2582
2583 // moving upwards: need to start from the first element
2584 // starting at second element, the first one cannot be moved upwards
2585 for (size_t i=1; i<lst->GetCount(); ++i)
2586 {
2587 // do not move upwards if the dir before is selected, too
2588 if (lst->IsSelected(i) && !lst->IsSelected(i-1))
2589 {
2590 wxString dir = lst->GetString(i);
2591 lst->Delete(i);
2592
2593 lst->InsertItems(1, &dir, i - 1);
2594 lst->SetSelection(i - 1);
2595
2596 m_bDirty = true;
2597 }
2598 }
2599 } // OnMoveDirUpClick
2600
OnMoveDirDownClick(cb_unused wxCommandEvent & event)2601 void CompilerOptionsDlg::OnMoveDirDownClick(cb_unused wxCommandEvent& event)
2602 {
2603 wxListBox* lst = GetDirsListBox();
2604 wxArrayInt sels;
2605 if (!lst || lst->GetSelections(sels) < 1)
2606 return;
2607
2608 // moving downwards: need to start from the last element
2609 // starting at pre-last element, the last one cannot be moved downwards
2610 for (size_t i=lst->GetCount()-1; i>0; --i)
2611 {
2612 // do not move downwards if the dir after is selected, too
2613 // notice here: as started with index+1 (due to GetCount)...
2614 // ... subtract 1 all the way to achieve the real index operated on
2615 if (lst->IsSelected(i-1) && !lst->IsSelected(i))
2616 {
2617 wxString dir = lst->GetString(i-1);
2618 lst->Delete(i-1);
2619
2620 lst->InsertItems(1, &dir, i);
2621 lst->SetSelection(i);
2622
2623 m_bDirty = true;
2624 }
2625 }
2626 } // OnMoveDirDownClick
2627
OnMasterPathClick(cb_unused wxCommandEvent & event)2628 void CompilerOptionsDlg::OnMasterPathClick(cb_unused wxCommandEvent& event)
2629 {
2630 wxString path = ChooseDirectory(this,
2631 _("Select directory"),
2632 XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->GetValue());
2633 if (!path.IsEmpty())
2634 {
2635 XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->SetValue(path);
2636 m_bDirty = true;
2637 }
2638 } // OnMasterPathClick
2639
OnAutoDetectClick(cb_unused wxCommandEvent & event)2640 void CompilerOptionsDlg::OnAutoDetectClick(cb_unused wxCommandEvent& event)
2641 {
2642 AutoDetectCompiler();
2643 } // OnAutoDetectClick
2644
OnSelectProgramClick(wxCommandEvent & event)2645 void CompilerOptionsDlg::OnSelectProgramClick(wxCommandEvent& event)
2646 {
2647 // see who called us
2648 wxTextCtrl* obj = 0L;
2649 if (event.GetId() == XRCID("btnCcompiler"))
2650 obj = XRCCTRL(*this, "txtCcompiler", wxTextCtrl);
2651 else if (event.GetId() == XRCID("btnCPPcompiler"))
2652 obj = XRCCTRL(*this, "txtCPPcompiler", wxTextCtrl);
2653 else if (event.GetId() == XRCID("btnLinker"))
2654 obj = XRCCTRL(*this, "txtLinker", wxTextCtrl);
2655 else if (event.GetId() == XRCID("btnLibLinker"))
2656 obj = XRCCTRL(*this, "txtLibLinker", wxTextCtrl);
2657 else if (event.GetId() == XRCID("btnResComp"))
2658 obj = XRCCTRL(*this, "txtResComp", wxTextCtrl);
2659 else if (event.GetId() == XRCID("btnMake"))
2660 obj = XRCCTRL(*this, "txtMake", wxTextCtrl);
2661
2662 if (!obj)
2663 return; // called from invalid caller
2664
2665 // common part follows
2666 wxString file_selection = _("All files (*)|*");
2667 if (platform::windows)
2668 file_selection = _("Executable files (*.exe)|*.exe");
2669 wxFileDialog dlg(this,
2670 _("Select file"),
2671 XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->GetValue() + _T("/bin"),
2672 obj->GetValue(),
2673 file_selection,
2674 wxFD_OPEN | wxFD_FILE_MUST_EXIST | compatibility::wxHideReadonly );
2675 dlg.SetFilterIndex(0);
2676
2677 PlaceWindow(&dlg);
2678 if (dlg.ShowModal() != wxID_OK)
2679 return;
2680 wxFileName fname(dlg.GetPath());
2681 obj->SetValue(fname.GetFullName());
2682 m_bDirty = true;
2683 } // OnSelectProgramClick
2684
OnAdvancedClick(cb_unused wxCommandEvent & event)2685 void CompilerOptionsDlg::OnAdvancedClick(cb_unused wxCommandEvent& event)
2686 {
2687 AnnoyingDialog dlg(_("Edit advanced compiler settings?"),
2688 _("The compiler's advanced settings, need command-line "
2689 "compiler knowledge to be tweaked.\nIf you don't know "
2690 "*exactly* what you 're doing, it is suggested to "
2691 "NOT tamper with these...\n\n"
2692 "Are you sure you want to proceed?"),
2693 wxART_QUESTION);
2694 if (dlg.ShowModal() == AnnoyingDialog::rtYES)
2695 {
2696 wxChoice* cmb = XRCCTRL(*this, "cmbCompiler", wxChoice);
2697 int compilerIdx = cmb->GetSelection();
2698 AdvancedCompilerOptionsDlg dlg2(this, CompilerFactory::GetCompiler(compilerIdx)->GetID());
2699 PlaceWindow(&dlg2);
2700 dlg2.ShowModal();
2701 // check if dirty
2702 if (dlg2.IsDirty())
2703 {
2704 // m_bDirty = true; // TO DO : Activate when implemented in the adv dialog
2705 }
2706 }
2707 } // OnAdvancedClick
2708
UpdateUIListBoxAndButtons(wxListBox & list,wxButton & edit,wxButton & del,wxButton & clear,wxButton & copy,wxButton & up,wxButton & down)2709 static void UpdateUIListBoxAndButtons(wxListBox &list, wxButton &edit, wxButton &del, wxButton &clear, wxButton ©,
2710 wxButton &up, wxButton &down)
2711 {
2712 wxArrayInt selections;
2713 int num = list.GetSelections(selections);
2714 int itemCount = list.GetCount();
2715 bool en = (num > 0);
2716
2717 edit.Enable(num == 1);
2718 del.Enable(en);
2719 clear.Enable(itemCount != 0);
2720 copy.Enable(en);
2721
2722 if (en)
2723 {
2724 int minIndex = selections.size();
2725 int maxIndex = 0;
2726 for (int index : selections)
2727 {
2728 minIndex = std::min(index, minIndex);
2729 maxIndex = std::max(index, maxIndex);
2730 }
2731 up.Enable(minIndex > 0);
2732 down.Enable(maxIndex < itemCount - 1);
2733 }
2734 else
2735 {
2736 up.Enable(false);
2737 down.Enable(false);
2738 }
2739 }
2740
OnUpdateUI(cb_unused wxUpdateUIEvent & event)2741 void CompilerOptionsDlg::OnUpdateUI(cb_unused wxUpdateUIEvent& event)
2742 {
2743 bool en = false;
2744
2745 wxListBox* control = GetDirsListBox();
2746 if (control)
2747 {
2748 UpdateUIListBoxAndButtons(*control, *XRCCTRL(*this, "btnEditDir", wxButton),
2749 *XRCCTRL(*this, "btnDelDir", wxButton), *XRCCTRL(*this, "btnClearDir", wxButton),
2750 *XRCCTRL(*this, "btnCopyDirs", wxButton), *XRCCTRL(*this, "btnMoveDirUp", wxButton),
2751 *XRCCTRL(*this, "btnMoveDirDown", wxButton));
2752 }
2753
2754 // edit/delete/clear/copy/moveup/movedown lib dirs
2755 wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
2756 if (lstLibs)
2757 {
2758 UpdateUIListBoxAndButtons(*lstLibs, *XRCCTRL(*this, "btnEditLib", wxButton),
2759 *XRCCTRL(*this, "btnDelLib", wxButton), *XRCCTRL(*this, "btnClearLib", wxButton),
2760 *XRCCTRL(*this, "btnCopyLibs", wxButton), *XRCCTRL(*this, "btnMoveLibUp", wxButton),
2761 *XRCCTRL(*this, "btnMoveLibDown", wxButton));
2762 }
2763
2764 // edit/delete/clear/copy/moveup/movedown extra path
2765 if (!m_pProject)
2766 {
2767 en = XRCCTRL(*this, "lstExtraPaths", wxListBox)->GetSelection() >= 0;
2768 XRCCTRL(*this, "btnExtraEdit", wxButton)->Enable(en);
2769 XRCCTRL(*this, "btnExtraDelete", wxButton)->Enable(en);
2770 XRCCTRL(*this, "btnExtraClear", wxButton)->Enable(XRCCTRL(*this, "lstExtraPaths", wxListBox)->GetCount() != 0);
2771 }
2772
2773 // add/edit/delete/clear vars
2774 en = XRCCTRL(*this, "lstVars", wxListBox)->GetSelection() >= 0;
2775 XRCCTRL(*this, "btnEditVar", wxButton)->Enable(en);
2776 XRCCTRL(*this, "btnDeleteVar", wxButton)->Enable(en);
2777 XRCCTRL(*this, "btnClearVar", wxButton)->Enable(XRCCTRL(*this, "lstVars", wxListBox)->GetCount() != 0);
2778
2779 // policies
2780 wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
2781 ScopeTreeData* data = (ScopeTreeData*)tc->GetItemData(tc->GetSelection());
2782 en = (data && data->GetTarget());
2783 XRCCTRL(*this, "cmbCompilerPolicy", wxChoice)->Enable(en);
2784 XRCCTRL(*this, "cmbLinkerPolicy", wxChoice)->Enable(en);
2785 XRCCTRL(*this, "cmbIncludesPolicy", wxChoice)->Enable(en);
2786 XRCCTRL(*this, "cmbLibDirsPolicy", wxChoice)->Enable(en);
2787 XRCCTRL(*this, "cmbResDirsPolicy", wxChoice)->Enable(en);
2788
2789 // compiler set buttons
2790 if (!m_pProject)
2791 {
2792 en = !data; // global options selected
2793 int idx = XRCCTRL(*this, "cmbCompiler", wxChoice)->GetSelection();
2794 int count = XRCCTRL(*this, "cmbCompiler", wxChoice)->GetCount(); // compilers count
2795 Compiler* compiler = CompilerFactory::GetCompiler(idx);
2796
2797 XRCCTRL(*this, "btnSetDefaultCompiler", wxButton)->Enable(CompilerFactory::GetCompilerIndex(CompilerFactory::GetDefaultCompiler()) != idx);
2798 XRCCTRL(*this, "btnAddCompiler", wxButton)->Enable(en);
2799 XRCCTRL(*this, "btnRenameCompiler", wxButton)->Enable(en && count);
2800 XRCCTRL(*this, "btnDelCompiler", wxButton)->Enable(en &&
2801 compiler &&
2802 !compiler->GetParentID().IsEmpty());
2803 XRCCTRL(*this, "btnResetCompiler", wxButton)->Enable(en &&
2804 compiler &&
2805 compiler->GetParentID().IsEmpty());
2806
2807 XRCCTRL(*this, "chkFullHtmlLog", wxCheckBox)->Enable(XRCCTRL(*this, "chkSaveHtmlLog", wxCheckBox)->IsChecked());
2808 XRCCTRL(*this, "btnIgnoreRemove", wxButton)->Enable(XRCCTRL(*this, "lstIgnore", wxListBox)->GetCount()>0);
2809 XRCCTRL(*this, "btnIgnoreAdd", wxButton)->Enable(XRCCTRL(*this, "txtIgnore", wxTextCtrl)->GetValue().Trim().Len()>0);
2810 }
2811 } // OnUpdateUI
2812
OnApply()2813 void CompilerOptionsDlg::OnApply()
2814 {
2815 m_CurrentCompilerIdx = XRCCTRL(*this, "cmbCompiler", wxChoice)->GetSelection();
2816 DoSaveCompilerDependentSettings();
2817 CompilerFactory::SaveSettings();
2818
2819 //others (projects don't have Other tab)
2820 if (!m_pProject)
2821 {
2822 ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("compiler"));
2823 wxCheckBox* chk = XRCCTRL(*this, "chkIncludeFileCwd", wxCheckBox);
2824 if (chk)
2825 cfg->Write(_T("/include_file_cwd"), (bool)chk->IsChecked());
2826 chk = XRCCTRL(*this, "chkIncludePrjCwd", wxCheckBox);
2827 if (chk)
2828 cfg->Write(_T("/include_prj_cwd"), (bool)chk->IsChecked());
2829 chk = XRCCTRL(*this, "chkSkipIncludeDeps", wxCheckBox);
2830 if (chk)
2831 cfg->Write(_T("/skip_include_deps"), (bool)chk->IsChecked());
2832 chk = XRCCTRL(*this, "chkSaveHtmlLog", wxCheckBox);
2833 if (chk)
2834 cfg->Write(_T("/save_html_build_log"), (bool)chk->IsChecked());
2835 chk = XRCCTRL(*this, "chkFullHtmlLog", wxCheckBox);
2836 if (chk)
2837 cfg->Write(_T("/save_html_build_log/full_command_line"), (bool)chk->IsChecked());
2838 chk = XRCCTRL(*this, "chkBuildProgressBar", wxCheckBox);
2839 if (chk)
2840 cfg->Write(_T("/build_progress/bar"), (bool)chk->IsChecked());
2841 chk = XRCCTRL(*this, "chkBuildProgressPerc", wxCheckBox);
2842 if (chk)
2843 {
2844 cfg->Write(_T("/build_progress/percentage"), (bool)chk->IsChecked());
2845 m_Compiler->m_LogBuildProgressPercentage = chk->IsChecked();
2846 }
2847 wxSpinCtrl* spn = XRCCTRL(*this, "spnParallelProcesses", wxSpinCtrl);
2848 if (spn && (((int)spn->GetValue()) != cfg->ReadInt(_T("/parallel_processes"), 0)))
2849 {
2850 if (m_Compiler->IsRunning())
2851 cbMessageBox(_("You can't change the number of parallel processes while building!\nSetting ignored..."), _("Warning"), wxICON_WARNING);
2852 else
2853 {
2854 cfg->Write(_T("/parallel_processes"), (int)spn->GetValue());
2855 m_Compiler->ReAllocProcesses();
2856 }
2857 }
2858 spn = XRCCTRL(*this, "spnMaxErrors", wxSpinCtrl);
2859 if (spn)
2860 cfg->Write(_T("/max_reported_errors"), (int)spn->GetValue());
2861
2862 chk = XRCCTRL(*this, "chkRebuildSeperately", wxCheckBox);
2863 if (chk)
2864 cfg->Write(_T("/rebuild_seperately"), (bool)chk->IsChecked());
2865
2866 wxListBox* lst = XRCCTRL(*this, "lstIgnore", wxListBox);
2867 if (lst)
2868 {
2869 wxArrayString IgnoreOutput;
2870 ListBox2ArrayString(IgnoreOutput, lst);
2871 cfg->Write(_T("/ignore_output"), IgnoreOutput);
2872 }
2873
2874 chk = XRCCTRL(*this, "chkNonPlatComp", wxCheckBox);
2875 if (chk && (chk->IsChecked() != cfg->ReadBool(_T("/non_plat_comp"), false)))
2876 {
2877 if (m_Compiler->IsRunning())
2878 cbMessageBox(_("You can't change the option to enable or disable non-platform compilers while building!\nSetting ignored..."), _("Warning"), wxICON_WARNING);
2879 else
2880 {
2881 cfg->Write(_T("/non_plat_comp"), (bool)chk->IsChecked());
2882 CompilerFactory::UnregisterCompilers();
2883 m_Compiler->DoRegisterCompilers();
2884 m_Compiler->LoadOptions();
2885 }
2886 }
2887 }
2888
2889 m_Compiler->SaveOptions();
2890 m_Compiler->SetupEnvironment();
2891 Manager::Get()->GetMacrosManager()->Reset();
2892 m_bDirty = false;
2893 } // OnApply
2894
OnMyCharHook(wxKeyEvent & event)2895 void CompilerOptionsDlg::OnMyCharHook(wxKeyEvent& event)
2896 {
2897 wxWindow* focused = wxWindow::FindFocus();
2898 if (!focused)
2899 {
2900 event.Skip();
2901 return;
2902 }
2903 int keycode = event.GetKeyCode();
2904 int id = focused->GetId();
2905
2906 int myid = 0;
2907 unsigned int myidx = 0;
2908
2909 const wxChar* str_libs[4] = { _T("btnEditLib"), _T("btnAddLib"), _T("btnDelLib"), _T("btnClearLib") };
2910 const wxChar* str_dirs[4] = { _T("btnEditDir"), _T("btnAddDir"), _T("btnDelDir"), _T("btnClearDir") };
2911 const wxChar* str_vars[4] = { _T("btnEditVar"), _T("btnAddVar"), _T("btnDeleteVar"), _T("btnClearVar") };
2912 const wxChar* str_xtra[4] = { _T("btnExtraEdit"),_T("btnExtraAdd"),_T("btnExtraDelete"),_T("btnExtraClear") };
2913
2914 if (keycode == WXK_RETURN || keycode == WXK_NUMPAD_ENTER)
2915 { myidx = 0; } // Edit
2916 else if (keycode == WXK_INSERT || keycode == WXK_NUMPAD_INSERT)
2917 { myidx = 1; } // Add
2918 else if (keycode == WXK_DELETE || keycode == WXK_NUMPAD_DELETE)
2919 { myidx = 2; } // Delete
2920 else
2921 {
2922 event.Skip();
2923 return;
2924 }
2925
2926 if ( id == XRCID("lstLibs")) // Link libraries
2927 { myid = wxXmlResource::GetXRCID(str_libs[myidx]); }
2928 else if (id == XRCID("lstIncludeDirs") || id == XRCID("lstLibDirs") || id == XRCID("lstResDirs")) // Directories
2929 { myid = wxXmlResource::GetXRCID(str_dirs[myidx]); }
2930 else if (id == XRCID("lstVars")) // Custom Vars
2931 { myid = wxXmlResource::GetXRCID(str_vars[myidx]); }
2932 else if (id == XRCID("lstExtraPaths")) // Extra Paths
2933 { myid = wxXmlResource::GetXRCID(str_xtra[myidx]); }
2934 else
2935 myid = 0;
2936
2937 // Generate the event
2938 if (myid == 0)
2939 event.Skip();
2940 else
2941 {
2942 wxCommandEvent newevent(wxEVT_COMMAND_BUTTON_CLICKED,myid);
2943 this->ProcessEvent(newevent);
2944 }
2945 } // OnMyCharHook
2946
2947 int CompilerOptionsDlg::m_MenuOption = -1;
2948
OnFlagsPopup(wxPropertyGridEvent & event)2949 void CompilerOptionsDlg::OnFlagsPopup(wxPropertyGridEvent& event)
2950 {
2951 int scroll = m_FlagsPG->GetScrollPos(wxVERTICAL);
2952 wxPGProperty *property = event.GetProperty();
2953
2954 enum FlagsMenuOptions
2955 {
2956 FMO_None = -1,
2957 FMO_New = 0,
2958 FMO_Modify,
2959 FMO_Delete,
2960 FMO_COnly,
2961 FMO_CPPOnly,
2962 FMO_ExpandAll,
2963 FMO_CollapseAll
2964 };
2965
2966 wxMenu* pop = new wxMenu;
2967 pop->Append(FMO_New, _("New flag..."));
2968 if (property && !property->IsCategory())
2969 {
2970 pop->Append(FMO_Modify, _("Modify flag..."));
2971 pop->Append(FMO_Delete, _("Delete flag"));
2972 }
2973 pop->AppendSeparator();
2974 pop->Append(FMO_COnly, _("C - only flags..."));
2975 pop->Append(FMO_CPPOnly, _("C++ - only flags..."));
2976 pop->AppendSeparator();
2977 pop->Append(FMO_ExpandAll, _("Expand all categories"));
2978 pop->Append(FMO_CollapseAll, _("Collapse all categories"));
2979 pop->Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&CompilerOptionsDlg::OnFlagsPopupClick);
2980 m_MenuOption = FMO_None;
2981 m_FlagsPG->PopupMenu(pop);
2982 delete pop;
2983 if (m_MenuOption == FMO_None)
2984 return;
2985 if (m_MenuOption == FMO_COnly)
2986 {
2987 Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
2988 wxTextEntryDialog dlg(this, wxT("List flags that will only be used during C compilation"),
2989 wxT("C - only flags"), compiler->GetCOnlyFlags(), wxTextEntryDialogStyle|wxTE_MULTILINE|wxRESIZE_BORDER);
2990 // TODO: Hack for Ubuntu, see here: http://forums.codeblocks.org/index.php/topic,16463.msg115270.html#msg115270 (Remove if no longer needed.)
2991 if (dlg.GetSize().GetHeight() < 220)
2992 {
2993 dlg.SetSize(dlg.GetPosition().x, dlg.GetPosition().y - (220 - dlg.GetSize().GetHeight()) / 2,
2994 dlg.GetSize().GetWidth(), 220);
2995 }
2996 PlaceWindow(&dlg);
2997 dlg.ShowModal();
2998 wxString flags = dlg.GetValue();
2999 flags.Replace(wxT("\n"), wxT(" "));
3000 flags.Replace(wxT("\r"), wxT(" "));
3001 flags.Replace(wxT("\t"), wxT(" "));
3002 flags = MakeUniqueString(flags, wxT(" "));
3003 if (flags != compiler->GetCOnlyFlags())
3004 {
3005 compiler->SetCOnlyFlags(flags);
3006 m_bDirty = true;
3007 }
3008 return;
3009 }
3010 else if (m_MenuOption == FMO_CPPOnly)
3011 {
3012 Compiler* compiler = CompilerFactory::GetCompiler(m_CurrentCompilerIdx);
3013 wxTextEntryDialog dlg(this, wxT("List flags that will only be used during C++ compilation"),
3014 wxT("C++ - only flags"), compiler->GetCPPOnlyFlags(), wxTextEntryDialogStyle|wxTE_MULTILINE|wxRESIZE_BORDER);
3015 // TODO: Hack for Ubuntu, see here: http://forums.codeblocks.org/index.php/topic,16463.msg115270.html#msg115270 (Remove if no longer needed.)
3016 if (dlg.GetSize().GetHeight() < 220)
3017 {
3018 dlg.SetSize(dlg.GetPosition().x, dlg.GetPosition().y - (220 - dlg.GetSize().GetHeight()) / 2,
3019 dlg.GetSize().GetWidth(), 220);
3020 }
3021 dlg.ShowModal();
3022 wxString flags = dlg.GetValue();
3023 flags.Replace(wxT("\n"), wxT(" "));
3024 flags.Replace(wxT("\r"), wxT(" "));
3025 flags.Replace(wxT("\t"), wxT(" "));
3026 flags = MakeUniqueString(flags, wxT(" "));
3027 if (flags != compiler->GetCPPOnlyFlags())
3028 {
3029 compiler->SetCPPOnlyFlags(flags);
3030 m_bDirty = true;
3031 }
3032 return;
3033 }
3034 else if (m_MenuOption == FMO_Delete)
3035 {
3036 size_t i = 0;
3037 for (; i < m_Options.GetCount(); ++i)
3038 {
3039 if (m_Options.GetOption(i)->name == property->GetLabel())
3040 break;
3041 }
3042 m_Options.RemoveOption(i);
3043 }
3044 else if (m_MenuOption == FMO_ExpandAll)
3045 {
3046 m_FlagsPG->ExpandAll();
3047 return;
3048 }
3049 else if (m_MenuOption == FMO_CollapseAll)
3050 {
3051 m_FlagsPG->CollapseAll();
3052 return;
3053 }
3054 else
3055 {
3056 wxArrayString categ;
3057 for (size_t i = 0; i < m_Options.GetCount(); ++i)
3058 {
3059 CompOption* opt = m_Options.GetOption(i);
3060 bool known = false;
3061 for (size_t j = 0; j < categ.GetCount(); ++j)
3062 {
3063 if (categ[j] == opt->category)
3064 {
3065 known = true;
3066 break;
3067 }
3068 }
3069 if (!known)
3070 categ.Add(opt->category);
3071 }
3072 if (categ.IsEmpty())
3073 categ.Add(wxT("General"));
3074 CompOption copt;
3075 if (m_MenuOption == FMO_Modify)
3076 copt = *m_Options.GetOptionByName(property->GetLabel());
3077
3078 wxString categoryName;
3079 if (property)
3080 {
3081 // If we have a selected property try to find the name of the category.
3082 if (property->IsCategory())
3083 categoryName = property->GetLabel();
3084 else
3085 {
3086 wxPGProperty *category = property->GetParent();
3087 if (category)
3088 categoryName = category->GetLabel();
3089 }
3090 }
3091 CompilerFlagDlg dlg(nullptr, &copt, categ, categoryName);
3092 PlaceWindow(&dlg);
3093 if (dlg.ShowModal() != wxID_OK)
3094 return;
3095 if (m_MenuOption == FMO_New)
3096 {
3097 size_t i;
3098 if (property)
3099 {
3100 wxString name;
3101 if (property->IsCategory())
3102 {
3103 wxPGProperty *child = m_FlagsPG->GetFirstChild(property);
3104 if (child)
3105 name = child->GetLabel();
3106 }
3107 else
3108 name = property->GetLabel();
3109 for (i = 0; i < m_Options.GetCount(); ++i)
3110 {
3111 if (m_Options.GetOption(i)->name == name)
3112 break;
3113 }
3114 }
3115 else
3116 i = m_Options.GetCount() - 1;
3117
3118 m_Options.AddOption(copt.name, copt.option,
3119 copt.category, copt.additionalLibs,
3120 copt.checkAgainst, copt.checkMessage,
3121 copt.supersedes, copt.exclusive, i + 1);
3122 }
3123 else
3124 {
3125 CompOption* opt = m_Options.GetOptionByName(property->GetLabel());
3126 wxString name = copt.name + wxT(" [");
3127 if (copt.option.IsEmpty())
3128 name += copt.additionalLibs;
3129 else
3130 name += copt.option;
3131 name += wxT("]");
3132 opt->name = name;
3133 opt->option = copt.option;
3134 opt->additionalLibs = copt.additionalLibs;
3135 opt->category = copt.category;
3136 opt->checkAgainst = copt.checkAgainst;
3137 opt->checkMessage = copt.checkMessage;
3138 opt->supersedes = copt.supersedes;
3139 opt->exclusive = copt.exclusive;
3140 }
3141 }
3142 DoFillOptions();
3143 m_FlagsPG->ScrollLines(scroll);
3144 m_bFlagsDirty = true;
3145 }
3146
OnFlagsPopupClick(wxCommandEvent & event)3147 void CompilerOptionsDlg::OnFlagsPopupClick(wxCommandEvent& event)
3148 {
3149 m_MenuOption = event.GetId();
3150 }
3151
OnOptionDoubleClick(wxPropertyGridEvent & event)3152 void CompilerOptionsDlg::OnOptionDoubleClick(wxPropertyGridEvent& event)
3153 {
3154 wxPGProperty* property = event.GetProperty();
3155 // For bool properties automatically toggle the checkbox on double click.
3156 if (property && property->IsKindOf(CLASSINFO(wxBoolProperty)))
3157 {
3158 bool realValue = m_FlagsPG->GetPropertyValue(property);
3159 m_FlagsPG->ChangePropertyValue(property, !realValue);
3160 }
3161 event.Skip();
3162 }
3163