You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
8.3 KiB

  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. #include <fp_tree_synchronizing_adapter.h>
  25. #include <footprint_edit_frame.h>
  26. #include <fp_lib_table.h>
  27. #include <footprint_info_impl.h>
  28. #include <class_board.h>
  29. #include <class_module.h>
  30. #include <tool/tool_manager.h>
  31. #include <tools/footprint_editor_tools.h>
  32. LIB_TREE_MODEL_ADAPTER::PTR FP_TREE_SYNCHRONIZING_ADAPTER::Create( FOOTPRINT_EDIT_FRAME* aFrame,
  33. FP_LIB_TABLE* aLibs )
  34. {
  35. return PTR( new FP_TREE_SYNCHRONIZING_ADAPTER( aFrame, aLibs ) );
  36. }
  37. FP_TREE_SYNCHRONIZING_ADAPTER::FP_TREE_SYNCHRONIZING_ADAPTER( FOOTPRINT_EDIT_FRAME* aFrame,
  38. FP_LIB_TABLE* aLibs ) :
  39. FP_TREE_MODEL_ADAPTER( aLibs ),
  40. m_frame( aFrame )
  41. {
  42. }
  43. TOOL_INTERACTIVE* FP_TREE_SYNCHRONIZING_ADAPTER::GetContextMenuTool()
  44. {
  45. return m_frame->GetToolManager()->GetTool<MODULE_EDITOR_TOOLS>();
  46. }
  47. bool FP_TREE_SYNCHRONIZING_ADAPTER::IsContainer( const wxDataViewItem& aItem ) const
  48. {
  49. const LIB_TREE_NODE* node = ToNode( aItem );
  50. return node ? node->Type == LIB_TREE_NODE::LIB : true;
  51. }
  52. #define PROGRESS_INTERVAL_MILLIS 66
  53. void FP_TREE_SYNCHRONIZING_ADAPTER::Sync()
  54. {
  55. // Process already stored libraries
  56. for( auto it = m_tree.Children.begin(); it != m_tree.Children.end(); )
  57. {
  58. const wxString& name = it->get()->Name;
  59. if( !m_libs->HasLibrary( name, true ) )
  60. {
  61. it = deleteLibrary( it );
  62. continue;
  63. }
  64. updateLibrary( *(LIB_TREE_NODE_LIB*) it->get() );
  65. ++it;
  66. }
  67. // Look for new libraries
  68. size_t count = m_libMap.size();
  69. for( const auto& libName : m_libs->GetLogicalLibs() )
  70. {
  71. if( m_libMap.count( libName ) == 0 )
  72. {
  73. const FP_LIB_TABLE_ROW* library = m_libs->FindRow( libName );
  74. DoAddLibrary( libName, library->GetDescr(), getFootprints( libName ), true );
  75. m_libMap.insert( libName );
  76. }
  77. }
  78. if( m_libMap.size() > count )
  79. m_tree.AssignIntrinsicRanks();
  80. }
  81. int FP_TREE_SYNCHRONIZING_ADAPTER::GetLibrariesCount() const
  82. {
  83. return GFootprintTable.GetCount();
  84. }
  85. void FP_TREE_SYNCHRONIZING_ADAPTER::updateLibrary( LIB_TREE_NODE_LIB& aLibNode )
  86. {
  87. std::vector<LIB_TREE_ITEM*> footprints = getFootprints( aLibNode.Name );
  88. // remove the common part from the footprints list
  89. for( auto nodeIt = aLibNode.Children.begin(); nodeIt != aLibNode.Children.end(); )
  90. {
  91. // Since the list is sorted we can use a binary search to speed up searches within
  92. // libraries with lots of footprints.
  93. FOOTPRINT_INFO_IMPL dummy( wxEmptyString, (*nodeIt)->Name );
  94. auto footprintIt = std::lower_bound( footprints.begin(), footprints.end(), &dummy,
  95. []( LIB_TREE_ITEM* a, LIB_TREE_ITEM* b )
  96. {
  97. return StrNumCmp( a->GetName(), b->GetName(), true ) < 0;
  98. } );
  99. if( footprintIt != footprints.end() && dummy.GetName() == (*footprintIt)->GetName() )
  100. {
  101. // footprint exists both in the lib tree and the footprint info list; just
  102. // update the node data
  103. static_cast<LIB_TREE_NODE_LIB_ID*>( nodeIt->get() )->Update( *footprintIt );
  104. footprints.erase( footprintIt );
  105. ++nodeIt;
  106. }
  107. else
  108. {
  109. // node does not exist in the library manager, remove the corresponding node
  110. nodeIt = aLibNode.Children.erase( nodeIt );
  111. }
  112. }
  113. // now the footprint list contains only new aliases that need to be added to the tree
  114. for( auto footprint : footprints )
  115. aLibNode.AddItem( footprint );
  116. aLibNode.AssignIntrinsicRanks();
  117. m_libMap.insert( aLibNode.Name );
  118. }
  119. LIB_TREE_NODE::PTR_VECTOR::iterator FP_TREE_SYNCHRONIZING_ADAPTER::deleteLibrary(
  120. LIB_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt )
  121. {
  122. LIB_TREE_NODE* node = aLibNodeIt->get();
  123. m_libMap.erase( node->Name );
  124. auto it = m_tree.Children.erase( aLibNodeIt );
  125. return it;
  126. }
  127. void FP_TREE_SYNCHRONIZING_ADAPTER::GetValue( wxVariant& aVariant, wxDataViewItem const& aItem,
  128. unsigned int aCol ) const
  129. {
  130. if( IsFrozen() )
  131. {
  132. aVariant = wxEmptyString;
  133. return;
  134. }
  135. auto node = ToNode( aItem );
  136. switch( aCol )
  137. {
  138. case 0:
  139. if( node->LibId == m_frame->GetLoadedFPID() && !m_frame->IsCurrentFPFromBoard() )
  140. {
  141. auto mod = m_frame->GetBoard()->GetFirstModule();
  142. wxASSERT( mod );
  143. wxString currentFPName = mod->GetFPID().GetLibItemName();
  144. // mark modified part with an asterix
  145. if( m_frame->GetScreen()->IsModify() )
  146. aVariant = currentFPName + " *";
  147. else
  148. aVariant = currentFPName;
  149. }
  150. else
  151. aVariant = node->Name;
  152. break;
  153. case 1:
  154. if( node->LibId == m_frame->GetLoadedFPID() && !m_frame->IsCurrentFPFromBoard() )
  155. {
  156. auto mod = m_frame->GetBoard()->GetFirstModule();
  157. wxASSERT( mod );
  158. aVariant = mod->GetDescription();
  159. }
  160. else
  161. aVariant = node->Desc;
  162. break;
  163. default: // column == -1 is used for default Compare function
  164. aVariant = node->Name;
  165. break;
  166. }
  167. }
  168. bool FP_TREE_SYNCHRONIZING_ADAPTER::GetAttr( wxDataViewItem const& aItem, unsigned int aCol,
  169. wxDataViewItemAttr& aAttr ) const
  170. {
  171. if( IsFrozen() )
  172. return false;
  173. // change attributes only for the name field
  174. if( aCol != 0 )
  175. return false;
  176. // don't link to a board footprint, even if the FPIDs match
  177. if( m_frame->IsCurrentFPFromBoard() )
  178. return false;
  179. auto node = ToNode( aItem );
  180. wxCHECK( node, false );
  181. switch( node->Type )
  182. {
  183. case LIB_TREE_NODE::LIB:
  184. if( node->Name == m_frame->GetLoadedFPID().GetLibNickname() )
  185. {
  186. #ifdef __WXGTK__
  187. // The native wxGTK+ impl ignores background colour, so set the text colour
  188. // instead. Works reasonably well in dark themes, less well in light ones....
  189. aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
  190. #else
  191. aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
  192. #endif
  193. // mark modified libs with bold font
  194. if( m_frame->GetScreen()->IsModify() && !m_frame->IsCurrentFPFromBoard() )
  195. aAttr.SetBold( true );
  196. }
  197. break;
  198. case LIB_TREE_NODE::LIBID:
  199. if( node->LibId == m_frame->GetLoadedFPID() )
  200. {
  201. #ifdef __WXGTK__
  202. // The native wxGTK+ impl ignores background colour, so set the text colour
  203. // instead. Works reasonably well in dark themes, less well in light ones....
  204. aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
  205. #else
  206. aAttr.SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
  207. #endif
  208. // mark modified part with bold font
  209. if( m_frame->GetScreen()->IsModify() && !m_frame->IsCurrentFPFromBoard() )
  210. aAttr.SetBold( true );
  211. }
  212. break;
  213. default:
  214. return false;
  215. }
  216. return true;
  217. }