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 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 <class_board.h>
31 #include <class_module.h>
32 #include <tool/tool_manager.h>
34 
35 
37  FP_LIB_TABLE* aLibs )
38 {
39  return PTR( new FP_TREE_SYNCHRONIZING_ADAPTER( aFrame, aLibs ) );
40 }
41 
42 
44  FP_LIB_TABLE* aLibs ) :
45  FP_TREE_MODEL_ADAPTER( aFrame, aLibs ),
46  m_frame( aFrame )
47 {
48 }
49 
50 
52 {
54 }
55 
56 
57 bool FP_TREE_SYNCHRONIZING_ADAPTER::IsContainer( const wxDataViewItem& aItem ) const
58 {
59  const LIB_TREE_NODE* node = ToNode( aItem );
60  return node ? node->m_Type == LIB_TREE_NODE::LIB : true;
61 }
62 
63 
64 #define PROGRESS_INTERVAL_MILLIS 66
65 
67 {
68  // Process already stored libraries
69  for( auto it = m_tree.m_Children.begin(); it != m_tree.m_Children.end(); )
70  {
71  const wxString& name = it->get()->m_Name;
72 
73  if( !m_libs->HasLibrary( name, true ) )
74  {
75  it = deleteLibrary( it );
76  continue;
77  }
78 
79  updateLibrary( *(LIB_TREE_NODE_LIB*) it->get() );
80  ++it;
81  }
82 
83  // Look for new libraries
84  size_t count = m_libMap.size();
85 
86  for( const auto& libName : m_libs->GetLogicalLibs() )
87  {
88  if( m_libMap.count( libName ) == 0 )
89  {
90  const FP_LIB_TABLE_ROW* library = m_libs->FindRow( libName );
91 
92  DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ), true );
93  m_libMap.insert( libName );
94  }
95  }
96 
97  if( m_libMap.size() > count )
99 }
100 
101 
103 {
104  return GFootprintTable.GetCount();
105 }
106 
107 
109 {
110  std::vector<LIB_TREE_ITEM*> footprints = getFootprints( aLibNode.m_Name );
111 
112  // remove the common part from the footprints list
113  for( auto nodeIt = aLibNode.m_Children.begin(); nodeIt != aLibNode.m_Children.end(); )
114  {
115  // Since the list is sorted we can use a binary search to speed up searches within
116  // libraries with lots of footprints.
117  FOOTPRINT_INFO_IMPL dummy( wxEmptyString, (*nodeIt)->m_Name );
118  auto footprintIt = std::lower_bound( footprints.begin(), footprints.end(), &dummy,
119  []( LIB_TREE_ITEM* a, LIB_TREE_ITEM* b )
120  {
121  return StrNumCmp( a->GetName(), b->GetName(), false ) < 0;
122  } );
123 
124  if( footprintIt != footprints.end() && dummy.GetName() == (*footprintIt)->GetName() )
125  {
126  // footprint exists both in the lib tree and the footprint info list; just
127  // update the node data
128  static_cast<LIB_TREE_NODE_LIB_ID*>( nodeIt->get() )->Update( *footprintIt );
129  footprints.erase( footprintIt );
130  ++nodeIt;
131  }
132  else
133  {
134  // node does not exist in the library manager, remove the corresponding node
135  nodeIt = aLibNode.m_Children.erase( nodeIt );
136  }
137  }
138 
139  // now the footprint list contains only new aliases that need to be added to the tree
140  for( auto footprint : footprints )
141  aLibNode.AddItem( footprint );
142 
143  aLibNode.AssignIntrinsicRanks();
144  m_libMap.insert( aLibNode.m_Name );
145 }
146 
147 
148 LIB_TREE_NODE::PTR_VECTOR::iterator FP_TREE_SYNCHRONIZING_ADAPTER::deleteLibrary(
149  LIB_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt )
150 {
151  LIB_TREE_NODE* node = aLibNodeIt->get();
152  m_libMap.erase( node->m_Name );
153  auto it = m_tree.m_Children.erase( aLibNodeIt );
154  return it;
155 }
156 
157 
158 void FP_TREE_SYNCHRONIZING_ADAPTER::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
159  unsigned int aCol ) const
160 {
161  if( IsFrozen() )
162  {
163  aVariant = wxEmptyString;
164  return;
165  }
166 
167  auto node = ToNode( aItem );
168 
169  switch( aCol )
170  {
171  case 0:
172  if( node->m_LibId == m_frame->GetLoadedFPID() && !m_frame->IsCurrentFPFromBoard() )
173  {
174  auto mod = m_frame->GetBoard()->GetFirstModule();
175 
176  wxASSERT( mod );
177 
178  wxString currentFPName = mod->GetFPID().GetLibItemName();
179 
180  // mark modified part with an asterisk
181  if( m_frame->GetScreen()->IsModify() )
182  aVariant = currentFPName + " *";
183  else
184  aVariant = currentFPName;
185  }
186  else if( node->m_Pinned )
187  aVariant = GetPinningSymbol() + node->m_Name;
188  else
189  aVariant = node->m_Name;
190  break;
191 
192  case 1:
193  aVariant = node->m_Desc;
194  break;
195 
196  default: // column == -1 is used for default Compare function
197  aVariant = node->m_Name;
198  break;
199  }
200 }
201 
202 
203 bool FP_TREE_SYNCHRONIZING_ADAPTER::GetAttr( wxDataViewItem const& aItem, unsigned int aCol,
204  wxDataViewItemAttr& aAttr ) const
205 {
206  if( IsFrozen() )
207  return false;
208 
209  // change attributes only for the name field
210  if( aCol != 0 )
211  return false;
212 
213  // don't link to a board footprint, even if the FPIDs match
215  return false;
216 
217  auto node = ToNode( aItem );
218  wxCHECK( node, false );
219 
220  switch( node->m_Type )
221  {
222  case LIB_TREE_NODE::LIB:
223  if( node->m_Name == m_frame->GetLoadedFPID().GetLibNickname() )
224  {
225 #ifdef __WXGTK__
226  // The native wxGTK+ impl ignores background colour, so set the text colour
227  // instead. Works reasonably well in dark themes, less well in light ones....
228  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
229 #else
230  aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
231  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT ) );
232 #endif
233 
234  // mark modified libs with bold font
236  aAttr.SetBold( true );
237  }
238  break;
239 
241  if( node->m_LibId == m_frame->GetLoadedFPID() )
242  {
243 #ifdef __WXGTK__
244  // The native wxGTK+ impl ignores background colour, so set the text colour
245  // instead. Works reasonably well in dark themes, less well in light ones....
246  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
247 #else
248  aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
249  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT ) );
250 #endif
251 
252  // mark modified part with bold font
254  aAttr.SetBold( true );
255  }
256  break;
257 
258  default:
259  return false;
260  }
261 
262  return true;
263 }
264 
265 
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
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
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:354
wxString GetName() const override
FP_LIB_TABLE_ROW.
Definition: fp_lib_table.h:42
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
FP_LIB_TABLE GFootprintTable
!!!!!!!!!!!!!! This code is obsolete because of the merge into pcbnew, don't bother with it.
unsigned GetCount() const
Get the number of rows contained in the table.
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)
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.
MODULE * GetFirstModule() const
Gets the first module in the list (used in footprint viewer/editor) or NULL if none.
Definition: class_board.h:283
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:97
bool IsModify() const
Definition: base_screen.h:228
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 FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName)
Function FindRow.
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:60
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
LIB_ID GetLoadedFPID() const
Return the LIB_ID of the part being edited.
MODULE_EDITOR_TOOLS.
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
wxString m_Name
static PTR Create(FOOTPRINT_EDIT_FRAME *aFrame, FP_LIB_TABLE *aLibs)
wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > PTR
Reference-counting container for a pointer to CMP_TREE_MODEL_ADAPTER_BASE.
Module description (excepted pads)
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.