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-2023 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#include <wx_filename.h>
39
40
42{
43 return wxT( "CADSTAR Schematic Archive" );
44}
45
46
48{
49 return 0;
50}
51
52
54 SCHEMATIC* aSchematic,
55 SCH_SHEET* aAppendToMe,
56 const STRING_UTF8_MAP* aProperties )
57{
58 wxCHECK( !aFileName.IsEmpty() && aSchematic, nullptr );
59
60 SCH_SHEET* rootSheet = nullptr;
61
62
63 if( aAppendToMe )
64 {
65 wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
66 rootSheet = &aSchematic->Root();
67 }
68 else
69 {
70 rootSheet = new SCH_SHEET( aSchematic );
71 rootSheet->SetFileName( aFileName );
72 aSchematic->SetRoot( rootSheet );
73 }
74
75 if( !rootSheet->GetScreen() )
76 {
77 SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
78 screen->SetFileName( aFileName );
79 rootSheet->SetScreen( screen );
80 }
81
83 csaLoader.Load( aSchematic, rootSheet );
84
85 // SAVE SYMBOLS TO PROJECT LIBRARY:
86 SYMBOL_LIB_TABLE* libTable = aSchematic->Prj().SchSymbolLibTable();
87
88 wxCHECK_MSG( libTable, nullptr, "Could not load symbol lib table." );
89
90 // Lets come up with a nice library name
91 wxString libName = aSchematic->Prj().GetProjectName();
92
93 if( libName.IsEmpty() )
94 {
95 wxFileName fn( rootSheet->GetFileName() );
96 libName = fn.GetName();
97 }
98
99 if( libName.IsEmpty() )
100 libName = "noname";
101
102 libName = LIB_ID::FixIllegalChars( libName, true ).wx_str();
103
104 wxFileName libFileName( aSchematic->Prj().GetProjectPath(), libName,
106
108 sch_plugin.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
109
110 if( !libTable->HasLibrary( libName ) )
111 {
112 // Create a new empty symbol library.
113 sch_plugin->CreateSymbolLib( libFileName.GetFullPath() );
114 wxString libTableUri = "${KIPRJMOD}/" + libFileName.GetFullName();
115
116 // Add the new library to the project symbol library table.
117 libTable->InsertRow(
118 new SYMBOL_LIB_TABLE_ROW( libName, libTableUri, wxString( "KiCad" ) ) );
119
120 // Save project symbol library table.
121 wxFileName fn( aSchematic->Prj().GetProjectPath(),
123
124 // So output formatter goes out of scope and closes the file before reloading.
125 {
126 FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
127 libTable->Format( &formatter, 0 );
128 }
129
130 // Relaod the symbol library table.
131 aSchematic->Prj().SetElem( PROJECT::ELEM_SYMBOL_LIB_TABLE, NULL );
132 aSchematic->Prj().SchSymbolLibTable();
133 }
134
135 // set properties to prevent save file on every symbol save
136 STRING_UTF8_MAP properties;
137 properties.emplace( SCH_SEXPR_PLUGIN::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->GetSheets() )
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->FixupJunctions();
162
163 return rootSheet;
164}
165
166
167void CADSTAR_SCH_ARCHIVE_PLUGIN::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
168 const wxString& aLibraryPath,
169 const STRING_UTF8_MAP* aProperties )
170{
171 ensureLoadedLibrary( aLibraryPath, aProperties );
172
173 for( auto& [libnameStr, libSymbol] : m_libCache )
174 aSymbolNameList.Add( libSymbol->GetName() );
175}
176
177
178void CADSTAR_SCH_ARCHIVE_PLUGIN::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
179 const wxString& aLibraryPath,
180 const STRING_UTF8_MAP* aProperties )
181{
182 ensureLoadedLibrary( aLibraryPath, aProperties );
183
184 for( auto& [libnameStr, libSymbol] : m_libCache )
185 aSymbolList.push_back( libSymbol.get() );
186}
187
188
190 const wxString& aAliasName,
191 const STRING_UTF8_MAP* 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 CADSTAR_SCH_ARCHIVE_PLUGIN::GetAvailableSymbolFields( std::vector<wxString>& aNames )
203{
204 std::set<wxString> fieldNames;
205
206 for( auto& [libnameStr, libSymbol] : m_libCache )
207 {
208 std::vector<LIB_FIELD*> fields;
209 libSymbol->GetFields( fields );
210
211 for( LIB_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
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 CADSTAR_SCH_ARCHIVE_PLUGIN::ensureLoadedLibrary( const wxString& aLibraryPath,
239 const STRING_UTF8_MAP* aProperties )
240{
241 wxFileName csafn;
242 wxString fplibname = "cadstarpcblib";
243
244 if( aProperties && aProperties->count( "csa" ) )
245 {
246 csafn = wxFileName( aProperties->at( "csa" ) );
247
248 if( !csafn.IsAbsolute() )
249 {
250 wxFileName libDir( aLibraryPath );
251 libDir.ClearExt();
252 libDir.SetName( "" );
253 // wxPATH_NORM_ALL is deprecated in wxWidgets 3.1, so use our flags
254 csafn.Normalize( FN_NORMALIZE_FLAGS, libDir.GetAbsolutePath() );
255 }
256 }
257 else
258 {
259 // If none specified, use
260 // symbol.csa in same folder as the .lib
261 csafn = wxFileName( aLibraryPath );
262 csafn.SetName( "symbol" );
263 csafn.SetExt( "csa" );
264 }
265
266 if( aProperties && aProperties->count( "fplib" ) )
267 {
268 fplibname = aProperties->at( "fplib" ).wx_str();
269 }
270
271 // Get timestamp
272 long long timestamp = 0;
273 wxFileName fn( aLibraryPath );
274
275 if( fn.IsFileReadable() )
276 timestamp = fn.GetModificationTime().GetValue().GetValue();
277
278
279 if( fn.IsFileReadable()
280 && m_cachePath == aLibraryPath
281 && m_cachecsafn.GetFullPath() == csafn.GetFullPath()
282 && m_cachefplibname == fplibname
283 && m_cacheTimestamp == timestamp )
284 {
285 return;
286 }
287
288 // Update cache
289 m_libCache.clear();
290
291 CADSTAR_SCH_ARCHIVE_LOADER csaLoader( csafn.GetFullPath(), m_reporter, m_progressReporter );
292 csaLoader.SetFpLibName( fplibname );
293
294 std::vector<LIB_SYMBOL*> symbols = csaLoader.LoadPartsLib( aLibraryPath );
295
296 for( LIB_SYMBOL* sym : symbols )
297 {
298 m_libCache.insert( { sym->GetName(), std::unique_ptr<LIB_SYMBOL>( sym ) } );
299 }
300
301 m_cachePath = aLibraryPath;
302 m_cachecsafn = csafn;
303 m_cachefplibname = fplibname;
304 m_cacheTimestamp = timestamp;
305}
306
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)
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 * LoadSchematicFile(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:62
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:99
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:191
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:143
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:149
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:311
@ ELEM_SYMBOL_LIB_TABLE
Definition: project.h:220
Holds all the data relating to one schematic.
Definition: schematic.h:75
void FixupJunctions()
Add junctions to this schematic where required.
Definition: schematic.cpp:654
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:100
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
Definition: schematic.cpp:113
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition: schematic.h:121
SCH_SHEET & Root() const
Definition: schematic.h:105
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:90
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:150
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:530
void set(SCH_PLUGIN *aPlugin)
Definition: sch_io_mgr.h:557
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:167
virtual void SaveLibrary(const wxString &aFileName, const STRING_UTF8_MAP *aProperties=nullptr)
Definition: sch_plugin.cpp:120
virtual void CreateSymbolLib(const wxString &aLibraryPath, const STRING_UTF8_MAP *aProperties=nullptr)
Create a new empty symbol library at aLibraryPath.
Definition: sch_plugin.cpp:183
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:116
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:318
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:312
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:287
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:173
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
wxString wx_str() const
Definition: utf8.cpp:45
#define _(s)
const std::string KiCadSymbolLibFileExtension
@ SCH_SYMBOL_T
Definition: typeinfo.h:155
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition: wx_filename.h:39