From 661bab72200967a2e5110f5bcd195f36d1a79147 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Sat, 11 Nov 2017 09:09:24 +0100 Subject: [PATCH] Fix crash when appending a board in pcbnew. Fixes: lp:1731539 https://bugs.launchpad.net/kicad/+bug/1731539 --- pcbnew/tools/pcbnew_control.cpp | 62 ++++++++++++++++++++++++++------- pcbnew/tools/pcbnew_control.h | 8 ++++- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp index 7c51ceceb4..f5ea9690be 100644 --- a/pcbnew/tools/pcbnew_control.cpp +++ b/pcbnew/tools/pcbnew_control.cpp @@ -792,7 +792,7 @@ int PCBNEW_CONTROL::PasteItemsFromClipboard( const TOOL_EVENT& aEvent ) items.push_back( clipItem ); } - placeBoardItems( items ); + placeBoardItems( items, true ); break; } default: @@ -829,29 +829,43 @@ int PCBNEW_CONTROL::placeBoardItems( BOARD* aBoard ) for( auto track : aBoard->Tracks() ) { - items.push_back( track ); + if( track->GetFlags() & FLAG0 ) + track->ClearFlags( FLAG0 ); + else + items.push_back( track ); } for( auto module : aBoard->Modules() ) { - items.push_back( module ); + if( module->GetFlags() & FLAG0 ) + module->ClearFlags( FLAG0 ); + else + items.push_back( module ); } for( auto drawing : aBoard->Drawings() ) { - items.push_back( drawing ); + if( drawing->GetFlags() & FLAG0 ) + drawing->ClearFlags( FLAG0 ); + else + items.push_back( drawing ); } for( auto zone : aBoard->Zones() ) { - items.push_back( zone ); + if( zone->GetFlags() & FLAG0 ) + zone->ClearFlags( FLAG0 ); + else + items.push_back( zone ); } - return placeBoardItems( items ); + // items are new if the current board is not the board source + bool isNew = board() != aBoard; + return placeBoardItems( items, isNew ); } -int PCBNEW_CONTROL::placeBoardItems( std::vector& aItems ) +int PCBNEW_CONTROL::placeBoardItems( std::vector& aItems, bool aIsNew ) { m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); @@ -864,7 +878,12 @@ int PCBNEW_CONTROL::placeBoardItems( std::vector& aItems ) { item->SetSelected(); selection.Add( item ); - editTool->GetCurrentCommit()->Add( item ); + + // Add or just select items for the move/place command + if( aIsNew ) + editTool->GetCurrentCommit()->Add( item ); + else + editTool->GetCurrentCommit()->Added( item ); } selection.SetReferencePoint( VECTOR2I( 0, 0 ) ); @@ -875,21 +894,40 @@ int PCBNEW_CONTROL::placeBoardItems( std::vector& aItems ) return 0; } + int PCBNEW_CONTROL::AppendBoard( PLUGIN& pi, wxString& fileName ) { PCB_EDIT_FRAME* editFrame = dynamic_cast( m_frame ); + if( !editFrame ) return 1; - // Mark existing tracks, in order to know what are the new tracks - // Tracks are inserted, not appended, so mark existing tracks to be - // able to select the new tracks only later BOARD* brd = board(); + if( !brd ) return 1; + // Mark existing items, in order to know what are the new items + // to be ble to select only the new items after loadind for( auto track : brd->Tracks() ) + { track->SetFlags( FLAG0 ); + } + + for( auto module : brd->Modules() ) + { + module->SetFlags( FLAG0 ); + } + + for( auto drawing : brd->Drawings() ) + { + drawing->SetFlags( FLAG0 ); + } + + for( auto zone : brd->Zones() ) + { + zone->SetFlags( FLAG0 ); + } // Keep also the count of copper layers, to adjust if necessary int initialCopperLayerCount = brd->GetCopperLayerCount(); @@ -923,7 +961,7 @@ int PCBNEW_CONTROL::AppendBoard( PLUGIN& pi, wxString& fileName ) // rebuild nets and ratsnest before any use of nets brd->BuildListOfNets(); brd->SynchronizeNetsAndNetClasses(); - + brd->BuildConnectivity(); // Synchronize layers // we should not ask PLUGINs to do these items: diff --git a/pcbnew/tools/pcbnew_control.h b/pcbnew/tools/pcbnew_control.h index 381731e5bb..9731372ac6 100644 --- a/pcbnew/tools/pcbnew_control.h +++ b/pcbnew/tools/pcbnew_control.h @@ -92,7 +92,13 @@ public: private: int placeBoardItems( BOARD* aBoard ); - int placeBoardItems( std::vector& aItems ); + + /** add and selec or just select for move/place command a list of board items. + * @param aItems is the list of items + * @param aIsNew = true to add items to the current board, false to just select if + * items are already managed by the current board + */ + int placeBoardItems( std::vector& aItems, bool aIsNew ); ///> Pointer to the currently used edit frame. PCB_BASE_FRAME* m_frame;