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 <config_params.h>
27 #include <confirm.h>
28 #include <core/arraydim.h>
29 #include <fp_lib_table.h>
30 #include <kicad_string.h>
31 #include <kiface_ids.h>
32 #include <kiway.h>
33 #include <pgm_base.h>
34 #include <project.h>
35 #include <project/project_file.h>
36 #include <trace_helpers.h>
38 
39 
41  m_readOnly( false ),
42  m_projectFile( nullptr ),
43  m_localSettings( 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 
135 {
136  return m_project_name.GetName().IsEmpty();
137 }
138 
139 
140 const wxString PROJECT::SymbolLibTableName() const
141 {
142  return libTableName( "sym-lib-table" );
143 }
144 
145 
146 const wxString PROJECT::FootprintLibTblName() const
147 {
148  return libTableName( "fp-lib-table" );
149 }
150 
151 
152 const wxString PROJECT::libTableName( const wxString& aLibTableName ) const
153 {
154  wxFileName fn = GetProjectFullName();
155  wxString path = fn.GetPath();
156 
157  // if there's no path to the project name, or the name as a whole is bogus or its not
158  // write-able then use a template file.
159  if( !fn.GetDirCount() || !fn.IsOk() || !wxFileName::IsDirWritable( path ) )
160  {
161  // return a template filename now.
162 
163  // this next line is likely a problem now, since it relies on an
164  // application title which is no longer constant or known. This next line needs
165  // to be re-thought out.
166 
167 #ifndef __WXMAC__
168  fn.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
169 #else
170  // don't pollute home folder, temp folder seems to be more appropriate
171  fn.AssignDir( wxStandardPaths::Get().GetTempDir() );
172 #endif
173 
174 #if defined( __WINDOWS__ )
175  fn.AppendDir( wxT( "kicad" ) );
176 #endif
177 
178  /*
179  * The library table name used when no project file is passed to the appropriate
180  * code. This is used temporarily to store the project specific library table
181  * until the project file being edited is saved. It is then moved to the correct
182  * file in the folder where the project file is saved.
183  */
184  fn.SetName( "prj-" + aLibTableName );
185  }
186  else // normal path.
187  {
188  fn.SetName( aLibTableName );
189  }
190 
191  fn.ClearExt();
192 
193  return fn.GetFullPath();
194 }
195 
196 
197 const wxString PROJECT::GetSheetName( const KIID& aSheetID )
198 {
199  if( m_sheetNames.empty() )
200  {
201  for( auto pair : GetProjectFile().GetSheets() )
202  m_sheetNames[pair.first] = pair.second;
203  }
204 
205  if( m_sheetNames.count( aSheetID ) )
206  return m_sheetNames.at( aSheetID );
207  else
208  return aSheetID.AsString();
209 }
210 
211 
212 void PROJECT::SetRString( RSTRING_T aIndex, const wxString& aString )
213 {
214  unsigned ndx = unsigned( aIndex );
215 
216  if( ndx < arrayDim( m_rstrings ) )
217  {
218  m_rstrings[ndx] = aString;
219  }
220  else
221  {
222  wxASSERT( 0 ); // bad index
223  }
224 }
225 
226 
227 const wxString& PROJECT::GetRString( RSTRING_T aIndex )
228 {
229  unsigned ndx = unsigned( aIndex );
230 
231  if( ndx < arrayDim( m_rstrings ) )
232  {
233  return m_rstrings[ndx];
234  }
235  else
236  {
237  static wxString no_cookie_for_you;
238 
239  wxASSERT( 0 ); // bad index
240 
241  return no_cookie_for_you;
242  }
243 }
244 
245 
247 {
248  // This is virtual, so implement it out of line
249 
250  if( unsigned( aIndex ) < arrayDim( m_elems ) )
251  {
252  return m_elems[aIndex];
253  }
254  return NULL;
255 }
256 
257 
258 void PROJECT::SetElem( ELEM_T aIndex, _ELEM* aElem )
259 {
260  // This is virtual, so implement it out of line
261 
262  if( unsigned( aIndex ) < arrayDim( m_elems ) )
263  {
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:356
std::map< wxString, wxString > m_TextVars
Definition: project_file.h:128
void Clear()
Function Clear clears the _ELEMs and RSTRINGs.
Definition: project.h:231
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:253
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: kiid.cpp:174
VTBL_ENTRY _ELEM * GetElem(ELEM_T aIndex)
Typically wrapped somewhere else in a more meaningful function wrapper.
Definition: project.cpp:246
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
VTBL_ENTRY void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:258
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:95
Definition: kiid.h:44
#define NULL
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:29
wxFileName m_project_name
<fullpath>/<basename>.pro
Definition: project.h:338
VTBL_ENTRY PROJECT_FILE & GetProjectFile() const
Definition: project.h:143
VTBL_ENTRY const wxString GetSheetName(const KIID &aSheetID)
Return the name of the sheet identified by the given UUID.
Definition: project.cpp:197
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
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
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:180
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
VTBL_ENTRY bool IsNullProject() const
Checks if this project is a null project (i.e.
Definition: project.cpp:134
PROJECT()
Definition: project.cpp:40
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:140
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:212
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:227
ELEM_T
Enum ELEM_T is the set of _ELEMs that a PROJECT can hold.
Definition: project.h:197
see class PGM_BASE
RSTRING_T
Retain a number of project specific wxStrings, enumerated here:
Definition: project.h:156
#define _(s)
Definition: 3d_actions.cpp:33
wxString m_rstrings[RSTRING_COUNT]
Definition: project.h:353
KIFACE is used by a participant in the KIWAY alchemy.
Definition: kiway.h:150
std::map< KIID, wxString > m_sheetNames
Definition: project.h:350
A PROJECT can hold stuff it knows nothing about, in the form of _ELEM derivatives.
Definition: project.h:76
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:146
const wxString libTableName(const wxString &aLibTableName) const
Return the full path and file name of the project specific library table aLibTableName.
Definition: project.cpp:152