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-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  * @author Maciej Suminski <maciej.suminski@cern.ch>
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 
27 #include <footprint_edit_frame.h>
28 #include <fp_lib_table.h>
29 #include <footprint_info_impl.h>
30 #include <kicad_string.h>
31 #include <board.h>
32 #include <footprint.h>
33 #include <tool/tool_manager.h>
35 
36 
37 wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>
39 {
40  auto* adapter = new FP_TREE_SYNCHRONIZING_ADAPTER( aFrame, aLibs );
41  return wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>( adapter );
42 }
43 
44 
46  FP_LIB_TABLE* aLibs ) :
47  FP_TREE_MODEL_ADAPTER( aFrame, aLibs ),
48  m_frame( aFrame )
49 {
50 }
51 
52 
54 {
56 }
57 
58 
59 bool FP_TREE_SYNCHRONIZING_ADAPTER::IsContainer( const wxDataViewItem& aItem ) const
60 {
61  const LIB_TREE_NODE* node = ToNode( aItem );
62  return node ? node->m_Type == LIB_TREE_NODE::LIB : true;
63 }
64 
65 
66 #define PROGRESS_INTERVAL_MILLIS 66
67 
69 {
70  // Process already stored libraries
71  for( auto it = m_tree.m_Children.begin(); it != m_tree.m_Children.end(); )
72  {
73  const wxString& name = it->get()->m_Name;
74 
75  // Remove the library if it no longer exists or it exists in both the global and the
76  // project library but the project library entry is disabled.
77  if( !m_libs->HasLibrary( name, true )
78  || ( m_libs->FindRow( name, true ) != m_libs->FindRow( name, false ) ) )
79  {
80  it = deleteLibrary( it );
81  continue;
82  }
83 
84  updateLibrary( *(LIB_TREE_NODE_LIB*) it->get() );
85  ++it;
86  }
87 
88  // Look for new libraries
89  size_t count = m_libMap.size();
90 
91  for( const auto& libName : m_libs->GetLogicalLibs() )
92  {
93  if( m_libMap.count( libName ) == 0 )
94  {
95  const FP_LIB_TABLE_ROW* library = m_libs->FindRow( libName, true );
96 
97  DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ), true );
98  m_libMap.insert( libName );
99  }
100  }
101 
102  if( m_libMap.size() > count )
104 }
105 
106 
108 {
109  return GFootprintTable.GetCount();
110 }
111 
112 
114 {
115  std::vector<LIB_TREE_ITEM*> footprints = getFootprints( aLibNode.m_Name );
116 
117  // remove the common part from the footprints list
118  for( auto nodeIt = aLibNode.m_Children.begin(); nodeIt != aLibNode.m_Children.end(); )
119  {
120  // Since the list is sorted we can use a binary search to speed up searches within
121  // libraries with lots of footprints.
122  FOOTPRINT_INFO_IMPL dummy( wxEmptyString, (*nodeIt)->m_Name );
123  auto footprintIt = std::lower_bound( footprints.begin(), footprints.end(), &dummy,
124  []( LIB_TREE_ITEM* a, LIB_TREE_ITEM* b )
125  {
126  return StrNumCmp( a->GetName(), b->GetName(), false ) < 0;
127  } );
128 
129  if( footprintIt != footprints.end() && dummy.GetName() == (*footprintIt)->GetName() )
130  {
131  // footprint exists both in the lib tree and the footprint info list; just
132  // update the node data
133  static_cast<LIB_TREE_NODE_LIB_ID*>( nodeIt->get() )->Update( *footprintIt );
134  footprints.erase( footprintIt );
135  ++nodeIt;
136  }
137  else
138  {
139  // node does not exist in the library manager, remove the corresponding node
140  nodeIt = aLibNode.m_Children.erase( nodeIt );
141  }
142  }
143 
144  // now the footprint list contains only new aliases that need to be added to the tree
145  for( auto footprint : footprints )
146  aLibNode.AddItem( footprint );
147 
148  aLibNode.AssignIntrinsicRanks();
149  m_libMap.insert( aLibNode.m_Name );
150 }
151 
152 
153 LIB_TREE_NODE::PTR_VECTOR::iterator FP_TREE_SYNCHRONIZING_ADAPTER::deleteLibrary(
154  LIB_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt )
155 {
156  LIB_TREE_NODE* node = aLibNodeIt->get();
157  m_libMap.erase( node->m_Name );
158  auto it = m_tree.m_Children.erase( aLibNodeIt );
159  return it;
160 }
161 
162 
163 void FP_TREE_SYNCHRONIZING_ADAPTER::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
164  unsigned int aCol ) const
165 {
166  if( IsFrozen() )
167  {
168  aVariant = wxEmptyString;
169  return;
170  }
171 
172  auto node = ToNode( aItem );
173 
174  switch( aCol )
175  {
176  case 0:
177  if( node->m_LibId == m_frame->GetLoadedFPID() && !m_frame->IsCurrentFPFromBoard() )
178  {
179  node->m_Name = m_frame->GetLoadedFPID().GetLibItemName();
180 
181  // mark modified part with an asterisk
182  if( m_frame->GetScreen()->IsModify() )
183  aVariant = node->m_Name + " *";
184  else
185  aVariant = node->m_Name;
186  }
187  else if( node->m_Pinned )
188  aVariant = GetPinningSymbol() + node->m_Name;
189  else
190  aVariant = node->m_Name;
191  break;
192 
193  case 1:
194  if( node->m_LibId == m_frame->GetLoadedFPID() && !m_frame->IsCurrentFPFromBoard() )
195  node->m_Desc = m_frame->GetBoard()->GetFirstFootprint()->GetDescription();
196 
197  aVariant = node->m_Desc;
198  break;
199 
200  default: // column == -1 is used for default Compare function
201  aVariant = node->m_Name;
202  break;
203  }
204 }
205 
206 
207 bool FP_TREE_SYNCHRONIZING_ADAPTER::GetAttr( wxDataViewItem const& aItem, unsigned int aCol,
208  wxDataViewItemAttr& aAttr ) const
209 {
210  if( IsFrozen() )
211  return false;
212 
213  // change attributes only for the name field
214  if( aCol != 0 )
215  return false;
216 
217  // don't link to a board footprint, even if the FPIDs match
219  return false;
220 
221  auto node = ToNode( aItem );
222  wxCHECK( node, false );
223 
224  switch( node->m_Type )
225  {
226  case LIB_TREE_NODE::LIB:
227  if( node->m_Name == m_frame->GetLoadedFPID().GetLibNickname() )
228  {
229 #ifdef __WXGTK__
230  // The native wxGTK+ impl ignores background colour, so set the text colour
231  // instead. Works reasonably well in dark themes, less well in light ones....
232  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
233 #else
234  aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
235  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT ) );
236 #endif
237 
238  // mark modified libs with bold font
240  aAttr.SetBold( true );
241  }
242  break;
243 
245  if( node->m_LibId == m_frame->GetLoadedFPID() )
246  {
247 #ifdef __WXGTK__
248  // The native wxGTK+ impl ignores background colour, so set the text colour
249  // instead. Works reasonably well in dark themes, less well in light ones....
250  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
251 #else
252  aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
253  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT ) );
254 #endif
255 
256  // mark modified part with bold font
258  aAttr.SetBold( true );
259  }
260  break;
261 
262  default:
263  return false;
264  }
265 
266  return true;
267 }
268 
269 
void DoAddLibrary(wxString const &aNodeName, wxString const &aDesc, std::vector< LIB_TREE_ITEM * > const &aItemList, bool presorted)
Add the given list of components by alias.
void GetValue(wxVariant &aVariant, wxDataViewItem const &aItem, unsigned int aCol) const override
Module editor specific tools.
const wxString & GetDescription() const
Definition: footprint.h:193
const UTF8 & GetLibItemName() const
Definition: lib_id.h:106
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
Definition: string.cpp:420
FP_LIB_TABLE GFootprintTable
!!!!!!!!!!!!!! This code is obsolete because of the merge into pcbnew, don't bother with it.
Definition: cvpcb.cpp:120
wxString GetName() const override
Definition: lib_symbol.h:129
Hold a record identifying a library accessed by the appropriate footprint library PLUGIN object in th...
Definition: fp_lib_table.h:40
bool IsContainer(const wxDataViewItem &aItem) const override
A mix-in to provide polymorphism between items stored in libraries (symbols, aliases and footprints).
Definition: lib_tree_item.h:39
unsigned GetCount() const
Get the number of rows contained in the table.
static wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > Create(FOOTPRINT_EDIT_FRAME *aFrame, FP_LIB_TABLE *aLibs)
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
Definition: sch_symbol.cpp:69
int GetLibrariesCount() const override
Return the number of libraries loaded in the tree.
TOOL_INTERACTIVE * GetContextMenuTool() override
const wxString & GetDescr() const
Return the description of the library referenced by this row.
std::vector< LIB_TREE_ITEM * > getFootprints(const wxString &aLibName)
LIB_TREE_NODE::PTR_VECTOR::iterator deleteLibrary(LIB_TREE_NODE::PTR_VECTOR::iterator &aLibNodeIt)
FOOTPRINT * GetFirstFootprint() const
Gets the first footprint on the board or nullptr.
Definition: board.h:373
LIB_TREE_NODE_LIB_ID & AddItem(LIB_TREE_ITEM *aItem)
Construct a new alias node, add it to this library, and return it.
Node type: library.
static LIB_TREE_NODE * ToNode(wxDataViewItem aItem)
Convert wxDataViewItem -> CMP_TREE_NODE.
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:92
bool IsModify() const
Definition: base_screen.h:63
Model class in the component selector Model-View-Adapter (mediated MVC) architecture.
FP_TREE_SYNCHRONIZING_ADAPTER(FOOTPRINT_EDIT_FRAME *aFrame, FP_LIB_TABLE *aLibs)
void updateLibrary(LIB_TREE_NODE_LIB &aLibNode)
const wxString GetPinningSymbol() const
void AssignIntrinsicRanks(bool presorted=false)
Store intrinsic ranks on all children of this node.
const char * name
Definition: DXF_plotter.cpp:59
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...
LIB_ID GetLoadedFPID() const
Return the LIB_ID of the part being edited.
enum TYPE m_Type
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
bool GetAttr(wxDataViewItem const &aItem, unsigned int aCol, wxDataViewItemAttr &aAttr) const override
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
BOARD * GetBoard() const
PTR_VECTOR m_Children
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.