diff --git a/include/board_item.h b/include/board_item.h
index b671d54705..8228c0e72c 100644
--- a/include/board_item.h
+++ b/include/board_item.h
@@ -88,6 +88,8 @@ public:
 
     ~BOARD_ITEM();
 
+    virtual void CopyFrom( const BOARD_ITEM* aOther );
+
     void SetParentGroup( PCB_GROUP* aGroup ) { m_group = aGroup; }
     PCB_GROUP* GetParentGroup() const { return m_group; }
 
diff --git a/pcbnew/api/api_handler_pcb.cpp b/pcbnew/api/api_handler_pcb.cpp
index 1a1f8f95d2..6af7e6668f 100644
--- a/pcbnew/api/api_handler_pcb.cpp
+++ b/pcbnew/api/api_handler_pcb.cpp
@@ -478,7 +478,7 @@ HANDLER_RESULT<ItemRequestStatus> API_HANDLER_PCB::handleCreateUpdateItemsIntern
         {
             BOARD_ITEM* boardItem = *optItem;
             commit->Modify( boardItem );
-            boardItem->SwapItemData( item.get() );
+            boardItem->CopyFrom( item.get() );
             boardItem->Serialize( newItem );
         }
 
diff --git a/pcbnew/board_item.cpp b/pcbnew/board_item.cpp
index c51f0c4a26..3bc4910002 100644
--- a/pcbnew/board_item.cpp
+++ b/pcbnew/board_item.cpp
@@ -44,6 +44,13 @@ BOARD_ITEM::~BOARD_ITEM()
 }
 
 
+void BOARD_ITEM::CopyFrom( const BOARD_ITEM* aOther )
+{
+    wxCHECK( aOther, /* void */ );
+    *this = *aOther;
+}
+
+
 const BOARD* BOARD_ITEM::GetBoard() const
 {
     if( Type() == PCB_T )
diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp
index d0cc29799d..3a88b4e86d 100644
--- a/pcbnew/footprint.cpp
+++ b/pcbnew/footprint.cpp
@@ -948,6 +948,13 @@ FOOTPRINT& FOOTPRINT::operator=( const FOOTPRINT& aOther )
 }
 
 
+void FOOTPRINT::CopyFrom( const BOARD_ITEM* aOther )
+{
+    wxCHECK( aOther && aOther->Type() == PCB_FOOTPRINT_T, /* void */ );
+    *this = *static_cast<const FOOTPRINT*>( aOther );
+}
+
+
 bool FOOTPRINT::IsConflicting() const
 {
     return HasFlag( COURTYARD_CONFLICT );
diff --git a/pcbnew/footprint.h b/pcbnew/footprint.h
index 0b5d0cf4da..529a44e024 100644
--- a/pcbnew/footprint.h
+++ b/pcbnew/footprint.h
@@ -135,6 +135,8 @@ public:
     FOOTPRINT& operator=( const FOOTPRINT& aOther );
     FOOTPRINT& operator=( FOOTPRINT&& aOther );
 
+    void CopyFrom( const BOARD_ITEM* aOther ) override;
+
     void Serialize( google::protobuf::Any &aContainer ) const override;
     bool Deserialize( const google::protobuf::Any &aContainer ) override;
 
diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp
index 734e05aa7c..c626a86000 100644
--- a/pcbnew/pad.cpp
+++ b/pcbnew/pad.cpp
@@ -141,6 +141,13 @@ PAD& PAD::operator=( const PAD &aOther )
 }
 
 
+void PAD::CopyFrom( const BOARD_ITEM* aOther )
+{
+    wxCHECK( aOther && aOther->Type() == PCB_PAD_T, /* void */ );
+    *this = *static_cast<const PAD*>( aOther );
+}
+
+
 void PAD::Serialize( google::protobuf::Any &aContainer ) const
 {
     using namespace kiapi::board::types;
diff --git a/pcbnew/pad.h b/pcbnew/pad.h
index ea4d31aaa6..9e368f245d 100644
--- a/pcbnew/pad.h
+++ b/pcbnew/pad.h
@@ -60,6 +60,8 @@ public:
     PAD( const PAD& aPad );
     PAD& operator=( const PAD &aOther );
 
+    void CopyFrom( const BOARD_ITEM* aOther ) override;
+
     void Serialize( google::protobuf::Any &aContainer ) const override;
     bool Deserialize( const google::protobuf::Any &aContainer ) override;
 
diff --git a/pcbnew/pcb_reference_image.cpp b/pcbnew/pcb_reference_image.cpp
index 4d7f2aaaaf..75eab7d6e4 100644
--- a/pcbnew/pcb_reference_image.cpp
+++ b/pcbnew/pcb_reference_image.cpp
@@ -81,6 +81,13 @@ PCB_REFERENCE_IMAGE& PCB_REFERENCE_IMAGE::operator=( const BOARD_ITEM& aItem )
 }
 
 
+void PCB_REFERENCE_IMAGE::CopyFrom( const BOARD_ITEM* aOther )
+{
+    wxCHECK( aOther && aOther->Type() == PCB_REFERENCE_IMAGE_T, /* void */ );
+    *this = *static_cast<const PCB_REFERENCE_IMAGE*>( aOther );
+}
+
+
 EDA_ITEM* PCB_REFERENCE_IMAGE::Clone() const
 {
     return new PCB_REFERENCE_IMAGE( *this );
diff --git a/pcbnew/pcb_reference_image.h b/pcbnew/pcb_reference_image.h
index ffcecff6cd..91fa95436a 100644
--- a/pcbnew/pcb_reference_image.h
+++ b/pcbnew/pcb_reference_image.h
@@ -43,6 +43,8 @@ public:
 
     ~PCB_REFERENCE_IMAGE();
 
+    void CopyFrom( const BOARD_ITEM* aOther ) override;
+
     PCB_REFERENCE_IMAGE& operator=( const BOARD_ITEM& aItem );
 
     /**
diff --git a/pcbnew/pcb_shape.cpp b/pcbnew/pcb_shape.cpp
index c29a02bc97..2e0b523928 100644
--- a/pcbnew/pcb_shape.cpp
+++ b/pcbnew/pcb_shape.cpp
@@ -69,6 +69,13 @@ PCB_SHAPE::~PCB_SHAPE()
 }
 
 
+void PCB_SHAPE::CopyFrom( const BOARD_ITEM* aOther )
+{
+    wxCHECK( aOther && aOther->Type() == PCB_SHAPE_T, /* void */ );
+    *this = *static_cast<const PCB_SHAPE*>( aOther );
+}
+
+
 void PCB_SHAPE::Serialize( google::protobuf::Any &aContainer ) const
 {
     using namespace kiapi::common;
diff --git a/pcbnew/pcb_shape.h b/pcbnew/pcb_shape.h
index ceebcd3723..cd23bf03e6 100644
--- a/pcbnew/pcb_shape.h
+++ b/pcbnew/pcb_shape.h
@@ -46,6 +46,8 @@ public:
 
     ~PCB_SHAPE() override;
 
+    void CopyFrom( const BOARD_ITEM* aOther ) override;
+
     static bool ClassOf( const EDA_ITEM* aItem )
     {
         return aItem && PCB_SHAPE_T == aItem->Type();
diff --git a/pcbnew/pcb_text.cpp b/pcbnew/pcb_text.cpp
index 1db1b6af3d..cabb4e6c04 100644
--- a/pcbnew/pcb_text.cpp
+++ b/pcbnew/pcb_text.cpp
@@ -81,6 +81,13 @@ PCB_TEXT::~PCB_TEXT()
 }
 
 
+void PCB_TEXT::CopyFrom( const BOARD_ITEM* aOther )
+{
+    wxCHECK( aOther && aOther->Type() == PCB_TEXT_T, /* void */ );
+    *this = *static_cast<const PCB_TEXT*>( aOther );
+}
+
+
 void PCB_TEXT::Serialize( google::protobuf::Any &aContainer ) const
 {
     using namespace kiapi::common;
diff --git a/pcbnew/pcb_text.h b/pcbnew/pcb_text.h
index 905863014c..121a73ea66 100644
--- a/pcbnew/pcb_text.h
+++ b/pcbnew/pcb_text.h
@@ -46,6 +46,8 @@ public:
 
     ~PCB_TEXT();
 
+    void CopyFrom( const BOARD_ITEM* aOther ) override;
+
     static inline bool ClassOf( const EDA_ITEM* aItem )
     {
         return aItem && PCB_TEXT_T == aItem->Type();
diff --git a/pcbnew/pcb_textbox.cpp b/pcbnew/pcb_textbox.cpp
index 7d7a10bdb2..0ae82d820f 100644
--- a/pcbnew/pcb_textbox.cpp
+++ b/pcbnew/pcb_textbox.cpp
@@ -61,6 +61,14 @@ PCB_TEXTBOX::~PCB_TEXTBOX()
 {
 }
 
+
+void PCB_TEXTBOX::CopyFrom( const BOARD_ITEM* aOther )
+{
+    wxCHECK( aOther && aOther->Type() == PCB_TEXTBOX_T, /* void */ );
+    *this = *static_cast<const PCB_TEXTBOX*>( aOther );
+}
+
+
 void PCB_TEXTBOX::Serialize( google::protobuf::Any &aContainer ) const
 {
     using namespace kiapi::common::types;
diff --git a/pcbnew/pcb_textbox.h b/pcbnew/pcb_textbox.h
index 6c0dc596e9..68be0bcadd 100644
--- a/pcbnew/pcb_textbox.h
+++ b/pcbnew/pcb_textbox.h
@@ -43,6 +43,8 @@ public:
 
     ~PCB_TEXTBOX();
 
+    void CopyFrom( const BOARD_ITEM* aOther ) override;
+
     static inline bool ClassOf( const EDA_ITEM* aItem )
     {
         return aItem && PCB_TEXTBOX_T == aItem->Type();
diff --git a/pcbnew/pcb_track.cpp b/pcbnew/pcb_track.cpp
index e163abe7a5..572cfe9693 100644
--- a/pcbnew/pcb_track.cpp
+++ b/pcbnew/pcb_track.cpp
@@ -71,6 +71,13 @@ EDA_ITEM* PCB_TRACK::Clone() const
 }
 
 
+void PCB_TRACK::CopyFrom( const BOARD_ITEM* aOther )
+{
+    wxCHECK( aOther && aOther->Type() == PCB_TRACE_T, /* void */ );
+    *this = *static_cast<const PCB_TRACK*>( aOther );
+}
+
+
 PCB_ARC::PCB_ARC( BOARD_ITEM* aParent, const SHAPE_ARC* aArc ) :
     PCB_TRACK( aParent, PCB_ARC_T )
 {
@@ -86,6 +93,13 @@ EDA_ITEM* PCB_ARC::Clone() const
 }
 
 
+void PCB_ARC::CopyFrom( const BOARD_ITEM* aOther )
+{
+    wxCHECK( aOther && aOther->Type() == PCB_ARC_T, /* void */ );
+    *this = *static_cast<const PCB_ARC*>( aOther );
+}
+
+
 PCB_VIA::PCB_VIA( BOARD_ITEM* aParent ) :
         PCB_TRACK( aParent, PCB_VIA_T ),
         m_padStack( this )
@@ -136,6 +150,13 @@ PCB_VIA& PCB_VIA::operator=( const PCB_VIA &aOther )
 }
 
 
+void PCB_VIA::CopyFrom( const BOARD_ITEM* aOther )
+{
+    wxCHECK( aOther && aOther->Type() == PCB_VIA_T, /* void */ );
+    *this = *static_cast<const PCB_VIA*>( aOther );
+}
+
+
 EDA_ITEM* PCB_VIA::Clone() const
 {
     return new PCB_VIA( *this );
diff --git a/pcbnew/pcb_track.h b/pcbnew/pcb_track.h
index 7058c57b82..3b53258a3e 100644
--- a/pcbnew/pcb_track.h
+++ b/pcbnew/pcb_track.h
@@ -124,6 +124,8 @@ public:
 
     // Do not create a copy constructor.  The one generated by the compiler is adequate.
 
+    void CopyFrom( const BOARD_ITEM* aOther ) override;
+
     void Move( const VECTOR2I& aMoveVector ) override
     {
         m_Start += aMoveVector;
@@ -311,6 +313,8 @@ public:
 
     PCB_ARC( BOARD_ITEM* aParent, const SHAPE_ARC* aArc );
 
+    void CopyFrom( const BOARD_ITEM* aOther ) override;
+
     static inline bool ClassOf( const EDA_ITEM *aItem )
     {
         return aItem && PCB_ARC_T == aItem->Type();
@@ -411,6 +415,8 @@ public:
     PCB_VIA( const PCB_VIA& aOther );
     PCB_VIA& operator=( const PCB_VIA &aOther );
 
+    void CopyFrom( const BOARD_ITEM* aOther ) override;
+
     bool IsType( const std::vector<KICAD_T>& aScanTypes ) const override
     {
         if( BOARD_CONNECTED_ITEM::IsType( aScanTypes ) )
diff --git a/pcbnew/zone.cpp b/pcbnew/zone.cpp
index d65214666e..44aa9f77f8 100644
--- a/pcbnew/zone.cpp
+++ b/pcbnew/zone.cpp
@@ -113,6 +113,13 @@ ZONE& ZONE::operator=( const ZONE& aOther )
 }
 
 
+void ZONE::CopyFrom( const BOARD_ITEM* aOther )
+{
+    wxCHECK( aOther && aOther->Type() == PCB_ZONE_T, /* void */ );
+    *this = *static_cast<const ZONE*>( aOther );
+}
+
+
 ZONE::~ZONE()
 {
     delete m_Poly;
diff --git a/pcbnew/zone.h b/pcbnew/zone.h
index d820c6b370..1371d61d99 100644
--- a/pcbnew/zone.h
+++ b/pcbnew/zone.h
@@ -80,6 +80,8 @@ public:
 
     ~ZONE();
 
+    void CopyFrom( const BOARD_ITEM* aOther ) override;
+
     static inline bool ClassOf( const EDA_ITEM* aItem )
     {
         return aItem && aItem->Type() == PCB_ZONE_T;