KiCad PCB EDA Suite
Loading...
Searching...
No Matches
api_sch_utils.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) 2024 Jon Evans <[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
21#include <algorithm>
22#include <trace_helpers.h>
23
24#include <sch_pin.h>
25#include <lib_symbol.h>
26#include <sch_symbol.h>
27#include <sch_bitmap.h>
28#include <sch_bus_entry.h>
29#include <sch_field.h>
30#include <sch_group.h>
31#include <sch_junction.h>
32#include <sch_label.h>
33#include <sch_line.h>
34#include <sch_no_connect.h>
35#include <sch_shape.h>
36#include <sch_sheet.h>
37#include <sch_screen.h>
38#include <sch_sheet_pin.h>
39#include <sch_table.h>
40#include <sch_tablecell.h>
41#include <sch_text.h>
42#include <sch_textbox.h>
43
44#include "api_sch_utils.h"
45
46#include <api/api_utils.h>
47#include <api/api_enums.h>
48
49
50using namespace kiapi::common;
51
52
53std::unique_ptr<EDA_ITEM> CreateItemForType( KICAD_T aType, EDA_ITEM* aContainer )
54{
55 SCH_ITEM* parentSchItem = dynamic_cast<SCH_ITEM*>( aContainer );
56
57 switch( aType )
58 {
59 case SCH_JUNCTION_T: return std::make_unique<SCH_JUNCTION>();
60 case SCH_NO_CONNECT_T: return std::make_unique<SCH_NO_CONNECT>();
61 case SCH_BUS_WIRE_ENTRY_T: return std::make_unique<SCH_BUS_WIRE_ENTRY>();
62 case SCH_BUS_BUS_ENTRY_T: return std::make_unique<SCH_BUS_BUS_ENTRY>();
63 case SCH_LINE_T: return std::make_unique<SCH_LINE>();
64 case SCH_SHAPE_T: return std::make_unique<SCH_SHAPE>();
65 case SCH_BITMAP_T: return std::make_unique<SCH_BITMAP>();
66 case SCH_TEXTBOX_T: return std::make_unique<SCH_TEXTBOX>();
67 case SCH_TEXT_T: return std::make_unique<SCH_TEXT>();
68 case SCH_TABLE_T: return std::make_unique<SCH_TABLE>();
69 case SCH_TABLECELL_T: return std::make_unique<SCH_TABLECELL>();
70 case SCH_LABEL_T: return std::make_unique<SCH_LABEL>();
71 case SCH_GLOBAL_LABEL_T: return std::make_unique<SCH_GLOBALLABEL>();
72 case SCH_HIER_LABEL_T: return std::make_unique<SCH_HIERLABEL>();
73 case SCH_DIRECTIVE_LABEL_T: return std::make_unique<SCH_DIRECTIVE_LABEL>();
74 case SCH_FIELD_T: return std::make_unique<SCH_FIELD>( parentSchItem );
75 case SCH_GROUP_T: return std::make_unique<SCH_GROUP>();
76 case SCH_SYMBOL_T: return std::make_unique<SCH_SYMBOL>();
77 case LIB_SYMBOL_T: return std::make_unique<LIB_SYMBOL>( wxEmptyString );
78 case SCH_SHEET_T:
79 {
80 if( aContainer && aContainer->Type() == SCH_SCREEN_T )
81 return std::make_unique<SCH_SHEET>( static_cast<SCH_SCREEN*>( aContainer ) );
82
83 return nullptr;
84 }
85
86
87 case SCH_SHEET_PIN_T:
88 if( aContainer && aContainer->Type() == SCH_SHEET_T )
89 return std::make_unique<SCH_SHEET_PIN>( static_cast<SCH_SHEET*>( aContainer ) );
90
91 return nullptr;
92
93 case SCH_PIN_T:
94 if( aContainer && aContainer->Type() == LIB_SYMBOL_T )
95 return std::make_unique<SCH_PIN>( static_cast<LIB_SYMBOL*>( aContainer ) );
96
97 return nullptr;
98
99 default:
100 return nullptr;
101 }
102}
103
104
105void PackPinMapOverride( kiapi::schematic::types::PinMapInstanceOverride* aOutput,
106 const PIN_MAP_INSTANCE_OVERRIDE& aOverride )
107{
108 aOutput->Clear();
109 aOutput->set_mode(
111 aOutput->set_active_map_name( aOverride.m_ActiveMapName.ToUTF8() );
112
113 for( const PIN_MAP_ENTRY& edit : aOverride.m_Edits )
114 {
115 kiapi::schematic::types::PinMapEntry* e = aOutput->add_edits();
116 e->set_pin_number( edit.m_PinNumber.ToUTF8() );
117 e->set_pad_number( edit.m_PadNumber.ToUTF8() );
118 }
119}
120
121
122PIN_MAP_INSTANCE_OVERRIDE UnpackPinMapOverride( const kiapi::schematic::types::PinMapInstanceOverride& aInput )
123{
125 override.m_Mode = FromProtoEnum<PIN_MAP_OVERRIDE_MODE>( aInput.mode() );
126 override.m_ActiveMapName = wxString::FromUTF8( aInput.active_map_name() );
127
128 for( const kiapi::schematic::types::PinMapEntry& e : aInput.edits() )
129 {
130 override.m_Edits.push_back( { wxString::FromUTF8( e.pin_number() ), wxString::FromUTF8( e.pad_number() ) } );
131 }
132
133 return override;
134}
135
136
137bool PackSymbol( kiapi::schematic::types::SchematicSymbolInstance* aOutput, const SCH_SYMBOL* aInput,
138 const SCH_SHEET_PATH& aPath )
139{
140 KIID_PATH path = aPath.Path();
141 SCH_SYMBOL_INSTANCE instance;
142
143 if( !aInput->GetInstance( instance, path ) )
144 {
145 wxLogTrace( traceApi, "error: instance data for symbol %s on %s is missing",
146 aInput->m_Uuid.AsString(), aPath.PathHumanReadable() );
147 return false;
148 }
149
150 google::protobuf::Any any;
151 aInput->Serialize( any );
152
153 if( !any.UnpackTo( aOutput ) )
154 return false;
155
156 PackSheetPath( *aOutput->mutable_path(), path );
157 aOutput->mutable_reference_field()->mutable_text()->set_text( instance.m_Reference.ToUTF8() );
158 aOutput->mutable_unit()->set_unit( instance.m_Unit );
159
160 kiapi::schematic::types::SchematicSymbol* def = aOutput->mutable_definition();
161
162 std::vector<const SCH_PIN*> pins = aInput->GetPins( &aPath );
163
164 std::ranges::sort( pins,
165 []( const SCH_PIN* a, const SCH_PIN* b )
166 {
167 return a->m_Uuid < b->m_Uuid;
168 } );
169
170 for( const SCH_PIN* pin : pins )
171 {
172 kiapi::schematic::types::SchematicSymbolChild* item = def->add_items();
173 item->mutable_unit()->set_unit( pin->GetUnit() );
174 item->mutable_body_style()->set_style( pin->GetBodyStyle() );
175 item->set_is_private( pin->IsPrivate() );
176 pin->Serialize( *item->mutable_item() );
177 }
178
179 // Pin-to-pad maps (issue #2282): report the library symbol's effective bundle and, on the
180 // instance, the active override.
181 if( const LIB_SYMBOL* lib = aInput->GetLibSymbolRef().get() )
182 {
183 kiapi::schematic::types::LibSymbolPinMaps* pinMaps = def->mutable_pin_maps();
184
185 for( const ASSOCIATED_FOOTPRINT& assoc : lib->GetEffectiveAssociatedFootprints() )
186 {
187 kiapi::schematic::types::AssociatedFootprint* a = pinMaps->add_associated_footprints();
188 PackLibId( a->mutable_footprint(), assoc.m_FootprintLibId );
189 a->set_map_name( assoc.m_MapName.ToUTF8() );
190 }
191
192 for( const PIN_MAP& map : lib->GetEffectivePinMaps().GetAll() )
193 {
194 kiapi::schematic::types::PinMap* m = pinMaps->add_pin_maps();
195 m->set_name( map.GetName().ToUTF8() );
196
197 for( const PIN_MAP_ENTRY& entry : map.GetEntries() )
198 {
199 kiapi::schematic::types::PinMapEntry* e = m->add_entries();
200 e->set_pin_number( entry.m_PinNumber.ToUTF8() );
201 e->set_pad_number( entry.m_PadNumber.ToUTF8() );
202 }
203 }
204 }
205
206 PIN_MAP_INSTANCE_OVERRIDE override = aInput->GetPinMapOverride( &aPath );
207
208 if( !override.IsDefault() )
209 PackPinMapOverride( aOutput->mutable_pin_map_override(), override );
210
211 kiapi::schematic::types::SchematicSymbolAttributes* attributes = aOutput->mutable_attributes();
212
213 attributes->set_exclude_from_simulation( instance.m_ExcludedFromSim );
214 attributes->set_exclude_from_bill_of_materials( instance.m_ExcludedFromBOM );
215 attributes->set_exclude_from_board( instance.m_ExcludedFromBoard );
216 attributes->set_exclude_from_position_files( instance.m_ExcludedFromPosFiles );
217 attributes->set_do_not_populate( instance.m_DNP );
218
219 for( const auto& [name, variantInfo] : instance.m_Variants )
220 {
221 kiapi::schematic::types::SchematicSymbolVariant* variant = aOutput->add_variants();
222 variant->set_name( name.ToUTF8() );
223 variant->set_description( variantInfo.m_Description.ToUTF8() );
224
225 attributes = variant->mutable_attributes();
226 attributes->set_exclude_from_simulation( variantInfo.m_ExcludedFromSim );
227 attributes->set_exclude_from_bill_of_materials( variantInfo.m_ExcludedFromBOM );
228 attributes->set_exclude_from_board( variantInfo.m_ExcludedFromBoard );
229 attributes->set_exclude_from_position_files( variantInfo.m_ExcludedFromPosFiles );
230 attributes->set_do_not_populate( variantInfo.m_DNP );
231
232 for( const auto& [key, value] : variantInfo.m_Fields )
233 ( *variant->mutable_fields() )[std::string( key.ToUTF8() )] = value.ToUTF8();
234 }
235
236 return true;
237}
238
239
240bool UnpackSymbol( SCH_SYMBOL* aOutput, const kiapi::schematic::types::SchematicSymbolInstance& aInput )
241{
242 using namespace kiapi::common::types;
243 using namespace kiapi::schematic::types;
244
245 google::protobuf::Any any;
246 any.PackFrom( aInput );
247
248 if( !aOutput->Deserialize( any ) )
249 return false;
250
251 SCH_SYMBOL_INSTANCE instance;
252 instance.m_Path = UnpackSheetPath( aInput.path() );
253 instance.m_Reference = wxString::FromUTF8( aInput.reference_field().text().text() );
254 instance.m_Unit = aInput.has_unit() ? aInput.unit().unit() : 1;
255
256 if( aInput.has_attributes() )
257 {
258 const SchematicSymbolAttributes& attrs = aInput.attributes();
259 instance.m_ExcludedFromSim = attrs.exclude_from_simulation();
260 instance.m_ExcludedFromBOM = attrs.exclude_from_bill_of_materials();
261 instance.m_ExcludedFromBoard = attrs.exclude_from_board();
262 instance.m_ExcludedFromPosFiles = attrs.exclude_from_position_files();
263 instance.m_DNP = attrs.do_not_populate();
264
265 aOutput->SetExcludedFromSim( attrs.exclude_from_simulation() );
266 aOutput->SetExcludedFromBOM( attrs.exclude_from_bill_of_materials() );
267 aOutput->SetExcludedFromBoard( attrs.exclude_from_board() );
268 aOutput->SetExcludedFromPosFiles( attrs.exclude_from_position_files() );
269 aOutput->SetDNP( attrs.do_not_populate() );
270 }
271
272 for( const SchematicSymbolVariant& variantProto : aInput.variants() )
273 {
274 SCH_SYMBOL_VARIANT variant( wxString::FromUTF8( variantProto.name() ) );
275 variant.m_Description = wxString::FromUTF8( variantProto.description() );
276
277 if( variantProto.has_attributes() )
278 {
279 const SchematicSymbolAttributes& vAttrs = variantProto.attributes();
280 variant.m_ExcludedFromSim = vAttrs.exclude_from_simulation();
281 variant.m_ExcludedFromBOM = vAttrs.exclude_from_bill_of_materials();
282 variant.m_ExcludedFromBoard = vAttrs.exclude_from_board();
283 variant.m_ExcludedFromPosFiles = vAttrs.exclude_from_position_files();
284 variant.m_DNP = vAttrs.do_not_populate();
285 }
286
287 for( const auto& [key, value] : variantProto.fields() )
288 variant.m_Fields[ wxString::FromUTF8( key ) ] = wxString::FromUTF8( value );
289
290 instance.m_Variants.emplace( variant.m_Name, std::move( variant ) );
291 }
292
293 if( aInput.has_pin_map_override() )
294 aOutput->SetPinMapOverride( UnpackPinMapOverride( aInput.pin_map_override() ) );
295
296 aOutput->AddHierarchicalReference( instance );
297 return true;
298}
299
300
301bool PackSheet( kiapi::schematic::types::SheetSymbol* aOutput, const SCH_SHEET* aInput,
302 const SCH_SHEET_PATH& aPath )
303{
304 google::protobuf::Any any;
305 aInput->Serialize( any );
306
307 if( !any.UnpackTo( aOutput ) )
308 return false;
309
310 PackSheetPath( *aOutput->mutable_path(), aPath.Path() );
311 aOutput->set_page_number( aPath.GetPageNumber().ToUTF8() );
312
313 return true;
314}
315
316
317tl::expected<bool, ApiResponseStatus> UnpackSheet( SCH_SHEET* aOutput, const kiapi::schematic::types::SheetSymbol& aInput )
318{
319 google::protobuf::Any any;
320 any.PackFrom( aInput );
321
322 if( !aOutput->Deserialize( any ) )
323 {
324 ApiResponseStatus e;
325 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
326 e.set_error_message( "could not unpack SCH_SHEET from SheetSymbol in request" );
327 return tl::unexpected( e );
328 }
329
330 KIID_PATH instancePath = UnpackSheetPath( aInput.path() );
331
332 if( !instancePath.empty() )
333 {
334 SCH_SHEET_INSTANCE instance;
335 instance.m_Path = instancePath;
336 instance.m_PageNumber = wxString::FromUTF8( aInput.page_number() );
337
338 aOutput->AddInstance( instance );
339 }
340
341 return true;
342}
const char * name
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:47
std::unique_ptr< EDA_ITEM > CreateItemForType(KICAD_T aType, EDA_ITEM *aContainer)
tl::expected< bool, ApiResponseStatus > UnpackSheet(SCH_SHEET *aOutput, const kiapi::schematic::types::SheetSymbol &aInput)
bool PackSheet(kiapi::schematic::types::SheetSymbol *aOutput, const SCH_SHEET *aInput, const SCH_SHEET_PATH &aPath)
bool PackSymbol(kiapi::schematic::types::SchematicSymbolInstance *aOutput, const SCH_SYMBOL *aInput, const SCH_SHEET_PATH &aPath)
PIN_MAP_INSTANCE_OVERRIDE UnpackPinMapOverride(const kiapi::schematic::types::PinMapInstanceOverride &aInput)
void PackPinMapOverride(kiapi::schematic::types::PinMapInstanceOverride *aOutput, const PIN_MAP_INSTANCE_OVERRIDE &aOverride)
Pack/unpack a pin-to-pad map instance override to/from its protobuf form (issue #2282).
bool UnpackSymbol(SCH_SYMBOL *aOutput, const kiapi::schematic::types::SchematicSymbolInstance &aInput)
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
const KIID m_Uuid
Definition eda_item.h:531
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
wxString AsString() const
Definition kiid.cpp:242
Define a library symbol object.
Definition lib_symbol.h:80
A named pin map.
Definition pin_map.h:64
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:162
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
wxString GetPageNumber() const
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false, bool aEscapeSheetNames=false) const
Return the sheet path in a human readable form made from the sheet names.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:44
void AddInstance(const SCH_SHEET_INSTANCE &aInstance)
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition sch_sheet.cpp:82
Variant information for a schematic symbol.
Schematic symbol object.
Definition sch_symbol.h:69
virtual void SetDNP(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void SetExcludedFromSim(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear the exclude from simulation flag.
PIN_MAP_INSTANCE_OVERRIDE GetPinMapOverride(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
void SetPinMapOverride(const PIN_MAP_INSTANCE_OVERRIDE &aOverride, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString)
Set the per-instance pin-to-pad map override (issue #2282).
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
void SetExcludedFromPosFiles(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
bool GetInstance(SCH_SYMBOL_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
void SetExcludedFromBOM(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear the exclude from schematic bill of materials flag.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:177
void SetExcludedFromBoard(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
wxString m_Name
bool m_ExcludedFromBOM
std::map< wxString, wxString > m_Fields
bool m_ExcludedFromPosFiles
bool m_ExcludedFromSim
bool m_ExcludedFromBoard
wxString m_Description
A type-safe container of any type.
Definition ki_any.h:92
const wxChar *const traceApi
Flag to enable debug output related to the IPC API and its plugin system.
Definition api_utils.cpp:29
KICOMMON_API KIID_PATH UnpackSheetPath(const types::SheetPath &aInput)
KICOMMON_API void PackSheetPath(types::SheetPath &aOutput, const KIID_PATH &aInput)
KICOMMON_API void PackLibId(types::LibraryIdentifier *aOutput, const LIB_ID &aId)
Class to handle a set of SCH_ITEMs.
A first-class footprint choice on a LIB_SYMBOL, tied to a named pin map.
Definition pin_map.h:158
One symbol-pin to footprint-pad mapping inside a PIN_MAP.
Definition pin_map.h:41
Per-instance override of the active pin map and a sparse delta on top.
Definition pin_map.h:199
std::vector< PIN_MAP_ENTRY > m_Edits
Definition pin_map.h:202
PIN_MAP_OVERRIDE_MODE m_Mode
Definition pin_map.h:200
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
std::map< wxString, SCH_SYMBOL_VARIANT > m_Variants
A list of symbol variants.
std::string path
KIBIS_PIN * pin
wxLogTrace helper definitions.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:71
@ SCH_GROUP_T
Definition typeinfo.h:170
@ SCH_TABLE_T
Definition typeinfo.h:162
@ SCH_LINE_T
Definition typeinfo.h:160
@ LIB_SYMBOL_T
Definition typeinfo.h:145
@ SCH_NO_CONNECT_T
Definition typeinfo.h:157
@ SCH_SYMBOL_T
Definition typeinfo.h:169
@ SCH_TABLECELL_T
Definition typeinfo.h:163
@ SCH_FIELD_T
Definition typeinfo.h:147
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:168
@ SCH_LABEL_T
Definition typeinfo.h:164
@ SCH_SHEET_T
Definition typeinfo.h:172
@ SCH_SHAPE_T
Definition typeinfo.h:146
@ SCH_HIER_LABEL_T
Definition typeinfo.h:166
@ SCH_BUS_BUS_ENTRY_T
Definition typeinfo.h:159
@ SCH_SCREEN_T
Definition typeinfo.h:199
@ SCH_SHEET_PIN_T
Definition typeinfo.h:171
@ SCH_TEXT_T
Definition typeinfo.h:148
@ SCH_BUS_WIRE_ENTRY_T
Definition typeinfo.h:158
@ SCH_BITMAP_T
Definition typeinfo.h:161
@ SCH_TEXTBOX_T
Definition typeinfo.h:149
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:165
@ SCH_JUNCTION_T
Definition typeinfo.h:156
@ SCH_PIN_T
Definition typeinfo.h:150