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
This commit is contained in:
Wayne Stambaugh 2020-05-15 15:53:59 -04:00
parent 733c553606
commit 980aefea4b
6 changed files with 97 additions and 12 deletions

View File

@ -1937,9 +1937,6 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly,
case T_lib_symbols: case T_lib_symbols:
{ {
if( aIsCopyableOnly )
Unexpected( T_lib_symbols );
// Dummy map. No derived symbols are allowed in the library cache. // Dummy map. No derived symbols are allowed in the library cache.
LIB_PART_MAP symbolLibMap; LIB_PART_MAP symbolLibMap;
@ -2032,7 +2029,6 @@ 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. // the field positions are set.
field = parseSchField( symbol.get() ); 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() ) ) if( symbol->GetField( field->GetId() ) )
*symbol->GetField( field->GetId() ) = *field; *symbol->GetField( field->GetId() ) = *field;
else else

View File

@ -77,7 +77,7 @@
#include <sch_sexpr_parser.h> #include <sch_sexpr_parser.h>
#include <symbol_lib_table.h> // for PropPowerSymsOnly definintion. #include <symbol_lib_table.h> // for PropPowerSymsOnly definintion.
#include <confirm.h> #include <confirm.h>
#include <tool/selection.h> #include <ee_selection.h>
#include <default_values.h> // For some default values #include <default_values.h> // 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; m_out = aFormatter;
for( unsigned i = 0; i < aSelection->GetSize(); ++i ) size_t i;
SCH_ITEM* item;
std::map<wxString, LIB_PART*> libSymbols;
SCH_SCREEN* screen = aSelection->GetScreen();
for( i = 0; i < aSelection->GetSize(); ++i )
{ {
SCH_ITEM* item = (SCH_ITEM*) aSelection->GetItem( i ); item = dynamic_cast<SCH_ITEM*>( aSelection->GetItem( i ) );
wxCHECK2( item, continue );
if( item->Type() != SCH_COMPONENT_T )
continue;
SCH_COMPONENT* symbol = dynamic_cast<SCH_COMPONENT*>( 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() ) switch( item->Type() )
{ {

View File

@ -41,7 +41,7 @@ class SCH_TEXT;
class SCH_COMPONENT; class SCH_COMPONENT;
class SCH_FIELD; class SCH_FIELD;
class PROPERTIES; class PROPERTIES;
class SELECTION; class EE_SELECTION;
class SCH_SEXPR_PLUGIN_CACHE; class SCH_SEXPR_PLUGIN_CACHE;
class LIB_PART; class LIB_PART;
class PART_LIB; class PART_LIB;
@ -96,7 +96,7 @@ public:
void Format( SCH_SHEET* aSheet ); void Format( SCH_SHEET* aSheet );
void Format( SELECTION* aSelection, OUTPUTFORMATTER* aFormatter ); void Format( EE_SELECTION* aSelection, OUTPUTFORMATTER* aFormatter );
void EnumerateSymbolLib( wxArrayString& aSymbolNameList, void EnumerateSymbolLib( wxArrayString& aSymbolNameList,
const wxString& aLibraryPath, const wxString& aLibraryPath,

View File

@ -25,6 +25,13 @@
#include <tools/ee_selection.h> #include <tools/ee_selection.h>
EE_SELECTION::EE_SELECTION( SCH_SCREEN* aScreen ) :
SELECTION()
{
m_screen = aScreen;
}
EDA_ITEM* EE_SELECTION::GetTopLeftItem( bool onlyModules ) const EDA_ITEM* EE_SELECTION::GetTopLeftItem( bool onlyModules ) const
{ {
EDA_ITEM* topLeftItem = nullptr; EDA_ITEM* topLeftItem = nullptr;

View File

@ -25,13 +25,26 @@
#ifndef EE_SELECTION_H #ifndef EE_SELECTION_H
#define EE_SELECTION_H #define EE_SELECTION_H
class SCH_SCREEN;
#include <tool/selection.h> #include <tool/selection.h>
class EE_SELECTION : public SELECTION class EE_SELECTION : public SELECTION
{ {
/**
* Screen of selected objects. Used to fetch library symbols for copy.
*/
SCH_SCREEN* m_screen;
public: public:
EE_SELECTION( SCH_SCREEN* aScreen = nullptr );
EDA_ITEM* GetTopLeftItem( bool onlyModules = false ) const override; 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 #endif // EE_SELECTION_H

View File

@ -1094,6 +1094,7 @@ bool SCH_EDITOR_CONTROL::doCopy()
if( !selection.GetSize() ) if( !selection.GetSize() )
return false; return false;
selection.SetScreen( m_frame->GetScreen() );
m_supplementaryClipboard.clear(); m_supplementaryClipboard.clear();
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )