KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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/log.h>
25#include <wx/stdpaths.h> // required on Mac
27
28#include <algorithm>
29#include <pgm_base.h>
30#include <confirm.h>
31#include <core/kicad_algo.h>
33#include <fp_lib_table.h>
34#include <string_utils.h>
35#include <kiface_ids.h>
36#include <kiway.h>
37#include <lockfile.h>
38#include <macros.h>
40#include <git2.h>
41#include <project.h>
43#include <trace_helpers.h>
47#include <title_block.h>
48
49
50
52 m_readOnly( false ),
55 m_projectFile( nullptr ),
56 m_localSettings( nullptr )
57{
58 m_elems.fill( nullptr );
59}
60
61
63{
64 // careful here, this should work, but the virtual destructor may not
65 // be in the same link image as PROJECT.
66 for( unsigned i = 0; i < m_elems.size(); ++i )
67 {
68 SetElem( static_cast<PROJECT::ELEM>( i ), nullptr );
69 }
70}
71
72
77
78
79bool PROJECT::TextVarResolver( wxString* aToken ) const
80{
81 if( aToken->IsSameAs( wxT( "PROJECTNAME" ) ) )
82 {
83 *aToken = GetProjectName();
84 return true;
85 }
86 else if( aToken->IsSameAs( wxT( "CURRENT_DATE" ) ) )
87 {
89 return true;
90 }
91 else if( aToken->IsSameAs( wxT( "VCSHASH" ) ) )
92 {
94 return true;
95 }
96 else if( aToken->IsSameAs( wxT( "VCSSHORTHASH" ) ) )
97 {
99 return true;
100 }
101 else if( GetTextVars().count( *aToken ) > 0 )
102 {
103 *aToken = GetTextVars().at( *aToken );
104 return true;
105 }
106
107 return false;
108}
109
110
111std::map<wxString, wxString>& PROJECT::GetTextVars() const
112{
113 return GetProjectFile().m_TextVars;
114}
115
116
117void PROJECT::ApplyTextVars( const std::map<wxString, wxString>& aVarsMap )
118{
119 if( aVarsMap.size() == 0 )
120 return;
121
122 std::map<wxString, wxString>& existingVarsMap = GetTextVars();
123
124 for( const auto& var : aVarsMap )
125 {
126 // create or update the existing vars
127 existingVarsMap[var.first] = var.second;
128 }
129}
130
131
132void PROJECT::setProjectFullName( const wxString& aFullPathAndName )
133{
134 // Compare paths, rather than inodes, to be less surprising to the user.
135 // Create a temporary wxFileName to normalize the path
136 wxFileName candidate_path( aFullPathAndName );
137
138 // Edge transitions only. This is what clears the project
139 // data using the Clear() function.
140 if( m_project_name.GetFullPath() != candidate_path.GetFullPath() )
141 {
142 Clear(); // clear the data when the project changes.
143
144 wxLogTrace( tracePathsAndFiles, "%s: old:'%s' new:'%s'", __func__,
145 TO_UTF8( GetProjectFullName() ), TO_UTF8( aFullPathAndName ) );
146
147 m_project_name = aFullPathAndName;
148
149 wxASSERT( m_project_name.IsAbsolute() );
150
151 wxASSERT( m_project_name.GetExt() == FILEEXT::ProjectFileExtension );
152 }
153}
154
155
156const wxString PROJECT::GetProjectFullName() const
157{
158 return m_project_name.GetFullPath();
159}
160
161
162const wxString PROJECT::GetProjectPath() const
163{
164 return m_project_name.GetPathWithSep();
165}
166
167
168const wxString PROJECT::GetProjectDirectory() const
169{
170 return m_project_name.GetPath();
171}
172
173
174const wxString PROJECT::GetProjectName() const
175{
176 return m_project_name.GetName();
177}
178
179
181{
182 return m_project_name.GetName().IsEmpty();
183}
184
185
190
191
196
197
202
203
204void PROJECT::PinLibrary( const wxString& aLibrary, enum LIB_TYPE_T aLibType )
205{
207 std::vector<wxString>* pinnedLibsCfg = nullptr;
208 std::vector<wxString>* pinnedLibsFile = nullptr;
209
210 switch( aLibType )
211 {
213 pinnedLibsFile = &m_projectFile->m_PinnedSymbolLibs;
214 pinnedLibsCfg = &cfg->m_Session.pinned_symbol_libs;
215 break;
217 pinnedLibsFile = &m_projectFile->m_PinnedFootprintLibs;
218 pinnedLibsCfg = &cfg->m_Session.pinned_fp_libs;
219 break;
221 pinnedLibsFile = &m_projectFile->m_PinnedDesignBlockLibs;
222 pinnedLibsCfg = &cfg->m_Session.pinned_design_block_libs;
223 break;
224 default:
225 wxFAIL_MSG( "Cannot pin library: invalid library type" );
226 return;
227 }
228
229 if( !alg::contains( *pinnedLibsFile, aLibrary ) )
230 pinnedLibsFile->push_back( aLibrary );
231
233
234 if( !alg::contains( *pinnedLibsCfg, aLibrary ) )
235 pinnedLibsCfg->push_back( aLibrary );
236
237 cfg->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( cfg ) );
238}
239
240
241void PROJECT::UnpinLibrary( const wxString& aLibrary, enum LIB_TYPE_T aLibType )
242{
244 std::vector<wxString>* pinnedLibsCfg = nullptr;
245 std::vector<wxString>* pinnedLibsFile = nullptr;
246
247 switch( aLibType )
248 {
250 pinnedLibsFile = &m_projectFile->m_PinnedSymbolLibs;
251 pinnedLibsCfg = &cfg->m_Session.pinned_symbol_libs;
252 break;
254 pinnedLibsFile = &m_projectFile->m_PinnedFootprintLibs;
255 pinnedLibsCfg = &cfg->m_Session.pinned_fp_libs;
256 break;
258 pinnedLibsFile = &m_projectFile->m_PinnedDesignBlockLibs;
259 pinnedLibsCfg = &cfg->m_Session.pinned_design_block_libs;
260 break;
261 default:
262 wxFAIL_MSG( "Cannot unpin library: invalid library type" );
263 return;
264 }
265
266 std::erase( *pinnedLibsFile, aLibrary );
268
269 std::erase( *pinnedLibsCfg, aLibrary );
270 cfg->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( cfg ) );
271}
272
273
274const wxString PROJECT::libTableName( const wxString& aLibTableName ) const
275{
276 wxFileName fn = GetProjectFullName();
277 wxString path = fn.GetPath();
278
279 // if there's no path to the project name, or the name as a whole is bogus or its not
280 // write-able then use a template file.
281 if( !fn.GetDirCount() || !fn.IsOk() || !wxFileName::IsDirWritable( path ) )
282 {
283 // return a template filename now.
284
285 // this next line is likely a problem now, since it relies on an
286 // application title which is no longer constant or known. This next line needs
287 // to be re-thought out.
288
289#ifdef __WXMAC__
290 fn.AssignDir( KIPLATFORM::ENV::GetUserConfigPath() );
291#else
292 // don't pollute home folder, temp folder seems to be more appropriate
293 fn.AssignDir( wxStandardPaths::Get().GetTempDir() );
294#endif
295
296#if defined( __WINDOWS__ )
297 fn.AppendDir( wxT( "kicad" ) );
298#endif
299
300 /*
301 * The library table name used when no project file is passed to the appropriate
302 * code. This is used temporarily to store the project specific library table
303 * until the project file being edited is saved. It is then moved to the correct
304 * file in the folder where the project file is saved.
305 */
306 fn.SetName( wxS( "prj-" ) + aLibTableName );
307 }
308 else // normal path.
309 {
310 fn.SetName( aLibTableName );
311 }
312
313 fn.ClearExt();
314
315 return fn.GetFullPath();
316}
317
318
319const wxString PROJECT::GetSheetName( const KIID& aSheetID )
320{
321 if( m_sheetNames.empty() )
322 {
323 for( const std::pair<KIID, wxString>& pair : GetProjectFile().GetSheets() )
324 m_sheetNames[pair.first] = pair.second;
325 }
326
327 if( m_sheetNames.count( aSheetID ) )
328 return m_sheetNames.at( aSheetID );
329 else
330 return aSheetID.AsString();
331}
332
333
334void PROJECT::SetRString( RSTRING_T aIndex, const wxString& aString )
335{
336 unsigned ndx = unsigned( aIndex );
337
338 if( ndx < m_rstrings.size() )
339 m_rstrings[ndx] = aString;
340 else
341 wxASSERT( 0 ); // bad index
342}
343
344
345const wxString& PROJECT::GetRString( RSTRING_T aIndex )
346{
347 unsigned ndx = unsigned( aIndex );
348
349 if( ndx < m_rstrings.size() )
350 {
351 return m_rstrings[ndx];
352 }
353 else
354 {
355 static wxString no_cookie_for_you;
356
357 wxASSERT( 0 ); // bad index
358
359 return no_cookie_for_you;
360 }
361}
362
363
365{
366 // This is virtual, so implement it out of line
367
368 if( static_cast<unsigned>( aIndex ) < m_elems.size() )
369 return m_elems[static_cast<unsigned>( aIndex )];
370
371 return nullptr;
372}
373
374
376{
377 // This is virtual, so implement it out of line
378 if( static_cast<unsigned>( aIndex ) < m_elems.size() )
379 {
380 delete m_elems[static_cast<unsigned>(aIndex)];
381 m_elems[static_cast<unsigned>( aIndex )] = aElem;
382 }
383}
384
385
386const wxString PROJECT::AbsolutePath( const wxString& aFileName ) const
387{
388 wxFileName fn = aFileName;
389
390 // Paths which start with an unresolved variable reference are more likely to be
391 // absolute than relative.
392 if( aFileName.StartsWith( wxT( "${" ) ) )
393 return aFileName;
394
395 if( !fn.IsAbsolute() )
396 {
397 wxString pro_dir = wxPathOnly( GetProjectFullName() );
398 fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS, pro_dir );
399 }
400
401 return fn.GetFullPath();
402}
403
404
406{
407 // This is a lazy loading function, it loads the project specific table when
408 // that table is asked for, not before.
409
411
412 if( tbl )
413 {
414 wxASSERT( tbl->ProjectElementType() == PROJECT::ELEM::FPTBL );
415 }
416 else
417 {
418 try
419 {
420 // Build a new project specific FP_LIB_TABLE with the global table as a fallback.
421 // ~FP_LIB_TABLE() will not touch the fallback table, so multiple projects may
422 // stack this way, all using the same global fallback table.
423 KIFACE* kiface = aKiway.KiFACE( KIWAY::FACE_PCB );
424
425 tbl = (FP_LIB_TABLE*) kiface->IfaceOrAddress( KIFACE_NEW_FOOTPRINT_TABLE );
426 tbl->Load( FootprintLibTblName() );
427
429 }
430 catch( const IO_ERROR& ioe )
431 {
432 DisplayErrorMessage( nullptr, _( "Error loading project footprint library table." ),
433 ioe.What() );
434 }
435 catch( ... )
436 {
437 DisplayErrorMessage( nullptr, _( "Error loading project footprint library table." ) );
438 }
439 }
440
441 return tbl;
442}
443
444
446{
447 // This is a lazy loading function, it loads the project specific table when
448 // that table is asked for, not before.
449
451
452 if( tbl )
453 {
455 }
456 else
457 {
458 try
459 {
461 tbl->Load( DesignBlockLibTblName() );
462
464 }
465 catch( const IO_ERROR& ioe )
466 {
467 DisplayErrorMessage( nullptr, _( "Error loading project design block library table." ),
468 ioe.What() );
469 }
470 catch( ... )
471 {
472 DisplayErrorMessage( nullptr,
473 _( "Error loading project design block library table." ) );
474 }
475 }
476
477 return tbl;
478}
479
480
482{
483 m_project_lock.reset( aLockFile );
484}
485
486
488{
489 return m_project_lock.get();
490}
PROJECT::ELEM ProjectElementType() override
static DESIGN_BLOCK_LIB_TABLE & GetGlobalLibTable()
PROJECT::ELEM ProjectElementType() override
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
virtual bool SaveToFile(const wxString &aDirectory="", bool aForce=false)
Calls Store() and then writes the contents of the JSON document to a file.
static wxString GetCurrentHash(const wxString &aProjectFile, bool aShort)
Return the current HEAD commit hash for the repository containing aProjectFile.
Definition kiid.h:49
wxString AsString() const
Definition kiid.cpp:246
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:286
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition kiway.cpp:198
@ FACE_PCB
pcbnew DSO
Definition kiway.h:294
void Load(const wxString &aFileName)
Load the library table using the path defined by aFileName aFallBackTable.
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:576
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:125
A PROJECT can hold stuff it knows nothing about, in the form of _ELEM derivatives.
Definition project.h:97
std::map< wxString, wxString > m_TextVars
PROJECT_FILE * m_projectFile
Backing store for project data – owned by SETTINGS_MANAGER.
Definition project.h:362
void SetProjectLock(LOCKFILE *aLockFile)
Definition project.cpp:481
LOCKFILE * GetProjectLock() const
Definition project.cpp:487
@ SYMBOL_LIB
Definition project.h:194
@ DESIGN_BLOCK_LIB
Definition project.h:196
@ FOOTPRINT_LIB
Definition project.h:195
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition project.cpp:156
virtual void SetElem(PROJECT::ELEM aIndex, _ELEM *aElem)
Definition project.cpp:375
virtual const wxString DesignBlockLibTblName() const
Return the path and file name of this projects design block library table.
Definition project.cpp:198
void PinLibrary(const wxString &aLibrary, enum LIB_TYPE_T aLibType)
Definition project.cpp:204
RSTRING_T
Retain a number of project specific wxStrings, enumerated here:
Definition project.h:218
std::map< KIID, wxString > m_sheetNames
Definition project.h:367
std::unique_ptr< LOCKFILE > m_project_lock
Lock.
Definition project.h:376
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:162
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition project.cpp:174
int m_netclassesTicker
Update counter on netclasses.
Definition project.h:359
virtual const wxString SymbolLibTableName() const
Return the path and file name of this projects symbol library table.
Definition project.cpp:186
virtual _ELEM * GetElem(PROJECT::ELEM aIndex)
Get and set the elements for this project.
Definition project.cpp:364
virtual DESIGN_BLOCK_LIB_TABLE * DesignBlockLibs()
Return the table of design block libraries.
Definition project.cpp:445
virtual ~PROJECT()
Definition project.cpp:73
virtual FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition project.cpp:405
virtual void ApplyTextVars(const std::map< wxString, wxString > &aVarsMap)
Applies the given var map, it will create or update existing vars.
Definition project.cpp:117
virtual bool TextVarResolver(wxString *aToken) const
Definition project.cpp:79
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:204
virtual const wxString GetSheetName(const KIID &aSheetID)
Return the name of the sheet identified by the given UUID.
Definition project.cpp:319
std::array< _ELEM *, static_cast< unsigned int >(PROJECT::ELEM::COUNT)> m_elems
Definition project.h:373
virtual void elemsClear()
Delete all the _ELEMs and set their pointers to NULL.
Definition project.cpp:62
virtual const wxString FootprintLibTblName() const
Returns the path and filename of this project's footprint library table.
Definition project.cpp:192
virtual void SetRString(RSTRING_T aStringId, const wxString &aString)
Store a "retained string", which is any session and project specific string identified in enum RSTRIN...
Definition project.cpp:334
wxFileName m_project_name
<fullpath>/<basename>.pro
Definition project.h:355
void Clear()
Clear the _ELEMs and RSTRINGs.
Definition project.h:275
PROJECT_LOCAL_SETTINGS * m_localSettings
Backing store for project local settings – owned by SETTINGS_MANAGER.
Definition project.h:365
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Definition project.cpp:386
int m_textVarsTicker
Update counter on text vars.
Definition project.h:358
void UnpinLibrary(const wxString &aLibrary, enum LIB_TYPE_T aLibType)
Definition project.cpp:241
std::array< wxString, RSTRING_COUNT > m_rstrings
Definition project.h:370
const wxString libTableName(const wxString &aLibTableName) const
Return the full path and file name of the project specific library table aLibTableName.
Definition project.cpp:274
virtual void setProjectFullName(const wxString &aFullPathAndName)
Set the full directory, basename, and extension of the project.
Definition project.cpp:132
bool m_readOnly
No project files will be written to disk.
Definition project.h:357
virtual const wxString GetProjectDirectory() const
Return the full path of the project DIRECTORY.
Definition project.cpp:168
virtual std::map< wxString, wxString > & GetTextVars() const
Definition project.cpp:111
PROJECT()
Definition project.cpp:51
virtual const wxString & GetRString(RSTRING_T aStringId)
Return a "retained string", which is any session and project specific string identified in enum RSTRI...
Definition project.cpp:345
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition project.cpp:180
ELEM
The set of #_ELEMs that a PROJECT can hold.
Definition project.h:71
@ DESIGN_BLOCK_LIB_TABLE
Definition project.h:80
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Save a loaded project.
static wxString GetCurrentDate()
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:194
This file is part of the common library.
#define _(s)
static const std::string SymbolLibraryTableFileName
static const std::string ProjectFileExtension
static const std::string DesignBlockLibraryTableFileName
static const std::string FootprintLibraryTableFileName
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
@ KIFACE_NEW_FOOTPRINT_TABLE
Return a new FP_LIB_TABLE with the global table installed as a fallback.
Definition kiface_ids.h:46
File locking utilities.
This file contains miscellaneous commonly used macros and functions.
wxString GetUserConfigPath()
Retrieves the operating system specific path for a user's configuration store.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:100
SETTINGS_MANAGER * GetSettingsManager()
PGM_BASE & Pgm()
The global program "get" accessor.
Definition pgm_base.cpp:913
see class PGM_BASE
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
std::vector< wxString > pinned_design_block_libs
std::vector< wxString > pinned_fp_libs
std::vector< wxString > pinned_symbol_libs
Implement a participant in the KIWAY alchemy.
Definition kiway.h:153
IFACE KIFACE_BASE kiface("pcb_test_frame", KIWAY::FACE_PCB)
wxLogTrace helper definitions.
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:39