KiCad PCB EDA Suite
Loading...
Searching...
No Matches
cadstar_sch_archive_plugin.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 (C) 2020-2021 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
29
30#include <lib_symbol.h>
31#include <progress_reporter.h>
32#include <string_utf8_map.h>
33#include <sch_screen.h>
34#include <sch_sheet.h>
35#include <schematic.h>
38
39
41{
42 return wxT( "CADSTAR Schematic Archive" );
43}
44
45
47{
49}
50
51
53{
55}
56
57
59{
60 return 0;
61}
62
63
64SCH_SHEET* CADSTAR_SCH_ARCHIVE_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchematic,
65 SCH_SHEET* aAppendToMe, const STRING_UTF8_MAP* aProperties )
66{
67 wxCHECK( !aFileName.IsEmpty() && aSchematic, nullptr );
68
69 SCH_SHEET* rootSheet = nullptr;
70
71
72 if( aAppendToMe )
73 {
74 wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
75 rootSheet = &aSchematic->Root();
76 }
77 else
78 {
79 rootSheet = new SCH_SHEET( aSchematic );
80 rootSheet->SetFileName( aFileName );
81 aSchematic->SetRoot( rootSheet );
82 }
83
84 if( !rootSheet->GetScreen() )
85 {
86 SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
87 screen->SetFileName( aFileName );
88 rootSheet->SetScreen( screen );
89 }
90
92 csaLoader.Load( aSchematic, rootSheet );
93
94 // SAVE SYMBOLS TO PROJECT LIBRARY:
95 SYMBOL_LIB_TABLE* libTable = aSchematic->Prj().SchSymbolLibTable();
96
97 wxCHECK_MSG( libTable, nullptr, "Could not load symbol lib table." );
98
99 // Lets come up with a nice library name
100 wxString libName = aSchematic->Prj().GetProjectName();
101
102 if( libName.IsEmpty() )
103 {
104 wxFileName fn( rootSheet->GetFileName() );
105 libName = fn.GetName();
106 }
107
108 if( libName.IsEmpty() )
109 libName = "noname";
110
111 libName = LIB_ID::FixIllegalChars( libName, true );
112
113 wxFileName libFileName( aSchematic->Prj().GetProjectPath(), libName,
115
117 sch_plugin.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
118
119 if( !libTable->HasLibrary( libName ) )
120 {
121 // Create a new empty symbol library.
122 sch_plugin->CreateSymbolLib( libFileName.GetFullPath() );
123 wxString libTableUri = "${KIPRJMOD}/" + libFileName.GetFullName();
124
125 // Add the new library to the project symbol library table.
126 libTable->InsertRow(
127 new SYMBOL_LIB_TABLE_ROW( libName, libTableUri, wxString( "KiCad" ) ) );
128
129 // Save project symbol library table.
130 wxFileName fn( aSchematic->Prj().GetProjectPath(),
132
133 // So output formatter goes out of scope and closes the file before reloading.
134 {
135 FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
136 libTable->Format( &formatter, 0 );
137 }
138
139 // Relaod the symbol library table.
140 aSchematic->Prj().SetElem( PROJECT::ELEM_SYMBOL_LIB_TABLE, NULL );
141 aSchematic->Prj().SchSymbolLibTable();
142 }
143
144 // set properties to prevent save file on every symbol save
145 STRING_UTF8_MAP properties;
146 properties.emplace( SCH_SEXPR_PLUGIN::PropBuffering, "" );
147
148 for( LIB_SYMBOL* const& symbol : csaLoader.GetLoadedSymbols() )
149 sch_plugin->SaveSymbol( libFileName.GetFullPath(), symbol, &properties );
150
151 sch_plugin->SaveLibrary( libFileName.GetFullPath() );
152
153 // Link up all symbols in the design to the newly created library
154 for( SCH_SHEET_PATH& sheet : aSchematic->GetSheets() )
155 {
156 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
157 {
158 SCH_SYMBOL* sym = static_cast<SCH_SYMBOL*>( item );
159
160 if( sym->GetLibId().IsLegacy() )
161 {
162 LIB_ID libid = sym->GetLibId();
163 libid.SetLibNickname( libName );
164 sym->SetLibId( libid );
165 }
166 };
167 }
168
169 // Need to fix up junctions after import to retain connectivity
170 aSchematic->FixupJunctions();
171
172 return rootSheet;
173}
174
175
176bool CADSTAR_SCH_ARCHIVE_PLUGIN::CheckHeader( const wxString& aFileName )
177{
178 // TODO: write a parser for the cpa header. For now assume it is valid
179 // and throw exceptions when parsing
180 return true;
181}
182
183
184void CADSTAR_SCH_ARCHIVE_PLUGIN::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
185 const wxString& aLibraryPath,
186 const STRING_UTF8_MAP* aProperties )
187{
188 ensureLoadedLibrary( aLibraryPath, aProperties );
189
190 for( auto& [libnameStr, libSymbol] : m_libCache )
191 aSymbolNameList.Add( libSymbol->GetName() );
192}
193
194
195void CADSTAR_SCH_ARCHIVE_PLUGIN::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
196 const wxString& aLibraryPath,
197 const STRING_UTF8_MAP* aProperties )
198{
199 ensureLoadedLibrary( aLibraryPath, aProperties );
200
201 for( auto& [libnameStr, libSymbol] : m_libCache )
202 aSymbolList.push_back( libSymbol.get() );
203}
204
205
207 const wxString& aAliasName,
208 const STRING_UTF8_MAP* aProperties )
209{
210 ensureLoadedLibrary( aLibraryPath, aProperties );
211
212 if( m_libCache.count( aAliasName ) )
213 return m_libCache.at( aAliasName ).get();
214
215 return nullptr;
216}
217
218
219void CADSTAR_SCH_ARCHIVE_PLUGIN::GetAvailableSymbolFields( std::vector<wxString>& aNames )
220{
221 std::set<wxString> fieldNames;
222
223 for( auto& [libnameStr, libSymbol] : m_libCache )
224 {
225 std::vector<LIB_FIELD*> fields;
226 libSymbol->GetFields( fields );
227
228 for( LIB_FIELD* field : fields )
229 {
230 if( field->IsMandatory() )
231 continue;
232
233 fieldNames.insert( field->GetName() );
234 }
235 }
236
237 std::copy( fieldNames.begin(), fieldNames.end(), std::back_inserter( aNames ) );
238}
239
240
242{
243 ( *aListToAppendTo )["csa"] =
244 UTF8( _( "Path to the CADSTAR schematic archive (*.csa) file related to this CADSTAR "
245 "parts library. If none specified it is assumed to be 'symbol.csa' in the "
246 "same folder." ) );
247
248 ( *aListToAppendTo )["fplib"] =
249 UTF8( _( "Name of the footprint library related to the symbols in this library. You "
250 "should create a separate entry for the CADSTAR PCB Archive (*.cpa) file in "
251 "the footprint library tables. If none specified, 'cadstarpcblib' is assumed." ) );
252}
253
254
255void CADSTAR_SCH_ARCHIVE_PLUGIN::ensureLoadedLibrary( const wxString& aLibraryPath,
256 const STRING_UTF8_MAP* aProperties )
257{
258 wxFileName csafn;
259 wxString fplibname = "cadstarpcblib";
260
261 if( aProperties->count( "csa" ) )
262 {
263 csafn = wxFileName( aProperties->at( "csa" ) );
264 }
265 else
266 {
267 // If none specified, use
268 // symbol.csa in same folder as the .lib
269 csafn = wxFileName( aLibraryPath );
270 csafn.SetName( "symbol" );
271 csafn.SetExt( "csa" );
272 }
273
274 if( aProperties->count( "fplib" ) )
275 {
276 fplibname = aProperties->at( "fplib" );
277 }
278
279 // Get timestamp
280 long long timestamp = 0;
281 wxFileName fn( aLibraryPath );
282
283 if( fn.IsFileReadable() )
284 timestamp = fn.GetModificationTime().GetValue().GetValue();
285
286
287 if( fn.IsFileReadable()
288 && m_cachePath == aLibraryPath
289 && m_cachecsafn.GetFullPath() == csafn.GetFullPath()
290 && m_cachefplibname == fplibname
291 && m_cacheTimestamp == timestamp )
292 {
293 return;
294 }
295
296 // Update cache
297 m_libCache.clear();
298
299 CADSTAR_SCH_ARCHIVE_LOADER csaLoader( csafn.GetFullPath(), m_reporter, m_progressReporter );
300 csaLoader.SetFpLibName( fplibname );
301
302 std::vector<LIB_SYMBOL*> symbols = csaLoader.LoadPartsLib( aLibraryPath );
303
304 for( LIB_SYMBOL* sym : symbols )
305 {
306 m_libCache.insert( { sym->GetName(), std::unique_ptr<LIB_SYMBOL>( sym ) } );
307 }
308
309 m_cachePath = aLibraryPath;
310 m_cachecsafn = csafn;
311 m_cachefplibname = fplibname;
312 m_cacheTimestamp = timestamp;
313}
314
Loads a csa file into a KiCad SCHEMATIC object.
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.
std::vector< LIB_SYMBOL * > LoadPartsLib(const wxString &aFilename)
void SetFpLibName(const wxString &aLibName)
bool CheckHeader(const wxString &aFileName) override
Return true if the first line in aFileName begins with the expected header.
const wxString GetLibraryFileExtension() const override
Return the library file extension for the SCH_PLUGIN object.
const wxString GetFileExtension() const override
Return the file extension for the SCH_PLUGIN.
void ensureLoadedLibrary(const wxString &aLibraryPath, const STRING_UTF8_MAP *aProperties)
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aAliasName, const STRING_UTF8_MAP *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 STRING_UTF8_MAP *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
const wxString GetName() const override
Return a brief hard coded name for this SCH_PLUGIN.
void GetAvailableSymbolFields(std::vector< wxString > &aNames) override
Retrieves a list of (custom) field names that are present on symbols in this library.
int GetModifyHash() const override
Return the modification hash from the library cache.
SCH_SHEET * Load(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const STRING_UTF8_MAP *aProperties=nullptr) override
Load information from some input file format that this SCH_PLUGIN implementation knows about,...
void SymbolLibOptions(STRING_UTF8_MAP *aListToAppendTo) const override
Append supported SCH_PLUGIN options to aListToAppenTo along with internationalized descriptions.
Used for text file output.
Definition: richio.h:469
Field object used in symbol libraries.
Definition: lib_field.h:61
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:98
bool IsLegacy() const
Definition: lib_id.h:180
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition: lib_id.cpp:190
Define a library symbol object.
Definition: lib_symbol.h:99
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:126
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:132
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:294
@ ELEM_SYMBOL_LIB_TABLE
Definition: project.h:211
Holds all the data relating to one schematic.
Definition: schematic.h:72
void FixupJunctions()
Add junctions to this schematic where required.
Definition: schematic.cpp:650
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:97
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
Definition: schematic.cpp:109
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition: schematic.h:118
SCH_SHEET & Root() const
Definition: schematic.h:102
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:87
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:536
void set(SCH_PLUGIN *aPlugin)
Definition: sch_io_mgr.h:563
virtual void SaveSymbol(const wxString &aLibraryPath, const LIB_SYMBOL *aSymbol, const STRING_UTF8_MAP *aProperties=nullptr)
Write aSymbol to an existing library located at aLibraryPath.
Definition: sch_plugin.cpp:82
virtual void SaveLibrary(const wxString &aFileName, const STRING_UTF8_MAP *aProperties=nullptr)
Definition: sch_plugin.cpp:35
virtual void CreateSymbolLib(const wxString &aLibraryPath, const STRING_UTF8_MAP *aProperties=nullptr)
Create a new empty symbol library at aLibraryPath.
Definition: sch_plugin.cpp:98
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:109
static const char * PropBuffering
The property used internally by the plugin to enable cache buffering which prevents the library file ...
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:57
void SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:316
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:310
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:161
Schematic symbol object.
Definition: sch_symbol.h:81
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:284
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:178
A name/value tuple with unique names and optional values.
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_PLUGIN obje...
static const wxString & GetSymbolLibTableFileName()
virtual void Format(OUTPUTFORMATTER *aOutput, int aIndentLevel) const override
Generate the table in s-expression format to aOutput with an indentation level of aIndentLevel.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition: utf8.h:71
#define _(s)
const std::string KiCadSymbolLibFileExtension
const std::string CadstarPartsLibraryFileExtension
const std::string CadstarSchematicFileExtension
@ SCH_SYMBOL_T
Definition: typeinfo.h:146
Definition of file extensions used in Kicad.