KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_io_cadstar_archive.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) 2020 Roberto Fernandez Bautista <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
24
25#include <font/fontconfig.h>
26#include <lib_symbol.h>
27#include <progress_reporter.h>
28#include <project_sch.h>
29#include <sch_screen.h>
30#include <sch_sheet.h>
31#include <schematic.h>
34#include <wx_filename.h>
37#include <reporter.h>
38#include <wx/dir.h>
39#include <wx/wfstream.h>
40#include <wx/txtstrm.h>
41
42
43bool SCH_IO_CADSTAR_ARCHIVE::CanReadLibrary( const wxString& aFileName ) const
44{
45 if( !SCH_IO::CanReadLibrary( aFileName ) )
46 return false;
47
48 try
49 {
51 return p.CheckFileHeader( aFileName.utf8_string() );
52 }
53 catch( const std::runtime_error& )
54 {
55 }
56
57 return false;
58}
59
60
62{
63 return 0;
64}
65
66
68 SCHEMATIC* aSchematic,
69 SCH_SHEET* aAppendToMe,
70 const std::map<std::string, UTF8>* aProperties )
71{
72 wxCHECK( !aFileName.IsEmpty() && aSchematic, nullptr );
73
74 // Collect the font substitution warnings (RAII - automatically reset on scope exit)
76
77 SCH_SHEET* rootSheet = nullptr;
78
79
80 if( aAppendToMe )
81 {
82 wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
83 rootSheet = aAppendToMe;
84 }
85 else
86 {
87 rootSheet = new SCH_SHEET( aSchematic );
88 rootSheet->SetFileName( aFileName );
89 aSchematic->SetTopLevelSheets( { rootSheet } );
90 }
91
92 if( !rootSheet->GetScreen() )
93 {
94 SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
95 screen->SetFileName( aFileName );
96 rootSheet->SetScreen( screen );
97
98 // Virtual root sheet UUID must be the same as the schematic file UUID.
99 const_cast<KIID&>( rootSheet->m_Uuid ) = screen->GetUuid();
100 }
101
103 csaLoader.Load( aSchematic, rootSheet );
104
105 // Save symbols to project library
107 LIBRARY_TABLE* table = adapter->ProjectTable().value_or( nullptr );
108 wxCHECK_MSG( table, nullptr, "Could not load symbol lib table." );
109
110 wxFileName prj_fn = aSchematic->Project().GetProjectFullName();
111 wxString libName = CADSTAR_SCH_ARCHIVE_LOADER::CreateLibName( prj_fn, nullptr );
112
113 wxFileName libFileName( aSchematic->Project().GetProjectPath(), libName,
115
116 IO_RELEASER<SCH_IO> sch_plugin( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
117
118 if( !table->HasRow( libName ) )
119 {
120 // Create a new empty symbol library.
121 sch_plugin->CreateLibrary( libFileName.GetFullPath() );
122 wxString libTableUri = "${KIPRJMOD}/" + libFileName.GetFullName();
123
124 // Add the new library to the project symbol library table.
125 LIBRARY_TABLE_ROW& row = table->InsertRow();
126 row.SetNickname( libName );
127 row.SetURI( libTableUri );
128 row.SetType( "KiCad" );
129
130 table->Save();
131
132 adapter->LoadOne( libName );
133 }
134
135 // set properties to prevent save file on every symbol save
136 std::map<std::string, UTF8> properties;
137 properties.emplace( SCH_IO_KICAD_SEXPR::PropBuffering, "" );
138
139 for( LIB_SYMBOL* const& symbol : csaLoader.GetLoadedSymbols() )
140 sch_plugin->SaveSymbol( libFileName.GetFullPath(), symbol, &properties );
141
142 sch_plugin->SaveLibrary( libFileName.GetFullPath() );
143
144 // Link up all symbols in the design to the newly created library
145 for( SCH_SHEET_PATH& sheet : aSchematic->Hierarchy() )
146 {
147 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
148 {
149 SCH_SYMBOL* sym = static_cast<SCH_SYMBOL*>( item );
150
151 if( sym->GetLibId().IsLegacy() )
152 {
153 LIB_ID libid = sym->GetLibId();
154 libid.SetLibNickname( libName );
155 sym->SetLibId( libid );
156 }
157 };
158 }
159
160 // Need to fix up junctions after import to retain connectivity
161 aSchematic->FixupJunctionsAfterImport();
162
163 return rootSheet;
164}
165
166
167void SCH_IO_CADSTAR_ARCHIVE::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
168 const wxString& aLibraryPath,
169 const std::map<std::string, UTF8>* aProperties )
170{
171 ensureLoadedLibrary( aLibraryPath, aProperties );
172
173 for( auto& [libnameStr, libSymbol] : m_libCache )
174 aSymbolNameList.Add( libSymbol->GetName() );
175}
176
177
178void SCH_IO_CADSTAR_ARCHIVE::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
179 const wxString& aLibraryPath,
180 const std::map<std::string, UTF8>* aProperties )
181{
182 ensureLoadedLibrary( aLibraryPath, aProperties );
183
184 for( auto& [libnameStr, libSymbol] : m_libCache )
185 aSymbolList.push_back( libSymbol.get() );
186}
187
188
189LIB_SYMBOL* SCH_IO_CADSTAR_ARCHIVE::LoadSymbol( const wxString& aLibraryPath,
190 const wxString& aAliasName,
191 const std::map<std::string, UTF8>* aProperties )
192{
193 ensureLoadedLibrary( aLibraryPath, aProperties );
194
195 if( m_libCache.count( aAliasName ) )
196 return m_libCache.at( aAliasName ).get();
197
198 return nullptr;
199}
200
201
202void SCH_IO_CADSTAR_ARCHIVE::GetAvailableSymbolFields( std::vector<wxString>& aNames )
203{
204 std::set<wxString> fieldNames;
205
206 for( auto& [libnameStr, libSymbol] : m_libCache )
207 {
208 std::vector<SCH_FIELD*> fields;
209 libSymbol->GetFields( fields );
210
211 for( SCH_FIELD* field : fields )
212 {
213 if( field->IsMandatory() )
214 continue;
215
216 fieldNames.insert( field->GetName() );
217 }
218 }
219
220 std::copy( fieldNames.begin(), fieldNames.end(), std::back_inserter( aNames ) );
221}
222
223
224void SCH_IO_CADSTAR_ARCHIVE::GetLibraryOptions( std::map<std::string, UTF8>* aListToAppendTo ) const
225{
226 ( *aListToAppendTo )["csa"] =
227 UTF8( _( "Path to the CADSTAR schematic archive (*.csa) file related to this CADSTAR "
228 "parts library. If none specified it is assumed to be 'symbol.csa' in the "
229 "same folder." ) );
230
231 ( *aListToAppendTo )["fplib"] =
232 UTF8( _( "Name of the footprint library related to the symbols in this library. You "
233 "should create a separate entry for the CADSTAR PCB Archive (*.cpa) file in "
234 "the footprint library tables. If none specified, 'cadstarpcblib' is assumed." ) );
235}
236
237
238void SCH_IO_CADSTAR_ARCHIVE::ensureLoadedLibrary( const wxString& aLibraryPath,
239 const std::map<std::string, UTF8>* aProperties )
240{
241 wxFileName csafn;
242 wxString fplibname = "cadstarpcblib";
243
244 // Suppress font substitution warnings (RAII - automatically restored on scope exit)
245 FONTCONFIG_REPORTER_SCOPE fontconfigScope( nullptr );
246
247 if( aProperties && aProperties->contains( "csa" ) )
248 {
249 csafn = wxFileName( aProperties->at( "csa" ) );
250
251 if( !csafn.IsAbsolute() )
252 {
253 wxFileName libDir( aLibraryPath );
254 libDir.ClearExt();
255 libDir.SetName( "" );
256 // wxPATH_NORM_ALL is deprecated in wxWidgets 3.1, so use our flags
257 csafn.Normalize( FN_NORMALIZE_FLAGS, libDir.GetAbsolutePath() );
258 }
259 }
260 else
261 {
262 // If none specified, look for the
263 // .csa file in same folder as the .lib
264 csafn = wxFileName( aLibraryPath );
265 csafn.SetExt( "csa" );
266
267 if( !csafn.FileExists() )
268 {
269 csafn.SetName( "symbol" );
270
271 if( !csafn.FileExists() )
272 {
273 csafn = wxDir::FindFirst( csafn.GetPath(), wxS( "*.csa" ),
274 wxDIR_FILES | wxDIR_HIDDEN );
275
276 if( !csafn.FileExists() )
277 {
278 THROW_IO_ERROR( wxString::Format(
279 _( "Cannot find the .csa file corresponding to library '%s'." ),
280 aLibraryPath ) );
281 }
282 }
283 }
284 }
285
286 if( aProperties && aProperties->contains( "fplib" ) )
287 {
288 fplibname = wxString::FromUTF8( aProperties->at( "fplib" ) );
289 }
290
291 // Get timestamp
292 long long timestamp = 0;
293 wxFileName fn( aLibraryPath );
294
295 if( fn.IsFileReadable() && fn.GetModificationTime().IsValid() )
296 timestamp = fn.GetModificationTime().GetValue().GetValue();
297
298 if( fn.IsFileReadable()
299 && m_cachePath == aLibraryPath
300 && m_cachecsafn.GetFullPath() == csafn.GetFullPath()
301 && m_cachefplibname == fplibname
302 && m_cacheTimestamp == timestamp )
303 {
304 return;
305 }
306
307 // Update cache
308 m_libCache.clear();
309
310 CADSTAR_SCH_ARCHIVE_LOADER csaLoader( csafn.GetFullPath(), m_reporter, m_progressReporter );
311 csaLoader.SetFpLibName( fplibname );
312
313 std::vector<LIB_SYMBOL*> symbols = csaLoader.LoadPartsLib( aLibraryPath );
314
315 for( LIB_SYMBOL* sym : symbols )
316 {
317 m_libCache.insert( { sym->GetName(), std::unique_ptr<LIB_SYMBOL>( sym ) } );
318 }
319
320 m_cachePath = aLibraryPath;
321 m_cachecsafn = csafn;
322 m_cachefplibname = fplibname;
323 m_cacheTimestamp = timestamp;
324}
Loads a csa file into a KiCad SCHEMATIC object.
bool CheckFileHeader(const std::filesystem::path &aPath) const
const std::vector< LIB_SYMBOL * > & GetLoadedSymbols() const
void Load(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet)
Loads a CADSTAR Schematic Archive file into the KiCad SCHEMATIC object given.
static wxString CreateLibName(const wxFileName &aFileName, const SCH_SHEET *aRootSheet)
std::vector< LIB_SYMBOL * > LoadPartsLib(const wxString &aFilename)
void SetFpLibName(const wxString &aLibName)
const KIID m_Uuid
Definition eda_item.h:522
RAII class to set and restore the fontconfig reporter.
Definition reporter.h:322
REPORTER * m_reporter
Reporter to log errors/warnings to, may be nullptr.
Definition io_base.h:237
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
Definition io_base.h:240
virtual bool CanReadLibrary(const wxString &aFileName) const
Checks if this IO object can read the specified library file/directory.
Definition io_base.cpp:71
Definition kiid.h:49
std::optional< LIBRARY_TABLE * > ProjectTable() const
Retrieves the project library table for this adapter type, or nullopt if one doesn't exist.
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
void SetURI(const wxString &aUri)
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:100
bool IsLegacy() const
Definition lib_id.h:180
Define a library symbol object.
Definition lib_symbol.h:83
static LOAD_INFO_REPORTER & GetInstance()
Definition reporter.cpp:218
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition project.cpp:161
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:167
Holds all the data relating to one schematic.
Definition schematic.h:88
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
PROJECT & Project() const
Return a reference to the project this schematic is part of.
Definition schematic.h:103
void FixupJunctionsAfterImport()
Add junctions to this schematic where required.
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition schematic.h:172
void SetTopLevelSheets(const std::vector< SCH_SHEET * > &aSheets)
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
int GetModifyHash() const override
Return the modification hash from the library cache.
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
void ensureLoadedLibrary(const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties)
void GetAvailableSymbolFields(std::vector< wxString > &aNames) override
Retrieves a list of (custom) field names that are present on symbols in this library.
void GetLibraryOptions(std::map< std::string, UTF8 > *aListToAppendTo) const override
Append supported SCH_IO options to aListToAppenTo along with internationalized descriptions.
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
static const char * PropBuffering
The property used internally by the plugin to enable cache buffering which prevents the library file ...
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:167
const KIID & GetUuid() const
Definition sch_screen.h:531
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:382
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Schematic symbol object.
Definition sch_symbol.h:76
void SetLibId(const LIB_ID &aName)
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:165
An interface to the global shared library manager that is schematic-specific and linked to one projec...
std::optional< LIB_STATUS > LoadOne(LIB_DATA *aLib) override
Loads or reloads the given library, if it exists.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition utf8.h:71
#define _(s)
static const std::string KiCadSymbolLibFileExtension
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
@ SCH_SYMBOL_T
Definition typeinfo.h:176
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:39