From 980aefea4bccf674034e8b0dbf8b22d734d4a624 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Fri, 15 May 2020 15:53:59 -0400 Subject: [PATCH] Eeschema: fix copy and paste bug. Add required library symbols to new file formatter and parser when copying schematic symbols to prevent missing library symbol when pasting into a different schematic which may not have the same library symbol available. Fix a minor bug where the default schematic symbol reference was not set by the parser when loading. Fixes https://gitlab.com/kicad/code/kicad/issues/4442 --- eeschema/sch_sexpr_parser.cpp | 33 +++++++++++++++--- eeschema/sch_sexpr_plugin.cpp | 49 ++++++++++++++++++++++++--- eeschema/sch_sexpr_plugin.h | 4 +-- eeschema/tools/ee_selection.cpp | 7 ++++ eeschema/tools/ee_selection.h | 15 +++++++- eeschema/tools/sch_editor_control.cpp | 1 + 6 files changed, 97 insertions(+), 12 deletions(-) diff --git a/eeschema/sch_sexpr_parser.cpp b/eeschema/sch_sexpr_parser.cpp index 905c3f11c4..8b884af328 100644 --- a/eeschema/sch_sexpr_parser.cpp +++ b/eeschema/sch_sexpr_parser.cpp @@ -1937,9 +1937,6 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly, case T_lib_symbols: { - if( aIsCopyableOnly ) - Unexpected( T_lib_symbols ); - // Dummy map. No derived symbols are allowed in the library cache. LIB_PART_MAP symbolLibMap; @@ -2032,8 +2029,7 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly, } } - if( !aIsCopyableOnly ) - screen->UpdateLocalLibSymbolLinks(); + screen->UpdateLocalLibSymbolLinks(); } @@ -2153,6 +2149,33 @@ SCH_COMPONENT* SCH_SEXPR_PARSER::parseSchematicSymbol() // the field positions are set. field = parseSchField( symbol.get() ); + // Set the default symbol reference prefix. + if( field->GetId() == REFERENCE ) + { + wxString refDesignator = field->GetText(); + + refDesignator.Replace( "~", " " ); + + wxString prefix = refDesignator; + + while( prefix.Length() ) + { + if( ( prefix.Last() < '0' || prefix.Last() > '9') && prefix.Last() != '?' ) + break; + + prefix.RemoveLast(); + } + + // Avoid a prefix containing trailing/leading spaces + prefix.Trim( true ); + prefix.Trim( false ); + + if( prefix.IsEmpty() ) + symbol->SetPrefix( wxString( "U" ) ); + else + symbol->SetPrefix( prefix ); + } + if( symbol->GetField( field->GetId() ) ) *symbol->GetField( field->GetId() ) = *field; else diff --git a/eeschema/sch_sexpr_plugin.cpp b/eeschema/sch_sexpr_plugin.cpp index 6f415b27a6..a6b807903c 100644 --- a/eeschema/sch_sexpr_plugin.cpp +++ b/eeschema/sch_sexpr_plugin.cpp @@ -77,7 +77,7 @@ #include #include // for PropPowerSymsOnly definintion. #include -#include +#include #include // For some default values @@ -771,13 +771,54 @@ void SCH_SEXPR_PLUGIN::Format( SCH_SHEET* aSheet ) } -void SCH_SEXPR_PLUGIN::Format( SELECTION* aSelection, OUTPUTFORMATTER* aFormatter ) +void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, OUTPUTFORMATTER* aFormatter ) { + wxCHECK( aSelection && aFormatter, /* void */ ); + m_out = aFormatter; - for( unsigned i = 0; i < aSelection->GetSize(); ++i ) + size_t i; + SCH_ITEM* item; + std::map libSymbols; + SCH_SCREEN* screen = aSelection->GetScreen(); + + for( i = 0; i < aSelection->GetSize(); ++i ) { - SCH_ITEM* item = (SCH_ITEM*) aSelection->GetItem( i ); + item = dynamic_cast( aSelection->GetItem( i ) ); + + wxCHECK2( item, continue ); + + if( item->Type() != SCH_COMPONENT_T ) + continue; + + SCH_COMPONENT* symbol = dynamic_cast( item ); + + wxCHECK2( symbol, continue ); + + wxString libSymbolLookup = symbol->GetLibId().Format().wx_str(); + + if( !symbol->UseLibIdLookup() ) + libSymbolLookup = symbol->GetSchSymbolLibraryName(); + + auto it = screen->GetLibSymbols().find( libSymbolLookup ); + + if( it != screen->GetLibSymbols().end() ) + libSymbols[ libSymbolLookup ] = it->second; + } + + if( !libSymbols.empty() ) + { + m_out->Print( 0, "(lib_symbols\n" ); + + for( auto libSymbol : libSymbols ) + SCH_SEXPR_PLUGIN_CACHE::SaveSymbol( libSymbol.second, *m_out, 1, libSymbol.first ); + + m_out->Print( 0, ")\n\n" ); + } + + for( i = 0; i < aSelection->GetSize(); ++i ) + { + item = (SCH_ITEM*) aSelection->GetItem( i ); switch( item->Type() ) { diff --git a/eeschema/sch_sexpr_plugin.h b/eeschema/sch_sexpr_plugin.h index 686b26b98e..2384a6add5 100644 --- a/eeschema/sch_sexpr_plugin.h +++ b/eeschema/sch_sexpr_plugin.h @@ -41,7 +41,7 @@ class SCH_TEXT; class SCH_COMPONENT; class SCH_FIELD; class PROPERTIES; -class SELECTION; +class EE_SELECTION; class SCH_SEXPR_PLUGIN_CACHE; class LIB_PART; class PART_LIB; @@ -96,7 +96,7 @@ public: void Format( SCH_SHEET* aSheet ); - void Format( SELECTION* aSelection, OUTPUTFORMATTER* aFormatter ); + void Format( EE_SELECTION* aSelection, OUTPUTFORMATTER* aFormatter ); void EnumerateSymbolLib( wxArrayString& aSymbolNameList, const wxString& aLibraryPath, diff --git a/eeschema/tools/ee_selection.cpp b/eeschema/tools/ee_selection.cpp index ec5534bae8..cff96b6264 100644 --- a/eeschema/tools/ee_selection.cpp +++ b/eeschema/tools/ee_selection.cpp @@ -25,6 +25,13 @@ #include +EE_SELECTION::EE_SELECTION( SCH_SCREEN* aScreen ) : + SELECTION() +{ + m_screen = aScreen; +} + + EDA_ITEM* EE_SELECTION::GetTopLeftItem( bool onlyModules ) const { EDA_ITEM* topLeftItem = nullptr; diff --git a/eeschema/tools/ee_selection.h b/eeschema/tools/ee_selection.h index 3b8d2f59d2..19343d5561 100644 --- a/eeschema/tools/ee_selection.h +++ b/eeschema/tools/ee_selection.h @@ -25,13 +25,26 @@ #ifndef EE_SELECTION_H #define EE_SELECTION_H +class SCH_SCREEN; + + #include class EE_SELECTION : public SELECTION { + /** + * Screen of selected objects. Used to fetch library symbols for copy. + */ + SCH_SCREEN* m_screen; + public: + EE_SELECTION( SCH_SCREEN* aScreen = nullptr ); + EDA_ITEM* GetTopLeftItem( bool onlyModules = false ) const override; + + void SetScreen( SCH_SCREEN* aScreen ) { m_screen = aScreen; } + SCH_SCREEN* GetScreen() { return m_screen; } }; -#endif // EE_SELECTION_H \ No newline at end of file +#endif // EE_SELECTION_H diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index b9ccf82f34..9f1aa667fb 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -1094,6 +1094,7 @@ bool SCH_EDITOR_CONTROL::doCopy() if( !selection.GetSize() ) return false; + selection.SetScreen( m_frame->GetScreen() ); m_supplementaryClipboard.clear(); for( EDA_ITEM* item : selection )