Implement Paste Special for eeschema.

Also changes the normal paste behaviour to only clear annotations
when a collision is found.

Fixes: lp:1837002
* https://bugs.launchpad.net/kicad/+bug/1837002
This commit is contained in:
Jeff Young 2019-09-02 19:23:46 +01:00
parent a675b8e3b2
commit fc50ddda64
11 changed files with 659 additions and 33 deletions

View File

@ -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" ),

View File

@ -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

View File

@ -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 <dialog_paste_special.h>
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;
}

View File

@ -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 <dialog_paste_special_base.h>
#include <widgets/unit_binder.h>
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

View File

@ -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 );
}

View File

@ -0,0 +1,343 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="15" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">dialog_paste_special_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">dialog_paste_special</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center">wxBOTH</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size">-1,-1</property>
<property name="name">DIALOG_PASTE_SPECIAL_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Paste Special</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">m_mainSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">optionsSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Paste Options</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticText7</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Keep existing annotations, even if they are duplicated</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_keepAnnotations</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">OnKeepAnnotations</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Clear annotations on pasted items</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_dropAnnotations</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">OnDropAnnotations</event>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxStaticLine" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticline1</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxLI_HORIZONTAL</property>
<property name="subclass">; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">6</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStdDialogButtonSizer" expanded="1">
<property name="Apply">0</property>
<property name="Cancel">1</property>
<property name="ContextHelp">0</property>
<property name="Help">0</property>
<property name="No">0</property>
<property name="OK">1</property>
<property name="Save">0</property>
<property name="Yes">0</property>
<property name="minimum_size"></property>
<property name="name">m_sdbSizer</property>
<property name="permission">protected</property>
<event name="OnOKButtonClick">onOKButton</event>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -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 <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
#include "dialog_shim.h"
#include <wx/string.h>
#include <wx/stattext.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/checkbox.h>
#include <wx/sizer.h>
#include <wx/statline.h>
#include <wx/button.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// 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();
};

View File

@ -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 );

View File

@ -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;

View File

@ -50,7 +50,7 @@
#include <dialogs/dialog_page_settings.h>
#include <dialogs/dialog_fields_editor_global.h>
#include <invoke_sch_dialog.h>
#include <dialogs/dialog_paste_special.h>
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<EE_SELECTION_TOOL>();
DLIST<SCH_ITEM>& 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() );

View File

@ -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;