KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_issue22620_group_annotation.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
32
33#include <boost/test/unit_test.hpp>
34
35#include <lib_symbol.h>
36#include <refdes_tracker.h>
37#include <sch_group.h>
38#include <sch_reference_list.h>
39#include <sch_screen.h>
40#include <sch_sheet_path.h>
41#include <sch_symbol.h>
42#include <schematic.h>
44#include <tools/sch_selection.h>
45
47
48#include <wx/filename.h>
49#include <wx/stdpaths.h>
50
51
53{
56 {
57 wxString tempDir = wxStandardPaths::Get().GetTempDir();
58 wxString projectPath = tempDir + wxFileName::GetPathSeparator()
59 + wxT( "test_group_annotation.kicad_pro" );
60 m_tempFiles.push_back( projectPath );
61
62 m_settingsManager.LoadProject( projectPath.ToStdString() );
63 m_schematic = std::make_unique<SCHEMATIC>( nullptr );
65 m_schematic->SetProject( m_project );
66 }
67
69 {
70 for( const wxString& file : m_tempFiles )
71 {
72 if( wxFileExists( file ) )
73 wxRemoveFile( file );
74 }
75
76 m_schematic.reset();
77 }
78
80 std::unique_ptr<SCHEMATIC> m_schematic;
82 std::vector<wxString> m_tempFiles;
83};
84
85
86std::unordered_set<SCH_SYMBOL*> getInferredSymbols( const SCH_SELECTION& aSelection );
87
88
89BOOST_FIXTURE_TEST_SUITE( Issue22620GroupAnnotation, GROUP_ANNOTATION_FIXTURE )
90
91
92
96BOOST_AUTO_TEST_CASE( TestGroupRunOnChildrenFindsSymbols )
97{
98 m_schematic->CreateDefaultScreens();
99
100 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
101 BOOST_REQUIRE( !topSheets.empty() );
102
103 SCH_SCREEN* screen = topSheets[0]->GetScreen();
104 BOOST_REQUIRE( screen != nullptr );
105
106 // Create two simple symbols
107 SCH_SYMBOL* symbol1 = new SCH_SYMBOL();
108 symbol1->SetPosition( VECTOR2I( 0, 0 ) );
109 screen->Append( symbol1 );
110
111 SCH_SYMBOL* symbol2 = new SCH_SYMBOL();
112 symbol2->SetPosition( VECTOR2I( 1000000, 0 ) );
113 screen->Append( symbol2 );
114
115 // Create a group containing both symbols
116 SCH_GROUP* group = new SCH_GROUP( screen );
117 group->SetName( wxT( "DesignBlock" ) );
118 group->AddItem( symbol1 );
119 group->AddItem( symbol2 );
120 screen->Append( group );
121
122 // Use RunOnChildren to find symbols in the group
123 std::unordered_set<SCH_SYMBOL*> foundSymbols;
124
125 group->RunOnChildren(
126 [&foundSymbols]( SCH_ITEM* aChild )
127 {
128 if( aChild->Type() == SCH_SYMBOL_T )
129 foundSymbols.insert( static_cast<SCH_SYMBOL*>( aChild ) );
130 },
132
133 // Verify both symbols were found
134 BOOST_CHECK_EQUAL( foundSymbols.size(), 2 );
135 BOOST_CHECK( foundSymbols.count( symbol1 ) == 1 );
136 BOOST_CHECK( foundSymbols.count( symbol2 ) == 1 );
137
138 BOOST_TEST_MESSAGE( "Test passed: RunOnChildren correctly finds symbols in groups" );
139}
140
141
145BOOST_AUTO_TEST_CASE( TestGroupRunOnChildrenWithNestedGroups )
146{
147 m_schematic->CreateDefaultScreens();
148
149 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
150 BOOST_REQUIRE( !topSheets.empty() );
151
152 SCH_SCREEN* screen = topSheets[0]->GetScreen();
153 BOOST_REQUIRE( screen != nullptr );
154
155 // Create symbols
156 SCH_SYMBOL* symbol1 = new SCH_SYMBOL();
157 symbol1->SetPosition( VECTOR2I( 0, 0 ) );
158 screen->Append( symbol1 );
159
160 SCH_SYMBOL* symbol2 = new SCH_SYMBOL();
161 symbol2->SetPosition( VECTOR2I( 1000000, 0 ) );
162 screen->Append( symbol2 );
163
164 SCH_SYMBOL* symbol3 = new SCH_SYMBOL();
165 symbol3->SetPosition( VECTOR2I( 2000000, 0 ) );
166 screen->Append( symbol3 );
167
168 // Create an inner group with symbol1
169 SCH_GROUP* innerGroup = new SCH_GROUP( screen );
170 innerGroup->SetName( wxT( "InnerGroup" ) );
171 innerGroup->AddItem( symbol1 );
172 screen->Append( innerGroup );
173
174 // Create an outer group containing the inner group and symbol2
175 SCH_GROUP* outerGroup = new SCH_GROUP( screen );
176 outerGroup->SetName( wxT( "OuterGroup" ) );
177 outerGroup->AddItem( innerGroup );
178 outerGroup->AddItem( symbol2 );
179 screen->Append( outerGroup );
180
181 // Use RunOnChildren with RECURSE to find all symbols in nested groups
182 std::unordered_set<SCH_SYMBOL*> foundSymbols;
183
184 outerGroup->RunOnChildren(
185 [&foundSymbols]( SCH_ITEM* aChild )
186 {
187 if( aChild->Type() == SCH_SYMBOL_T )
188 foundSymbols.insert( static_cast<SCH_SYMBOL*>( aChild ) );
189 },
191
192 // Verify both symbol1 (in nested group) and symbol2 were found
193 BOOST_CHECK_EQUAL( foundSymbols.size(), 2 );
194 BOOST_CHECK( foundSymbols.count( symbol1 ) == 1 );
195 BOOST_CHECK( foundSymbols.count( symbol2 ) == 1 );
196 BOOST_CHECK( foundSymbols.count( symbol3 ) == 0 ); // symbol3 is not in any group
197
198 BOOST_TEST_MESSAGE( "Test passed: RunOnChildren correctly handles nested groups" );
199}
200
201
215BOOST_AUTO_TEST_CASE( Issue23519_GroupSelectionReannotatesPowerSymbols )
216{
217 m_schematic->CreateDefaultScreens();
218 m_schematic->Settings().m_refDesTracker = std::make_shared<REFDES_TRACKER>( false );
219
220 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
221 BOOST_REQUIRE( !topSheets.empty() );
222
223 SCH_SHEET* rootSheet = topSheets[0];
224 SCH_SCREEN* screen = rootSheet->GetScreen();
225 BOOST_REQUIRE( screen != nullptr );
226
227 SCH_SHEET_PATH sheetPath;
228 sheetPath.push_back( rootSheet );
229
230 LIB_SYMBOL powerLib( wxT( "PWR" ), nullptr );
231 powerLib.SetGlobalPower();
232
233 SCH_SYMBOL* existingPowerSymbol =
234 new SCH_SYMBOL( powerLib, powerLib.GetLibId(), &sheetPath, 0, 0, VECTOR2I( -1000000, 0 ) );
235 existingPowerSymbol->SetRef( &sheetPath, wxT( "#PWR01" ) );
236 existingPowerSymbol->SetValueFieldText( wxT( "+3V3" ), &sheetPath );
237 screen->Append( existingPowerSymbol );
238
239 LIB_SYMBOL normalLib( wxT( "R" ), nullptr );
240 SCH_SYMBOL* normalSymbol = new SCH_SYMBOL( normalLib, normalLib.GetLibId(), &sheetPath, 0, 0, VECTOR2I( 0, 0 ) );
241 normalSymbol->SetRef( &sheetPath, wxT( "R123" ) );
242 normalSymbol->SetValueFieldText( wxT( "10k" ), &sheetPath );
243 screen->Append( normalSymbol );
244
245 SCH_SYMBOL* powerSymbol = new SCH_SYMBOL( powerLib, powerLib.GetLibId(), &sheetPath, 0, 0, VECTOR2I( 1000000, 0 ) );
246 powerSymbol->SetRef( &sheetPath, wxT( "#PWR01" ) );
247 powerSymbol->SetValueFieldText( wxT( "+5V" ), &sheetPath );
248 screen->Append( powerSymbol );
249
250 SCH_GROUP* group = new SCH_GROUP( screen );
251 group->SetName( wxT( "DesignBlock" ) );
252 group->AddItem( normalSymbol );
253 group->AddItem( powerSymbol );
254 screen->Append( group );
255
256 SCH_SELECTION selection( screen );
257 selection.Add( group );
258
259 std::unordered_set<SCH_SYMBOL*> selectedSymbols = getInferredSymbols( selection );
260
261 BOOST_REQUIRE_EQUAL( selectedSymbols.size(), 2 );
262
263 SCH_REFERENCE_LIST references;
264 SCH_REFERENCE_LIST allReferences;
265 SCH_MULTI_UNIT_REFERENCE_MAP lockedSymbols;
266
267 // Mirror the design-block placement flow when normal symbol annotation is skipped:
268 // only the power-only selection pass runs.
269 for( SCH_SYMBOL* symbol : selectedSymbols )
270 sheetPath.AppendSymbol( references, symbol, SYMBOL_FILTER_POWER, true );
271
272 SCH_REFERENCE_LIST additionalRefs;
273
274 sheetPath.GetSymbols( allReferences, SYMBOL_FILTER_ALL );
275
276 for( unsigned i = 0; i < allReferences.GetCount(); ++i )
277 {
278 if( !references.Contains( allReferences[i] ) )
279 additionalRefs.AddItem( allReferences[i] );
280 }
281
282 references.RemoveAnnotation();
283 references.SetRefDesTracker( m_schematic->Settings().m_refDesTracker );
284 references.SplitReferences();
285 references.Annotate( false, 0, 0, lockedSymbols, additionalRefs );
286 references.UpdateAnnotation();
287
288 BOOST_CHECK_EQUAL( references.GetCount(), 1u );
289 BOOST_CHECK_EQUAL( normalSymbol->GetRef( &sheetPath ), wxT( "R123" ) );
290 BOOST_CHECK_EQUAL( existingPowerSymbol->GetRef( &sheetPath ), wxT( "#PWR01" ) );
291 BOOST_CHECK_EQUAL( powerSymbol->GetRef( &sheetPath ), wxT( "#PWR02" ) );
292}
293
294
void AddItem(EDA_ITEM *aItem)
Add item to group.
Definition eda_group.cpp:58
void SetName(const wxString &aName)
Definition eda_group.h:48
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
Define a library symbol object.
Definition lib_symbol.h:79
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:148
void SetGlobalPower()
Container for project specific data.
Definition project.h:62
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:48
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:162
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
bool Contains(const SCH_REFERENCE &aItem) const
Return true if aItem exists in this list.
void Annotate(bool aUseSheetNum, int aSheetIntervalId, int aStartNumber, const SCH_MULTI_UNIT_REFERENCE_MAP &aLockedUnitMap, const SCH_REFERENCE_LIST &aAdditionalRefs, bool aStartAtCurrent=false)
Set the reference designators in the list that have not been annotated.
void SetRefDesTracker(std::shared_ptr< REFDES_TRACKER > aTracker)
void SplitReferences()
Attempt to split all reference designators into a name (U) and number (1).
void RemoveAnnotation()
Treat all symbols in this list as non-annotated.
void AddItem(const SCH_REFERENCE &aItem)
void UpdateAnnotation()
Update the symbol references for the schematic project (or the current sheet).
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void AppendSymbol(SCH_REFERENCE_LIST &aReferences, SCH_SYMBOL *aSymbol, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Append a SCH_REFERENCE object to aReferences based on aSymbol.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Adds SCH_REFERENCE object to aReferences for each symbol in the sheet.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:44
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:139
Schematic symbol object.
Definition sch_symbol.h:69
void SetPosition(const VECTOR2I &aPosition) override
Definition sch_symbol.h:886
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
void SetValueFieldText(const wxString &aValue, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString)
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
virtual void Add(EDA_ITEM *aItem)
Definition selection.cpp:38
@ RECURSE
Definition eda_item.h:49
Class to handle a set of SCH_ITEMs.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
std::map< wxString, SCH_REFERENCE_LIST > SCH_MULTI_UNIT_REFERENCE_MAP
Container to map reference designators for multi-unit parts.
@ SYMBOL_FILTER_ALL
@ SYMBOL_FILTER_POWER
std::unique_ptr< SCHEMATIC > m_schematic
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(TestGroupRunOnChildrenFindsSymbols)
Test that SCH_GROUP::RunOnChildren correctly finds symbols inside a group.
std::unordered_set< SCH_SYMBOL * > getInferredSymbols(const SCH_SELECTION &aSelection)
Definition annotate.cpp:179
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_SYMBOL_T
Definition typeinfo.h:169
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683