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_readOnly( false ),
44  m_projectFile( nullptr ),
45  m_localSettings( nullptr )
46 {
47  memset( m_elems, 0, sizeof(m_elems) );
48 }
49 
50 
52 {
53  // careful here, this should work, but the virtual destructor may not
54  // be in the same link image as PROJECT.
55  for( unsigned i = 0; i < arrayDim( m_elems ); ++i )
56  {
57  SetElem( ELEM_T( i ), NULL );
58  }
59 }
60 
61 
63 {
64  ElemsClear();
65 }
66 
67 
68 bool PROJECT::TextVarResolver( wxString* aToken ) const
69 {
70  if( GetTextVars().count( *aToken ) > 0 )
71  {
72  *aToken = GetTextVars().at( *aToken );
73  return true;
74  }
75 
76  return false;
77 }
78 
79 
80 std::map<wxString, wxString>& PROJECT::GetTextVars() const
81 {
82  return GetProjectFile().m_TextVars;
83 }
84 
85 
86 void PROJECT::setProjectFullName( const wxString& aFullPathAndName )
87 {
88  // Compare paths, rather than inodes, to be less surprising to the user.
89  // Create a temporary wxFileName to normalize the path
90  wxFileName candidate_path( aFullPathAndName );
91 
92  // Edge transitions only. This is what clears the project
93  // data using the Clear() function.
94  if( m_project_name.GetFullPath() != candidate_path.GetFullPath() )
95  {
96  Clear(); // clear the data when the project changes.
97 
98  wxLogTrace( tracePathsAndFiles, "%s: old:'%s' new:'%s'", __func__,
99  TO_UTF8( GetProjectFullName() ), TO_UTF8( aFullPathAndName ) );
100 
101  m_project_name = aFullPathAndName;
102 
103  wxASSERT( m_project_name.IsAbsolute() );
104 
105  wxASSERT( m_project_name.GetExt() == ProjectFileExtension );
106 
107  // until multiple projects are in play, set an environment variable for the
108  // the project pointer.
109  {
110  wxString path = m_project_name.GetPath();
111 
112  wxSetEnv( PROJECT_VAR_NAME, path );
113  }
114  }
115 }
116 
117 
118 const wxString PROJECT::GetProjectFullName() const
119 {
120  return m_project_name.GetFullPath();
121 }
122 
123 
124 const wxString PROJECT::GetProjectPath() const
125 {
126  return m_project_name.GetPathWithSep();
127 }
128 
129 
130 const wxString PROJECT::GetProjectName() const
131 {
132  return m_project_name.GetName();
133 }
134 
135 
137 {
138  return m_project_name.GetName().IsEmpty();
139 }
140 
141 
142 const wxString PROJECT::SymbolLibTableName() const
143 {
144  return libTableName( "sym-lib-table" );
145 }
146 
147 
148 const wxString PROJECT::FootprintLibTblName() const
149 {
150  return libTableName( "fp-lib-table" );
151 }
152 
153 
154 const wxString PROJECT::libTableName( const wxString& aLibTableName ) const
155 {
156  wxFileName fn = GetProjectFullName();
157  wxString path = fn.GetPath();
158 
159  // if there's no path to the project name, or the name as a whole is bogus or its not
160  // write-able then use a template file.
161  if( !fn.GetDirCount() || !fn.IsOk() || !wxFileName::IsDirWritable( path ) )
162  {
163  // return a template filename now.
164 
165  // this next line is likely a problem now, since it relies on an
166  // application title which is no longer constant or known. This next line needs
167  // to be re-thought out.
168 
169 #ifndef __WXMAC__
170  fn.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
171 #else
172  // don't pollute home folder, temp folder seems to be more appropriate
173  fn.AssignDir( wxStandardPaths::Get().GetTempDir() );
174 #endif
175 
176 #if defined( __WINDOWS__ )
177  fn.AppendDir( wxT( "kicad" ) );
178 #endif
179 
180  /*
181  * The library table name used when no project file is passed to the appropriate
182  * code. This is used temporarily to store the project specific library table
183  * until the project file being edited is saved. It is then moved to the correct
184  * file in the folder where the project file is saved.
185  */
186  fn.SetName( "prj-" + aLibTableName );
187  }
188  else // normal path.
189  {
190  fn.SetName( aLibTableName );
191  }
192 
193  fn.ClearExt();
194 
195  return fn.GetFullPath();
196 }
197 
198 
199 const wxString PROJECT::GetSheetName( const KIID& aSheetID )
200 {
201  if( m_sheetNames.empty() )
202  {
203  for( auto pair : GetProjectFile().GetSheets() )
204  m_sheetNames[pair.first] = pair.second;
205  }
206 
207  if( m_sheetNames.count( aSheetID ) )
208  return m_sheetNames.at( aSheetID );
209  else
210  return aSheetID.AsString();
211 }
212 
213 
214 void PROJECT::SetRString( RSTRING_T aIndex, const wxString& aString )
215 {
216  unsigned ndx = unsigned( aIndex );
217 
218  if( ndx < arrayDim( m_rstrings ) )
219  {
220  m_rstrings[ndx] = aString;
221  }
222  else
223  {
224  wxASSERT( 0 ); // bad index
225  }
226 }
227 
228 
229 const wxString& PROJECT::GetRString( RSTRING_T aIndex )
230 {
231  unsigned ndx = unsigned( aIndex );
232 
233  if( ndx < arrayDim( m_rstrings ) )
234  {
235  return m_rstrings[ndx];
236  }
237  else
238  {
239  static wxString no_cookie_for_you;
240 
241  wxASSERT( 0 ); // bad index
242 
243  return no_cookie_for_you;
244  }
245 }
246 
247 
249 {
250  // This is virtual, so implement it out of line
251 
252  if( unsigned( aIndex ) < arrayDim( m_elems ) )
253  {
254  return m_elems[aIndex];
255  }
256  return NULL;
257 }
258 
259 
260 void PROJECT::SetElem( ELEM_T aIndex, _ELEM* aElem )
261 {
262  // This is virtual, so implement it out of line
263 
264  if( unsigned( aIndex ) < arrayDim( m_elems ) )
265  {
266  delete m_elems[aIndex];
267  m_elems[aIndex] = aElem;
268  }
269 }
270 
271 
272 const wxString PROJECT::AbsolutePath( const wxString& aFileName ) const
273 {
274  wxFileName fn = aFileName;
275 
276  if( !fn.IsAbsolute() )
277  {
278  wxString pro_dir = wxPathOnly( GetProjectFullName() );
279  fn.Normalize( wxPATH_NORM_ALL, pro_dir );
280  }
281 
282  return fn.GetFullPath();
283 }
284 
285 
287 {
288  // This is a lazy loading function, it loads the project specific table when
289  // that table is asked for, not before.
290 
292 
293  if( tbl )
294  {
295  wxASSERT( tbl->Type() == FP_LIB_TABLE_T );
296  }
297  else
298  {
299  try
300  {
301  // Build a new project specific FP_LIB_TABLE with the global table as a fallback.
302  // ~FP_LIB_TABLE() will not touch the fallback table, so multiple projects may
303  // stack this way, all using the same global fallback table.
304  KIFACE* kiface = aKiway.KiFACE( KIWAY::FACE_PCB );
305 
306  tbl = (FP_LIB_TABLE*) kiface->IfaceOrAddress( KIFACE_NEW_FOOTPRINT_TABLE );
307  tbl->Load( FootprintLibTblName() );
308 
309  SetElem( ELEM_FPTBL, tbl );
310  }
311  catch( const IO_ERROR& ioe )
312  {
313  DisplayErrorMessage( NULL, _( "Error loading project footprint library table" ),
314  ioe.What() );
315  }
316  catch( ... )
317  {
318  DisplayErrorMessage( NULL, _( "Error loading project footprint library table" ) );
319  }
320  }
321 
322  return tbl;
323 }
_ELEM * m_elems[ELEM_COUNT]
Definition: project.h:354
std::map< wxString, wxString > m_TextVars
Definition: project_file.h:128
void Clear()
Function Clear clears the _ELEMs and RSTRINGs.
Definition: project.h:229
BITMAP2CMP_SETTINGS kiface
VTBL_ENTRY std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:80
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:248
VTBL_ENTRY const wxString GetProjectPath() const
Function GetProjectPath returns the full path of the project.
Definition: project.cpp:124
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:272
This file contains miscellaneous commonly used macros and functions.
VTBL_ENTRY void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:260
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:100
Definition: common.h:68
#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:336
VTBL_ENTRY PROJECT_FILE & GetProjectFile() const
Definition: project.h:141
VTBL_ENTRY const wxString GetSheetName(const KIID &aSheetID)
Return the name of the sheet identified by the given UUID.
Definition: project.cpp:199
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:68
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:118
VTBL_ENTRY KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Function KiFACE returns the KIFACE* given a FACE_T.
Definition: kiway.cpp:179
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:51
VTBL_ENTRY bool IsNullProject() const
Checks if this project is a null project (i.e.
Definition: project.cpp:136
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:86
VTBL_ENTRY const wxString SymbolLibTableName() const
Return the path and file name of this projects symbol library table.
Definition: project.cpp:142
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:214
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:286
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:229
ELEM_T
Enum ELEM_T is the set of _ELEMs that a PROJECT can hold.
Definition: project.h:195
see class PGM_BASE
RSTRING_T
Retain a number of project specific wxStrings, enumerated here:
Definition: project.h:154
#define _(s)
Definition: 3d_actions.cpp:33
wxString m_rstrings[RSTRING_COUNT]
Definition: project.h:351
KIFACE is used by a participant in the KIWAY alchemy.
Definition: kiway.h:150
The common library.
std::map< KIID, wxString > m_sheetNames
Definition: project.h:348
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:130
VTBL_ENTRY ~PROJECT()
Definition: project.cpp:62
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:148
const wxString libTableName(const wxString &aLibTableName) const
Return the full path and file name of the project specific library table aLibTableName.
Definition: project.cpp:154