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  node->m_Name = m_frame->GetLoadedFPID().GetLibItemName();
175 
176  // mark modified part with an asterisk
177  if( m_frame->GetScreen()->IsModify() )
178  aVariant = node->m_Name + " *";
179  else
180  aVariant = node->m_Name;
181  }
182  else if( node->m_Pinned )
183  aVariant = GetPinningSymbol() + node->m_Name;
184  else
185  aVariant = node->m_Name;
186  break;
187 
188  case 1:
189  if( node->m_LibId == m_frame->GetLoadedFPID() && !m_frame->IsCurrentFPFromBoard() )
190  node->m_Desc = m_frame->GetBoard()->GetFirstModule()->GetDescription();
191 
192  aVariant = node->m_Desc;
193  break;
194 
195  default: // column == -1 is used for default Compare function
196  aVariant = node->m_Name;
197  break;
198  }
199 }
200 
201 
202 bool FP_TREE_SYNCHRONIZING_ADAPTER::GetAttr( wxDataViewItem const& aItem, unsigned int aCol,
203  wxDataViewItemAttr& aAttr ) const
204 {
205  if( IsFrozen() )
206  return false;
207 
208  // change attributes only for the name field
209  if( aCol != 0 )
210  return false;
211 
212  // don't link to a board footprint, even if the FPIDs match
214  return false;
215 
216  auto node = ToNode( aItem );
217  wxCHECK( node, false );
218 
219  switch( node->m_Type )
220  {
221  case LIB_TREE_NODE::LIB:
222  if( node->m_Name == m_frame->GetLoadedFPID().GetLibNickname() )
223  {
224 #ifdef __WXGTK__
225  // The native wxGTK+ impl ignores background colour, so set the text colour
226  // instead. Works reasonably well in dark themes, less well in light ones....
227  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
228 #else
229  aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
230  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT ) );
231 #endif
232 
233  // mark modified libs with bold font
235  aAttr.SetBold( true );
236  }
237  break;
238 
240  if( node->m_LibId == m_frame->GetLoadedFPID() )
241  {
242 #ifdef __WXGTK__
243  // The native wxGTK+ impl ignores background colour, so set the text colour
244  // instead. Works reasonably well in dark themes, less well in light ones....
245  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
246 #else
247  aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
248  aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT ) );
249 #endif
250 
251  // mark modified part with bold font
253  aAttr.SetBold( true );
254  }
255  break;
256 
257  default:
258  return false;
259  }
260 
261  return true;
262 }
263 
264 
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 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:388
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.
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:330
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:187
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 & GetDescription() const
Definition: class_module.h:218
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.
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)
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:74
wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > PTR
Reference-counting container for a pointer to CMP_TREE_MODEL_ADAPTER_BASE.
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.