KiCad PCB EDA Suite
dialog_env_var_config.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KICAD, a free EDA CAD application.
3  *
4  * Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com>
5  * Copyright (C) 2015-2017 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
29 #include <dialog_env_var_config.h>
30 
31 #include <confirm.h>
32 
33 #include <validators.h>
34 #include <html_messagebox.h>
35 
36 #include <wx/regex.h>
37 
41 {
42 public:
43  DIALOG_ENV_VAR_SINGLE( wxWindow* parent, const wxString& aEnvVarName,
44  const wxString& aEnvVarPath );
45 
47  wxString GetEnvVarName() const
48  {
49  return m_envVarName->GetValue();
50  }
51 
53  wxString GetEnvVarValue() const
54  {
55  return m_envVarPath->GetValue();
56  }
57 
61  {
62  m_envVarName->Enable( false );
63  }
64 
65 protected:
66  void OnSelectPath( wxCommandEvent& event ) override;
67  void onHelpClick( wxCommandEvent& event ) override;
68  bool TransferDataFromWindow() override;
69 };
70 
71 
72 DIALOG_ENV_VAR_CONFIG::DIALOG_ENV_VAR_CONFIG( wxWindow* aParent, const ENV_VAR_MAP& aEnvVarMap ) :
74 {
75  // Copy environment variables across
76  m_envVarMap = aEnvVarMap;
77 }
78 
79 
81 {
82  wxLogDebug( wxT( "In DIALOG_ENV_VAR_CONFIG::TransferDataToWindow()." ) );
83 
84  if( !wxDialog::TransferDataToWindow() )
85  return false;
86 
87  //TODO
88  /*
89  // Grab the project path var (not editable)
90  wxString prjPath;
91 
92  wxGetEnv( PROJECT_VAR_NAME, &prjPath );
93 
94  m_kiprjmod->SetLabel( prjPath );
95  */
96 
97  //TODO - Call SetAlternateRowColour first to prevent assertion error
98  //m_pathList->EnableAlternateRowColours( true );
99 
101 
102  // Select the first item in the list
103  SelectListIndex( 0 );
104 
105  GetSizer()->Layout();
106  GetSizer()->Fit( this );
107  GetSizer()->SetSizeHints( this );
108 
109  return true;
110 }
111 
112 
114 {
115  if( !wxDialog::TransferDataFromWindow() )
116  {
117  return false;
118  }
119 
121 
122  return true;
123 }
124 
125 
127 {
128  m_pathList->Freeze();
129 
130  m_pathList->ClearAll();
131 
132  m_pathList->AppendColumn( _( "Name:" ) );
133  m_pathList->AppendColumn( _( "Path:" ) );
134 
135  int row = 0;
136 
137  for( auto it = m_envVarMap.begin(); it != m_envVarMap.end(); ++it )
138  {
139  long index = m_pathList->InsertItem( row, it->first );
140 
141  m_pathList->SetItem( index, 1, it->second.GetValue() );
142 
143  if( it->second.GetDefinedExternally() )
144  {
145  wxColour color = wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT );
146 
147  m_pathList->SetItemBackgroundColour( index, color );
148  }
149 
150  row++;
151  }
152 
153  m_pathList->SetColumnWidth( 0, wxLIST_AUTOSIZE );
154  m_pathList->SetColumnWidth( 1, wxLIST_AUTOSIZE );
155 
156  m_pathList->Update();
157 
158  m_pathList->Thaw();
159 }
160 
161 
162 bool DIALOG_ENV_VAR_CONFIG::GetPathAtIndex( unsigned int aIndex, wxString& aEnvVar,
163  wxString& aEnvPath )
164 {
165  if( aIndex > m_envVarMap.size() )
166  {
167  return false;
168  }
169 
170  unsigned int idx = 0;
171 
172  for( auto it = m_envVarMap.begin(); it != m_envVarMap.end(); ++it )
173  {
174  if( idx == aIndex )
175  {
176  aEnvVar = it->first;
177  aEnvPath = it->second.GetValue();
178 
179  return true;
180  }
181 
182  idx++;
183  }
184 
185  return false;
186 }
187 
188 
189 void DIALOG_ENV_VAR_CONFIG::OnAddButton( wxCommandEvent& event )
190 {
191  DIALOG_ENV_VAR_SINGLE dlg( this, wxEmptyString, wxEmptyString );
192 
193  if( dlg.ShowModal() == wxID_OK )
194  {
195  wxString newName = dlg.GetEnvVarName();
196  wxString newPath = dlg.GetEnvVarValue();
197 
198  // Check that the name does not already exist
199  if( m_envVarMap.count( newName ) > 0 )
200  {
201  //TODO - Improve this message, use DisplayErrorMessage instead
202  DisplayError( this, _( "Path already exists." ) );
203  }
204  else
205  {
206  m_envVarMap[newName] = ENV_VAR_ITEM( newPath );
207 
208  // Update path list
210  }
211  }
212 }
213 
214 
215 void DIALOG_ENV_VAR_CONFIG::OnEditButton( wxCommandEvent& event )
216 {
218 }
219 
220 
222 {
223  wxString envName;
224  wxString envPath;
225 
226  if( GetPathAtIndex( m_pathIndex, envName, envPath ) )
227  {
228  auto dlg = new DIALOG_ENV_VAR_SINGLE( nullptr, envName, envPath );
229 
230  if( IsEnvVarImmutable( envName ) )
231  {
232  dlg->SetEnvVarProtected();
233  }
234 
235  if( dlg->ShowModal() == wxID_OK )
236  {
237  wxString newName = dlg->GetEnvVarName();
238  wxString newPath = dlg->GetEnvVarValue();
239 
240  // If the path name has not been changed
241  if( envName.Cmp( newName ) == 0 )
242  {
243  m_envVarMap[envName].SetValue( newPath );
244 
245  if( m_envVarMap[envName].GetDefinedExternally() )
246  {
247  m_extDefsChanged = true;
248  }
249  }
250  // Path-name needs to be updated
251  else
252  {
253  if( IsEnvVarImmutable( envName ) )
254  {
255  DisplayErrorMessage( this,
256  wxString::Format( _( "Environment variable \"%s\" cannot "
257  "be renamed." ),
258  envName.ToStdString() ),
259  _( "The selected environment variable name "
260  "is required for KiCad functionality and "
261  "can not be renamed." ) );
262 
263  return;
264  }
265 
266  auto envVar = m_envVarMap[envName];
267 
268  m_envVarMap.erase( envName );
269 
270  envVar.SetValue( newPath );
271  envVar.SetDefinedExternally( false );
272  m_envVarMap[newName] = envVar;
273  }
274 
275  // Update the path list
277  }
278 
279  dlg->Destroy();
280  }
281 }
282 
283 void DIALOG_ENV_VAR_CONFIG::OnHelpButton( wxCommandEvent& event )
284 {
285  wxString msg = _( "Enter the name and value for each environment variable. Grey entries "
286  "are names that have been defined externally at the system or user "
287  "level. Environment variables defined at the system or user level "
288  "take precedence over the ones defined in this table. This means the "
289  "values in this table are ignored." );
290  msg << wxT( "<br><br><b>" );
291  msg << _( "To ensure environment variable names are valid on all platforms, the name field "
292  "will only accept upper case letters, digits, and the underscore characters." );
293  msg << wxT( "</b><br><br>" );
294  msg << _( "<b>KICAD_SYMBOL_DIR</b> is the base path of the locally installed symbol libraries." );
295  msg << wxT( "<br><br>" );
296  msg << _( "<b>KIGITHUB</b> is used by KiCad to define the URL of the repository "
297  "of the official KiCad footprint libraries." );
298  msg << wxT( "<br><br>" );
299  msg << _( "<b>KISYS3DMOD</b> is the base path of system footprint 3D "
300  "shapes (.3Dshapes folders)." );
301  msg << wxT( "<br><br>" );
302  msg << _( "<b>KISYSMOD</b> is the base path of locally installed system "
303  "footprint libraries (.pretty folders)." );
304  msg << wxT( "<br><br>" );
305  msg << _( "<b>KIPRJMOD</b> is internally defined by KiCad (cannot be edited) and is set "
306  "to the absolute path of the currently loaded project file. This environment "
307  "variable can be used to define files and paths relative to the currently loaded "
308  "project. For instance, ${KIPRJMOD}/libs/footprints.pretty can be defined as a "
309  "folder containing a project specific footprint library named footprints.pretty." );
310  msg << wxT( "<br><br>" );
311  msg << _( "<b>KICAD_PTEMPLATES</b> is optional and can be defined if you want to "
312  "create your own project templates folder." );
313 
314  HTML_MESSAGE_BOX dlg( GetParent(), _( "Environment Variable Help" ) );
315  dlg.SetDialogSizeInDU( 400, 350 );
316 
317  dlg.AddHTML_Text( msg );
318  dlg.ShowModal();
319 }
320 
321 
322 bool DIALOG_ENV_VAR_CONFIG::IsEnvVarImmutable( const wxString aEnvVar )
323 {
324  /*
325  * TODO - Instead of defining these values here,
326  * extract them from elsewhere in the program
327  * (where they are originally defined)
328  */
329 
330  static const wxString immutable[] = {
331  "KIGITHUB",
332  "KISYS3DMOD",
333  "KISYSMOD",
334  "KIPRJMOD",
335  "KICAD_PTEMPLATES",
336  "KICAD_SYMBOL_DIR"
337  };
338 
339  for( unsigned int ii=0; ii<6; ii++ )
340  {
341  if( aEnvVar.Cmp( immutable[ii] ) == 0 )
342  {
343  return true;
344  }
345  }
346 
347  return false;
348 }
349 
350 
351 void DIALOG_ENV_VAR_CONFIG::OnRemoveButton( wxCommandEvent& event )
352 {
353  wxString envName;
354  wxString envPath;
355 
356  if( GetPathAtIndex( m_pathIndex, envName, envPath ) )
357  {
358  if( IsEnvVarImmutable( envName ) )
359  {
360  return;
361  }
362 
363  m_envVarMap.erase( envName );
364 
366  }
367 }
368 
369 
370 void DIALOG_ENV_VAR_CONFIG::SelectListIndex( unsigned int aIndex )
371 {
372  if( aIndex >= m_envVarMap.size() )
373  {
374  aIndex = 0;
375  }
376 
377  m_pathIndex = aIndex;
378 
379  wxString envName;
380  wxString envPath;
381 
382  if( GetPathAtIndex( m_pathIndex, envName, envPath ) )
383  {
384  // Disable the 'delete' button if the path cannot be deleted
385  m_deletePathButton->Enable( !IsEnvVarImmutable( envName ) );
386  }
387 }
388 
389 void DIALOG_ENV_VAR_CONFIG::OnPathSelected( wxListEvent& event )
390 {
391  SelectListIndex( event.GetIndex() );
392 }
393 
394 
395 void DIALOG_ENV_VAR_CONFIG::OnPathActivated( wxListEvent& event )
396 {
397  SelectListIndex( event.GetIndex() );
398 
400 }
401 
402 
404 // DIALOG_ENV_VAR_SINGLE //
406 
408  const wxString& aEnvVarName,
409  const wxString& aEnvVarPath ) :
411 {
412  m_envVarName->SetValue( aEnvVarName );
413  m_envVarPath->SetValue( aEnvVarPath );
415 }
416 
417 
418 void DIALOG_ENV_VAR_SINGLE::OnSelectPath( wxCommandEvent& event )
419 {
420  wxString title = _( "Select Path for Environment Variable" );
421  wxString path; // Currently the first opened path is not initialized
422 
423  wxDirDialog dlg( nullptr, title, path, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST );
424 
425  if( dlg.ShowModal() == wxID_OK )
426  m_envVarPath->SetValue( dlg.GetPath() );
427 }
428 
429 
431 {
432  // The user pressed the OK button, test data validity
433  wxString name = m_envVarName->GetValue();
434  wxString path = m_envVarPath->GetValue();
435 
436  // Neither name nor path can be empty
437  if( name.IsEmpty() )
438  {
439  DisplayError( this, _( "Environment variable name cannot be empty." ) );
440  // Veto:
441  return false;
442  }
443 
444  if( path.IsEmpty() )
445  {
446  DisplayError( this, _( "Environment variable value cannot be empty." ) );
447  // Veto:
448  return false;
449  }
450 
451  // Name cannot start with a number
452  if( name.Left( 1 ).IsNumber() )
453  {
454  DisplayError( this, _( "Environment variable names cannot start with a digit (0-9)." ) );
455  // Veto:
456  return false;
457  }
458 
459  // No errors detected
460  return true;
461 }
462 
463 
464 void DIALOG_ENV_VAR_SINGLE::onHelpClick( wxCommandEvent& event )
465 {
466  wxString msg = _( "An environment variable is used for string substitutions.<br>"
467  "Environment variables are primarily used for paths to make KiCad portable "
468  "between platforms.<br><br>"
469  "If an environment variable is defined as <b>MYLIBPATH</b> with a "
470  "value <b>e:/kicad_libs</b>, then a library name "
471  "<b>${MYLIBPATH}/mylib.lib</b> gets expanded to "
472  "<b>e:/kicad_libs/mylib.lib</b>"
473  "<br><br>"
474  "<b>Note:</b><br>"
475  "Only characters <b>ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_</b> are "
476  "allowed in environment variable names and the environment variable name "
477  "cannot start with a digit (0-9)."
478  );
479 
480  HTML_MESSAGE_BOX dlg( GetParent(), _( "Environment Variable Help" ) );
481  dlg.SetDialogSizeInDU( 400, 350 );
482 
483  dlg.AddHTML_Text( msg );
484  dlg.ShowModal();
485 }
void EditSelectedEntry()
Edit the currently selected ENV_VAR entry.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Function DisplayErrorMessage displays an error message with aMessage.
Definition: confirm.cpp:88
bool GetPathAtIndex(unsigned int aIndex, wxString &aEnvVar, wxString &aEnvPath)
Extract the NAME and PATH data from the ENV_VAR at the provided index.
wxString GetEnvVarName() const
bool TransferDataFromWindow() override
This file is part of the common library.
virtual void OnEditButton(wxCommandEvent &event) override
Class ENV_VAR_ITEM.
Definition: pgm_base.h:58
Class DIALOG_ENV_VAR_CONFIG_BASE.
virtual void OnRemoveButton(wxCommandEvent &event) override
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:65
void OnSelectPath(wxCommandEvent &event) override
wxString GetEnvVarValue() const
Class ENVIRONMENT_VARIABLE_CHAR_VALIDATOR.
Definition: validators.h:75
void SetEnvVarProtected()
disable the environment variable name (must be called for predefined environment variable names...
void PopulatePathList()
Update the displayed list of ENV_VAR paths.
virtual void OnPathActivated(wxListEvent &event) override
void SelectListIndex(unsigned int aIndex)
Select the ENV_VAR at the provided index.
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
Definition: pgm_base.h:87
bool IsEnvVarImmutable(const wxString aEnvVar)
Determine if a particular ENV_VAR is protected.
Subclass of DIALOG_DISPLAY_HTML_TEXT_BASE, which is generated by wxFormBuilder.
virtual void OnHelpButton(wxCommandEvent &event) override
Class DIALOG_ENV_VAR_SINGLE_BASE.
Class HTML_MESSAGE_BOX.
A helper dialog to edit a env var name and/or its value (often a path)
VTBL_ENTRY void SetLocalEnvVariables(const ENV_VAR_MAP &aEnvVarMap)
Function SetLocalEnvVariables.
Definition: pgm_base.cpp:884
void SetDialogSizeInDU(int aWidth, int aHeight)
set the dialog size, using a "logical value.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
virtual void OnAddButton(wxCommandEvent &event) override
DIALOG_ENV_VAR_SINGLE(wxWindow *parent, const wxString &aEnvVarName, const wxString &aEnvVarPath)
void AddHTML_Text(const wxString &message)
Function AddHTML_Text adds html text (without any change) to message list.
DIALOG_ENV_VAR_CONFIG(wxWindow *parent, const ENV_VAR_MAP &aEnvVarMap)
virtual void OnPathSelected(wxListEvent &event) override
bool TransferDataFromWindow() override
const char * name
bool TransferDataToWindow() override
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:74
void onHelpClick(wxCommandEvent &event) override
Custom text control validator definitions.