KiCad PCB EDA Suite
project.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) 2014-2018 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <wx/stdpaths.h>
25 
26 #include <common.h> // NAMELESS_PROJECT
27 #include <config_params.h>
28 #include <confirm.h>
29 #include <fctsys.h>
30 #include <fp_lib_table.h>
31 #include <kicad_string.h>
32 #include <kiface_ids.h>
33 #include <kiway.h>
34 #include <macros.h>
35 #include <pgm_base.h>
36 #include <project.h>
37 #include <project/project_file.h>
38 #include <trace_helpers.h>
40 
41 
43  m_projectFile( nullptr )
44 {
45  memset( m_elems, 0, sizeof(m_elems) );
46 }
47 
48 
50 {
51  // careful here, this should work, but the virtual destructor may not
52  // be in the same link image as PROJECT.
53  for( unsigned i = 0; i < arrayDim( m_elems ); ++i )
54  {
55  SetElem( ELEM_T( i ), NULL );
56  }
57 }
58 
59 
61 {
62  ElemsClear();
63 }
64 
65 
66 bool PROJECT::TextVarResolver( wxString* aToken ) const
67 {
68  if( GetTextVars().count( *aToken ) > 0 )
69  {
70  *aToken = GetTextVars().at( *aToken );
71  return true;
72  }
73 
74  return false;
75 }
76 
77 
78 std::map<wxString, wxString>& PROJECT::GetTextVars() const
79 {
80  return GetProjectFile().m_TextVars;
81 }
82 
83 
84 void PROJECT::setProjectFullName( const wxString& aFullPathAndName )
85 {
86  // Compare paths, rather than inodes, to be less surprising to the user.
87  // Create a temporary wxFileName to normalize the path
88  wxFileName candidate_path( aFullPathAndName );
89 
90  // Edge transitions only. This is what clears the project
91  // data using the Clear() function.
92  if( m_project_name.GetFullPath() != candidate_path.GetFullPath() )
93  {
94  Clear(); // clear the data when the project changes.
95 
96  wxLogTrace( tracePathsAndFiles, "%s: old:'%s' new:'%s'", __func__,
97  TO_UTF8( GetProjectFullName() ), TO_UTF8( aFullPathAndName ) );
98 
99  m_project_name = aFullPathAndName;
100 
101  wxASSERT( m_project_name.IsAbsolute() );
102 
103  wxASSERT( m_project_name.GetExt() == ProjectFileExtension );
104 
105  // until multiple projects are in play, set an environment variable for the
106  // the project pointer.
107  {
108  wxString path = m_project_name.GetPath();
109 
110  wxSetEnv( PROJECT_VAR_NAME, path );
111  }
112  }
113 }
114 
115 
116 const wxString PROJECT::GetProjectFullName() const
117 {
118  return m_project_name.GetFullPath();
119 }
120 
121 
122 const wxString PROJECT::GetProjectPath() const
123 {
124  return m_project_name.GetPathWithSep();
125 }
126 
127 
128 const wxString PROJECT::GetProjectName() const
129 {
130  return m_project_name.GetName();
131 }
132 
133 
134 const wxString PROJECT::SymbolLibTableName() const
135 {
136  return libTableName( "sym-lib-table" );
137 }
138 
139 
140 const wxString PROJECT::FootprintLibTblName() const
141 {
142  return libTableName( "fp-lib-table" );
143 }
144 
145 
146 const wxString PROJECT::libTableName( const wxString& aLibTableName ) const
147 {
148  wxFileName fn = GetProjectFullName();
149  wxString path = fn.GetPath();
150 
151  // if there's no path to the project name, or the name as a whole is bogus or its not
152  // write-able then use a template file.
153  if( !fn.GetDirCount() || !fn.IsOk() || !wxFileName::IsDirWritable( path ) )
154  {
155  // return a template filename now.
156 
157  // this next line is likely a problem now, since it relies on an
158  // application title which is no longer constant or known. This next line needs
159  // to be re-thought out.
160 
161 #ifndef __WXMAC__
162  fn.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
163 #else
164  // don't pollute home folder, temp folder seems to be more appropriate
165  fn.AssignDir( wxStandardPaths::Get().GetTempDir() );
166 #endif
167 
168 #if defined( __WINDOWS__ )
169  fn.AppendDir( wxT( "kicad" ) );
170 #endif
171 
172  /*
173  * The library table name used when no project file is passed to the appropriate
174  * code. This is used temporarily to store the project specific library table
175  * until the project file being edited is saved. It is then moved to the correct
176  * file in the folder where the project file is saved.
177  */
178  fn.SetName( "prj-" + aLibTableName );
179  }
180  else // normal path.
181  {
182  fn.SetName( aLibTableName );
183  }
184 
185  fn.ClearExt();
186 
187  return fn.GetFullPath();
188 }
189 
190 
191 const wxString PROJECT::GetSheetName( const KIID& aSheetID )
192 {
193  if( m_sheetNames.empty() )
194  {
195  for( auto pair : GetProjectFile().GetSheets() )
196  m_sheetNames[pair.first] = pair.second;
197  }
198 
199  if( m_sheetNames.count( aSheetID ) )
200  return m_sheetNames.at( aSheetID );
201  else
202  return aSheetID.AsString();
203 }
204 
205 
206 void PROJECT::SetRString( RSTRING_T aIndex, const wxString& aString )
207 {
208  unsigned ndx = unsigned( aIndex );
209 
210  if( ndx < arrayDim( m_rstrings ) )
211  {
212  m_rstrings[ndx] = aString;
213  }
214  else
215  {
216  wxASSERT( 0 ); // bad index
217  }
218 }
219 
220 
221 const wxString& PROJECT::GetRString( RSTRING_T aIndex )
222 {
223  unsigned ndx = unsigned( aIndex );
224 
225  if( ndx < arrayDim( m_rstrings ) )
226  {
227  return m_rstrings[ndx];
228  }
229  else
230  {
231  static wxString no_cookie_for_you;
232 
233  wxASSERT( 0 ); // bad index
234 
235  return no_cookie_for_you;
236  }
237 }
238 
239 
241 {
242  // This is virtual, so implement it out of line
243 
244  if( unsigned( aIndex ) < arrayDim( m_elems ) )
245  {
246  return m_elems[aIndex];
247  }
248  return NULL;
249 }
250 
251 
252 void PROJECT::SetElem( ELEM_T aIndex, _ELEM* aElem )
253 {
254  // This is virtual, so implement it out of line
255 
256  if( unsigned( aIndex ) < arrayDim( m_elems ) )
257  {
258 #if defined(DEBUG) && 0
259  if( aIndex == ELEM_SCH_PART_LIBS )
260  {
261  printf( "%s: &m_elems[%i]:%p aElem:%p\n", __func__, aIndex, &m_elems[aIndex], aElem );
262  }
263 #endif
264  delete m_elems[aIndex];
265  m_elems[aIndex] = aElem;
266  }
267 }
268 
269 
270 const wxString PROJECT::AbsolutePath( const wxString& aFileName ) const
271 {
272  wxFileName fn = aFileName;
273 
274  if( !fn.IsAbsolute() )
275  {
276  wxString pro_dir = wxPathOnly( GetProjectFullName() );
277  fn.Normalize( wxPATH_NORM_ALL, pro_dir );
278  }
279 
280  return fn.GetFullPath();
281 }
282 
283 
285 {
286  // This is a lazy loading function, it loads the project specific table when
287  // that table is asked for, not before.
288 
290 
291  if( tbl )
292  {
293  wxASSERT( tbl->Type() == FP_LIB_TABLE_T );
294  }
295  else
296  {
297  try
298  {
299  // Build a new project specific FP_LIB_TABLE with the global table as a fallback.
300  // ~FP_LIB_TABLE() will not touch the fallback table, so multiple projects may
301  // stack this way, all using the same global fallback table.
302  KIFACE* kiface = aKiway.KiFACE( KIWAY::FACE_PCB );
303 
304  tbl = (FP_LIB_TABLE*) kiface->IfaceOrAddress( KIFACE_NEW_FOOTPRINT_TABLE );
305  tbl->Load( FootprintLibTblName() );
306 
307  SetElem( ELEM_FPTBL, tbl );
308  }
309  catch( const IO_ERROR& ioe )
310  {
311  DisplayErrorMessage( NULL, _( "Error loading project footprint library table" ),
312  ioe.What() );
313  }
314  catch( ... )
315  {
316  DisplayErrorMessage( NULL, _( "Error loading project footprint library table" ) );
317  }
318  }
319 
320  return tbl;
321 }
_ELEM * m_elems[ELEM_COUNT]
Definition: project.h:339
std::map< wxString, wxString > m_TextVars
Definition: project_file.h:128
void Clear()
Function Clear clears the _ELEMs and RSTRINGs.
Definition: project.h:217
BITMAP2CMP_SETTINGS kiface
VTBL_ENTRY std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:78
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:252
This file is part of the common library.
const std::string ProjectFileExtension
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition: project.h:38
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
wxString AsString() const
Definition: common.cpp:165
VTBL_ENTRY _ELEM * GetElem(ELEM_T aIndex)
Typically wrapped somewhere else in a more meaningful function wrapper.
Definition: project.cpp:240
VTBL_ENTRY const wxString GetProjectPath() const
Function GetProjectPath returns the full path of the project.
Definition: project.cpp:122
VTBL_ENTRY const wxString AbsolutePath(const wxString &aFileName) const
Function AbsolutePath fixes up aFileName if it is relative to the project's directory to be an absolu...
Definition: project.cpp:270
This file contains miscellaneous commonly used macros and functions.
VTBL_ENTRY void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:252
Definition: common.h:68
#define NULL
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
wxFileName m_project_name
<fullpath>/<basename>.pro
Definition: project.h:324
VTBL_ENTRY PROJECT_FILE & GetProjectFile() const
Definition: project.h:129
VTBL_ENTRY const wxString GetSheetName(const KIID &aSheetID)
Return the name of the sheet identified by the given UUID.
Definition: project.cpp:191
Definition of file extensions used in Kicad.
KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the s...
Definition: kiway.h:273
VTBL_ENTRY bool TextVarResolver(wxString *aToken) const
Definition: project.cpp:66
pcbnew DSO
Definition: kiway.h:282
Return a new FP_LIB_TABLE with the global table installed as a fallback.
Definition: kiface_ids.h:46
wxLogTrace helper definitions.
VTBL_ENTRY const wxString GetProjectFullName() const
Function GetProjectFullName returns the full path and name of the project.
Definition: project.cpp:116
VTBL_ENTRY KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Function KiFACE returns the KIFACE* given a FACE_T.
Definition: kiway.cpp:178
void Load(const wxString &aFileName)
Load the library table using the path defined by aFileName aFallBackTable.
VTBL_ENTRY void ElemsClear()
Function ElemsClear deletes all the _ELEMs and set their pointers to NULL.
Definition: project.cpp:49
PROJECT()
Definition: project.cpp:42
KICAD_T Type() override
Definition: fp_lib_table.h:108
VTBL_ENTRY void setProjectFullName(const wxString &aFullPathAndName)
Sets the: 1) full directory, 2) basename, and 3) extension of the project.
Definition: project.cpp:84
VTBL_ENTRY const wxString SymbolLibTableName() const
Return the path and file name of this projects symbol library table.
Definition: project.cpp:134
VTBL_ENTRY void SetRString(RSTRING_T aStringId, const wxString &aString)
Function SetRString stores a "retained string", which is any session and project specific string iden...
Definition: project.cpp:206
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:160
VTBL_ENTRY FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:284
std::vector< FILE_INFO_PAIR > & GetSheets()
Definition: project_file.h:82
VTBL_ENTRY const wxString & GetRString(RSTRING_T aStringId)
Function GetRString returns a "retained string", which is any session and project specific string ide...
Definition: project.cpp:221
ELEM_T
Enum ELEM_T is the set of _ELEMs that a PROJECT can hold.
Definition: project.h:183
see class PGM_BASE
RSTRING_T
Retain a number of project specific wxStrings, enumerated here:
Definition: project.h:142
#define _(s)
Definition: 3d_actions.cpp:33
wxString m_rstrings[RSTRING_COUNT]
Definition: project.h:336
KIFACE is used by a participant in the KIWAY alchemy.
Definition: kiway.h:150
#define TO_UTF8(wxstring)
The common library.
std::map< KIID, wxString > m_sheetNames
Definition: project.h:333
A PROJECT can hold stuff it knows nothing about, in the form of _ELEM derivatives.
Definition: project.h:74
VTBL_ENTRY const wxString GetProjectName() const
Function GetProjectName returns the short name of the project.
Definition: project.cpp:128
VTBL_ENTRY ~PROJECT()
Definition: project.cpp:60
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
VTBL_ENTRY const wxString FootprintLibTblName() const
Function FootprintLibTblName returns the path and filename of this project's fp-lib-table,...
Definition: project.cpp:140
const wxString libTableName(const wxString &aLibTableName) const
Return the full path and file name of the project specific library table aLibTableName.
Definition: project.cpp:146