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 The 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::TYPE::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 try
83 {
84 // Remove the library if it no longer exists or it exists in both the global and the
85 // project library but the project library entry is disabled.
86 if( !m_libs->HasLibrary( name, true )
87 || m_libs->FindRow( name, true ) != m_libs->FindRow( name, false ) )
88 {
89 it = deleteLibrary( it );
90 continue;
91 }
92
93 updateLibrary( *(LIB_TREE_NODE_LIBRARY*) it->get() );
94 }
95 catch( ... )
96 {
97 // If the library isn't found, remove it
98 it = deleteLibrary( it );
99 continue;
100 }
101
102 ++it;
103 }
104
105 // Look for new libraries
108 size_t count = m_libMap.size();
109
110 for( const wxString& libName : m_libs->GetLogicalLibs() )
111 {
112 if( m_libMap.count( libName ) == 0 )
113 {
114 try
115 {
116 const FP_LIB_TABLE_ROW* library = m_libs->FindRow( libName, true );
117 bool pinned = alg::contains( cfg->m_Session.pinned_fp_libs, libName )
118 || alg::contains( project.m_PinnedFootprintLibs, libName );
119
120 DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ), pinned, true );
121 m_libMap.insert( libName );
122 }
123 catch( ... )
124 {
125 // do nothing if libname is not found. Just skip it
126 }
127 }
128 }
129
130 if( m_libMap.size() > count )
132}
133
134
136{
137 return GFootprintTable.GetCount();
138}
139
140
142{
143 std::vector<LIB_TREE_ITEM*> footprints = getFootprints( aLibNode.m_Name );
144
145 // remove the common part from the footprints list
146 for( auto nodeIt = aLibNode.m_Children.begin(); nodeIt != aLibNode.m_Children.end(); )
147 {
148 // Since the list is sorted we can use a binary search to speed up searches within
149 // libraries with lots of footprints.
150 FOOTPRINT_INFO_IMPL dummy( wxEmptyString, (*nodeIt)->m_Name );
151 auto footprintIt = std::lower_bound( footprints.begin(), footprints.end(), &dummy,
152 []( LIB_TREE_ITEM* a, LIB_TREE_ITEM* b )
153 {
154 return StrNumCmp( a->GetName(), b->GetName(), false ) < 0;
155 } );
156
157 if( footprintIt != footprints.end() && dummy.GetName() == (*footprintIt)->GetName() )
158 {
159 // footprint exists both in the lib tree and the footprint info list; just
160 // update the node data
161 static_cast<LIB_TREE_NODE_ITEM*>( nodeIt->get() )->Update( *footprintIt );
162 footprints.erase( footprintIt );
163 ++nodeIt;
164 }
165 else
166 {
167 // node does not exist in the library manager, remove the corresponding node
168 nodeIt = aLibNode.m_Children.erase( nodeIt );
169 }
170 }
171
172 // now the footprint list contains only new aliases that need to be added to the tree
173 for( LIB_TREE_ITEM* footprint : footprints )
174 aLibNode.AddItem( footprint );
175
176 aLibNode.AssignIntrinsicRanks();
177 m_libMap.insert( aLibNode.m_Name );
178}
179
180
181LIB_TREE_NODE::PTR_VECTOR::iterator
182FP_TREE_SYNCHRONIZING_ADAPTER::deleteLibrary( LIB_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt )
183{
184 LIB_TREE_NODE* node = aLibNodeIt->get();
185 m_libMap.erase( node->m_Name );
186 auto it = m_tree.m_Children.erase( aLibNodeIt );
187 return it;
188}
189
190
192{
193 return FindItem( m_frame->GetLoadedFPID() );
194}
195
196
197void FP_TREE_SYNCHRONIZING_ADAPTER::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
198 unsigned int aCol ) const
199{
200 if( IsFrozen() )
201 {
202 aVariant = wxEmptyString;
203 return;
204 }
205
206 LIB_TREE_NODE* node = ToNode( aItem );
207
208 switch( aCol )
209 {
210 case NAME_COL:
211 {
213 {
214 // Do not use GetLoadedFPID(); it returns m_footprintNameWhenLoaded.
215 node->m_Name =
217
218 // mark modified part with an asterisk
220 aVariant = node->m_Name + wxT( " *" );
221 else
222 aVariant = node->m_Name;
223 }
224 else if( node->m_Pinned )
225 {
226 aVariant = GetPinningSymbol() + node->m_Name;
227 }
228 else
229 {
230 aVariant = node->m_Name;
231 }
232
233 break;
234 }
235
236 case DESC_COL:
237 {
239 {
241 }
242 else if( node->m_Type == LIB_TREE_NODE::TYPE::LIBRARY )
243 {
244 try
245 {
246 const FP_LIB_TABLE_ROW* lib =
248
249 if( lib )
250 node->m_Desc = lib->GetDescr();
251 }
252 catch( IO_ERROR& )
253 {
254 }
255 }
256
257 wxString descStr = UnescapeString( node->m_Desc );
258 descStr.Replace( wxS( "\n" ), wxS( " " ) ); // Clear line breaks
259
260 aVariant = descStr;
261 break;
262 }
263
264 default: // column == -1 is used for default Compare function
265 aVariant = node->m_Name;
266 break;
267 }
268}
269
270
271bool FP_TREE_SYNCHRONIZING_ADAPTER::GetAttr( wxDataViewItem const& aItem, unsigned int aCol,
272 wxDataViewItemAttr& aAttr ) const
273{
274 if( IsFrozen() )
275 return false;
276
277 // change attributes only for the name field
278 if( aCol != 0 )
279 return false;
280
281 // don't link to a board footprint, even if the FPIDs match
283 return false;
284
285 LIB_TREE_NODE* node = ToNode( aItem );
286 wxCHECK( node, false );
287
288 switch( node->m_Type )
289 {
290 case LIB_TREE_NODE::TYPE::LIBRARY:
291 if( node->m_Name == m_frame->GetLoadedFPID().GetLibNickname().wx_str() )
292 {
293 // mark the current library if it's collapsed
294 if( !m_widget->IsExpanded( ToItem( node ) ) )
295 {
296 aAttr.SetStrikethrough( true ); // LIB_TREE_RENDERER uses strikethrough as a
297 // proxy for "is canvas item"
298 }
299
300 // mark modified libs with bold font
302 aAttr.SetBold( true );
303 }
304 break;
305
306 case LIB_TREE_NODE::TYPE::ITEM:
307 if( node->m_LibId == m_frame->GetLoadedFPID() )
308 {
309 // mark the current (on-canvas) part
310 aAttr.SetStrikethrough( true ); // LIB_TREE_RENDERER uses strikethrough as a
311 // proxy for "is canvas item"
312
313 // mark modified part with bold font
315 aAttr.SetBold( true );
316 }
317 break;
318
319 default:
320 return false;
321 }
322
323 return true;
324}
325
326
327bool FP_TREE_SYNCHRONIZING_ADAPTER::HasPreview( const wxDataViewItem& aItem )
328{
329 LIB_TREE_NODE* node = ToNode( aItem );
330 wxCHECK( node, false );
331
332 return node->m_Type == LIB_TREE_NODE::TYPE::ITEM && node->m_LibId != m_frame->GetLoadedFPID();
333}
334
335
336void FP_TREE_SYNCHRONIZING_ADAPTER::ShowPreview( wxWindow* aParent, const wxDataViewItem& aItem )
337{
338 static const wxString c_previewName = wxS( "fpHoverPreview" );
339
340 LIB_TREE_NODE* node = ToNode( aItem );
341 wxCHECK( node, /* void */ );
342
343 wxWindow* previewWindow = wxWindow::FindWindowByName( c_previewName, aParent );
344 FOOTPRINT_PREVIEW_PANEL* preview = dynamic_cast<FOOTPRINT_PREVIEW_PANEL*>( previewWindow );
345
346 if( !preview )
347 {
348 wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
349 aParent->SetSizer( mainSizer );
350
351 preview = FOOTPRINT_PREVIEW_PANEL::New( &m_frame->Kiway(), aParent, m_frame );
352
353 preview->SetName( c_previewName );
354 preview->GetGAL()->SetAxesEnabled( false );
355
356 mainSizer->Add( preview, 1, wxEXPAND | wxALL, 1 );
357 aParent->Layout();
358 }
359
360 preview->DisplayFootprint( node->m_LibId );
361}
const char * name
Definition: DXF_plotter.cpp:59
bool IsContentModified() const
Definition: base_screen.h:60
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:462
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:255
const LIB_ID & GetFPID() const
Definition: footprint.h:246
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.
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.
LIB_TREE_NODE_LIBRARY & 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.
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:689
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:72
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:200
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:1073
see class PGM_BASE
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
std::vector< wxString > pinned_fp_libs