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 <set>
23#include <trace_helpers.h>
24
25#include <sch_pin.h>
26#include <lib_symbol.h>
27#include <schematic.h>
28#include <sch_symbol.h>
29#include <sch_bitmap.h>
30#include <sch_bus_entry.h>
31#include <sch_field.h>
32#include <sch_group.h>
33#include <sch_junction.h>
34#include <sch_label.h>
35#include <sch_line.h>
36#include <sch_no_connect.h>
37#include <sch_rule_area.h>
38#include <sch_shape.h>
39#include <sch_sheet.h>
40#include <sch_sheet_path.h>
41#include <sch_screen.h>
42#include <sch_sheet_pin.h>
43#include <sch_table.h>
44#include <sch_tablecell.h>
45#include <sch_text.h>
46#include <sch_textbox.h>
47
48#include "api_sch_utils.h"
49
50#include <fmt/format.h>
51#include <fmt/ranges.h>
52#include <schematic.h>
53
54#include <api/api_utils.h>
55#include <api/api_enums.h>
56
57
58using namespace kiapi::common;
59
60
61std::unique_ptr<EDA_ITEM> CreateItemForType( KICAD_T aType, EDA_ITEM* aContainer )
62{
63 SCH_ITEM* parentSchItem = dynamic_cast<SCH_ITEM*>( aContainer );
64
65 switch( aType )
66 {
67 case SCH_JUNCTION_T: return std::make_unique<SCH_JUNCTION>();
68 case SCH_NO_CONNECT_T: return std::make_unique<SCH_NO_CONNECT>();
69 case SCH_BUS_WIRE_ENTRY_T: return std::make_unique<SCH_BUS_WIRE_ENTRY>();
70 case SCH_BUS_BUS_ENTRY_T: return std::make_unique<SCH_BUS_BUS_ENTRY>();
71 case SCH_LINE_T: return std::make_unique<SCH_LINE>();
72 case SCH_SHAPE_T: return std::make_unique<SCH_SHAPE>();
73 case SCH_BITMAP_T: return std::make_unique<SCH_BITMAP>();
74 case SCH_TEXTBOX_T: return std::make_unique<SCH_TEXTBOX>();
75 case SCH_TEXT_T: return std::make_unique<SCH_TEXT>();
76 case SCH_TABLE_T: return std::make_unique<SCH_TABLE>();
77 case SCH_TABLECELL_T: return std::make_unique<SCH_TABLECELL>();
78 case SCH_LABEL_T: return std::make_unique<SCH_LABEL>();
79 case SCH_GLOBAL_LABEL_T: return std::make_unique<SCH_GLOBALLABEL>();
80 case SCH_HIER_LABEL_T: return std::make_unique<SCH_HIERLABEL>();
81 case SCH_DIRECTIVE_LABEL_T: return std::make_unique<SCH_DIRECTIVE_LABEL>();
82 case SCH_RULE_AREA_T: return std::make_unique<SCH_RULE_AREA>();
83 case SCH_FIELD_T: return std::make_unique<SCH_FIELD>( parentSchItem );
84 case SCH_GROUP_T: return std::make_unique<SCH_GROUP>();
85 case SCH_SYMBOL_T: return std::make_unique<SCH_SYMBOL>();
86 case LIB_SYMBOL_T: return std::make_unique<LIB_SYMBOL>( wxEmptyString );
87 case SCH_SHEET_T:
88 {
89 if( aContainer && aContainer->Type() == SCH_SCREEN_T )
90 return std::make_unique<SCH_SHEET>( static_cast<SCH_SCREEN*>( aContainer ) );
91
92 return nullptr;
93 }
94
95
96 case SCH_SHEET_PIN_T:
97 if( aContainer && aContainer->Type() == SCH_SHEET_T )
98 return std::make_unique<SCH_SHEET_PIN>( static_cast<SCH_SHEET*>( aContainer ) );
99
100 return nullptr;
101
102 case SCH_PIN_T:
103 if( aContainer && aContainer->Type() == LIB_SYMBOL_T )
104 return std::make_unique<SCH_PIN>( static_cast<LIB_SYMBOL*>( aContainer ) );
105
106 return nullptr;
107
108 default:
109 return nullptr;
110 }
111}
112
113
114void PackPinMapOverride( kiapi::schematic::types::PinMapInstanceOverride* aOutput,
115 const PIN_MAP_INSTANCE_OVERRIDE& aOverride )
116{
117 aOutput->Clear();
118 aOutput->set_mode(
120 aOutput->set_active_map_name( aOverride.m_ActiveMapName.ToUTF8() );
121
122 for( const PIN_MAP_ENTRY& edit : aOverride.m_Edits )
123 {
124 kiapi::schematic::types::PinMapEntry* e = aOutput->add_edits();
125 e->set_pin_number( edit.m_PinNumber.ToUTF8() );
126 e->set_pad_number( edit.m_PadNumber.ToUTF8() );
127 }
128}
129
130
131PIN_MAP_INSTANCE_OVERRIDE UnpackPinMapOverride( const kiapi::schematic::types::PinMapInstanceOverride& aInput )
132{
134 override.m_Mode = FromProtoEnum<PIN_MAP_OVERRIDE_MODE>( aInput.mode() );
135 override.m_ActiveMapName = wxString::FromUTF8( aInput.active_map_name() );
136
137 for( const kiapi::schematic::types::PinMapEntry& e : aInput.edits() )
138 {
139 override.m_Edits.push_back( { wxString::FromUTF8( e.pin_number() ), wxString::FromUTF8( e.pad_number() ) } );
140 }
141
142 return override;
143}
144
145
146bool PackSymbol( kiapi::schematic::types::SchematicSymbolInstance* aOutput, const SCH_SYMBOL* aInput,
147 const SCH_SHEET_PATH& aPath )
148{
149 KIID_PATH path = aPath.Path();
150 SCH_SYMBOL_INSTANCE instance;
151
152 if( !aInput->GetInstance( instance, path ) )
153 {
154 wxLogTrace( traceApi, "error: instance data for symbol %s on %s is missing",
155 aInput->m_Uuid.AsString(), aPath.PathHumanReadable() );
156 return false;
157 }
158
159 google::protobuf::Any any;
160 aInput->Serialize( any );
161
162 if( !any.UnpackTo( aOutput ) )
163 return false;
164
165 PackSheetPath( *aOutput->mutable_path(), aPath );
166 aOutput->mutable_reference_field()->mutable_text()->set_text( instance.m_Reference.ToUTF8() );
167 aOutput->mutable_unit()->set_unit( instance.m_Unit );
168
169 kiapi::schematic::types::SchematicSymbol* def = aOutput->mutable_definition();
170
171 std::vector<const SCH_PIN*> pins = aInput->GetPins( &aPath );
172
173 std::ranges::sort( pins,
174 []( const SCH_PIN* a, const SCH_PIN* b )
175 {
176 return a->m_Uuid < b->m_Uuid;
177 } );
178
179 for( const SCH_PIN* pin : pins )
180 {
181 kiapi::schematic::types::SchematicSymbolChild* item = def->add_items();
182 item->mutable_unit()->set_unit( pin->GetUnit() );
183 item->mutable_body_style()->set_style( pin->GetBodyStyle() );
184 item->set_is_private( pin->IsPrivate() );
185 pin->Serialize( *item->mutable_item() );
186 }
187
188 // Also include the pins from non-placed units
189 if( const LIB_SYMBOL* lib = aInput->GetLibSymbolRef().get() )
190 {
191 std::set<wxString> placedNumbers;
192
193 for( const SCH_PIN* pin : pins )
194 placedNumbers.insert( pin->GetNumber() );
195
196 for( const SCH_PIN* libPin : lib->GetGraphicalPins( ALL_UNITS, ALL_BODY_STYLES ) )
197 {
198 if( libPin->GetBodyStyle() != ALL_BODY_STYLES
199 && aInput->GetBodyStyle() != ALL_BODY_STYLES
200 && aInput->GetBodyStyle() != libPin->GetBodyStyle() )
201 {
202 continue;
203 }
204
205 if( placedNumbers.count( libPin->GetNumber() ) )
206 continue;
207
208 kiapi::schematic::types::SchematicSymbolChild* item = def->add_items();
209 item->mutable_unit()->set_unit( libPin->GetUnit() );
210 item->mutable_body_style()->set_style( libPin->GetBodyStyle() );
211 item->set_is_private( libPin->IsPrivate() );
212 libPin->Serialize( *item->mutable_item() );
213 }
214 }
215
216 PIN_MAP_INSTANCE_OVERRIDE override = aInput->GetPinMapOverride( &aPath );
217
218 if( !override.IsDefault() )
219 PackPinMapOverride( aOutput->mutable_pin_map_override(), override );
220
221 kiapi::schematic::types::SchematicSymbolAttributes* attributes = aOutput->mutable_attributes();
222
223 attributes->set_exclude_from_simulation( aInput->GetExcludedFromSim() );
224 attributes->set_exclude_from_bill_of_materials( aInput->GetExcludedFromBOM() );
225 attributes->set_exclude_from_board( aInput->GetExcludedFromBoard() );
226 attributes->set_exclude_from_position_files( aInput->GetExcludedFromPosFiles() );
227 attributes->set_do_not_populate( aInput->GetDNP() );
228
229 // Descriptions belong to the schematic's variant registry rather than to each record.
230 SCHEMATIC* schematic = aInput->Schematic();
231
232 // Always set, so that sending the response back describes the placement's variants in full.
233 kiapi::schematic::types::SchematicSymbolVariants* variants = aOutput->mutable_variants();
234
235 for( const auto& [name, variantInfo] : instance.m_Variants )
236 {
237 kiapi::schematic::types::SchematicSymbolVariant* variant = variants->add_variants();
238 variant->set_name( name.ToUTF8() );
239
240 if( schematic )
241 variant->set_description( schematic->GetVariantDescription( name ).ToUTF8() );
242
243 attributes = variant->mutable_attributes();
244 attributes->set_exclude_from_simulation( variantInfo.m_ExcludedFromSim );
245 attributes->set_exclude_from_bill_of_materials( variantInfo.m_ExcludedFromBOM );
246 attributes->set_exclude_from_board( variantInfo.m_ExcludedFromBoard );
247 attributes->set_exclude_from_position_files( variantInfo.m_ExcludedFromPosFiles );
248 attributes->set_do_not_populate( variantInfo.m_DNP );
249
250 for( const auto& [key, value] : variantInfo.m_Fields )
251 ( *variant->mutable_fields() )[std::string( key.ToUTF8() )] = value.ToUTF8();
252
253 if( variantInfo.m_SymbolOverride )
254 PackLibId( variant->mutable_symbol_override(), *variantInfo.m_SymbolOverride );
255
256 if( !variantInfo.m_PinMapOverride.IsDefault() )
257 PackPinMapOverride( variant->mutable_pin_map_override(), variantInfo.m_PinMapOverride );
258 }
259
260 return true;
261}
262
263
264bool UnpackSymbol( SCH_SYMBOL* aOutput, const kiapi::schematic::types::SchematicSymbolInstance& aInput )
265{
266 using namespace kiapi::common::types;
267 using namespace kiapi::schematic::types;
268
269 if( !aOutput->Deserialize( aInput ) )
270 return false;
271
272 if( aInput.has_attributes() )
273 {
274 const SchematicSymbolAttributes& attrs = aInput.attributes();
275
276 aOutput->SetExcludedFromSim( attrs.exclude_from_simulation() );
277 aOutput->SetExcludedFromBOM( attrs.exclude_from_bill_of_materials() );
278 aOutput->SetExcludedFromBoard( attrs.exclude_from_board() );
279 aOutput->SetExcludedFromPosFiles( attrs.exclude_from_position_files() );
280 aOutput->SetDNP( attrs.do_not_populate() );
281 }
282
283 aOutput->SetPinMapOverride( aInput.has_pin_map_override() ? UnpackPinMapOverride( aInput.pin_map_override() )
285
286 return true;
287}
288
289
290// Variant names are stored and compared exactly, but SCHEMATIC::HasVariant matches case-insensitively
291std::optional<wxString> FindVariantNoCase( const SCHEMATIC* aSchematic, const wxString& aName )
292{
293 for( const wxString& variantName : aSchematic->GetVariantNames() )
294 {
295 if( variantName.CmpNoCase( aName ) == 0 )
296 return variantName;
297 }
298
299 return std::nullopt;
300}
301
302
304template <typename VariantProto>
305static void registerVariant( SCHEMATIC* aSchematic, const wxString& aName, const VariantProto& aInput )
306{
307 if( !aSchematic )
308 return;
309
310 wxString name( aName );
311
312 if( std::optional<wxString> canonical = FindVariantNoCase( aSchematic, name ) )
313 name = *canonical;
314
315 aSchematic->AddVariant( name );
316
317 // An empty description clears the one the variant has, so honour presence rather than text.
318 if( aInput.has_description() )
319 aSchematic->SetVariantDescription( aName, wxString::FromUTF8( aInput.description() ) );
320}
321
322
324static void applySymbolVariants( SCH_SYMBOL* aSymbol,
325 const kiapi::schematic::types::SchematicSymbolVariants& aInput,
326 const SCH_SHEET_PATH& aPath, SCHEMATIC* aSchematic )
327{
328 using namespace kiapi::schematic::types;
329
330 std::set<wxString> requested;
331
332 for( const SchematicSymbolVariant& variantProto : aInput.variants() )
333 {
334 wxString name = wxString::FromUTF8( variantProto.name() );
335
336 // The empty name selects the default variant, whose values are the symbol's own.
337 if( name.IsEmpty() )
338 continue;
339
340 requested.insert( name );
341 registerVariant( aSchematic, name, variantProto );
342
343 if( variantProto.has_attributes() )
344 {
345 const SchematicSymbolAttributes& attrs = variantProto.attributes();
346
347 aSymbol->SetExcludedFromSim( attrs.exclude_from_simulation(), &aPath, name );
348 aSymbol->SetExcludedFromBOM( attrs.exclude_from_bill_of_materials(), &aPath, name );
349 aSymbol->SetExcludedFromBoard( attrs.exclude_from_board(), &aPath, name );
350 aSymbol->SetExcludedFromPosFiles( attrs.exclude_from_position_files(), &aPath, name );
351 aSymbol->SetDNP( attrs.do_not_populate(), &aPath, name );
352 }
353
354 // Overrides the request dropped go back to resolving as the symbol's own value.
355 SCH_SYMBOL_INSTANCE stored;
356
357 if( aSymbol->GetInstance( stored, aPath.Path() ) && stored.m_Variants.contains( name ) )
358 {
359 for( const auto& [fieldName, unused] : stored.m_Variants[name].m_Fields )
360 {
361 if( variantProto.fields().find( std::string( fieldName.ToUTF8() ) )
362 == variantProto.fields().end() )
363 {
364 aSymbol->ClearVariantField( aPath.Path(), name, fieldName );
365 }
366 }
367 }
368
369 if( variantProto.has_symbol_override() )
370 aSymbol->SetVariantSymbolOverride( aPath, name, UnpackLibId( variantProto.symbol_override() ) );
371 else
372 aSymbol->ClearVariantSymbolOverride( aPath, name );
373
374 if( variantProto.has_pin_map_override() )
375 aSymbol->SetPinMapOverride( UnpackPinMapOverride( variantProto.pin_map_override() ), &aPath, name );
376 else
377 aSymbol->SetPinMapOverride( PIN_MAP_INSTANCE_OVERRIDE(), &aPath, name );
378
379 for( const auto& [key, value] : variantProto.fields() )
380 {
381 aSymbol->SetFieldText( wxString::FromUTF8( key ), wxString::FromUTF8( value ), &aPath,
382 name );
383 }
384 }
385
386 // Variants the request left out are removed from this placement only; the variant itself
387 // stays registered with the schematic and other placements keep theirs.
388 SCH_SYMBOL_INSTANCE stored;
389
390 if( aSymbol->GetInstance( stored, aPath.Path() ) )
391 {
392 for( const auto& [name, unused] : stored.m_Variants )
393 {
394 if( !requested.contains( name ) )
395 aSymbol->DeleteVariant( aPath.Path(), name );
396 }
397 }
398}
399
400
402 const kiapi::schematic::types::SchematicSymbolInstance& aInput,
403 const SCH_SHEET_PATH& aPath, SCHEMATIC* aSchematic )
404{
405 wxString reference = wxString::FromUTF8( aInput.reference_field().text().text() );
406 int unit = aInput.has_unit() ? aInput.unit().unit() : 1;
407 SCH_SYMBOL_INSTANCE existing;
408
409 if( aSymbol->GetInstance( existing, aPath.Path() ) )
410 {
411 if( !reference.IsEmpty() )
412 aSymbol->SetRef( &aPath, reference );
413
414 aSymbol->SetUnitSelection( &aPath, unit );
415 }
416 else
417 {
418 SCH_SYMBOL_INSTANCE instance;
419 instance.m_Path = aPath.Path();
420 instance.m_Reference = reference;
421 instance.m_Unit = unit;
422
423 aSymbol->AddHierarchicalReference( instance );
424 }
425
426 // The displayed unit follows the placement the request targeted, as it does in the editor.
427 aSymbol->SetUnit( unit );
428
429 // A request that carries no variant set leaves the placement's variants as they are.
430 if( aInput.has_variants() )
431 applySymbolVariants( aSymbol, aInput.variants(), aPath, aSchematic );
432}
433
434
435bool PackSheet( kiapi::schematic::types::SheetSymbol* aOutput, const SCH_SHEET* aInput,
436 const SCH_SHEET_PATH& aPath )
437{
438 google::protobuf::Any any;
439 aInput->Serialize( any );
440
441 if( !any.UnpackTo( aOutput ) )
442 return false;
443
444 PackSheetPath( *aOutput->mutable_path(), aPath );
445
446 SCHEMATIC* schematic = aInput->Schematic();
447
448 kiapi::schematic::types::SheetVariants* variants = aOutput->mutable_variants();
449
450 if( const SCH_SHEET_INSTANCE* instance = aInput->GetInstance( aPath.Path() ) )
451 {
452 aOutput->set_page_number( instance->m_PageNumber.ToUTF8() );
453
454 for( const auto& [name, variantInfo] : instance->m_Variants )
455 {
456 kiapi::schematic::types::SheetVariant* variant = variants->add_variants();
457 variant->set_name( name.ToUTF8() );
458
459 if( schematic )
460 variant->set_description( schematic->GetVariantDescription( name ).ToUTF8() );
461
462 variant->set_exclude_from_sim( variantInfo.m_ExcludedFromSim );
463 variant->set_exclude_from_bom( variantInfo.m_ExcludedFromBOM );
464 variant->set_dnp( variantInfo.m_DNP );
465
466 for( const auto& [key, value] : variantInfo.m_Fields )
467 ( *variant->mutable_fields() )[std::string( key.ToUTF8() )] = value.ToUTF8();
468 }
469 }
470
471 return true;
472}
473
474
478static void applySheetVariants( SCH_SHEET* aSheet,
479 const kiapi::schematic::types::SheetVariants& aInput,
480 const SCH_SHEET_PATH& aParentPath, SCHEMATIC* aSchematic )
481{
482 using namespace kiapi::schematic::types;
483
484 std::set<wxString> requested;
485
486 for( const SheetVariant& variantProto : aInput.variants() )
487 {
488 wxString name = wxString::FromUTF8( variantProto.name() );
489
490 // The empty name selects the default variant, whose values are the sheet's own.
491 if( name.IsEmpty() )
492 continue;
493
494 requested.insert( name );
495 registerVariant( aSchematic, name, variantProto );
496
497 // Each attribute the request leaves out keeps the value this variant already has.
498 if( variantProto.has_exclude_from_sim() )
499 aSheet->SetExcludedFromSim( variantProto.exclude_from_sim(), &aParentPath, name );
500
501 if( variantProto.has_exclude_from_bom() )
502 aSheet->SetExcludedFromBOM( variantProto.exclude_from_bom(), &aParentPath, name );
503
504 if( variantProto.has_dnp() )
505 aSheet->SetDNP( variantProto.dnp(), &aParentPath, name );
506
507 // Overrides the request dropped go back to resolving as the sheet's own value.
508 if( const SCH_SHEET_INSTANCE* stored = aSheet->GetInstance( aParentPath.Path() );
509 stored && stored->m_Variants.contains( name ) )
510 {
511 std::map<wxString, wxString> storedFields = stored->m_Variants.at( name ).m_Fields;
512
513 for( const auto& [fieldName, unused] : storedFields )
514 {
515 if( variantProto.fields().find( std::string( fieldName.ToUTF8() ) )
516 == variantProto.fields().end() )
517 {
518 aSheet->ClearVariantField( aParentPath.Path(), name, fieldName );
519 }
520 }
521 }
522
523 for( const auto& [key, value] : variantProto.fields() )
524 {
525 aSheet->SetFieldText( wxString::FromUTF8( key ), wxString::FromUTF8( value ),
526 &aParentPath, name );
527 }
528 }
529
530 // Remove variants from the sheet (not the schematic) that the client didn't send.
531 if( const SCH_SHEET_INSTANCE* stored = aSheet->GetInstance( aParentPath.Path() ) )
532 {
533 std::vector<wxString> obsolete;
534
535 for( const auto& [name, unused] : stored->m_Variants )
536 {
537 if( !requested.contains( name ) )
538 obsolete.push_back( name );
539 }
540
541 for( const wxString& name : obsolete )
542 aSheet->DeleteVariant( aParentPath.Path(), name );
543 }
544}
545
546
547void ApplySheetInstance( SCH_SHEET* aSheet, const kiapi::schematic::types::SheetSymbol& aInput,
548 const SCH_SHEET_PATH& aParentPath, SCHEMATIC* aSchematic )
549{
550 wxString pageNumber = wxString::FromUTF8( aInput.page_number() );
551 SCH_SHEET_PATH path( aParentPath );
552
553 path.push_back( aSheet );
554
555 // Creates the placement record when it is missing and keeps an existing one's variants; an
556 // empty page number in the request leaves the placement on the page it already has.
557 path.SetPageNumber( pageNumber.IsEmpty() ? path.GetPageNumber() : pageNumber );
558
559 // A request that carries no variant set leaves the placement's variants as they are.
560 if( aInput.has_variants() )
561 applySheetVariants( aSheet, aInput.variants(), aParentPath, aSchematic );
562}
563
564
565tl::expected<bool, ApiResponseStatus> UnpackSheet( SCH_SHEET* aOutput, const kiapi::schematic::types::SheetSymbol& aInput )
566{
567 google::protobuf::Any any;
568 any.PackFrom( aInput );
569
570 if( !aOutput->Deserialize( any ) )
571 {
572 ApiResponseStatus e;
573 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
574 e.set_error_message( "could not unpack SCH_SHEET from SheetSymbol in request" );
575 return tl::unexpected( e );
576 }
577
578 return true;
579}
580
581
582void PackSheetPath( types::SheetPath& aOutput, const SCH_SHEET_PATH& aInput )
583{
584 PackSheetPath( aOutput, aInput.Path() );
585 aOutput.set_path_human_readable( aInput.PathHumanReadable().ToUTF8() );
586}
587
588
589tl::expected<SCH_FOCUS_TARGET, ApiResponseStatus>
590ResolveFocusItems( SCHEMATIC& aSchematic, const std::vector<KIID>& aIds, const std::optional<KIID_PATH>& aSheetPath )
591{
592 if( aIds.empty() )
593 return tl::unexpected( MakeResponseStatus( AS_BAD_REQUEST, "no items were given to focus on" ) );
594
595 if( !aSchematic.HasHierarchy() )
596 aSchematic.RefreshHierarchy();
597
598 std::optional<SCH_SHEET_PATH> sheet;
599
600 if( aSheetPath )
601 {
602 sheet = aSchematic.Hierarchy().GetSheetPathByKIIDPath( *aSheetPath );
603
604 if( !sheet )
605 {
606 return tl::unexpected(
607 MakeResponseStatus( AS_BAD_REQUEST, "the requested sheet path is not valid for this schematic" ) );
608 }
609 }
610
611 std::optional<BOX2I> bbox;
612 std::vector<std::string> missing;
613
614 for( const KIID& id : aIds )
615 {
616 SCH_SHEET_PATH itemSheet;
617 SCH_ITEM* item = aSheetPath ? sheet->ResolveItem( id ) : aSchematic.ResolveItem( id, &itemSheet, true );
618
619 if( !item )
620 {
621 missing.push_back( id.AsStdString() );
622 continue;
623 }
624
625 if( !sheet )
626 {
627 sheet = itemSheet;
628 }
629 else if( !aSheetPath && itemSheet != *sheet )
630 {
631 return tl::unexpected( MakeResponseStatus(
632 AS_BAD_REQUEST, "the items are not all on one sheet; set the document's sheet path to choose "
633 "the sheet to focus" ) );
634 }
635
636 if( bbox )
637 bbox->Merge( item->GetBoundingBox() );
638 else
639 bbox = item->GetBoundingBox();
640 }
641
642 if( !missing.empty() )
643 {
644 return tl::unexpected(
645 MakeResponseStatus( AS_BAD_REQUEST, fmt::format( "the items {} are not in the requested document",
646 fmt::join( missing, ", " ) ) ) );
647 }
648
649 return SCH_FOCUS_TARGET{ *sheet, *bbox };
650}
const char * name
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICOMMON_API KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:55
static void registerVariant(SCHEMATIC *aSchematic, const wxString &aName, const VariantProto &aInput)
Make the schematic aware of a variant a request named. Accepts either variant message.
static void applySheetVariants(SCH_SHEET *aSheet, const kiapi::schematic::types::SheetVariants &aInput, const SCH_SHEET_PATH &aParentPath, SCHEMATIC *aSchematic)
Make the set of variant records on one placement of a sheet match aInput, by name.
std::unique_ptr< EDA_ITEM > CreateItemForType(KICAD_T aType, EDA_ITEM *aContainer)
void ApplySymbolInstance(SCH_SYMBOL *aSymbol, const kiapi::schematic::types::SchematicSymbolInstance &aInput, const SCH_SHEET_PATH &aPath, SCHEMATIC *aSchematic)
Apply placement-specific data to an aSymbol at aPath: reference, unit, and the per-placement attribut...
tl::expected< bool, ApiResponseStatus > UnpackSheet(SCH_SHEET *aOutput, const kiapi::schematic::types::SheetSymbol &aInput)
Unpack the every placement data from the input.
std::optional< wxString > FindVariantNoCase(const SCHEMATIC *aSchematic, const wxString &aName)
Variant names are stored and compared exactly, but SCHEMATIC::HasVariant matches case-insensitively.
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)
void ApplySheetInstance(SCH_SHEET *aSheet, const kiapi::schematic::types::SheetSymbol &aInput, const SCH_SHEET_PATH &aParentPath, SCHEMATIC *aSchematic)
Apply the placement data in a sheet message to aSheet: page number and the variants the message carri...
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).
tl::expected< SCH_FOCUS_TARGET, ApiResponseStatus > ResolveFocusItems(SCHEMATIC &aSchematic, const std::vector< KIID > &aIds, const std::optional< KIID_PATH > &aSheetPath)
Resolve the items of a FocusOnItems request to the sheet that shows them and their combined bounding ...
static void applySymbolVariants(SCH_SYMBOL *aSymbol, const kiapi::schematic::types::SchematicSymbolVariants &aInput, const SCH_SHEET_PATH &aPath, SCHEMATIC *aSchematic)
Make the set of variant records on one placement of a symbol match aInput, by name.
bool UnpackSymbol(SCH_SYMBOL *aOutput, const kiapi::schematic::types::SchematicSymbolInstance &aInput)
Unpack the geometry, the library definition, fields, and the default-variant attributes that are shar...
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:270
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
Definition kiid.h:46
wxString AsString() const
Definition kiid.cpp:264
Define a library symbol object.
Definition lib_symbol.h:114
Holds all the data relating to one schematic.
Definition schematic.h:149
void AddVariant(const wxString &aVariantName)
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Definition schematic.h:194
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
bool HasHierarchy() const
Check if the hierarchy has been built.
Definition schematic.h:190
void SetVariantDescription(const wxString &aVariantName, const wxString &aDescription)
Set the description for a variant.
const std::set< wxString > & GetVariantNames() const
Return the set of variant names (without the default placeholder).
Definition schematic.h:656
void RefreshHierarchy()
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:302
int GetBodyStyle() const
Definition sch_item.h:253
virtual void SetUnit(int aUnit)
Definition sch_item.h:242
std::optional< SCH_SHEET_PATH > GetSheetPathByKIIDPath(const KIID_PATH &aPath, bool aIncludeLastSheet=true) const
Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
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 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:48
void ClearVariantField(const KIID_PATH &aPath, const wxString &aVariantName, const wxString &aFieldName)
void SetExcludedFromSim(bool aExcludeFromSim, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear the exclude from simulation flag.
const SCH_SHEET_INSTANCE * GetInstance(const KIID_PATH &aParentPath) const
Return this sheet's placement record under aParentPath, or nullptr if it has none.
Definition sch_sheet.h:524
void SetDNP(bool aDNP, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
void SetExcludedFromBOM(bool aExcludeFromBOM, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear the exclude from schematic bill of materials flag.
void DeleteVariant(const KIID_PATH &aPath, const wxString &aVariantName)
void SetFieldText(const wxString &aFieldName, const wxString &aFieldText, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString)
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.
Schematic symbol object.
Definition sch_symbol.h:73
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
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.
bool ClearVariantSymbolOverride(const SCH_SHEET_PATH &aPath, const wxString &aVariantName)
Remove the alternate-symbol override for a given variant and sheet instance.
void SetFieldText(const wxString &aFieldName, const wxString &aFieldText, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString)
void SetVariantSymbolOverride(const SCH_SHEET_PATH &aPath, const wxString &aVariantName, const LIB_ID &aLibId)
Set the alternate-symbol override for a given variant and sheet instance.
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.
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
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 ClearVariantField(const KIID_PATH &aPath, const wxString &aVariantName, const wxString &aFieldName)
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
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 GetExcludedFromPosFiles(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool GetInstance(SCH_SYMBOL_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
Set the selected unit of this symbol on one sheet.
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:182
void DeleteVariant(const KIID_PATH &aPath, const wxString &aVariantName)
virtual bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
void SetExcludedFromBoard(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
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:33
KICOMMON_API ApiResponseStatus MakeResponseStatus(ApiStatusCode aCode, const std::string &aMessage)
Definition api_utils.cpp:39
KICOMMON_API void PackSheetPath(types::SheetPath &aOutput, const KIID_PATH &aInput)
KICOMMON_API void PackLibId(types::LibraryIdentifier *aOutput, const LIB_ID &aId)
KICOMMON_API LIB_ID UnpackLibId(const types::LibraryIdentifier &aId)
Class to handle a set of SCH_ITEMs.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
One symbol-pin to footprint-pad mapping inside a PIN_MAP.
Definition pin_map.h:42
Per-instance override of the active pin map and a sparse delta on top.
Definition pin_map.h:200
std::vector< PIN_MAP_ENTRY > m_Edits
Definition pin_map.h:203
PIN_MAP_OVERRIDE_MODE m_Mode
Definition pin_map.h:201
A simple container for sheet instance information.
std::map< wxString, SCH_SHEET_VARIANT > m_Variants
A list of sheet variants.
A simple container for schematic symbol instance information.
std::map< wxString, SCH_SYMBOL_VARIANT > m_Variants
A list of symbol variants.
#define ALL_UNITS
Definition symbol.h:150
#define ALL_BODY_STYLES
Definition symbol.h:151
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:70
@ SCH_GROUP_T
Definition typeinfo.h:169
@ SCH_TABLE_T
Definition typeinfo.h:161
@ SCH_LINE_T
Definition typeinfo.h:159
@ LIB_SYMBOL_T
Definition typeinfo.h:144
@ SCH_NO_CONNECT_T
Definition typeinfo.h:156
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_TABLECELL_T
Definition typeinfo.h:162
@ SCH_FIELD_T
Definition typeinfo.h:146
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:167
@ SCH_LABEL_T
Definition typeinfo.h:163
@ SCH_SHEET_T
Definition typeinfo.h:171
@ SCH_SHAPE_T
Definition typeinfo.h:145
@ SCH_RULE_AREA_T
Definition typeinfo.h:166
@ SCH_HIER_LABEL_T
Definition typeinfo.h:165
@ SCH_BUS_BUS_ENTRY_T
Definition typeinfo.h:158
@ SCH_SCREEN_T
Definition typeinfo.h:198
@ SCH_SHEET_PIN_T
Definition typeinfo.h:170
@ SCH_TEXT_T
Definition typeinfo.h:147
@ SCH_BUS_WIRE_ENTRY_T
Definition typeinfo.h:157
@ SCH_BITMAP_T
Definition typeinfo.h:160
@ SCH_TEXTBOX_T
Definition typeinfo.h:148
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:164
@ SCH_JUNCTION_T
Definition typeinfo.h:155
@ SCH_PIN_T
Definition typeinfo.h:149