From fa57c8a570923c41bea168d093cecf4f52a678a7 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Sun, 26 Apr 2020 14:27:51 -0400 Subject: [PATCH] Eeschema: fix sheet bug in schematic editor drawing tool. SCH_SHEET objects can only have another SCH_SHEET object as a parent or nullptr for the root sheet so overload EDA_ITEM::SetParent() to prevent the parent from being set to another type of object and add some checks to the root sheet code just in case someone gets clever and attempts to bypass the overloaded SetParent() call. --- eeschema/sch_eagle_plugin.cpp | 2 +- eeschema/sch_sheet.cpp | 22 ++++++++++++++++++++-- eeschema/sch_sheet.h | 2 ++ eeschema/tools/sch_drawing_tools.cpp | 2 +- include/base_struct.h | 4 ++-- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/eeschema/sch_eagle_plugin.cpp b/eeschema/sch_eagle_plugin.cpp index c86db924ca..5c241aff1e 100644 --- a/eeschema/sch_eagle_plugin.cpp +++ b/eeschema/sch_eagle_plugin.cpp @@ -596,7 +596,7 @@ void SCH_EAGLE_PLUGIN::loadSchematic( wxXmlNode* aSchematicNode ) std::unique_ptr sheet( new SCH_SHEET( pos ) ); SCH_SCREEN* screen = new SCH_SCREEN( m_kiway ); - sheet->SetParent( m_rootSheet->GetScreen() ); + sheet->SetParent( m_rootSheet ); sheet->SetScreen( screen ); sheet->GetScreen()->SetFileName( sheet->GetFileName() ); diff --git a/eeschema/sch_sheet.cpp b/eeschema/sch_sheet.cpp index db1fa79d2e..a43bfe036d 100644 --- a/eeschema/sch_sheet.cpp +++ b/eeschema/sch_sheet.cpp @@ -146,6 +146,19 @@ EDA_ITEM* SCH_SHEET::Clone() const } +void SCH_SHEET::SetParent( EDA_ITEM* aSheet ) +{ + m_Parent = nullptr; + + if( aSheet ) + { + // Parent must be another SCH_SHEET object or nullptr + wxCHECK( aSheet->Type() == SCH_SHEET_T, /* void */ ); + m_Parent = aSheet; + } +} + + void SCH_SHEET::SetScreen( SCH_SCREEN* aScreen ) { if( aScreen == m_screen ) @@ -180,11 +193,16 @@ int SCH_SHEET::GetScreenCount() const SCH_SHEET* SCH_SHEET::GetRootSheet() { - SCH_SHEET* sheet = dynamic_cast< SCH_SHEET* >( GetParent() ); + EDA_ITEM* item = GetParent(); - if( sheet == NULL ) + if( item == nullptr ) return this; + SCH_SHEET* sheet = dynamic_cast< SCH_SHEET* >( item ); + + // The parent must be a SCH_SHEET object. + wxCHECK( sheet, nullptr ); + // Recurse until a sheet is found with no parent which is the root sheet. return sheet->GetRootSheet(); } diff --git a/eeschema/sch_sheet.h b/eeschema/sch_sheet.h index ab3f51da57..5091ff97f6 100644 --- a/eeschema/sch_sheet.h +++ b/eeschema/sch_sheet.h @@ -254,6 +254,8 @@ public: return wxT( "SCH_SHEET" ); } + virtual void SetParent( EDA_ITEM* aSheet ) override; + /** * Return true for items which are moved with the anchor point at mouse cursor * and false for items moved with no reference to anchor. diff --git a/eeschema/tools/sch_drawing_tools.cpp b/eeschema/tools/sch_drawing_tools.cpp index bf4ac5be01..724aa73deb 100644 --- a/eeschema/tools/sch_drawing_tools.cpp +++ b/eeschema/tools/sch_drawing_tools.cpp @@ -843,7 +843,7 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent ) sheet = new SCH_SHEET( (wxPoint) cursorPos ); sheet->SetFlags( IS_NEW | IS_RESIZED ); - sheet->SetParent( m_frame->GetScreen() ); + sheet->SetParent( m_frame->GetCurrentSheet().Last() ); sheet->SetScreen( NULL ); sheet->SetBorderWidth( m_frame->GetDefaultLineWidth() ); sheet->SetBorderColor( cfg->m_Drawing.default_sheet_border_color ); diff --git a/include/base_struct.h b/include/base_struct.h index ed23e08c8f..e3b72dc871 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -4,7 +4,7 @@ * Copyright (C) 2013-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2008-2015 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2008 Wayne Stambaugh - * Copyright (C) 2004-2019 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2004-2020 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -197,7 +197,7 @@ public: inline KICAD_T Type() const { return m_StructType; } EDA_ITEM* GetParent() const { return m_Parent; } - void SetParent( EDA_ITEM* aParent ) { m_Parent = aParent; } + virtual void SetParent( EDA_ITEM* aParent ) { m_Parent = aParent; } inline bool IsNew() const { return m_Flags & IS_NEW; } inline bool IsModified() const { return m_Flags & IS_CHANGED; }