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  * @author Maciej Suminski <maciej.suminski@cern.ch>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * https://www.gnu.org/licenses/gpl-3.0.html
20  * or you may search the http://www.gnu.org website for the version 3 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
26 #include <footprint_edit_frame.h>
27 #include <fp_lib_table.h>
28 #include <footprint_info_impl.h>
29 #include <class_board.h>
30 #include <class_module.h>
31 
32 
34  FP_LIB_TABLE* aLibs )
35 {
36  return PTR( new FP_TREE_SYNCHRONIZING_ADAPTER( aFrame, aLibs ) );
37 }
38 
39 
41  FP_LIB_TABLE* aLibs ) :
42  FP_TREE_MODEL_ADAPTER( aLibs ),
43  m_frame( aFrame )
44 {
45 }
46 
47 
48 bool FP_TREE_SYNCHRONIZING_ADAPTER::IsContainer( const wxDataViewItem& aItem ) const
49 {
50  const LIB_TREE_NODE* node = ToNode( aItem );
51  return node ? node->Type == LIB_TREE_NODE::LIB : true;
52 }
53 
54 
55 #define PROGRESS_INTERVAL_MILLIS 66
56 
58 {
59  // Process already stored libraries
60  for( auto it = m_tree.Children.begin(); it != m_tree.Children.end(); )
61  {
62  const wxString& name = it->get()->Name;
63 
64  if( !m_libs->HasLibrary( name, true ) )
65  {
66  it = deleteLibrary( it );
67  continue;
68  }
69 
70  updateLibrary( *(LIB_TREE_NODE_LIB*) it->get() );
71  ++it;
72  }
73 
74  // Look for new libraries
75  size_t count = m_libMap.size();
76 
77  for( const auto& libName : m_libs->GetLogicalLibs() )
78  {
79  if( m_libMap.count( libName ) == 0 )
80  {
81  const FP_LIB_TABLE_ROW* library = m_libs->FindRow( libName );
82 
83  DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ), true );
84  m_libMap.insert( libName );
85  }
86  }
87 
88  if( m_libMap.size() > count )
90 }
91 
92 
94 {
95  return GFootprintTable.GetCount();
96 }
97 
98 
100 {
101  std::vector<LIB_TREE_ITEM*> footprints = getFootprints( aLibNode.Name );
102 
103  // remove the common part from the footprints list
104  for( auto nodeIt = aLibNode.Children.begin(); nodeIt != aLibNode.Children.end(); )
105  {
106  // Since the list is sorted we can use a binary search to speed up searches within
107  // libraries with lots of footprints.
108  FOOTPRINT_INFO_IMPL dummy( wxEmptyString, (*nodeIt)->Name );
109  auto footprintIt = std::lower_bound( footprints.begin(), footprints.end(), &dummy,
110  []( LIB_TREE_ITEM* a, LIB_TREE_ITEM* b )
111  {
112  return StrNumCmp( a->GetName(), b->GetName(), true ) < 0;
113  } );
114 
115  if( footprintIt != footprints.end() && dummy.GetName() == (*footprintIt)->GetName() )
116  {
117  // footprint exists both in the lib tree and the footprint info list; just
118  // update the node data
119  static_cast<LIB_TREE_NODE_LIB_ID*>( nodeIt->get() )->Update( *footprintIt );
120  footprints.erase( footprintIt );
121  ++nodeIt;
122  }
123  else
124  {
125  // node does not exist in the library manager, remove the corresponding node
126  nodeIt = aLibNode.Children.erase( nodeIt );
127  }
128  }
129 
130  // now the footprint list contains only new aliases that need to be added to the tree
131  for( auto footprint : footprints )
132  aLibNode.AddItem( footprint );
133 
134  aLibNode.AssignIntrinsicRanks();
135  m_libMap.insert( aLibNode.Name );
136 }
137 
138 
139 LIB_TREE_NODE::PTR_VECTOR::iterator FP_TREE_SYNCHRONIZING_ADAPTER::deleteLibrary(
140  LIB_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt )
141 {
142  LIB_TREE_NODE* node = aLibNodeIt->get();
143  m_libMap.erase( node->Name );
144  auto it = m_tree.Children.erase( aLibNodeIt );
145  return it;
146 }
147 
148 
149 void FP_TREE_SYNCHRONIZING_ADAPTER::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
150  unsigned int aCol ) const
151 {
152  if( IsFrozen() )
153  {
154  aVariant = wxEmptyString;
155  return;
156  }
157 
158  auto node = ToNode( aItem );
159 
160  switch( aCol )
161  {
162  case 0:
163  if( node->LibId == m_frame->GetLoadedFPID() && !m_frame->IsCurrentFPFromBoard() )
164  {
165  wxString currentFPName = m_frame->GetBoard()->m_Modules->GetFPID().GetLibItemName();
166 
167  // mark modified part with an asterix
168  if( m_frame->GetScreen()->IsModify() )
169  aVariant = currentFPName + " *";
170  else
171  aVariant = currentFPName;
172  }
173  else
174  aVariant = node->Name;
175  break;
176 
177  case 1:
178  if( node->LibId == m_frame->GetLoadedFPID() && !m_frame->IsCurrentFPFromBoard() )
179  aVariant = m_frame->GetBoard()->m_Modules->GetDescription();
180  else
181  aVariant = node->Desc;
182  break;
183 
184  default: // column == -1 is used for default Compare function
185  aVariant = node->Name;
186  break;
187  }
188 }
189 
190 
191 bool FP_TREE_SYNCHRONIZING_ADAPTER::GetAttr( wxDataViewItem const& aItem, unsigned int aCol,
192  wxDataViewItemAttr& aAttr ) const
193 {
194  if( IsFrozen() )
195  return false;
196 
197  // change attributes only for the name field
198  if( aCol != 0 )
199  return false;
200 
201  // don't link to a board footprint, even if the FPIDs match
203  return false;
204 
205  auto node = ToNode( aItem );
206  wxCHECK( node, false );
207 
208  switch( node->Type )
209  {
210  case LIB_TREE_NODE::LIB:
211  if( node->Name == m_frame->GetLoadedFPID().GetLibNickname() )
212  {
213 #ifdef __WXGTK__
214  // The native wxGTK+ impl ignores background colour, so set the text colour
215  // instead. Works reasonably well in dark themes, less well in light ones....
216  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
217 #else
218  aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
219 #endif
220 
221  // mark modified libs with bold font
223  aAttr.SetBold( true );
224  }
225  break;
226 
228  if( node->LibId == m_frame->GetLoadedFPID() )
229  {
230 #ifdef __WXGTK__
231  // The native wxGTK+ impl ignores background colour, so set the text colour
232  // instead. Works reasonably well in dark themes, less well in light ones....
233  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
234 #else
235  aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
236 #endif
237 
238  // mark modified part with bold font
240  aAttr.SetBold( true );
241  }
242  break;
243 
244  default:
245  return false;
246  }
247 
248  return true;
249 }
250 
251 
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
Get the value of an item.
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:342
PTR_VECTOR Children
List of child nodes.
enum TYPE Type
Node type.
Class FP_LIB_TABLE_ROW.
Definition: fp_lib_table.h:42
bool IsContainer(const wxDataViewItem &aItem) const override
Check whether an item can have children.
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.
Class BOARD to handle a board.
int GetLibrariesCount() const override
Return the number of libraries loaded in the tree.
FP_LIB_TABLE GFootprintTable
The global footprint library table.
Definition: pcbnew.cpp:326
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.
static LIB_TREE_NODE const * 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:328
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.
wxString Name
Actual name of the part.
void AssignIntrinsicRanks(bool presorted=false)
Store intrinsic ranks on all children of this node.
const char * name
Definition: DXF_plotter.cpp:61
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
LIB_ID GetLoadedFPID() const
Return the LIB_ID of the part being edited.
const wxString & GetName() const
DLIST< MODULE > m_Modules
Definition: class_board.h:248
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
Get any formatting for an item.
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
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.