Code::Blocks  SVN r11506
uservarmanager.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  *
5  * $Revision: 11359 $
6  * $Id: uservarmanager.cpp 11359 2018-04-01 17:11:54Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/uservarmanager.cpp $
8  */
9 
10 #include "sdk_precomp.h"
11 
12 #ifndef CB_PRECOMP
13  #include "uservarmanager.h"
14  #include "configmanager.h"
15  #include "logmanager.h"
16  #include "projectmanager.h"
17  #include "macrosmanager.h"
18  #include "manager.h"
19  #include "cbexception.h"
20  #include "infowindow.h"
21 
22  #include <wx/button.h>
23  #include "scrollingdialog.h"
24  #include <wx/intl.h>
25  #include <wx/xrc/xmlres.h>
26  #include <wx/textctrl.h>
27  #include <wx/textdlg.h>
28  #include <wx/splitter.h>
29  #include <wx/choice.h>
30  #include <wx/listbox.h>
31 #endif
32 
33 #include "annoyingdialog.h"
34 
35 #if wxCHECK_VERSION(3, 0, 0)
36 #include <wx/unichar.h>
37 #endif
38 
39 #include <ctype.h>
40 
41 template<> UserVariableManager* Mgr<UserVariableManager>::instance = nullptr;
42 template<> bool Mgr<UserVariableManager>::isShutdown = false;
43 
44 const wxString cBase (_T("base"));
45 const wxString cDir (_T("dir"));
46 const wxChar cSlash(_T ('/'));
47 const wxString cSlashBase(_T("/base"));
48 const wxString cInclude (_T("include"));
49 const wxString cLib (_T("lib"));
50 const wxString cObj (_T("obj"));
51 const wxString cBin (_T("bin"));
52 const wxString cCflags (_T("cflags"));
53 const wxString cLflags (_T("lflags"));
54 const wxString cSets (_T("/sets/"));
55 
56 const wxChar *bim[] =
57 {
58  _T("base"),
59  _T("include"),
60  _T("lib"),
61  _T("obj"),
62  _T("bin"),
63  _T("cflags"),
64  _T("lflags")
65 };
66 const wxArrayString builtinMembers((size_t) 7, bim);
67 
69 {
70 public:
71  GetUserVariableDialog(wxWindow *parent, const wxString &old);
72 
74 private:
75  void OnOK(cb_unused wxCommandEvent& event);
76  void OnCancel(cb_unused wxCommandEvent& event);
77  void OnConfig(cb_unused wxCommandEvent& event);
78  void OnActivated(wxTreeEvent& event);
79 
80  void Load();
81 
83 private:
87 
88  DECLARE_EVENT_TABLE()
89 };
90 
92 {
95 
98 
100 
106 
107  wxTextCtrl *m_Name[7];
108  wxTextCtrl *m_Value[7];
109 
111 
112  void Help(wxCommandEvent& event);
113  void DoClose();
114  void OnOK(cb_unused wxCommandEvent& event) { DoClose(); };
115  void OnCancel(cb_unused wxCommandEvent& event) { DoClose(); };
116  void CloseHandler(cb_unused wxCloseEvent& event) { DoClose(); };
117 
118  void CloneVar(wxCommandEvent& event);
119  void CloneSet(wxCommandEvent& event);
120  void NewVar(wxCommandEvent& event);
121  void NewSet(wxCommandEvent& event);
122  void DeleteVar(wxCommandEvent& event);
123  void DeleteSet(wxCommandEvent& event);
124  // handler for the folder selection button
125  void OnFS(wxCommandEvent& event);
126 
127  void SelectSet(wxCommandEvent& event);
128  void SelectVar(wxCommandEvent& event);
129 
130  void Load();
131  void Save();
132  void UpdateChoices();
133  void AddVar(const wxString& var);
134  void Sanitise(wxString& s);
135 
136  DECLARE_EVENT_TABLE()
137 
138 public:
140  friend class UserVariableManager;
141 };
142 
144 {
146  PlaceWindow(&d);
147  d.ShowModal();
148  m_ActiveSet = Manager::Get()->GetConfigManager(_T("gcv"))->Read(_T("/active"));
149 }
150 
151 
153 {
154  wxString package = variable.AfterLast(wxT('#')).BeforeFirst(wxT('.')).MakeLower();
155  wxString member = variable.AfterFirst(wxT('.')).MakeLower();
156 
157  wxString path(cSets + m_ActiveSet + _T('/') + package + _T('/'));
158 
159  wxString base = m_CfgMan->Read(path + cBase);
160 
161  if (base.IsEmpty())
162  {
164  {
165  // a project/workspace is being loaded.
166  // no need to bug the user now about global vars.
167  // just preempt it; ProjectManager will call Arrogate() when it's done.
168  Preempt(variable);
169  return variable;
170  }
171  else
172  {
173  wxString msg;
174  msg.Printf(_("In the currently active set, Code::Blocks does not know\n"
175  "the global compiler variable \"%s\".\n\n"
176  "Please define it."), package.wx_str());
177  InfoWindow::Display(_("Global Compiler Variables"), msg , 8000, 1000);
179  d.AddVar(package);
180  PlaceWindow(&d);
181  d.ShowModal();
182  }
183  }
184 
185  if (member.IsEmpty() || member.IsSameAs(cBase))
186  return base;
187 
188  if (member.IsSameAs(cInclude) || member.IsSameAs(cLib) || member.IsSameAs(cObj) || member.IsSameAs(cBin))
189  {
190  wxString ret = m_CfgMan->Read(path + member);
191  if (ret.IsEmpty())
192  ret = base + _T('/') + member;
193  return ret;
194  }
195 
196  const wxString wtf(wxT("#$%&???WTF???&%$#"));
197  wxString ret = m_CfgMan->Read(path + member, wtf);
198  if ( ret.IsSameAs(wtf) )
199  {
200  wxString msg;
201  msg.Printf(_("In the currently active set, Code::Blocks does not know\n"
202  "the member \"%s\" of the global compiler variable \"%s\".\n\n"
203  "Please define it."), member.wx_str(), package.wx_str());
204  InfoWindow::Display(_("Global Compiler Variables"), msg , 8000, 1000);
205  }
206 
207  return ret;
208 }
209 
210 
212 {
213  if (variable.find(_T('#')) == wxString::npos)
214  return;
215 
216  wxString member(variable.AfterLast(wxT('#')).BeforeFirst(wxT('.')).BeforeFirst(wxT(')')).MakeLower());
217 
218  if (!m_CfgMan->Exists(cSets + m_ActiveSet + _T('/') + member + _T("/base")) &&
219  m_Preempted.Index(member) == wxNOT_FOUND)
220  {
221  m_Preempted.Add(member);
222  }
223 }
224 
225 bool UserVariableManager::Exists(const wxString& variable) const
226 {
227  if (variable.find(_T('#')) == wxString::npos)
228  return false;
229 
230  wxString member(variable.AfterLast(wxT('#')).BeforeFirst(wxT('.')).BeforeFirst(wxT(')')).MakeLower());
231  return !m_CfgMan->Exists(cSets + m_ActiveSet + _T('/') + member + _T("/base"));
232 }
233 
235 {
236  if (m_Preempted.GetCount() == 0)
237  return;
238 
239  wxString peList;
240 
242 
243  for (unsigned int i = 0; i < m_Preempted.GetCount(); ++i)
244  {
245  d.AddVar(m_Preempted[i]);
246  peList << m_Preempted[i] << _T('\n');
247  }
248  peList = peList.BeforeLast('\n'); // remove trailing newline
249 
250  wxString msg;
251  if (m_Preempted.GetCount() == 1)
252  msg.Printf(_("In the currently active set, Code::Blocks does not know\n"
253  "the global compiler variable \"%s\".\n\n"
254  "Please define it."), peList.wx_str());
255  else
256  msg.Printf(_("In the currently active set, Code::Blocks does not know\n"
257  "the following global compiler variables:\n"
258  "%s\n\n"
259  "Please define them."), peList.wx_str());
260 
261  PlaceWindow(&d);
262  m_Preempted.Clear();
263  InfoWindow::Display(_("Global Compiler Variables"), msg , 8000 + 800*m_Preempted.GetCount(), 100);
264 
265  d.ShowModal();
266 }
267 
269 {
270  m_CfgMan = Manager::Get()->GetConfigManager(_T("gcv"));
271  Migrate();
272 }
273 
275 {
276  ConfigManager *cfgman_gcv = Manager::Get()->GetConfigManager(_T("gcv"));
277 
278  m_ActiveSet = cfgman_gcv->Read(_T("/active"));
279 
280  if (!m_ActiveSet.IsEmpty())
281  return;
282 
283  m_ActiveSet = _T("default");
284  cfgman_gcv->Exists(_T("/sets/default/foo")); // assert /sets/default
285  cfgman_gcv->Write(_T("/active"), m_ActiveSet);
286  wxString oldpath;
287  wxString newpath;
288 
289  ConfigManager *cfgman_old = Manager::Get()->GetConfigManager(_T("global_uservars"));
290  wxArrayString vars = cfgman_old->EnumerateSubPaths(_T("/"));
291 
292  for (unsigned int i = 0; i < vars.GetCount(); ++i)
293  {
294  vars[i].Prepend(_T('/'));
295  wxArrayString members = cfgman_old->EnumerateKeys(vars[i]);
296 
297  for (unsigned j = 0; j < members.GetCount(); ++j)
298  {
299  oldpath.assign(vars[i] + _T("/") + members[j]);
300  newpath.assign(_T("/sets/default") + vars[i] + _T("/") + members[j]);
301 
302  cfgman_gcv->Write(newpath, cfgman_old->Read(oldpath));
303  }
304  }
305  cfgman_old->Delete();
306 }
307 
309 {
310  GetUserVariableDialog dlg(parent, old);
311  dlg.ShowModal();
312  return dlg.GetVariable();
313 }
314 
315 BEGIN_EVENT_TABLE(GetUserVariableDialog, wxScrollingDialog)
316  EVT_BUTTON(XRCID("ID_CONFIG"), GetUserVariableDialog::OnConfig)
317  EVT_BUTTON(XRCID("wxID_OK"), GetUserVariableDialog::OnOK)
318  EVT_BUTTON(XRCID("wxID_CANCEL"), GetUserVariableDialog::OnCancel)
319  EVT_TREE_ITEM_ACTIVATED(XRCID("ID_GET_USER_VAR_TREE"), GetUserVariableDialog::OnActivated)
320 END_EVENT_TABLE()
321 
323  m_old(old)
324 {
325  wxXmlResource::Get()->LoadObject(this, parent, wxT("dlgGetGlobalUsrVar"), wxT("wxScrollingDialog"));
326  m_treectrl = XRCCTRL(*this, "ID_GET_USER_VAR_TREE", wxTreeCtrl);
327 
328  if (m_treectrl == nullptr)
329  Manager::Get()->GetLogManager()->LogError(_("Failed to load dlgGetGlobalUsrVar"));
330 
331  Load();
332 
333  // Try to open the old variable
334  if (m_old != wxEmptyString && m_old.StartsWith(wxT("$(#")))
335  {
336  // Remove "$(#"
337  wxString tmp = m_old.AfterFirst('#');
338  // Remove the last ")"
339  tmp = tmp.BeforeFirst(')');
340  // In tmp is now "var.subVar". subVar is optional
341  wxString var[2];
342  var[0] = tmp.Before('.');
343  var[1] = tmp.After('.');
345  wxTreeItemIdValue cookie;
346  wxTreeItemId child = m_treectrl->GetFirstChild(root, cookie);
347  unsigned int i = 0;
348  while (child.IsOk())
349  {
350  if (m_treectrl->GetItemText(child) == var[i])
351  {
352  m_treectrl->EnsureVisible(child);
353  m_treectrl->SelectItem(child);
354  i++;
355  if (i >= 2 || var[i] == wxEmptyString)
356  break;
357 
358  root = child;
359  child = m_treectrl->GetFirstChild(root, cookie);
360  }
361  else
362  child = m_treectrl->GetNextChild(root, cookie);
363  }
364  }
365 
366  Fit();
367  SetMinSize(GetSize());
368 }
369 
371 {
372  if (m_treectrl == nullptr)
373  return;
374 
376 
377  ConfigManager* CfgMan = Manager::Get()->GetConfigManager(wxT("gcv"));
378  const wxString &ActiveSet = Manager::Get()->GetConfigManager(wxT("gcv"))->Read(wxT("/active"));
379  wxArrayString vars = CfgMan->EnumerateSubPaths(cSets + ActiveSet + wxT("/"));
380  vars.Sort();
381 
382  wxTreeItemId root = m_treectrl->AddRoot(ActiveSet);
383 
384  for (wxArrayString::iterator var_itr = vars.begin(); var_itr != vars.end() ; ++var_itr)
385  {
386  wxTreeItemId varId = m_treectrl->AppendItem(root, (*var_itr));
387  wxArrayString subItems = CfgMan->EnumerateKeys(cSets + ActiveSet + wxT("/") + (*var_itr) + wxT("/"));
388 
389  for (wxArrayString::iterator subItr = subItems.begin(); subItr != subItems.end() ; ++subItr)
390  m_treectrl->AppendItem(varId, (*subItr));
391  }
392  m_treectrl->Expand(root);
393 }
394 
396 {
398  EndModal(wxID_OK);
399 }
400 
402 {
404  EndModal(wxID_OK);
405 }
406 
408 {
411 }
412 
414 {
416  Load();
417 }
418 
420 {
422  wxTreeItemId var = m_treectrl->GetItemParent(subVar);
423 
424  if (subVar == m_treectrl->GetRootItem() || !subVar.IsOk())
425  return wxEmptyString;
426 
427  wxString ret;
428  ret << wxT("$(#");
429  if (var == m_treectrl->GetRootItem()) // It is only a variable
430  ret << m_treectrl->GetItemText(subVar) << wxT(")");
431  else // var with subitem
432  ret << m_treectrl->GetItemText(var) << wxT(".") << m_treectrl->GetItemText(subVar) << wxT(")");
433 
434  return ret;
435 }
436 
437 BEGIN_EVENT_TABLE(UsrGlblMgrEditDialog, wxScrollingDialog)
438  EVT_BUTTON(XRCID("cloneVar"), UsrGlblMgrEditDialog::CloneVar)
439  EVT_BUTTON(XRCID("newVar"), UsrGlblMgrEditDialog::NewVar)
440  EVT_BUTTON(XRCID("deleteVar"), UsrGlblMgrEditDialog::DeleteVar)
441  EVT_BUTTON(XRCID("cloneSet"), UsrGlblMgrEditDialog::CloneSet)
442  EVT_BUTTON(XRCID("newSet"), UsrGlblMgrEditDialog::NewSet)
443  EVT_BUTTON(XRCID("deleteSet"), UsrGlblMgrEditDialog::DeleteSet)
444  EVT_BUTTON(XRCID("help"), UsrGlblMgrEditDialog::Help)
447  EVT_BUTTON(XRCID("fs1"), UsrGlblMgrEditDialog::OnFS)
448  EVT_BUTTON(XRCID("fs2"), UsrGlblMgrEditDialog::OnFS)
449  EVT_BUTTON(XRCID("fs3"), UsrGlblMgrEditDialog::OnFS)
450  EVT_BUTTON(XRCID("fs4"), UsrGlblMgrEditDialog::OnFS)
451  EVT_BUTTON(XRCID("fs5"), UsrGlblMgrEditDialog::OnFS)
452 
453  EVT_CHOICE(XRCID("selSet"), UsrGlblMgrEditDialog::SelectSet)
454  EVT_LISTBOX(XRCID("selVar"), UsrGlblMgrEditDialog::SelectVar)
455 END_EVENT_TABLE()
456 
458  m_CurrentSet(Manager::Get()->GetConfigManager(_T("gcv"))->Read(_T("/active"))),
459  m_CurrentVar(var)
460 {
461  wxXmlResource::Get()->LoadObject(this, Manager::Get()->GetAppWindow(), _T("dlgGlobalUservars"),_T("wxScrollingDialog"));
462  m_SelSet = XRCCTRL(*this, "selSet", wxChoice);
463  m_SelVar = XRCCTRL(*this, "selVar", wxListBox);
464  m_DeleteSet = XRCCTRL(*this, "deleteSet",wxButton);
465 
466  m_Base = XRCCTRL(*this, "base", wxTextCtrl);
467  m_Include = XRCCTRL(*this, "include", wxTextCtrl);
468  m_Lib = XRCCTRL(*this, "lib", wxTextCtrl);
469  m_Obj = XRCCTRL(*this, "obj", wxTextCtrl);
470  m_Bin = XRCCTRL(*this, "bin", wxTextCtrl);
471 
472  wxSplitterWindow *splitter = XRCCTRL(*this, "splitter", wxSplitterWindow);
473  if (splitter)
474  splitter->SetSashGravity(0.7);
475 
476  wxString n;
477  for (unsigned int i = 0; i < 7; ++i)
478  {
479  n.Printf(_T("n%d"), i);
480  m_Name[i] = (wxTextCtrl*) FindWindow(n);
481 
482  n.Printf(_T("v%d"), i);
483  m_Value[i] = (wxTextCtrl*) FindWindow(n);
484  }
485 
486  m_CfgMan = Manager::Get()->GetConfigManager(_T("gcv"));
487  m_CfgMan->Exists(_T("/sets/default/foo"));
488 
489  UpdateChoices();
490  Load();
491  PlaceWindow(this);
492 }
493 
495 {
496  Save();
497  EndModal(wxID_OK);
498 }
499 
500 
502 {
503  wxTextEntryDialog d(this, _("Please specify a name for the new clone:"), _("Clone Variable"));
504  PlaceWindow(&d);
505  if (d.ShowModal() == wxID_OK)
506  {
507  wxString clone = d.GetValue();
508 
509  if (clone.IsEmpty())
510  return;
511 
512  Sanitise(clone);
513 
514  wxString srcPath(_T("/sets/") + m_CurrentSet + _T('/') + m_CurrentVar + _T('/'));
515  wxString dstPath(_T("/sets/") + m_CurrentSet + _T('/') + clone + _T('/'));
516 
517  wxArrayString existing = m_CfgMan->EnumerateSubPaths(_T("/sets/" + m_CurrentSet));
518 
519  if (existing.Index(clone) != wxNOT_FOUND)
520  {
521  wxString msg;
522  msg.Printf(_("Cowardly refusing to overwrite existing variable \"%s\"."), clone.wx_str());
523  InfoWindow::Display(_("Clone Set"), msg);
524  return;
525  }
526 
527  wxArrayString members = m_CfgMan->EnumerateKeys(srcPath);
528 
529  for (unsigned j = 0; j < members.GetCount(); ++j)
530  m_CfgMan->Write(dstPath + members[j], m_CfgMan->Read(srcPath + members[j]));
531 
532  m_CurrentVar = clone;
533  UpdateChoices();
534  Load();
535  }
536 }
537 
539 {
540  wxTextEntryDialog d(this, _("Please specify a name for the new clone:"), _("Clone Set"));
541  PlaceWindow(&d);
542  if (d.ShowModal() == wxID_OK)
543  {
544  wxString clone = d.GetValue();
545  Sanitise(clone);
546 
547  if (clone.IsEmpty())
548  return;
549  wxArrayString existing = m_CfgMan->EnumerateSubPaths(_T("/sets"));
550 
551  if (existing.Index(clone) != wxNOT_FOUND)
552  {
553  wxString msg;
554  msg.Printf(_("Cowardly refusing overwrite existing set \"%s\"."), clone.wx_str());
555  InfoWindow::Display(_("Clone Set"), msg);
556  return;
557  }
558 
559  wxString srcPath(cSets + m_CurrentSet + _T("/"));
560  wxString dstPath(cSets + clone + _T("/"));
561  wxString oldpath, newpath;
562 
563  wxArrayString vars = m_CfgMan->EnumerateSubPaths(srcPath);
564 
565  for (unsigned int i = 0; i < vars.GetCount(); ++i)
566  {
567  wxArrayString members = m_CfgMan->EnumerateKeys(srcPath + vars[i]);
568 
569  for (unsigned j = 0; j < members.GetCount(); ++j)
570  {
571  wxString item = vars[i] + _T("/") + members[j];
572  m_CfgMan->Write(dstPath + item, m_CfgMan->Read(srcPath + item));
573  }
574  }
575  m_CurrentSet = clone;
576  UpdateChoices();
577  Load();
578  }
579 }
580 
582 {
583  wxString msg;
584  msg.Printf(_("Delete the global compiler variable \"%s\" from this set?"), m_CurrentVar.wx_str());
585  AnnoyingDialog d(_("Delete Global Variable"), msg, wxART_QUESTION);
586  PlaceWindow(&d);
587  if (d.ShowModal() == AnnoyingDialog::rtYES)
588  {
589  m_CfgMan->DeleteSubPath(cSets + m_CurrentSet + _T('/') + m_CurrentVar + _T('/'));
590  m_CurrentVar = wxEmptyString;
591  UpdateChoices();
592  Load();
593  }
594 }
595 
597 {
598  wxString msg;
599  msg.Printf(_("Do you really want to delete the entire\n"
600  "global compiler variable set \"%s\"?\n\n"
601  "This cannot be undone."), m_CurrentSet.wx_str());
602  AnnoyingDialog d(_("Delete Global Variable Set"), msg, wxART_QUESTION);
603  PlaceWindow(&d);
604  if (d.ShowModal() == AnnoyingDialog::rtYES)
605  {
606  m_CfgMan->DeleteSubPath(cSets + m_CurrentSet + _T('/'));
607  m_CurrentSet = wxEmptyString;
608  m_CurrentVar = wxEmptyString;
609  UpdateChoices();
610  Load();
611  }
612 }
613 
615 {
616  if (name.IsEmpty())
617  return;
618  m_CurrentVar = name;
619  m_CfgMan->Exists(_T("/sets/") + m_CurrentSet + _T('/') + name + _T('/'));
620 
621  m_CurrentVar = name;
622  UpdateChoices();
623  Load();
624 }
625 
627 {
628  s.Trim().Trim(true);
629 
630  if (s.IsEmpty())
631  {
632  s = _T("[?empty?]");
633  return;
634  }
635 
636  for (unsigned int i = 0; i < s.length(); ++i)
637 #if wxCHECK_VERSION(3, 0, 0)
638  s[i] = wxIsalnum(s.GetChar(i)) ? s.GetChar(i) : wxUniChar('_');
639 #else
640  s[i] = wxIsalnum(s.GetChar(i)) ? s.GetChar(i) : _T('_');
641 #endif
642 
643  if (s.GetChar(0) == _T('_'))
644  s.Prepend(_T("set"));
645 
646  if (s.GetChar(0) >= _T('0') && s.GetChar(0) <= _T('9'))
647  s.Prepend(_T("set_"));
648 }
649 
651 {
652  wxTextEntryDialog d(this, _("Please specify a name for the new variable:"), _("New Variable"));
653  PlaceWindow(&d);
654  if (d.ShowModal() == wxID_OK)
655  {
656  wxString name = d.GetValue();
657  Save();
658  Sanitise(name);
659  AddVar(name);
660  }
661 }
662 
664 {
665  wxTextEntryDialog d(this, _("Please specify a name for the new set:"), _("New Set"));
666  PlaceWindow(&d);
667  if (d.ShowModal() == wxID_OK)
668  {
669  wxString name = d.GetValue();
670  Sanitise(name);
671 
672  if (name.IsEmpty())
673  return;
674  m_CurrentSet = name;
675  m_CfgMan->Exists(_T("/sets/") + name + _T('/'));
676 
677  m_CurrentSet = name;
678  UpdateChoices();
679  Load();
680  }
681 }
682 
684 {
685  Save();
686  m_CurrentVar = m_SelVar->GetStringSelection();
687  Load();
688 }
689 
691 {
692  Save();
693  m_CurrentSet = m_SelSet->GetStringSelection();
694  m_CfgMan->Write(_T("/active"), m_CurrentSet);
695  UpdateChoices();
696  Load();
697 }
698 
699 
701 {
702  m_DeleteSet->Enable(!m_CurrentSet.IsSameAs(_T("default")));
703 
704  wxString path(cSets + m_CurrentSet + _T('/') + m_CurrentVar + _T('/'));
705 
706  wxArrayString knownMembers = m_CfgMan->EnumerateKeys(path);
707 
708  for (unsigned int i = 0; i < builtinMembers.GetCount(); ++i)
709  {
710  ((wxTextCtrl*) FindWindow(builtinMembers[i]))->SetValue(m_CfgMan->Read(path + builtinMembers[i]));
711 
712  int index = knownMembers.Index(builtinMembers[i], false);
713  if (index != wxNOT_FOUND)
714  knownMembers.RemoveAt(index);
715  }
716 
717  for (unsigned int i = 0; i < 7; ++i)
718  {
719  m_Name[i]->SetValue(wxEmptyString);
720  m_Value[i]->SetValue(wxEmptyString);
721  }
722 
723  for (unsigned int i = 0; i < knownMembers.GetCount(); ++i)
724  {
725  m_Name[i]->SetValue(knownMembers[i].Lower());
726  m_Value[i]->SetValue(m_CfgMan->Read(path + knownMembers[i]));
727  }
728 }
729 
731 {
732  wxString path(cSets + m_CurrentSet + _T('/') + m_CurrentVar + _T('/'));
733  wxString mbr(_T('#') + m_CurrentVar + _T('.'));
734 
735  m_CfgMan->DeleteSubPath(path);
736 
737  wxString s, t;
738  for (unsigned int i = 0; i < builtinMembers.GetCount(); ++i)
739  {
740  t = ((wxTextCtrl*) FindWindow(builtinMembers[i]))->GetValue();
741 
742  if ( i == 0
743  && ( ( !m_CurrentVar.IsEmpty()
744  && t.IsEmpty() )
745  || t.Contains(_T('#') + m_CurrentVar) ) )
746  {
747  if (cbMessageBox(_("Are you sure you want to save an invalid global variable?"), _("Global variables"),
749  {
750  t.assign(_T("(invalid)"));
751  }
752  }
753 
754  if (t.Contains(mbr + builtinMembers[i]))
755  t.assign(_T("(invalid)"));
756 
757  if (!t.IsEmpty())
758  m_CfgMan->Write(path + builtinMembers[i], t);
759  }
760 
761  for (unsigned int i = 0; i < 7; ++i)
762  {
763  s = m_Name[i]->GetValue();
764  t = m_Value[i]->GetValue();
765 
766  if (t.Contains(mbr + s))
767  t.assign(_T("(invalid)"));
768 
769  if (!s.IsEmpty() && !t.IsEmpty())
770  m_CfgMan->Write(path + s, t);
771  }
772 }
773 
775 {
776  if (m_CurrentSet.IsEmpty())
777  m_CurrentSet = _T("default");
778 
779  wxArrayString sets = m_CfgMan->EnumerateSubPaths(cSets);
780  wxArrayString vars = m_CfgMan->EnumerateSubPaths(cSets + m_CurrentSet + _T("/"));
781  sets.Sort();
782  vars.Sort();
783 
784  m_SelSet->Clear();
785  m_SelSet->Append(sets);
786  m_SelVar->Clear();
787  m_SelVar->Append(vars);
788 
789  if (m_CurrentVar.IsEmpty() && m_SelVar->GetCount() > 0)
790  m_CurrentVar = m_SelVar->GetString(0);
791 
792  m_SelSet->SetStringSelection(m_CurrentSet);
793  m_SelVar->SetStringSelection(m_CurrentVar);
794 }
795 
796 
798 {
799  wxTextCtrl* c = nullptr;
800  int id = event.GetId();
801 
802  if (id == XRCID("fs1"))
803  c = m_Base;
804  else if (id == XRCID("fs2"))
805  c = m_Include;
806  else if (id == XRCID("fs3"))
807  c = m_Lib;
808  else if (id == XRCID("fs4"))
809  c = m_Obj;
810  else if (id == XRCID("fs5"))
811  c = m_Bin;
812  else
813  cbThrow(_T("Encountered invalid button ID"));
814 
815  wxString path = ChooseDirectory(this, _("Choose a location"), c->GetValue());
816  if (!path.IsEmpty())
817  c->SetValue(path);
818 }
819 
821 {
822  wxLaunchDefaultBrowser(_T("http://wiki.codeblocks.org/index.php?title=Global_compiler_variables"));
823 }
virtual wxTreeItemId GetNextChild(const wxTreeItemId &item, wxTreeItemIdValue &cookie) const
const wxChar * bim[]
void Preempt(const wxString &variable)
wxString AfterLast(wxUniChar ch) const
static void Display(const wxString &title, const wxString &message, unsigned int delay=5000, unsigned int hysteresis=1)
Definition: infowindow.cpp:294
void EndModal(int retCode)
Definition: sc_dialog.cpp:112
bool Exists(const wxString &variable) const
const wxString cLib(_T("lib"))
const wxString cCflags(_T("cflags"))
#define wxICON_QUESTION
const wxString cLflags(_T("lflags"))
const wxChar cSlash(_T('/'))
virtual wxTreeItemId GetItemParent(const wxTreeItemId &item) const
const wxArrayString builtinMembers((size_t) 7, bim)
ConfigManager * GetConfigManager(const wxString &name_space) const
Definition: manager.cpp:474
UserVariableManager * GetUserVariableManager() const
Definition: manager.cpp:464
bool IsOk() const
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
void SelectSet(wxCommandEvent &event)
size_t length() const
virtual void DeleteAllItems()
void CloseHandler(cb_unused wxCloseEvent &event)
const wxString cSets(_T("/sets/"))
void OnOK(cb_unused wxCommandEvent &event)
DLLIMPORT wxString ChooseDirectory(wxWindow *parent, const wxString &message=_("Select directory"), const wxString &initialPath=_T(""), const wxString &basePath=_T(""), bool askToMakeRelative=false, bool showCreateDirButton=false)
Definition: globals.cpp:639
void OnActivated(wxTreeEvent &event)
int Index(const wxString &sz, bool bCase=true, bool bFromEnd=false) const
void SelectVar(wxCommandEvent &event)
const wxString cBase(_T("base"))
virtual wxTreeItemId GetSelection() const
virtual void EnsureVisible(const wxTreeItemId &item)
wxString Replace(const wxString &variable)
#define _T(string)
const wxString cInclude(_T("include"))
void SetValue(WatchesProperty *prop)
Definition: watchesdlg.cpp:515
void DeleteSet(wxCommandEvent &event)
wxString BeforeLast(wxUniChar ch, wxString *rest=NULL) const
#define wxYES_NO
void OnOK(cb_unused wxCommandEvent &event)
bool IsLoading()
Check if the project manager is loading a project/workspace.
void SetSashGravity(double gravity)
virtual wxString GetItemText(const wxTreeItemId &item) const
void NewSet(wxCommandEvent &event)
wxString AfterFirst(wxUniChar ch) const
#define wxT(string)
#define wxNOT_FOUND
size_t find(const wxString &str, size_t nStart=0) const
const wxString cDir(_T("dir"))
void LogError(const wxString &msg, int i=app_log)
Definition: logmanager.h:142
void DeleteVar(wxCommandEvent &event)
wxUSE_UNICODE_dependent wxChar
void CloneSet(wxCommandEvent &event)
wxString BeforeFirst(wxUniChar ch, wxString *rest=NULL) const
ProjectManager * GetProjectManager() const
Functions returning pointers to the respective sub-manager instances.
Definition: manager.cpp:429
virtual wxTreeItemId GetFirstChild(const wxTreeItemId &item, wxTreeItemIdValue &cookie) const
bool Contains(const wxString &str) const
void Write(const wxString &name, const wxString &value, bool ignoreEmpty=false)
void Sanitise(wxString &s)
wxArtID wxART_QUESTION
void NewVar(wxCommandEvent &event)
void OnCancel(cb_unused wxCommandEvent &event)
wxArrayString EnumerateSubPaths(const wxString &path)
bool Exists(const wxString &name)
void OnFS(wxCommandEvent &event)
wxString GetVariable(wxWindow *parent, const wxString &old)
virtual void SelectItem(const wxTreeItemId &item, bool select=true)
#define wxCHECK_VERSION(major, minor, release)
bool IsSameAs(const wxString &s, bool caseSensitive=true) const
LogManager * GetLogManager() const
Definition: manager.cpp:439
wxString Read(const wxString &key, const wxString &defaultVal=wxEmptyString)
const wxStringCharType * wx_str() const
virtual int ShowModal()
wxString wxEmptyString
wxString & assign(const wxString &str, size_t pos, size_t n)
Definition: manager.h:183
const wxString & _(const wxString &string)
wxString & Trim(bool fromRight=true)
const wxString cObj(_T("obj"))
#define cbThrow(message)
Definition: cbexception.h:42
bool wxIsalnum(const wxUniChar &c)
void SetMinSize(wxPropertyGrid *grid)
virtual void Expand(const wxTreeItemId &item)
void Help(wxCommandEvent &event)
bool IsEmpty() const
DLLIMPORT void PlaceWindow(wxTopLevelWindow *w, cbPlaceDialogMode mode=pdlBest, bool enforce=false)
Definition: globals.cpp:1177
static const size_t npos
ConfigManager * m_CfgMan
int ShowModal() override
wxString & Prepend(const wxString &str)
GetUserVariableDialog(wxWindow *parent, const wxString &old)
const wxString cBin(_T("bin"))
virtual wxTreeItemId AddRoot(const wxString &text, int image=-1, int selImage=-1, wxTreeItemData *data=NULL)
bool StartsWith(const wxString &prefix, wxString *rest=NULL) const
const wxString cSlashBase(_T("/base"))
void Sort(bool reverseOrder=false)
virtual wxTreeItemId GetRootItem() const
void AddVar(const wxString &var)
size_t GetCount() const
static wxXmlResource * Get()
wxUniChar GetChar(size_t n) const
void OnConfig(cb_unused wxCommandEvent &event)
void OnCancel(cb_unused wxCommandEvent &event)
bool wxLaunchDefaultBrowser(const wxString &url, int flags=0)
void RemoveAt(size_t nIndex, size_t count=1)
int Printf(const wxString &pszFormat,...)
wxArrayString EnumerateKeys(const wxString &path)
wxObject * LoadObject(wxWindow *parent, const wxString &name, const wxString &classname)
Dialog that contains a "Don&#39;t annoy me" checkbox.
DLLIMPORT int cbMessageBox(const wxString &message, const wxString &caption=wxEmptyString, int style=wxOK, wxWindow *parent=NULL, int x=-1, int y=-1)
wxMessageBox wrapper.
Definition: globals.cpp:1395
wxTreeItemId AppendItem(const wxTreeItemId &parent, const wxString &text, int image=-1, int selImage=-1, wxTreeItemData *data=NULL)
wxString & MakeLower()
void CloneVar(wxCommandEvent &event)