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
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
24
25#include <font/fontconfig.h>
26#include <lib_symbol.h>
27#include <progress_reporter.h>
28#include <sch_screen.h>
29#include <sch_sheet.h>
30#include <schematic.h>
31#include <wx_filename.h>
32#include <reporter.h>
33#include <wx/dir.h>
34#include <wx/wfstream.h>
35#include <wx/txtstrm.h>
36
37
38bool SCH_IO_CADSTAR_ARCHIVE::CanReadLibrary( const wxString& aFileName ) const
39{
40 if( !SCH_IO::CanReadLibrary( aFileName ) )
41 return false;
42
43 try
44 {
46 return p.CheckFileHeader( aFileName.utf8_string() );
47 }
48 catch( const std::runtime_error& )
49 {
50 }
51
52 return false;
53}
54
55
57{
58 return 0;
59}
60
61
63 SCHEMATIC* aSchematic,
64 SCH_SHEET* aAppendToMe,
65 const std::map<std::string, UTF8>* aProperties )
66{
67 wxCHECK( !aFileName.IsEmpty() && aSchematic, nullptr );
68
69 // Collect the font substitution warnings (RAII - automatically reset on scope exit)
71
72 SCH_SHEET* rootSheet = nullptr;
73
74
75 if( aAppendToMe )
76 {
77 wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
78 rootSheet = aAppendToMe;
79 }
80 else
81 {
82 rootSheet = new SCH_SHEET( aSchematic );
83 rootSheet->SetFileName( aFileName );
84 aSchematic->SetTopLevelSheets( { rootSheet } );
85 }
86
87 if( !rootSheet->GetScreen() )
88 {
89 SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
90 screen->SetFileName( aFileName );
91 rootSheet->SetScreen( screen );
92
93 // Virtual root sheet UUID must be the same as the schematic file UUID.
94 const_cast<KIID&>( rootSheet->m_Uuid ) = screen->GetUuid();
95 }
96
98 csaLoader.Load( aSchematic, rootSheet );
99
100 // Loading a schematic must not write to disk, so the project library is left to the reconciler
101 wxFileName prj_fn = aSchematic->Project().GetProjectFullName();
102 wxString libName = CADSTAR_SCH_ARCHIVE_LOADER::CreateLibName( prj_fn, nullptr );
103
104 m_importedLibSymbols.clear();
105
106 for( LIB_SYMBOL* symbol : csaLoader.GetLoadedSymbols() )
107 {
108 if( symbol )
109 m_importedLibSymbols.emplace_back( std::make_unique<LIB_SYMBOL>( *symbol ) );
110 }
111
112 // Legacy IDs carry no nickname, so give the reconciler a stable one to key the lookup on
113 for( SCH_SHEET_PATH& sheet : aSchematic->Hierarchy() )
114 {
115 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
116 {
117 SCH_SYMBOL* sym = static_cast<SCH_SYMBOL*>( item );
118
119 if( sym->GetLibId().IsLegacy() )
120 {
121 LIB_ID libid = sym->GetLibId();
122 libid.SetLibNickname( libName );
123 sym->SetLibId( libid );
124 }
125 };
126 }
127
128 // Need to fix up junctions after import to retain connectivity
129 aSchematic->FixupJunctionsAfterImport();
130
131 return rootSheet;
132}
133
134
136{
137 std::vector<LIB_SYMBOL*> result;
138
139 result.reserve( m_importedLibSymbols.size() );
140
141 for( const std::unique_ptr<LIB_SYMBOL>& symbol : m_importedLibSymbols )
142 result.push_back( new LIB_SYMBOL( *symbol ) );
143
144 return result;
145}
146
147
148void SCH_IO_CADSTAR_ARCHIVE::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
149 const wxString& aLibraryPath,
150 const std::map<std::string, UTF8>* aProperties )
151{
152 ensureLoadedLibrary( aLibraryPath, aProperties );
153
154 for( auto& [libnameStr, libSymbol] : m_libCache )
155 aSymbolNameList.Add( libSymbol->GetName() );
156}
157
158
159void SCH_IO_CADSTAR_ARCHIVE::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
160 const wxString& aLibraryPath,
161 const std::map<std::string, UTF8>* aProperties )
162{
163 ensureLoadedLibrary( aLibraryPath, aProperties );
164
165 for( auto& [libnameStr, libSymbol] : m_libCache )
166 aSymbolList.push_back( libSymbol.get() );
167}
168
169
170LIB_SYMBOL* SCH_IO_CADSTAR_ARCHIVE::LoadSymbol( const wxString& aLibraryPath,
171 const wxString& aAliasName,
172 const std::map<std::string, UTF8>* aProperties )
173{
174 ensureLoadedLibrary( aLibraryPath, aProperties );
175
176 if( m_libCache.count( aAliasName ) )
177 return m_libCache.at( aAliasName ).get();
178
179 return nullptr;
180}
181
182
183void SCH_IO_CADSTAR_ARCHIVE::GetAvailableSymbolFields( std::vector<wxString>& aNames )
184{
185 std::set<wxString> fieldNames;
186
187 for( auto& [libnameStr, libSymbol] : m_libCache )
188 {
189 std::vector<SCH_FIELD*> fields;
190 libSymbol->GetFields( fields );
191
192 for( SCH_FIELD* field : fields )
193 {
194 if( field->IsMandatory() )
195 continue;
196
197 fieldNames.insert( field->GetName() );
198 }
199 }
200
201 std::copy( fieldNames.begin(), fieldNames.end(), std::back_inserter( aNames ) );
202}
203
204
205void SCH_IO_CADSTAR_ARCHIVE::GetLibraryOptions( std::map<std::string, UTF8>* aListToAppendTo ) const
206{
207 ( *aListToAppendTo )["csa"] =
208 UTF8( _( "Path to the CADSTAR schematic archive (*.csa) file related to this CADSTAR "
209 "parts library. If none specified it is assumed to be 'symbol.csa' in the "
210 "same folder." ) );
211
212 ( *aListToAppendTo )["fplib"] =
213 UTF8( _( "Name of the footprint library related to the symbols in this library. You "
214 "should create a separate entry for the CADSTAR PCB Archive (*.cpa) file in "
215 "the footprint library tables. If none specified, 'cadstarpcblib' is assumed." ) );
216}
217
218
219void SCH_IO_CADSTAR_ARCHIVE::ensureLoadedLibrary( const wxString& aLibraryPath,
220 const std::map<std::string, UTF8>* aProperties )
221{
222 wxFileName csafn;
223 wxString fplibname = "cadstarpcblib";
224
225 // Suppress font substitution warnings (RAII - automatically restored on scope exit)
226 FONTCONFIG_REPORTER_SCOPE fontconfigScope( nullptr );
227
228 if( aProperties && aProperties->contains( "csa" ) )
229 {
230 csafn = wxFileName( aProperties->at( "csa" ) );
231
232 if( !csafn.IsAbsolute() )
233 {
234 wxFileName libDir( aLibraryPath );
235 libDir.ClearExt();
236 libDir.SetName( "" );
237 // wxPATH_NORM_ALL is deprecated in wxWidgets 3.1, so use our flags
238 csafn.Normalize( FN_NORMALIZE_FLAGS, libDir.GetAbsolutePath() );
239 }
240 }
241 else
242 {
243 // If none specified, look for the
244 // .csa file in same folder as the .lib
245 csafn = wxFileName( aLibraryPath );
246 csafn.SetExt( "csa" );
247
248 if( !csafn.FileExists() )
249 {
250 csafn.SetName( "symbol" );
251
252 if( !csafn.FileExists() )
253 {
254 csafn = wxDir::FindFirst( csafn.GetPath(), wxS( "*.csa" ), wxDIR_FILES | wxDIR_HIDDEN );
255
256 if( !csafn.FileExists() )
257 THROW_IO_ERRORF( _( "Cannot find the .csa file corresponding to library '%s'." ), aLibraryPath );
258 }
259 }
260 }
261
262 if( aProperties && aProperties->contains( "fplib" ) )
263 fplibname = wxString::FromUTF8( aProperties->at( "fplib" ) );
264
265 // Get timestamp
266 long long timestamp = 0;
267 wxFileName fn( aLibraryPath );
268
269 if( fn.IsFileReadable() && fn.GetModificationTime().IsValid() )
270 timestamp = fn.GetModificationTime().GetValue().GetValue();
271
272 if( fn.IsFileReadable()
273 && m_cachePath == aLibraryPath
274 && m_cachecsafn.GetFullPath() == csafn.GetFullPath()
275 && m_cachefplibname == fplibname
276 && m_cacheTimestamp == timestamp )
277 {
278 return;
279 }
280
281 // Update cache
282 m_libCache.clear();
283
284 CADSTAR_SCH_ARCHIVE_LOADER csaLoader( csafn.GetFullPath(), m_reporter, m_progressReporter );
285 csaLoader.SetFpLibName( fplibname );
286
287 std::vector<LIB_SYMBOL*> symbols = csaLoader.LoadPartsLib( aLibraryPath );
288
289 for( LIB_SYMBOL* sym : symbols )
290 {
291 m_libCache.insert( { sym->GetName(), std::unique_ptr<LIB_SYMBOL>( sym ) } );
292 }
293
294 m_cachePath = aLibraryPath;
295 m_cachecsafn = csafn;
296 m_cachefplibname = fplibname;
297 m_cacheTimestamp = timestamp;
298}
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:531
RAII class to set and restore the fontconfig reporter.
Definition reporter.h:368
REPORTER * m_reporter
Reporter to log errors/warnings to, may be nullptr.
Definition io_base.h:238
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
Definition io_base.h:241
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:46
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:113
bool IsLegacy() const
Definition lib_id.h:176
Define a library symbol object.
Definition lib_symbol.h:114
static LOAD_INFO_REPORTER & GetInstance()
Definition reporter.cpp:306
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition project.cpp:177
Holds all the data relating to one schematic.
Definition schematic.h:90
int FixupJunctionsAfterImport()
Add junctions to this schematic where required.
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:105
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition schematic.h:174
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)
std::vector< LIB_SYMBOL * > GetImportedCachedLibrarySymbols() override
Return the canonical symbol definitions produced by the last LoadSchematicFile().
void GetAvailableSymbolFields(std::vector< wxString > &aNames) override
Retrieves a list of (custom) field names that are present on symbols in this library.
std::vector< std::unique_ptr< LIB_SYMBOL > > m_importedLibSymbols
Definitions from the last LoadSchematicFile, cloned out to the import reconciler on request.
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.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:162
const KIID & GetUuid() const
Definition sch_screen.h:529
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:44
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:376
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:139
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Schematic symbol object.
Definition sch_symbol.h:69
void SetLibId(const LIB_ID &aName)
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:158
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition utf8.h:67
#define _(s)
#define THROW_IO_ERRORF(msg,...)
wxString result
Test unit parsing edge cases and error handling.
@ SCH_SYMBOL_T
Definition typeinfo.h:169
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:35