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.

165 lines
5.0 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2022 KiCad Developers, see AUTHORS.TXT for contributors.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 3
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/gpl-3.0.html
  19. * or you may search the http://www.gnu.org website for the version 3 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. #include <eeschema_helpers.h>
  24. #include <sch_edit_frame.h>
  25. #include <settings/settings_manager.h>
  26. #include <wildcards_and_files_ext.h>
  27. #include <schematic.h>
  28. #include <sch_io_mgr.h>
  29. #include <locale_io.h>
  30. #include <wx/app.h>
  31. #include <connection_graph.h>
  32. SCH_EDIT_FRAME* EESCHEMA_HELPERS::s_SchEditFrame = nullptr;
  33. SETTINGS_MANAGER* EESCHEMA_HELPERS::s_SettingsManager = nullptr;
  34. void EESCHEMA_HELPERS::SetSchEditFrame( SCH_EDIT_FRAME* aSchEditFrame )
  35. {
  36. s_SchEditFrame = aSchEditFrame;
  37. }
  38. SETTINGS_MANAGER* EESCHEMA_HELPERS::GetSettingsManager()
  39. {
  40. if( !s_SettingsManager )
  41. {
  42. if( s_SchEditFrame )
  43. {
  44. s_SettingsManager = s_SchEditFrame->GetSettingsManager();
  45. }
  46. else
  47. {
  48. s_SettingsManager = new SETTINGS_MANAGER( true );
  49. }
  50. }
  51. return s_SettingsManager;
  52. }
  53. PROJECT* EESCHEMA_HELPERS::GetDefaultProject()
  54. {
  55. // For some reasons, LoadProject() needs a C locale, so ensure we have the right locale
  56. // This is mainly when running QA Python tests
  57. LOCALE_IO dummy;
  58. PROJECT* project = GetSettingsManager()->GetProject( "" );
  59. if( !project )
  60. {
  61. GetSettingsManager()->LoadProject( "" );
  62. project = GetSettingsManager()->GetProject( "" );
  63. }
  64. return project;
  65. }
  66. SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( wxString& aFileName )
  67. {
  68. if( aFileName.EndsWith( KiCadSchematicFileExtension ) )
  69. return LoadSchematic( aFileName, SCH_IO_MGR::SCH_KICAD );
  70. else if( aFileName.EndsWith( LegacySchematicFileExtension ) )
  71. return LoadSchematic( aFileName, SCH_IO_MGR::SCH_LEGACY );
  72. // as fall back for any other kind use the legacy format
  73. return LoadSchematic( aFileName, SCH_IO_MGR::SCH_LEGACY );
  74. }
  75. SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( wxString& aFileName, SCH_IO_MGR::SCH_FILE_T aFormat )
  76. {
  77. wxFileName pro = aFileName;
  78. pro.SetExt( ProjectFileExtension );
  79. pro.MakeAbsolute();
  80. wxString projectPath = pro.GetFullPath();
  81. // Ensure the "C" locale is temporary set, before reading any file
  82. // It also avoid wxWidget alerts about locale issues, later, when using Python 3
  83. LOCALE_IO dummy;
  84. PROJECT* project = GetSettingsManager()->GetProject( projectPath );
  85. if( !project )
  86. {
  87. if( wxFileExists( projectPath ) )
  88. {
  89. GetSettingsManager()->LoadProject( projectPath, false );
  90. project = GetSettingsManager()->GetProject( projectPath );
  91. }
  92. }
  93. else if( s_SchEditFrame && project == &GetSettingsManager()->Prj() )
  94. {
  95. // Project is already loaded? Then so is the board
  96. return &s_SchEditFrame->Schematic();
  97. }
  98. // Board cannot be loaded without a project, so create the default project
  99. if( !project )
  100. project = GetDefaultProject();
  101. SCH_PLUGIN* plugin = SCH_IO_MGR::FindPlugin( aFormat );
  102. SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( plugin );
  103. SCHEMATIC* schematic = new SCHEMATIC( project );
  104. try
  105. {
  106. schematic->SetRoot( pi->Load( aFileName, schematic ) );
  107. }
  108. catch( ... )
  109. {
  110. return nullptr;
  111. }
  112. SCH_SHEET_LIST sheetList = schematic->GetSheets();
  113. SCH_SCREENS schematicScreenRoot( schematic->Root() );
  114. for( SCH_SCREEN* screen = schematicScreenRoot.GetFirst(); screen;
  115. screen = schematicScreenRoot.GetNext() )
  116. screen->UpdateLocalLibSymbolLinks();
  117. if( schematic->RootScreen()->GetFileFormatVersionAtLoad() < 20221002 )
  118. sheetList.UpdateSymbolInstances( schematic->RootScreen()->GetSymbolInstances() );
  119. sheetList.UpdateSheetInstances( schematic->RootScreen()->GetSheetInstances() );
  120. sheetList.AnnotatePowerSymbols();
  121. schematic->ConnectionGraph()->Reset();
  122. schematic->SetSheetNumberAndCount();
  123. schematic->RecomputeIntersheetRefs( true, []( SCH_GLOBALLABEL* ) { } );
  124. for( SCH_SHEET_PATH& sheet : sheetList )
  125. {
  126. sheet.UpdateAllScreenReferences();
  127. sheet.LastScreen()->TestDanglingEnds( nullptr, nullptr );
  128. }
  129. schematic->ConnectionGraph()->Recalculate( sheetList, true );
  130. return schematic;
  131. }