KiCad PCB EDA Suite
Loading...
Searching...
No Matches
symbol_import_manager.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 along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21#include <lib_symbol.h>
22
23
27
28
32
33
35{
36 m_symbols.clear();
37 m_parentMap.clear();
38 m_derivativesMap.clear();
39}
40
41
42void SYMBOL_IMPORT_MANAGER::AddSymbol( const wxString& aName, const wxString& aParentName,
43 bool aIsPower, LIB_SYMBOL* aSymbol )
44{
46 info.m_name = aName;
47 info.m_parentName = aParentName;
48 info.m_isPower = aIsPower;
49 info.m_symbol.reset( aSymbol );
50 info.m_existsInDest = false;
51 info.m_checked = false;
52 info.m_autoSelected = false;
53
54 m_symbols[aName] = std::move( info );
55}
56
57
59{
60 for( auto& [name, info] : m_symbols )
61 {
62 info.m_existsInDest = aExistsFunc( name );
63 }
64}
65
66
68{
69 m_parentMap.clear();
70 m_derivativesMap.clear();
71
72 for( const auto& [name, info] : m_symbols )
73 {
74 if( !info.m_parentName.IsEmpty() )
75 {
76 m_parentMap[name] = info.m_parentName;
77 m_derivativesMap[info.m_parentName].push_back( name );
78 }
79 }
80}
81
82
83std::vector<wxString> SYMBOL_IMPORT_MANAGER::GetSymbolNames() const
84{
85 std::vector<wxString> names;
86 names.reserve( m_symbols.size() );
87
88 for( const auto& [name, info] : m_symbols )
89 names.push_back( name );
90
91 return names;
92}
93
94
96{
97 auto it = m_symbols.find( aName );
98 return ( it != m_symbols.end() ) ? &it->second : nullptr;
99}
100
101
102const SYMBOL_IMPORT_INFO* SYMBOL_IMPORT_MANAGER::GetSymbolInfo( const wxString& aName ) const
103{
104 auto it = m_symbols.find( aName );
105 return ( it != m_symbols.end() ) ? &it->second : nullptr;
106}
107
108
109std::set<wxString> SYMBOL_IMPORT_MANAGER::GetAncestors( const wxString& aSymbolName ) const
110{
111 std::set<wxString> ancestors;
112 wxString current = aSymbolName;
113
114 while( true )
115 {
116 auto it = m_parentMap.find( current );
117
118 if( it == m_parentMap.end() || it->second.IsEmpty() )
119 break;
120
121 wxString parent = it->second;
122
123 if( m_symbols.find( parent ) == m_symbols.end() )
124 break;
125
126 ancestors.insert( parent );
127 current = parent;
128 }
129
130 return ancestors;
131}
132
133
134std::set<wxString> SYMBOL_IMPORT_MANAGER::GetDescendants( const wxString& aSymbolName ) const
135{
136 std::set<wxString> descendants;
137 std::vector<wxString> toProcess = { aSymbolName };
138
139 while( !toProcess.empty() )
140 {
141 wxString current = toProcess.back();
142 toProcess.pop_back();
143
144 auto it = m_derivativesMap.find( current );
145
146 if( it != m_derivativesMap.end() )
147 {
148 for( const wxString& child : it->second )
149 {
150 if( descendants.find( child ) == descendants.end() )
151 {
152 descendants.insert( child );
153 toProcess.push_back( child );
154 }
155 }
156 }
157 }
158
159 return descendants;
160}
161
162
163wxString SYMBOL_IMPORT_MANAGER::GetParent( const wxString& aSymbolName ) const
164{
165 auto it = m_parentMap.find( aSymbolName );
166 return ( it != m_parentMap.end() ) ? it->second : wxString();
167}
168
169
170std::vector<wxString> SYMBOL_IMPORT_MANAGER::GetDirectDerivatives( const wxString& aSymbolName ) const
171{
172 auto it = m_derivativesMap.find( aSymbolName );
173
174 if( it != m_derivativesMap.end() )
175 return it->second;
176
177 return {};
178}
179
180
181bool SYMBOL_IMPORT_MANAGER::IsDerived( const wxString& aSymbolName ) const
182{
183 auto it = m_parentMap.find( aSymbolName );
184 return it != m_parentMap.end() && !it->second.IsEmpty();
185}
186
187
188std::vector<wxString> SYMBOL_IMPORT_MANAGER::SetSymbolSelected( const wxString& aSymbolName,
189 bool aSelected )
190{
191 std::vector<wxString> changedSymbols;
192
193 SYMBOL_IMPORT_INFO* info = GetSymbolInfo( aSymbolName );
194
195 if( !info )
196 return changedSymbols;
197
198 if( aSelected )
199 {
200 info->m_checked = true;
201 info->m_autoSelected = false;
202
203 // Auto-select all ancestors
204 std::set<wxString> ancestors = GetAncestors( aSymbolName );
205
206 for( const wxString& ancestor : ancestors )
207 {
208 SYMBOL_IMPORT_INFO* ancestorInfo = GetSymbolInfo( ancestor );
209
210 if( ancestorInfo && !ancestorInfo->m_checked && !ancestorInfo->m_autoSelected )
211 {
212 ancestorInfo->m_autoSelected = true;
213 changedSymbols.push_back( ancestor );
214 }
215 }
216 }
217 else
218 {
219 info->m_checked = false;
220 info->m_autoSelected = false;
221
223
224 for( const auto& [name, symInfo] : m_symbols )
225 {
226 if( name != aSymbolName )
227 changedSymbols.push_back( name );
228 }
229 }
230
231 return changedSymbols;
232}
233
234
235std::vector<wxString> SYMBOL_IMPORT_MANAGER::GetSelectedDescendants( const wxString& aSymbolName ) const
236{
237 std::vector<wxString> selectedDescendants;
238 std::set<wxString> descendants = GetDescendants( aSymbolName );
239
240 for( const wxString& desc : descendants )
241 {
242 const SYMBOL_IMPORT_INFO* info = GetSymbolInfo( desc );
243
244 if( info && info->m_checked )
245 selectedDescendants.push_back( desc );
246 }
247
248 return selectedDescendants;
249}
250
251
252void SYMBOL_IMPORT_MANAGER::DeselectWithDescendants( const wxString& aSymbolName )
253{
254 SYMBOL_IMPORT_INFO* info = GetSymbolInfo( aSymbolName );
255
256 if( info )
257 {
258 info->m_checked = false;
259 info->m_autoSelected = false;
260 }
261
262 std::set<wxString> descendants = GetDescendants( aSymbolName );
263
264 for( const wxString& desc : descendants )
265 {
266 SYMBOL_IMPORT_INFO* descInfo = GetSymbolInfo( desc );
267
268 if( descInfo )
269 {
270 descInfo->m_checked = false;
271 descInfo->m_autoSelected = false;
272 }
273 }
274
276}
277
278
279void SYMBOL_IMPORT_MANAGER::SelectAll( std::function<bool( const wxString& )> aFilter )
280{
281 for( auto& [name, info] : m_symbols )
282 {
283 if( !aFilter || aFilter( name ) )
284 {
285 info.m_checked = true;
286 info.m_autoSelected = false;
287 }
288 }
289
291}
292
293
294void SYMBOL_IMPORT_MANAGER::DeselectAll( std::function<bool( const wxString& )> aFilter )
295{
296 for( auto& [name, info] : m_symbols )
297 {
298 if( !aFilter || aFilter( name ) )
299 {
300 info.m_checked = false;
301 info.m_autoSelected = false;
302 }
303 }
304
306}
307
308
309std::vector<wxString> SYMBOL_IMPORT_MANAGER::GetSymbolsToImport() const
310{
311 std::vector<wxString> result;
312
313 for( const auto& [name, info] : m_symbols )
314 {
315 if( info.m_checked || info.m_autoSelected )
316 result.push_back( name );
317 }
318
319 return result;
320}
321
322
324{
325 int count = 0;
326
327 for( const auto& [name, info] : m_symbols )
328 {
329 if( info.m_checked )
330 count++;
331 }
332
333 return count;
334}
335
336
338{
339 int count = 0;
340
341 for( const auto& [name, info] : m_symbols )
342 {
343 if( info.m_autoSelected && !info.m_checked )
344 count++;
345 }
346
347 return count;
348}
349
350
351std::vector<wxString> SYMBOL_IMPORT_MANAGER::GetConflicts() const
352{
353 std::vector<wxString> conflicts;
354
355 for( const auto& [name, info] : m_symbols )
356 {
357 if( ( info.m_checked || info.m_autoSelected ) && info.m_existsInDest )
358 conflicts.push_back( name );
359 }
360
361 return conflicts;
362}
363
364
365bool SYMBOL_IMPORT_MANAGER::MatchesFilter( const wxString& aSymbolName, const wxString& aFilter )
366{
367 if( aFilter.IsEmpty() )
368 return true;
369
370 return aSymbolName.Lower().Contains( aFilter.Lower() );
371}
372
373
375{
376 // Clear all auto-selections
377 for( auto& [name, info] : m_symbols )
378 info.m_autoSelected = false;
379
380 // Re-apply auto-selections for all checked symbols
381 for( const auto& [name, info] : m_symbols )
382 {
383 if( info.m_checked )
384 {
385 std::set<wxString> ancestors = GetAncestors( name );
386
387 for( const wxString& ancestor : ancestors )
388 {
389 SYMBOL_IMPORT_INFO* ancestorInfo = GetSymbolInfo( ancestor );
390
391 if( ancestorInfo && !ancestorInfo->m_checked )
392 ancestorInfo->m_autoSelected = true;
393 }
394 }
395 }
396}
const char * name
Define a library symbol object.
Definition lib_symbol.h:83
std::function< bool(const wxString &symbolName)> SYMBOL_EXISTS_FUNC
Callback type for checking if a symbol exists in the destination library.
void DeselectWithDescendants(const wxString &aSymbolName)
Force deselection of a symbol and all its descendants.
std::vector< wxString > GetConflicts() const
Get list of symbols that will conflict (selected and exist in destination).
void CheckExistingSymbols(SYMBOL_EXISTS_FUNC aExistsFunc)
Mark symbols that exist in the destination library.
std::map< wxString, wxString > m_parentMap
Map from symbol name to its parent name (for derived symbols)
void SelectAll(std::function< bool(const wxString &)> aFilter=nullptr)
Select all symbols (optionally filtered).
std::vector< wxString > GetDirectDerivatives(const wxString &aSymbolName) const
Get direct children (derivatives) of a symbol.
wxString GetParent(const wxString &aSymbolName) const
Get the direct parent of a symbol.
int GetManualSelectionCount() const
Get count of manually selected symbols.
std::map< wxString, SYMBOL_IMPORT_INFO > m_symbols
All symbols available for import, keyed by name.
void DeselectAll(std::function< bool(const wxString &)> aFilter=nullptr)
Deselect all symbols (optionally filtered).
void AddSymbol(const wxString &aName, const wxString &aParentName, bool aIsPower, LIB_SYMBOL *aSymbol=nullptr)
Add a symbol to the import list.
std::vector< wxString > GetSelectedDescendants(const wxString &aSymbolName) const
Get selected descendants that would be orphaned if a symbol is deselected.
std::vector< wxString > SetSymbolSelected(const wxString &aSymbolName, bool aSelected)
Set the selection state of a symbol.
std::vector< wxString > GetSymbolNames() const
Get all symbol names.
static bool MatchesFilter(const wxString &aSymbolName, const wxString &aFilter)
Check if a symbol name matches a filter string (case-insensitive contains).
int GetAutoSelectionCount() const
Get count of auto-selected symbols (dependencies).
void Clear()
Clear all loaded symbols and reset state.
void recalculateAutoSelections()
Recalculate auto-selection state for all symbols based on current manual selections.
SYMBOL_IMPORT_INFO * GetSymbolInfo(const wxString &aName)
Get symbol info by name.
std::map< wxString, std::vector< wxString > > m_derivativesMap
Map from parent name to list of direct derivative names.
bool IsDerived(const wxString &aSymbolName) const
Check if a symbol is derived from another.
std::set< wxString > GetAncestors(const wxString &aSymbolName) const
Get all ancestors of a symbol (full inheritance chain).
std::set< wxString > GetDescendants(const wxString &aSymbolName) const
Get all descendants of a symbol (all derived symbols recursively).
std::vector< wxString > GetSymbolsToImport() const
Get list of all symbols that will be imported (checked + auto-selected).
void BuildDependencyMaps()
Build the dependency maps from parent relationships.
Information about a symbol available for import.
bool m_checked
User's manual selection state.
bool m_autoSelected
True if auto-selected as dependency.
wxString result
Test unit parsing edge cases and error handling.