KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_sch_symbol.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21#include <sch_screen.h>
22#include <schematic.h>
23#include <locale_io.h>
26#include "eeschema_test_utils.h"
27#include <sch_symbol.h>
28#include <sch_edit_frame.h>
29#include <sch_commit.h>
31#include <lib_symbol.h>
32#include <eda_search_data.h>
33#include <sim/sim_lib_mgr.h>
34#include <sim/sim_model.h>
35#include <reporter.h>
36
37#include "tool/tool_manager.h"
38
39
41{
42public:
44 {
45 if( !m_schematic )
46 return nullptr;
47
48 SCH_SCREEN* screen = m_schematic->RootScreen();
49
50 if( !screen )
51 return nullptr;
52
53 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
54 {
55 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
56
57 if( symbol )
58 return symbol;
59 }
60
61 return nullptr;
62 }
63
66};
67
68
72BOOST_FIXTURE_TEST_SUITE( SchSymbol, TEST_SCH_SYMBOL_FIXTURE )
73
74
75
78BOOST_AUTO_TEST_CASE( DefaultProperties )
79{
80}
81
82
87{
88 TRANSFORM t = m_symbol.GetTransform();
89
90 m_symbol.SetOrientation( SYM_ORIENT_90 );
91 t = m_symbol.GetTransform();
92 m_symbol.SetTransform( TRANSFORM() );
93 m_symbol.SetOrientation( SYM_ORIENT_180 );
94 t = m_symbol.GetTransform();
95 m_symbol.SetTransform( TRANSFORM() );
96 m_symbol.SetOrientation( SYM_ORIENT_270 );
97 t = m_symbol.GetTransform();
98}
99
100
101BOOST_AUTO_TEST_CASE( DuplicatePinMatchingPreservesStoredOrder )
102{
103 LoadSchematic( SchematicQAPath( wxS( "component_classes" ) ) );
104 SCH_SYMBOL* source = nullptr;
105
106 for( SCH_ITEM* item : m_schematic->RootScreen()->Items().OfType( SCH_SYMBOL_T ) )
107 {
108 auto* candidate = static_cast<SCH_SYMBOL*>( item );
109 std::set<wxString> numbers;
110
111 for( const auto& pin : candidate->GetRawPins() )
112 numbers.insert( pin->GetNumber() );
113
114 if( numbers.size() >= 3 && numbers.size() == candidate->GetRawPins().size() )
115 {
116 source = candidate;
117 break;
118 }
119 }
120
122 std::unique_ptr<SCH_SYMBOL> symbol( static_cast<SCH_SYMBOL*>( source->Clone() ) );
123 std::vector<std::unique_ptr<SCH_PIN>>& pins = symbol->GetRawPins();
124 const wxString number = pins.front()->GetNumber();
125 const size_t originalCount = pins.size();
126 pins.emplace_back( static_cast<SCH_PIN*>( pins.front()->Duplicate( false ) ) );
127
128 // Oppose allocation order so the saved order cannot pass by allocator coincidence.
129 const auto opposeAllocationOrder =
130 [&]
131 {
132 std::sort( pins.begin(), pins.end(), []( const auto& a, const auto& b )
133 { return std::less<SCH_PIN*>{}( b.get(), a.get() ); } );
134 };
135
136 const auto numbered =
137 [&]( const auto& pin )
138 {
139 return pin->GetNumber() == number;
140 };
141
142 opposeAllocationOrder();
143 const KIID expected = ( *std::find_if( pins.begin(), pins.end(), numbered ) )->m_Uuid;
144 symbol->UpdatePins();
145 BOOST_CHECK_EQUAL( pins.size(), originalCount );
146
147 for( int pass = 0; pass < 2; ++pass )
148 {
149 const auto retained = std::find_if( pins.begin(), pins.end(), numbered );
150 BOOST_REQUIRE( retained != pins.end() );
151 BOOST_CHECK( ( *retained )->m_Uuid == expected );
152 symbol->UpdatePins();
153 }
154
155 opposeAllocationOrder();
156 const std::vector<SCH_PIN*> libraryPins = symbol->GetLibSymbolRef()->GetGraphicalPins( ALL_UNITS, ALL_BODY_STYLES );
157 BOOST_REQUIRE_EQUAL( libraryPins.size(), pins.size() );
158 const wxString commonNumber = libraryPins.front()->GetNumber();
159 std::map<const SCH_PIN*, KIID> expectedMapping;
160
161 for( size_t i = 0; i < pins.size(); ++i )
162 {
163 expectedMapping.emplace( libraryPins[i], pins[i]->m_Uuid );
164 pins[i]->SetNumber( commonNumber );
165 }
166
167 // Only the first library pin matches; the others must reuse saved pins in order.
168 symbol->UpdatePins();
169 BOOST_REQUIRE_EQUAL( pins.size(), originalCount );
170
171 for( const std::unique_ptr<SCH_PIN>& pin : pins )
172 {
173 BOOST_REQUIRE( expectedMapping.contains( pin->GetLibPin() ) );
174 BOOST_CHECK( pin->m_Uuid == expectedMapping.at( pin->GetLibPin() ) );
175 }
176}
177
178
182BOOST_AUTO_TEST_CASE( SchSymbolVariantTest )
183{
184 wxFileName fn;
185 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
186 fn.AppendDir( wxS( "variant_test" ) );
187 fn.SetName( wxS( "variant_test" ) );
189
190 LoadSchematic( fn.GetFullPath() );
191
192 SCH_SYMBOL* symbol = GetFirstSymbol();
193 BOOST_CHECK( symbol );
194
195 // Test for an empty (non-existant) variant.
196 wxString variantName = wxS( "Variant1" );
197 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
198 BOOST_CHECK( !variant );
199
200 // Test DNP property variant.
201 BOOST_CHECK( !symbol->GetDNP() );
202 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
203 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
204
205 // Test exclude from BOM property variant.
206 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
207 symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], variantName );
208 BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], variantName ) );
209
210 // Test exclude from simulation property variant.
211 BOOST_CHECK( !symbol->GetExcludedFromSim() );
212 symbol->SetExcludedFromSim( true, &m_schematic->Hierarchy()[0], variantName );
213 BOOST_CHECK( symbol->GetExcludedFromSim( &m_schematic->Hierarchy()[0], variantName ) );
214
215 // Test exclude from board property variant.
216 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
217 symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], variantName );
218 BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], variantName ) );
219
220 // Test exclude from position files property variant.
221 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
222 symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], variantName );
223 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], variantName ) );
224
225 // Test a value field variant change.
226 BOOST_CHECK( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL )
227 == wxS( "1K" ) );
228 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "10K" ), &m_schematic->Hierarchy()[0], variantName );
229 BOOST_CHECK( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, variantName )
230 == wxS( "10K" ) );
231 // BOOST_CHECK( symbol->GetFieldText( FIELD_T::VALUE, &m_schematic->Hierarchy()[0], variantName ) == wxS( "10K" ) );
232}
233
234
240BOOST_AUTO_TEST_CASE( FieldAdditionByName )
241{
242 wxFileName fn;
243 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
244 fn.AppendDir( wxS( "variant_test" ) );
245 fn.SetName( wxS( "variant_test" ) );
247
248 LoadSchematic( fn.GetFullPath() );
249
250 SCH_SYMBOL* symbol = GetFirstSymbol();
251 BOOST_REQUIRE( symbol );
252
253 wxString newFieldName = wxS( "Sim.Library" );
254
255 // GetField by name should return null for non-existent field
256 const SCH_FIELD* existing = symbol->GetField( newFieldName );
257 BOOST_CHECK( existing == nullptr );
258
259 // Create a field to add
260 SCH_FIELD newField( symbol, FIELD_T::USER, newFieldName );
261 newField.SetText( wxS( "test_model.lib" ) );
262
263 // AddField should add the field and return a valid pointer
264 SCH_FIELD* addedField = symbol->AddField( newField );
265 BOOST_REQUIRE( addedField != nullptr );
266
267 // After setting the parent, verify the field is correctly configured
268 addedField->SetParent( symbol );
269 BOOST_CHECK( addedField->GetParent() == symbol );
270
271 // Now GetField should find the newly added field
272 const SCH_FIELD* found = symbol->GetField( newFieldName );
273 BOOST_REQUIRE( found != nullptr );
274 BOOST_CHECK( found->GetText() == wxS( "test_model.lib" ) );
275}
276
277
286BOOST_AUTO_TEST_CASE( UndoSwapItemDataRestoresUnitPinDisplayState )
287{
288 LoadSchematic( SchematicQAPath( wxS( "component_classes" ) ) );
289 BOOST_REQUIRE( m_schematic );
290
291 SCH_SHEET_LIST hierarchy = m_schematic->Hierarchy();
292 BOOST_REQUIRE( !hierarchy.empty() );
293
294 const SCH_SHEET_PATH& sheet = hierarchy[0];
295 SCH_SYMBOL* symbol = nullptr;
296
297 for( SCH_ITEM* item : m_schematic->RootScreen()->Items().OfType( SCH_SYMBOL_T ) )
298 {
299 SCH_SYMBOL* candidate = static_cast<SCH_SYMBOL*>( item );
300
301 if( candidate->GetRef( &sheet, false ) == wxS( "U1" )
302 && candidate->GetUnitSelection( &sheet ) == 1 )
303 {
304 symbol = candidate;
305 break;
306 }
307 }
308
309 BOOST_REQUIRE( symbol );
310
311 auto pinNumbers =
312 []( const std::vector<SCH_PIN*>& aPins )
313 {
314 std::set<wxString> numbers;
315
316 for( SCH_PIN* pin : aPins )
317 numbers.insert( pin->GetNumber() );
318
319 return numbers;
320 };
321
322 const std::set<wxString> unitAPins = { wxS( "1" ), wxS( "2" ), wxS( "3" ) };
323 const std::set<wxString> unitBPins = { wxS( "5" ), wxS( "6" ), wxS( "7" ) };
324
325 BOOST_CHECK_EQUAL( symbol->GetUnitSelection( &sheet ), 1 );
326 BOOST_CHECK_EQUAL( symbol->GetUnit(), 1 );
327 BOOST_CHECK( pinNumbers( symbol->GetLibPins() ) == unitAPins );
328
329 std::unique_ptr<SCH_SYMBOL> undoImage( static_cast<SCH_SYMBOL*>( symbol->Clone() ) );
330
331 symbol->SetUnitSelection( &sheet, 2 );
332 symbol->SetUnit( 2 );
333
334 BOOST_CHECK_EQUAL( symbol->GetUnitSelection( &sheet ), 2 );
335 BOOST_CHECK_EQUAL( symbol->GetUnit(), 2 );
336 BOOST_CHECK( pinNumbers( symbol->GetLibPins() ) == unitBPins );
337
338 symbol->SwapItemData( undoImage.get() );
339 symbol->UpdatePins();
340
341 BOOST_CHECK_EQUAL( symbol->GetUnitSelection( &sheet ), 1 );
342 BOOST_CHECK_EQUAL( symbol->GetUnit(), 1 );
343 BOOST_CHECK( pinNumbers( symbol->GetLibPins() ) == unitAPins );
344
345 BOOST_CHECK_EQUAL( undoImage->GetUnitSelection( &sheet ), 2 );
346 BOOST_CHECK_EQUAL( undoImage->GetUnit(), 2 );
347 BOOST_CHECK( pinNumbers( undoImage->GetLibPins() ) == unitBPins );
348}
349
350
363BOOST_AUTO_TEST_CASE( VariantDialogBatchCommit )
364{
365 wxFileName fn;
366 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
367 fn.AppendDir( wxS( "variant_test" ) );
368 fn.SetName( wxS( "variant_test" ) );
370
371 LoadSchematic( fn.GetFullPath() );
372
373 SCH_SYMBOL* symbol = GetFirstSymbol();
374 BOOST_REQUIRE( symbol );
375
376 SCH_SHEET_LIST hierarchy = m_schematic->Hierarchy();
377 const SCH_SHEET_PATH& sheet = hierarchy[0];
378 wxString variantName = wxS( "DialogTest" );
379
380 // All base properties should start false.
381 BOOST_CHECK( !symbol->GetDNP() );
382 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
383 BOOST_CHECK( !symbol->GetExcludedFromSim() );
384 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
385 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
386
387 // Simulate dialog_symbol_properties TransferDataFromWindow call order.
388 // ExcludeFromSim is left unchecked (false), the other four are checked (true).
389 symbol->SetExcludedFromSim( false, &sheet, variantName );
390 symbol->SetExcludedFromBOM( true, &sheet, variantName );
391 symbol->SetExcludedFromBoard( true, &sheet, variantName );
392 symbol->SetExcludedFromPosFiles( true, &sheet, variantName );
393 symbol->SetDNP( true, &sheet, variantName );
394
395 // All four checked properties must read back as true through the variant.
396 BOOST_CHECK( symbol->GetDNP( &sheet, variantName ) );
397 BOOST_CHECK( symbol->GetExcludedFromBOM( &sheet, variantName ) );
398 BOOST_CHECK( symbol->GetExcludedFromBoard( &sheet, variantName ) );
399 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &sheet, variantName ) );
400 BOOST_CHECK( !symbol->GetExcludedFromSim( &sheet, variantName ) );
401
402 // Base properties must remain unchanged.
403 BOOST_CHECK( !symbol->GetDNP() );
404 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
405 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
406 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
407}
408
409
413BOOST_AUTO_TEST_CASE( VariantDescription )
414{
415 wxFileName fn;
416 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
417 fn.AppendDir( wxS( "variant_test" ) );
418 fn.SetName( wxS( "variant_test" ) );
420
421 LoadSchematic( fn.GetFullPath() );
422 BOOST_REQUIRE( m_schematic );
423
424 wxString variantName = wxS( "TestVariant" );
425 wxString description = wxS( "This is a test variant description" );
426
427 // Add a variant
428 m_schematic->AddVariant( variantName );
429 BOOST_CHECK( m_schematic->GetVariantNames().contains( variantName ) );
430
431 // Set description
432 m_schematic->SetVariantDescription( variantName, description );
433 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( variantName ), description );
434
435 // Empty description for non-existent variant
436 BOOST_CHECK( m_schematic->GetVariantDescription( wxS( "NonExistent" ) ).IsEmpty() );
437
438 // Clear description
439 m_schematic->SetVariantDescription( variantName, wxEmptyString );
440 BOOST_CHECK( m_schematic->GetVariantDescription( variantName ).IsEmpty() );
441}
442
443
447BOOST_AUTO_TEST_CASE( TextVariableVARIANT )
448{
449 wxFileName fn;
450 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
451 fn.AppendDir( wxS( "variant_test" ) );
452 fn.SetName( wxS( "variant_test" ) );
454
455 LoadSchematic( fn.GetFullPath() );
456 BOOST_REQUIRE( m_schematic );
457
458 wxString variantName = wxS( "MilitaryGrade" );
459
460 // Add a variant and set it as current
461 m_schematic->AddVariant( variantName );
462 m_schematic->SetCurrentVariant( variantName );
463
464 // Test that ${VARIANT} resolves to the current variant name
465 wxString token = wxS( "VARIANT" );
466 bool resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
467 BOOST_CHECK( resolved );
468 BOOST_CHECK_EQUAL( token, variantName );
469
470 // Also test VARIANTNAME (legacy/alias)
471 token = wxS( "VARIANTNAME" );
472 resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
473 BOOST_CHECK( resolved );
474 BOOST_CHECK_EQUAL( token, variantName );
475
476 // Empty variant
477 m_schematic->SetCurrentVariant( wxEmptyString );
478 token = wxS( "VARIANT" );
479 resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
480 BOOST_CHECK( resolved );
481 BOOST_CHECK( token.IsEmpty() );
482}
483
484
488BOOST_AUTO_TEST_CASE( TextVariableVARIANT_DESC )
489{
490 wxFileName fn;
491 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
492 fn.AppendDir( wxS( "variant_test" ) );
493 fn.SetName( wxS( "variant_test" ) );
495
496 LoadSchematic( fn.GetFullPath() );
497 BOOST_REQUIRE( m_schematic );
498
499 wxString variantName = wxS( "IndustrialVariant" );
500 wxString description = wxS( "Industrial temperature range components" );
501
502 // Add a variant with description and set it as current
503 m_schematic->AddVariant( variantName );
504 m_schematic->SetVariantDescription( variantName, description );
505 m_schematic->SetCurrentVariant( variantName );
506
507 // Test that ${VARIANT_DESC} resolves to the variant description
508 wxString token = wxS( "VARIANT_DESC" );
509 bool resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
510 BOOST_CHECK( resolved );
511 BOOST_CHECK_EQUAL( token, description );
512
513 // Test with no description set
514 m_schematic->SetVariantDescription( variantName, wxEmptyString );
515 token = wxS( "VARIANT_DESC" );
516 resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
517 BOOST_CHECK( resolved );
518 BOOST_CHECK( token.IsEmpty() );
519}
520
521
525BOOST_AUTO_TEST_CASE( RenameVariantPreservesData )
526{
527 wxFileName fn;
528 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
529 fn.AppendDir( wxS( "variant_test" ) );
530 fn.SetName( wxS( "variant_test" ) );
532
533 LoadSchematic( fn.GetFullPath() );
534 BOOST_REQUIRE( m_schematic );
535
536 SCH_SYMBOL* symbol = GetFirstSymbol();
537 BOOST_REQUIRE( symbol );
538
539 wxString oldName = wxS( "OriginalVariant" );
540 wxString newName = wxS( "RenamedVariant" );
541 wxString description = wxS( "Original description" );
542
543 // Set up the variant with data
544 m_schematic->AddVariant( oldName );
545 m_schematic->SetVariantDescription( oldName, description );
546 m_schematic->SetCurrentVariant( oldName );
547
548 // Set symbol variant properties
549 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], oldName );
550 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "100K" ), &m_schematic->Hierarchy()[0], oldName );
551
552 // Verify the data is set
553 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], oldName ) );
554 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
555 INTERNAL, oldName ), wxS( "100K" ) );
556
557 // Rename the variant
558 m_schematic->RenameVariant( oldName, newName );
559
560 // Verify old name is gone
561 BOOST_CHECK( !m_schematic->GetVariantNames().contains( oldName ) );
562
563 // Verify new name exists
564 BOOST_CHECK( m_schematic->GetVariantNames().contains( newName ) );
565
566 // Verify description was preserved
567 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( newName ), description );
568
569 // Verify current variant was updated
570 BOOST_CHECK_EQUAL( m_schematic->GetCurrentVariant(), newName );
571
572 // Verify symbol variant data was preserved
573 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], newName ) );
574 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
575 INTERNAL, newName ), wxS( "100K" ) );
576}
577
578
582BOOST_AUTO_TEST_CASE( CopyVariantCreatesIndependentCopy )
583{
584 wxFileName fn;
585 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
586 fn.AppendDir( wxS( "variant_test" ) );
587 fn.SetName( wxS( "variant_test" ) );
589
590 LoadSchematic( fn.GetFullPath() );
591 BOOST_REQUIRE( m_schematic );
592
593 SCH_SYMBOL* symbol = GetFirstSymbol();
594 BOOST_REQUIRE( symbol );
595
596 wxString sourceVariant = wxS( "SourceVariant" );
597 wxString copyVariant = wxS( "CopiedVariant" );
598 wxString description = wxS( "Source description" );
599
600 // Set up the source variant
601 m_schematic->AddVariant( sourceVariant );
602 m_schematic->SetVariantDescription( sourceVariant, description );
603
604 // Set symbol variant properties for source
605 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], sourceVariant );
606 symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], sourceVariant );
607 symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], sourceVariant );
608 symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], sourceVariant );
609 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "47K" ), &m_schematic->Hierarchy()[0], sourceVariant );
610
611 // Copy the variant
612 m_schematic->CopyVariant( sourceVariant, copyVariant );
613
614 // Verify both variants exist
615 BOOST_CHECK( m_schematic->GetVariantNames().contains( sourceVariant ) );
616 BOOST_CHECK( m_schematic->GetVariantNames().contains( copyVariant ) );
617
618 // Verify description was copied
619 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( copyVariant ), description );
620
621 // Verify symbol properties were copied
622 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], copyVariant ) );
623 BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], copyVariant ) );
624 BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], copyVariant ) );
625 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], copyVariant ) );
626 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
627 INTERNAL, copyVariant ), wxS( "47K" ) );
628
629 // Modify the copy and verify source is unchanged
630 symbol->SetDNP( false, &m_schematic->Hierarchy()[0], copyVariant );
631 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "100K" ), &m_schematic->Hierarchy()[0], copyVariant );
632
633 // Source should still have original values
634 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], sourceVariant ) );
635 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
636 INTERNAL, sourceVariant ), wxS( "47K" ) );
637
638 // Copy should have modified values
639 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], copyVariant ) );
640 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
641 INTERNAL, copyVariant ), wxS( "100K" ) );
642}
643
644
648BOOST_AUTO_TEST_CASE( VariantFieldDifferenceDetection )
649{
650 wxFileName fn;
651 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
652 fn.AppendDir( wxS( "variant_test" ) );
653 fn.SetName( wxS( "variant_test" ) );
655
656 LoadSchematic( fn.GetFullPath() );
657 BOOST_REQUIRE( m_schematic );
658
659 SCH_SYMBOL* symbol = GetFirstSymbol();
660 BOOST_REQUIRE( symbol );
661
662 wxString variantName1 = wxS( "DiffTestVariant1" );
663 wxString variantName2 = wxS( "DiffTestVariant2" );
664
665 // Get the default value
666 wxString defaultValue = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
667 INTERNAL );
668 BOOST_CHECK_EQUAL( defaultValue, wxS( "1K" ) );
669
670 // Add a variant and set a different value
671 m_schematic->AddVariant( variantName1 );
672 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "2.2K" ), &m_schematic->Hierarchy()[0], variantName1 );
673
674 // Get variant value
675 wxString variantValue = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
676 INTERNAL, variantName1 );
677 BOOST_CHECK_EQUAL( variantValue, wxS( "2.2K" ) );
678
679 // Verify values differ
680 BOOST_CHECK( defaultValue != variantValue );
681
682 // Add another variant with same value as default to verify equality detection
683 m_schematic->AddVariant( variantName2 );
684 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "1K" ), &m_schematic->Hierarchy()[0], variantName2 );
685 wxString variantValue2 = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
686 INTERNAL, variantName2 );
687
688 // Second variant should have the same value as default
689 BOOST_CHECK_EQUAL( defaultValue, variantValue2 );
690}
691
692
696BOOST_AUTO_TEST_CASE( VariantDNPFiltering )
697{
698 wxFileName fn;
699 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
700 fn.AppendDir( wxS( "variant_test" ) );
701 fn.SetName( wxS( "variant_test" ) );
703
704 LoadSchematic( fn.GetFullPath() );
705 BOOST_REQUIRE( m_schematic );
706
707 SCH_SYMBOL* symbol = GetFirstSymbol();
708 BOOST_REQUIRE( symbol );
709
710 wxString variantName = wxS( "DNPVariant" );
711
712 // By default, symbol should not be DNP
713 BOOST_CHECK( !symbol->GetDNP() );
714 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], wxEmptyString ) );
715
716 // Add a variant where symbol is DNP
717 m_schematic->AddVariant( variantName );
718 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
719
720 // Default should still not be DNP
721 BOOST_CHECK( !symbol->GetDNP() );
722 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], wxEmptyString ) );
723
724 // Variant should be DNP
725 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
726
727 // Test exclude from BOM as well
728 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
729 symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], variantName );
730 BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], variantName ) );
731 BOOST_CHECK( !symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], wxEmptyString ) );
732
733 // Test exclude from board as well
734 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
735 symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], variantName );
736 BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], variantName ) );
737 BOOST_CHECK( !symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], wxEmptyString ) );
738
739 // Test exclude from position files as well
740 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
741 symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], variantName );
742 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], variantName ) );
743 BOOST_CHECK( !symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], wxEmptyString ) );
744}
745
746
750BOOST_AUTO_TEST_CASE( GetVariantNamesForUI )
751{
752 wxFileName fn;
753 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
754 fn.AppendDir( wxS( "variant_test" ) );
755 fn.SetName( wxS( "variant_test" ) );
757
758 LoadSchematic( fn.GetFullPath() );
759 BOOST_REQUIRE( m_schematic );
760
761 // Add some variants
762 m_schematic->AddVariant( wxS( "Zebra" ) );
763 m_schematic->AddVariant( wxS( "Alpha" ) );
764 m_schematic->AddVariant( wxS( "Beta" ) );
765
766 wxArrayString variantNames = m_schematic->GetVariantNamesForUI();
767
768 // Should have at least 4 items (default + 3 variants)
769 BOOST_CHECK( variantNames.GetCount() >= 4 );
770
771 // First item should be the default placeholder
772 // The actual string may vary but should represent "default"
773 BOOST_CHECK( !variantNames[0].IsEmpty() );
774
775 // Remaining items should be sorted
776 // Alpha, Beta, Zebra
777 bool foundAlpha = false;
778 bool foundBeta = false;
779 bool foundZebra = false;
780
781 for( size_t i = 1; i < variantNames.GetCount(); i++ )
782 {
783 if( variantNames[i] == wxS( "Alpha" ) )
784 foundAlpha = true;
785 else if( variantNames[i] == wxS( "Beta" ) )
786 foundBeta = true;
787 else if( variantNames[i] == wxS( "Zebra" ) )
788 foundZebra = true;
789 }
790
791 BOOST_CHECK( foundAlpha );
792 BOOST_CHECK( foundBeta );
793 BOOST_CHECK( foundZebra );
794}
795
796
802BOOST_AUTO_TEST_CASE( SetValueFieldTextPersistsVariantValue )
803{
804 wxFileName fn;
805 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
806 fn.AppendDir( wxS( "variant_test" ) );
807 fn.SetName( wxS( "variant_test" ) );
809
810 LoadSchematic( fn.GetFullPath() );
811 BOOST_REQUIRE( m_schematic );
812
813 SCH_SYMBOL* symbol = GetFirstSymbol();
814 BOOST_REQUIRE( symbol );
815
816 wxString variantName = wxS( "PersistenceTest" );
817 wxString newValue = wxS( "4.7K" );
818 wxString defaultValue = symbol->GetField( FIELD_T::VALUE )->GetText();
819
820 // Add the variant
821 m_schematic->AddVariant( variantName );
822
823 // Set value using SetValueFieldText (the function that had the bug)
824 symbol->SetValueFieldText( newValue, &m_schematic->Hierarchy()[0], variantName );
825
826 // Verify that the variant value was actually saved by reading it back
827 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
828 BOOST_REQUIRE( variant.has_value() );
829
830 wxString fieldName = symbol->GetField( FIELD_T::VALUE )->GetName();
831 BOOST_CHECK( variant->m_Fields.contains( fieldName ) );
832 BOOST_CHECK_EQUAL( variant->m_Fields.at( fieldName ), newValue );
833
834 // Verify through GetValue method as well
835 wxString retrievedValue = symbol->GetValue( &m_schematic->Hierarchy()[0], RAW_VALUE, variantName );
836 BOOST_CHECK_EQUAL( retrievedValue, newValue );
837
838 // Verify default value is unchanged
839 wxString retrievedDefault = symbol->GetValue( &m_schematic->Hierarchy()[0], RAW_VALUE, wxEmptyString );
840 BOOST_CHECK_EQUAL( retrievedDefault, defaultValue );
841}
842
843
847BOOST_AUTO_TEST_CASE( SetFieldTextAndSetValueFieldTextConsistency )
848{
849 wxFileName fn;
850 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
851 fn.AppendDir( wxS( "variant_test" ) );
852 fn.SetName( wxS( "variant_test" ) );
854
855 LoadSchematic( fn.GetFullPath() );
856 BOOST_REQUIRE( m_schematic );
857
858 SCH_SYMBOL* symbol = GetFirstSymbol();
859 BOOST_REQUIRE( symbol );
860
861 wxString variantName1 = wxS( "MethodTest1" );
862 wxString variantName2 = wxS( "MethodTest2" );
863 wxString value1 = wxS( "10K" );
864 wxString value2 = wxS( "22K" );
865 wxString fieldName = symbol->GetField( FIELD_T::VALUE )->GetName();
866
867 m_schematic->AddVariant( variantName1 );
868 m_schematic->AddVariant( variantName2 );
869
870 // Set variant 1 using SetValueFieldText
871 symbol->SetValueFieldText( value1, &m_schematic->Hierarchy()[0], variantName1 );
872
873 // Set variant 2 using SetFieldText
874 symbol->SetFieldText( fieldName, value2, &m_schematic->Hierarchy()[0], variantName2 );
875
876 // Both methods should produce the same result structure
877 std::optional<SCH_SYMBOL_VARIANT> variant1 = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName1 );
878 std::optional<SCH_SYMBOL_VARIANT> variant2 = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName2 );
879
880 BOOST_REQUIRE( variant1.has_value() );
881 BOOST_REQUIRE( variant2.has_value() );
882
883 BOOST_CHECK( variant1->m_Fields.contains( fieldName ) );
884 BOOST_CHECK( variant2->m_Fields.contains( fieldName ) );
885
886 BOOST_CHECK_EQUAL( variant1->m_Fields.at( fieldName ), value1 );
887 BOOST_CHECK_EQUAL( variant2->m_Fields.at( fieldName ), value2 );
888
889 // Verify through GetValue
890 BOOST_CHECK_EQUAL( symbol->GetValue( &m_schematic->Hierarchy()[0], RAW_VALUE, variantName1 ), value1 );
891 BOOST_CHECK_EQUAL( symbol->GetValue( &m_schematic->Hierarchy()[0], RAW_VALUE, variantName2 ), value2 );
892
893 // Verify through GetFieldText
894 BOOST_CHECK_EQUAL( symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], variantName1 ), value1 );
895 BOOST_CHECK_EQUAL( symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], variantName2 ), value2 );
896}
897
898
903BOOST_AUTO_TEST_CASE( VariantNameHandling )
904{
905 wxFileName fn;
906 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
907 fn.AppendDir( wxS( "variant_test" ) );
908 fn.SetName( wxS( "variant_test" ) );
910
911 LoadSchematic( fn.GetFullPath() );
912 BOOST_REQUIRE( m_schematic );
913
914 SCH_SYMBOL* symbol = GetFirstSymbol();
915 BOOST_REQUIRE( symbol );
916
917 wxString variantName = wxS( "ProductionVariant" );
918
919 // Add variant with specific casing
920 m_schematic->AddVariant( variantName );
921
922 // Set DNP on variant
923 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
924
925 // Verify with exact case - this should work
926 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], wxS( "ProductionVariant" ) ) );
927
928 // Verify variant exists
929 BOOST_CHECK( m_schematic->GetVariantNames().contains( wxS( "ProductionVariant" ) ) );
930
931 // Set and get current variant
932 m_schematic->SetCurrentVariant( variantName );
933 BOOST_CHECK_EQUAL( m_schematic->GetCurrentVariant(), variantName );
934
935 // Unknown variant should return base DNP (false)
936 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], wxS( "NonExistentVariant" ) ) );
937}
938
939
943BOOST_AUTO_TEST_CASE( VariantDeletionCascade )
944{
945 wxFileName fn;
946 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
947 fn.AppendDir( wxS( "variant_test" ) );
948 fn.SetName( wxS( "variant_test" ) );
950
951 LoadSchematic( fn.GetFullPath() );
952 BOOST_REQUIRE( m_schematic );
953
954 SCH_SYMBOL* symbol = GetFirstSymbol();
955 BOOST_REQUIRE( symbol );
956
957 wxString variantName = wxS( "DeleteMe" );
958
959 // Add variant and set properties
960 m_schematic->AddVariant( variantName );
961 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
962 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "DeletedValue" ), &m_schematic->Hierarchy()[0], variantName );
963
964 // Verify data is set
965 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
966 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
967 BOOST_CHECK( variant.has_value() );
968
969 // Delete the variant
970 TOOL_MANAGER manager;
971 manager.SetEnvironment( m_schematic.get(), nullptr, nullptr, nullptr, nullptr );
972 SCH_COMMIT commit( &manager );
973 m_schematic->DeleteVariant( variantName, &commit );
974
975 // Variant should no longer exist at schematic level
976 BOOST_CHECK( !m_schematic->GetVariantNames().contains( variantName ) );
977
978 // After deletion, querying DNP for non-existent variant should return base value
979 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
980}
981
982
986BOOST_AUTO_TEST_CASE( VariantFieldUnicodeAndSpecialChars )
987{
988 wxFileName fn;
989 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
990 fn.AppendDir( wxS( "variant_test" ) );
991 fn.SetName( wxS( "variant_test" ) );
993
994 LoadSchematic( fn.GetFullPath() );
995 BOOST_REQUIRE( m_schematic );
996
997 SCH_SYMBOL* symbol = GetFirstSymbol();
998 BOOST_REQUIRE( symbol );
999
1000 wxString variantName = wxS( "UnicodeTest" );
1001 m_schematic->AddVariant( variantName );
1002
1003 // Test Unicode characters in field values
1004 wxString unicodeValue = wxS( "1kΩ ±5% 日本語" );
1005 symbol->GetField( FIELD_T::VALUE )->SetText( unicodeValue, &m_schematic->Hierarchy()[0], variantName );
1006
1007 wxString retrieved;
1008 retrieved = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, variantName );
1009 BOOST_CHECK_EQUAL( retrieved, unicodeValue );
1010
1011 // Test special characters
1012 wxString specialChars = wxS( "R<1K>\"test\"'value'" );
1013 symbol->GetField( FIELD_T::VALUE )->SetText( specialChars, &m_schematic->Hierarchy()[0], variantName );
1014
1015 retrieved = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, variantName );
1016 BOOST_CHECK_EQUAL( retrieved, specialChars );
1017
1018 // Test empty string
1019 symbol->GetField( FIELD_T::VALUE )->SetText( wxEmptyString, &m_schematic->Hierarchy()[0], variantName );
1020 retrieved = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, variantName );
1021 BOOST_CHECK( retrieved.IsEmpty() );
1022
1023 // Test description with unicode
1024 wxString unicodeDesc = wxS( "Variante für Produktion — 测试" );
1025 m_schematic->SetVariantDescription( variantName, unicodeDesc );
1026 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( variantName ), unicodeDesc );
1027}
1028
1029
1033BOOST_AUTO_TEST_CASE( VariantSpecificFieldDereferencing )
1034{
1035 wxFileName fn;
1036 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1037 fn.AppendDir( wxS( "variant_test" ) );
1038 fn.SetName( wxS( "variant_test" ) );
1040
1041 LoadSchematic( fn.GetFullPath() );
1042 BOOST_REQUIRE( m_schematic );
1043
1044 SCH_SYMBOL* symbol = GetFirstSymbol();
1045 BOOST_REQUIRE( symbol );
1046
1047 wxString variantName = wxS( "MilitaryGrade" );
1048 wxString variantValue = wxS( "1K-MIL" );
1049 wxString defaultValue = wxS( "1K" );
1050
1051 // Create a variant with a different value field
1052 m_schematic->AddVariant( variantName );
1053 symbol->GetField( FIELD_T::VALUE )->SetText( variantValue, &m_schematic->Hierarchy()[0], variantName );
1054 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
1055
1056 // Verify default value
1057 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL ),
1058 defaultValue );
1059
1060 // Get the symbol's reference (R1) for cross-reference testing
1061 wxString symbolRef = symbol->GetRef( &m_schematic->Hierarchy()[0], false );
1062
1063 // Test 1: ResolveCrossReference with variant syntax - should return variant-specific value
1064 wxString token = symbolRef + wxS( ":VALUE:" ) + variantName;
1065 bool resolved = m_schematic->ResolveCrossReference( &token, 0 );
1066 BOOST_CHECK( resolved );
1067 BOOST_CHECK_EQUAL( token, variantValue );
1068
1069 // Test 2: ResolveCrossReference without variant - should return default value
1070 token = symbolRef + wxS( ":VALUE" );
1071 resolved = m_schematic->ResolveCrossReference( &token, 0 );
1072 BOOST_CHECK( resolved );
1073 BOOST_CHECK_EQUAL( token, defaultValue );
1074
1075 // Test 3: ResolveCrossReference with non-existent variant - should return default value
1076 token = symbolRef + wxS( ":VALUE:NonExistentVariant" );
1077 resolved = m_schematic->ResolveCrossReference( &token, 0 );
1078 BOOST_CHECK( resolved );
1079 BOOST_CHECK_EQUAL( token, defaultValue );
1080
1081 // Test 4: ResolveTextVar with variant parameter directly
1082 token = wxS( "VALUE" );
1083 resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, variantName, 0 );
1084 BOOST_CHECK( resolved );
1085 BOOST_CHECK_EQUAL( token, variantValue );
1086
1087 // Test 5: ResolveTextVar with empty variant - should return default
1088 m_schematic->SetCurrentVariant( variantName );
1089 token = wxS( "VALUE" );
1090 resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, wxEmptyString, 0 );
1091 BOOST_CHECK( resolved );
1092 BOOST_CHECK_EQUAL( token, defaultValue );
1093
1094 // Test 6: ResolveTextVar DNP without a variant parameter - should return current variant
1095 token = wxS( "DNP" );
1096 resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
1097 BOOST_CHECK( resolved );
1098 BOOST_CHECK_EQUAL( token, wxS( "DNP" ) );
1099
1100 // Test 7: ResolveTextVar DNP with empty variant - should return default
1101 token = wxS( "DNP" );
1102 resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, wxEmptyString, 0 );
1103 BOOST_CHECK( resolved );
1104 BOOST_CHECK_EQUAL( token, wxEmptyString );
1105}
1106
1107
1113BOOST_AUTO_TEST_CASE( FootprintFieldVariantSupport )
1114{
1115 wxFileName fn;
1116 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1117 fn.AppendDir( wxS( "variant_test" ) );
1118 fn.SetName( wxS( "variant_test" ) );
1120
1121 LoadSchematic( fn.GetFullPath() );
1122 BOOST_REQUIRE( m_schematic );
1123
1124 SCH_SYMBOL* symbol = GetFirstSymbol();
1125 BOOST_REQUIRE( symbol );
1126
1127 wxString variantName = wxS( "FootprintVariant" );
1128 wxString baseFootprint = wxS( "Resistor_SMD:R_0805_2012Metric" );
1129 wxString variantFootprint = wxS( "Resistor_SMD:R_0402_1005Metric" );
1130 wxString fieldName = symbol->GetField( FIELD_T::FOOTPRINT )->GetName();
1131
1132 // Set a base footprint first
1133 symbol->SetFootprintFieldText( baseFootprint );
1134 BOOST_CHECK_EQUAL( symbol->GetFootprintFieldText( nullptr, RAW_VALUE ), baseFootprint );
1135
1136 // Add the variant
1137 m_schematic->AddVariant( variantName );
1138
1139 // Set a different footprint for the variant using SetFieldText
1140 symbol->SetFieldText( fieldName, variantFootprint, &m_schematic->Hierarchy()[0], variantName );
1141
1142 // Verify base footprint is unchanged
1143 wxString retrievedBase = symbol->GetFootprintFieldText( nullptr, RAW_VALUE );
1144 BOOST_CHECK_EQUAL( retrievedBase, baseFootprint );
1145
1146 // Verify GetFieldText with no variant returns base footprint
1147 wxString retrievedDefault = symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], wxEmptyString );
1148 BOOST_CHECK_EQUAL( retrievedDefault, baseFootprint );
1149
1150 // Verify GetFieldText with variant returns variant-specific footprint
1151 wxString retrievedVariant = symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], variantName );
1152 BOOST_CHECK_EQUAL( retrievedVariant, variantFootprint );
1153
1154 // Verify that the variant data structure contains the footprint override
1155 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
1156 BOOST_REQUIRE( variant.has_value() );
1157 BOOST_CHECK( variant->m_Fields.contains( fieldName ) );
1158 BOOST_CHECK_EQUAL( variant->m_Fields.at( fieldName ), variantFootprint );
1159}
1160
1161
1166BOOST_AUTO_TEST_CASE( FootprintFieldVariantNoOpWhenSame )
1167{
1168 wxFileName fn;
1169 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1170 fn.AppendDir( wxS( "variant_test" ) );
1171 fn.SetName( wxS( "variant_test" ) );
1173
1174 LoadSchematic( fn.GetFullPath() );
1175 BOOST_REQUIRE( m_schematic );
1176
1177 SCH_SYMBOL* symbol = GetFirstSymbol();
1178 BOOST_REQUIRE( symbol );
1179
1180 wxString variantName = wxS( "NoOpTest" );
1181 wxString baseFootprint = wxS( "Resistor_SMD:R_0805_2012Metric" );
1182 wxString fieldName = symbol->GetField( FIELD_T::FOOTPRINT )->GetName();
1183
1184 // Set a base footprint first
1185 symbol->SetFootprintFieldText( baseFootprint );
1186
1187 // Add the variant
1188 m_schematic->AddVariant( variantName );
1189
1190 // Set the same footprint value for the variant
1191 symbol->SetFieldText( fieldName, baseFootprint, &m_schematic->Hierarchy()[0], variantName );
1192
1193 // Verify that no variant override was created since the value is the same
1194 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
1195
1196 // Either no variant was created, or it exists but doesn't have a footprint override
1197 if( variant.has_value() )
1198 {
1199 BOOST_CHECK( !variant->m_Fields.contains( fieldName ) );
1200 }
1201}
1202
1203
1208BOOST_AUTO_TEST_CASE( VariantSwitchInvalidatesBoundingBoxCache )
1209{
1210 wxFileName fn;
1211 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1212 fn.AppendDir( wxS( "variant_test" ) );
1213 fn.SetName( wxS( "variant_test" ) );
1215
1216 LoadSchematic( fn.GetFullPath() );
1217 BOOST_REQUIRE( m_schematic );
1218
1219 // GetShownText(bool) resolves variants via CurrentSheet(), so we must set it
1220 m_schematic->SetCurrentSheet( m_schematic->Hierarchy()[0] );
1221
1222 SCH_SYMBOL* symbol = GetFirstSymbol();
1223 BOOST_REQUIRE( symbol );
1224
1225 SCH_FIELD* fpField = symbol->GetField( FIELD_T::FOOTPRINT );
1226 BOOST_REQUIRE( fpField );
1227
1228 wxString variantName = wxS( "BboxVariant" );
1229 wxString shortFp = wxS( "R_0402" );
1230 wxString longFp = wxS( "Resistor_SMD:R_2512_6332Metric_Pad1.52x3.35mm_HandSolder" );
1231
1232 symbol->SetFootprintFieldText( shortFp );
1233 fpField->SetVisible( true );
1234 fpField->ClearBoundingBoxCache();
1235
1236 m_schematic->AddVariant( variantName );
1237 symbol->SetFieldText( fpField->GetName(), longFp, &m_schematic->Hierarchy()[0], variantName );
1238
1239 // Confirm variant text resolution works
1240 wxString resolvedDefault = fpField->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, wxEmptyString );
1241 wxString resolvedVariant = fpField->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, variantName );
1242 BOOST_CHECK_EQUAL( resolvedDefault, shortFp );
1243 BOOST_CHECK_EQUAL( resolvedVariant, longFp );
1244
1245 // Verify the implicit text resolution via GetShownText(bool) works for each variant
1246 m_schematic->SetCurrentVariant( wxEmptyString );
1247 wxString implicitDefault = fpField->GetShownText( INTERNAL );
1248
1249 m_schematic->SetCurrentVariant( variantName );
1250 wxString implicitVariant = fpField->GetShownText( INTERNAL );
1251
1252 BOOST_CHECK_EQUAL( implicitDefault, shortFp );
1253 BOOST_CHECK_EQUAL( implicitVariant, longFp );
1254
1255 // Prime the bounding box cache with the default variant (short footprint text)
1256 m_schematic->SetCurrentVariant( wxEmptyString );
1257 fpField->ClearBoundingBoxCache();
1258 BOX2I defaultTextBox = fpField->GetTextBox( nullptr );
1259
1260 // Switch to the variant with a much longer footprint string.
1261 // SetCurrentVariant must invalidate caches so the new text is reflected.
1262 m_schematic->SetCurrentVariant( variantName );
1263 BOX2I variantTextBox = fpField->GetTextBox( nullptr );
1264
1265 // The longer text must produce a wider text box. If the bounding box cache was not
1266 // invalidated on variant switch, both boxes would be identical.
1267 BOOST_CHECK_GT( variantTextBox.GetWidth(), defaultTextBox.GetWidth() );
1268
1269 // Switch back and verify it returns to the original width
1270 m_schematic->SetCurrentVariant( wxEmptyString );
1271 BOX2I restoredTextBox = fpField->GetTextBox( nullptr );
1272 BOOST_CHECK_EQUAL( restoredTextBox.GetWidth(), defaultTextBox.GetWidth() );
1273}
1274
1275
1286BOOST_AUTO_TEST_CASE( VariantAttributeInitFromSymbol )
1287{
1288 wxFileName fn;
1289 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1290 fn.AppendDir( wxS( "variant_test" ) );
1291 fn.SetName( wxS( "variant_test" ) );
1293
1294 LoadSchematic( fn.GetFullPath() );
1295 BOOST_REQUIRE( m_schematic );
1296
1297 SCH_SYMBOL* symbol = GetFirstSymbol();
1298 BOOST_REQUIRE( symbol );
1299
1300 // Set all default attributes to true on the symbol
1301 symbol->SetDNP( true );
1302 symbol->SetExcludedFromBOM( true );
1303 symbol->SetExcludedFromSim( true );
1304 symbol->SetExcludedFromBoard( true );
1305 symbol->SetExcludedFromPosFiles( true );
1306
1307 // Default-constructed variant has all-false attributes
1308 SCH_SYMBOL_VARIANT defaultVariant( wxS( "Default" ) );
1309 BOOST_CHECK( !defaultVariant.m_DNP );
1310 BOOST_CHECK( !defaultVariant.m_ExcludedFromBOM );
1311 BOOST_CHECK( !defaultVariant.m_ExcludedFromSim );
1312 BOOST_CHECK( !defaultVariant.m_ExcludedFromBoard );
1313 BOOST_CHECK( !defaultVariant.m_ExcludedFromPosFiles );
1314
1315 // InitializeAttributes should copy the symbol's attributes
1316 SCH_SYMBOL_VARIANT initializedVariant( wxS( "Initialized" ) );
1317 initializedVariant.InitializeAttributes( *symbol );
1318
1319 BOOST_CHECK_MESSAGE( initializedVariant.m_DNP,
1320 "InitializeAttributes should copy DNP from symbol" );
1321 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromBOM,
1322 "InitializeAttributes should copy ExcludedFromBOM from symbol" );
1323 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromSim,
1324 "InitializeAttributes should copy ExcludedFromSim from symbol" );
1325 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromBoard,
1326 "InitializeAttributes should copy ExcludedFromBoard from symbol" );
1327 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromPosFiles,
1328 "InitializeAttributes should copy ExcludedFromPosFiles from symbol" );
1329}
1330
1331
1342BOOST_AUTO_TEST_CASE( MatchesExcludesFieldText )
1343{
1344 LIB_SYMBOL* libSym = new LIB_SYMBOL( wxS( "+5V" ) );
1345 libSym->GetValueField().SetText( wxS( "+5V" ) );
1346 libSym->SetDescription( wxS( "power rail" ) );
1347
1348 SCH_SYMBOL symbol( *libSym, libSym->GetLibId(), nullptr, 0, 0, VECTOR2I() );
1349 symbol.GetField( FIELD_T::VALUE )->SetText( wxS( "+5VA" ) );
1350
1351 SCH_FIELD customField( &symbol, FIELD_T::USER, wxS( "MyField" ) );
1352 customField.SetText( wxS( "aayyxx" ) );
1353 customField.SetVisible( true );
1354 SCH_FIELD* custom = symbol.AddField( customField );
1355
1356 SCH_SHEET_PATH sheetPath;
1357
1358 SCH_SEARCH_DATA data;
1359 data.findString = wxS( "aayyxx" );
1361
1362 // a custom field hit must be a single hit, not also the symbol and the reference
1363 BOOST_CHECK( custom->Matches( data, &sheetPath ) );
1364 BOOST_CHECK( !symbol.Matches( data, &sheetPath ) );
1365 BOOST_CHECK( !symbol.GetField( FIELD_T::REFERENCE )->Matches( data, &sheetPath ) );
1366
1367 // whole-word "+5V" must not match a symbol whose value is "+5VA"
1368 data.findString = wxS( "+5V" );
1370 BOOST_CHECK( !symbol.Matches( data, &sheetPath ) );
1371 BOOST_CHECK( !symbol.GetField( FIELD_T::VALUE )->Matches( data, &sheetPath ) );
1372
1373 data.findString = wxS( "+5VA" );
1374 BOOST_CHECK( symbol.GetField( FIELD_T::VALUE )->Matches( data, &sheetPath ) );
1375
1376 // metadata search still surfaces the symbol, via the reference field in the
1377 // search pane
1378 data.findString = wxS( "power rail" );
1380 data.searchMetadata = true;
1381 BOOST_CHECK( symbol.Matches( data, &sheetPath ) );
1382 BOOST_CHECK( symbol.GetField( FIELD_T::REFERENCE )->Matches( data, &sheetPath ) );
1383
1384 data.searchMetadata = false;
1385 BOOST_CHECK( !symbol.Matches( data, &sheetPath ) );
1386
1387 delete libSym;
1388}
1389
1390
1391BOOST_AUTO_TEST_CASE( OperatingPointSkipsMissingSymbolPinMappings )
1392{
1393 wxFileName fn;
1394 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1395 fn.AppendDir( wxS( "variant_test" ) );
1396 fn.SetName( wxS( "variant_test" ) );
1398 LoadSchematic( fn.GetFullPath() );
1399 SCH_SYMBOL* symbol = GetFirstSymbol();
1400 BOOST_REQUIRE( symbol );
1401 BOOST_REQUIRE( symbol->GetPin( wxS( "1" ) ) );
1402 BOOST_REQUIRE( symbol->GetPin( wxS( "2" ) ) );
1403 BOOST_REQUIRE( !symbol->GetPin( wxS( "999" ) ) );
1404 const SCH_SHEET_PATH path = m_schematic->Hierarchy()[0];
1405
1406 SetFieldValue( symbol->GetFields(), SIM_DEVICE_FIELD, "R" );
1407 SetFieldValue( symbol->GetFields(), SIM_PARAMS_FIELD, "r=1k" );
1408 SetFieldValue( symbol->GetFields(), SIM_PINS_FIELD, "999=+ 2=-" );
1409
1410 SIM_LIB_MGR manager( &m_schematic->Project() );
1412 const auto input = SIM_LIB_MGR::CaptureModelInput( &path, *symbol, 0, wxString() );
1413 const auto owned = manager.CreateModel( input, true, reporter );
1414 const auto live = manager.CreateModel( &path, *symbol, true, 0, wxString(), reporter );
1415 BOOST_CHECK_MESSAGE( !reporter.HasMessage(), reporter.GetMessages() );
1416 BOOST_REQUIRE_EQUAL( owned.model.GetPinCount(), 2 );
1417 BOOST_REQUIRE_EQUAL( live.model.GetPinCount(), 2 );
1418 BOOST_CHECK_EQUAL( owned.model.GetPin( 0 ).symbolPinNumber, wxString( "999" ) );
1419 BOOST_CHECK_EQUAL( live.model.GetPin( 0 ).symbolPinNumber, wxString( "999" ) );
1420
1421 // A stale mapping must not prevent a later valid pin from resolving.
1422 wxString token = wxS( "OP:2" );
1423 BOOST_CHECK( symbol->ResolveTextVar( &path, &token, wxString(), 0 ) );
1424 BOOST_CHECK_EQUAL( token, wxString( "--" ) );
1425
1426 token = wxS( "OP:999" );
1427 BOOST_CHECK( symbol->ResolveTextVar( &path, &token, wxString(), 0 ) );
1428 BOOST_CHECK_EQUAL( token, wxString( "?" ) );
1429}
1430
1431
1432BOOST_AUTO_TEST_CASE( ExactMembershipAvoidsTextGeometryAndTracksTreeLifetime )
1433{
1434 LoadSchematic( wxString::FromUTF8( KI_TEST::GetEeschemaTestDataDir() ) + wxS( "/issue7203.kicad_sch" ) );
1435 auto symbols = m_schematic->Hierarchy().front().LastScreen()->Items().OfType( SCH_SYMBOL_T );
1436 BOOST_REQUIRE( symbols.begin() != symbols.end() );
1437
1438 struct COUNTED_SYMBOL : SCH_SYMBOL
1439 {
1440 explicit COUNTED_SYMBOL( const SCH_SYMBOL& aSource ) : SCH_SYMBOL( aSource ) {}
1441
1442 const BOX2I GetBoundingBox() const override
1443 {
1444 ++boundsReads;
1446 }
1447
1448 mutable unsigned boundsReads = 0;
1449 };
1450
1451 COUNTED_SYMBOL item( *static_cast<SCH_SYMBOL*>( *symbols.begin() ) );
1452 COUNTED_SYMBOL copy( item );
1453 EE_RTREE tree;
1454 tree.insert( &item );
1455 item.boundsReads = 0;
1456 copy.boundsReads = 0;
1457 BOOST_CHECK( tree.contains( &item, true ) );
1458 BOOST_CHECK( !tree.contains( &copy, true ) );
1459 BOOST_CHECK_EQUAL( item.boundsReads, 0u );
1460 BOOST_CHECK_EQUAL( copy.boundsReads, 0u );
1461 item.Move( VECTOR2I( 100000000, 100000000 ) );
1462 BOOST_CHECK( tree.contains( &item, true ) );
1463 tree.insert( &copy );
1464 BOOST_CHECK( tree.contains( &copy, true ) );
1465 tree.insert( &item );
1466 BOOST_REQUIRE( tree.remove( &item ) );
1467 BOOST_CHECK( tree.contains( &item, true ) );
1468 BOOST_REQUIRE( tree.remove( &item ) );
1469 BOOST_CHECK( !tree.contains( &item, true ) );
1470 BOOST_CHECK( !tree.remove( &item ) );
1471
1472 EE_RTREE moved( std::move( tree ) );
1473 BOOST_CHECK( moved.contains( &copy, true ) );
1474 BOOST_CHECK( !tree.contains( &copy, true ) );
1475 tree.insert( &item );
1476 tree = std::move( moved );
1477 BOOST_CHECK( tree.contains( &copy, true ) );
1478 BOOST_CHECK( !tree.contains( &item, true ) );
1479 BOOST_CHECK( !moved.contains( &copy, true ) );
1480 tree.clear();
1481 BOOST_CHECK( !tree.contains( &copy, true ) );
1482 tree.insert( &item );
1483 BOOST_CHECK( tree.contains( &item, true ) );
1484}
1485
1486BOOST_AUTO_TEST_CASE( SymbolPropertyReferencesUseTheExplicitPath )
1487{
1488 LOCALE_IO locale;
1489 SETTINGS_MANAGER settings;
1490 std::unique_ptr<SCHEMATIC> schematic;
1491 KI_TEST::LoadSchematic( settings, wxS( "issue23840/BusAndVectors" ), schematic );
1492 BOOST_REQUIRE_GT( schematic->Hierarchy().size(), 1 );
1493 size_t differentReferences = 0;
1494
1495 for( const SCH_SHEET_PATH& path : schematic->Hierarchy() )
1496 {
1497 for( SCH_ITEM* item : path.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1498 {
1499 auto* symbol = static_cast<SCH_SYMBOL*>( item );
1500 const wxString expected = symbol->GetRef( &path );
1501
1502 for( const SCH_SHEET_PATH& current : schematic->Hierarchy() )
1503 {
1504 if( current.LastScreen() != path.LastScreen() )
1505 continue;
1506
1507 schematic->SetCurrentSheet( current );
1508 differentReferences += symbol->GetRef( &current ) != expected;
1509 wxString token( "PROPERTY.Reference" );
1510 BOOST_REQUIRE( symbol->ResolveTextVar( &path, &token, 0 ) );
1511 BOOST_CHECK_EQUAL( token, expected );
1512 }
1513 }
1514 }
1515
1516 BOOST_CHECK_GT( differentReferences, 0 );
1517}
1518
1519
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr size_type GetWidth() const
Definition box2.h:211
EDA_ITEM * GetParent() const
Definition eda_item.h:112
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:153
BOX2I GetTextBox(const RENDER_SETTINGS *aSettings, int aLine=-1) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition eda_text.cpp:754
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:347
virtual void ClearBoundingBoxCache()
Definition eda_text.cpp:675
Implement an R-tree for fast spatial and type indexing of schematic items.
Definition sch_rtree.h:37
bool remove(SCH_ITEM *aItem)
Remove an item from the tree.
Definition sch_rtree.h:99
void insert(SCH_ITEM *aItem)
Insert an item into the tree.
Definition sch_rtree.h:70
bool contains(const SCH_ITEM *aItem, bool aRobust=false) const
Determine if a given item exists in the tree.
Definition sch_rtree.h:140
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:248
void clear()
Remove all items from the RTree.
Definition sch_rtree.h:124
Definition kiid.h:46
A generic fixture for loading schematics and associated settings for qa tests.
std::unique_ptr< SCHEMATIC > m_schematic
Define a library symbol object.
Definition lib_symbol.h:114
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:190
void SetDescription(const wxString &aDescription)
Set the Description field text value.
SCH_FIELD & GetValueField()
Definition lib_symbol.h:447
virtual void SetName(const wxString &aName)
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
Commit for the schematic and symbol editors.
Definition sch_commit.h:54
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:139
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
wxString GetShownText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString, int aDepth=0) const
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
void SetText(const wxString &aText) override
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
int GetUnit() const
Definition sch_item.h:243
virtual void SetUnit(int aUnit)
Definition sch_item.h:242
void SwapItemData(SCH_ITEM *aImage)
Swap data between aItem and aImage.
Definition sch_item.cpp:840
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:122
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Variant information for a schematic symbol.
void InitializeAttributes(const SCH_SYMBOL &aSymbol)
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 SetFieldText(const wxString &aFieldName, const wxString &aFieldText, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString)
wxString GetFieldText(const wxString &aFieldName, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString) const
void SetExcludedFromSim(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear the exclude from simulation flag.
const wxString GetFootprintFieldText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString) const
std::optional< SCH_SYMBOL_VARIANT > GetVariant(const SCH_SHEET_PATH &aInstance, const wxString &aVariantName) const
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void SetFootprintFieldText(const wxString &aFootprint)
void SetExcludedFromPosFiles(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the symbol.
void SetValueFieldText(const wxString &aValue, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString)
std::vector< SCH_PIN * > GetLibPins() const
Populate a vector with all the pins from the library object that match the current unit and bodyStyle...
bool GetExcludedFromPosFiles(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
const wxString GetValue(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString) const override
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
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.
virtual bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
void SetExcludedFromBoard(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
SIM_MODEL & CreateModel(SIM_MODEL::TYPE aType, std::span< const wxString > aPins, REPORTER &aReporter)
static SIM_MODEL_INPUT CaptureModelInput(const SCH_SHEET_PATH *aSheetPath, const SCH_SYMBOL &aSymbol, int aDepth, const wxString &aVariantName, const wxString &aMergedSimPins=wxEmptyString)
Resolve instance fields once; editors use the field-based overloads for unresolved input.
SCH_SYMBOL m_symbol
SCH_SYMBOL object with no extra data set.
Master controller class:
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, APP_SETTINGS_BASE *aSettings, TOOLS_HOLDER *aFrame)
Set the work environment (model, view, view controls and the parent window).
for transforming drawing coordinates for a wxDC device context.
Definition transform.h:42
bool m_ExcludedFromBOM
bool m_ExcludedFromPosFiles
bool m_ExcludedFromSim
bool m_ExcludedFromBoard
A wrapper for reporting to a wxString object.
Definition reporter.h:242
@ RAW_VALUE
Definition common.h:96
@ INTERNAL
Definition common.h:94
static const std::string KiCadSchematicFileExtension
std::string source
void LoadSchematic(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< SCHEMATIC > &aSchematic)
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
void SetFieldValue(std::vector< SCH_FIELD > &aFields, const wxString &aFieldName, const std::string &aValue, bool aIsVisible=true, const SCH_SHEET_PATH *aSheetPath=nullptr, const wxString &aVariantName=wxEmptyString)
Definition sch_field.h:457
static void LoadSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxString &aFileName)
#define SIM_PINS_FIELD
Definition sim_model.h:51
#define SIM_DEVICE_FIELD
Definition sim_model.h:49
#define SIM_PARAMS_FIELD
Definition sim_model.h:53
EDA_SEARCH_MATCH_MODE matchMode
#define ALL_UNITS
Definition symbol.h:150
#define ALL_BODY_STYLES
Definition symbol.h:151
@ SYM_ORIENT_270
Definition symbol.h:39
@ SYM_ORIENT_180
Definition symbol.h:38
@ SYM_ORIENT_90
Definition symbol.h:37
@ USER
The field ID hasn't been set yet; field is invalid.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
bool moved
std::string path
IbisParser parser & reporter
KIBIS_PIN * pin
VECTOR3I expected(15, 30, 45)
BOOST_AUTO_TEST_CASE(DefaultProperties)
Declare the test suite.
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_SYMBOL_T
Definition typeinfo.h:168
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
Definition of file extensions used in Kicad.