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.

176 lines
5.2 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software: you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation, either version 3 of the License, or (at your
  9. * option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <symbol_library.h>
  20. #include <confirm.h>
  21. #include <dialogs/html_message_box.h>
  22. #include <kiface_base.h>
  23. #include <pgm_base.h>
  24. #include <wx/app.h>
  25. #include <core/utf8.h>
  26. #include <symbol_lib_table.h>
  27. #include <project_sch.h>
  28. static std::mutex s_symbolTableMutex;
  29. // non-member so it can be moved easily, and kept REALLY private.
  30. // Do NOT Clear() in here.
  31. static void add_search_paths( SEARCH_STACK* aDst, const SEARCH_STACK& aSrc, int aIndex )
  32. {
  33. for( unsigned i=0; i<aSrc.GetCount(); ++i )
  34. aDst->AddPaths( aSrc[i], aIndex );
  35. }
  36. SEARCH_STACK* PROJECT_SCH::SchSearchS( PROJECT* aProject )
  37. {
  38. SEARCH_STACK* ss = (SEARCH_STACK*) aProject->GetElem( PROJECT::ELEM::SCH_SEARCH_STACK );
  39. wxASSERT( !ss || dynamic_cast<SEARCH_STACK*>( ss ) );
  40. if( !ss )
  41. {
  42. ss = new SEARCH_STACK();
  43. // Make PROJECT the new SEARCH_STACK owner.
  44. aProject->SetElem( PROJECT::ELEM::SCH_SEARCH_STACK, ss );
  45. // to the empty SEARCH_STACK for SchSearchS(), add project dir as first
  46. ss->AddPaths( aProject->GetProjectDirectory() );
  47. // next add the paths found in *.pro, variable "LibDir"
  48. wxString libDir;
  49. try
  50. {
  51. SYMBOL_LIBS::GetLibNamesAndPaths( aProject, &libDir );
  52. }
  53. catch( const IO_ERROR& )
  54. {
  55. }
  56. if( !!libDir )
  57. {
  58. wxArrayString paths;
  59. SEARCH_STACK::Split( &paths, libDir );
  60. for( unsigned i =0; i<paths.GetCount(); ++i )
  61. {
  62. wxString path = aProject->AbsolutePath( paths[i] );
  63. ss->AddPaths( path ); // at the end
  64. }
  65. }
  66. // append all paths from aSList
  67. add_search_paths( ss, Kiface().KifaceSearch(), -1 );
  68. }
  69. return ss;
  70. }
  71. SYMBOL_LIBS* PROJECT_SCH::SchLibs( PROJECT* aProject )
  72. {
  73. SYMBOL_LIBS* libs = (SYMBOL_LIBS*) aProject->GetElem( PROJECT::ELEM::SCH_SYMBOL_LIBS );
  74. wxASSERT( !libs || libs->ProjectElementType() == PROJECT::ELEM::SCH_SYMBOL_LIBS );
  75. if( !libs )
  76. {
  77. libs = new SYMBOL_LIBS();
  78. // Make PROJECT the new SYMBOL_LIBS owner.
  79. aProject->SetElem( PROJECT::ELEM::SCH_SYMBOL_LIBS, libs );
  80. try
  81. {
  82. libs->LoadAllLibraries( aProject );
  83. }
  84. catch( const PARSE_ERROR& pe )
  85. {
  86. wxString lib_list = UTF8( pe.inputLine );
  87. wxWindow* parent = Pgm().App().GetTopWindow();
  88. // parent of this dialog cannot be NULL since that breaks the Kiway() chain.
  89. HTML_MESSAGE_BOX dlg( parent, _( "Not Found" ) );
  90. dlg.MessageSet( _( "The following libraries were not found:" ) );
  91. dlg.ListSet( lib_list );
  92. dlg.Layout();
  93. dlg.ShowModal();
  94. }
  95. catch( const IO_ERROR& ioe )
  96. {
  97. wxWindow* parent = Pgm().App().GetTopWindow();
  98. DisplayError( parent, ioe.What() );
  99. }
  100. }
  101. return libs;
  102. }
  103. SYMBOL_LIB_TABLE* PROJECT_SCH::SchSymbolLibTable( PROJECT* aProject )
  104. {
  105. std::lock_guard<std::mutex> lock( s_symbolTableMutex );
  106. // This is a lazy loading function, it loads the project specific table when
  107. // that table is asked for, not before.
  108. SYMBOL_LIB_TABLE* tbl =
  109. (SYMBOL_LIB_TABLE*) aProject->GetElem( PROJECT::ELEM::SYMBOL_LIB_TABLE );
  110. // its gotta be NULL or a SYMBOL_LIB_TABLE, or a bug.
  111. wxASSERT( !tbl || tbl->ProjectElementType() == PROJECT::ELEM::SYMBOL_LIB_TABLE );
  112. if( !tbl )
  113. {
  114. // Stack the project specific SYMBOL_LIB_TABLE overlay on top of the global table.
  115. // ~SYMBOL_LIB_TABLE() will not touch the fallback table, so multiple projects may
  116. // stack this way, all using the same global fallback table.
  117. tbl = new SYMBOL_LIB_TABLE( &SYMBOL_LIB_TABLE::GetGlobalLibTable() );
  118. aProject->SetElem( PROJECT::ELEM::SYMBOL_LIB_TABLE, tbl );
  119. wxString prjPath;
  120. wxGetEnv( PROJECT_VAR_NAME, &prjPath );
  121. if( !prjPath.IsEmpty() )
  122. {
  123. wxFileName fn( prjPath, SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
  124. try
  125. {
  126. tbl->Load( fn.GetFullPath() );
  127. }
  128. catch( const IO_ERROR& ioe )
  129. {
  130. wxString msg;
  131. msg.Printf( _( "Error loading the symbol library table '%s'." ), fn.GetFullPath() );
  132. DisplayErrorMessage( nullptr, msg, ioe.What() );
  133. }
  134. }
  135. }
  136. return tbl;
  137. }