eeschema: Duplicate() is a Copy() followed by a Paste()

The only subtle difference is that Duplicate() does not modify the
clipboard contents so we need to keep a local variable in which to
store the result of a Copy()
This commit is contained in:
Roberto Fernandez Bautista 2021-05-21 17:43:34 +01:00
parent 2131a44889
commit 5cf3e6d31a
4 changed files with 29 additions and 135 deletions

View File

@ -795,135 +795,6 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
} }
static KICAD_T duplicatableItems[] =
{
SCH_JUNCTION_T,
SCH_LINE_T,
SCH_BUS_BUS_ENTRY_T,
SCH_BUS_WIRE_ENTRY_T,
SCH_TEXT_T,
SCH_LABEL_T,
SCH_GLOBAL_LABEL_T,
SCH_HIER_LABEL_T,
SCH_NO_CONNECT_T,
SCH_SHEET_T,
SCH_COMPONENT_T,
EOT
};
int SCH_EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
{
EE_SELECTION& selection = m_selectionTool->RequestSelection( duplicatableItems );
if( selection.GetSize() == 0 )
return 0;
// Doing a duplicate of a new object doesn't really make any sense; we'd just end
// up dragging around a stack of objects...
if( selection.Front()->IsNew() )
return 0;
EDA_ITEMS newItems;
// Keep track of existing sheet paths. Duplicating a selection can modify this list
bool copiedSheets = false;
SCH_SHEET_LIST initial_sheetpathList = m_frame->Schematic().GetSheets();
for( unsigned ii = 0; ii < selection.GetSize(); ++ii )
{
SCH_ITEM* oldItem = static_cast<SCH_ITEM*>( selection.GetItem( ii ) );
SCH_ITEM* newItem = oldItem->Duplicate();
newItem->SetFlags( IS_NEW );
newItems.push_back( newItem );
saveCopyInUndoList( newItem, UNDO_REDO::NEWITEM, ii > 0 );
switch( newItem->Type() )
{
case SCH_JUNCTION_T:
case SCH_LINE_T:
case SCH_BUS_BUS_ENTRY_T:
case SCH_BUS_WIRE_ENTRY_T:
case SCH_TEXT_T:
case SCH_LABEL_T:
case SCH_GLOBAL_LABEL_T:
case SCH_HIER_LABEL_T:
case SCH_NO_CONNECT_T:
newItem->SetParent( m_frame->GetScreen() );
m_frame->AddToScreen( newItem, m_frame->GetScreen() );
break;
case SCH_SHEET_T:
{
SCH_SHEET_LIST hierarchy = m_frame->Schematic().GetSheets();
SCH_SHEET* sheet = (SCH_SHEET*) newItem;
SCH_FIELD& nameField = sheet->GetFields()[SHEETNAME];
wxString baseName = nameField.GetText();
wxString number;
while( !baseName.IsEmpty() && wxIsdigit( baseName.Last() ) )
{
number = baseName.Last() + number;
baseName.RemoveLast();
}
int uniquifier = std::max( 0, wxAtoi( number ) ) + 1;
wxString candidateName = wxString::Format( wxT( "%s%d" ), baseName, uniquifier++ );
while( hierarchy.NameExists( candidateName ) )
candidateName = wxString::Format( wxT( "%s%d" ), baseName, uniquifier++ );
nameField.SetText( candidateName );
sheet->SetParent( m_frame->GetCurrentSheet().Last() );
SCH_SHEET_PATH sheetpath = m_frame->GetCurrentSheet();
sheetpath.push_back( sheet );
int page = 1;
wxString pageNum = wxString::Format( "%d", page );
while( hierarchy.PageNumberExists( pageNum ) )
pageNum = wxString::Format( "%d", ++page );
sheet->AddInstance( sheetpath.Path() );
sheet->SetPageNumber( sheetpath, pageNum );
m_frame->AddToScreen( sheet, m_frame->GetScreen() );
copiedSheets = true;
break;
}
case SCH_COMPONENT_T:
{
SCH_COMPONENT* symbol = (SCH_COMPONENT*) newItem;
symbol->ClearAnnotation( NULL );
symbol->SetParent( m_frame->GetScreen() );
m_frame->AddToScreen( symbol, m_frame->GetScreen() );
break;
}
default:
break;
}
}
if( copiedSheets )
{
// We clear annotation of new sheet paths.
// Annotation of new symbols added in current sheet is already cleared.
SCH_SCREENS screensList( &m_frame->Schematic().Root() );
screensList.ClearAnnotationOfNewSheetPaths( initial_sheetpathList );
m_frame->SetSheetNumberAndCount();
}
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
m_toolMgr->RunAction( EE_ACTIONS::addItemsToSel, true, &newItems );
m_toolMgr->RunAction( EE_ACTIONS::move, false );
return 0;
}
int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent ) int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
{ {
SCH_ITEM* sourceItem = m_frame->GetRepeatItem(); SCH_ITEM* sourceItem = m_frame->GetRepeatItem();
@ -1848,7 +1719,6 @@ int SCH_EDIT_TOOL::EditPageNumber( const TOOL_EVENT& aEvent )
void SCH_EDIT_TOOL::setTransitions() void SCH_EDIT_TOOL::setTransitions()
{ {
Go( &SCH_EDIT_TOOL::Duplicate, ACTIONS::duplicate.MakeEvent() );
Go( &SCH_EDIT_TOOL::RepeatDrawItem, EE_ACTIONS::repeatDrawItem.MakeEvent() ); Go( &SCH_EDIT_TOOL::RepeatDrawItem, EE_ACTIONS::repeatDrawItem.MakeEvent() );
Go( &SCH_EDIT_TOOL::Rotate, EE_ACTIONS::rotateCW.MakeEvent() ); Go( &SCH_EDIT_TOOL::Rotate, EE_ACTIONS::rotateCW.MakeEvent() );
Go( &SCH_EDIT_TOOL::Rotate, EE_ACTIONS::rotateCCW.MakeEvent() ); Go( &SCH_EDIT_TOOL::Rotate, EE_ACTIONS::rotateCCW.MakeEvent() );

View File

@ -45,7 +45,6 @@ public:
int Rotate( const TOOL_EVENT& aEvent ); int Rotate( const TOOL_EVENT& aEvent );
int Mirror( const TOOL_EVENT& aEvent ); int Mirror( const TOOL_EVENT& aEvent );
int Duplicate( const TOOL_EVENT& aEvent );
int RepeatDrawItem( const TOOL_EVENT& aEvent ); int RepeatDrawItem( const TOOL_EVENT& aEvent );
int Properties( const TOOL_EVENT& aEvent ); int Properties( const TOOL_EVENT& aEvent );

View File

@ -1222,7 +1222,7 @@ int SCH_EDITOR_CONTROL::Redo( const TOOL_EVENT& aEvent )
} }
bool SCH_EDITOR_CONTROL::doCopy() bool SCH_EDITOR_CONTROL::doCopy( bool aUseLocalClipboard )
{ {
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>(); EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
EE_SELECTION& selection = selTool->RequestSelection(); EE_SELECTION& selection = selTool->RequestSelection();
@ -1250,6 +1250,12 @@ bool SCH_EDITOR_CONTROL::doCopy()
plugin.Format( &selection, &selPath, &hiearchy, &formatter ); plugin.Format( &selection, &selPath, &hiearchy, &formatter );
if( aUseLocalClipboard )
{
m_localClipboard = formatter.GetString();
return true;
}
return m_toolMgr->SaveClipboard( formatter.GetString() ); return m_toolMgr->SaveClipboard( formatter.GetString() );
} }
@ -1267,6 +1273,15 @@ bool SCH_EDITOR_CONTROL::searchSupplementaryClipboard( const wxString& aSheetFil
} }
int SCH_EDITOR_CONTROL::Duplicate( const TOOL_EVENT& aEvent )
{
doCopy( true ); // Use the local clipboard
Paste( aEvent );
return 0;
}
int SCH_EDITOR_CONTROL::Cut( const TOOL_EVENT& aEvent ) int SCH_EDITOR_CONTROL::Cut( const TOOL_EVENT& aEvent )
{ {
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() ); wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wxWindow::FindFocus() );
@ -1426,7 +1441,12 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
} }
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>(); EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
std::string text = m_toolMgr->GetClipboardUTF8(); std::string text;
if( aEvent.IsAction( &ACTIONS::duplicate ) )
text = m_localClipboard;
else
text = m_toolMgr->GetClipboardUTF8();
if( text.empty() ) if( text.empty() )
return 0; return 0;
@ -1990,6 +2010,7 @@ void SCH_EDITOR_CONTROL::setTransitions()
Go( &SCH_EDITOR_CONTROL::Copy, ACTIONS::copy.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::Copy, ACTIONS::copy.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::Paste, ACTIONS::paste.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::Paste, ACTIONS::paste.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::Paste, ACTIONS::pasteSpecial.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::Paste, ACTIONS::pasteSpecial.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::Duplicate, ACTIONS::duplicate.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::EditWithSymbolEditor, EE_ACTIONS::editWithLibEdit.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::EditWithSymbolEditor, EE_ACTIONS::editWithLibEdit.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::ShowCvpcb, EE_ACTIONS::assignFootprints.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::ShowCvpcb, EE_ACTIONS::assignFootprints.MakeEvent() );

View File

@ -111,6 +111,7 @@ public:
int Cut( const TOOL_EVENT& aEvent ); int Cut( const TOOL_EVENT& aEvent );
int Copy( const TOOL_EVENT& aEvent ); int Copy( const TOOL_EVENT& aEvent );
int Paste( const TOOL_EVENT& aEvent ); int Paste( const TOOL_EVENT& aEvent );
int Duplicate( const TOOL_EVENT& aEvent );
int EditWithSymbolEditor( const TOOL_EVENT& aEvent ); int EditWithSymbolEditor( const TOOL_EVENT& aEvent );
int ShowCvpcb( const TOOL_EVENT& aEvent ); int ShowCvpcb( const TOOL_EVENT& aEvent );
@ -150,8 +151,8 @@ public:
SCH_SEARCH_T aSearchType, const wxString& aSearchText ); SCH_SEARCH_T aSearchType, const wxString& aSearchText );
private: private:
///< copy selection to clipboard ///< copy selection to clipboard or to m_localClipboard if aUseLocalClipboard is true
bool doCopy(); bool doCopy( bool aUseLocalClipboard = false );
bool rescueProject( RESCUER& aRescuer, bool aRunningOnDemand ); bool rescueProject( RESCUER& aRescuer, bool aRunningOnDemand );
@ -211,6 +212,9 @@ private:
bool m_probingPcbToSch; // Recursion guard when cross-probing to PcbNew bool m_probingPcbToSch; // Recursion guard when cross-probing to PcbNew
EDA_ITEM* m_pickerItem; // Current item for picker highlighting. EDA_ITEM* m_pickerItem; // Current item for picker highlighting.
// Temporary storage location for Duplicate action
std::string m_localClipboard;
// A map of sheet filename --> screens for the clipboard contents. We use these to hook up // A map of sheet filename --> screens for the clipboard contents. We use these to hook up
// cut/paste operations for unsaved sheet content. // cut/paste operations for unsaved sheet content.
std::map<wxString, SCH_SCREEN*> m_supplementaryClipboard; std::map<wxString, SCH_SCREEN*> m_supplementaryClipboard;