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.

387 lines
11 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2011 Jean-Pierre Charras, <jp.charras@wanadoo.fr>
  5. * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
  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 2
  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. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 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. /*
  25. * @file footprint_info.h
  26. */
  27. #ifndef FOOTPRINT_INFO_H_
  28. #define FOOTPRINT_INFO_H_
  29. #include <boost/ptr_container/ptr_vector.hpp>
  30. #include <import_export.h>
  31. #include <ki_exception.h>
  32. #include <ki_mutex.h>
  33. #include <kicad_string.h>
  34. #include <sync_queue.h>
  35. #include <atomic>
  36. #include <functional>
  37. #include <memory>
  38. #define USE_FPI_LAZY 0 // 1:yes lazy, 0:no early
  39. class FP_LIB_TABLE;
  40. class FOOTPRINT_LIST;
  41. class FOOTPRINT_LIST_IMPL;
  42. class FOOTPRINT_ASYNC_LOADER;
  43. class WX_PROGRESS_REPORTER;
  44. class wxTopLevelWindow;
  45. class KIWAY;
  46. /*
  47. * Helper class to handle the list of footprints available in libraries. It stores
  48. * footprint names, doc and keywords.
  49. *
  50. * This is a virtual class; its implementation lives in pcbnew/footprint_info_impl.cpp.
  51. * To get instances of these classes, see FOOTPRINT_LIST::GetInstance().
  52. */
  53. class APIEXPORT FOOTPRINT_INFO
  54. {
  55. friend bool operator<( const FOOTPRINT_INFO& item1, const FOOTPRINT_INFO& item2 );
  56. public:
  57. virtual ~FOOTPRINT_INFO()
  58. {
  59. }
  60. // These two accessors do not have to call ensure_loaded(), because constructor
  61. // fills in these fields:
  62. const wxString& GetFootprintName() const
  63. {
  64. return m_fpname;
  65. }
  66. const wxString& GetNickname() const
  67. {
  68. return m_nickname;
  69. }
  70. const wxString& GetDoc()
  71. {
  72. ensure_loaded();
  73. return m_doc;
  74. }
  75. const wxString& GetKeywords()
  76. {
  77. ensure_loaded();
  78. return m_keywords;
  79. }
  80. unsigned GetPadCount()
  81. {
  82. ensure_loaded();
  83. return m_pad_count;
  84. }
  85. unsigned GetUniquePadCount()
  86. {
  87. ensure_loaded();
  88. return m_unique_pad_count;
  89. }
  90. int GetOrderNum()
  91. {
  92. ensure_loaded();
  93. return m_num;
  94. }
  95. /**
  96. * Test if the #FOOTPRINT_INFO object was loaded from \a aLibrary.
  97. *
  98. * @param aLibrary is the nickname of the library to test.
  99. *
  100. * @return true if the #FOOTPRINT_INFO object was loaded from \a aLibrary. Otherwise
  101. * false.
  102. */
  103. bool InLibrary( const wxString& aLibrary ) const;
  104. protected:
  105. void ensure_loaded()
  106. {
  107. if( !m_loaded )
  108. load();
  109. }
  110. /// lazily load stuff not filled in by constructor. This may throw IO_ERRORS.
  111. virtual void load() = 0;
  112. FOOTPRINT_LIST* m_owner; ///< provides access to FP_LIB_TABLE
  113. bool m_loaded;
  114. wxString m_nickname; ///< library as known in FP_LIB_TABLE
  115. wxString m_fpname; ///< Module name.
  116. int m_num; ///< Order number in the display list.
  117. int m_pad_count; ///< Number of pads
  118. int m_unique_pad_count; ///< Number of unique pads
  119. wxString m_doc; ///< Footprint description.
  120. wxString m_keywords; ///< Footprint keywords.
  121. };
  122. /// FOOTPRINT object list sort function.
  123. inline bool operator<( const FOOTPRINT_INFO& item1, const FOOTPRINT_INFO& item2 )
  124. {
  125. int retv = StrNumCmp( item1.m_nickname, item2.m_nickname, INT_MAX, true );
  126. if( retv != 0 )
  127. return retv < 0;
  128. return StrNumCmp( item1.m_fpname, item2.m_fpname, INT_MAX, true ) < 0;
  129. }
  130. /**
  131. * Holds a list of FOOTPRINT_INFO objects, along with a list of IO_ERRORs or
  132. * PARSE_ERRORs that were thrown acquiring the FOOTPRINT_INFOs.
  133. *
  134. * This is a virtual class; its implementation lives in pcbnew/footprint_info_impl.cpp.
  135. * To get instances of these classes, see FOOTPRINT_LIST::GetInstance().
  136. */
  137. class APIEXPORT FOOTPRINT_LIST
  138. {
  139. friend class FOOTPRINT_ASYNC_LOADER;
  140. protected:
  141. FP_LIB_TABLE* m_lib_table; ///< no ownership
  142. typedef std::vector<std::unique_ptr<FOOTPRINT_INFO>> FPILIST;
  143. typedef SYNC_QUEUE<std::unique_ptr<IO_ERROR>> ERRLIST;
  144. FPILIST m_list;
  145. ERRLIST m_errors; ///< some can be PARSE_ERRORs also
  146. MUTEX m_list_lock;
  147. public:
  148. FOOTPRINT_LIST() : m_lib_table( 0 )
  149. {
  150. }
  151. virtual ~FOOTPRINT_LIST()
  152. {
  153. }
  154. /**
  155. * @return the number of items stored in list
  156. */
  157. unsigned GetCount() const
  158. {
  159. return m_list.size();
  160. }
  161. /// Was forced to add this by modview_frame.cpp
  162. const FPILIST& GetList() const
  163. {
  164. return m_list;
  165. }
  166. /**
  167. * Get info for a module by name.
  168. * @param aFootprintName = the footprint name inside the FOOTPRINT_INFO of interest.
  169. * @return FOOTPRINT_INF* - the item stored in list if found
  170. */
  171. FOOTPRINT_INFO* GetModuleInfo( const wxString& aFootprintName );
  172. /**
  173. * Get info for a module by index.
  174. * @param aIdx = index of the given item
  175. * @return the aIdx item in list
  176. */
  177. FOOTPRINT_INFO& GetItem( unsigned aIdx )
  178. {
  179. return *m_list[aIdx];
  180. }
  181. /**
  182. * Add aItem to list
  183. * @param aItem = item to add
  184. */
  185. void AddItem( FOOTPRINT_INFO* aItem );
  186. unsigned GetErrorCount() const
  187. {
  188. return m_errors.size();
  189. }
  190. std::unique_ptr<IO_ERROR> PopError()
  191. {
  192. std::unique_ptr<IO_ERROR> error;
  193. m_errors.pop( error );
  194. return error;
  195. }
  196. /**
  197. * Read all the footprints provided by the combination of aTable and aNickname.
  198. *
  199. * @param aTable defines all the libraries.
  200. * @param aNickname is the library to read from, or if NULL means read all
  201. * footprints from all known libraries in aTable.
  202. * @param aProgressReporter is an optional progress reporter. ReadFootprintFiles()
  203. * will use 2 phases within the reporter.
  204. * @return bool - true if it ran to completion, else false if it aborted after
  205. * some number of errors. If true, it does not mean there were no errors, check
  206. * GetErrorCount() for that, should be zero to indicate success.
  207. */
  208. virtual bool ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname = nullptr,
  209. WX_PROGRESS_REPORTER* aProgressReporter = nullptr ) = 0;
  210. void DisplayErrors( wxTopLevelWindow* aCaller = NULL );
  211. FP_LIB_TABLE* GetTable() const
  212. {
  213. return m_lib_table;
  214. }
  215. /**
  216. * Factory function to return a new FOOTPRINT_LIST via Kiway. NOT guaranteed
  217. * to succeed; will return null if the kiface is not available.
  218. *
  219. * @param aKiway - active kiway instance
  220. */
  221. static std::unique_ptr<FOOTPRINT_LIST> GetInstance( KIWAY& aKiway );
  222. protected:
  223. /**
  224. * Launch worker threads to load footprints. Part of the
  225. * FOOTPRINT_ASYNC_LOADER implementation.
  226. */
  227. virtual void StartWorkers( FP_LIB_TABLE* aTable, wxString const* aNickname,
  228. FOOTPRINT_ASYNC_LOADER* aLoader, unsigned aNThreads ) = 0;
  229. /**
  230. * Join worker threads. Part of the FOOTPRINT_ASYNC_LOADER implementation.
  231. */
  232. virtual bool JoinWorkers() = 0;
  233. /**
  234. * Return the number of libraries finished (successfully or otherwise).
  235. */
  236. virtual size_t CountFinished() = 0;
  237. };
  238. /**
  239. * This class can be used to populate a FOOTPRINT_LIST asynchronously.
  240. * Constructing one, calling .Start(), then waiting until it reports completion
  241. * is equivalent to calling FOOTPRINT_LIST::ReadFootprintFiles().
  242. */
  243. class APIEXPORT FOOTPRINT_ASYNC_LOADER
  244. {
  245. friend class FOOTPRINT_LIST;
  246. friend class FOOTPRINT_LIST_IMPL;
  247. FOOTPRINT_LIST* m_list;
  248. std::function<void()> m_completion_cb;
  249. std::string m_last_table;
  250. bool m_started; ///< True if Start() has been called - does not reset
  251. int m_total_libs;
  252. public:
  253. /**
  254. * Construct an asynchronous loader.
  255. */
  256. FOOTPRINT_ASYNC_LOADER();
  257. /**
  258. * Assign a FOOTPRINT_LIST to the loader. This does not take ownership of
  259. * the list.
  260. */
  261. void SetList( FOOTPRINT_LIST* aList );
  262. /**
  263. * Launch the worker threads.
  264. * @param aTable defines all the libraries.
  265. * @param aNickname is the library to read from, or if NULL means read all
  266. * footprints from all known libraries in aTable.
  267. * @param aNThreads is the number of worker threads.
  268. */
  269. void Start( FP_LIB_TABLE* aTable, wxString const* aNickname = nullptr,
  270. unsigned aNThreads = DEFAULT_THREADS );
  271. /**
  272. * Wait until the worker threads are finished, and then perform any required
  273. * single-threaded finishing on the list. This must be called before using
  274. * the list, even if the completion callback was used!
  275. *
  276. * It is safe to call this method from a thread, but it is not safe to use
  277. * the list from ANY thread until it completes. It is recommended to call
  278. * this from the main thread because of this.
  279. *
  280. * It is safe to call this multiple times, but after the first it will
  281. * always return true.
  282. *
  283. * @return true if no errors occurred
  284. */
  285. bool Join();
  286. /**
  287. * Get the current completion percentage. 0 and 100 are reserved values:
  288. * 0 will only be returned if Start() has not yet been called, and 100
  289. * will only be returned if totally complete (i.e. rounding errors will
  290. * never cause a 100% progress despite not being complete).
  291. *
  292. * If there are no libraries at all, returns 100 (as loading zero libraries
  293. * is always complete).
  294. *
  295. * Threadsafe.
  296. */
  297. int GetProgress() const;
  298. /**
  299. * Set a callback to receive notice when loading is complete.
  300. *
  301. * Callback MUST be threadsafe, and must be set before calling Start
  302. * if you want to use it (it is safe not to set it at all).
  303. */
  304. void SetCompletionCallback( std::function<void()> aCallback );
  305. /**
  306. * Return true if the given table is the same as the last table loaded.
  307. * Useful for checking if the table has been modified and needs to be
  308. * reloaded.
  309. */
  310. bool IsSameTable( FP_LIB_TABLE* aOther );
  311. /**
  312. * Default number of worker threads. Determined empirically (by dickelbeck):
  313. * More than 6 is not significantly faster, less than 6 is likely slower.
  314. */
  315. static constexpr unsigned DEFAULT_THREADS = 6;
  316. };
  317. #endif // FOOTPRINT_INFO_H_