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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 */
20
22
23#include <algorithm>
24#include <eda_text.h>
25#include <sch_field.h>
26#include <sch_item.h>
27#include <sch_screen.h>
28#include <sch_sheet.h>
29#include <sch_sheet_path.h>
30#include <sch_symbol.h>
31
32
34 m_schematic( aSchematic )
35{
36 m_tracker.SetSourceKeyExtractor(
37 [this]( EDA_ITEM* aItem ) -> std::vector<TEXT_VAR_REF_KEY>
38 { return ExtractSourceKeys( aItem ); } );
39}
40
41
43{
44 if( !aItem )
45 return;
46
47 // SCH_SYMBOL: register its constituent SCH_FIELDs (not the symbol itself).
48 // The symbol is a cross-ref source, not a dependent.
49 if( SCH_SYMBOL* sym = dynamic_cast<SCH_SYMBOL*>( aItem ) )
50 {
51 for( SCH_FIELD& field : sym->GetFields() )
52 registerItem( &field );
53
54 return;
55 }
56
57 // SCH_SHEET: its fields (sheet name, file name) can carry text vars.
58 // Sheet pins are separate sch items and flow through the listener on
59 // their own when added/removed.
60 if( SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( aItem ) )
61 {
62 for( SCH_FIELD& field : sheet->GetFields() )
63 registerItem( &field );
64
65 return;
66 }
67
68 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem );
69
70 if( !text )
71 return;
72
73 m_tracker.RegisterItem( aItem, FilterTrackable( text->GetTextVarReferences() ) );
74}
75
76
78{
79 if( !aItem )
80 return;
81
82 m_tracker.UnregisterItem( aItem );
83
84 if( SCH_SYMBOL* sym = dynamic_cast<SCH_SYMBOL*>( aItem ) )
85 {
86 for( SCH_FIELD& field : sym->GetFields() )
87 m_tracker.UnregisterItem( &field );
88 }
89 else if( SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( aItem ) )
90 {
91 for( SCH_FIELD& field : sheet->GetFields() )
92 m_tracker.UnregisterItem( &field );
93 }
94}
95
96
98{
99 if( !aItem )
100 return;
101
102 // A SCH_SYMBOL change covers both "its fields were edited" (re-register
103 // each field) and "this symbol's values source cross-refs" (fan out
104 // ${REFDES:FIELD} keys).
105 if( SCH_SYMBOL* sym = dynamic_cast<SCH_SYMBOL*>( aItem ) )
106 {
107 for( SCH_FIELD& field : sym->GetFields() )
108 {
109 std::vector<TEXT_VAR_REF_KEY> refs = FilterTrackable( field.GetTextVarReferences() );
110 m_tracker.RegisterItem( &field, refs );
111 }
112
113 m_tracker.HandleItemChanged( aItem, {} );
114 return;
115 }
116
117 if( SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( aItem ) )
118 {
119 for( SCH_FIELD& field : sheet->GetFields() )
120 {
121 std::vector<TEXT_VAR_REF_KEY> refs = FilterTrackable( field.GetTextVarReferences() );
122 m_tracker.RegisterItem( &field, refs );
123 }
124
125 return;
126 }
127
128 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem ) )
129 {
130 std::vector<TEXT_VAR_REF_KEY> updated = FilterTrackable( text->GetTextVarReferences() );
131 m_tracker.HandleItemChanged( aItem, updated );
132 }
133}
134
135
137 std::vector<SCH_ITEM*>& aItems )
138{
139 for( SCH_ITEM* item : aItems )
140 registerItem( item );
141}
142
143
145 std::vector<SCH_ITEM*>& aItems )
146{
147 for( SCH_ITEM* item : aItems )
148 unregisterItem( item );
149}
150
151
153 std::vector<SCH_ITEM*>& aItems )
154{
155 for( SCH_ITEM* item : aItems )
156 handleItemChanged( item );
157}
158
159
161{
162 m_tracker.Clear();
163
164 // Walk the hierarchy. Each screen can be referenced by multiple sheet
165 // paths, but the SCH_ITEM pointers are shared — we only register each
166 // item once via the screen traversal.
167 for( const SCH_SHEET_PATH& path : m_schematic.Hierarchy() )
168 {
169 SCH_SCREEN* screen = path.LastScreen();
170
171 if( !screen )
172 continue;
173
174 for( SCH_ITEM* item : screen->Items() )
175 registerItem( item );
176 }
177}
178
179
180std::vector<TEXT_VAR_REF_KEY> SCHEMATIC_TEXT_VAR_ADAPTER::ExtractSourceKeys( EDA_ITEM* aItem ) const
181{
182 std::vector<TEXT_VAR_REF_KEY> out;
183
184 SCH_SYMBOL* sym = dynamic_cast<SCH_SYMBOL*>( aItem );
185
186 if( !sym )
187 return out;
188
189 // Repeated-sheet instances: a single SCH_SYMBOL can carry different
190 // reference designators on each SCH_SHEET_PATH it participates in.
191 // Collect every distinct refdes the symbol currently has across the
192 // hierarchy so each ${REFDES:FIELD} dependent fan-out reaches the right
193 // dependents. Over-approximation (firing U1:Value when U2 — same symbol
194 // on a different sheet — is the actual edit target) is the acceptable
195 // tradeoff for not yet carrying sheet-path identity in the key itself.
196 std::vector<wxString> refdesList;
197 const SCH_SHEET_LIST& hierarchy = m_schematic.Hierarchy();
198
199 if( hierarchy.empty() )
200 {
201 // No hierarchy yet (e.g., bare SCHEMATIC before sheets added) —
202 // fall back to the current sheet context.
203 const wxString refdes = sym->GetRef( &m_schematic.CurrentSheet(), false );
204
205 if( !refdes.IsEmpty() )
206 refdesList.push_back( refdes );
207 }
208 else
209 {
210 // SCH_SYMBOL::GetRef falls back to its REFERENCE field when the query
211 // path is not one of its instances, so iterating every path and
212 // calling GetRef would pollute the list with the same refdes from
213 // unrelated sheets. Filter to paths whose last screen matches the
214 // symbol's parent screen — those are the ones where this symbol
215 // actually lives.
216 const SCH_SCREEN* parentScreen = dynamic_cast<const SCH_SCREEN*>( sym->GetParent() );
217
218 for( const SCH_SHEET_PATH& path : hierarchy )
219 {
220 if( path.LastScreen() != parentScreen )
221 continue;
222
223 const wxString refdes = sym->GetRef( &path, false );
224
225 if( refdes.IsEmpty() )
226 continue;
227
228 if( std::find( refdesList.begin(), refdesList.end(), refdes ) == refdesList.end() )
229 refdesList.push_back( refdes );
230 }
231 }
232
233 if( refdesList.empty() )
234 return out;
235
236 out.reserve( refdesList.size() * sym->GetFields().size() );
237
238 for( const wxString& refdes : refdesList )
239 {
240 for( const SCH_FIELD& field : sym->GetFields() )
241 {
244 key.primary = refdes;
245 key.secondary = field.GetCanonicalName();
246 out.push_back( key );
247 }
248 }
249
250 return out;
251}
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:100
EDA_ITEM * GetParent() const
Definition eda_item.h:114
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:93
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:89
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:168
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:119
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:48
Schematic symbol object.
Definition sch_symbol.h:76
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...