KiCad PCB EDA Suite
Loading...
Searching...
No Matches
schematic_text_var_adapter.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <algorithm>
23#include <eda_text.h>
24#include <sch_field.h>
25#include <sch_item.h>
26#include <sch_screen.h>
27#include <sch_sheet.h>
28#include <sch_sheet_path.h>
29#include <sch_symbol.h>
30
31
33 m_schematic( aSchematic )
34{
35 m_tracker.SetSourceKeyExtractor(
36 [this]( EDA_ITEM* aItem ) -> std::vector<TEXT_VAR_REF_KEY>
37 { return ExtractSourceKeys( aItem ); } );
38}
39
40
42{
43 if( !aItem )
44 return;
45
46 // SCH_SYMBOL: register its constituent SCH_FIELDs (not the symbol itself).
47 // The symbol is a cross-ref source, not a dependent.
48 if( SCH_SYMBOL* sym = dynamic_cast<SCH_SYMBOL*>( aItem ) )
49 {
50 for( SCH_FIELD& field : sym->GetFields() )
51 registerItem( &field );
52
53 return;
54 }
55
56 // SCH_SHEET: its fields (sheet name, file name) can carry text vars.
57 // Sheet pins are separate sch items and flow through the listener on
58 // their own when added/removed.
59 if( SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( aItem ) )
60 {
61 for( SCH_FIELD& field : sheet->GetFields() )
62 registerItem( &field );
63
64 return;
65 }
66
67 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem );
68
69 if( !text )
70 return;
71
72 m_tracker.RegisterItem( aItem, FilterTrackable( text->GetTextVarReferences() ) );
73}
74
75
77{
78 if( !aItem )
79 return;
80
81 m_tracker.UnregisterItem( aItem );
82
83 if( SCH_SYMBOL* sym = dynamic_cast<SCH_SYMBOL*>( aItem ) )
84 {
85 for( SCH_FIELD& field : sym->GetFields() )
86 m_tracker.UnregisterItem( &field );
87 }
88 else if( SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( aItem ) )
89 {
90 for( SCH_FIELD& field : sheet->GetFields() )
91 m_tracker.UnregisterItem( &field );
92 }
93}
94
95
97{
98 if( !aItem )
99 return;
100
101 // A SCH_SYMBOL change covers both "its fields were edited" (re-register
102 // each field) and "this symbol's values source cross-refs" (fan out
103 // ${REFDES:FIELD} keys).
104 if( SCH_SYMBOL* sym = dynamic_cast<SCH_SYMBOL*>( aItem ) )
105 {
106 for( SCH_FIELD& field : sym->GetFields() )
107 {
108 std::vector<TEXT_VAR_REF_KEY> refs = FilterTrackable( field.GetTextVarReferences() );
109 m_tracker.RegisterItem( &field, refs );
110 }
111
112 m_tracker.HandleItemChanged( aItem, {} );
113 return;
114 }
115
116 if( SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( aItem ) )
117 {
118 for( SCH_FIELD& field : sheet->GetFields() )
119 {
120 std::vector<TEXT_VAR_REF_KEY> refs = FilterTrackable( field.GetTextVarReferences() );
121 m_tracker.RegisterItem( &field, refs );
122 }
123
124 return;
125 }
126
127 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
128 {
129 std::vector<TEXT_VAR_REF_KEY> updated = FilterTrackable( text->GetTextVarReferences() );
130 m_tracker.HandleItemChanged( aItem, updated );
131 }
132}
133
134
136 std::vector<SCH_ITEM*>& aItems )
137{
138 for( SCH_ITEM* item : aItems )
139 registerItem( item );
140}
141
142
144 std::vector<SCH_ITEM*>& aItems )
145{
146 for( SCH_ITEM* item : aItems )
147 unregisterItem( item );
148}
149
150
152 std::vector<SCH_ITEM*>& aItems )
153{
154 for( SCH_ITEM* item : aItems )
155 handleItemChanged( item );
156}
157
158
160{
161 m_tracker.Clear();
162
163 // Walk the hierarchy. Each screen can be referenced by multiple sheet
164 // paths, but the SCH_ITEM pointers are shared — we only register each
165 // item once via the screen traversal.
166 for( const SCH_SHEET_PATH& path : m_schematic.Hierarchy() )
167 {
168 SCH_SCREEN* screen = path.LastScreen();
169
170 if( !screen )
171 continue;
172
173 for( SCH_ITEM* item : screen->Items() )
174 registerItem( item );
175 }
176}
177
178
179std::vector<TEXT_VAR_REF_KEY> SCHEMATIC_TEXT_VAR_ADAPTER::ExtractSourceKeys( EDA_ITEM* aItem ) const
180{
181 std::vector<TEXT_VAR_REF_KEY> out;
182
183 SCH_SYMBOL* sym = dynamic_cast<SCH_SYMBOL*>( aItem );
184
185 if( !sym )
186 return out;
187
188 // Repeated-sheet instances: a single SCH_SYMBOL can carry different
189 // reference designators on each SCH_SHEET_PATH it participates in.
190 // Collect every distinct refdes the symbol currently has across the
191 // hierarchy so each ${REFDES:FIELD} dependent fan-out reaches the right
192 // dependents. Over-approximation (firing U1:Value when U2 — same symbol
193 // on a different sheet — is the actual edit target) is the acceptable
194 // tradeoff for not yet carrying sheet-path identity in the key itself.
195 std::vector<wxString> refdesList;
196 const SCH_SHEET_LIST& hierarchy = m_schematic.Hierarchy();
197
198 if( hierarchy.empty() )
199 {
200 // No hierarchy yet (e.g., bare SCHEMATIC before sheets added) —
201 // fall back to the current sheet context.
202 const wxString refdes = sym->GetRef( &m_schematic.CurrentSheet(), false );
203
204 if( !refdes.IsEmpty() )
205 refdesList.push_back( refdes );
206 }
207 else
208 {
209 // SCH_SYMBOL::GetRef falls back to its REFERENCE field when the query
210 // path is not one of its instances, so iterating every path and
211 // calling GetRef would pollute the list with the same refdes from
212 // unrelated sheets. Filter to paths whose last screen matches the
213 // symbol's parent screen — those are the ones where this symbol
214 // actually lives.
215 const SCH_SCREEN* parentScreen = dynamic_cast<const SCH_SCREEN*>( sym->GetParent() );
216
217 for( const SCH_SHEET_PATH& path : hierarchy )
218 {
219 if( path.LastScreen() != parentScreen )
220 continue;
221
222 const wxString refdes = sym->GetRef( &path, false );
223
224 if( refdes.IsEmpty() )
225 continue;
226
227 if( std::find( refdesList.begin(), refdesList.end(), refdes ) == refdesList.end() )
228 refdesList.push_back( refdes );
229 }
230 }
231
232 if( refdesList.empty() )
233 return out;
234
235 out.reserve( refdesList.size() * sym->GetFields().size() );
236
237 for( const wxString& refdes : refdesList )
238 {
239 for( const SCH_FIELD& field : sym->GetFields() )
240 {
243 key.primary = refdes;
244 key.secondary = field.GetCanonicalName();
245 out.push_back( key );
246 }
247 }
248
249 return out;
250}
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
EDA_ITEM * GetParent() const
Definition eda_item.h:110
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:89
std::vector< TEXT_VAR_REF_KEY > ExtractSourceKeys(EDA_ITEM *aItem) const
Return the keys aItem could source as a cross-reference target.
void OnSchItemsChanged(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aItems) override
SCHEMATIC_TEXT_VAR_ADAPTER(SCHEMATIC &aSchematic)
void OnSchItemsRemoved(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aItems) override
void RebuildIndex()
Walk every sheet in the hierarchy and register text-bearing items.
void OnSchItemsAdded(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aItems) override
Holds all the data relating to one schematic.
Definition schematic.h:90
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:162
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:115
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...
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:44
Schematic symbol object.
Definition sch_symbol.h:69
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
Identifies a single resolvable source that a text item's ${...} reference depends on.
std::string path
std::vector< TEXT_VAR_REF_KEY > FilterTrackable(const std::vector< TEXT_VAR_REF_KEY > &aRefs)
Filter aRefs down to the subset that should be registered in the index (drops OP and any future non-t...