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 <string_utils.h>
34#include <kiface_ids.h>
35#include <kiway.h>
38#include <lockfile.h>
39#include <macros.h>
41#include <git2.h>
42#include <project.h>
43
45
47#include <trace_helpers.h>
51#include <title_block.h>
52#include <local_history.h>
53
54
55
57 m_readOnly( false ),
60 m_projectFile( nullptr ),
61 m_localSettings( nullptr )
62{
63 m_elems.fill( nullptr );
64}
65
66
68{
69 // careful here, this should work, but the virtual destructor may not
70 // be in the same link image as PROJECT.
71 for( unsigned i = 0; i < m_elems.size(); ++i )
72 {
73 SetElem( static_cast<PROJECT::ELEM>( i ), nullptr );
74 }
75}
76
77
82
83
84bool PROJECT::TextVarResolver( wxString* aToken ) const
85{
86 if( aToken->IsSameAs( wxT( "PROJECTNAME" ) ) )
87 {
88 *aToken = GetProjectName();
89 return true;
90 }
91 else if( aToken->IsSameAs( wxT( "CURRENT_DATE" ) ) )
92 {
94 return true;
95 }
96 else if( aToken->IsSameAs( wxT( "VCSHASH" ) ) )
97 {
99 return true;
100 }
101 else if( aToken->IsSameAs( wxT( "VCSSHORTHASH" ) ) )
102 {
104 return true;
105 }
106 else if( GetTextVars().count( *aToken ) > 0 )
107 {
108 *aToken = GetTextVars().at( *aToken );
109 return true;
110 }
111
112 return false;
113}
114
115
116std::map<wxString, wxString>& PROJECT::GetTextVars() const
117{
118 return GetProjectFile().m_TextVars;
119}
120
121
122void PROJECT::ApplyTextVars( const std::map<wxString, wxString>& aVarsMap )
123{
124 if( aVarsMap.size() == 0 )
125 return;
126
127 std::map<wxString, wxString>& existingVarsMap = GetTextVars();
128
129 for( const auto& var : aVarsMap )
130 {
131 // create or update the existing vars
132 existingVarsMap[var.first] = var.second;
133 }
134}
135
136
137void PROJECT::setProjectFullName( const wxString& aFullPathAndName )
138{
139 // Compare paths, rather than inodes, to be less surprising to the user.
140 // Create a temporary wxFileName to normalize the path
141 wxFileName candidate_path( aFullPathAndName );
142
143 // Edge transitions only. This is what clears the project
144 // data using the Clear() function.
145 if( m_project_name.GetFullPath() != candidate_path.GetFullPath() )
146 {
147 Clear(); // clear the data when the project changes.
148
149 wxLogTrace( tracePathsAndFiles, "%s: old:'%s' new:'%s'", __func__,
150 TO_UTF8( GetProjectFullName() ), TO_UTF8( aFullPathAndName ) );
151
152 m_project_name = aFullPathAndName;
153
154 wxASSERT( m_project_name.IsAbsolute() );
155
156 wxASSERT( m_project_name.GetExt() == FILEEXT::ProjectFileExtension );
157 }
158}
159
160
161const wxString PROJECT::GetProjectFullName() const
162{
163 return m_project_name.GetFullPath();
164}
165
166
167const wxString PROJECT::GetProjectPath() const
168{
169 return m_project_name.GetPathWithSep();
170}
171
172
173const wxString PROJECT::GetProjectDirectory() const
174{
175 return m_project_name.GetPath();
176}
177
178
179const wxString PROJECT::GetProjectName() const
180{
181 return m_project_name.GetName();
182}
183
184
186{
187 return m_project_name.GetName().IsEmpty();
188}
189
190
195
196
201
202
207
208
209void PROJECT::PinLibrary( const wxString& aLibrary, enum LIB_TYPE_T aLibType )
210{
212 std::vector<wxString>* pinnedLibsCfg = nullptr;
213 std::vector<wxString>* pinnedLibsFile = nullptr;
214
215 switch( aLibType )
216 {
218 pinnedLibsFile = &m_projectFile->m_PinnedSymbolLibs;
219 pinnedLibsCfg = &cfg->m_Session.pinned_symbol_libs;
220 break;
222 pinnedLibsFile = &m_projectFile->m_PinnedFootprintLibs;
223 pinnedLibsCfg = &cfg->m_Session.pinned_fp_libs;
224 break;
226 pinnedLibsFile = &m_projectFile->m_PinnedDesignBlockLibs;
227 pinnedLibsCfg = &cfg->m_Session.pinned_design_block_libs;
228 break;
229 default:
230 wxFAIL_MSG( "Cannot pin library: invalid library type" );
231 return;
232 }
233
234 if( !alg::contains( *pinnedLibsFile, aLibrary ) )
235 pinnedLibsFile->push_back( aLibrary );
236
238
239 if( !alg::contains( *pinnedLibsCfg, aLibrary ) )
240 pinnedLibsCfg->push_back( aLibrary );
241
242 cfg->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( cfg ) );
243}
244
245
246void PROJECT::UnpinLibrary( const wxString& aLibrary, enum LIB_TYPE_T aLibType )
247{
249 std::vector<wxString>* pinnedLibsCfg = nullptr;
250 std::vector<wxString>* pinnedLibsFile = nullptr;
251
252 switch( aLibType )
253 {
255 pinnedLibsFile = &m_projectFile->m_PinnedSymbolLibs;
256 pinnedLibsCfg = &cfg->m_Session.pinned_symbol_libs;
257 break;
259 pinnedLibsFile = &m_projectFile->m_PinnedFootprintLibs;
260 pinnedLibsCfg = &cfg->m_Session.pinned_fp_libs;
261 break;
263 pinnedLibsFile = &m_projectFile->m_PinnedDesignBlockLibs;
264 pinnedLibsCfg = &cfg->m_Session.pinned_design_block_libs;
265 break;
266 default:
267 wxFAIL_MSG( "Cannot unpin library: invalid library type" );
268 return;
269 }
270
271 std::erase( *pinnedLibsFile, aLibrary );
273
274 std::erase( *pinnedLibsCfg, aLibrary );
275 cfg->SaveToFile( Pgm().GetSettingsManager().GetPathForSettingsFile( cfg ) );
276}
277
278
279const wxString PROJECT::libTableName( const wxString& aLibTableName ) const
280{
281 wxFileName fn = GetProjectFullName();
282 wxString path = fn.GetPath();
283
284 // if there's no path to the project name, or the name as a whole is bogus or its not
285 // write-able then use a template file.
286 if( !fn.GetDirCount() || !fn.IsOk() || !wxFileName::IsDirWritable( path ) )
287 {
288 // return a template filename now.
289
290 // this next line is likely a problem now, since it relies on an
291 // application title which is no longer constant or known. This next line needs
292 // to be re-thought out.
293
294#ifdef __WXMAC__
295 fn.AssignDir( KIPLATFORM::ENV::GetUserConfigPath() );
296#else
297 // don't pollute home folder, temp folder seems to be more appropriate
298 fn.AssignDir( wxStandardPaths::Get().GetTempDir() );
299#endif
300
301#if defined( __WINDOWS__ )
302 fn.AppendDir( wxT( "kicad" ) );
303#endif
304
305 /*
306 * The library table name used when no project file is passed to the appropriate
307 * code. This is used temporarily to store the project specific library table
308 * until the project file being edited is saved. It is then moved to the correct
309 * file in the folder where the project file is saved.
310 */
311 fn.SetName( wxS( "prj-" ) + aLibTableName );
312 }
313 else // normal path.
314 {
315 fn.SetName( aLibTableName );
316 }
317
318 fn.ClearExt();
319
320 return fn.GetFullPath();
321}
322
323
324const wxString PROJECT::GetSheetName( const KIID& aSheetID )
325{
326 if( m_sheetNames.empty() )
327 {
328 for( const std::pair<KIID, wxString>& pair : GetProjectFile().GetSheets() )
329 m_sheetNames[pair.first] = pair.second;
330 }
331
332 if( m_sheetNames.count( aSheetID ) )
333 return m_sheetNames.at( aSheetID );
334 else
335 return aSheetID.AsString();
336}
337
338
339void PROJECT::SetRString( RSTRING_T aIndex, const wxString& aString )
340{
341 unsigned ndx = unsigned( aIndex );
342
343 if( ndx < m_rstrings.size() )
344 m_rstrings[ndx] = aString;
345 else
346 wxASSERT( 0 ); // bad index
347}
348
349
350const wxString& PROJECT::GetRString( RSTRING_T aIndex )
351{
352 unsigned ndx = unsigned( aIndex );
353
354 if( ndx < m_rstrings.size() )
355 {
356 return m_rstrings[ndx];
357 }
358 else
359 {
360 static wxString no_cookie_for_you;
361
362 wxASSERT( 0 ); // bad index
363
364 return no_cookie_for_you;
365 }
366}
367
368
370{
371 // This is virtual, so implement it out of line
372
373 if( static_cast<unsigned>( aIndex ) < m_elems.size() )
374 return m_elems[static_cast<unsigned>( aIndex )];
375
376 return nullptr;
377}
378
379
381{
382 // This is virtual, so implement it out of line
383 if( static_cast<unsigned>( aIndex ) < m_elems.size() )
384 {
385 delete m_elems[static_cast<unsigned>(aIndex)];
386 m_elems[static_cast<unsigned>( aIndex )] = aElem;
387 }
388}
389
390
391const wxString PROJECT::AbsolutePath( const wxString& aFileName ) const
392{
393 wxFileName fn = aFileName;
394
395 // Paths which start with an unresolved variable reference are more likely to be
396 // absolute than relative.
397 if( aFileName.StartsWith( wxT( "${" ) ) )
398 return aFileName;
399
400 if( !fn.IsAbsolute() )
401 {
402 wxString pro_dir = wxPathOnly( GetProjectFullName() );
403 fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS, pro_dir );
404 }
405
406 return fn.GetFullPath();
407}
408
409
411{
413
414 if( adapter )
415 {
416 wxASSERT( adapter->ProjectElementType() == PROJECT::ELEM::FPTBL );
417 }
418 else
419 {
420 KIFACE* kiface = aKiway.KiFACE( KIWAY::FACE_PCB );
421 adapter = static_cast<FOOTPRINT_LIBRARY_ADAPTER*>( kiface->IfaceOrAddress( KIFACE_FOOTPRINT_LIBRARY_ADAPTER ) );
422 SetElem( ELEM::FPTBL, adapter );
423 }
424
425 return adapter;
426}
427
428
430{
431 std::scoped_lock lock( m_designBlockLibsMutex );
432
434 std::optional<LIBRARY_MANAGER_ADAPTER*> adapter = mgr.Adapter( LIBRARY_TABLE_TYPE::DESIGN_BLOCK );
435
436 if( !adapter )
437 {
439 std::make_unique<DESIGN_BLOCK_LIBRARY_ADAPTER>( mgr ) );
440
441 std::optional<LIBRARY_MANAGER_ADAPTER*> created = mgr.Adapter( LIBRARY_TABLE_TYPE::DESIGN_BLOCK );
442 wxCHECK( created && ( *created )->Type() == LIBRARY_TABLE_TYPE::DESIGN_BLOCK, nullptr );
443 return static_cast<DESIGN_BLOCK_LIBRARY_ADAPTER*>( *created );
444 }
445
446 wxCHECK( ( *adapter )->Type() == LIBRARY_TABLE_TYPE::DESIGN_BLOCK, nullptr );
447 return static_cast<DESIGN_BLOCK_LIBRARY_ADAPTER*>( *adapter );
448}
449
450
452{
453 return m_project_lock.get();
454}
455
456
458{
459 m_project_lock.reset( aLockFile );
460}
461
462
463void PROJECT::SaveToHistory( const wxString& aProjectPath, std::vector<wxString>& aFiles )
464{
465 wxString projectFile = GetProjectFullName();
466
467 if( projectFile.IsEmpty() )
468 return;
469
470 wxFileName projectFn( projectFile );
471 wxFileName requestedFn( aProjectPath );
472
473 if( !projectFn.Normalize( wxPATH_NORM_ALL ) || !requestedFn.Normalize( wxPATH_NORM_ALL ) )
474 return;
475
476 if( projectFn.GetFullPath() != requestedFn.GetFullPath() )
477 return;
478
479 wxFileName historyDir( projectFn.GetPath(), wxS( ".history" ) );
480
481 if( !historyDir.DirExists() )
482 {
483 if( !historyDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
484 return;
485 }
486
487 // Save project file (.kicad_pro)
488 wxFileName historyProFile( historyDir.GetFullPath(), projectFn.GetName(),
489 projectFn.GetExt() );
490 wxCopyFile( projectFile, historyProFile.GetFullPath(), true );
491 aFiles.push_back( historyProFile.GetFullPath() );
492
493 // Save project local settings (.kicad_prl) if it exists
494 wxFileName prlFile( projectFn.GetPath(), projectFn.GetName(), FILEEXT::ProjectLocalSettingsFileExtension );
495
496 if( prlFile.FileExists() )
497 {
498 wxFileName historyPrlFile( historyDir.GetFullPath(), prlFile.GetName(),
499 prlFile.GetExt() );
500 wxCopyFile( prlFile.GetFullPath(), historyPrlFile.GetFullPath(), true );
501 aFiles.push_back( historyPrlFile.GetFullPath() );
502 }
503}
An interface to the global shared library manager that is schematic-specific and linked to one projec...
PROJECT::ELEM ProjectElementType() override
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:292
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition kiway.cpp:206
@ FACE_PCB
pcbnew DSO
Definition kiway.h:300
std::optional< LIBRARY_MANAGER_ADAPTER * > Adapter(LIBRARY_TABLE_TYPE aType) const
void RegisterAdapter(LIBRARY_TABLE_TYPE aType, std::unique_ptr< LIBRARY_MANAGER_ADAPTER > &&aAdapter)
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:537
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:129
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:131
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:371
void SetProjectLock(LOCKFILE *aLockFile)
Definition project.cpp:457
LOCKFILE * GetProjectLock() const
Definition project.cpp:451
@ 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:161
virtual void SetElem(PROJECT::ELEM aIndex, _ELEM *aElem)
Definition project.cpp:380
virtual const wxString DesignBlockLibTblName() const
Return the path and file name of this projects design block library table.
Definition project.cpp:203
void PinLibrary(const wxString &aLibrary, enum LIB_TYPE_T aLibType)
Definition project.cpp:209
RSTRING_T
Retain a number of project specific wxStrings, enumerated here:
Definition project.h:218
std::map< KIID, wxString > m_sheetNames
Definition project.h:376
std::unique_ptr< LOCKFILE > m_project_lock
Lock.
Definition project.h:385
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:167
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition project.cpp:179
int m_netclassesTicker
Update counter on netclasses.
Definition project.h:368
virtual const wxString SymbolLibTableName() const
Return the path and file name of this projects symbol library table.
Definition project.cpp:191
virtual _ELEM * GetElem(PROJECT::ELEM aIndex)
Get and set the elements for this project.
Definition project.cpp:369
virtual ~PROJECT()
Definition project.cpp:78
void SaveToHistory(const wxString &aProjectPath, std::vector< wxString > &aFiles)
Save project files (.kicad_pro and .kicad_prl) to the .history directory.
Definition project.cpp:463
virtual void ApplyTextVars(const std::map< wxString, wxString > &aVarsMap)
Applies the given var map, it will create or update existing vars.
Definition project.cpp:122
virtual DESIGN_BLOCK_LIBRARY_ADAPTER * DesignBlockLibs()
Return the table of design block libraries.
Definition project.cpp:429
virtual bool TextVarResolver(wxString *aToken) const
Definition project.cpp:84
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:324
std::mutex m_designBlockLibsMutex
Synchronise access to DesignBlockLibs()
Definition project.h:388
std::array< _ELEM *, static_cast< unsigned int >(PROJECT::ELEM::COUNT)> m_elems
Definition project.h:382
virtual void elemsClear()
Delete all the _ELEMs and set their pointers to NULL.
Definition project.cpp:67
virtual const wxString FootprintLibTblName() const
Returns the path and filename of this project's footprint library table.
Definition project.cpp:197
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:339
wxFileName m_project_name
<fullpath>/<basename>.pro
Definition project.h:364
void Clear()
Clear the _ELEMs and RSTRINGs.
Definition project.h:275
virtual FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(KIWAY &aKiway)
Fetches the footprint library adapter from the PCB editor instance.
Definition project.cpp:410
PROJECT_LOCAL_SETTINGS * m_localSettings
Backing store for project local settings – owned by SETTINGS_MANAGER.
Definition project.h:374
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:391
int m_textVarsTicker
Update counter on text vars.
Definition project.h:367
void UnpinLibrary(const wxString &aLibrary, enum LIB_TYPE_T aLibType)
Definition project.cpp:246
std::array< wxString, RSTRING_COUNT > m_rstrings
Definition project.h:379
const wxString libTableName(const wxString &aLibTableName) const
Return the full path and file name of the project specific library table aLibTableName.
Definition project.cpp:279
virtual void setProjectFullName(const wxString &aFullPathAndName)
Set the full directory, basename, and extension of the project.
Definition project.cpp:137
bool m_readOnly
No project files will be written to disk.
Definition project.h:366
virtual const wxString GetProjectDirectory() const
Return the full path of the project DIRECTORY.
Definition project.cpp:173
virtual std::map< wxString, wxString > & GetTextVars() const
Definition project.cpp:116
PROJECT()
Definition project.cpp:56
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:350
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition project.cpp:185
ELEM
The set of #_ELEMs that a PROJECT can hold.
Definition project.h:71
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Save a loaded project.
static wxString GetCurrentDate()
This file is part of the common library.
static const std::string SymbolLibraryTableFileName
static const std::string ProjectFileExtension
static const std::string ProjectLocalSettingsFileExtension
static const std::string DesignBlockLibraryTableFileName
static const std::string FootprintLibraryTableFileName
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
@ KIFACE_FOOTPRINT_LIBRARY_ADAPTER
Definition kiface_ids.h:40
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:946
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:155
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