KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_variant.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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
29
31#include <boost/test/unit_test.hpp>
32
33#include <board.h>
34#include <footprint.h>
39#include <richio.h>
40
41
42BOOST_AUTO_TEST_SUITE( Variant )
43
44
45
48BOOST_AUTO_TEST_CASE( FootprintVariantBasics )
49{
50 FOOTPRINT_VARIANT variant( "TestVariant" );
51
52 // Check default values
53 BOOST_CHECK_EQUAL( variant.GetName(), "TestVariant" );
54 BOOST_CHECK( !variant.GetDNP() );
55 BOOST_CHECK( !variant.GetExcludedFromBOM() );
56 BOOST_CHECK( !variant.GetExcludedFromPosFiles() );
57 BOOST_CHECK( variant.GetFields().empty() );
58
59 // Test setting values
60 variant.SetDNP( true );
61 variant.SetExcludedFromBOM( true );
62 variant.SetExcludedFromPosFiles( true );
63 variant.SetFieldValue( "Value", "100R" );
64
65 BOOST_CHECK( variant.GetDNP() );
66 BOOST_CHECK( variant.GetExcludedFromBOM() );
67 BOOST_CHECK( variant.GetExcludedFromPosFiles() );
68 BOOST_CHECK( variant.HasFieldValue( "Value" ) );
69 BOOST_CHECK_EQUAL( variant.GetFieldValue( "Value" ), "100R" );
70}
71
72
76BOOST_AUTO_TEST_CASE( BoardVariantRegistry )
77{
78 BOARD board;
79
80 // Initially no variants
81 BOOST_CHECK( board.GetVariantNames().empty() );
82 BOOST_CHECK( board.GetCurrentVariant().IsEmpty() );
83
84 // Add a variant
85 board.AddVariant( "Production" );
86 BOOST_CHECK( board.HasVariant( "Production" ) );
87 BOOST_CHECK_EQUAL( board.GetVariantNames().size(), 1 );
88
89 // Add another variant
90 board.AddVariant( "Debug" );
91 BOOST_CHECK( board.HasVariant( "Debug" ) );
92 BOOST_CHECK_EQUAL( board.GetVariantNames().size(), 2 );
93
94 // Test case insensitivity
95 BOOST_CHECK( board.HasVariant( "production" ) );
96 BOOST_CHECK( board.HasVariant( "PRODUCTION" ) );
97 BOOST_CHECK( board.HasVariant( "PrOdUcTiOn" ) );
98
99 // Set current variant
100 board.SetCurrentVariant( "Production" );
101 BOOST_CHECK_EQUAL( board.GetCurrentVariant(), "Production" );
102
103 // Set variant description
104 board.SetVariantDescription( "Production", "Standard production build" );
105 BOOST_CHECK_EQUAL( board.GetVariantDescription( "Production" ), "Standard production build" );
106
107 // Delete a variant
108 board.DeleteVariant( "Debug" );
109 BOOST_CHECK( !board.HasVariant( "Debug" ) );
110 BOOST_CHECK_EQUAL( board.GetVariantNames().size(), 1 );
111}
112
113
117BOOST_AUTO_TEST_CASE( FootprintDNPForVariant )
118{
119 BOARD board;
120 FOOTPRINT fp( &board );
121
122 // Add variants to board
123 board.AddVariant( "Production" );
124 board.AddVariant( "Debug" );
125
126 // Set base DNP to false
127 fp.SetAttributes( 0 );
128 BOOST_CHECK( !fp.GetDNPForVariant( wxEmptyString ) );
129 BOOST_CHECK( !fp.GetDNPForVariant( "Production" ) );
130
131 // Set base DNP to true
132 fp.SetAttributes( FP_DNP );
133 BOOST_CHECK( fp.GetDNPForVariant( wxEmptyString ) );
134 BOOST_CHECK( fp.GetDNPForVariant( "Production" ) );
135
136 // Now set Production variant to override DNP
137 FOOTPRINT_VARIANT prodVariant( "Production" );
138 prodVariant.SetDNP( false );
139 fp.SetVariant( prodVariant );
140
141 // Base is still DNP, but Production overrides to not DNP
142 BOOST_CHECK( fp.GetDNPForVariant( wxEmptyString ) );
143 BOOST_CHECK( !fp.GetDNPForVariant( "Production" ) );
144 BOOST_CHECK( !fp.GetDNPForVariant( "production" ) ); // Case insensitive
145 BOOST_CHECK( fp.GetDNPForVariant( "Debug" ) ); // No override, uses base
146
147 // Set Debug variant to also override
148 FOOTPRINT_VARIANT debugVariant( "Debug" );
149 debugVariant.SetDNP( true );
150 fp.SetVariant( debugVariant );
151
152 BOOST_CHECK( fp.GetDNPForVariant( "Debug" ) );
153}
154
155
159BOOST_AUTO_TEST_CASE( FootprintBOMExclusionForVariant )
160{
161 BOARD board;
162 FOOTPRINT fp( &board );
163
164 board.AddVariant( "Production" );
165
166 // Set base exclude from BOM to false
167 fp.SetAttributes( 0 );
168 BOOST_CHECK( !fp.GetExcludedFromBOMForVariant( wxEmptyString ) );
169 BOOST_CHECK( !fp.GetExcludedFromBOMForVariant( "Production" ) );
170
171 // Set base exclude from BOM to true
173 BOOST_CHECK( fp.GetExcludedFromBOMForVariant( wxEmptyString ) );
174 BOOST_CHECK( fp.GetExcludedFromBOMForVariant( "Production" ) );
175
176 // Override for Production variant
177 FOOTPRINT_VARIANT prodVariant( "Production" );
178 prodVariant.SetExcludedFromBOM( false );
179 fp.SetVariant( prodVariant );
180
181 BOOST_CHECK( fp.GetExcludedFromBOMForVariant( wxEmptyString ) );
182 BOOST_CHECK( !fp.GetExcludedFromBOMForVariant( "Production" ) );
183}
184
185
189BOOST_AUTO_TEST_CASE( FootprintPosFileExclusionForVariant )
190{
191 BOARD board;
192 FOOTPRINT fp( &board );
193
194 board.AddVariant( "Production" );
195
196 // Set base exclude from position files to false
197 fp.SetAttributes( 0 );
198 BOOST_CHECK( !fp.GetExcludedFromPosFilesForVariant( wxEmptyString ) );
199 BOOST_CHECK( !fp.GetExcludedFromPosFilesForVariant( "Production" ) );
200
201 // Set base exclude from position files to true
203 BOOST_CHECK( fp.GetExcludedFromPosFilesForVariant( wxEmptyString ) );
204 BOOST_CHECK( fp.GetExcludedFromPosFilesForVariant( "Production" ) );
205
206 // Override for Production variant
207 FOOTPRINT_VARIANT prodVariant( "Production" );
208 prodVariant.SetExcludedFromPosFiles( false );
209 fp.SetVariant( prodVariant );
210
211 BOOST_CHECK( fp.GetExcludedFromPosFilesForVariant( wxEmptyString ) );
212 BOOST_CHECK( !fp.GetExcludedFromPosFilesForVariant( "Production" ) );
213}
214
215
219BOOST_AUTO_TEST_CASE( VariantCaseInsensitivity )
220{
221 BOARD board;
222 FOOTPRINT fp( &board );
223
224 board.AddVariant( "Production" );
225
226 // Set variant override with specific case
227 FOOTPRINT_VARIANT prodVariant( "Production" );
228 prodVariant.SetDNP( true );
229 fp.SetVariant( prodVariant );
230
231 // Access with different cases - all should find the same variant
232 BOOST_CHECK( fp.GetDNPForVariant( "Production" ) );
233 BOOST_CHECK( fp.GetDNPForVariant( "production" ) );
234 BOOST_CHECK( fp.GetDNPForVariant( "PRODUCTION" ) );
235 BOOST_CHECK( fp.GetDNPForVariant( "PrOdUcTiOn" ) );
236
237 // Board operations should also be case insensitive
238 BOOST_CHECK( board.HasVariant( "production" ) );
239 BOOST_CHECK( board.HasVariant( "PRODUCTION" ) );
240}
241
242
246BOOST_AUTO_TEST_CASE( EmptyVariantReturnsBase )
247{
248 BOARD board;
249 FOOTPRINT fp( &board );
250
251 // Set base DNP
252 fp.SetAttributes( FP_DNP );
253
254 // Empty variant should return base
255 BOOST_CHECK( fp.GetDNPForVariant( wxEmptyString ) );
256
257 // Add a variant but still check empty
258 board.AddVariant( "Production" );
259
260 FOOTPRINT_VARIANT prodVariant( "Production" );
261 prodVariant.SetDNP( false );
262 fp.SetVariant( prodVariant );
263
264 // Empty still returns base
265 BOOST_CHECK( fp.GetDNPForVariant( wxEmptyString ) );
266 BOOST_CHECK( !fp.GetDNPForVariant( "Production" ) );
267}
268
269
273BOOST_AUTO_TEST_CASE( UnknownVariantReturnsBase )
274{
275 BOARD board;
276 FOOTPRINT fp( &board );
277
278 // Set base DNP
279 fp.SetAttributes( FP_DNP );
280
281 board.AddVariant( "Production" );
282
283 FOOTPRINT_VARIANT prodVariant( "Production" );
284 prodVariant.SetDNP( false );
285 fp.SetVariant( prodVariant );
286
287 // Unknown variant should return base
288 BOOST_CHECK( fp.GetDNPForVariant( "NonExistentVariant" ) );
289 BOOST_CHECK( fp.GetDNPForVariant( "Debug" ) );
290}
291
292
293BOOST_AUTO_TEST_CASE( FootprintVariantCopyAssignment )
294{
295 BOARD board;
296 FOOTPRINT original( &board );
297
298 original.SetReference( "R1" );
299 original.SetValue( "10K" );
300
301 FOOTPRINT_VARIANT prodVariant( "Production" );
302 prodVariant.SetDNP( true );
303 prodVariant.SetExcludedFromBOM( true );
304 prodVariant.SetFieldValue( original.Value().GetName(), "22K" );
305 original.SetVariant( prodVariant );
306
307 FOOTPRINT copy( original );
308 const FOOTPRINT_VARIANT* copyVariant = copy.GetVariant( "Production" );
309 BOOST_REQUIRE( copyVariant );
310 BOOST_CHECK( copyVariant->GetDNP() );
311 BOOST_CHECK( copyVariant->GetExcludedFromBOM() );
312 BOOST_CHECK_EQUAL( copyVariant->GetFieldValue( original.Value().GetName() ), "22K" );
313
314 FOOTPRINT assigned( &board );
315 assigned = original;
316
317 const FOOTPRINT_VARIANT* assignedVariant = assigned.GetVariant( "Production" );
318 BOOST_REQUIRE( assignedVariant );
319 BOOST_CHECK( assignedVariant->GetDNP() );
320 BOOST_CHECK( assignedVariant->GetExcludedFromBOM() );
321 BOOST_CHECK_EQUAL( assignedVariant->GetFieldValue( original.Value().GetName() ), "22K" );
322}
323
324
325BOOST_AUTO_TEST_CASE( FootprintFieldShownTextForVariant )
326{
327 BOARD board;
328 FOOTPRINT fp( &board );
329
330 board.AddVariant( "Production" );
331 board.SetCurrentVariant( "Production" );
332
333 fp.SetValue( "10K" );
334
335 FOOTPRINT_VARIANT prodVariant( "Production" );
336 prodVariant.SetFieldValue( fp.Value().GetName(), "22K" );
337 fp.SetVariant( prodVariant );
338
339 BOOST_CHECK_EQUAL( fp.Value().GetShownText( false ), "22K" );
340
341 board.SetCurrentVariant( wxEmptyString );
342 BOOST_CHECK_EQUAL( fp.Value().GetShownText( false ), "10K" );
343}
344
345
346BOOST_AUTO_TEST_CASE( BoardVariantTextVars )
347{
348 BOARD board;
349
350 board.AddVariant( "Production" );
351 board.SetVariantDescription( "Production", "Production build" );
352 board.SetCurrentVariant( "Production" );
353
354 wxString variantToken = wxT( "VARIANT" );
355 BOOST_CHECK( board.ResolveTextVar( &variantToken, 0 ) );
356 BOOST_CHECK_EQUAL( variantToken, "Production" );
357
358 wxString descToken = wxT( "VARIANT_DESC" );
359 BOOST_CHECK( board.ResolveTextVar( &descToken, 0 ) );
360 BOOST_CHECK_EQUAL( descToken, "Production build" );
361
362 board.SetCurrentVariant( wxEmptyString );
363 wxString defaultToken = wxT( "VARIANT" );
364 BOOST_CHECK( board.ResolveTextVar( &defaultToken, 0 ) );
365 BOOST_CHECK( defaultToken.IsEmpty() );
366}
367
368
369BOOST_AUTO_TEST_CASE( NetlistComponentVariantsParsing )
370{
371 const std::string netlist =
372 "(export (version 1)\n"
373 " (components\n"
374 " (comp (ref R1)\n"
375 " (value 10K)\n"
376 " (footprint Resistor_SMD:R_0603_1608Metric)\n"
377 " (libsource (lib Device) (part R))\n"
378 " (variants\n"
379 " (variant (name Alt)\n"
380 " (property (name dnp) (value 1))\n"
381 " (property (name exclude_from_bom) (value 0))\n"
382 " (fields\n"
383 " (field (name Value) \"22K\")\n"
384 " (field (name Footprint) \"Resistor_SMD:R_0805_2012Metric\")\n"
385 " )\n"
386 " )\n"
387 " )\n"
388 " )\n"
389 " )\n"
390 ")\n";
391
392 STRING_LINE_READER reader( netlist, wxT( "variant_netlist" ) );
393 NETLIST parsedNetlist;
394 KICAD_NETLIST_PARSER parser( &reader, &parsedNetlist );
395
396 parser.Parse();
397
398 BOOST_REQUIRE_EQUAL( parsedNetlist.GetCount(), 1 );
399
400 COMPONENT* component = parsedNetlist.GetComponent( 0 );
401 const COMPONENT_VARIANT* variant = component->GetVariant( "Alt" );
402
403 BOOST_REQUIRE( variant );
404 BOOST_CHECK( variant->m_hasDnp );
405 BOOST_CHECK( variant->m_dnp );
406 BOOST_CHECK( variant->m_hasExcludedFromBOM );
407 BOOST_CHECK( !variant->m_excludedFromBOM );
408
409 auto valueIt = variant->m_fields.find( "Value" );
410 BOOST_CHECK( valueIt != variant->m_fields.end() );
411 BOOST_CHECK_EQUAL( valueIt->second, "22K" );
412
413 auto fpIt = variant->m_fields.find( "Footprint" );
414 BOOST_CHECK( fpIt != variant->m_fields.end() );
415 BOOST_CHECK_EQUAL( fpIt->second, "Resistor_SMD:R_0805_2012Metric" );
416}
417
418
422BOOST_AUTO_TEST_CASE( MultipleVariantsIndependent )
423{
424 BOARD board;
425
426 // Add multiple variants
427 board.AddVariant( "Variant1" );
428 board.AddVariant( "Variant2" );
429 board.SetVariantDescription( "Variant1", "First variant" );
430 board.SetVariantDescription( "Variant2", "Second variant" );
431
432 // Create footprint and set variant-specific properties
433 FOOTPRINT fp( &board );
434 fp.SetReference( "R1" );
435 fp.SetValue( "10K" );
436
437 FOOTPRINT_VARIANT variant1( "Variant1" );
438 variant1.SetDNP( true );
439 variant1.SetFieldValue( fp.Value().GetName(), "22K" );
440 fp.SetVariant( variant1 );
441
442 FOOTPRINT_VARIANT variant2( "Variant2" );
443 variant2.SetDNP( false );
444 variant2.SetFieldValue( fp.Value().GetName(), "47K" );
445 fp.SetVariant( variant2 );
446
447 // Verify both variants are independent
448 BOOST_CHECK( fp.GetDNPForVariant( "Variant1" ) );
449 BOOST_CHECK( !fp.GetDNPForVariant( "Variant2" ) );
450
451 const FOOTPRINT_VARIANT* v1 = fp.GetVariant( "Variant1" );
452 const FOOTPRINT_VARIANT* v2 = fp.GetVariant( "Variant2" );
453
454 BOOST_REQUIRE( v1 );
455 BOOST_REQUIRE( v2 );
456
457 BOOST_CHECK_EQUAL( v1->GetFieldValue( fp.Value().GetName() ), "22K" );
458 BOOST_CHECK_EQUAL( v2->GetFieldValue( fp.Value().GetName() ), "47K" );
459
460 // Verify descriptions are independent
461 BOOST_CHECK_EQUAL( board.GetVariantDescription( "Variant1" ), "First variant" );
462 BOOST_CHECK_EQUAL( board.GetVariantDescription( "Variant2" ), "Second variant" );
463}
464
465
469BOOST_AUTO_TEST_CASE( VariantFieldUnicodeAndSpecialChars )
470{
471 BOARD board;
472 FOOTPRINT fp( &board );
473
474 board.AddVariant( "UnicodeTest" );
475
476 fp.SetValue( "Default" );
477
478 // Unicode characters
479 FOOTPRINT_VARIANT unicodeVariant( "UnicodeTest" );
480 wxString unicodeValue = wxT( "1kΩ ±5% 日本語" );
481 unicodeVariant.SetFieldValue( fp.Value().GetName(), unicodeValue );
482 fp.SetVariant( unicodeVariant );
483
484 const FOOTPRINT_VARIANT* retrieved = fp.GetVariant( "UnicodeTest" );
485 BOOST_REQUIRE( retrieved );
486 BOOST_CHECK_EQUAL( retrieved->GetFieldValue( fp.Value().GetName() ), unicodeValue );
487
488 // Special characters
489 FOOTPRINT_VARIANT specialVariant( "SpecialChars" );
490 wxString specialChars = wxT( "R<1K>\"test\"'value'" );
491 specialVariant.SetFieldValue( fp.Value().GetName(), specialChars );
492 fp.SetVariant( specialVariant );
493
494 const FOOTPRINT_VARIANT* retrievedSpecial = fp.GetVariant( "SpecialChars" );
495 BOOST_REQUIRE( retrievedSpecial );
496 BOOST_CHECK_EQUAL( retrievedSpecial->GetFieldValue( fp.Value().GetName() ), specialChars );
497
498 // Unicode in variant description
499 wxString unicodeDesc = wxT( "Variante für Produktion — 测试" );
500 board.SetVariantDescription( "UnicodeTest", unicodeDesc );
501 BOOST_CHECK_EQUAL( board.GetVariantDescription( "UnicodeTest" ), unicodeDesc );
502}
503
504
508BOOST_AUTO_TEST_CASE( VariantDeletionClearsRegistry )
509{
510 BOARD board;
511
512 board.AddVariant( "Variant1" );
513 board.AddVariant( "Variant2" );
514 board.SetVariantDescription( "Variant1", "Description 1" );
515 board.SetCurrentVariant( "Variant1" );
516
517 BOOST_CHECK_EQUAL( board.GetVariantNames().size(), 2 );
518 BOOST_CHECK( board.HasVariant( "Variant1" ) );
519
520 // Delete the variant
521 board.DeleteVariant( "Variant1" );
522
523 // Verify it's gone
524 BOOST_CHECK_EQUAL( board.GetVariantNames().size(), 1 );
525 BOOST_CHECK( !board.HasVariant( "Variant1" ) );
526 BOOST_CHECK( board.HasVariant( "Variant2" ) );
527
528 // Current variant should be cleared since we deleted the current one
529 BOOST_CHECK( board.GetCurrentVariant().IsEmpty() || board.GetCurrentVariant() != "Variant1" );
530}
531
532
536BOOST_AUTO_TEST_CASE( RenameVariantPreservesData )
537{
538 BOARD board;
539
540 board.AddVariant( "OldName" );
541 board.SetVariantDescription( "OldName", "Test description" );
542 board.SetCurrentVariant( "OldName" );
543
544 // Rename the variant
545 board.RenameVariant( "OldName", "NewName" );
546
547 // Old name should be gone
548 BOOST_CHECK( !board.HasVariant( "OldName" ) );
549
550 // New name should exist with same properties
551 BOOST_CHECK( board.HasVariant( "NewName" ) );
552 BOOST_CHECK_EQUAL( board.GetVariantDescription( "NewName" ), "Test description" );
553
554 // Current variant should be updated if it was the renamed one
555 BOOST_CHECK_EQUAL( board.GetCurrentVariant(), "NewName" );
556}
557
558
562BOOST_AUTO_TEST_CASE( GetVariantNamesForUIFormat )
563{
564 BOARD board;
565
566 board.AddVariant( "Zebra" );
567 board.AddVariant( "Alpha" );
568 board.AddVariant( "Beta" );
569
570 wxArrayString names = board.GetVariantNamesForUI();
571
572 // Should have 4 entries (default + 3 variants)
573 BOOST_CHECK( names.GetCount() >= 4 );
574
575 // First should be the default placeholder
576 BOOST_CHECK( !names[0].IsEmpty() );
577
578 // Remaining should be sorted alphabetically
579 bool foundAlpha = false;
580 bool foundBeta = false;
581 bool foundZebra = false;
582
583 for( size_t i = 1; i < names.GetCount(); i++ )
584 {
585 if( names[i] == wxT( "Alpha" ) )
586 foundAlpha = true;
587 else if( names[i] == wxT( "Beta" ) )
588 foundBeta = true;
589 else if( names[i] == wxT( "Zebra" ) )
590 foundZebra = true;
591 }
592
593 BOOST_CHECK( foundAlpha );
594 BOOST_CHECK( foundBeta );
595 BOOST_CHECK( foundZebra );
596}
597
598
602BOOST_AUTO_TEST_CASE( VariantMultipleFlagsCombinations )
603{
604 BOARD board;
605 FOOTPRINT fp( &board );
606
607 board.AddVariant( "DNPOnly" );
608 board.AddVariant( "BOMOnly" );
609 board.AddVariant( "AllFlags" );
610 board.AddVariant( "NoFlags" );
611
612 // Set various flag combinations
613 FOOTPRINT_VARIANT dnpOnly( "DNPOnly" );
614 dnpOnly.SetDNP( true );
615 dnpOnly.SetExcludedFromBOM( false );
616 dnpOnly.SetExcludedFromPosFiles( false );
617 fp.SetVariant( dnpOnly );
618
619 FOOTPRINT_VARIANT bomOnly( "BOMOnly" );
620 bomOnly.SetDNP( false );
621 bomOnly.SetExcludedFromBOM( true );
622 bomOnly.SetExcludedFromPosFiles( false );
623 fp.SetVariant( bomOnly );
624
625 FOOTPRINT_VARIANT allFlags( "AllFlags" );
626 allFlags.SetDNP( true );
627 allFlags.SetExcludedFromBOM( true );
628 allFlags.SetExcludedFromPosFiles( true );
629 fp.SetVariant( allFlags );
630
631 FOOTPRINT_VARIANT noFlags( "NoFlags" );
632 noFlags.SetDNP( false );
633 noFlags.SetExcludedFromBOM( false );
634 noFlags.SetExcludedFromPosFiles( false );
635 fp.SetVariant( noFlags );
636
637 // Verify each variant has correct flags
638 BOOST_CHECK( fp.GetDNPForVariant( "DNPOnly" ) );
639 BOOST_CHECK( !fp.GetExcludedFromBOMForVariant( "DNPOnly" ) );
640 BOOST_CHECK( !fp.GetExcludedFromPosFilesForVariant( "DNPOnly" ) );
641
642 BOOST_CHECK( !fp.GetDNPForVariant( "BOMOnly" ) );
643 BOOST_CHECK( fp.GetExcludedFromBOMForVariant( "BOMOnly" ) );
644 BOOST_CHECK( !fp.GetExcludedFromPosFilesForVariant( "BOMOnly" ) );
645
646 BOOST_CHECK( fp.GetDNPForVariant( "AllFlags" ) );
647 BOOST_CHECK( fp.GetExcludedFromBOMForVariant( "AllFlags" ) );
648 BOOST_CHECK( fp.GetExcludedFromPosFilesForVariant( "AllFlags" ) );
649
650 BOOST_CHECK( !fp.GetDNPForVariant( "NoFlags" ) );
651 BOOST_CHECK( !fp.GetExcludedFromBOMForVariant( "NoFlags" ) );
652 BOOST_CHECK( !fp.GetExcludedFromPosFilesForVariant( "NoFlags" ) );
653}
654
655
660BOOST_AUTO_TEST_CASE( ComponentVariantToFootprintTransfer )
661{
662 BOARD board;
663 FOOTPRINT fp( &board );
664
665 fp.SetReference( "R1" );
666 fp.SetValue( "10K" );
667
668 board.AddVariant( "Variant A" );
669 board.AddVariant( "Variant B" );
670
671 // Create a COMPONENT with variant data (simulating schematic data)
672 LIB_ID fpid( wxT( "Resistor_SMD" ), wxT( "R_0805_2012Metric" ) );
673 wxString reference = wxT( "R1" );
674 wxString value = wxT( "10K" );
676 std::vector<KIID> kiids;
677
678 COMPONENT component( fpid, reference, value, path, kiids );
679
680 // Add variant "Variant A" with DNP=true, ExcludedFromBOM=false, ExcludedFromPosFiles=true
681 // and a field override for Datasheet
682 COMPONENT_VARIANT variantA( "Variant A" );
683 variantA.m_dnp = true;
684 variantA.m_hasDnp = true;
685 variantA.m_excludedFromBOM = false;
686 variantA.m_hasExcludedFromBOM = true;
687 variantA.m_excludedFromPosFiles = true;
688 variantA.m_hasExcludedFromPosFiles = true;
689 variantA.m_fields[wxT( "Datasheet" )] = wxT( "https://example.com/datasheet.pdf" );
690 component.AddVariant( variantA );
691
692 // Add variant "Variant B" with DNP=false, ExcludedFromBOM=true
693 COMPONENT_VARIANT variantB( "Variant B" );
694 variantB.m_dnp = false;
695 variantB.m_hasDnp = true;
696 variantB.m_excludedFromBOM = true;
697 variantB.m_hasExcludedFromBOM = true;
698 variantB.m_excludedFromPosFiles = false;
699 variantB.m_hasExcludedFromPosFiles = true;
700 variantB.m_fields[wxT( "Value" )] = wxT( "22K" );
701 component.AddVariant( variantB );
702
703 // Transfer variant data from COMPONENT to FOOTPRINT (simulating applyComponentVariants)
704 for( const auto& [variantName, componentVariant] : component.GetVariants() )
705 {
706 FOOTPRINT_VARIANT* fpVariant = fp.AddVariant( variantName );
707 BOOST_REQUIRE( fpVariant );
708
709 if( componentVariant.m_hasDnp )
710 fpVariant->SetDNP( componentVariant.m_dnp );
711
712 if( componentVariant.m_hasExcludedFromBOM )
713 fpVariant->SetExcludedFromBOM( componentVariant.m_excludedFromBOM );
714
715 if( componentVariant.m_hasExcludedFromPosFiles )
716 fpVariant->SetExcludedFromPosFiles( componentVariant.m_excludedFromPosFiles );
717
718 for( const auto& [fieldName, fieldValue] : componentVariant.m_fields )
719 fpVariant->SetFieldValue( fieldName, fieldValue );
720 }
721
722 // Verify Variant A properties
723 const FOOTPRINT_VARIANT* fpVariantA = fp.GetVariant( "Variant A" );
724 BOOST_REQUIRE( fpVariantA );
725 BOOST_CHECK( fpVariantA->GetDNP() );
726 BOOST_CHECK( !fpVariantA->GetExcludedFromBOM() );
727 BOOST_CHECK( fpVariantA->GetExcludedFromPosFiles() );
728 BOOST_CHECK( fpVariantA->HasFieldValue( wxT( "Datasheet" ) ) );
729 BOOST_CHECK_EQUAL( fpVariantA->GetFieldValue( wxT( "Datasheet" ) ),
730 wxT( "https://example.com/datasheet.pdf" ) );
731
732 // Verify Variant B properties
733 const FOOTPRINT_VARIANT* fpVariantB = fp.GetVariant( "Variant B" );
734 BOOST_REQUIRE( fpVariantB );
735 BOOST_CHECK( !fpVariantB->GetDNP() );
736 BOOST_CHECK( fpVariantB->GetExcludedFromBOM() );
737 BOOST_CHECK( !fpVariantB->GetExcludedFromPosFiles() );
738 BOOST_CHECK( fpVariantB->HasFieldValue( wxT( "Value" ) ) );
739 BOOST_CHECK_EQUAL( fpVariantB->GetFieldValue( wxT( "Value" ) ), wxT( "22K" ) );
740
741 // Verify variant-aware getters work
742 BOOST_CHECK( fp.GetDNPForVariant( "Variant A" ) );
743 BOOST_CHECK( !fp.GetDNPForVariant( "Variant B" ) );
744 BOOST_CHECK( !fp.GetExcludedFromBOMForVariant( "Variant A" ) );
745 BOOST_CHECK( fp.GetExcludedFromBOMForVariant( "Variant B" ) );
746 BOOST_CHECK( fp.GetExcludedFromPosFilesForVariant( "Variant A" ) );
747 BOOST_CHECK( !fp.GetExcludedFromPosFilesForVariant( "Variant B" ) );
748}
749
750
756BOOST_AUTO_TEST_CASE( ComponentVariantPartialOverride )
757{
758 BOARD board;
759 FOOTPRINT fp( &board );
760
761 fp.SetReference( "R1" );
762
763 // Set base footprint to have all attributes false
764 fp.SetDNP( false );
765 fp.SetExcludedFromBOM( false );
766 fp.SetExcludedFromPosFiles( false );
767
768 board.AddVariant( "TestVariant" );
769
770 // Pre-populate the footprint variant with all true values (simulating old state)
771 FOOTPRINT_VARIANT initialVariant( "TestVariant" );
772 initialVariant.SetDNP( true );
773 initialVariant.SetExcludedFromBOM( true );
774 initialVariant.SetExcludedFromPosFiles( true );
775 fp.SetVariant( initialVariant );
776
777 // Create a component variant that only has explicit DNP override set
778 LIB_ID fpid( wxT( "Resistor_SMD" ), wxT( "R_0805_2012Metric" ) );
780 std::vector<KIID> kiids;
781 COMPONENT component( fpid, wxT( "R1" ), wxT( "10K" ), path, kiids );
782
783 COMPONENT_VARIANT partialVariant( "TestVariant" );
784 partialVariant.m_dnp = true;
785 partialVariant.m_hasDnp = true;
786 // m_hasExcludedFromBOM and m_hasExcludedFromPosFiles are false (no explicit override)
787 component.AddVariant( partialVariant );
788
789 // Transfer properties, resetting non-overridden ones to base footprint values
790 for( const auto& [variantName, componentVariant] : component.GetVariants() )
791 {
792 FOOTPRINT_VARIANT* fpVariant = fp.GetVariant( variantName );
793 BOOST_REQUIRE( fpVariant );
794
795 // Apply explicit override or reset to base footprint value
796 bool targetDnp = componentVariant.m_hasDnp ? componentVariant.m_dnp : fp.IsDNP();
797 fpVariant->SetDNP( targetDnp );
798
799 bool targetBOM = componentVariant.m_hasExcludedFromBOM
800 ? componentVariant.m_excludedFromBOM
801 : fp.IsExcludedFromBOM();
802 fpVariant->SetExcludedFromBOM( targetBOM );
803
804 bool targetPos = componentVariant.m_hasExcludedFromPosFiles
805 ? componentVariant.m_excludedFromPosFiles
807 fpVariant->SetExcludedFromPosFiles( targetPos );
808 }
809
810 // Verify: DNP should be true (m_hasDnp was true with value true)
811 BOOST_CHECK( fp.GetDNPForVariant( "TestVariant" ) );
812
813 // Verify: ExcludedFromBOM should be reset to base (false)
814 BOOST_CHECK( !fp.GetExcludedFromBOMForVariant( "TestVariant" ) );
815
816 // Verify: ExcludedFromPosFiles should be reset to base (false)
817 BOOST_CHECK( !fp.GetExcludedFromPosFilesForVariant( "TestVariant" ) );
818}
819
820
825BOOST_AUTO_TEST_CASE( NetlistVariantAttributeParsing )
826{
827 // Create component variants with all attribute types
828 COMPONENT_VARIANT variantWithAll( "WithAll" );
829 variantWithAll.m_dnp = true;
830 variantWithAll.m_hasDnp = true;
831 variantWithAll.m_excludedFromBOM = true;
832 variantWithAll.m_hasExcludedFromBOM = true;
833 variantWithAll.m_excludedFromPosFiles = true;
834 variantWithAll.m_hasExcludedFromPosFiles = true;
835
836 // Verify all flags are set correctly
837 BOOST_CHECK( variantWithAll.m_hasDnp );
838 BOOST_CHECK( variantWithAll.m_dnp );
839 BOOST_CHECK( variantWithAll.m_hasExcludedFromBOM );
840 BOOST_CHECK( variantWithAll.m_excludedFromBOM );
841 BOOST_CHECK( variantWithAll.m_hasExcludedFromPosFiles );
842 BOOST_CHECK( variantWithAll.m_excludedFromPosFiles );
843
844 // Create a component variant with only some attributes
845 COMPONENT_VARIANT variantPartial( "Partial" );
846 variantPartial.m_dnp = true;
847 variantPartial.m_hasDnp = true;
848 // ExcludedFromBOM and ExcludedFromPosFiles have no explicit override
849
850 BOOST_CHECK( variantPartial.m_hasDnp );
851 BOOST_CHECK( !variantPartial.m_hasExcludedFromBOM );
852 BOOST_CHECK( !variantPartial.m_hasExcludedFromPosFiles );
853
854 // Create a variant with false values (explicit override to false)
855 COMPONENT_VARIANT variantAllFalse( "AllFalse" );
856 variantAllFalse.m_dnp = false;
857 variantAllFalse.m_hasDnp = true;
858 variantAllFalse.m_excludedFromBOM = false;
859 variantAllFalse.m_hasExcludedFromBOM = true;
860 variantAllFalse.m_excludedFromPosFiles = false;
861 variantAllFalse.m_hasExcludedFromPosFiles = true;
862
863 BOOST_CHECK( variantAllFalse.m_hasDnp );
864 BOOST_CHECK( !variantAllFalse.m_dnp );
865 BOOST_CHECK( variantAllFalse.m_hasExcludedFromBOM );
866 BOOST_CHECK( !variantAllFalse.m_excludedFromBOM );
867 BOOST_CHECK( variantAllFalse.m_hasExcludedFromPosFiles );
868 BOOST_CHECK( !variantAllFalse.m_excludedFromPosFiles );
869}
870
871
876BOOST_AUTO_TEST_CASE( VariantAttributeTransferWithReset )
877{
878 BOARD board;
879 FOOTPRINT fp( &board );
880 fp.SetReference( "R1" );
881 fp.SetFPID( LIB_ID( wxT( "Resistor_SMD" ), wxT( "R_0805" ) ) );
882
883 // Base footprint has no flags set
884 fp.SetDNP( false );
885 fp.SetExcludedFromBOM( false );
886 fp.SetExcludedFromPosFiles( false );
887
888 board.AddVariant( "Variant A" );
889
890 // Step 1: Initial state - variant has all attributes set (simulating previous netlist update)
891 FOOTPRINT_VARIANT* fpVariant = fp.AddVariant( "Variant A" );
892 BOOST_REQUIRE( fpVariant );
893 fpVariant->SetDNP( true );
894 fpVariant->SetExcludedFromBOM( true );
895 fpVariant->SetExcludedFromPosFiles( true );
896
897 // Verify initial state
898 BOOST_CHECK( fp.GetDNPForVariant( "Variant A" ) );
899 BOOST_CHECK( fp.GetExcludedFromBOMForVariant( "Variant A" ) );
900 BOOST_CHECK( fp.GetExcludedFromPosFilesForVariant( "Variant A" ) );
901
902 // Step 2: New netlist has variant with NO explicit attribute overrides
903 // This simulates the user removing all variant attribute overrides from schematic
904 COMPONENT_VARIANT componentVariant( "Variant A" );
905 // All m_has* flags are false by default (no explicit overrides)
906
907 // Step 3: Apply the fixed transfer logic (same as board_netlist_updater::applyComponentVariants)
908 // For isActive = true case with no explicit overrides, attributes should reset to base
909 bool targetDnp = componentVariant.m_hasDnp ? componentVariant.m_dnp : fp.IsDNP();
910 bool targetBOM = componentVariant.m_hasExcludedFromBOM ? componentVariant.m_excludedFromBOM
911 : fp.IsExcludedFromBOM();
912 bool targetPos = componentVariant.m_hasExcludedFromPosFiles
913 ? componentVariant.m_excludedFromPosFiles
915
916 fpVariant->SetDNP( targetDnp );
917 fpVariant->SetExcludedFromBOM( targetBOM );
918 fpVariant->SetExcludedFromPosFiles( targetPos );
919
920 // Step 4: Verify all attributes were reset to base footprint values (false)
921 BOOST_CHECK_MESSAGE( !fp.GetDNPForVariant( "Variant A" ),
922 "DNP should be reset to base value (false) when no explicit override" );
923 BOOST_CHECK_MESSAGE( !fp.GetExcludedFromBOMForVariant( "Variant A" ),
924 "ExcludedFromBOM should be reset to base value (false) when no override" );
925 BOOST_CHECK_MESSAGE( !fp.GetExcludedFromPosFilesForVariant( "Variant A" ),
926 "ExcludedFromPosFiles should be reset to base (false) when no override" );
927}
928
929
941BOOST_AUTO_TEST_CASE( VariantTestR2FootprintAttributeVerification )
942{
943 wxString dataPath = KI_TEST::GetPcbnewTestDataDir() + wxString( "variant_test/variant_test.kicad_pcb" );
944
945 PCB_IO_KICAD_SEXPR pcbIo;
946 std::unique_ptr<BOARD> board( pcbIo.LoadBoard( dataPath, nullptr ) );
947
948 BOOST_REQUIRE( board );
949 BOOST_REQUIRE( board->HasVariant( "Variant A" ) );
950
951 // Find both R2 footprints and verify their variant data
952 FOOTPRINT* r2_c1210 = nullptr; // Variant A's footprint (C_1210_3225Metric)
953 FOOTPRINT* r2_c3640 = nullptr; // Base footprint (C_3640_9110Metric)
954
955 for( FOOTPRINT* fp : board->Footprints() )
956 {
957 if( fp->GetReference() == wxT( "R2" ) )
958 {
959 wxString fpName = fp->GetFPID().GetLibItemName();
960
961 if( fpName.Contains( wxT( "C_1210" ) ) )
962 r2_c1210 = fp;
963 else if( fpName.Contains( wxT( "C_3640" ) ) )
964 r2_c3640 = fp;
965 }
966 }
967
968 // Verify we found both R2 footprints
969 BOOST_TEST_MESSAGE( "Looking for R2 footprints in test data" );
970 BOOST_REQUIRE_MESSAGE( r2_c1210, "Should find R2 with C_1210 footprint (variant footprint)" );
971 BOOST_REQUIRE_MESSAGE( r2_c3640, "Should find R2 with C_3640 footprint (base footprint)" );
972
973 // Check C_1210 (Variant A's footprint) - this IS the active footprint for Variant A
974 // The schematic has NO attribute overrides, so the PCB variant should also have no overrides
975 // (or equivalently, values should match base footprint)
976 const FOOTPRINT_VARIANT* c1210_variantA = r2_c1210->GetVariant( "Variant A" );
977
978 BOOST_TEST_MESSAGE( "R2 C_1210 (variant footprint) base attributes: DNP="
979 << r2_c1210->IsDNP() << " ExcludedFromBOM=" << r2_c1210->IsExcludedFromBOM()
980 << " ExcludedFromPosFiles=" << r2_c1210->IsExcludedFromPosFiles() );
981
982 if( c1210_variantA )
983 {
984 BOOST_TEST_MESSAGE( "R2 C_1210 Variant A attributes: DNP=" << c1210_variantA->GetDNP()
985 << " ExcludedFromBOM=" << c1210_variantA->GetExcludedFromBOM()
986 << " ExcludedFromPosFiles=" << c1210_variantA->GetExcludedFromPosFiles() );
987
988 // For the variant footprint, since schematic has NO attribute overrides,
989 // variant attributes should match base footprint values (all false)
990 BOOST_CHECK_MESSAGE( !c1210_variantA->GetDNP(),
991 "C_1210 Variant A DNP should be false (no schematic override)" );
992 BOOST_CHECK_MESSAGE( !c1210_variantA->GetExcludedFromBOM(),
993 "C_1210 Variant A ExcludedFromBOM should be false (no override)" );
994 BOOST_CHECK_MESSAGE( !c1210_variantA->GetExcludedFromPosFiles(),
995 "C_1210 Variant A ExcludedFromPosFiles should be false (no override)" );
996 }
997 else
998 {
999 BOOST_TEST_MESSAGE( "R2 C_1210 has no Variant A data" );
1000 }
1001
1002 // Check C_3640 (base footprint) - this is NOT the active footprint for Variant A
1003 // Since schematic R2:Variant A has NO explicit attribute overrides, the PCB variant
1004 // should also have no attribute overrides (attributes reset to base footprint values).
1005 // This matches the schematic inheritance model where unset attributes inherit from base.
1006 const FOOTPRINT_VARIANT* c3640_variantA = r2_c3640->GetVariant( "Variant A" );
1007
1008 BOOST_TEST_MESSAGE( "R2 C_3640 (base footprint) base attributes: DNP="
1009 << r2_c3640->IsDNP() << " ExcludedFromBOM=" << r2_c3640->IsExcludedFromBOM()
1010 << " ExcludedFromPosFiles=" << r2_c3640->IsExcludedFromPosFiles() );
1011
1012 if( c3640_variantA )
1013 {
1014 BOOST_TEST_MESSAGE( "R2 C_3640 Variant A attributes: DNP=" << c3640_variantA->GetDNP()
1015 << " ExcludedFromBOM=" << c3640_variantA->GetExcludedFromBOM()
1016 << " ExcludedFromPosFiles=" << c3640_variantA->GetExcludedFromPosFiles() );
1017
1018 // For the base footprint, since schematic has NO explicit attribute overrides,
1019 // variant attributes should match base footprint values (all false).
1020 // The PCB should mirror the schematic's inheritance model.
1021 BOOST_CHECK_MESSAGE( !c3640_variantA->GetDNP(),
1022 "C_3640 Variant A DNP should be false (no schematic override)" );
1023 BOOST_CHECK_MESSAGE( !c3640_variantA->GetExcludedFromBOM(),
1024 "C_3640 Variant A ExcludedFromBOM should be false (no override)" );
1025 BOOST_CHECK_MESSAGE( !c3640_variantA->GetExcludedFromPosFiles(),
1026 "C_3640 Variant A ExcludedFromPosFiles should be false (no override)" );
1027 }
1028 else
1029 {
1030 // If there's no variant data stored, that's also acceptable - implies no overrides
1031 BOOST_TEST_MESSAGE( "R2 C_3640 has no Variant A data (implies no overrides)" );
1032 }
1033}
1034
1035
1039BOOST_AUTO_TEST_CASE( VariantTestProjectLoad )
1040{
1041 wxString dataPath = KI_TEST::GetPcbnewTestDataDir() + wxString( "variant_test/variant_test.kicad_pcb" );
1042
1043 PCB_IO_KICAD_SEXPR pcbIo;
1044 std::unique_ptr<BOARD> board( pcbIo.LoadBoard( dataPath, nullptr ) );
1045
1046 BOOST_REQUIRE( board );
1047
1048 // Verify the board has the "Variant A" variant registered
1049 BOOST_CHECK( board->HasVariant( "Variant A" ) );
1050
1051 // Find footprints and verify their variant properties
1052 // Based on the variant_test.kicad_pcb and schematic:
1053 // - R1 with Variant A having field override for Datasheet
1054 // - R2 (C_3640 base footprint) with Variant A having NO attribute overrides
1055 // (schematic has no explicit overrides, so PCB mirrors base values)
1056 // - R3 with Variant A having DNP (explicit schematic override)
1057
1058 for( FOOTPRINT* fp : board->Footprints() )
1059 {
1060 const wxString& ref = fp->GetReference();
1061
1062 if( ref == wxT( "R1" ) )
1063 {
1064 const FOOTPRINT_VARIANT* variantA = fp->GetVariant( "Variant A" );
1065
1066 if( variantA )
1067 {
1068 // R1 has a Datasheet field override in Variant A
1069 BOOST_CHECK( variantA->HasFieldValue( wxT( "Datasheet" ) ) );
1070 BOOST_CHECK_EQUAL( variantA->GetFieldValue( wxT( "Datasheet" ) ), wxT( "test" ) );
1071 }
1072 }
1073 else if( ref == wxT( "R2" ) )
1074 {
1075 // R2's C_3640 footprint (base) should have NO attribute overrides
1076 // because schematic R2:Variant A has no explicit attribute overrides.
1077 // PCB mirrors the schematic inheritance model.
1078 wxString fpName = fp->GetFPID().GetLibItemName();
1079
1080 if( fpName.Contains( wxT( "C_3640" ) ) )
1081 {
1082 const FOOTPRINT_VARIANT* variantA = fp->GetVariant( "Variant A" );
1083
1084 if( variantA )
1085 {
1086 BOOST_CHECK( !variantA->GetDNP() );
1087 BOOST_CHECK( !variantA->GetExcludedFromBOM() );
1088 BOOST_CHECK( !variantA->GetExcludedFromPosFiles() );
1089 }
1090 }
1091 }
1092 else if( ref == wxT( "R3" ) )
1093 {
1094 const FOOTPRINT_VARIANT* variantA = fp->GetVariant( "Variant A" );
1095
1096 if( variantA )
1097 {
1098 // R3 has DNP in Variant A (explicit schematic override)
1099 BOOST_CHECK( variantA->GetDNP() );
1100 }
1101 }
1102 }
1103}
1104
1105
General utilities for PCB file IO for QA programs.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
void SetCurrentVariant(const wxString &aVariant)
Definition board.cpp:2498
const std::vector< wxString > & GetVariantNames() const
Definition board.h:407
wxArrayString GetVariantNamesForUI() const
Return the variant names for UI display.
Definition board.cpp:2644
void DeleteVariant(const wxString &aVariantName)
Definition board.cpp:2532
bool ResolveTextVar(wxString *token, int aDepth) const
Definition board.cpp:501
bool HasVariant(const wxString &aVariantName) const
Definition board.cpp:2515
void AddVariant(const wxString &aVariantName)
Definition board.cpp:2521
wxString GetVariantDescription(const wxString &aVariantName) const
Definition board.cpp:2608
wxString GetCurrentVariant() const
Definition board.h:404
void RenameVariant(const wxString &aOldName, const wxString &aNewName)
Definition board.cpp:2560
void SetVariantDescription(const wxString &aVariantName, const wxString &aDescription)
Definition board.cpp:2627
Store all of the related component information found in a netlist.
void AddVariant(const COMPONENT_VARIANT &aVariant)
const COMPONENT_VARIANT * GetVariant(const wxString &aVariantName) const
const CASE_INSENSITIVE_MAP< COMPONENT_VARIANT > & GetVariants() const
Variant information for a footprint.
Definition footprint.h:144
wxString GetName() const
Definition footprint.h:154
bool HasFieldValue(const wxString &aFieldName) const
Definition footprint.h:191
void SetExcludedFromPosFiles(bool aExclude)
Definition footprint.h:164
wxString GetFieldValue(const wxString &aFieldName) const
Get a field value override for this variant.
Definition footprint.h:171
const std::map< wxString, wxString > & GetFields() const
Definition footprint.h:196
bool GetExcludedFromBOM() const
Definition footprint.h:160
void SetDNP(bool aDNP)
Definition footprint.h:158
bool GetExcludedFromPosFiles() const
Definition footprint.h:163
bool GetDNP() const
Definition footprint.h:157
void SetFieldValue(const wxString &aFieldName, const wxString &aValue)
Set a field value override for this variant.
Definition footprint.h:186
void SetExcludedFromBOM(bool aExclude)
Definition footprint.h:161
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:350
bool IsDNP() const
Definition footprint.h:869
bool IsExcludedFromBOM() const
Definition footprint.h:860
void SetDNP(bool aDNP=true)
Definition footprint.h:870
void SetExcludedFromBOM(bool aExclude=true)
Definition footprint.h:861
void SetAttributes(int aAttributes)
Definition footprint.h:408
PCB_FIELD & Value()
read/write accessors:
Definition footprint.h:777
void SetExcludedFromPosFiles(bool aExclude=true)
Definition footprint.h:852
const FOOTPRINT_VARIANT * GetVariant(const wxString &aVariantName) const
Get a variant by name.
void SetReference(const wxString &aReference)
Definition footprint.h:747
bool IsExcludedFromPosFiles() const
Definition footprint.h:851
void SetValue(const wxString &aValue)
Definition footprint.h:768
bool GetDNPForVariant(const wxString &aVariantName) const
Get the DNP status for a specific variant.
void SetVariant(const FOOTPRINT_VARIANT &aVariant)
Add or update a variant.
bool GetExcludedFromPosFilesForVariant(const wxString &aVariantName) const
Get the exclude-from-position-files status for a specific variant.
FOOTPRINT_VARIANT * AddVariant(const wxString &aVariantName)
Add a new variant with the given name.
bool GetExcludedFromBOMForVariant(const wxString &aVariantName) const
Get the exclude-from-BOM status for a specific variant.
The parser for reading the KiCad s-expression netlist format.
void Parse()
Function Parse parse the full netlist.
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
unsigned GetCount() const
COMPONENT * GetComponent(unsigned aIndex)
Return the COMPONENT at aIndex.
wxString GetShownText(bool aAllowExtraText, int aDepth=0) const override
Return the string actually shown after processing of the base text.
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition richio.h:226
@ FP_DNP
Definition footprint.h:88
@ FP_EXCLUDE_FROM_POS_FILES
Definition footprint.h:84
@ FP_EXCLUDE_FROM_BOM
Definition footprint.h:85
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
bool m_hasExcludedFromPosFiles
nlohmann::ordered_map< wxString, wxString > m_fields
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
std::string path
VECTOR3I v1(5, 5, 5)
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
BOOST_CHECK_EQUAL(result, "25.4")
BOOST_AUTO_TEST_CASE(FootprintVariantBasics)
Test FOOTPRINT_VARIANT class basic operations.
VECTOR2I v2(1, 0)