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 <wx/dir.h>
38#include <wx/wfstream.h>
39#include <wx/txtstrm.h>
40
41
42bool SCH_IO_CADSTAR_ARCHIVE::CanReadLibrary( const wxString& aFileName ) const
43{
44 if( !SCH_IO::CanReadLibrary( aFileName ) )
45 return false;
46
47 try
48 {
50 return p.CheckFileHeader( aFileName.utf8_string() );
51 }
52 catch( const std::runtime_error& )
53 {
54 }
55
56 return false;
57}
58
59
61{
62 return 0;
63}
64
65
67 SCHEMATIC* aSchematic,
68 SCH_SHEET* aAppendToMe,
69 const std::map<std::string, UTF8>* aProperties )
70{
71 wxCHECK( !aFileName.IsEmpty() && aSchematic, nullptr );
72
73 // Show the font substitution warnings
75
76 SCH_SHEET* rootSheet = nullptr;
77
78
79 if( aAppendToMe )
80 {
81 wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
82 rootSheet = &aSchematic->Root();
83 }
84 else
85 {
86 rootSheet = new SCH_SHEET( aSchematic );
87 rootSheet->SetFileName( aFileName );
88 aSchematic->SetRoot( rootSheet );
89 }
90
91 if( !rootSheet->GetScreen() )
92 {
93 SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
94 screen->SetFileName( aFileName );
95 rootSheet->SetScreen( screen );
96
97 // Virtual root sheet UUID must be the same as the schematic file UUID.
98 const_cast<KIID&>( rootSheet->m_Uuid ) = screen->GetUuid();
99 }
100
102 csaLoader.Load( aSchematic, rootSheet );
103
104 // Save symbols to project library
106 LIBRARY_TABLE* table = adapter->ProjectTable().value_or( nullptr );
107 wxCHECK_MSG( table, nullptr, "Could not load symbol lib table." );
108
109 wxFileName prj_fn = aSchematic->Project().GetProjectFullName();
110 wxString libName = CADSTAR_SCH_ARCHIVE_LOADER::CreateLibName( prj_fn, nullptr );
111
112 wxFileName libFileName( aSchematic->Project().GetProjectPath(), libName,
114
115 IO_RELEASER<SCH_IO> sch_plugin( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
116
117 if( !table->HasRow( libName ) )
118 {
119 // Create a new empty symbol library.
120 sch_plugin->CreateLibrary( libFileName.GetFullPath() );
121 wxString libTableUri = "${KIPRJMOD}/" + libFileName.GetFullName();
122
123 // Add the new library to the project symbol library table.
124 LIBRARY_TABLE_ROW& row = table->InsertRow();
125 row.SetNickname( libName );
126 row.SetURI( libTableUri );
127 row.SetType( "KiCad" );
128
129 table->Save();
130
131 adapter->LoadOne( libName );
132 }
133
134 // set properties to prevent save file on every symbol save
135 std::map<std::string, UTF8> properties;
136 properties.emplace( SCH_IO_KICAD_SEXPR::PropBuffering, "" );
137
138 for( LIB_SYMBOL* const& symbol : csaLoader.GetLoadedSymbols() )
139 sch_plugin->SaveSymbol( libFileName.GetFullPath(), symbol, &properties );
140
141 sch_plugin->SaveLibrary( libFileName.GetFullPath() );
142
143 // Link up all symbols in the design to the newly created library
144 for( SCH_SHEET_PATH& sheet : aSchematic->Hierarchy() )
145 {
146 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
147 {
148 SCH_SYMBOL* sym = static_cast<SCH_SYMBOL*>( item );
149
150 if( sym->GetLibId().IsLegacy() )
151 {
152 LIB_ID libid = sym->GetLibId();
153 libid.SetLibNickname( libName );
154 sym->SetLibId( libid );
155 }
156 };
157 }
158
159 // Need to fix up junctions after import to retain connectivity
160 aSchematic->FixupJunctionsAfterImport();
161
162 return rootSheet;
163}
164
165
166void SCH_IO_CADSTAR_ARCHIVE::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
167 const wxString& aLibraryPath,
168 const std::map<std::string, UTF8>* aProperties )
169{
170 ensureLoadedLibrary( aLibraryPath, aProperties );
171
172 for( auto& [libnameStr, libSymbol] : m_libCache )
173 aSymbolNameList.Add( libSymbol->GetName() );
174}
175
176
177void SCH_IO_CADSTAR_ARCHIVE::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
178 const wxString& aLibraryPath,
179 const std::map<std::string, UTF8>* aProperties )
180{
181 ensureLoadedLibrary( aLibraryPath, aProperties );
182
183 for( auto& [libnameStr, libSymbol] : m_libCache )
184 aSymbolList.push_back( libSymbol.get() );
185}
186
187
188LIB_SYMBOL* SCH_IO_CADSTAR_ARCHIVE::LoadSymbol( const wxString& aLibraryPath,
189 const wxString& aAliasName,
190 const std::map<std::string, UTF8>* aProperties )
191{
192 ensureLoadedLibrary( aLibraryPath, aProperties );
193
194 if( m_libCache.count( aAliasName ) )
195 return m_libCache.at( aAliasName ).get();
196
197 return nullptr;
198}
199
200
201void SCH_IO_CADSTAR_ARCHIVE::GetAvailableSymbolFields( std::vector<wxString>& aNames )
202{
203 std::set<wxString> fieldNames;
204
205 for( auto& [libnameStr, libSymbol] : m_libCache )
206 {
207 std::vector<SCH_FIELD*> fields;
208 libSymbol->GetFields( fields );
209
210 for( SCH_FIELD* field : fields )
211 {
212 if( field->IsMandatory() )
213 continue;
214
215 fieldNames.insert( field->GetName() );
216 }
217 }
218
219 std::copy( fieldNames.begin(), fieldNames.end(), std::back_inserter( aNames ) );
220}
221
222
223void SCH_IO_CADSTAR_ARCHIVE::GetLibraryOptions( std::map<std::string, UTF8>* aListToAppendTo ) const
224{
225 ( *aListToAppendTo )["csa"] =
226 UTF8( _( "Path to the CADSTAR schematic archive (*.csa) file related to this CADSTAR "
227 "parts library. If none specified it is assumed to be 'symbol.csa' in the "
228 "same folder." ) );
229
230 ( *aListToAppendTo )["fplib"] =
231 UTF8( _( "Name of the footprint library related to the symbols in this library. You "
232 "should create a separate entry for the CADSTAR PCB Archive (*.cpa) file in "
233 "the footprint library tables. If none specified, 'cadstarpcblib' is assumed." ) );
234}
235
236
237void SCH_IO_CADSTAR_ARCHIVE::ensureLoadedLibrary( const wxString& aLibraryPath,
238 const std::map<std::string, UTF8>* aProperties )
239{
240 wxFileName csafn;
241 wxString fplibname = "cadstarpcblib";
242
243 // Suppress font substitution warnings
245
246 if( aProperties && aProperties->contains( "csa" ) )
247 {
248 csafn = wxFileName( aProperties->at( "csa" ) );
249
250 if( !csafn.IsAbsolute() )
251 {
252 wxFileName libDir( aLibraryPath );
253 libDir.ClearExt();
254 libDir.SetName( "" );
255 // wxPATH_NORM_ALL is deprecated in wxWidgets 3.1, so use our flags
256 csafn.Normalize( FN_NORMALIZE_FLAGS, libDir.GetAbsolutePath() );
257 }
258 }
259 else
260 {
261 // If none specified, look for the
262 // .csa file in same folder as the .lib
263 csafn = wxFileName( aLibraryPath );
264 csafn.SetExt( "csa" );
265
266 if( !csafn.FileExists() )
267 {
268 csafn.SetName( "symbol" );
269
270 if( !csafn.FileExists() )
271 {
272 csafn = wxDir::FindFirst( csafn.GetPath(), wxS( "*.csa" ),
273 wxDIR_FILES | wxDIR_HIDDEN );
274
275 if( !csafn.FileExists() )
276 {
277 THROW_IO_ERROR( wxString::Format(
278 _( "Cannot find the .csa file corresponding to library '%s'." ),
279 aLibraryPath ) );
280 }
281 }
282 }
283 }
284
285 if( aProperties && aProperties->contains( "fplib" ) )
286 {
287 fplibname = wxString::FromUTF8( aProperties->at( "fplib" ) );
288 }
289
290 // Get timestamp
291 long long timestamp = 0;
292 wxFileName fn( aLibraryPath );
293
294 if( fn.IsFileReadable() && fn.GetModificationTime().IsValid() )
295 timestamp = fn.GetModificationTime().GetValue().GetValue();
296
297 if( fn.IsFileReadable()
298 && m_cachePath == aLibraryPath
299 && m_cachecsafn.GetFullPath() == csafn.GetFullPath()
300 && m_cachefplibname == fplibname
301 && m_cacheTimestamp == timestamp )
302 {
303 return;
304 }
305
306 // Update cache
307 m_libCache.clear();
308
309 CADSTAR_SCH_ARCHIVE_LOADER csaLoader( csafn.GetFullPath(), m_reporter, m_progressReporter );
310 csaLoader.SetFpLibName( fplibname );
311
312 std::vector<LIB_SYMBOL*> symbols = csaLoader.LoadPartsLib( aLibraryPath );
313
314 for( LIB_SYMBOL* sym : symbols )
315 {
316 m_libCache.insert( { sym->GetName(), std::unique_ptr<LIB_SYMBOL>( sym ) } );
317 }
318
319 m_cachePath = aLibraryPath;
320 m_cachecsafn = csafn;
321 m_cachefplibname = fplibname;
322 m_cacheTimestamp = timestamp;
323}
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:516
REPORTER * m_reporter
Reporter to log errors/warnings to, may be nullptr.
Definition io_base.h:235
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
Definition io_base.h:238
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:85
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.
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition schematic.h:171
SCH_SHEET & Root() const
Definition schematic.h:125
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:520
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:47
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:347
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:116
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(const wxString &aNickname)
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:72
static REPORTER & GetInstance()
Definition reporter.cpp:190
static void SetReporter(REPORTER *aReporter)
Set the reporter to use for reporting font substitution warnings.
#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