diff --git a/common/tool/actions.cpp b/common/tool/actions.cpp index 1cdc35c9b1..f3d3c1136d 100644 --- a/common/tool/actions.cpp +++ b/common/tool/actions.cpp @@ -164,6 +164,11 @@ TOOL_ACTION ACTIONS::paste( "common.Interactive.paste", _( "Paste" ), _( "Paste clipboard into schematic" ), paste_xpm ); +TOOL_ACTION ACTIONS::pasteSpecial( "common.Interactive.pasteSpecial", + AS_GLOBAL, 0, "", + _( "Paste Special..." ), _( "Paste clipboard into schematic with options" ), + paste_xpm ); + TOOL_ACTION ACTIONS::duplicate( "common.Interactive.duplicate", AS_GLOBAL, MD_CTRL + 'D', LEGACY_HK_NAME( "Duplicate" ), diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index ce290b4390..6a997989d8 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -72,6 +72,8 @@ set( EESCHEMA_DLGS dialogs/dialog_migrate_buses_base.cpp dialogs/dialog_netlist.cpp dialogs/dialog_netlist_base.cpp + dialogs/dialog_paste_special.cpp + dialogs/dialog_paste_special_base.cpp dialogs/dialog_plot_schematic.cpp dialogs/dialog_plot_schematic_base.cpp dialogs/dialog_print_using_printer.cpp diff --git a/eeschema/dialogs/dialog_paste_special.cpp b/eeschema/dialogs/dialog_paste_special.cpp new file mode 100644 index 0000000000..e35c02562a --- /dev/null +++ b/eeschema/dialogs/dialog_paste_special.cpp @@ -0,0 +1,68 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2019 KiCad Developers, see AUTHORS.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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + + +static bool g_keepAnnotations = true; +static bool g_dropAnnotations = false; + + +DIALOG_PASTE_SPECIAL::DIALOG_PASTE_SPECIAL( wxWindow* parent, bool* aKeep, bool* aDrop ) : + DIALOG_PASTE_SPECIAL_BASE( parent ), + m_keep( aKeep ), + m_drop( aDrop ) +{ + // Now all widgets have the size fixed, call FinishDialogSettings + FinishDialogSettings(); +} + + +bool DIALOG_PASTE_SPECIAL::TransferDataToWindow() +{ + m_keepAnnotations->SetValue( g_keepAnnotations ); + m_dropAnnotations->SetValue( g_dropAnnotations ); + return true; +} + + +void DIALOG_PASTE_SPECIAL::OnKeepAnnotations( wxCommandEvent& event ) +{ + if( m_keepAnnotations->GetValue() ) + m_dropAnnotations->SetValue( false ); +} + + +void DIALOG_PASTE_SPECIAL::OnDropAnnotations( wxCommandEvent& event ) +{ + if( m_dropAnnotations->GetValue() ) + m_keepAnnotations->SetValue( false ); +} + + +bool DIALOG_PASTE_SPECIAL::TransferDataFromWindow() +{ + g_keepAnnotations = *m_keep = m_keepAnnotations->GetValue(); + g_dropAnnotations = *m_drop = m_dropAnnotations->GetValue(); + return true; +} diff --git a/eeschema/dialogs/dialog_paste_special.h b/eeschema/dialogs/dialog_paste_special.h new file mode 100644 index 0000000000..ef9711544f --- /dev/null +++ b/eeschema/dialogs/dialog_paste_special.h @@ -0,0 +1,52 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2019 KiCad Developers, see AUTHORS.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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef DIALOG_PASTE_SPECIAL_H +#define DIALOG_PASTE_SPECIAL_H + + +#include +#include + + +class SCH_SHEET_PIN; + + +class DIALOG_PASTE_SPECIAL : public DIALOG_PASTE_SPECIAL_BASE +{ + +public: + DIALOG_PASTE_SPECIAL( wxWindow* parent, bool* aKeepAnnotations, bool* aDropAnnotations ); + + void OnKeepAnnotations( wxCommandEvent& event ) override; + void OnDropAnnotations( wxCommandEvent& event ) override; + + bool TransferDataToWindow() override; + bool TransferDataFromWindow() override; + +private: + bool* m_keep; + bool* m_drop; +}; + +#endif // DIALOG_PASTE_SPECIAL_H diff --git a/eeschema/dialogs/dialog_paste_special_base.cpp b/eeschema/dialogs/dialog_paste_special_base.cpp new file mode 100644 index 0000000000..90eb3be104 --- /dev/null +++ b/eeschema/dialogs/dialog_paste_special_base.cpp @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 26 2018) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_paste_special_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_PASTE_SPECIAL_BASE::DIALOG_PASTE_SPECIAL_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); + + wxBoxSizer* m_mainSizer; + m_mainSizer = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* optionsSizer; + optionsSizer = new wxBoxSizer( wxVERTICAL ); + + m_staticText7 = new wxStaticText( this, wxID_ANY, _("Paste Options"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText7->Wrap( -1 ); + optionsSizer->Add( m_staticText7, 0, wxALL, 5 ); + + m_keepAnnotations = new wxCheckBox( this, wxID_ANY, _("Keep existing annotations, even if they are duplicated"), wxDefaultPosition, wxDefaultSize, 0 ); + optionsSizer->Add( m_keepAnnotations, 0, wxALL, 5 ); + + m_dropAnnotations = new wxCheckBox( this, wxID_ANY, _("Clear annotations on pasted items"), wxDefaultPosition, wxDefaultSize, 0 ); + optionsSizer->Add( m_dropAnnotations, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + + m_mainSizer->Add( optionsSizer, 1, wxALL|wxEXPAND, 10 ); + + m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + m_mainSizer->Add( m_staticline1, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 ); + + m_sdbSizer = new wxStdDialogButtonSizer(); + m_sdbSizerOK = new wxButton( this, wxID_OK ); + m_sdbSizer->AddButton( m_sdbSizerOK ); + m_sdbSizerCancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer->AddButton( m_sdbSizerCancel ); + m_sdbSizer->Realize(); + + m_mainSizer->Add( m_sdbSizer, 0, wxALL|wxEXPAND, 6 ); + + + this->SetSizer( m_mainSizer ); + this->Layout(); + m_mainSizer->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + m_keepAnnotations->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::OnKeepAnnotations ), NULL, this ); + m_dropAnnotations->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::OnDropAnnotations ), NULL, this ); + m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::onOKButton ), NULL, this ); +} + +DIALOG_PASTE_SPECIAL_BASE::~DIALOG_PASTE_SPECIAL_BASE() +{ + // Disconnect Events + m_keepAnnotations->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::OnKeepAnnotations ), NULL, this ); + m_dropAnnotations->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::OnDropAnnotations ), NULL, this ); + m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::onOKButton ), NULL, this ); + +} diff --git a/eeschema/dialogs/dialog_paste_special_base.fbp b/eeschema/dialogs/dialog_paste_special_base.fbp new file mode 100644 index 0000000000..631c55234f --- /dev/null +++ b/eeschema/dialogs/dialog_paste_special_base.fbp @@ -0,0 +1,343 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_paste_special_base + 1000 + none + + 1 + dialog_paste_special + + . + + 1 + 1 + 1 + 1 + UI + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + -1,-1 + DIALOG_PASTE_SPECIAL_BASE + + -1,-1 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Paste Special + + + + + + + m_mainSizer + wxVERTICAL + none + + 10 + wxALL|wxEXPAND + 1 + + + optionsSizer + wxVERTICAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Paste Options + 0 + + 0 + + + 0 + + 1 + m_staticText7 + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Keep existing annotations, even if they are duplicated + + 0 + + + 0 + + 1 + m_keepAnnotations + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnKeepAnnotations + + + + 5 + wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Clear annotations on pasted items + + 0 + + + 0 + + 1 + m_dropAnnotations + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnDropAnnotations + + + + + + 10 + wxEXPAND|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_staticline1 + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + ; forward_declare + 0 + + + + + + + + 6 + wxALL|wxEXPAND + 0 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizer + protected + onOKButton + + + + + + diff --git a/eeschema/dialogs/dialog_paste_special_base.h b/eeschema/dialogs/dialog_paste_special_base.h new file mode 100644 index 0000000000..fed8ddebac --- /dev/null +++ b/eeschema/dialogs/dialog_paste_special_base.h @@ -0,0 +1,57 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 26 2018) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_PASTE_SPECIAL_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_PASTE_SPECIAL_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxStaticText* m_staticText7; + wxCheckBox* m_keepAnnotations; + wxCheckBox* m_dropAnnotations; + wxStaticLine* m_staticline1; + wxStdDialogButtonSizer* m_sdbSizer; + wxButton* m_sdbSizerOK; + wxButton* m_sdbSizerCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnKeepAnnotations( wxCommandEvent& event ) { event.Skip(); } + virtual void OnDropAnnotations( wxCommandEvent& event ) { event.Skip(); } + virtual void onOKButton( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_PASTE_SPECIAL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Paste Special"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_PASTE_SPECIAL_BASE(); + +}; + diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp index 208103f189..0fa73e18e7 100644 --- a/eeschema/menubar.cpp +++ b/eeschema/menubar.cpp @@ -137,6 +137,7 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() editMenu->AddItem( ACTIONS::cut, EE_CONDITIONS::NotEmpty ); editMenu->AddItem( ACTIONS::copy, EE_CONDITIONS::NotEmpty ); editMenu->AddItem( ACTIONS::paste, EE_CONDITIONS::Idle ); + editMenu->AddItem( ACTIONS::pasteSpecial, EE_CONDITIONS::Idle ); editMenu->AddItem( ACTIONS::doDelete, EE_CONDITIONS::NotEmpty ); editMenu->AddItem( ACTIONS::duplicate, EE_CONDITIONS::NotEmpty ); diff --git a/eeschema/tools/sch_edit_tool.cpp b/eeschema/tools/sch_edit_tool.cpp index 71eace35e0..b1ea231ac0 100644 --- a/eeschema/tools/sch_edit_tool.cpp +++ b/eeschema/tools/sch_edit_tool.cpp @@ -316,6 +316,7 @@ bool SCH_EDIT_TOOL::Init() selToolMenu.AddItem( ACTIONS::cut, E_C::IdleSelection, 300 ); selToolMenu.AddItem( ACTIONS::copy, E_C::IdleSelection, 300 ); selToolMenu.AddItem( ACTIONS::paste, E_C::Idle, 300 ); + selToolMenu.AddItem( ACTIONS::pasteSpecial, E_C::Idle, 300 ); selToolMenu.AddItem( ACTIONS::duplicate, duplicateCondition, 300 ); return true; diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index b3fbbd6fdc..cc2ef88339 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -50,7 +50,7 @@ #include #include #include - +#include int SCH_EDITOR_CONTROL::New( const TOOL_EVENT& aEvent ) { @@ -943,7 +943,7 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent ) EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool(); DLIST& dlist = m_frame->GetScreen()->GetDrawList(); - SCH_ITEM* last = dlist.GetLast(); + SCH_ITEM* lastExisting = dlist.GetLast(); std::string text = m_toolMgr->GetClipboard(); @@ -963,16 +963,28 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent ) dlist.Append( new SCH_TEXT( wxPoint( 0, 0 ), text ) ); } + bool forceKeepAnnotations = false; + bool forceDropAnnotations = false; + bool dropAnnotations = false; + + if( aEvent.IsAction( &ACTIONS::pasteSpecial ) ) + { + DIALOG_PASTE_SPECIAL dlg( m_frame, &forceKeepAnnotations, &forceDropAnnotations ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return 0; + } + + if( forceDropAnnotations ) + dropAnnotations = true; + // SCH_LEGACY_PLUGIN added the items to the DLIST, but not to the view or anything // else. Pull them back out to start with. // - EDA_ITEMS loadedItems; - SCH_ITEM* next = nullptr; + SCH_ITEM* firstNew = lastExisting ? lastExisting->Next() : dlist.GetFirst(); + EDA_ITEMS loadedItems; + SCH_ITEM* next = nullptr; - // We also make sure any pasted sheets will not cause recursion in the destination. - // Moreover new sheets create new sheetpaths, and component alternate references must - // be created and cleared - // bool sheetsPasted = false; SCH_SHEET_LIST hierarchy( g_RootSheet ); wxFileName destFn = g_CurrentSheet->Last()->GetFileName(); @@ -980,7 +992,7 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent ) if( destFn.IsRelative() ) destFn.MakeAbsolute( m_frame->Prj().GetProjectPath() ); - for( SCH_ITEM* item = last ? last->Next() : dlist.GetFirst(); item; item = next ) + for( SCH_ITEM* item = firstNew; item; item = next ) { next = item->Next(); dlist.Remove( item ); @@ -989,16 +1001,16 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent ) if( item->Type() == SCH_COMPONENT_T ) { - SCH_COMPONENT* component = (SCH_COMPONENT*) item; - - component->SetTimeStamp( GetNewTimeStamp() ); - - // clear the annotation, but preserve the selected unit - int unit = component->GetUnit(); - component->ClearAnnotation( nullptr ); - component->SetUnit( unit ); + if( !dropAnnotations && !forceKeepAnnotations ) + { + for( SCH_ITEM* temp = dlist.GetFirst(); temp != lastExisting; temp = temp->Next() ) + { + if( item->GetTimeStamp() == temp->GetTimeStamp() ) + dropAnnotations = true; + } + } } - if( item->Type() == SCH_SHEET_T ) + else if( item->Type() == SCH_SHEET_T ) { SCH_SHEET* sheet = (SCH_SHEET*) item; wxFileName srcFn = sheet->GetFileName(); @@ -1017,18 +1029,6 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent ) DisplayError( m_frame, msg ); loadedItems.pop_back(); } - else - { - // Duplicate sheet names and sheet time stamps are not valid. Use a time stamp - // based sheet name and update the time stamp for each sheet in the block. - timestamp_t uid = GetNewTimeStamp(); - - sheet->SetName( wxString::Format( wxT( "sheet%8.8lX" ), (unsigned long)uid ) ); - sheet->SetTimeStamp( uid ); - sheet->SetParent( g_CurrentSheet->Last() ); - sheet->SetScreen( nullptr ); - sheetsPasted = true; - } } } @@ -1044,6 +1044,17 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent ) if( item->Type() == SCH_COMPONENT_T ) { SCH_COMPONENT* component = (SCH_COMPONENT*) item; + + if( dropAnnotations ) + { + component->SetTimeStamp( GetNewTimeStamp() ); + + // clear the annotation, but preserve the selected unit + int unit = component->GetUnit(); + component->ClearAnnotation( nullptr ); + component->SetUnit( unit ); + } + component->Resolve( *symLibTable, partLib ); component->UpdatePins(); } @@ -1052,6 +1063,17 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent ) SCH_SHEET* sheet = (SCH_SHEET*) item; wxFileName fn = sheet->GetFileName(); SCH_SCREEN* existingScreen = nullptr; + bool dropSheetAnnotations = false; + + // Duplicate sheet names and timestamps are not valid. Generate new timestamps + // and timestamp-based sheet names. + timestamp_t uid = GetNewTimeStamp(); + + sheet->SetName( wxString::Format( wxT( "sheet%8.8lX" ), (unsigned long)uid ) ); + sheet->SetTimeStamp( uid ); + sheet->SetParent( g_CurrentSheet->Last() ); + sheet->SetScreen( nullptr ); + sheetsPasted = true; if( !fn.IsAbsolute() ) { @@ -1059,8 +1081,12 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent ) fn.Normalize( wxPATH_NORM_ALL, currentSheetFileName.GetPath() ); } - if( g_RootSheet->SearchHierarchy( fn.GetFullPath( wxPATH_UNIX ), &existingScreen ) - || searchSupplementaryClipboard( sheet->GetFileName(), &existingScreen ) ) + if( g_RootSheet->SearchHierarchy( fn.GetFullPath( wxPATH_UNIX ), &existingScreen ) ) + dropSheetAnnotations = true; + else + searchSupplementaryClipboard( sheet->GetFileName(), &existingScreen ); + + if( existingScreen ) { sheet->SetScreen( existingScreen ); @@ -1072,7 +1098,9 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent ) // Otherwise ClearAnnotation do nothing, because the F1 field is used as // reference default value and takes the latest displayed value existingScreen->EnsureAlternateReferencesExist(); - existingScreen->ClearAnnotation( &sheetpath ); + + if( forceDropAnnotations || dropSheetAnnotations ) + existingScreen->ClearAnnotation( &sheetpath ); } else { @@ -1318,6 +1346,7 @@ void SCH_EDITOR_CONTROL::setTransitions() Go( &SCH_EDITOR_CONTROL::Cut, ACTIONS::cut.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::Copy, ACTIONS::copy.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::Paste, ACTIONS::paste.MakeEvent() ); + Go( &SCH_EDITOR_CONTROL::Paste, ACTIONS::pasteSpecial.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::EditWithLibEdit, EE_ACTIONS::editWithLibEdit.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::ShowCvpcb, EE_ACTIONS::assignFootprints.MakeEvent() ); diff --git a/include/tool/actions.h b/include/tool/actions.h index 3859ed2305..4d4759c569 100644 --- a/include/tool/actions.h +++ b/include/tool/actions.h @@ -69,6 +69,7 @@ public: static TOOL_ACTION cut; static TOOL_ACTION copy; static TOOL_ACTION paste; + static TOOL_ACTION pasteSpecial; static TOOL_ACTION duplicate; static TOOL_ACTION doDelete; // sadly 'delete' is a reserved word static TOOL_ACTION deleteTool;