KiCad PCB EDA Suite
fp_tree_synchronizing_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 (C) 2017 CERN
5 * Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Maciej Suminski <[email protected]>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 3
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * https://www.gnu.org/licenses/gpl-3.0.html
21 * or you may search the http://www.gnu.org website for the version 3 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <pgm_base.h>
30#include <fp_lib_table.h>
31#include <footprint_info_impl.h>
32#include <string_utils.h>
33#include <board.h>
34#include <footprint.h>
35#include <tool/tool_manager.h>
37#include <wx/settings.h>
38
39
40wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>
42{
43 auto* adapter = new FP_TREE_SYNCHRONIZING_ADAPTER( aFrame, aLibs );
44 return wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>( adapter );
45}
46
47
49 FP_LIB_TABLE* aLibs ) :
50 FP_TREE_MODEL_ADAPTER( aFrame, aLibs ),
51 m_frame( aFrame )
52{
53}
54
55
57{
59}
60
61
62bool FP_TREE_SYNCHRONIZING_ADAPTER::IsContainer( const wxDataViewItem& aItem ) const
63{
64 const LIB_TREE_NODE* node = ToNode( aItem );
65 return node ? node->m_Type == LIB_TREE_NODE::LIB : true;
66}
67
68
69#define PROGRESS_INTERVAL_MILLIS 33 // 30 FPS refresh rate
70
72{
73 // Process already stored libraries
74 for( auto it = m_tree.m_Children.begin(); it != m_tree.m_Children.end(); )
75 {
76 const wxString& name = it->get()->m_Name;
77
78 // Remove the library if it no longer exists or it exists in both the global and the
79 // project library but the project library entry is disabled.
80 if( !m_libs->HasLibrary( name, true )
81 || m_libs->FindRow( name, true ) != m_libs->FindRow( name, false ) )
82 {
83 it = deleteLibrary( it );
84 continue;
85 }
86
87 updateLibrary( *(LIB_TREE_NODE_LIB*) it->get() );
88 ++it;
89 }
90
91 // Look for new libraries
92 COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
94 size_t count = m_libMap.size();
95
96 for( const wxString& libName : m_libs->GetLogicalLibs() )
97 {
98 if( m_libMap.count( libName ) == 0 )
99 {
100 const FP_LIB_TABLE_ROW* library = m_libs->FindRow( libName, true );
101 bool pinned = alg::contains( cfg->m_Session.pinned_fp_libs, libName )
102 || alg::contains( project.m_PinnedFootprintLibs, libName );
103
104 DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ), pinned, true );
105 m_libMap.insert( libName );
106 }
107 }
108
109 if( m_libMap.size() > count )
111}
112
113
115{
116 return GFootprintTable.GetCount();
117}
118
119
121{
122 std::vector<LIB_TREE_ITEM*> footprints = getFootprints( aLibNode.m_Name );
123
124 // remove the common part from the footprints list
125 for( auto nodeIt = aLibNode.m_Children.begin(); nodeIt != aLibNode.m_Children.end(); )
126 {
127 // Since the list is sorted we can use a binary search to speed up searches within
128 // libraries with lots of footprints.
129 FOOTPRINT_INFO_IMPL dummy( wxEmptyString, (*nodeIt)->m_Name );
130 auto footprintIt = std::lower_bound( footprints.begin(), footprints.end(), &dummy,
131 []( LIB_TREE_ITEM* a, LIB_TREE_ITEM* b )
132 {
133 return StrNumCmp( a->GetName(), b->GetName(), false ) < 0;
134 } );
135
136 if( footprintIt != footprints.end() && dummy.GetName() == (*footprintIt)->GetName() )
137 {
138 // footprint exists both in the lib tree and the footprint info list; just
139 // update the node data
140 static_cast<LIB_TREE_NODE_LIB_ID*>( nodeIt->get() )->Update( *footprintIt );
141 footprints.erase( footprintIt );
142 ++nodeIt;
143 }
144 else
145 {
146 // node does not exist in the library manager, remove the corresponding node
147 nodeIt = aLibNode.m_Children.erase( nodeIt );
148 }
149 }
150
151 // now the footprint list contains only new aliases that need to be added to the tree
152 for( LIB_TREE_ITEM* footprint : footprints )
153 aLibNode.AddItem( footprint );
154
155 aLibNode.AssignIntrinsicRanks();
156 m_libMap.insert( aLibNode.m_Name );
157}
158
159
160LIB_TREE_NODE::PTR_VECTOR::iterator
161FP_TREE_SYNCHRONIZING_ADAPTER::deleteLibrary( LIB_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt )
162{
163 LIB_TREE_NODE* node = aLibNodeIt->get();
164 m_libMap.erase( node->m_Name );
165 auto it = m_tree.m_Children.erase( aLibNodeIt );
166 return it;
167}
168
169
170void FP_TREE_SYNCHRONIZING_ADAPTER::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
171 unsigned int aCol ) const
172{
173 if( IsFrozen() )
174 {
175 aVariant = wxEmptyString;
176 return;
177 }
178
179 LIB_TREE_NODE* node = ToNode( aItem );
180
181 switch( aCol )
182 {
183 case NAME_COL:
185 {
186 // Do not use GetLoadedFPID(); it returns m_footprintNameWhenLoaded.
188
189 // mark modified part with an asterisk
191 aVariant = node->m_Name + wxT( " *" );
192 else
193 aVariant = node->m_Name;
194 }
195 else if( node->m_Pinned )
196 {
197 aVariant = GetPinningSymbol() + node->m_Name;
198 }
199 else
200 {
201 aVariant = node->m_Name;
202 }
203
204 break;
205
206 case DESC_COL:
208 {
210 }
211 else if( node->m_Type == LIB_TREE_NODE::LIB )
212 {
213 try
214 {
215 const FP_LIB_TABLE_ROW* lib =
217
218 if( lib )
219 node->m_Desc = lib->GetDescr();
220 }
221 catch( IO_ERROR& )
222 {
223 }
224 }
225
226 aVariant = node->m_Desc;
227 break;
228
229 default: // column == -1 is used for default Compare function
230 aVariant = node->m_Name;
231 break;
232 }
233}
234
235
236bool FP_TREE_SYNCHRONIZING_ADAPTER::GetAttr( wxDataViewItem const& aItem, unsigned int aCol,
237 wxDataViewItemAttr& aAttr ) const
238{
239 if( IsFrozen() )
240 return false;
241
242 // change attributes only for the name field
243 if( aCol != 0 )
244 return false;
245
246 // don't link to a board footprint, even if the FPIDs match
248 return false;
249
250 LIB_TREE_NODE* node = ToNode( aItem );
251 wxCHECK( node, false );
252
253 switch( node->m_Type )
254 {
256 if( node->m_Name == m_frame->GetLoadedFPID().GetLibNickname() )
257 {
258#ifdef __WXGTK__
259 // The native wxGTK+ impl ignores background colour, so set the text colour
260 // instead. Works reasonably well in dark themes, less well in light ones....
261 aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
262#else
263 aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
264 aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT ) );
265#endif
266
267 // mark modified libs with bold font
269 aAttr.SetBold( true );
270 }
271 break;
272
274 if( node->m_LibId == m_frame->GetLoadedFPID() )
275 {
276#ifdef __WXGTK__
277 // The native wxGTK+ impl ignores background colour, so set the text colour
278 // instead. Works reasonably well in dark themes, less well in light ones....
279 aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
280#else
281 aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
282 aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT ) );
283#endif
284
285 // mark modified part with bold font
287 aAttr.SetBold( true );
288 }
289 break;
290
291 default:
292 return false;
293 }
294
295 return true;
296}
297
298
const char * name
Definition: DXF_plotter.cpp:56
bool IsContentModified() const
Definition: base_screen.h:60
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:397
Module editor specific tools.
LIB_ID GetLoadedFPID() const
Return the LIB_ID of the part being edited.
wxString GetDescription() const
Definition: footprint.h:218
const LIB_ID & GetFPID() const
Definition: footprint.h:212
Hold a record identifying a library accessed by the appropriate footprint library PLUGIN object in th...
Definition: fp_lib_table.h:41
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an FP_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back table frag...
std::vector< LIB_TREE_ITEM * > getFootprints(const wxString &aLibName)
FP_TREE_SYNCHRONIZING_ADAPTER(FOOTPRINT_EDIT_FRAME *aFrame, FP_LIB_TABLE *aLibs)
bool GetAttr(wxDataViewItem const &aItem, unsigned int aCol, wxDataViewItemAttr &aAttr) const override
void updateLibrary(LIB_TREE_NODE_LIB &aLibNode)
int GetLibrariesCount() const override
Return the number of libraries loaded in the tree.
bool IsContainer(const wxDataViewItem &aItem) const override
static wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > Create(FOOTPRINT_EDIT_FRAME *aFrame, FP_LIB_TABLE *aLibs)
LIB_TREE_NODE::PTR_VECTOR::iterator deleteLibrary(LIB_TREE_NODE::PTR_VECTOR::iterator &aLibNodeIt)
TOOL_INTERACTIVE * GetContextMenuTool() override
void GetValue(wxVariant &aVariant, wxDataViewItem const &aItem, unsigned int aCol) const override
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:76
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
const UTF8 & GetLibItemName() const
Definition: lib_id.h:101
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
wxString GetName() const override
Definition: lib_symbol.h:136
const wxString & GetDescr() const
Return the description of the library referenced by this row.
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
unsigned GetCount() const
Get the number of rows contained in the table.
A mix-in to provide polymorphism between items stored in libraries (symbols, aliases and footprints).
Definition: lib_tree_item.h:40
static LIB_TREE_NODE * ToNode(wxDataViewItem aItem)
Convert wxDataViewItem -> #SYM_TREE_NODE.
void DoAddLibrary(const wxString &aNodeName, const wxString &aDesc, const std::vector< LIB_TREE_ITEM * > &aItemList, bool pinned, bool presorted)
Add the given list of symbols by alias.
static const wxString GetPinningSymbol()
@ NAME_COL
Library or library item name column.
@ DESC_COL
Library or library description column.
Node type: LIB_ID.
Node type: library.
LIB_TREE_NODE_LIB_ID & AddItem(LIB_TREE_ITEM *aItem)
Construct a new alias node, add it to this library, and return it.
Model class in the component selector Model-View-Adapter (mediated MVC) architecture.
enum TYPE m_Type
PTR_VECTOR m_Children
void AssignIntrinsicRanks(bool presorted=false)
Store intrinsic ranks on all children of this node.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:65
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:148
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
FP_LIB_TABLE GFootprintTable
The global footprint library table.
Definition: cvpcb.cpp:134
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:99
see class PGM_BASE
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:74
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
std::vector< wxString > pinned_fp_libs