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.

174 lines
5.5 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 <sch_label.h>
  32. #include <connection_graph.h>
  33. SCH_EDIT_FRAME* EESCHEMA_HELPERS::s_SchEditFrame = nullptr;
  34. SETTINGS_MANAGER* EESCHEMA_HELPERS::s_SettingsManager = nullptr;
  35. void EESCHEMA_HELPERS::SetSchEditFrame( SCH_EDIT_FRAME* aSchEditFrame )
  36. {
  37. s_SchEditFrame = aSchEditFrame;
  38. }
  39. SETTINGS_MANAGER* EESCHEMA_HELPERS::GetSettingsManager()
  40. {
  41. if( !s_SettingsManager )
  42. {
  43. if( s_SchEditFrame )
  44. {
  45. s_SettingsManager = s_SchEditFrame->GetSettingsManager();
  46. }
  47. else
  48. {
  49. s_SettingsManager = new SETTINGS_MANAGER( true );
  50. }
  51. }
  52. return s_SettingsManager;
  53. }
  54. PROJECT* EESCHEMA_HELPERS::GetDefaultProject()
  55. {
  56. // For some reasons, LoadProject() needs a C locale, so ensure we have the right locale
  57. // This is mainly when running QA Python tests
  58. LOCALE_IO dummy;
  59. PROJECT* project = GetSettingsManager()->GetProject( "" );
  60. if( !project )
  61. {
  62. GetSettingsManager()->LoadProject( "" );
  63. project = GetSettingsManager()->GetProject( "" );
  64. }
  65. return project;
  66. }
  67. SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( wxString& aFileName )
  68. {
  69. if( aFileName.EndsWith( KiCadSchematicFileExtension ) )
  70. return LoadSchematic( aFileName, SCH_IO_MGR::SCH_KICAD );
  71. else if( aFileName.EndsWith( LegacySchematicFileExtension ) )
  72. return LoadSchematic( aFileName, SCH_IO_MGR::SCH_LEGACY );
  73. // as fall back for any other kind use the legacy format
  74. return LoadSchematic( aFileName, SCH_IO_MGR::SCH_LEGACY );
  75. }
  76. SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( wxString& aFileName, SCH_IO_MGR::SCH_FILE_T aFormat )
  77. {
  78. wxFileName pro = aFileName;
  79. pro.SetExt( ProjectFileExtension );
  80. pro.MakeAbsolute();
  81. wxString projectPath = pro.GetFullPath();
  82. // Ensure the "C" locale is temporary set, before reading any file
  83. // It also avoid wxWidget alerts about locale issues, later, when using Python 3
  84. LOCALE_IO dummy;
  85. PROJECT* project = GetSettingsManager()->GetProject( projectPath );
  86. if( !project )
  87. {
  88. if( wxFileExists( projectPath ) )
  89. {
  90. GetSettingsManager()->LoadProject( projectPath, false );
  91. project = GetSettingsManager()->GetProject( projectPath );
  92. }
  93. }
  94. else if( s_SchEditFrame && project == &GetSettingsManager()->Prj() )
  95. {
  96. // Project is already loaded? Then so is the board
  97. return &s_SchEditFrame->Schematic();
  98. }
  99. // Board cannot be loaded without a project, so create the default project
  100. if( !project )
  101. project = GetDefaultProject();
  102. SCH_PLUGIN* plugin = SCH_IO_MGR::FindPlugin( aFormat );
  103. SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( plugin );
  104. SCHEMATIC* schematic = new SCHEMATIC( project );
  105. try
  106. {
  107. schematic->SetRoot( pi->Load( aFileName, schematic ) );
  108. }
  109. catch( ... )
  110. {
  111. return nullptr;
  112. }
  113. SCH_SHEET_LIST sheetList = schematic->GetSheets();
  114. SCH_SCREENS screens( schematic->Root() );
  115. for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
  116. screen->UpdateLocalLibSymbolLinks();
  117. if( schematic->RootScreen()->GetFileFormatVersionAtLoad() < 20221002 )
  118. sheetList.UpdateSymbolInstanceData( schematic->RootScreen()->GetSymbolInstances());
  119. sheetList.UpdateSheetInstanceData( schematic->RootScreen()->GetSheetInstances());
  120. for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
  121. screen->MigrateSimModels();
  122. sheetList.AnnotatePowerSymbols();
  123. schematic->ConnectionGraph()->Reset();
  124. schematic->SetSheetNumberAndCount();
  125. schematic->RecomputeIntersheetRefs( []( SCH_GLOBALLABEL* aGlobal )
  126. {
  127. for( SCH_FIELD& field : aGlobal->GetFields() )
  128. field.ClearBoundingBoxCache();
  129. aGlobal->ClearBoundingBoxCache();
  130. } );
  131. for( SCH_SHEET_PATH& sheet : sheetList )
  132. {
  133. sheet.UpdateAllScreenReferences();
  134. sheet.LastScreen()->TestDanglingEnds( nullptr, nullptr );
  135. }
  136. schematic->ConnectionGraph()->Recalculate( sheetList, true );
  137. return schematic;
  138. }