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 <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  if( !m_libs->HasLibrary( name, true ) )
76  {
77  it = deleteLibrary( it );
78  continue;
79  }
80 
81  updateLibrary( *(LIB_TREE_NODE_LIB*) it->get() );
82  ++it;
83  }
84 
85  // Look for new libraries
86  size_t count = m_libMap.size();
87 
88  for( const auto& libName : m_libs->GetLogicalLibs() )
89  {
90  if( m_libMap.count( libName ) == 0 )
91  {
92  const FP_LIB_TABLE_ROW* library = m_libs->FindRow( libName );
93 
94  DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ), true );
95  m_libMap.insert( libName );
96  }
97  }
98 
99  if( m_libMap.size() > count )
101 }
102 
103 
105 {
106  return GFootprintTable.GetCount();
107 }
108 
109 
111 {
112  std::vector<LIB_TREE_ITEM*> footprints = getFootprints( aLibNode.m_Name );
113 
114  // remove the common part from the footprints list
115  for( auto nodeIt = aLibNode.m_Children.begin(); nodeIt != aLibNode.m_Children.end(); )
116  {
117  // Since the list is sorted we can use a binary search to speed up searches within
118  // libraries with lots of footprints.
119  FOOTPRINT_INFO_IMPL dummy( wxEmptyString, (*nodeIt)->m_Name );
120  auto footprintIt = std::lower_bound( footprints.begin(), footprints.end(), &dummy,
121  []( LIB_TREE_ITEM* a, LIB_TREE_ITEM* b )
122  {
123  return StrNumCmp( a->GetName(), b->GetName(), false ) < 0;
124  } );
125 
126  if( footprintIt != footprints.end() && dummy.GetName() == (*footprintIt)->GetName() )
127  {
128  // footprint exists both in the lib tree and the footprint info list; just
129  // update the node data
130  static_cast<LIB_TREE_NODE_LIB_ID*>( nodeIt->get() )->Update( *footprintIt );
131  footprints.erase( footprintIt );
132  ++nodeIt;
133  }
134  else
135  {
136  // node does not exist in the library manager, remove the corresponding node
137  nodeIt = aLibNode.m_Children.erase( nodeIt );
138  }
139  }
140 
141  // now the footprint list contains only new aliases that need to be added to the tree
142  for( auto footprint : footprints )
143  aLibNode.AddItem( footprint );
144 
145  aLibNode.AssignIntrinsicRanks();
146  m_libMap.insert( aLibNode.m_Name );
147 }
148 
149 
150 LIB_TREE_NODE::PTR_VECTOR::iterator FP_TREE_SYNCHRONIZING_ADAPTER::deleteLibrary(
151  LIB_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt )
152 {
153  LIB_TREE_NODE* node = aLibNodeIt->get();
154  m_libMap.erase( node->m_Name );
155  auto it = m_tree.m_Children.erase( aLibNodeIt );
156  return it;
157 }
158 
159 
160 void FP_TREE_SYNCHRONIZING_ADAPTER::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
161  unsigned int aCol ) const
162 {
163  if( IsFrozen() )
164  {
165  aVariant = wxEmptyString;
166  return;
167  }
168 
169  auto node = ToNode( aItem );
170 
171  switch( aCol )
172  {
173  case 0:
174  if( node->m_LibId == m_frame->GetLoadedFPID() && !m_frame->IsCurrentFPFromBoard() )
175  {
176  node->m_Name = m_frame->GetLoadedFPID().GetLibItemName();
177 
178  // mark modified part with an asterisk
179  if( m_frame->GetScreen()->IsModify() )
180  aVariant = node->m_Name + " *";
181  else
182  aVariant = node->m_Name;
183  }
184  else if( node->m_Pinned )
185  aVariant = GetPinningSymbol() + node->m_Name;
186  else
187  aVariant = node->m_Name;
188  break;
189 
190  case 1:
191  if( node->m_LibId == m_frame->GetLoadedFPID() && !m_frame->IsCurrentFPFromBoard() )
192  node->m_Desc = m_frame->GetBoard()->GetFirstFootprint()->GetDescription();
193 
194  aVariant = node->m_Desc;
195  break;
196 
197  default: // column == -1 is used for default Compare function
198  aVariant = node->m_Name;
199  break;
200  }
201 }
202 
203 
204 bool FP_TREE_SYNCHRONIZING_ADAPTER::GetAttr( wxDataViewItem const& aItem, unsigned int aCol,
205  wxDataViewItemAttr& aAttr ) const
206 {
207  if( IsFrozen() )
208  return false;
209 
210  // change attributes only for the name field
211  if( aCol != 0 )
212  return false;
213 
214  // don't link to a board footprint, even if the FPIDs match
216  return false;
217 
218  auto node = ToNode( aItem );
219  wxCHECK( node, false );
220 
221  switch( node->m_Type )
222  {
223  case LIB_TREE_NODE::LIB:
224  if( node->m_Name == m_frame->GetLoadedFPID().GetLibNickname() )
225  {
226 #ifdef __WXGTK__
227  // The native wxGTK+ impl ignores background colour, so set the text colour
228  // instead. Works reasonably well in dark themes, less well in light ones....
229  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
230 #else
231  aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
232  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT ) );
233 #endif
234 
235  // mark modified libs with bold font
237  aAttr.SetBold( true );
238  }
239  break;
240 
242  if( node->m_LibId == m_frame->GetLoadedFPID() )
243  {
244 #ifdef __WXGTK__
245  // The native wxGTK+ impl ignores background colour, so set the text colour
246  // instead. Works reasonably well in dark themes, less well in light ones....
247  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
248 #else
249  aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
250  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT ) );
251 #endif
252 
253  // mark modified part with bold font
255  aAttr.SetBold( true );
256  }
257  break;
258 
259  default:
260  return false;
261  }
262 
263  return true;
264 }
265 
266 
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
const wxString & GetDescription() const
Definition: footprint.h:211
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
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:415
FOOTPRINT_EDITOR_TOOLS.
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.
static wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > Create(FOOTPRINT_EDIT_FRAME *aFrame, FP_LIB_TABLE *aLibs)
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:348
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:97
bool IsModify() const
Definition: base_screen.h:124
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:59
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.
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
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:76
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.