KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_schematic_text_var_reactive.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21#include <algorithm>
22#include <memory>
23
24#include <eeschema_helpers.h>
25#include <eeschema_test_utils.h>
26#include <locale_io.h>
27#include <schematic.h>
29#include <sch_screen.h>
30#include <sch_sheet.h>
31#include <sch_symbol.h>
32#include <sch_text.h>
33#include <sch_field.h>
34#include <sch_sheet_pin.h>
35#include <text_var_dependency.h>
36
37#include "sch_table.h"
38
39
47BOOST_AUTO_TEST_SUITE( SchematicTextVarReactive )
48
49
50BOOST_AUTO_TEST_CASE( AdapterInstalledOnSchematicConstruction )
51{
52 SCHEMATIC sch( nullptr );
55}
56
57
58BOOST_AUTO_TEST_CASE( SchTextItemRegistersOnAdded )
59{
60 SCHEMATIC sch( nullptr );
62 text.SetText( wxT( "${U1:Value}" ) );
63
64 std::vector<SCH_ITEM*> added{ &text };
65 sch.GetTextVarAdapter()->OnSchItemsAdded( sch, added );
66
68 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "U1:Value" ) ) ), 1u );
69}
70
71
72BOOST_AUTO_TEST_CASE( SchSymbolFieldsRegisterAsDependents )
73{
74 SCHEMATIC sch( nullptr );
75 SCH_SYMBOL sym;
76
77 // The symbol's own VALUE field has a text-var reference.
78 sym.GetField( FIELD_T::VALUE )->SetText( wxT( "${SHEETNAME}" ) );
79
80 std::vector<SCH_ITEM*> added{ &sym };
81 sch.GetTextVarAdapter()->OnSchItemsAdded( sch, added );
82
84 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "SHEETNAME" ) ) ), 1u );
85}
86
87
88BOOST_AUTO_TEST_CASE( RemovedItemsAreUnregistered )
89{
90 SCHEMATIC sch( nullptr );
92 text.SetText( wxT( "${X}" ) );
93
94 std::vector<SCH_ITEM*> items{ &text };
95 sch.GetTextVarAdapter()->OnSchItemsAdded( sch, items );
96
98 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "X" ) ) ), 1u );
99
100 sch.GetTextVarAdapter()->OnSchItemsRemoved( sch, items );
101 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "X" ) ) ), 0u );
102}
103
104
105BOOST_AUTO_TEST_CASE( RetextReRegisters )
106{
107 SCHEMATIC sch( nullptr );
109 text.SetText( wxT( "${OLD}" ) );
110
111 SCH_SHEET sheet;
112 SCH_SHEET_PIN* pin = new SCH_SHEET_PIN( &sheet );
113 sheet.AddPin( pin );
114 pin->SetText( wxT( "${OLD}" ) );
115
117 SCH_TABLECELL* cell = new SCH_TABLECELL();
118 table.AddCell( cell );
119 cell->SetText( wxT( "${OLD}" ) );
120
121 std::vector<SCH_ITEM*> items{ &text, &sheet, &table };
122 std::vector<SCH_ITEM*> just_text{ &text };
123 std::vector<SCH_ITEM*> just_sheet{ &sheet };
124 std::vector<SCH_ITEM*> just_table{ &table };
125 sch.GetTextVarAdapter()->OnSchItemsAdded( sch, items );
126
128 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "OLD" ) ) ), 3u );
129
130 // Edit the text and fire a change notification — the adapter must drop
131 // the old edge and register the new one.
132 text.SetText( wxT( "${NEW}" ) );
133 sch.GetTextVarAdapter()->OnSchItemsChanged( sch, just_text );
134
135 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "OLD" ) ) ), 2u );
136 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "NEW" ) ) ), 1u );
137
138 // Edit the pin and fire a change notification — the adapter must drop
139 // the old edge and register the new one.
140 pin->SetText( wxT( "${NEW}" ) );
141 sch.GetTextVarAdapter()->OnSchItemsChanged( sch, just_sheet );
142
143 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "OLD" ) ) ), 1u );
144 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "NEW" ) ) ), 2u );
145
146 // Edit the cell text and fire a change notification — the adapter must drop
147 // the old edge and register the new one.
148 cell->SetText( wxT( "${NEW}" ) );
149 sch.GetTextVarAdapter()->OnSchItemsChanged( sch, just_table );
150
151 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "OLD" ) ) ), 0u );
152 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "NEW" ) ) ), 3u );
153}
154
155
156BOOST_AUTO_TEST_CASE( SpiceOPTokensAreNotRegistered )
157{
158 SCHEMATIC sch( nullptr );
160 text.SetText( wxT( "${OP:port}" ) );
161
162 std::vector<SCH_ITEM*> items{ &text };
163 sch.GetTextVarAdapter()->OnSchItemsAdded( sch, items );
164
166}
167
168
169BOOST_AUTO_TEST_CASE( LoadedSchematicIsIndexed )
170{
172
173 wxString path = wxString::FromUTF8( KI_TEST::GetEeschemaTestDataDir() )
174 + wxS( "NoConnectOnLineWithGlobalLabel.kicad_sch" );
175 std::unique_ptr<SCHEMATIC> sch( EESCHEMA_HELPERS::LoadSchematic( path, true, true ) );
176 BOOST_REQUIRE( sch );
177
178 // Both global labels carry ${INTERSHEET_REFS} in their intersheet references field
179 const TEXT_VAR_DEPENDENCY_INDEX& index = sch->GetTextVarAdapter()->Tracker().Index();
180 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "INTERSHEET_REFS" ) ) ), 2u );
181}
182
183
184BOOST_AUTO_TEST_CASE( ReplacedSheetScreenIsUnindexed )
185{
187
188 wxString path = wxString::FromUTF8( KI_TEST::GetEeschemaTestDataDir() ) + wxS( "issue13212.kicad_sch" );
189 std::unique_ptr<SCHEMATIC> sch( EESCHEMA_HELPERS::LoadSchematic( path, true, true ) );
190 BOOST_REQUIRE( sch );
191
192 const TEXT_VAR_REF_KEY key = TEXT_VAR_REF_KEY::FromToken( wxT( "INTERSHEET_REFS" ) );
193 const TEXT_VAR_DEPENDENCY_INDEX& index = sch->GetTextVarAdapter()->Tracker().Index();
194
195 // Root holds 3 labels, subsheet 1 holds 2, and the shared subsheet 2 holds 1
196 BOOST_REQUIRE_EQUAL( index.DependentCount( key ), 6u );
197
198 SCH_SHEET* subsheet = nullptr;
199
200 for( SCH_ITEM* item : sch->RootScreen()->Items().OfType( SCH_SHEET_T ) )
201 {
202 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
203
204 if( sheet->GetFileName().EndsWith( wxS( "issue13212_subsheet_1.kicad_sch" ) ) )
205 subsheet = sheet;
206 }
207
208 BOOST_REQUIRE( subsheet );
209
210 // Same sequence as pointing a sheet at another file outside undo; the old screen is freed
211 subsheet->SetScreen( new SCH_SCREEN( sch.get() ) );
212
213 std::vector<SCH_ITEM*> items{ subsheet };
214 sch->OnItemsRemoved( items );
215 sch->OnItemsAdded( items );
216 sch->RefreshHierarchy();
217
218 BOOST_CHECK_EQUAL( index.DependentCount( key ), 4u );
219}
220
221
222BOOST_AUTO_TEST_CASE( KiidCrossRefInvalidatedBySymbolChange )
223{
225
226 wxString path = wxString::FromUTF8( KI_TEST::GetEeschemaTestDataDir() ) + wxS( "NoConnectOnPin.kicad_sch" );
227 std::unique_ptr<SCHEMATIC> sch( EESCHEMA_HELPERS::LoadSchematic( path, true, true ) );
228 BOOST_REQUIRE( sch );
229
230 SCH_SYMBOL* tp1 = nullptr;
231
232 for( const SCH_SHEET_PATH& sheet : sch->Hierarchy() )
233 {
234 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
235 tp1 = static_cast<SCH_SYMBOL*>( item );
236 }
237
238 BOOST_REQUIRE( tp1 );
239
240 // Text dialogs store cross-refs in KIID form
242 text.SetText( sch->ConvertRefsToKIIDs( wxS( "${TP1:value}" ) ) );
243 BOOST_REQUIRE( !text.GetText().Contains( wxS( "TP1" ) ) );
244
245 SCHEMATIC_TEXT_VAR_ADAPTER* adapter = sch->GetTextVarAdapter();
246 std::vector<SCH_ITEM*> added{ &text };
247 adapter->OnSchItemsAdded( *sch, added );
248
249 bool invalidated = false;
250
252 [&]( EDA_ITEM* aDep, const TEXT_VAR_REF_KEY& )
253 {
254 invalidated |= aDep == &text;
255 } );
256
257 std::vector<SCH_ITEM*> changed{ tp1 };
258 adapter->OnSchItemsChanged( *sch, changed );
259 adapter->Tracker().RemoveInvalidateListener( handle );
260
261 BOOST_CHECK( invalidated );
262}
263
264
int index
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:236
static SCHEMATIC * LoadSchematic(const wxString &aFileName, bool aSetActive, bool aForceDefaultProject, PROJECT *aProject=nullptr, bool aCalculateConnectivity=true, REPORTER *aRootReporter=nullptr)
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
Bridges SCHEMATIC's listener stream into the generic TEXT_VAR_TRACKER.
void OnSchItemsChanged(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aItems) override
void OnSchItemsRemoved(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aItems) override
void OnSchItemsAdded(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aItems) override
Holds all the data relating to one schematic.
Definition schematic.h:149
class SCHEMATIC_TEXT_VAR_ADAPTER * GetTextVarAdapter() const
Definition schematic.h:814
void SetText(const wxString &aText) override
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:386
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Schematic symbol object.
Definition sch_symbol.h:73
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Bidirectional index mapping TEXT_VAR_REF_KEY → dependent items and item → keys.
ListenerHandle AddInvalidateListener(InvalidateCallback aCallback)
Register a listener that fires for every invalidation.
std::size_t ListenerHandle
Opaque handle returned by AddInvalidateListener and consumed by RemoveInvalidateListener.
TEXT_VAR_DEPENDENCY_INDEX & Index()
void RemoveInvalidateListener(ListenerHandle aHandle)
Drop a previously-registered listener.
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
std::vector< FAB_LAYER_COLOR > dummy
Identifies a single resolvable source that a text item's ${...} reference depends on.
static TEXT_VAR_REF_KEY FromToken(const wxString &aToken)
Parse a raw token (the text between ${ and }) into a key using lexical classification only — no looku...
@ VALUE
Field Value of part, i.e. "3.3K".
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
KIBIS_PIN * pin
BOOST_AUTO_TEST_CASE(AdapterInstalledOnSchematicConstruction)
SCHEMATIC_TEXT_VAR_ADAPTER exercised at the listener interface.
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_SHEET_T
Definition typeinfo.h:171