KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2023 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>
31#include <fp_lib_table.h>
32#include <footprint_info_impl.h>
34#include <string_utils.h>
35#include <board.h>
36#include <footprint.h>
37#include <tool/tool_manager.h>
39#include <wx/settings.h>
40
41
42wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>
44{
45 auto* adapter = new FP_TREE_SYNCHRONIZING_ADAPTER( aFrame, aLibs );
46 return wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>( adapter );
47}
48
49
51 FP_LIB_TABLE* aLibs ) :
52 FP_TREE_MODEL_ADAPTER( aFrame, aLibs ),
53 m_frame( aFrame )
54{
55}
56
57
59{
61}
62
63
64bool FP_TREE_SYNCHRONIZING_ADAPTER::IsContainer( const wxDataViewItem& aItem ) const
65{
66 const LIB_TREE_NODE* node = ToNode( aItem );
67 return node ? node->m_Type == LIB_TREE_NODE::LIBRARY : true;
68}
69
70
71#define PROGRESS_INTERVAL_MILLIS 33 // 30 FPS refresh rate
72
74{
75 m_libs = aLibs;
76
77 // Process already stored libraries
78 for( auto it = m_tree.m_Children.begin(); it != m_tree.m_Children.end(); )
79 {
80 const wxString& name = it->get()->m_Name;
81
82 // Remove the library if it no longer exists or it exists in both the global and the
83 // project library but the project library entry is disabled.
84 if( !m_libs->HasLibrary( name, true )
85 || m_libs->FindRow( name, true ) != m_libs->FindRow( name, false ) )
86 {
87 it = deleteLibrary( it );
88 continue;
89 }
90
91 updateLibrary( *(LIB_TREE_NODE_LIBRARY*) it->get() );
92 ++it;
93 }
94
95 // Look for new libraries
98 size_t count = m_libMap.size();
99
100 for( const wxString& libName : m_libs->GetLogicalLibs() )
101 {
102 if( m_libMap.count( libName ) == 0 )
103 {
104 try
105 {
106 const FP_LIB_TABLE_ROW* library = m_libs->FindRow( libName, true );
107 bool pinned = alg::contains( cfg->m_Session.pinned_fp_libs, libName )
108 || alg::contains( project.m_PinnedFootprintLibs, libName );
109
110 DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ), pinned, true );
111 m_libMap.insert( libName );
112 }
113 catch( ... )
114 {
115 // do nothing if libname is not found. Just skip it
116 }
117 }
118 }
119
120 if( m_libMap.size() > count )
122}
123
124
126{
127 return GFootprintTable.GetCount();
128}
129
130
132{
133 std::vector<LIB_TREE_ITEM*> footprints = getFootprints( aLibNode.m_Name );
134
135 // remove the common part from the footprints list
136 for( auto nodeIt = aLibNode.m_Children.begin(); nodeIt != aLibNode.m_Children.end(); )
137 {
138 // Since the list is sorted we can use a binary search to speed up searches within
139 // libraries with lots of footprints.
140 FOOTPRINT_INFO_IMPL dummy( wxEmptyString, (*nodeIt)->m_Name );
141 auto footprintIt = std::lower_bound( footprints.begin(), footprints.end(), &dummy,
142 []( LIB_TREE_ITEM* a, LIB_TREE_ITEM* b )
143 {
144 return StrNumCmp( a->GetName(), b->GetName(), false ) < 0;
145 } );
146
147 if( footprintIt != footprints.end() && dummy.GetName() == (*footprintIt)->GetName() )
148 {
149 // footprint exists both in the lib tree and the footprint info list; just
150 // update the node data
151 static_cast<LIB_TREE_NODE_ITEM*>( nodeIt->get() )->Update( *footprintIt );
152 footprints.erase( footprintIt );
153 ++nodeIt;
154 }
155 else
156 {
157 // node does not exist in the library manager, remove the corresponding node
158 nodeIt = aLibNode.m_Children.erase( nodeIt );
159 }
160 }
161
162 // now the footprint list contains only new aliases that need to be added to the tree
163 for( LIB_TREE_ITEM* footprint : footprints )
164 aLibNode.AddItem( footprint );
165
166 aLibNode.AssignIntrinsicRanks();
167 m_libMap.insert( aLibNode.m_Name );
168}
169
170
171LIB_TREE_NODE::PTR_VECTOR::iterator
172FP_TREE_SYNCHRONIZING_ADAPTER::deleteLibrary( LIB_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt )
173{
174 LIB_TREE_NODE* node = aLibNodeIt->get();
175 m_libMap.erase( node->m_Name );
176 auto it = m_tree.m_Children.erase( aLibNodeIt );
177 return it;
178}
179
180
182{
183 return FindItem( m_frame->GetLoadedFPID() );
184}
185
186
187void FP_TREE_SYNCHRONIZING_ADAPTER::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
188 unsigned int aCol ) const
189{
190 if( IsFrozen() )
191 {
192 aVariant = wxEmptyString;
193 return;
194 }
195
196 LIB_TREE_NODE* node = ToNode( aItem );
197
198 switch( aCol )
199 {
200 case NAME_COL:
201 {
203 {
204 // Do not use GetLoadedFPID(); it returns m_footprintNameWhenLoaded.
205 node->m_Name =
207
208 // mark modified part with an asterisk
210 aVariant = node->m_Name + wxT( " *" );
211 else
212 aVariant = node->m_Name;
213 }
214 else if( node->m_Pinned )
215 {
216 aVariant = GetPinningSymbol() + node->m_Name;
217 }
218 else
219 {
220 aVariant = node->m_Name;
221 }
222
223 break;
224 }
225
226 case DESC_COL:
227 {
229 {
231 }
232 else if( node->m_Type == LIB_TREE_NODE::LIBRARY )
233 {
234 try
235 {
236 const FP_LIB_TABLE_ROW* lib =
238
239 if( lib )
240 node->m_Desc = lib->GetDescr();
241 }
242 catch( IO_ERROR& )
243 {
244 }
245 }
246
247 wxString descStr = UnescapeString( node->m_Desc );
248 descStr.Replace( wxS( "\n" ), wxS( " " ) ); // Clear line breaks
249
250 aVariant = descStr;
251 break;
252 }
253
254 default: // column == -1 is used for default Compare function
255 aVariant = node->m_Name;
256 break;
257 }
258}
259
260
261bool FP_TREE_SYNCHRONIZING_ADAPTER::GetAttr( wxDataViewItem const& aItem, unsigned int aCol,
262 wxDataViewItemAttr& aAttr ) const
263{
264 if( IsFrozen() )
265 return false;
266
267 // change attributes only for the name field
268 if( aCol != 0 )
269 return false;
270
271 // don't link to a board footprint, even if the FPIDs match
273 return false;
274
275 LIB_TREE_NODE* node = ToNode( aItem );
276 wxCHECK( node, false );
277
278 switch( node->m_Type )
279 {
281 if( node->m_Name == m_frame->GetLoadedFPID().GetLibNickname().wx_str() )
282 {
283 // mark the current library if it's collapsed
284 if( !m_widget->IsExpanded( ToItem( node ) ) )
285 {
286 aAttr.SetStrikethrough( true ); // LIB_TREE_RENDERER uses strikethrough as a
287 // proxy for "is canvas item"
288 }
289
290 // mark modified libs with bold font
292 aAttr.SetBold( true );
293 }
294 break;
295
297 if( node->m_LibId == m_frame->GetLoadedFPID() )
298 {
299 // mark the current (on-canvas) part
300 aAttr.SetStrikethrough( true ); // LIB_TREE_RENDERER uses strikethrough as a
301 // proxy for "is canvas item"
302
303 // mark modified part with bold font
305 aAttr.SetBold( true );
306 }
307 break;
308
309 default:
310 return false;
311 }
312
313 return true;
314}
315
316
317bool FP_TREE_SYNCHRONIZING_ADAPTER::HasPreview( const wxDataViewItem& aItem )
318{
319 LIB_TREE_NODE* node = ToNode( aItem );
320 wxCHECK( node, false );
321
322 return node->m_Type == LIB_TREE_NODE::ITEM && node->m_LibId != m_frame->GetLoadedFPID();
323}
324
325
326void FP_TREE_SYNCHRONIZING_ADAPTER::ShowPreview( wxWindow* aParent, const wxDataViewItem& aItem )
327{
328 static const wxString c_previewName = wxS( "fpHoverPreview" );
329
330 LIB_TREE_NODE* node = ToNode( aItem );
331 wxCHECK( node, /* void */ );
332
333 FOOTPRINT_PREVIEW_PANEL* preview = dynamic_cast<FOOTPRINT_PREVIEW_PANEL*>(
334 wxWindow::FindWindowByName( c_previewName, aParent ) );
335
336 if( !preview )
337 {
338 wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
339 aParent->SetSizer( mainSizer );
340
341 preview = FOOTPRINT_PREVIEW_PANEL::New( &m_frame->Kiway(), aParent, m_frame );
342
343 preview->SetName( c_previewName );
344 preview->GetGAL()->SetAxesEnabled( false );
345
346 mainSizer->Add( preview, 1, wxEXPAND | wxALL, 1 );
347 aParent->Layout();
348 }
349
350 preview->DisplayFootprint( node->m_LibId );
351}
const char * name
Definition: DXF_plotter.cpp:57
bool IsContentModified() const
Definition: base_screen.h:60
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:432
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL instance used in the panel.
Module editor specific tools.
LIB_ID GetLoadedFPID() const
Return the LIB_ID of the part being edited.
Panel that renders a single footprint via Cairo GAL, meant to be exported through Kiface.
virtual bool DisplayFootprint(const LIB_ID &aFPID) override
Set the currently displayed footprint.
static FOOTPRINT_PREVIEW_PANEL * New(KIWAY *aKiway, wxWindow *aParent, UNITS_PROVIDER *aUnitsProvider)
wxString GetLibDescription() const
Definition: footprint.h:243
const LIB_ID & GetFPID() const
Definition: footprint.h:233
Hold a record identifying a library accessed by the appropriate footprint library #PLUGIN object in t...
Definition: fp_lib_table.h:42
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)
virtual bool HasPreview(const wxDataViewItem &aItem) override
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_LIBRARY &aLibNode)
wxDataViewItem GetCurrentDataViewItem() override
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
virtual void ShowPreview(wxWindow *aParent, const wxDataViewItem &aItem) 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:77
void SetAxesEnabled(bool aAxesEnabled)
Enable drawing the axes.
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
Definition: lib_id.h:112
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
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:41
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 wxDataViewItem ToItem(const LIB_TREE_NODE *aNode)
Convert #SYM_TREE_NODE -> wxDataViewItem.
static const wxString GetPinningSymbol()
@ NAME_COL
Library or library item name column.
@ DESC_COL
Library or library description column.
wxDataViewItem FindItem(const LIB_ID &aLibId)
Returns tree item corresponding to part.
Node type: LIB_ID.
Node type: library.
LIB_TREE_NODE_ITEM & 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
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:678
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:70
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:166
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
wxString wx_str() const
Definition: utf8.cpp:45
FP_LIB_TABLE GFootprintTable
The global footprint library table.
Definition: cvpcb.cpp:150
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1059
see class PGM_BASE
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
std::vector< wxString > pinned_fp_libs