mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-11 14:50:11 +00:00
Add 'Copy as Text' action
This is useful when you want to copy text content out to some external program (or put it in a text item/box). I'm not sure it's possible to intuit exactly what a user wants, as you will often want to copy items as the real items, and sometimes as text. While KiCad might be able to make a smart guess, external programs will have no chance!
This commit is contained in:
parent
d9890e38ff
commit
b0043587c2
common/tool
eeschema
include/tool
pcbnew/tools
@ -228,6 +228,15 @@ TOOL_ACTION ACTIONS::copy( TOOL_ACTION_ARGS()
|
||||
.Flags( AF_NONE )
|
||||
.UIId( wxID_COPY ) );
|
||||
|
||||
TOOL_ACTION ACTIONS::copyAsText( TOOL_ACTION_ARGS()
|
||||
.Name( "common.Interactive.copyAsText" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.DefaultHotkey( MD_CTRL + MD_SHIFT + 'C' )
|
||||
.FriendlyName( _( "Copy as Text" ) )
|
||||
.Tooltip( _( "Copy selected item(s) to clipboard as text" ) )
|
||||
.Icon( BITMAPS::copy )
|
||||
.Flags( AF_NONE ) );
|
||||
|
||||
TOOL_ACTION ACTIONS::paste( TOOL_ACTION_ARGS()
|
||||
.Name( "common.Interactive.paste" )
|
||||
.Scope( AS_GLOBAL )
|
||||
|
@ -447,6 +447,7 @@ set( EESCHEMA_SRCS
|
||||
tools/ee_point_editor.cpp
|
||||
tools/ee_selection.cpp
|
||||
tools/ee_selection_tool.cpp
|
||||
tools/ee_tool_utils.cpp
|
||||
tools/rule_area_create_helper.cpp
|
||||
tools/sch_drawing_tools.cpp
|
||||
tools/sch_design_block_control.cpp
|
||||
|
@ -146,6 +146,7 @@ void SCH_EDIT_FRAME::doReCreateMenuBar()
|
||||
editMenu->AppendSeparator();
|
||||
editMenu->Add( ACTIONS::cut );
|
||||
editMenu->Add( ACTIONS::copy );
|
||||
editMenu->Add( ACTIONS::copyAsText );
|
||||
editMenu->Add( ACTIONS::paste );
|
||||
editMenu->Add( ACTIONS::pasteSpecial );
|
||||
editMenu->Add( ACTIONS::doDelete );
|
||||
|
@ -645,6 +645,7 @@ void SCH_EDIT_FRAME::setupUIConditions()
|
||||
|
||||
mgr->SetConditions( ACTIONS::cut, ENABLE( hasElements ) );
|
||||
mgr->SetConditions( ACTIONS::copy, ENABLE( hasElements ) );
|
||||
mgr->SetConditions( ACTIONS::copyAsText, ENABLE( hasElements ) );
|
||||
mgr->SetConditions( ACTIONS::paste, ENABLE( SELECTION_CONDITIONS::Idle && cond.NoActiveTool() ) );
|
||||
mgr->SetConditions( ACTIONS::pasteSpecial, ENABLE( SELECTION_CONDITIONS::Idle && cond.NoActiveTool() ) );
|
||||
mgr->SetConditions( ACTIONS::doDelete, ENABLE( hasElements ) );
|
||||
|
@ -96,6 +96,7 @@ void SYMBOL_EDIT_FRAME::doReCreateMenuBar()
|
||||
editMenu->AppendSeparator();
|
||||
editMenu->Add( ACTIONS::cut );
|
||||
editMenu->Add( ACTIONS::copy );
|
||||
editMenu->Add( ACTIONS::copyAsText );
|
||||
editMenu->Add( ACTIONS::paste );
|
||||
editMenu->Add( ACTIONS::doDelete );
|
||||
editMenu->Add( ACTIONS::duplicate );
|
||||
|
@ -490,6 +490,7 @@ void SYMBOL_EDIT_FRAME::setupUIConditions()
|
||||
|
||||
mgr->SetConditions( ACTIONS::cut, ENABLE( isEditableCond ) );
|
||||
mgr->SetConditions( ACTIONS::copy, ENABLE( haveSymbolCond ) );
|
||||
mgr->SetConditions( ACTIONS::copyAsText, ENABLE( haveSymbolCond ) );
|
||||
mgr->SetConditions( ACTIONS::paste, ENABLE( isEditableCond &&
|
||||
SELECTION_CONDITIONS::Idle && cond.NoActiveTool() ) );
|
||||
mgr->SetConditions( ACTIONS::doDelete, ENABLE( isEditableCond ) );
|
||||
|
126
eeschema/tools/ee_tool_utils.cpp
Normal file
126
eeschema/tools/ee_tool_utils.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "ee_tool_utils.h"
|
||||
|
||||
#include <sch_text.h>
|
||||
#include <sch_field.h>
|
||||
#include <sch_pin.h>
|
||||
#include <sch_table.h>
|
||||
#include <sch_tablecell.h>
|
||||
#include <sch_textbox.h>
|
||||
|
||||
#include <wx/arrstr.h>
|
||||
|
||||
wxString GetSchItemAsText( const SCH_ITEM& aItem )
|
||||
{
|
||||
switch( aItem.Type() )
|
||||
{
|
||||
case SCH_TEXT_T:
|
||||
case SCH_LABEL_T:
|
||||
case SCH_HIER_LABEL_T:
|
||||
case SCH_GLOBAL_LABEL_T:
|
||||
case SCH_DIRECTIVE_LABEL_T:
|
||||
case SCH_SHEET_PIN_T:
|
||||
{
|
||||
const SCH_TEXT& text = static_cast<const SCH_TEXT&>( aItem );
|
||||
return text.GetShownText( true );
|
||||
}
|
||||
case SCH_FIELD_T:
|
||||
{
|
||||
// Goes via EDA_TEXT
|
||||
const SCH_FIELD& field = static_cast<const SCH_FIELD&>( aItem );
|
||||
return field.GetShownText( true );
|
||||
}
|
||||
case SCH_TEXTBOX_T:
|
||||
case SCH_TABLECELL_T:
|
||||
{
|
||||
// Also EDA_TEXT
|
||||
const SCH_TEXTBOX& textbox = static_cast<const SCH_TEXTBOX&>( aItem );
|
||||
return textbox.GetShownText( true );
|
||||
}
|
||||
case SCH_PIN_T:
|
||||
{
|
||||
// This is a choice - probably the name makes more sense than the number
|
||||
// (or should it be name/number?)
|
||||
const SCH_PIN& pin = static_cast<const SCH_PIN&>( aItem );
|
||||
return pin.GetShownName();
|
||||
}
|
||||
case SCH_TABLE_T:
|
||||
{
|
||||
// A simple tabbed list of the cells seems like a place to start here
|
||||
const SCH_TABLE& table = static_cast<const SCH_TABLE&>( aItem );
|
||||
wxString s;
|
||||
|
||||
for( int row = 0; row < table.GetRowCount(); ++row )
|
||||
{
|
||||
for( int col = 0; col < table.GetColCount(); ++col )
|
||||
{
|
||||
const SCH_TABLECELL* cell = table.GetCell( row, col );
|
||||
s << cell->GetShownText( true );
|
||||
|
||||
if( col < table.GetColCount() - 1 )
|
||||
{
|
||||
s << '\t';
|
||||
}
|
||||
}
|
||||
|
||||
if( row < table.GetRowCount() - 1 )
|
||||
{
|
||||
s << '\n';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return wxEmptyString;
|
||||
};
|
||||
|
||||
|
||||
wxString GetSelectedItemsAsText( const SELECTION& aSel )
|
||||
{
|
||||
wxArrayString itemTexts;
|
||||
|
||||
for( EDA_ITEM* item : aSel )
|
||||
{
|
||||
if( item->IsSCH_ITEM() )
|
||||
{
|
||||
const SCH_ITEM& schItem = static_cast<const SCH_ITEM&>( *item );
|
||||
wxString itemText = GetSchItemAsText( schItem );
|
||||
|
||||
itemText.Trim( false ).Trim( true );
|
||||
|
||||
if( !itemText.IsEmpty() )
|
||||
{
|
||||
itemTexts.Add( std::move( itemText ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wxJoin( itemTexts, '\n', '\0' );
|
||||
}
|
31
eeschema/tools/ee_tool_utils.h
Normal file
31
eeschema/tools/ee_tool_utils.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sch_item.h>
|
||||
#include <tool/selection.h>
|
||||
|
||||
wxString GetSchItemAsText( const SCH_ITEM& aItem );
|
||||
|
||||
wxString GetSelectedItemsAsText( const SELECTION& aSel );
|
@ -587,6 +587,20 @@ bool SCH_EDIT_TOOL::Init()
|
||||
return menu;
|
||||
};
|
||||
|
||||
const auto canCopyText = EE_CONDITIONS::OnlyTypes( {
|
||||
SCH_TEXT_T,
|
||||
SCH_TEXTBOX_T,
|
||||
SCH_FIELD_T,
|
||||
SCH_LABEL_T,
|
||||
SCH_HIER_LABEL_T,
|
||||
SCH_GLOBAL_LABEL_T,
|
||||
SCH_DIRECTIVE_LABEL_T,
|
||||
SCH_SHEET_PIN_T,
|
||||
SCH_PIN_T,
|
||||
SCH_TABLE_T,
|
||||
SCH_TABLECELL_T,
|
||||
} );
|
||||
|
||||
//
|
||||
// Add edit actions to the move tool menu
|
||||
//
|
||||
@ -605,6 +619,7 @@ bool SCH_EDIT_TOOL::Init()
|
||||
moveMenu.AddSeparator();
|
||||
moveMenu.AddItem( ACTIONS::cut, E_C::IdleSelection );
|
||||
moveMenu.AddItem( ACTIONS::copy, E_C::IdleSelection );
|
||||
moveMenu.AddItem( ACTIONS::copyAsText, canCopyText && E_C::IdleSelection );
|
||||
moveMenu.AddItem( ACTIONS::doDelete, E_C::NotEmpty );
|
||||
moveMenu.AddItem( ACTIONS::duplicate, duplicateCondition );
|
||||
|
||||
@ -665,6 +680,7 @@ bool SCH_EDIT_TOOL::Init()
|
||||
selToolMenu.AddSeparator( 300 );
|
||||
selToolMenu.AddItem( ACTIONS::cut, E_C::IdleSelection, 300 );
|
||||
selToolMenu.AddItem( ACTIONS::copy, E_C::IdleSelection, 300 );
|
||||
selToolMenu.AddItem( ACTIONS::copyAsText, canCopyText && E_C::IdleSelection, 300 );
|
||||
selToolMenu.AddItem( ACTIONS::paste, E_C::Idle, 300 );
|
||||
selToolMenu.AddItem( ACTIONS::pasteSpecial, E_C::Idle, 300 );
|
||||
selToolMenu.AddItem( ACTIONS::doDelete, E_C::NotEmpty, 300 );
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include <tools/ee_actions.h>
|
||||
#include <tools/ee_selection.h>
|
||||
#include <tools/ee_selection_tool.h>
|
||||
#include <tools/ee_tool_utils.h>
|
||||
#include <drawing_sheet/ds_proxy_undo_item.h>
|
||||
#include <eda_list_dialog.h>
|
||||
#include <view/view_controls.h>
|
||||
@ -1397,6 +1398,23 @@ int SCH_EDITOR_CONTROL::Copy( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
|
||||
|
||||
int SCH_EDITOR_CONTROL::CopyAsText( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
|
||||
EE_SELECTION& selection = selTool->RequestSelection();
|
||||
|
||||
if( selection.Empty() )
|
||||
return false;
|
||||
|
||||
wxString itemsAsText = GetSelectedItemsAsText( selection );
|
||||
|
||||
if( selection.IsHover() )
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection );
|
||||
|
||||
return m_toolMgr->SaveClipboard( itemsAsText.ToStdString() );
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDITOR_CONTROL::updatePastedSymbol( SCH_SYMBOL* aSymbol,
|
||||
const SCH_SHEET_PATH& aPastePath,
|
||||
const KIID_PATH& aClipPath,
|
||||
@ -2812,6 +2830,7 @@ void SCH_EDITOR_CONTROL::setTransitions()
|
||||
Go( &SCH_EDITOR_CONTROL::Redo, ACTIONS::redo.MakeEvent() );
|
||||
Go( &SCH_EDITOR_CONTROL::Cut, ACTIONS::cut.MakeEvent() );
|
||||
Go( &SCH_EDITOR_CONTROL::Copy, ACTIONS::copy.MakeEvent() );
|
||||
Go( &SCH_EDITOR_CONTROL::CopyAsText, ACTIONS::copyAsText.MakeEvent() );
|
||||
Go( &SCH_EDITOR_CONTROL::Paste, ACTIONS::paste.MakeEvent() );
|
||||
Go( &SCH_EDITOR_CONTROL::Paste, ACTIONS::pasteSpecial.MakeEvent() );
|
||||
Go( &SCH_EDITOR_CONTROL::Duplicate, ACTIONS::duplicate.MakeEvent() );
|
||||
|
@ -108,6 +108,7 @@ public:
|
||||
///< Clipboard support.
|
||||
int Cut( const TOOL_EVENT& aEvent );
|
||||
int Copy( const TOOL_EVENT& aEvent );
|
||||
int CopyAsText( const TOOL_EVENT& aEvent );
|
||||
int Paste( const TOOL_EVENT& aEvent );
|
||||
int Duplicate( const TOOL_EVENT& aEvent );
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <tool/picker_tool.h>
|
||||
#include <tools/ee_selection_tool.h>
|
||||
#include <tools/ee_tool_utils.h>
|
||||
#include <tools/symbol_editor_pin_tool.h>
|
||||
#include <tools/symbol_editor_drawing_tools.h>
|
||||
#include <tools/symbol_editor_move_tool.h>
|
||||
@ -86,6 +87,15 @@ bool SYMBOL_EDITOR_EDIT_TOOL::Init()
|
||||
return true;
|
||||
};
|
||||
|
||||
const auto canCopyText = EE_CONDITIONS::OnlyTypes( {
|
||||
SCH_TEXT_T,
|
||||
SCH_TEXTBOX_T,
|
||||
SCH_FIELD_T,
|
||||
SCH_PIN_T,
|
||||
SCH_TABLE_T,
|
||||
SCH_TABLECELL_T,
|
||||
} );
|
||||
|
||||
// Add edit actions to the move tool menu
|
||||
if( moveTool )
|
||||
{
|
||||
@ -103,6 +113,7 @@ bool SYMBOL_EDITOR_EDIT_TOOL::Init()
|
||||
moveMenu.AddSeparator( 300 );
|
||||
moveMenu.AddItem( ACTIONS::cut, EE_CONDITIONS::IdleSelection, 300 );
|
||||
moveMenu.AddItem( ACTIONS::copy, EE_CONDITIONS::IdleSelection, 300 );
|
||||
moveMenu.AddItem( ACTIONS::copyAsText, canCopyText && EE_CONDITIONS::IdleSelection, 300 );
|
||||
moveMenu.AddItem( ACTIONS::duplicate, canEdit && EE_CONDITIONS::NotEmpty, 300 );
|
||||
moveMenu.AddItem( ACTIONS::doDelete, canEdit && EE_CONDITIONS::NotEmpty, 200 );
|
||||
|
||||
@ -136,6 +147,7 @@ bool SYMBOL_EDITOR_EDIT_TOOL::Init()
|
||||
selToolMenu.AddSeparator( 300 );
|
||||
selToolMenu.AddItem( ACTIONS::cut, EE_CONDITIONS::IdleSelection, 300 );
|
||||
selToolMenu.AddItem( ACTIONS::copy, EE_CONDITIONS::IdleSelection, 300 );
|
||||
selToolMenu.AddItem( ACTIONS::copyAsText, canCopyText && EE_CONDITIONS::IdleSelection, 300 );
|
||||
selToolMenu.AddItem( ACTIONS::paste, canEdit && EE_CONDITIONS::Idle, 300 );
|
||||
selToolMenu.AddItem( ACTIONS::duplicate, canEdit && EE_CONDITIONS::NotEmpty, 300 );
|
||||
selToolMenu.AddItem( ACTIONS::doDelete, canEdit && EE_CONDITIONS::NotEmpty, 300 );
|
||||
@ -898,6 +910,23 @@ int SYMBOL_EDITOR_EDIT_TOOL::Copy( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
|
||||
|
||||
int SYMBOL_EDITOR_EDIT_TOOL::CopyAsText( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
|
||||
EE_SELECTION& selection = selTool->RequestSelection();
|
||||
|
||||
if( selection.Empty() )
|
||||
return 0;
|
||||
|
||||
wxString itemsAsText = GetSelectedItemsAsText( selection );
|
||||
|
||||
if( selection.IsHover() )
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection );
|
||||
|
||||
return m_toolMgr->SaveClipboard( itemsAsText.ToStdString() );
|
||||
}
|
||||
|
||||
|
||||
int SYMBOL_EDITOR_EDIT_TOOL::Paste( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
|
||||
@ -1051,10 +1080,12 @@ int SYMBOL_EDITOR_EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
|
||||
|
||||
void SYMBOL_EDITOR_EDIT_TOOL::setTransitions()
|
||||
{
|
||||
// clang-format off
|
||||
Go( &SYMBOL_EDITOR_EDIT_TOOL::Undo, ACTIONS::undo.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_EDIT_TOOL::Redo, ACTIONS::redo.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_EDIT_TOOL::Cut, ACTIONS::cut.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_EDIT_TOOL::Copy, ACTIONS::copy.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_EDIT_TOOL::CopyAsText, ACTIONS::copyAsText.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_EDIT_TOOL::Paste, ACTIONS::paste.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_EDIT_TOOL::Duplicate, ACTIONS::duplicate.MakeEvent() );
|
||||
|
||||
@ -1071,4 +1102,5 @@ void SYMBOL_EDITOR_EDIT_TOOL::setTransitions()
|
||||
Go( &SYMBOL_EDITOR_EDIT_TOOL::PinTable, EE_ACTIONS::pinTable.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_EDIT_TOOL::UpdateSymbolFields, EE_ACTIONS::updateSymbolFields.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_EDIT_TOOL::SetUnitDisplayName, EE_ACTIONS::setUnitDisplayName.MakeEvent() );
|
||||
// clang-format on
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ public:
|
||||
int Redo( const TOOL_EVENT& aEvent );
|
||||
int Cut( const TOOL_EVENT& aEvent );
|
||||
int Copy( const TOOL_EVENT& aEvent );
|
||||
int CopyAsText( const TOOL_EVENT& aEvent );
|
||||
int Paste( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
static TOOL_ACTION redo;
|
||||
static TOOL_ACTION cut;
|
||||
static TOOL_ACTION copy;
|
||||
static TOOL_ACTION copyAsText;
|
||||
static TOOL_ACTION paste;
|
||||
static TOOL_ACTION pasteSpecial;
|
||||
static TOOL_ACTION selectAll;
|
||||
|
@ -326,6 +326,20 @@ bool EDIT_TOOL::Init()
|
||||
return frame()->IsCurrentTool( PCB_ACTIONS::moveIndividually );
|
||||
};
|
||||
|
||||
const auto canCopyAsText = SELECTION_CONDITIONS::NotEmpty
|
||||
&& SELECTION_CONDITIONS::OnlyTypes( {
|
||||
PCB_FIELD_T,
|
||||
PCB_TEXT_T,
|
||||
PCB_TEXTBOX_T,
|
||||
PCB_DIM_ALIGNED_T,
|
||||
PCB_DIM_LEADER_T,
|
||||
PCB_DIM_CENTER_T,
|
||||
PCB_DIM_RADIAL_T,
|
||||
PCB_DIM_ORTHOGONAL_T,
|
||||
PCB_TABLE_T,
|
||||
PCB_TABLECELL_T,
|
||||
} );
|
||||
|
||||
// Add context menu entries that are displayed when selection tool is active
|
||||
CONDITIONAL_MENU& menu = m_selectionTool->GetToolMenu().GetMenu();
|
||||
|
||||
@ -378,6 +392,7 @@ bool EDIT_TOOL::Init()
|
||||
menu.AddSeparator( 150 );
|
||||
menu.AddItem( ACTIONS::cut, SELECTION_CONDITIONS::NotEmpty, 150 );
|
||||
menu.AddItem( ACTIONS::copy, SELECTION_CONDITIONS::NotEmpty, 150 );
|
||||
menu.AddItem( ACTIONS::copyAsText, canCopyAsText, 150 );
|
||||
|
||||
// Selection tool handles the context menu for some other tools, such as the Picker.
|
||||
// Don't add things like Paste when another tool is active.
|
||||
@ -3195,6 +3210,102 @@ int EDIT_TOOL::copyToClipboard( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
|
||||
|
||||
int EDIT_TOOL::copyToClipboardAsText( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
PCB_SELECTION& selection = m_selectionTool->RequestSelection(
|
||||
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
|
||||
{
|
||||
// Anything unsupported will just be ignored
|
||||
},
|
||||
// No prompt for locked items
|
||||
false );
|
||||
|
||||
if( selection.IsHover() )
|
||||
m_selectionTool->ClearSelection();
|
||||
|
||||
const auto getItemText = [&]( const BOARD_ITEM& aItem ) -> wxString
|
||||
{
|
||||
switch( aItem.Type() )
|
||||
{
|
||||
case PCB_TEXT_T:
|
||||
case PCB_FIELD_T:
|
||||
case PCB_DIM_ALIGNED_T:
|
||||
case PCB_DIM_LEADER_T:
|
||||
case PCB_DIM_CENTER_T:
|
||||
case PCB_DIM_RADIAL_T:
|
||||
case PCB_DIM_ORTHOGONAL_T:
|
||||
{
|
||||
// These can all go via the PCB_TEXT class
|
||||
const PCB_TEXT& text = static_cast<const PCB_TEXT&>( aItem );
|
||||
return text.GetShownText( true );
|
||||
}
|
||||
case PCB_TEXTBOX_T:
|
||||
case PCB_TABLECELL_T:
|
||||
{
|
||||
// This one goes via EDA_TEXT
|
||||
const PCB_TEXTBOX& textBox = static_cast<const PCB_TEXTBOX&>( aItem );
|
||||
return textBox.GetShownText( true );
|
||||
}
|
||||
case PCB_TABLE_T:
|
||||
{
|
||||
const PCB_TABLE& table = static_cast<const PCB_TABLE&>( aItem );
|
||||
wxString s;
|
||||
|
||||
for( int row = 0; row < table.GetRowCount(); ++row )
|
||||
{
|
||||
for( int col = 0; col < table.GetColCount(); ++col )
|
||||
{
|
||||
const PCB_TABLECELL* cell = table.GetCell( row, col );
|
||||
s << cell->GetShownText( true );
|
||||
|
||||
if( col < table.GetColCount() - 1 )
|
||||
{
|
||||
s << '\t';
|
||||
}
|
||||
}
|
||||
|
||||
if( row < table.GetRowCount() - 1 )
|
||||
{
|
||||
s << '\n';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
default:
|
||||
// No string representation for this item type
|
||||
break;
|
||||
}
|
||||
return wxEmptyString;
|
||||
};
|
||||
|
||||
wxArrayString itemTexts;
|
||||
|
||||
for( EDA_ITEM* item : selection )
|
||||
{
|
||||
if( item->IsBOARD_ITEM() )
|
||||
{
|
||||
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
|
||||
wxString itemText = getItemText( *boardItem );
|
||||
|
||||
itemText.Trim( false ).Trim( true );
|
||||
|
||||
if( !itemText.IsEmpty() )
|
||||
{
|
||||
itemTexts.Add( std::move( itemText ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send the text to the clipboard
|
||||
if( !itemTexts.empty() )
|
||||
{
|
||||
m_toolMgr->SaveClipboard( wxJoin( itemTexts, '\n', '\0' ).ToStdString() );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int EDIT_TOOL::cutToClipboard( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( !copyToClipboard( aEvent ) )
|
||||
@ -3261,6 +3372,7 @@ void EDIT_TOOL::setTransitions()
|
||||
|
||||
Go( &EDIT_TOOL::copyToClipboard, ACTIONS::copy.MakeEvent() );
|
||||
Go( &EDIT_TOOL::copyToClipboard, PCB_ACTIONS::copyWithReference.MakeEvent() );
|
||||
Go( &EDIT_TOOL::copyToClipboardAsText, ACTIONS::copyAsText.MakeEvent() );
|
||||
Go( &EDIT_TOOL::cutToClipboard, ACTIONS::cut.MakeEvent() );
|
||||
}
|
||||
// clang-format on
|
||||
|
@ -197,6 +197,11 @@ private:
|
||||
*/
|
||||
int copyToClipboard( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Send the current selection to the clipboard as text.
|
||||
*/
|
||||
int copyToClipboardAsText( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Cut the current selection to the clipboard by formatting it as a fake pcb
|
||||
* see #AppendBoardFromClipboard for importing.
|
||||
|
Loading…
Reference in New Issue
Block a user