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
24
26#include <sch_screen.h>
27#include <schematic.h>
28#include <locale_io.h>
31#include "eeschema_test_utils.h"
32
33// Code under test
34#include <sch_symbol.h>
35#include <sch_edit_frame.h>
37#include <lib_symbol.h>
38#include <eda_search_data.h>
39#include <sim/sim_lib_mgr.h>
40#include <sim/sim_model.h>
41#include <reporter.h>
42
43
45{
46public:
48 {
49 if( !m_schematic )
50 return nullptr;
51
52 SCH_SCREEN* screen = m_schematic->RootScreen();
53
54 if( !screen )
55 return nullptr;
56
57 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
58 {
59 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
60
61 if( symbol )
62 return symbol;
63 }
64
65 return nullptr;
66 }
67
70};
71
72
76BOOST_FIXTURE_TEST_SUITE( SchSymbol, TEST_SCH_SYMBOL_FIXTURE )
77
78
79
82BOOST_AUTO_TEST_CASE( DefaultProperties )
83{
84}
85
86
91{
92 TRANSFORM t = m_symbol.GetTransform();
93
94 m_symbol.SetOrientation( SYM_ORIENT_90 );
95 t = m_symbol.GetTransform();
96 m_symbol.SetTransform( TRANSFORM() );
97 m_symbol.SetOrientation( SYM_ORIENT_180 );
98 t = m_symbol.GetTransform();
99 m_symbol.SetTransform( TRANSFORM() );
100 m_symbol.SetOrientation( SYM_ORIENT_270 );
101 t = m_symbol.GetTransform();
102}
103
104
105BOOST_AUTO_TEST_CASE( DuplicatePinMatchingPreservesStoredOrder )
106{
107 LoadSchematic( SchematicQAPath( wxS( "component_classes" ) ) );
108 SCH_SYMBOL* source = nullptr;
109
110 for( SCH_ITEM* item : m_schematic->RootScreen()->Items().OfType( SCH_SYMBOL_T ) )
111 {
112 auto* candidate = static_cast<SCH_SYMBOL*>( item );
113 std::set<wxString> numbers;
114
115 for( const auto& pin : candidate->GetRawPins() )
116 numbers.insert( pin->GetNumber() );
117
118 if( numbers.size() >= 3 && numbers.size() == candidate->GetRawPins().size() )
119 {
120 source = candidate;
121 break;
122 }
123 }
124
125 BOOST_REQUIRE( source );
126 std::unique_ptr<SCH_SYMBOL> symbol( static_cast<SCH_SYMBOL*>( source->Clone() ) );
127 auto& pins = symbol->GetRawPins();
128 const wxString number = pins.front()->GetNumber();
129 const size_t originalCount = pins.size();
130 pins.emplace_back( static_cast<SCH_PIN*>( pins.front()->Duplicate( false ) ) );
131
132 // Oppose allocation order so the saved order cannot pass by allocator coincidence.
133 const auto opposeAllocationOrder = [&]
134 {
135 std::sort( pins.begin(), pins.end(), []( const auto& a, const auto& b )
136 { return std::less<SCH_PIN*>{}( b.get(), a.get() ); } );
137 };
138 const auto numbered = [&]( const auto& pin ) { return pin->GetNumber() == number; };
139 opposeAllocationOrder();
140 const KIID expected = ( *std::find_if( pins.begin(), pins.end(), numbered ) )->m_Uuid;
141 symbol->UpdatePins();
142 BOOST_CHECK_EQUAL( pins.size(), originalCount );
143
144 for( int pass = 0; pass < 2; ++pass )
145 {
146 const auto retained = std::find_if( pins.begin(), pins.end(), numbered );
147 BOOST_REQUIRE( retained != pins.end() );
148 BOOST_CHECK( ( *retained )->m_Uuid == expected );
149 symbol->UpdatePins();
150 }
151
152 opposeAllocationOrder();
153 const auto libraryPins = symbol->GetLibSymbolRef()->GetPins();
154 BOOST_REQUIRE_EQUAL( libraryPins.size(), pins.size() );
155 const wxString commonNumber = libraryPins.front()->GetNumber();
156 std::map<const SCH_PIN*, KIID> expectedMapping;
157
158 for( size_t i = 0; i < pins.size(); ++i )
159 {
160 expectedMapping.emplace( libraryPins[i], pins[i]->m_Uuid );
161 pins[i]->SetNumber( commonNumber );
162 }
163
164 // Only the first library pin matches; the others must reuse saved pins in order.
165 symbol->UpdatePins();
166 BOOST_REQUIRE_EQUAL( pins.size(), originalCount );
167
168 for( const auto& pin : pins )
169 {
170 BOOST_REQUIRE( expectedMapping.contains( pin->GetLibPin() ) );
171 BOOST_CHECK( pin->m_Uuid == expectedMapping.at( pin->GetLibPin() ) );
172 }
173}
174
175
179BOOST_AUTO_TEST_CASE( SchSymbolVariantTest )
180{
181 wxFileName fn;
182 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
183 fn.AppendDir( wxS( "variant_test" ) );
184 fn.SetName( wxS( "variant_test" ) );
186
187 LoadSchematic( fn.GetFullPath() );
188
189 SCH_SYMBOL* symbol = GetFirstSymbol();
190 BOOST_CHECK( symbol );
191
192 // Test for an empty (non-existant) variant.
193 wxString variantName = wxS( "Variant1" );
194 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
195 BOOST_CHECK( !variant );
196
197 // Test DNP property variant.
198 BOOST_CHECK( !symbol->GetDNP() );
199 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
200 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
201
202 // Test exclude from BOM property variant.
203 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
204 symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], variantName );
205 BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], variantName ) );
206
207 // Test exclude from simulation property variant.
208 BOOST_CHECK( !symbol->GetExcludedFromSim() );
209 symbol->SetExcludedFromSim( true, &m_schematic->Hierarchy()[0], variantName );
210 BOOST_CHECK( symbol->GetExcludedFromSim( &m_schematic->Hierarchy()[0], variantName ) );
211
212 // Test exclude from board property variant.
213 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
214 symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], variantName );
215 BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], variantName ) );
216
217 // Test exclude from position files property variant.
218 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
219 symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], variantName );
220 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], variantName ) );
221
222 // Test a value field variant change.
223 BOOST_CHECK( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL )
224 == wxS( "1K" ) );
225 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "10K" ), &m_schematic->Hierarchy()[0], variantName );
226 BOOST_CHECK( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, variantName )
227 == wxS( "10K" ) );
228 // BOOST_CHECK( symbol->GetFieldText( FIELD_T::VALUE, &m_schematic->Hierarchy()[0], variantName ) == wxS( "10K" ) );
229}
230
231
237BOOST_AUTO_TEST_CASE( FieldAdditionByName )
238{
239 wxFileName fn;
240 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
241 fn.AppendDir( wxS( "variant_test" ) );
242 fn.SetName( wxS( "variant_test" ) );
244
245 LoadSchematic( fn.GetFullPath() );
246
247 SCH_SYMBOL* symbol = GetFirstSymbol();
248 BOOST_REQUIRE( symbol );
249
250 wxString newFieldName = wxS( "Sim.Library" );
251
252 // GetField by name should return null for non-existent field
253 const SCH_FIELD* existing = symbol->GetField( newFieldName );
254 BOOST_CHECK( existing == nullptr );
255
256 // Create a field to add
257 SCH_FIELD newField( symbol, FIELD_T::USER, newFieldName );
258 newField.SetText( wxS( "test_model.lib" ) );
259
260 // AddField should add the field and return a valid pointer
261 SCH_FIELD* addedField = symbol->AddField( newField );
262 BOOST_REQUIRE( addedField != nullptr );
263
264 // After setting the parent, verify the field is correctly configured
265 addedField->SetParent( symbol );
266 BOOST_CHECK( addedField->GetParent() == symbol );
267
268 // Now GetField should find the newly added field
269 const SCH_FIELD* found = symbol->GetField( newFieldName );
270 BOOST_REQUIRE( found != nullptr );
271 BOOST_CHECK( found->GetText() == wxS( "test_model.lib" ) );
272}
273
274
283BOOST_AUTO_TEST_CASE( UndoSwapItemDataRestoresUnitPinDisplayState )
284{
285 LoadSchematic( SchematicQAPath( wxS( "component_classes" ) ) );
286 BOOST_REQUIRE( m_schematic );
287
288 SCH_SHEET_LIST hierarchy = m_schematic->Hierarchy();
289 BOOST_REQUIRE( !hierarchy.empty() );
290
291 const SCH_SHEET_PATH& sheet = hierarchy[0];
292 SCH_SYMBOL* symbol = nullptr;
293
294 for( SCH_ITEM* item : m_schematic->RootScreen()->Items().OfType( SCH_SYMBOL_T ) )
295 {
296 SCH_SYMBOL* candidate = static_cast<SCH_SYMBOL*>( item );
297
298 if( candidate->GetRef( &sheet, false ) == wxS( "U1" )
299 && candidate->GetUnitSelection( &sheet ) == 1 )
300 {
301 symbol = candidate;
302 break;
303 }
304 }
305
306 BOOST_REQUIRE( symbol );
307
308 auto pinNumbers =
309 []( const std::vector<SCH_PIN*>& aPins )
310 {
311 std::set<wxString> numbers;
312
313 for( SCH_PIN* pin : aPins )
314 numbers.insert( pin->GetNumber() );
315
316 return numbers;
317 };
318
319 const std::set<wxString> unitAPins = { wxS( "1" ), wxS( "2" ), wxS( "3" ) };
320 const std::set<wxString> unitBPins = { wxS( "5" ), wxS( "6" ), wxS( "7" ) };
321
322 BOOST_CHECK_EQUAL( symbol->GetUnitSelection( &sheet ), 1 );
323 BOOST_CHECK_EQUAL( symbol->GetUnit(), 1 );
324 BOOST_CHECK( pinNumbers( symbol->GetLibPins() ) == unitAPins );
325
326 std::unique_ptr<SCH_SYMBOL> undoImage( static_cast<SCH_SYMBOL*>( symbol->Clone() ) );
327
328 symbol->SetUnitSelection( &sheet, 2 );
329 symbol->SetUnit( 2 );
330
331 BOOST_CHECK_EQUAL( symbol->GetUnitSelection( &sheet ), 2 );
332 BOOST_CHECK_EQUAL( symbol->GetUnit(), 2 );
333 BOOST_CHECK( pinNumbers( symbol->GetLibPins() ) == unitBPins );
334
335 symbol->SwapItemData( undoImage.get() );
336 symbol->UpdatePins();
337
338 BOOST_CHECK_EQUAL( symbol->GetUnitSelection( &sheet ), 1 );
339 BOOST_CHECK_EQUAL( symbol->GetUnit(), 1 );
340 BOOST_CHECK( pinNumbers( symbol->GetLibPins() ) == unitAPins );
341
342 BOOST_CHECK_EQUAL( undoImage->GetUnitSelection( &sheet ), 2 );
343 BOOST_CHECK_EQUAL( undoImage->GetUnit(), 2 );
344 BOOST_CHECK( pinNumbers( undoImage->GetLibPins() ) == unitBPins );
345}
346
347
360BOOST_AUTO_TEST_CASE( VariantDialogBatchCommit )
361{
362 wxFileName fn;
363 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
364 fn.AppendDir( wxS( "variant_test" ) );
365 fn.SetName( wxS( "variant_test" ) );
367
368 LoadSchematic( fn.GetFullPath() );
369
370 SCH_SYMBOL* symbol = GetFirstSymbol();
371 BOOST_REQUIRE( symbol );
372
373 SCH_SHEET_LIST hierarchy = m_schematic->Hierarchy();
374 const SCH_SHEET_PATH& sheet = hierarchy[0];
375 wxString variantName = wxS( "DialogTest" );
376
377 // All base properties should start false.
378 BOOST_CHECK( !symbol->GetDNP() );
379 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
380 BOOST_CHECK( !symbol->GetExcludedFromSim() );
381 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
382 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
383
384 // Simulate dialog_symbol_properties TransferDataFromWindow call order.
385 // ExcludeFromSim is left unchecked (false), the other four are checked (true).
386 symbol->SetExcludedFromSim( false, &sheet, variantName );
387 symbol->SetExcludedFromBOM( true, &sheet, variantName );
388 symbol->SetExcludedFromBoard( true, &sheet, variantName );
389 symbol->SetExcludedFromPosFiles( true, &sheet, variantName );
390 symbol->SetDNP( true, &sheet, variantName );
391
392 // All four checked properties must read back as true through the variant.
393 BOOST_CHECK( symbol->GetDNP( &sheet, variantName ) );
394 BOOST_CHECK( symbol->GetExcludedFromBOM( &sheet, variantName ) );
395 BOOST_CHECK( symbol->GetExcludedFromBoard( &sheet, variantName ) );
396 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &sheet, variantName ) );
397 BOOST_CHECK( !symbol->GetExcludedFromSim( &sheet, variantName ) );
398
399 // Base properties must remain unchanged.
400 BOOST_CHECK( !symbol->GetDNP() );
401 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
402 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
403 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
404}
405
406
410BOOST_AUTO_TEST_CASE( VariantDescription )
411{
412 wxFileName fn;
413 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
414 fn.AppendDir( wxS( "variant_test" ) );
415 fn.SetName( wxS( "variant_test" ) );
417
418 LoadSchematic( fn.GetFullPath() );
419 BOOST_REQUIRE( m_schematic );
420
421 wxString variantName = wxS( "TestVariant" );
422 wxString description = wxS( "This is a test variant description" );
423
424 // Add a variant
425 m_schematic->AddVariant( variantName );
426 BOOST_CHECK( m_schematic->GetVariantNames().contains( variantName ) );
427
428 // Set description
429 m_schematic->SetVariantDescription( variantName, description );
430 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( variantName ), description );
431
432 // Empty description for non-existent variant
433 BOOST_CHECK( m_schematic->GetVariantDescription( wxS( "NonExistent" ) ).IsEmpty() );
434
435 // Clear description
436 m_schematic->SetVariantDescription( variantName, wxEmptyString );
437 BOOST_CHECK( m_schematic->GetVariantDescription( variantName ).IsEmpty() );
438}
439
440
444BOOST_AUTO_TEST_CASE( TextVariableVARIANT )
445{
446 wxFileName fn;
447 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
448 fn.AppendDir( wxS( "variant_test" ) );
449 fn.SetName( wxS( "variant_test" ) );
451
452 LoadSchematic( fn.GetFullPath() );
453 BOOST_REQUIRE( m_schematic );
454
455 wxString variantName = wxS( "MilitaryGrade" );
456
457 // Add a variant and set it as current
458 m_schematic->AddVariant( variantName );
459 m_schematic->SetCurrentVariant( variantName );
460
461 // Test that ${VARIANT} resolves to the current variant name
462 wxString token = wxS( "VARIANT" );
463 bool resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
464 BOOST_CHECK( resolved );
465 BOOST_CHECK_EQUAL( token, variantName );
466
467 // Also test VARIANTNAME (legacy/alias)
468 token = wxS( "VARIANTNAME" );
469 resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
470 BOOST_CHECK( resolved );
471 BOOST_CHECK_EQUAL( token, variantName );
472
473 // Empty variant
474 m_schematic->SetCurrentVariant( wxEmptyString );
475 token = wxS( "VARIANT" );
476 resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
477 BOOST_CHECK( resolved );
478 BOOST_CHECK( token.IsEmpty() );
479}
480
481
485BOOST_AUTO_TEST_CASE( TextVariableVARIANT_DESC )
486{
487 wxFileName fn;
488 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
489 fn.AppendDir( wxS( "variant_test" ) );
490 fn.SetName( wxS( "variant_test" ) );
492
493 LoadSchematic( fn.GetFullPath() );
494 BOOST_REQUIRE( m_schematic );
495
496 wxString variantName = wxS( "IndustrialVariant" );
497 wxString description = wxS( "Industrial temperature range components" );
498
499 // Add a variant with description and set it as current
500 m_schematic->AddVariant( variantName );
501 m_schematic->SetVariantDescription( variantName, description );
502 m_schematic->SetCurrentVariant( variantName );
503
504 // Test that ${VARIANT_DESC} resolves to the variant description
505 wxString token = wxS( "VARIANT_DESC" );
506 bool resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
507 BOOST_CHECK( resolved );
508 BOOST_CHECK_EQUAL( token, description );
509
510 // Test with no description set
511 m_schematic->SetVariantDescription( variantName, wxEmptyString );
512 token = wxS( "VARIANT_DESC" );
513 resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
514 BOOST_CHECK( resolved );
515 BOOST_CHECK( token.IsEmpty() );
516}
517
518
522BOOST_AUTO_TEST_CASE( RenameVariantPreservesData )
523{
524 wxFileName fn;
525 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
526 fn.AppendDir( wxS( "variant_test" ) );
527 fn.SetName( wxS( "variant_test" ) );
529
530 LoadSchematic( fn.GetFullPath() );
531 BOOST_REQUIRE( m_schematic );
532
533 SCH_SYMBOL* symbol = GetFirstSymbol();
534 BOOST_REQUIRE( symbol );
535
536 wxString oldName = wxS( "OriginalVariant" );
537 wxString newName = wxS( "RenamedVariant" );
538 wxString description = wxS( "Original description" );
539
540 // Set up the variant with data
541 m_schematic->AddVariant( oldName );
542 m_schematic->SetVariantDescription( oldName, description );
543 m_schematic->SetCurrentVariant( oldName );
544
545 // Set symbol variant properties
546 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], oldName );
547 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "100K" ), &m_schematic->Hierarchy()[0], oldName );
548
549 // Verify the data is set
550 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], oldName ) );
551 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
552 INTERNAL, oldName ), wxS( "100K" ) );
553
554 // Rename the variant
555 m_schematic->RenameVariant( oldName, newName );
556
557 // Verify old name is gone
558 BOOST_CHECK( !m_schematic->GetVariantNames().contains( oldName ) );
559
560 // Verify new name exists
561 BOOST_CHECK( m_schematic->GetVariantNames().contains( newName ) );
562
563 // Verify description was preserved
564 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( newName ), description );
565
566 // Verify current variant was updated
567 BOOST_CHECK_EQUAL( m_schematic->GetCurrentVariant(), newName );
568
569 // Verify symbol variant data was preserved
570 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], newName ) );
571 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
572 INTERNAL, newName ), wxS( "100K" ) );
573}
574
575
579BOOST_AUTO_TEST_CASE( CopyVariantCreatesIndependentCopy )
580{
581 wxFileName fn;
582 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
583 fn.AppendDir( wxS( "variant_test" ) );
584 fn.SetName( wxS( "variant_test" ) );
586
587 LoadSchematic( fn.GetFullPath() );
588 BOOST_REQUIRE( m_schematic );
589
590 SCH_SYMBOL* symbol = GetFirstSymbol();
591 BOOST_REQUIRE( symbol );
592
593 wxString sourceVariant = wxS( "SourceVariant" );
594 wxString copyVariant = wxS( "CopiedVariant" );
595 wxString description = wxS( "Source description" );
596
597 // Set up the source variant
598 m_schematic->AddVariant( sourceVariant );
599 m_schematic->SetVariantDescription( sourceVariant, description );
600
601 // Set symbol variant properties for source
602 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], sourceVariant );
603 symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], sourceVariant );
604 symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], sourceVariant );
605 symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], sourceVariant );
606 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "47K" ), &m_schematic->Hierarchy()[0], sourceVariant );
607
608 // Copy the variant
609 m_schematic->CopyVariant( sourceVariant, copyVariant );
610
611 // Verify both variants exist
612 BOOST_CHECK( m_schematic->GetVariantNames().contains( sourceVariant ) );
613 BOOST_CHECK( m_schematic->GetVariantNames().contains( copyVariant ) );
614
615 // Verify description was copied
616 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( copyVariant ), description );
617
618 // Verify symbol properties were copied
619 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], copyVariant ) );
620 BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], copyVariant ) );
621 BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], copyVariant ) );
622 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], copyVariant ) );
623 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
624 INTERNAL, copyVariant ), wxS( "47K" ) );
625
626 // Modify the copy and verify source is unchanged
627 symbol->SetDNP( false, &m_schematic->Hierarchy()[0], copyVariant );
628 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "100K" ), &m_schematic->Hierarchy()[0], copyVariant );
629
630 // Source should still have original values
631 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], sourceVariant ) );
632 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
633 INTERNAL, sourceVariant ), wxS( "47K" ) );
634
635 // Copy should have modified values
636 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], copyVariant ) );
637 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
638 INTERNAL, copyVariant ), wxS( "100K" ) );
639}
640
641
645BOOST_AUTO_TEST_CASE( VariantFieldDifferenceDetection )
646{
647 wxFileName fn;
648 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
649 fn.AppendDir( wxS( "variant_test" ) );
650 fn.SetName( wxS( "variant_test" ) );
652
653 LoadSchematic( fn.GetFullPath() );
654 BOOST_REQUIRE( m_schematic );
655
656 SCH_SYMBOL* symbol = GetFirstSymbol();
657 BOOST_REQUIRE( symbol );
658
659 wxString variantName1 = wxS( "DiffTestVariant1" );
660 wxString variantName2 = wxS( "DiffTestVariant2" );
661
662 // Get the default value
663 wxString defaultValue = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
664 INTERNAL );
665 BOOST_CHECK_EQUAL( defaultValue, wxS( "1K" ) );
666
667 // Add a variant and set a different value
668 m_schematic->AddVariant( variantName1 );
669 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "2.2K" ), &m_schematic->Hierarchy()[0], variantName1 );
670
671 // Get variant value
672 wxString variantValue = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
673 INTERNAL, variantName1 );
674 BOOST_CHECK_EQUAL( variantValue, wxS( "2.2K" ) );
675
676 // Verify values differ
677 BOOST_CHECK( defaultValue != variantValue );
678
679 // Add another variant with same value as default to verify equality detection
680 m_schematic->AddVariant( variantName2 );
681 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "1K" ), &m_schematic->Hierarchy()[0], variantName2 );
682 wxString variantValue2 = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
683 INTERNAL, variantName2 );
684
685 // Second variant should have the same value as default
686 BOOST_CHECK_EQUAL( defaultValue, variantValue2 );
687}
688
689
693BOOST_AUTO_TEST_CASE( VariantDNPFiltering )
694{
695 wxFileName fn;
696 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
697 fn.AppendDir( wxS( "variant_test" ) );
698 fn.SetName( wxS( "variant_test" ) );
700
701 LoadSchematic( fn.GetFullPath() );
702 BOOST_REQUIRE( m_schematic );
703
704 SCH_SYMBOL* symbol = GetFirstSymbol();
705 BOOST_REQUIRE( symbol );
706
707 wxString variantName = wxS( "DNPVariant" );
708
709 // By default, symbol should not be DNP
710 BOOST_CHECK( !symbol->GetDNP() );
711 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], wxEmptyString ) );
712
713 // Add a variant where symbol is DNP
714 m_schematic->AddVariant( variantName );
715 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
716
717 // Default should still not be DNP
718 BOOST_CHECK( !symbol->GetDNP() );
719 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], wxEmptyString ) );
720
721 // Variant should be DNP
722 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
723
724 // Test exclude from BOM as well
725 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
726 symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], variantName );
727 BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], variantName ) );
728 BOOST_CHECK( !symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], wxEmptyString ) );
729
730 // Test exclude from board as well
731 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
732 symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], variantName );
733 BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], variantName ) );
734 BOOST_CHECK( !symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], wxEmptyString ) );
735
736 // Test exclude from position files as well
737 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
738 symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], variantName );
739 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], variantName ) );
740 BOOST_CHECK( !symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], wxEmptyString ) );
741}
742
743
747BOOST_AUTO_TEST_CASE( GetVariantNamesForUI )
748{
749 wxFileName fn;
750 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
751 fn.AppendDir( wxS( "variant_test" ) );
752 fn.SetName( wxS( "variant_test" ) );
754
755 LoadSchematic( fn.GetFullPath() );
756 BOOST_REQUIRE( m_schematic );
757
758 // Add some variants
759 m_schematic->AddVariant( wxS( "Zebra" ) );
760 m_schematic->AddVariant( wxS( "Alpha" ) );
761 m_schematic->AddVariant( wxS( "Beta" ) );
762
763 wxArrayString variantNames = m_schematic->GetVariantNamesForUI();
764
765 // Should have at least 4 items (default + 3 variants)
766 BOOST_CHECK( variantNames.GetCount() >= 4 );
767
768 // First item should be the default placeholder
769 // The actual string may vary but should represent "default"
770 BOOST_CHECK( !variantNames[0].IsEmpty() );
771
772 // Remaining items should be sorted
773 // Alpha, Beta, Zebra
774 bool foundAlpha = false;
775 bool foundBeta = false;
776 bool foundZebra = false;
777
778 for( size_t i = 1; i < variantNames.GetCount(); i++ )
779 {
780 if( variantNames[i] == wxS( "Alpha" ) )
781 foundAlpha = true;
782 else if( variantNames[i] == wxS( "Beta" ) )
783 foundBeta = true;
784 else if( variantNames[i] == wxS( "Zebra" ) )
785 foundZebra = true;
786 }
787
788 BOOST_CHECK( foundAlpha );
789 BOOST_CHECK( foundBeta );
790 BOOST_CHECK( foundZebra );
791}
792
793
799BOOST_AUTO_TEST_CASE( SetValueFieldTextPersistsVariantValue )
800{
801 wxFileName fn;
802 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
803 fn.AppendDir( wxS( "variant_test" ) );
804 fn.SetName( wxS( "variant_test" ) );
806
807 LoadSchematic( fn.GetFullPath() );
808 BOOST_REQUIRE( m_schematic );
809
810 SCH_SYMBOL* symbol = GetFirstSymbol();
811 BOOST_REQUIRE( symbol );
812
813 wxString variantName = wxS( "PersistenceTest" );
814 wxString newValue = wxS( "4.7K" );
815 wxString defaultValue = symbol->GetField( FIELD_T::VALUE )->GetText();
816
817 // Add the variant
818 m_schematic->AddVariant( variantName );
819
820 // Set value using SetValueFieldText (the function that had the bug)
821 symbol->SetValueFieldText( newValue, &m_schematic->Hierarchy()[0], variantName );
822
823 // Verify that the variant value was actually saved by reading it back
824 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
825 BOOST_REQUIRE( variant.has_value() );
826
827 wxString fieldName = symbol->GetField( FIELD_T::VALUE )->GetName();
828 BOOST_CHECK( variant->m_Fields.contains( fieldName ) );
829 BOOST_CHECK_EQUAL( variant->m_Fields.at( fieldName ), newValue );
830
831 // Verify through GetValue method as well
832 wxString retrievedValue = symbol->GetValue( &m_schematic->Hierarchy()[0], RAW_VALUE, variantName );
833 BOOST_CHECK_EQUAL( retrievedValue, newValue );
834
835 // Verify default value is unchanged
836 wxString retrievedDefault = symbol->GetValue( &m_schematic->Hierarchy()[0], RAW_VALUE, wxEmptyString );
837 BOOST_CHECK_EQUAL( retrievedDefault, defaultValue );
838}
839
840
844BOOST_AUTO_TEST_CASE( SetFieldTextAndSetValueFieldTextConsistency )
845{
846 wxFileName fn;
847 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
848 fn.AppendDir( wxS( "variant_test" ) );
849 fn.SetName( wxS( "variant_test" ) );
851
852 LoadSchematic( fn.GetFullPath() );
853 BOOST_REQUIRE( m_schematic );
854
855 SCH_SYMBOL* symbol = GetFirstSymbol();
856 BOOST_REQUIRE( symbol );
857
858 wxString variantName1 = wxS( "MethodTest1" );
859 wxString variantName2 = wxS( "MethodTest2" );
860 wxString value1 = wxS( "10K" );
861 wxString value2 = wxS( "22K" );
862 wxString fieldName = symbol->GetField( FIELD_T::VALUE )->GetName();
863
864 m_schematic->AddVariant( variantName1 );
865 m_schematic->AddVariant( variantName2 );
866
867 // Set variant 1 using SetValueFieldText
868 symbol->SetValueFieldText( value1, &m_schematic->Hierarchy()[0], variantName1 );
869
870 // Set variant 2 using SetFieldText
871 symbol->SetFieldText( fieldName, value2, &m_schematic->Hierarchy()[0], variantName2 );
872
873 // Both methods should produce the same result structure
874 std::optional<SCH_SYMBOL_VARIANT> variant1 = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName1 );
875 std::optional<SCH_SYMBOL_VARIANT> variant2 = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName2 );
876
877 BOOST_REQUIRE( variant1.has_value() );
878 BOOST_REQUIRE( variant2.has_value() );
879
880 BOOST_CHECK( variant1->m_Fields.contains( fieldName ) );
881 BOOST_CHECK( variant2->m_Fields.contains( fieldName ) );
882
883 BOOST_CHECK_EQUAL( variant1->m_Fields.at( fieldName ), value1 );
884 BOOST_CHECK_EQUAL( variant2->m_Fields.at( fieldName ), value2 );
885
886 // Verify through GetValue
887 BOOST_CHECK_EQUAL( symbol->GetValue( &m_schematic->Hierarchy()[0], RAW_VALUE, variantName1 ), value1 );
888 BOOST_CHECK_EQUAL( symbol->GetValue( &m_schematic->Hierarchy()[0], RAW_VALUE, variantName2 ), value2 );
889
890 // Verify through GetFieldText
891 BOOST_CHECK_EQUAL( symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], variantName1 ), value1 );
892 BOOST_CHECK_EQUAL( symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], variantName2 ), value2 );
893}
894
895
900BOOST_AUTO_TEST_CASE( VariantNameHandling )
901{
902 wxFileName fn;
903 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
904 fn.AppendDir( wxS( "variant_test" ) );
905 fn.SetName( wxS( "variant_test" ) );
907
908 LoadSchematic( fn.GetFullPath() );
909 BOOST_REQUIRE( m_schematic );
910
911 SCH_SYMBOL* symbol = GetFirstSymbol();
912 BOOST_REQUIRE( symbol );
913
914 wxString variantName = wxS( "ProductionVariant" );
915
916 // Add variant with specific casing
917 m_schematic->AddVariant( variantName );
918
919 // Set DNP on variant
920 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
921
922 // Verify with exact case - this should work
923 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], wxS( "ProductionVariant" ) ) );
924
925 // Verify variant exists
926 BOOST_CHECK( m_schematic->GetVariantNames().contains( wxS( "ProductionVariant" ) ) );
927
928 // Set and get current variant
929 m_schematic->SetCurrentVariant( variantName );
930 BOOST_CHECK_EQUAL( m_schematic->GetCurrentVariant(), variantName );
931
932 // Unknown variant should return base DNP (false)
933 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], wxS( "NonExistentVariant" ) ) );
934}
935
936
940BOOST_AUTO_TEST_CASE( VariantDeletionCascade )
941{
942 wxFileName fn;
943 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
944 fn.AppendDir( wxS( "variant_test" ) );
945 fn.SetName( wxS( "variant_test" ) );
947
948 LoadSchematic( fn.GetFullPath() );
949 BOOST_REQUIRE( m_schematic );
950
951 SCH_SYMBOL* symbol = GetFirstSymbol();
952 BOOST_REQUIRE( symbol );
953
954 wxString variantName = wxS( "DeleteMe" );
955
956 // Add variant and set properties
957 m_schematic->AddVariant( variantName );
958 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
959 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "DeletedValue" ), &m_schematic->Hierarchy()[0], variantName );
960
961 // Verify data is set
962 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
963 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
964 BOOST_CHECK( variant.has_value() );
965
966 // Delete the variant
967 m_schematic->DeleteVariant( variantName );
968
969 // Variant should no longer exist at schematic level
970 BOOST_CHECK( !m_schematic->GetVariantNames().contains( variantName ) );
971
972 // After deletion, querying DNP for non-existent variant should return base value
973 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
974}
975
976
980BOOST_AUTO_TEST_CASE( VariantFieldUnicodeAndSpecialChars )
981{
982 wxFileName fn;
983 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
984 fn.AppendDir( wxS( "variant_test" ) );
985 fn.SetName( wxS( "variant_test" ) );
987
988 LoadSchematic( fn.GetFullPath() );
989 BOOST_REQUIRE( m_schematic );
990
991 SCH_SYMBOL* symbol = GetFirstSymbol();
992 BOOST_REQUIRE( symbol );
993
994 wxString variantName = wxS( "UnicodeTest" );
995 m_schematic->AddVariant( variantName );
996
997 // Test Unicode characters in field values
998 wxString unicodeValue = wxS( "1kΩ ±5% 日本語" );
999 symbol->GetField( FIELD_T::VALUE )->SetText( unicodeValue, &m_schematic->Hierarchy()[0], variantName );
1000
1001 wxString retrieved;
1002 retrieved = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, variantName );
1003 BOOST_CHECK_EQUAL( retrieved, unicodeValue );
1004
1005 // Test special characters
1006 wxString specialChars = wxS( "R<1K>\"test\"'value'" );
1007 symbol->GetField( FIELD_T::VALUE )->SetText( specialChars, &m_schematic->Hierarchy()[0], variantName );
1008
1009 retrieved = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, variantName );
1010 BOOST_CHECK_EQUAL( retrieved, specialChars );
1011
1012 // Test empty string
1013 symbol->GetField( FIELD_T::VALUE )->SetText( wxEmptyString, &m_schematic->Hierarchy()[0], variantName );
1014 retrieved = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, variantName );
1015 BOOST_CHECK( retrieved.IsEmpty() );
1016
1017 // Test description with unicode
1018 wxString unicodeDesc = wxS( "Variante für Produktion — 测试" );
1019 m_schematic->SetVariantDescription( variantName, unicodeDesc );
1020 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( variantName ), unicodeDesc );
1021}
1022
1023
1027BOOST_AUTO_TEST_CASE( VariantSpecificFieldDereferencing )
1028{
1029 wxFileName fn;
1030 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1031 fn.AppendDir( wxS( "variant_test" ) );
1032 fn.SetName( wxS( "variant_test" ) );
1034
1035 LoadSchematic( fn.GetFullPath() );
1036 BOOST_REQUIRE( m_schematic );
1037
1038 SCH_SYMBOL* symbol = GetFirstSymbol();
1039 BOOST_REQUIRE( symbol );
1040
1041 wxString variantName = wxS( "MilitaryGrade" );
1042 wxString variantValue = wxS( "1K-MIL" );
1043 wxString defaultValue = wxS( "1K" );
1044
1045 // Create a variant with a different value field
1046 m_schematic->AddVariant( variantName );
1047 symbol->GetField( FIELD_T::VALUE )->SetText( variantValue, &m_schematic->Hierarchy()[0], variantName );
1048 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
1049
1050 // Verify default value
1051 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL ),
1052 defaultValue );
1053
1054 // Get the symbol's reference (R1) for cross-reference testing
1055 wxString symbolRef = symbol->GetRef( &m_schematic->Hierarchy()[0], false );
1056
1057 // Test 1: ResolveCrossReference with variant syntax - should return variant-specific value
1058 wxString token = symbolRef + wxS( ":VALUE:" ) + variantName;
1059 bool resolved = m_schematic->ResolveCrossReference( &token, 0 );
1060 BOOST_CHECK( resolved );
1061 BOOST_CHECK_EQUAL( token, variantValue );
1062
1063 // Test 2: ResolveCrossReference without variant - should return default value
1064 token = symbolRef + wxS( ":VALUE" );
1065 resolved = m_schematic->ResolveCrossReference( &token, 0 );
1066 BOOST_CHECK( resolved );
1067 BOOST_CHECK_EQUAL( token, defaultValue );
1068
1069 // Test 3: ResolveCrossReference with non-existent variant - should return default value
1070 token = symbolRef + wxS( ":VALUE:NonExistentVariant" );
1071 resolved = m_schematic->ResolveCrossReference( &token, 0 );
1072 BOOST_CHECK( resolved );
1073 BOOST_CHECK_EQUAL( token, defaultValue );
1074
1075 // Test 4: ResolveTextVar with variant parameter directly
1076 token = wxS( "VALUE" );
1077 resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, variantName, 0 );
1078 BOOST_CHECK( resolved );
1079 BOOST_CHECK_EQUAL( token, variantValue );
1080
1081 // Test 5: ResolveTextVar with empty variant - should return default
1082 m_schematic->SetCurrentVariant( variantName );
1083 token = wxS( "VALUE" );
1084 resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, wxEmptyString, 0 );
1085 BOOST_CHECK( resolved );
1086 BOOST_CHECK_EQUAL( token, defaultValue );
1087
1088 // Test 6: ResolveTextVar DNP without a variant parameter - should return current variant
1089 token = wxS( "DNP" );
1090 resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
1091 BOOST_CHECK( resolved );
1092 BOOST_CHECK_EQUAL( token, wxS( "DNP" ) );
1093
1094 // Test 7: ResolveTextVar DNP with empty variant - should return default
1095 token = wxS( "DNP" );
1096 resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, wxEmptyString, 0 );
1097 BOOST_CHECK( resolved );
1098 BOOST_CHECK_EQUAL( token, wxEmptyString );
1099}
1100
1101
1107BOOST_AUTO_TEST_CASE( FootprintFieldVariantSupport )
1108{
1109 wxFileName fn;
1110 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1111 fn.AppendDir( wxS( "variant_test" ) );
1112 fn.SetName( wxS( "variant_test" ) );
1114
1115 LoadSchematic( fn.GetFullPath() );
1116 BOOST_REQUIRE( m_schematic );
1117
1118 SCH_SYMBOL* symbol = GetFirstSymbol();
1119 BOOST_REQUIRE( symbol );
1120
1121 wxString variantName = wxS( "FootprintVariant" );
1122 wxString baseFootprint = wxS( "Resistor_SMD:R_0805_2012Metric" );
1123 wxString variantFootprint = wxS( "Resistor_SMD:R_0402_1005Metric" );
1124 wxString fieldName = symbol->GetField( FIELD_T::FOOTPRINT )->GetName();
1125
1126 // Set a base footprint first
1127 symbol->SetFootprintFieldText( baseFootprint );
1128 BOOST_CHECK_EQUAL( symbol->GetFootprintFieldText( nullptr, RAW_VALUE ), baseFootprint );
1129
1130 // Add the variant
1131 m_schematic->AddVariant( variantName );
1132
1133 // Set a different footprint for the variant using SetFieldText
1134 symbol->SetFieldText( fieldName, variantFootprint, &m_schematic->Hierarchy()[0], variantName );
1135
1136 // Verify base footprint is unchanged
1137 wxString retrievedBase = symbol->GetFootprintFieldText( nullptr, RAW_VALUE );
1138 BOOST_CHECK_EQUAL( retrievedBase, baseFootprint );
1139
1140 // Verify GetFieldText with no variant returns base footprint
1141 wxString retrievedDefault = symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], wxEmptyString );
1142 BOOST_CHECK_EQUAL( retrievedDefault, baseFootprint );
1143
1144 // Verify GetFieldText with variant returns variant-specific footprint
1145 wxString retrievedVariant = symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], variantName );
1146 BOOST_CHECK_EQUAL( retrievedVariant, variantFootprint );
1147
1148 // Verify that the variant data structure contains the footprint override
1149 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
1150 BOOST_REQUIRE( variant.has_value() );
1151 BOOST_CHECK( variant->m_Fields.contains( fieldName ) );
1152 BOOST_CHECK_EQUAL( variant->m_Fields.at( fieldName ), variantFootprint );
1153}
1154
1155
1160BOOST_AUTO_TEST_CASE( FootprintFieldVariantNoOpWhenSame )
1161{
1162 wxFileName fn;
1163 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1164 fn.AppendDir( wxS( "variant_test" ) );
1165 fn.SetName( wxS( "variant_test" ) );
1167
1168 LoadSchematic( fn.GetFullPath() );
1169 BOOST_REQUIRE( m_schematic );
1170
1171 SCH_SYMBOL* symbol = GetFirstSymbol();
1172 BOOST_REQUIRE( symbol );
1173
1174 wxString variantName = wxS( "NoOpTest" );
1175 wxString baseFootprint = wxS( "Resistor_SMD:R_0805_2012Metric" );
1176 wxString fieldName = symbol->GetField( FIELD_T::FOOTPRINT )->GetName();
1177
1178 // Set a base footprint first
1179 symbol->SetFootprintFieldText( baseFootprint );
1180
1181 // Add the variant
1182 m_schematic->AddVariant( variantName );
1183
1184 // Set the same footprint value for the variant
1185 symbol->SetFieldText( fieldName, baseFootprint, &m_schematic->Hierarchy()[0], variantName );
1186
1187 // Verify that no variant override was created since the value is the same
1188 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
1189
1190 // Either no variant was created, or it exists but doesn't have a footprint override
1191 if( variant.has_value() )
1192 {
1193 BOOST_CHECK( !variant->m_Fields.contains( fieldName ) );
1194 }
1195}
1196
1197
1202BOOST_AUTO_TEST_CASE( VariantSwitchInvalidatesBoundingBoxCache )
1203{
1204 wxFileName fn;
1205 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1206 fn.AppendDir( wxS( "variant_test" ) );
1207 fn.SetName( wxS( "variant_test" ) );
1209
1210 LoadSchematic( fn.GetFullPath() );
1211 BOOST_REQUIRE( m_schematic );
1212
1213 // GetShownText(bool) resolves variants via CurrentSheet(), so we must set it
1214 m_schematic->SetCurrentSheet( m_schematic->Hierarchy()[0] );
1215
1216 SCH_SYMBOL* symbol = GetFirstSymbol();
1217 BOOST_REQUIRE( symbol );
1218
1219 SCH_FIELD* fpField = symbol->GetField( FIELD_T::FOOTPRINT );
1220 BOOST_REQUIRE( fpField );
1221
1222 wxString variantName = wxS( "BboxVariant" );
1223 wxString shortFp = wxS( "R_0402" );
1224 wxString longFp = wxS( "Resistor_SMD:R_2512_6332Metric_Pad1.52x3.35mm_HandSolder" );
1225
1226 symbol->SetFootprintFieldText( shortFp );
1227 fpField->SetVisible( true );
1228 fpField->ClearBoundingBoxCache();
1229
1230 m_schematic->AddVariant( variantName );
1231 symbol->SetFieldText( fpField->GetName(), longFp, &m_schematic->Hierarchy()[0], variantName );
1232
1233 // Confirm variant text resolution works
1234 wxString resolvedDefault = fpField->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, wxEmptyString );
1235 wxString resolvedVariant = fpField->GetShownText( &m_schematic->Hierarchy()[0], INTERNAL, variantName );
1236 BOOST_CHECK_EQUAL( resolvedDefault, shortFp );
1237 BOOST_CHECK_EQUAL( resolvedVariant, longFp );
1238
1239 // Verify the implicit text resolution via GetShownText(bool) works for each variant
1240 m_schematic->SetCurrentVariant( wxEmptyString );
1241 wxString implicitDefault = fpField->GetShownText( INTERNAL );
1242
1243 m_schematic->SetCurrentVariant( variantName );
1244 wxString implicitVariant = fpField->GetShownText( INTERNAL );
1245
1246 BOOST_CHECK_EQUAL( implicitDefault, shortFp );
1247 BOOST_CHECK_EQUAL( implicitVariant, longFp );
1248
1249 // Prime the bounding box cache with the default variant (short footprint text)
1250 m_schematic->SetCurrentVariant( wxEmptyString );
1251 fpField->ClearBoundingBoxCache();
1252 BOX2I defaultTextBox = fpField->GetTextBox( nullptr );
1253
1254 // Switch to the variant with a much longer footprint string.
1255 // SetCurrentVariant must invalidate caches so the new text is reflected.
1256 m_schematic->SetCurrentVariant( variantName );
1257 BOX2I variantTextBox = fpField->GetTextBox( nullptr );
1258
1259 // The longer text must produce a wider text box. If the bounding box cache was not
1260 // invalidated on variant switch, both boxes would be identical.
1261 BOOST_CHECK_GT( variantTextBox.GetWidth(), defaultTextBox.GetWidth() );
1262
1263 // Switch back and verify it returns to the original width
1264 m_schematic->SetCurrentVariant( wxEmptyString );
1265 BOX2I restoredTextBox = fpField->GetTextBox( nullptr );
1266 BOOST_CHECK_EQUAL( restoredTextBox.GetWidth(), defaultTextBox.GetWidth() );
1267}
1268
1269
1280BOOST_AUTO_TEST_CASE( VariantAttributeInitFromSymbol )
1281{
1282 wxFileName fn;
1283 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1284 fn.AppendDir( wxS( "variant_test" ) );
1285 fn.SetName( wxS( "variant_test" ) );
1287
1288 LoadSchematic( fn.GetFullPath() );
1289 BOOST_REQUIRE( m_schematic );
1290
1291 SCH_SYMBOL* symbol = GetFirstSymbol();
1292 BOOST_REQUIRE( symbol );
1293
1294 // Set all default attributes to true on the symbol
1295 symbol->SetDNP( true );
1296 symbol->SetExcludedFromBOM( true );
1297 symbol->SetExcludedFromSim( true );
1298 symbol->SetExcludedFromBoard( true );
1299 symbol->SetExcludedFromPosFiles( true );
1300
1301 // Default-constructed variant has all-false attributes
1302 SCH_SYMBOL_VARIANT defaultVariant( wxS( "Default" ) );
1303 BOOST_CHECK( !defaultVariant.m_DNP );
1304 BOOST_CHECK( !defaultVariant.m_ExcludedFromBOM );
1305 BOOST_CHECK( !defaultVariant.m_ExcludedFromSim );
1306 BOOST_CHECK( !defaultVariant.m_ExcludedFromBoard );
1307 BOOST_CHECK( !defaultVariant.m_ExcludedFromPosFiles );
1308
1309 // InitializeAttributes should copy the symbol's attributes
1310 SCH_SYMBOL_VARIANT initializedVariant( wxS( "Initialized" ) );
1311 initializedVariant.InitializeAttributes( *symbol );
1312
1313 BOOST_CHECK_MESSAGE( initializedVariant.m_DNP,
1314 "InitializeAttributes should copy DNP from symbol" );
1315 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromBOM,
1316 "InitializeAttributes should copy ExcludedFromBOM from symbol" );
1317 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromSim,
1318 "InitializeAttributes should copy ExcludedFromSim from symbol" );
1319 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromBoard,
1320 "InitializeAttributes should copy ExcludedFromBoard from symbol" );
1321 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromPosFiles,
1322 "InitializeAttributes should copy ExcludedFromPosFiles from symbol" );
1323}
1324
1325
1336BOOST_AUTO_TEST_CASE( MatchesExcludesFieldText )
1337{
1338 LIB_SYMBOL* libSym = new LIB_SYMBOL( wxS( "+5V" ) );
1339 libSym->GetValueField().SetText( wxS( "+5V" ) );
1340 libSym->SetDescription( wxS( "power rail" ) );
1341
1342 SCH_SYMBOL symbol( *libSym, libSym->GetLibId(), nullptr, 0, 0, VECTOR2I() );
1343 symbol.GetField( FIELD_T::VALUE )->SetText( wxS( "+5VA" ) );
1344
1345 SCH_FIELD customField( &symbol, FIELD_T::USER, wxS( "MyField" ) );
1346 customField.SetText( wxS( "aayyxx" ) );
1347 customField.SetVisible( true );
1348 SCH_FIELD* custom = symbol.AddField( customField );
1349
1350 SCH_SHEET_PATH sheetPath;
1351
1352 SCH_SEARCH_DATA data;
1353 data.findString = wxS( "aayyxx" );
1355
1356 // a custom field hit must be a single hit, not also the symbol and the reference
1357 BOOST_CHECK( custom->Matches( data, &sheetPath ) );
1358 BOOST_CHECK( !symbol.Matches( data, &sheetPath ) );
1359 BOOST_CHECK( !symbol.GetField( FIELD_T::REFERENCE )->Matches( data, &sheetPath ) );
1360
1361 // whole-word "+5V" must not match a symbol whose value is "+5VA"
1362 data.findString = wxS( "+5V" );
1364 BOOST_CHECK( !symbol.Matches( data, &sheetPath ) );
1365 BOOST_CHECK( !symbol.GetField( FIELD_T::VALUE )->Matches( data, &sheetPath ) );
1366
1367 data.findString = wxS( "+5VA" );
1368 BOOST_CHECK( symbol.GetField( FIELD_T::VALUE )->Matches( data, &sheetPath ) );
1369
1370 // metadata search still surfaces the symbol, via the reference field in the
1371 // search pane
1372 data.findString = wxS( "power rail" );
1374 data.searchMetadata = true;
1375 BOOST_CHECK( symbol.Matches( data, &sheetPath ) );
1376 BOOST_CHECK( symbol.GetField( FIELD_T::REFERENCE )->Matches( data, &sheetPath ) );
1377
1378 data.searchMetadata = false;
1379 BOOST_CHECK( !symbol.Matches( data, &sheetPath ) );
1380
1381 delete libSym;
1382}
1383
1384
1385BOOST_AUTO_TEST_CASE( OperatingPointSkipsMissingSymbolPinMappings )
1386{
1387 wxFileName fn;
1388 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1389 fn.AppendDir( wxS( "variant_test" ) );
1390 fn.SetName( wxS( "variant_test" ) );
1392 LoadSchematic( fn.GetFullPath() );
1393 SCH_SYMBOL* symbol = GetFirstSymbol();
1394 BOOST_REQUIRE( symbol );
1395 BOOST_REQUIRE( symbol->GetPin( wxS( "1" ) ) );
1396 BOOST_REQUIRE( symbol->GetPin( wxS( "2" ) ) );
1397 BOOST_REQUIRE( !symbol->GetPin( wxS( "999" ) ) );
1398 const SCH_SHEET_PATH path = m_schematic->Hierarchy()[0];
1399
1400 SetFieldValue( symbol->GetFields(), SIM_DEVICE_FIELD, "R" );
1401 SetFieldValue( symbol->GetFields(), SIM_PARAMS_FIELD, "r=1k" );
1402 SetFieldValue( symbol->GetFields(), SIM_PINS_FIELD, "999=+ 2=-" );
1403
1404 SIM_LIB_MGR manager( &m_schematic->Project() );
1406 const auto input = SIM_LIB_MGR::CaptureModelInput( &path, *symbol, 0, wxString() );
1407 const auto owned = manager.CreateModel( input, true, reporter );
1408 const auto live = manager.CreateModel( &path, *symbol, true, 0, wxString(), reporter );
1409 BOOST_CHECK_MESSAGE( !reporter.HasMessage(), reporter.GetMessages() );
1410 BOOST_REQUIRE_EQUAL( owned.model.GetPinCount(), 2 );
1411 BOOST_REQUIRE_EQUAL( live.model.GetPinCount(), 2 );
1412 BOOST_CHECK_EQUAL( owned.model.GetPin( 0 ).symbolPinNumber, wxString( "999" ) );
1413 BOOST_CHECK_EQUAL( live.model.GetPin( 0 ).symbolPinNumber, wxString( "999" ) );
1414
1415 // A stale mapping must not prevent a later valid pin from resolving.
1416 wxString token = wxS( "OP:2" );
1417 BOOST_CHECK( symbol->ResolveTextVar( &path, &token, wxString(), 0 ) );
1418 BOOST_CHECK_EQUAL( token, wxString( "--" ) );
1419
1420 token = wxS( "OP:999" );
1421 BOOST_CHECK( symbol->ResolveTextVar( &path, &token, wxString(), 0 ) );
1422 BOOST_CHECK_EQUAL( token, wxString( "?" ) );
1423}
1424
1425
1426BOOST_AUTO_TEST_CASE( ExactMembershipAvoidsTextGeometryAndTracksTreeLifetime )
1427{
1428 LoadSchematic( wxString::FromUTF8( KI_TEST::GetEeschemaTestDataDir() ) + wxS( "/issue7203.kicad_sch" ) );
1429 auto symbols = m_schematic->Hierarchy().front().LastScreen()->Items().OfType( SCH_SYMBOL_T );
1430 BOOST_REQUIRE( symbols.begin() != symbols.end() );
1431
1432 struct COUNTED_SYMBOL : SCH_SYMBOL
1433 {
1434 explicit COUNTED_SYMBOL( const SCH_SYMBOL& aSource ) : SCH_SYMBOL( aSource ) {}
1435
1436 const BOX2I GetBoundingBox() const override
1437 {
1438 ++boundsReads;
1440 }
1441
1442 mutable unsigned boundsReads = 0;
1443 };
1444
1445 COUNTED_SYMBOL item( *static_cast<SCH_SYMBOL*>( *symbols.begin() ) );
1446 COUNTED_SYMBOL copy( item );
1447 EE_RTREE tree;
1448 tree.insert( &item );
1449 item.boundsReads = 0;
1450 copy.boundsReads = 0;
1451 BOOST_CHECK( tree.contains( &item, true ) );
1452 BOOST_CHECK( !tree.contains( &copy, true ) );
1453 BOOST_CHECK_EQUAL( item.boundsReads, 0u );
1454 BOOST_CHECK_EQUAL( copy.boundsReads, 0u );
1455 item.Move( VECTOR2I( 100000000, 100000000 ) );
1456 BOOST_CHECK( tree.contains( &item, true ) );
1457 tree.insert( &copy );
1458 BOOST_CHECK( tree.contains( &copy, true ) );
1459 tree.insert( &item );
1460 BOOST_REQUIRE( tree.remove( &item ) );
1461 BOOST_CHECK( tree.contains( &item, true ) );
1462 BOOST_REQUIRE( tree.remove( &item ) );
1463 BOOST_CHECK( !tree.contains( &item, true ) );
1464 BOOST_CHECK( !tree.remove( &item ) );
1465
1466 EE_RTREE moved( std::move( tree ) );
1467 BOOST_CHECK( moved.contains( &copy, true ) );
1468 BOOST_CHECK( !tree.contains( &copy, true ) );
1469 tree.insert( &item );
1470 tree = std::move( moved );
1471 BOOST_CHECK( tree.contains( &copy, true ) );
1472 BOOST_CHECK( !tree.contains( &item, true ) );
1473 BOOST_CHECK( !moved.contains( &copy, true ) );
1474 tree.clear();
1475 BOOST_CHECK( !tree.contains( &copy, true ) );
1476 tree.insert( &item );
1477 BOOST_CHECK( tree.contains( &item, true ) );
1478}
1479
1480BOOST_AUTO_TEST_CASE( SymbolPropertyReferencesUseTheExplicitPath )
1481{
1482 LOCALE_IO locale;
1483 SETTINGS_MANAGER settings;
1484 std::unique_ptr<SCHEMATIC> schematic;
1485 KI_TEST::LoadSchematic( settings, wxS( "issue23840/BusAndVectors" ), schematic );
1486 BOOST_REQUIRE_GT( schematic->Hierarchy().size(), 1 );
1487 size_t differentReferences = 0;
1488
1489 for( const SCH_SHEET_PATH& path : schematic->Hierarchy() )
1490 {
1491 for( SCH_ITEM* item : path.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1492 {
1493 auto* symbol = static_cast<SCH_SYMBOL*>( item );
1494 const wxString expected = symbol->GetRef( &path );
1495
1496 for( const SCH_SHEET_PATH& current : schematic->Hierarchy() )
1497 {
1498 if( current.LastScreen() != path.LastScreen() )
1499 continue;
1500
1501 schematic->SetCurrentSheet( current );
1502 differentReferences += symbol->GetRef( &current ) != expected;
1503 wxString token( "PROPERTY.Reference" );
1504 BOOST_REQUIRE( symbol->ResolveTextVar( &path, &token, 0 ) );
1505 BOOST_CHECK_EQUAL( token, expected );
1506 }
1507 }
1508 }
1509
1510 BOOST_CHECK_GT( differentReferences, 0 );
1511}
1512
1513
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
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:737
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:342
virtual void ClearBoundingBoxCache()
Definition eda_text.cpp:658
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:119
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:188
void SetDescription(const wxString &aDescription)
Gets the Description field text value *‍/.
SCH_FIELD & GetValueField()
Return reference to the value field.
Definition lib_symbol.h:437
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
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:138
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:165
int GetUnit() const
Definition sch_item.h:237
virtual void SetUnit(int aUnit)
Definition sch_item.h:236
void SwapItemData(SCH_ITEM *aImage)
Swap data between aItem and aImage.
Definition sch_item.cpp:665
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:118
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:75
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 * GetFirstSymbol()
SCH_SYMBOL object with no extra data set.
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:94
@ INTERNAL
Definition common.h:92
static const std::string KiCadSchematicFileExtension
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:456
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
@ SYM_ORIENT_270
Definition symbol.h:38
@ SYM_ORIENT_180
Definition symbol.h:37
@ SYM_ORIENT_90
Definition symbol.h:36
@ 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:683
Definition of file extensions used in Kicad.