KiCad PCB EDA Suite
prjconfig.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) 2004-2015 Jean-Pierre Charras
5  * Copyright (C) 2004-2016 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 
31 #include <wx/dir.h>
32 #include <wx/filename.h>
33 #include <wx/stdpaths.h>
34 
35 #include <build_version.h>
36 #include <config_params.h>
37 #include <confirm.h>
38 #include <kiway.h>
39 #include <project.h>
41 
43 
44 #include "kicad.h"
45 #include "pgm_kicad.h"
46 #include "tree_project_frame.h"
47 
48 
49 #define SEP() wxFileName::GetPathSeparator()
50 
51 // Not really useful, provided to save/restore params in project config file,
52 // (Add them in s_KicadManagerParams if any)
53 // Used also to create new .pro files from the kicad.pro template file
54 // for new projects
55 #define GeneralGroupName wxT( "/general" )
56 
58 
59 void KICAD_MANAGER_FRAME::CreateNewProject( const wxString& aPrjFullFileName,
60  bool aTemplateSelector = false )
61 {
62  wxFileName newProjectName = aPrjFullFileName;
63  wxChar sep[2] = { SEP(), 0 }; // nul terminated separator wxChar string.
64 
65  ClearMsg();
66 
67  // If we are creating a project from a template, make sure the template directory is sane
68  if( aTemplateSelector )
69  {
71 
72  wxFileName templatePath;
73  wxString envStr;
74 
75 #ifndef __WXMAC__
76  wxGetEnv( wxT( "KICAD" ), &envStr );
77 
78  // Add a new tab for system templates
79  if( !envStr.empty() )
80  {
81  // user may or may not have including terminating separator.
82  if( !envStr.EndsWith( sep ) )
83  envStr += sep;
84 
85  templatePath = envStr + wxT( "template" ) + sep;
86  }
87  else
88  {
89  // The standard path should be in the share directory for kicad. As
90  // it is normal on Windows to only have the share directory and not
91  // the kicad sub-directory we fall back to that if the directory
92  // doesn't exist
93  templatePath = wxPathOnly( wxStandardPaths::Get().GetExecutablePath() ) +
94  sep + wxT( ".." ) + sep + wxT( "share" ) + sep + wxT( "kicad" ) +
95  sep + wxT( "template" ) + sep;
96 
97  if( !wxDirExists( templatePath.GetFullPath() ) )
98  {
99  templatePath = wxPathOnly( wxStandardPaths::Get().GetExecutablePath() ) +
100  sep + wxT( ".." ) + sep + wxT( "share" ) + sep + wxT( "template" ) + sep;
101  }
102  }
103 #else
104  // Use what is provided in the bundle data dir
105  templatePath = GetOSXKicadDataDir() + sep + wxT( "template" );
106 #endif
107 
108  ps->AddTemplatesPage( _( "System Templates" ), templatePath );
109 
110  // Add a new tab for user templates
111  wxFileName userPath = wxStandardPaths::Get().GetDocumentsDir() +
112  sep + wxT( "kicad" ) + sep + wxT( "template" ) + sep;
113 
114  ps->AddTemplatesPage( _( "User Templates" ), userPath );
115 
116  // Check to see if a custom template location is available and setup a
117  // new selection tab if there is.
118  envStr.clear();
119  wxGetEnv( wxT( "KICAD_PTEMPLATES" ), &envStr );
120 
121  if( !envStr.empty() )
122  {
123  if( !envStr.EndsWith( sep ) )
124  envStr += sep;
125 
126  wxFileName envPath = envStr;
127 
128  ps->AddTemplatesPage( _( "Portable Templates" ), envPath );
129  }
130 
131  // Show the project template selector dialog
132  int result = ps->ShowModal();
133 
134  if( ( result != wxID_OK ) || ( ps->GetSelectedTemplate() == NULL ) )
135  {
136  if( ps->GetSelectedTemplate() == NULL )
137  {
138  wxMessageBox( _( "No project template was selected. Cannot generate new "
139  "project." ),
140  _( "Error" ),
141  wxOK | wxICON_ERROR,
142  this );
143  }
144  }
145  else
146  {
147  // The selected template widget contains the template we're attempting to use to
148  // create a project
149  if( !ps->GetSelectedTemplate()->CreateProject( newProjectName ) )
150  {
151  wxMessageBox( _( "Problem whilst creating new project from template!" ),
152  _( "Template Error" ),
153  wxOK | wxICON_ERROR,
154  this );
155  }
156  }
157  }
158 
159  // Init project filename
160  SetProjectFileName( newProjectName.GetFullPath() );
161 
162  // Write settings to project file
163  // was: wxGetApp().WriteProjectConfig( aPrjFullFileName, GeneralGroupName, s_KicadManagerParams );
164  Prj().ConfigSave( PgmTop().SysSearch(), GeneralGroupName, s_KicadManagerParams );
165 
166  // Ensure a "stub" for a schematic root sheet and a board exist.
167  // It will avoid messages from the schematic editor or the board editor to create a new file
168  // And forces the user to create main files under the right name for the project manager
169  wxFileName fn( newProjectName.GetFullPath() );
170  fn.SetExt( SchematicFileExtension );
171 
172  // If a <project>.sch file does not exist, create a "stub" file
173  // ( minimal schematic file )
174  if( !fn.FileExists() )
175  {
176  wxFile file( fn.GetFullPath(), wxFile::write );
177 
178  if( file.IsOpened() )
179  file.Write( wxT( "EESchema Schematic File Version 2\n"
180  "EELAYER 25 0\nEELAYER END\n$EndSCHEMATC\n" ) );
181 
182  // wxFile dtor will close the file
183  }
184 
185  // If a <project>.kicad_pcb or <project>.brd file does not exist,
186  // create a .kicad_pcb "stub" file
187  fn.SetExt( KiCadPcbFileExtension );
188  wxFileName leg_fn( fn );
189  leg_fn.SetExt( LegacyPcbFileExtension );
190 
191  if( !fn.FileExists() && !leg_fn.FileExists() )
192  {
193  wxFile file( fn.GetFullPath(), wxFile::write );
194 
195  if( file.IsOpened() )
196  file.Write( wxT( "(kicad_pcb (version 4) (host kicad \"dummy file\") )\n" ) );
197 
198  // wxFile dtor will close the file
199  }
200 
201  // Enable the toolbar and menubar buttons and clear the help text.
202  m_active_project = true;
203  m_MessagesBox->Clear();
204 }
205 
206 
207 void KICAD_MANAGER_FRAME::OnLoadProject( wxCommandEvent& event )
208 {
209  // Any open KIFACE's must be closed if they are not part of the new project.
210  // (We never want a KIWAY_PLAYER open on a KIWAY that isn't in the same project.)
211  // User is prompted here to close those KIWAY_PLAYERs:
212  if( !Kiway.PlayersClose( false ) )
213  return;
214 
215  // evt_id can be one of:
216  // ID_NEW_PROJECT, ID_NEW_PROJECT_FROM_TEMPLATE, ID_LOAD_PROJECT, and
217  // wxID_ANY from 3 different places.
218  int evt_id = event.GetId();
219 
220  wxString title;
221 
222  ClearMsg();
223 
224  bool newProject = ( evt_id == ID_NEW_PROJECT ) ||
225  ( evt_id == ID_NEW_PROJECT_FROM_TEMPLATE );
226 
227  if( evt_id != wxID_ANY )
228  {
229  int style;
230 
231  if( newProject )
232  {
233  title = _( "Create New Project" );
234  style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT;
235  }
236  else
237  {
238  title = _( "Open Existing Project" );
239  style = wxFD_OPEN | wxFD_FILE_MUST_EXIST;
240  }
241 
242  wxString default_dir = GetMruPath();
243  wxFileDialog dlg( this, title, default_dir, wxEmptyString,
244  ProjectFileWildcard, style );
245 
246  if( dlg.ShowModal() == wxID_CANCEL )
247  return;
248 
249  //DBG( printf( "%s: wxFileDialog::GetPath=%s\n", __func__, TO_UTF8( dlg.GetPath() ) );)
250 
251  wxFileName pro( dlg.GetPath() );
252  pro.SetExt( ProjectFileExtension ); // enforce extension
253 
254  if( !pro.IsAbsolute() )
255  pro.MakeAbsolute();
256 
257  if( newProject )
258  {
259  // Check if the project directory is empty
260  wxDir directory( pro.GetPath() );
261 
262  if( directory.HasFiles() )
263  {
264  wxString msg = _( "The selected directory is not empty. We recommend you "
265  "create projects in their own clean directory.\n\nDo you "
266  "want to create a new empty directory for the project?" );
267 
268  if( IsOK( this, msg ) )
269  {
270  // Append a new directory with the same name of the project file
271  // and try to create it
272  pro.AppendDir( pro.GetName() );
273 
274  if( !wxMkdir( pro.GetPath() ) )
275  // There was a problem, undo
276  pro.RemoveLastDir();
277  }
278  }
279 
280  if( evt_id == ID_NEW_PROJECT )
281  {
282  CreateNewProject( pro.GetFullPath() );
283  }
284  else if( evt_id == ID_NEW_PROJECT_FROM_TEMPLATE )
285  {
286  // Launch the template selector dialog
287  CreateNewProject( pro.GetFullPath(), true );
288  }
289  }
290 
291  SetProjectFileName( pro.GetFullPath() );
292  }
293 
294  wxString prj_filename = GetProjectFileName();
295 
296  wxString nameless_prj = NAMELESS_PROJECT wxT( ".pro" );
297 
298  wxLogDebug( wxT( "%s: %s" ),
299  GetChars( wxFileName( prj_filename ).GetFullName() ),
300  GetChars( nameless_prj ) );
301 
302  // Check if project file exists and if it is not noname.pro
303  if( !wxFileExists( prj_filename )
304  && !wxFileName( prj_filename ).GetFullName().IsSameAs( nameless_prj ) )
305  {
306  wxString msg = wxString::Format( _(
307  "KiCad project file '%s' not found" ),
308  GetChars( prj_filename ) );
309 
310  DisplayError( this, msg );
311  return;
312  }
313 
314  // Either this is the first time kicad has been run or one of the projects in the
315  // history list is no longer valid. This prevents kicad from automatically creating
316  // a noname.pro file in the same folder as the kicad binary.
317  if( wxFileName( prj_filename ).GetFullName().IsSameAs( nameless_prj ) && !newProject )
318  {
319  m_active_project = false;
320  m_MessagesBox->SetValue( _( "To proceed, you can use the File menu to start a new project." ) );
321  return;
322  }
323  else
324  {
325  m_active_project = true;
326  m_MessagesBox->Clear();
327  }
328 
329  Prj().ConfigLoad( PgmTop().SysSearch(), GeneralGroupName, s_KicadManagerParams );
330 
331  title = L"KiCad \u2014 " + prj_filename;
332 
333  if( !wxFileName( prj_filename ).IsDirWritable() )
334  title += _( " [Read Only]" );
335  else
336  SetMruPath( Prj().GetProjectPath() ); // Only set MRU path if we have write access.
337 
338  SetTitle( title );
339 
340  if( !prj_filename.IsSameAs( nameless_prj ) )
341  UpdateFileHistory( prj_filename, &PgmTop().GetFileHistory() );
342 
344 
345  // Rebuild the list of watched paths.
346  // however this is possible only when the main loop event handler is running,
347  // so we use it to run the rebuild function.
348  wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_INIT_WATCHED_PATHS );
349 
350  wxPostEvent( this, cmd );
351 
352  PrintPrjInfo();
353 }
354 
355 
356 /* Creates a new project folder, copy a template into this new folder.
357  * and open this new project as working project
358  */
360 {
361  wxString default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep();
362  wxString title = _("New Project Folder");
363  wxDirDialog dlg( this, title, default_dir );
364 
365  if( dlg.ShowModal() == wxID_CANCEL )
366  return;
367 
368  // Builds the project .pro filename, from the new project folder name
369  wxFileName fn;
370  fn.AssignDir( dlg.GetPath() );
371  fn.SetName( dlg.GetPath().AfterLast( SEP() ) );
372  fn.SetExt( wxT( "pro" ) );
373 
374  // Launch the template selector dialog, and copy files
375  CreateNewProject( fn.GetFullPath(), true );
376 
377  // Initialize the project
378  event.SetId( wxID_ANY );
379  OnLoadProject( event );
380 }
381 
382 
383 void KICAD_MANAGER_FRAME::OnSaveProject( wxCommandEvent& event )
384 {
385  if( !wxIsWritable( GetProjectFileName() ) )
386  return;
387 
388  // was: wxGetApp().WriteProjectConfig( m_ProjectFileName.GetFullPath(),
389  // GeneralGroupName, s_KicadManagerParams );
390  Prj().ConfigSave( PgmTop().SysSearch(), GeneralGroupName, s_KicadManagerParams );
391 }
392 
393 
394 void KICAD_MANAGER_FRAME::OnUpdateRequiresProject( wxUpdateUIEvent& event )
395 {
396  event.Enable( m_active_project );
397 }
A list of parameters type.
VTBL_ENTRY bool PlayersClose(bool doForce)
Function PlayersClose calls the KIWAY_PLAYER::Close( bool force ) function on all the windows and if ...
Definition: kiway.cpp:374
VTBL_ENTRY void ConfigSave(const SEARCH_STACK &aSList, const wxString &aGroupName, const PARAM_CFG_ARRAY &aParams, const wxString &aFileName=wxEmptyString)
Function ConfigSave saves the current "project" parameters into the wxConfigBase* derivative...
Definition: project.cpp:307
void SetMruPath(const wxString &aPath)
Definition: wxstruct.h:357
PARAM_CFG_ARRAY s_KicadManagerParams
Definition: prjconfig.cpp:57
This file is part of the common library.
const wxString ProjectFileExtension
PROJECT_TEMPLATE * GetSelectedTemplate()
PROJECT & Prj()
Definition: kicad.cpp:293
const wxString ProjectFileWildcard
#define SEP()
Definition: prjconfig.cpp:49
void CreateNewProject(const wxString &aPrjFullFileName, bool aTemplateSelector)
Definition: prjconfig.cpp:59
The common library.
void OnLoadProject(wxCommandEvent &event)
Function OnLoadProject loads an exiting or creates a new project (.pro) file.
Definition: prjconfig.cpp:207
void UpdateFileHistory(const wxString &FullFileName, wxFileHistory *aFileHistory=NULL)
Function UpdateFileHistory Updates the list of recently opened files.
Definition: basicframe.cpp:388
void OnUpdateRequiresProject(wxUpdateUIEvent &event)
Definition: prjconfig.cpp:394
KICAD_MANAGER_FRAME is the KiCad main frame.
The common library.
void OnCreateProjectFromTemplate(wxCommandEvent &event)
Function OnCreateProjectFromTemplate Creates a new project folder, copy a template into this new fold...
Definition: prjconfig.cpp:359
void ReCreateTreePrj()
Create or modify the tree showing project file names.
PGM_KICAD & PgmTop()
Definition: kicad.cpp:71
#define GeneralGroupName
Definition: prjconfig.cpp:55
const wxString SchematicFileExtension
const wxString GetProjectFileName()
Definition: mainframe.cpp:144
void SetProjectFileName(const wxString &aFullProjectProFileName)
Definition: mainframe.cpp:132
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
bool CreateProject(wxFileName &aNewProjectPath)
Copies and renames all template files to create a new project.
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
wxTextCtrl * m_MessagesBox
Definition: kicad.h:296
const wxString LegacyPcbFileExtension
TREE_PROJECT_FRAME * m_LeftWin
Definition: kicad.h:294
const wxString KiCadPcbFileExtension
void AddTemplatesPage(const wxString &aTitle, wxFileName &aPath)
Add a new page with aTitle, populated with templates from aPath.
VTBL_ENTRY bool ConfigLoad(const SEARCH_STACK &aSearchS, const wxString &aGroupName, const PARAM_CFG_ARRAY &aParams, const wxString &aForeignConfigFileName=wxEmptyString)
Function ConfigLoad reads a subset of parameters from the "project" file.
Definition: project.cpp:342
bool m_active_project
Definition: kicad.h:304
wxFileHistory & GetFileHistory()
Definition: pgm_kicad.h:57
#define NAMELESS_PROJECT
default name for nameless projects
Definition: common.h:73
wxString GetMruPath() const
Definition: wxstruct.h:359
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:69
void ClearMsg()
a minor helper function: Erase the text panel.
Definition: mainframe.cpp:526
void PrintPrjInfo()
a minor helper function: Prints the Current Working Dir name and the projet name on the text panel...
Definition: mainframe.cpp:550
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:111
void OnSaveProject(wxCommandEvent &event)
Function OnSaveProject is the command event hendler to Save the project (.pro) file containing the to...
Definition: prjconfig.cpp:383
KIWAY Kiway