From 6f5a92c7e278be644cb8a4e9c23b6944f4337f32 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Mon, 19 Jan 2026 13:51:24 -0800 Subject: [PATCH] Altium Schematic Import: Fix duplicate sheet creation in hierarchical projects When importing Altium projects, sheets were sometimes imported as both top-level sheets and hierarchical subsheets. This happened because the project file lists sheets in arbitrary order. If a parent sheet was processed before its children, the children would be loaded as subsheets during hierarchy descent. Later, when those same files appeared in the project file, duplicate sheets were created. The importer now checks whether a file has already been loaded as a subsheet before creating a new top-level sheet entry. The check includes a case-insensitive fallback search since Altium uses inconsistent casing in its .SchDoc extension. Sheet filenames were also being set to the original Altium paths instead of KiCad project-relative paths. This caused path mismatches in the hierarchy search and left references to non-existent Altium paths in the saved schematic. Filenames now use the KiCad project directory with the .kicad_sch extension. Hierarchical labels on top-level sheets are converted to global labels during import since top-level sheets have no parent sheet to connect them to. Fixes https://gitlab.com/kicad/code/kicad/-/issues/21909 (cherry picked from commit f00dc1befd64092dedf9808482e2d6472ad39bc5) --- eeschema/sch_io/altium/sch_io_altium.cpp | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/eeschema/sch_io/altium/sch_io_altium.cpp b/eeschema/sch_io/altium/sch_io_altium.cpp index 38013e512c..78b04fe875 100644 --- a/eeschema/sch_io/altium/sch_io_altium.cpp +++ b/eeschema/sch_io/altium/sch_io_altium.cpp @@ -595,6 +595,37 @@ SCH_SHEET* SCH_IO_ALTIUM::LoadSchematicFile( const wxString& aFileName, SCHEMATI else ParseAltiumSch( aFileName ); + // Convert hierarchical labels to global labels on top-level sheets. + // Top-level sheets have no parent, so hierarchical labels don't make sense. + if( aFileName.empty() ) + { + for( SCH_ITEM* item : rootScreen->Items().OfType( SCH_SHEET_T ) ) + { + SCH_SHEET* sheet = static_cast( item ); + SCH_SCREEN* screen = sheet->GetScreen(); + + if( !screen ) + continue; + + std::vector hierLabels; + + for( SCH_ITEM* labelItem : screen->Items().OfType( SCH_HIER_LABEL_T ) ) + hierLabels.push_back( static_cast( labelItem ) ); + + for( SCH_HIERLABEL* hierLabel : hierLabels ) + { + SCH_GLOBALLABEL* globalLabel = new SCH_GLOBALLABEL( hierLabel->GetPosition(), + hierLabel->GetText() ); + globalLabel->SetShape( hierLabel->GetShape() ); + globalLabel->SetSpinStyle( hierLabel->GetSpinStyle() ); + + screen->Remove( hierLabel ); + screen->Append( globalLabel ); + delete hierLabel; + } + } + } + if( m_reporter ) { for( auto& [msg, severity] : m_errorMessages )