ADDED Duplicate Footprint, Rename Symbol and Rename Footprint.
This commit is contained in:
parent
b42365190e
commit
c6f83b6dec
|
@ -189,11 +189,12 @@ LIB_TREE_NODE_UNIT& LIB_TREE_NODE_LIB_ID::AddUnit( LIB_TREE_ITEM* aItem, int aUn
|
|||
|
||||
void LIB_TREE_NODE_LIB_ID::Update( LIB_TREE_ITEM* aItem )
|
||||
{
|
||||
// Update is called when the names match, so just update the other fields.
|
||||
|
||||
m_LibId.SetLibNickname( aItem->GetLibId().GetLibNickname() );
|
||||
m_LibId.SetLibItemName( aItem->GetName() );
|
||||
|
||||
m_Name = aItem->GetName();
|
||||
m_Desc = aItem->GetDescription();
|
||||
m_MatchName = aItem->GetName();
|
||||
|
||||
m_SearchText = aItem->GetSearchText();
|
||||
m_Normalized = false;
|
||||
|
|
|
@ -317,7 +317,7 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
|||
{
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( _( "The name '%s' conflicts with an existing entry in the library '%s'." ),
|
||||
msg.Printf( _( "Symbol name '%s' already in use in library '%s'." ),
|
||||
UnescapeString( newName ),
|
||||
libName );
|
||||
DisplayErrorMessage( this, msg );
|
||||
|
|
|
@ -1014,6 +1014,23 @@ void SYMBOL_EDIT_FRAME::RefreshLibraryTree()
|
|||
}
|
||||
|
||||
|
||||
void SYMBOL_EDIT_FRAME::FocusOnLibId( const LIB_ID& aLibID )
|
||||
{
|
||||
m_treePane->GetLibTree()->SelectLibId( aLibID );
|
||||
}
|
||||
|
||||
|
||||
void SYMBOL_EDIT_FRAME::UpdateLibraryTree( const wxDataViewItem& aTreeItem, LIB_SYMBOL* aSymbol )
|
||||
{
|
||||
if( aTreeItem.IsOk() ) // Can be not found in tree if the current footprint is imported
|
||||
// from file therefore not yet in tree.
|
||||
{
|
||||
static_cast<LIB_TREE_NODE_LIB_ID*>( aTreeItem.GetID() )->Update( aSymbol );
|
||||
m_treePane->GetLibTree()->RefreshLibTree();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SYMBOL_LIB_TABLE* SYMBOL_EDIT_FRAME::selectSymLibTable( bool aOptional )
|
||||
{
|
||||
// If no project is loaded, always work with the global table
|
||||
|
@ -1087,11 +1104,11 @@ void SYMBOL_EDIT_FRAME::storeCurrentSymbol()
|
|||
}
|
||||
|
||||
|
||||
bool SYMBOL_EDIT_FRAME::isCurrentSymbol( const LIB_ID& aLibId ) const
|
||||
bool SYMBOL_EDIT_FRAME::IsCurrentSymbol( const LIB_ID& aLibId ) const
|
||||
{
|
||||
// This will return the root symbol of any alias
|
||||
LIB_SYMBOL* symbol = m_libMgr->GetBufferedSymbol( aLibId.GetLibItemName(),
|
||||
aLibId.GetLibNickname() );
|
||||
aLibId.GetLibNickname() );
|
||||
|
||||
// Now we can compare the libId of the current symbol and the root symbol
|
||||
return ( symbol && m_symbol && symbol->GetLibId() == m_symbol->GetLibId() );
|
||||
|
|
|
@ -312,6 +312,19 @@ public:
|
|||
*/
|
||||
void RefreshLibraryTree();
|
||||
|
||||
/**
|
||||
* Update a symbol node in the library tree.
|
||||
*/
|
||||
void UpdateLibraryTree( const wxDataViewItem& aTreeItem, LIB_SYMBOL* aSymbol );
|
||||
|
||||
/**
|
||||
* Return either the symbol selected in the symbol tree (if context menu is active) or the
|
||||
* symbol on the editor canvas.
|
||||
*/
|
||||
LIB_ID GetTargetLibId() const;
|
||||
|
||||
void FocusOnLibId( const LIB_ID& aLibID );
|
||||
|
||||
/**
|
||||
* Called after the preferences dialog is run.
|
||||
*/
|
||||
|
@ -356,13 +369,12 @@ public:
|
|||
|
||||
bool IsSymbolAlias() const;
|
||||
|
||||
///< Return true if \a aLibId is an alias for the editor screen symbol.
|
||||
bool IsCurrentSymbol( const LIB_ID& aLibId ) const;
|
||||
|
||||
///< Restore the empty editor screen, without any symbol or library selected.
|
||||
void emptyScreen();
|
||||
|
||||
///< Return either the symbol selected in the symbol tree, if context menu is active or the
|
||||
///< currently modified symbol.
|
||||
LIB_ID GetTargetLibId() const;
|
||||
|
||||
protected:
|
||||
void setupUIConditions() override;
|
||||
|
||||
|
@ -469,9 +481,6 @@ private:
|
|||
///< Store the currently modified symbol in the library manager buffer.
|
||||
void storeCurrentSymbol();
|
||||
|
||||
///< Return true if \a aLibId is an alias for the editor screen symbol.
|
||||
bool isCurrentSymbol( const LIB_ID& aLibId ) const;
|
||||
|
||||
///< Rename LIB_SYMBOL aliases to avoid conflicts before adding a symbol to a library.
|
||||
void ensureUniqueName( LIB_SYMBOL* aSymbol, const wxString& aLibrary );
|
||||
|
||||
|
|
|
@ -868,7 +868,7 @@ void SYMBOL_EDIT_FRAME::DeleteSymbolFromLibrary()
|
|||
return;
|
||||
}
|
||||
|
||||
if( isCurrentSymbol( libId ) )
|
||||
if( IsCurrentSymbol( libId ) )
|
||||
emptyScreen();
|
||||
|
||||
m_libMgr->RemoveSymbol( libId.GetLibItemName(), libId.GetLibNickname() );
|
||||
|
@ -1027,7 +1027,7 @@ void SYMBOL_EDIT_FRAME::Revert( bool aConfirm )
|
|||
}
|
||||
else
|
||||
{
|
||||
reload_currentSymbol = isCurrentSymbol( libId );
|
||||
reload_currentSymbol = IsCurrentSymbol( libId );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -284,11 +284,25 @@ bool SYMBOL_LIBRARY_MANAGER::IsSymbolModified( const wxString& aAlias,
|
|||
return false;
|
||||
|
||||
const LIB_BUFFER& buf = libIt->second;
|
||||
auto symbolBuf = buf.GetBuffer( aAlias );
|
||||
const std::shared_ptr<SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER> symbolBuf = buf.GetBuffer( aAlias );
|
||||
return symbolBuf ? symbolBuf->IsModified() : false;
|
||||
}
|
||||
|
||||
|
||||
void SYMBOL_LIBRARY_MANAGER::SetSymbolModified( const wxString& aAlias,
|
||||
const wxString& aLibrary )
|
||||
{
|
||||
auto libIt = m_libs.find( aLibrary );
|
||||
|
||||
if( libIt == m_libs.end() )
|
||||
return;
|
||||
|
||||
const LIB_BUFFER& buf = libIt->second;
|
||||
std::shared_ptr<SYMBOL_LIBRARY_MANAGER::SYMBOL_BUFFER> symbolBuf = buf.GetBuffer( aAlias );
|
||||
symbolBuf->GetScreen()->SetContentModified();
|
||||
}
|
||||
|
||||
|
||||
bool SYMBOL_LIBRARY_MANAGER::ClearLibraryModified( const wxString& aLibrary ) const
|
||||
{
|
||||
auto libIt = m_libs.find( aLibrary );
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is symbol of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
|
@ -175,6 +175,8 @@ public:
|
|||
*/
|
||||
bool IsSymbolModified( const wxString& aAlias, const wxString& aLibrary ) const;
|
||||
|
||||
void SetSymbolModified( const wxString& aAlias, const wxString& aLibrary );
|
||||
|
||||
/**
|
||||
* Clear the modified flag for all symbols in a library.
|
||||
*/
|
||||
|
|
|
@ -133,6 +133,11 @@ TOOL_ACTION EE_ACTIONS::duplicateSymbol( "eeschema.SymbolLibraryControl.duplicat
|
|||
_( "Duplicate Symbol" ), _( "Make a copy of the selected symbol" ),
|
||||
BITMAPS::duplicate );
|
||||
|
||||
TOOL_ACTION EE_ACTIONS::renameSymbol( "eeschema.SymbolLibraryControl.renameFootprint",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Rename Symbol..." ), _( "Rename the selected symbol" ),
|
||||
BITMAPS::edit );
|
||||
|
||||
TOOL_ACTION EE_ACTIONS::saveSymbolAs( "eeschema.SymbolLibraryControl.saveSymbolAs",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Save As..." ), _( "Save the current symbol to a different library." ),
|
||||
|
|
|
@ -179,6 +179,7 @@ public:
|
|||
static TOOL_ACTION newSymbol;
|
||||
static TOOL_ACTION editSymbol;
|
||||
static TOOL_ACTION duplicateSymbol;
|
||||
static TOOL_ACTION renameSymbol;
|
||||
static TOOL_ACTION deleteSymbol;
|
||||
static TOOL_ACTION cutSymbol;
|
||||
static TOOL_ACTION copySymbol;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 CERN
|
||||
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2022 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
|
||||
|
@ -36,7 +36,8 @@
|
|||
#include <bitmaps/bitmap_types.h>
|
||||
#include <confirm.h>
|
||||
#include <wx/filedlg.h>
|
||||
|
||||
#include "wx/generic/textdlgg.h"
|
||||
#include "string_utils.h"
|
||||
|
||||
bool SYMBOL_EDITOR_CONTROL::Init()
|
||||
{
|
||||
|
@ -108,6 +109,7 @@ bool SYMBOL_EDITOR_CONTROL::Init()
|
|||
ctxMenu.AddItem( EE_ACTIONS::copySymbol, symbolSelectedCondition );
|
||||
ctxMenu.AddItem( EE_ACTIONS::pasteSymbol, libInferredCondition );
|
||||
ctxMenu.AddItem( EE_ACTIONS::duplicateSymbol, symbolSelectedCondition );
|
||||
ctxMenu.AddItem( EE_ACTIONS::renameSymbol, symbolSelectedCondition );
|
||||
ctxMenu.AddItem( EE_ACTIONS::deleteSymbol, symbolSelectedCondition );
|
||||
|
||||
ctxMenu.AddSeparator();
|
||||
|
@ -285,6 +287,96 @@ int SYMBOL_EDITOR_CONTROL::DuplicateSymbol( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
int SYMBOL_EDITOR_CONTROL::RenameSymbol( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
|
||||
{
|
||||
SYMBOL_EDIT_FRAME* editFrame = static_cast<SYMBOL_EDIT_FRAME*>( m_frame );
|
||||
SYMBOL_LIBRARY_MANAGER& libMgr = editFrame->GetLibManager();
|
||||
|
||||
LIB_ID libId = editFrame->GetTreeLIBID();
|
||||
wxString libName = libId.GetLibNickname();
|
||||
wxString symbolName = libId.GetLibItemName();
|
||||
wxString newName = symbolName;
|
||||
bool done = false;
|
||||
|
||||
if( !libMgr.LibraryExists( libName ) )
|
||||
return 0;
|
||||
|
||||
while( !done )
|
||||
{
|
||||
wxTextEntryDialog dlg( m_frame, _( "New name:" ), _( "Change Symbol Name" ), newName );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return 0; // canceled by user
|
||||
|
||||
newName = dlg.GetValue();
|
||||
newName.Trim( true ).Trim( false );
|
||||
|
||||
if( newName.IsEmpty() )
|
||||
{
|
||||
DisplayErrorMessage( editFrame, _( "Symbol name cannot be empty." ) );
|
||||
}
|
||||
else if( libMgr.SymbolExists( newName, libName ) )
|
||||
{
|
||||
DisplayErrorMessage( editFrame, wxString::Format( _( "Symbol name '%s' already "
|
||||
"in use in library '%s'." ),
|
||||
UnescapeString( newName ),
|
||||
libName ) );
|
||||
newName = symbolName;
|
||||
}
|
||||
else
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
wxString oldName = symbolName;
|
||||
LIB_SYMBOL* libSymbol = nullptr;
|
||||
|
||||
if( editFrame->IsCurrentSymbol( libId ) )
|
||||
{
|
||||
// Update buffered copy
|
||||
libSymbol = libMgr.GetBufferedSymbol( oldName, libName );
|
||||
|
||||
libSymbol->SetName( newName );
|
||||
libSymbol->GetFieldById( VALUE_FIELD )->SetText( newName );
|
||||
|
||||
libMgr.UpdateSymbolAfterRename( libSymbol, newName, libName );
|
||||
|
||||
// Now update canvasy copy
|
||||
libSymbol = editFrame->GetCurSymbol();
|
||||
|
||||
libSymbol->SetName( newName );
|
||||
libSymbol->GetFieldById( VALUE_FIELD )->SetText( newName );
|
||||
|
||||
editFrame->RebuildView();
|
||||
editFrame->OnModify();
|
||||
|
||||
// N.B. The view needs to be rebuilt first as the Symbol Properties change may
|
||||
// invalidate the view pointers by rebuilting the field table
|
||||
editFrame->UpdateMsgPanel();
|
||||
}
|
||||
else
|
||||
{
|
||||
libSymbol = libMgr.GetBufferedSymbol( oldName, libName );
|
||||
|
||||
libSymbol->SetName( newName );
|
||||
libSymbol->GetFieldById( VALUE_FIELD )->SetText( newName );
|
||||
|
||||
libMgr.UpdateSymbolAfterRename( libSymbol, newName, libName );
|
||||
libMgr.SetSymbolModified( newName, libName );
|
||||
}
|
||||
|
||||
wxDataViewItem treeItem = libMgr.GetAdapter()->FindItem( libId );
|
||||
editFrame->UpdateLibraryTree( treeItem, libSymbol );
|
||||
editFrame->FocusOnLibId( LIB_ID( libName, newName ) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int SYMBOL_EDITOR_CONTROL::OnDeMorgan( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
int convert = aEvent.IsAction( &EE_ACTIONS::showDeMorganStandard ) ?
|
||||
|
@ -453,9 +545,8 @@ int SYMBOL_EDITOR_CONTROL::ExportSymbolAsSVG( const TOOL_EVENT& aEvent )
|
|||
PAGE_INFO pageSave = editFrame->GetScreen()->GetPageSettings();
|
||||
PAGE_INFO pageTemp = pageSave;
|
||||
|
||||
VECTOR2I symbolSize =
|
||||
symbol->GetUnitBoundingBox( editFrame->GetUnit(),
|
||||
editFrame->GetConvert() ).GetSize();
|
||||
VECTOR2I symbolSize = symbol->GetUnitBoundingBox( editFrame->GetUnit(),
|
||||
editFrame->GetConvert() ).GetSize();
|
||||
|
||||
// Add a small margin to the plot bounding box
|
||||
pageTemp.SetWidthMils( int( symbolSize.x * 1.2 ) );
|
||||
|
@ -552,6 +643,7 @@ void SYMBOL_EDITOR_CONTROL::setTransitions()
|
|||
Go( &SYMBOL_EDITOR_CONTROL::Revert, ACTIONS::revert.MakeEvent() );
|
||||
|
||||
Go( &SYMBOL_EDITOR_CONTROL::DuplicateSymbol, EE_ACTIONS::duplicateSymbol.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_CONTROL::RenameSymbol, EE_ACTIONS::renameSymbol.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_CONTROL::CutCopyDelete, EE_ACTIONS::deleteSymbol.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_CONTROL::CutCopyDelete, EE_ACTIONS::cutSymbol.MakeEvent() );
|
||||
Go( &SYMBOL_EDITOR_CONTROL::CutCopyDelete, EE_ACTIONS::copySymbol.MakeEvent() );
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 CERN
|
||||
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2022 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
|
||||
|
@ -55,6 +55,7 @@ public:
|
|||
|
||||
int CutCopyDelete( const TOOL_EVENT& aEvent );
|
||||
int DuplicateSymbol( const TOOL_EVENT& aEvent );
|
||||
int RenameSymbol( const TOOL_EVENT& aEvent );
|
||||
int ExportSymbol( const TOOL_EVENT& aEvent );
|
||||
int ExportView( const TOOL_EVENT& aEvent );
|
||||
int ExportSymbolAsSVG( const TOOL_EVENT& aEvent );
|
||||
|
|
|
@ -181,6 +181,7 @@ public:
|
|||
* @return : true if OK, false if abort
|
||||
*/
|
||||
bool SaveFootprint( FOOTPRINT* aFootprint );
|
||||
bool DuplicateFootprint( FOOTPRINT* aFootprint );
|
||||
bool SaveFootprintAs( FOOTPRINT* aFootprint );
|
||||
bool SaveFootprintToBoard( bool aAddNew );
|
||||
bool SaveFootprintInLibrary( FOOTPRINT* aFootprint, const wxString& aLibraryName );
|
||||
|
@ -306,6 +307,11 @@ public:
|
|||
*/
|
||||
void RefreshLibraryTree();
|
||||
|
||||
/**
|
||||
* Update a single node in the library tree.
|
||||
*/
|
||||
void UpdateLibraryTree( const wxDataViewItem& treeItem, FOOTPRINT* aFootprint );
|
||||
|
||||
///< Reload displayed items and sets view.
|
||||
void UpdateView();
|
||||
|
||||
|
|
|
@ -148,6 +148,20 @@ public:
|
|||
};
|
||||
|
||||
|
||||
void FOOTPRINT_EDIT_FRAME::UpdateLibraryTree( const wxDataViewItem& aTreeItem,
|
||||
FOOTPRINT* aFootprint )
|
||||
{
|
||||
BASIC_FOOTPRINT_INFO footprintInfo( aFootprint );
|
||||
|
||||
if( aTreeItem.IsOk() ) // Can be not found in tree if the current footprint is imported
|
||||
// from file therefore not yet in tree.
|
||||
{
|
||||
static_cast<LIB_TREE_NODE_LIB_ID*>( aTreeItem.GetID() )->Update( &footprintInfo );
|
||||
m_treePane->GetLibTree()->RefreshLibTree();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FOOTPRINT_EDIT_FRAME::editFootprintProperties( FOOTPRINT* aFootprint )
|
||||
{
|
||||
LIB_ID oldFPID = aFootprint->GetFPID();
|
||||
|
@ -155,18 +169,10 @@ void FOOTPRINT_EDIT_FRAME::editFootprintProperties( FOOTPRINT* aFootprint )
|
|||
DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR dialog( this, aFootprint );
|
||||
dialog.ShowModal();
|
||||
|
||||
// Update library tree
|
||||
BASIC_FOOTPRINT_INFO footprintInfo( aFootprint );
|
||||
wxDataViewItem treeItem = m_adapter->FindItem( oldFPID );
|
||||
|
||||
if( treeItem.IsOk() ) // Can be not found in tree if the current footprint is imported
|
||||
// from file therefore not yet in tree.
|
||||
{
|
||||
static_cast<LIB_TREE_NODE_LIB_ID*>( treeItem.GetID() )->Update( &footprintInfo );
|
||||
m_treePane->GetLibTree()->RefreshLibTree();
|
||||
}
|
||||
|
||||
UpdateTitle(); // in case of a name change...
|
||||
// Update library tree and title in case of a name change
|
||||
wxDataViewItem treeItem = m_adapter->FindItem( oldFPID );
|
||||
UpdateLibraryTree( treeItem, aFootprint );
|
||||
UpdateTitle();
|
||||
|
||||
UpdateMsgPanel();
|
||||
}
|
||||
|
|
|
@ -851,6 +851,39 @@ bool FOOTPRINT_EDIT_FRAME::SaveFootprint( FOOTPRINT* aFootprint )
|
|||
}
|
||||
|
||||
|
||||
bool FOOTPRINT_EDIT_FRAME::DuplicateFootprint( FOOTPRINT* aFootprint )
|
||||
{
|
||||
LIB_ID fpID = aFootprint->GetFPID();
|
||||
wxString libraryName = fpID.GetLibNickname();
|
||||
wxString footprintName = fpID.GetLibItemName();
|
||||
|
||||
// Legacy libraries are readable, but modifying legacy format is not allowed
|
||||
// So prompt the user if he try to add/replace a footprint in a legacy lib
|
||||
wxString libFullName = Prj().PcbFootprintLibs()->FindRow( libraryName )->GetFullURI();
|
||||
|
||||
if( IO_MGR::GuessPluginTypeFromLibPath( libFullName ) == IO_MGR::LEGACY )
|
||||
{
|
||||
DisplayInfoMessage( this, INFO_LEGACY_LIB_WARN_EDIT );
|
||||
return false;
|
||||
}
|
||||
|
||||
FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs();
|
||||
int i = 1;
|
||||
wxString newName = footprintName;
|
||||
|
||||
// Append a number to the name until the name is unique in the library.
|
||||
while( tbl->FootprintExists( libraryName, newName ) )
|
||||
newName.Printf( "%s_%d", footprintName, i++ );
|
||||
|
||||
aFootprint->SetFPID( LIB_ID( libraryName, newName ) );
|
||||
|
||||
if( aFootprint->GetValue() == footprintName )
|
||||
aFootprint->SetValue( newName );
|
||||
|
||||
return SaveFootprintInLibrary( aFootprint, libraryName );
|
||||
}
|
||||
|
||||
|
||||
bool FOOTPRINT_EDIT_FRAME::SaveFootprintInLibrary( FOOTPRINT* aFootprint,
|
||||
const wxString& aLibraryName )
|
||||
{
|
||||
|
|
|
@ -177,7 +177,8 @@ void FP_TREE_SYNCHRONIZING_ADAPTER::GetValue( wxVariant& aVariant, wxDataViewIte
|
|||
case 0:
|
||||
if( node->m_LibId == m_frame->GetLoadedFPID() && !m_frame->IsCurrentFPFromBoard() )
|
||||
{
|
||||
node->m_Name = m_frame->GetLoadedFPID().GetLibItemName();
|
||||
// Do not use GetLoadedFPID(); it returns m_footprintNameWhenLoaded.
|
||||
node->m_Name = m_frame->GetBoard()->GetFirstFootprint()->GetFPID().GetLibItemName();
|
||||
|
||||
// mark modified part with an asterisk
|
||||
if( m_frame->GetScreen()->IsContentModified() )
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include "footprint_editor_control.h"
|
||||
#include "kicad_clipboard.h"
|
||||
#include "wx/generic/textdlgg.h"
|
||||
#include "string_utils.h"
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <view/view_controls.h>
|
||||
|
@ -109,31 +111,33 @@ bool FOOTPRINT_EDITOR_CONTROL::Init()
|
|||
return !sel.GetLibNickname().empty() && !sel.GetLibItemName().empty();
|
||||
};
|
||||
|
||||
ctxMenu.AddItem( ACTIONS::pinLibrary, unpinnedLibSelectedCondition );
|
||||
ctxMenu.AddItem( ACTIONS::unpinLibrary, pinnedLibSelectedCondition );
|
||||
ctxMenu.AddItem( ACTIONS::pinLibrary, unpinnedLibSelectedCondition );
|
||||
ctxMenu.AddItem( ACTIONS::unpinLibrary, pinnedLibSelectedCondition );
|
||||
|
||||
ctxMenu.AddSeparator();
|
||||
ctxMenu.AddItem( PCB_ACTIONS::newFootprint, libSelectedCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::createFootprint, libSelectedCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::newFootprint, libSelectedCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::createFootprint, libSelectedCondition );
|
||||
|
||||
ctxMenu.AddSeparator();
|
||||
ctxMenu.AddItem( ACTIONS::save, libSelectedCondition || libInferredCondition );
|
||||
ctxMenu.AddItem( ACTIONS::saveAs, libSelectedCondition );
|
||||
ctxMenu.AddItem( ACTIONS::saveCopyAs, fpSelectedCondition );
|
||||
ctxMenu.AddItem( ACTIONS::revert, libSelectedCondition || libInferredCondition );
|
||||
ctxMenu.AddItem( ACTIONS::save, libSelectedCondition || libInferredCondition );
|
||||
ctxMenu.AddItem( ACTIONS::saveAs, libSelectedCondition );
|
||||
ctxMenu.AddItem( ACTIONS::saveCopyAs, fpSelectedCondition );
|
||||
ctxMenu.AddItem( ACTIONS::revert, libSelectedCondition || libInferredCondition );
|
||||
|
||||
ctxMenu.AddSeparator();
|
||||
ctxMenu.AddItem( PCB_ACTIONS::cutFootprint, fpSelectedCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::copyFootprint, fpSelectedCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::pasteFootprint, libInferredCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::deleteFootprint, fpSelectedCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::cutFootprint, fpSelectedCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::copyFootprint, fpSelectedCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::pasteFootprint, libInferredCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::duplicateFootprint, fpSelectedCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::renameFootprint, fpSelectedCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::deleteFootprint, fpSelectedCondition );
|
||||
|
||||
ctxMenu.AddSeparator();
|
||||
ctxMenu.AddItem( PCB_ACTIONS::importFootprint, libInferredCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::exportFootprint, fpSelectedCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::importFootprint, libInferredCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::exportFootprint, fpSelectedCondition );
|
||||
|
||||
// If we've got nothing else to show, at least show a hide tree option
|
||||
ctxMenu.AddItem( PCB_ACTIONS::hideFootprintTree, !libInferredCondition );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::hideFootprintTree, !libInferredCondition );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -357,6 +361,116 @@ int FOOTPRINT_EDITOR_CONTROL::PasteFootprint( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
int FOOTPRINT_EDITOR_CONTROL::DuplicateFootprint( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_ID fpID = m_frame->GetTreeFPID();
|
||||
wxString libraryName = fpID.GetLibNickname();
|
||||
wxString footprintName = fpID.GetLibItemName();
|
||||
FOOTPRINT* footprint;
|
||||
|
||||
if( fpID == m_frame->GetLoadedFPID() )
|
||||
footprint = new FOOTPRINT( *m_frame->GetBoard()->GetFirstFootprint() );
|
||||
else
|
||||
footprint = m_frame->LoadFootprint( m_frame->GetTargetFPID() );
|
||||
|
||||
if( footprint && m_frame->DuplicateFootprint( footprint ) )
|
||||
{
|
||||
m_frame->SyncLibraryTree( true );
|
||||
m_frame->FocusOnLibID( footprint->GetFPID() );
|
||||
m_frame->RefreshLibraryTree();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int FOOTPRINT_EDITOR_CONTROL::RenameFootprint( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
FP_LIB_TABLE* tbl = m_frame->Prj().PcbFootprintLibs();
|
||||
LIB_ID fpID = m_frame->GetTreeFPID();
|
||||
wxString libraryName = fpID.GetLibNickname();
|
||||
wxString oldName = fpID.GetLibItemName();
|
||||
wxString newName = oldName;
|
||||
bool done = false;
|
||||
|
||||
while( !done )
|
||||
{
|
||||
wxTextEntryDialog dlg( m_frame, _( "New name:" ), _( "Change Footprint Name" ), newName );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return 0; // canceled by user
|
||||
|
||||
newName = dlg.GetValue();
|
||||
newName.Trim( true ).Trim( false );
|
||||
|
||||
if( newName.IsEmpty() )
|
||||
{
|
||||
DisplayErrorMessage( m_frame, _( "Footprint name cannot be empty." ) );
|
||||
}
|
||||
else if( tbl->FootprintExists( libraryName, newName ) )
|
||||
{
|
||||
DisplayErrorMessage( m_frame, wxString::Format( _( "Footprint name '%s' already "
|
||||
"in use in library '%s'." ),
|
||||
UnescapeString( newName ),
|
||||
libraryName ) );
|
||||
newName = oldName;
|
||||
}
|
||||
else
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
FOOTPRINT* footprint = nullptr;
|
||||
|
||||
if( fpID == m_frame->GetLoadedFPID() )
|
||||
{
|
||||
footprint = m_frame->GetBoard()->GetFirstFootprint();
|
||||
|
||||
if( footprint )
|
||||
{
|
||||
footprint->SetFPID( LIB_ID( libraryName, newName ) );
|
||||
|
||||
if( footprint->GetValue() == oldName )
|
||||
footprint->SetValue( newName );
|
||||
|
||||
m_frame->OnModify();
|
||||
m_frame->UpdateView();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
footprint = m_frame->LoadFootprint( fpID );
|
||||
|
||||
try
|
||||
{
|
||||
footprint->SetFPID( LIB_ID( libraryName, newName ) );
|
||||
|
||||
if( footprint->GetValue() == oldName )
|
||||
footprint->SetValue( newName );
|
||||
|
||||
m_frame->SaveFootprintInLibrary( footprint, libraryName );
|
||||
|
||||
m_frame->Prj().PcbFootprintLibs()->FootprintDelete( libraryName, oldName );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( m_frame, ioe.What() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
// Best efforts...
|
||||
}
|
||||
}
|
||||
|
||||
wxDataViewItem treeItem = m_frame->GetLibTreeAdapter()->FindItem( fpID );
|
||||
m_frame->UpdateLibraryTree( treeItem, footprint );
|
||||
m_frame->FocusOnLibID( LIB_ID( libraryName, newName ) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int FOOTPRINT_EDITOR_CONTROL::DeleteFootprint( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
FOOTPRINT_EDIT_FRAME* frame = getEditFrame<FOOTPRINT_EDIT_FRAME>();
|
||||
|
@ -608,6 +722,8 @@ void FOOTPRINT_EDITOR_CONTROL::setTransitions()
|
|||
Go( &FOOTPRINT_EDITOR_CONTROL::SaveAs, ACTIONS::saveAs.MakeEvent() );
|
||||
Go( &FOOTPRINT_EDITOR_CONTROL::SaveAs, ACTIONS::saveCopyAs.MakeEvent() );
|
||||
Go( &FOOTPRINT_EDITOR_CONTROL::Revert, ACTIONS::revert.MakeEvent() );
|
||||
Go( &FOOTPRINT_EDITOR_CONTROL::DuplicateFootprint, PCB_ACTIONS::duplicateFootprint.MakeEvent() );
|
||||
Go( &FOOTPRINT_EDITOR_CONTROL::RenameFootprint, PCB_ACTIONS::renameFootprint.MakeEvent() );
|
||||
Go( &FOOTPRINT_EDITOR_CONTROL::DeleteFootprint, PCB_ACTIONS::deleteFootprint.MakeEvent() );
|
||||
|
||||
Go( &FOOTPRINT_EDITOR_CONTROL::EditFootprint, PCB_ACTIONS::editFootprint.MakeEvent() );
|
||||
|
|
|
@ -58,6 +58,8 @@ public:
|
|||
int EditFootprint( const TOOL_EVENT& aEvent );
|
||||
int CutCopyFootprint( const TOOL_EVENT& aEvent );
|
||||
int PasteFootprint( const TOOL_EVENT& aEvent );
|
||||
int DuplicateFootprint( const TOOL_EVENT& aEvent );
|
||||
int RenameFootprint( const TOOL_EVENT& aEvent );
|
||||
int DeleteFootprint( const TOOL_EVENT& aEvent );
|
||||
int ImportFootprint( const TOOL_EVENT& aEvent );
|
||||
int ExportFootprint( const TOOL_EVENT& aEvent );
|
||||
|
|
|
@ -369,6 +369,16 @@ TOOL_ACTION PCB_ACTIONS::editFootprint( "pcbnew.ModuleEditor.editFootprint",
|
|||
_( "Edit Footprint" ), _( "Show selected footprint on editor canvas" ),
|
||||
BITMAPS::edit );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::duplicateFootprint( "pcbnew.ModuleEditor.duplicateFootprint",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Duplicate Footprint" ), _( "Make a copy of the selected footprint" ),
|
||||
BITMAPS::duplicate );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::renameFootprint( "pcbnew.ModuleEditor.renameFootprint",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Rename Footprint..." ), _( "Rename the selected footprint" ),
|
||||
BITMAPS::edit );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::deleteFootprint( "pcbnew.ModuleEditor.deleteFootprint",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Delete Footprint from Library" ), _( "Delete Footprint from Library" ),
|
||||
|
|
|
@ -374,6 +374,8 @@ public:
|
|||
static TOOL_ACTION saveToLibrary;
|
||||
|
||||
static TOOL_ACTION editFootprint;
|
||||
static TOOL_ACTION duplicateFootprint;
|
||||
static TOOL_ACTION renameFootprint;
|
||||
static TOOL_ACTION deleteFootprint;
|
||||
static TOOL_ACTION cutFootprint;
|
||||
static TOOL_ACTION copyFootprint;
|
||||
|
|
Loading…
Reference in New Issue