Use new file formats for copy and paste in schematic and symbol editors.

This commit is contained in:
Wayne Stambaugh 2020-05-13 17:58:30 -04:00
parent 3a9746c657
commit ad88874adf
6 changed files with 111 additions and 66 deletions

View File

@ -48,7 +48,6 @@
#include <sch_component.h>
#include <sch_edit_frame.h> // CMP_ORIENT_XXX
#include <sch_field.h>
#include <sch_file_versions.h>
#include <sch_line.h>
#include <sch_junction.h>
#include <sch_no_connect.h>
@ -95,7 +94,7 @@ void SCH_SEXPR_PARSER::ParseLib( LIB_PART_MAP& aSymbolLibMap )
{
m_unit = 1;
m_convert = 1;
LIB_PART* symbol = ParseSymbol( aSymbolLibMap );
LIB_PART* symbol = ParseSymbol( aSymbolLibMap, m_requiredVersion );
aSymbolLibMap[symbol->GetName()] = symbol;
}
else
@ -106,7 +105,7 @@ void SCH_SEXPR_PARSER::ParseLib( LIB_PART_MAP& aSymbolLibMap )
}
LIB_PART* SCH_SEXPR_PARSER::ParseSymbol( LIB_PART_MAP& aSymbolLibMap, bool aIsSchematicLib )
LIB_PART* SCH_SEXPR_PARSER::ParseSymbol( LIB_PART_MAP& aSymbolLibMap, int aFileVersion )
{
wxCHECK_MSG( CurTok() == T_symbol, nullptr,
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a symbol." ) );
@ -118,6 +117,7 @@ LIB_PART* SCH_SEXPR_PARSER::ParseSymbol( LIB_PART_MAP& aSymbolLibMap, bool aIsSc
LIB_ITEM* item;
std::unique_ptr<LIB_PART> symbol( new LIB_PART( wxEmptyString ) );
m_requiredVersion = aFileVersion;
symbol->SetUnitCount( 1 );
m_fieldId = MANDATORY_FIELDS;
@ -1861,7 +1861,7 @@ void SCH_SEXPR_PARSER::parseSchSymbolInstances( SCH_SCREEN* aScreen )
}
void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet )
void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly, int aFileVersion )
{
wxCHECK( aSheet != nullptr, /* void */ );
@ -1869,8 +1869,13 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet )
wxCHECK( screen != nullptr, /* void */ );
if( aIsCopyableOnly )
m_requiredVersion = aFileVersion;
T token;
if( !aIsCopyableOnly )
{
NeedLEFT();
NextTok();
@ -1878,21 +1883,28 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet )
Expecting( "kicad_sch" );
parseHeader( T_kicad_sch, SEXPR_SCHEMATIC_FILE_VERSION );
}
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
if( aIsCopyableOnly && token == T_EOF )
break;
if( token != T_LEFT )
Expecting( T_LEFT );
token = NextTok();
if( token == T_page && m_requiredVersion <= 20200506 )
if( !aIsCopyableOnly && token == T_page && m_requiredVersion <= 20200506 )
token = T_paper;
switch( token )
{
case T_paper:
{
if( aIsCopyableOnly )
Unexpected( T_paper );
PAGE_INFO pageInfo;
parsePAGE_INFO( pageInfo );
screen->SetPageSettings( pageInfo );
@ -1901,6 +1913,9 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet )
case T_page:
{
if( aIsCopyableOnly )
Unexpected( T_page );
// Only saved for top-level sniffing in Kicad Manager frame and other external
// tool usage with flat hierarchies
NeedSYMBOLorNUMBER();
@ -1911,6 +1926,9 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet )
case T_title_block:
{
if( aIsCopyableOnly )
Unexpected( T_title_block );
TITLE_BLOCK tb;
parseTITLE_BLOCK( tb );
screen->SetTitleBlock( tb );
@ -1919,6 +1937,9 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet )
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;
@ -1932,7 +1953,7 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet )
switch( token )
{
case T_symbol:
screen->AddLibSymbol( ParseSymbol( symbolLibMap, true ) );
screen->AddLibSymbol( ParseSymbol( symbolLibMap ) );
break;
default:
@ -1991,10 +2012,16 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet )
break;
case T_symbol_instances:
if( aIsCopyableOnly )
Unexpected( T_symbol_instances );
parseSchSymbolInstances( screen );
break;
case T_bus_alias:
if( aIsCopyableOnly )
Unexpected( T_bus_alias );
parseBusAlias( screen );
break;
@ -2005,6 +2032,7 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet )
}
}
if( !aIsCopyableOnly )
screen->UpdateLocalLibSymbolLinks();
}

View File

@ -36,6 +36,7 @@
#include <class_library.h>
#include <schematic_lexer.h>
#include <sch_file_versions.h>
#include <default_values.h> // For some default values
@ -222,18 +223,30 @@ public:
void ParseLib( LIB_PART_MAP& aSymbolLibMap );
LIB_PART* ParseSymbol( LIB_PART_MAP& aSymbolLibMap, bool aIsSchematicLib = false );
LIB_PART* ParseSymbol( LIB_PART_MAP& aSymbolLibMap,
int aFileVersion = SEXPR_SYMBOL_LIB_FILE_VERSION );
LIB_ITEM* ParseDrawItem();
/**
* Parse a single schematic file into \a aSheet.
* Parse the internal #LINE_READER object into \a aSheet.
*
* When \a aIsCopyableOnly is true, only schematic objects that are viewable on the canvas
* for copy and paste purposes are parsed. Other schematic content such as bus definitions
* or instance data will throw an #IO_ERROR exception.
*
* When \a aIsCopyableOnly is false, full schematic file parsing is performed.
*
* @note This does not load any sub-sheets or decent complex sheet hierarchies.
*
* @param aSheet The #SCH_SHEET object to store the parsed schematic file.
* @param aIsCopyableOnly Load only the schematic objects that can be copied into \a aSheet
* if true. Otherwise, load the full schematic file format.
* @param aFileVersion The schematic file version to parser. Defaults to the schematic
* file being parsed when \a aIsCopyableOnly is false.
*/
void ParseSchematic( SCH_SHEET* aSheet );
void ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyablyOnly = false,
int aFileVersion = SEXPR_SCHEMATIC_FILE_VERSION );
/**
* Return whether a version number, if any was parsed, was too recent

View File

@ -389,8 +389,6 @@ public:
wxString GetFileName() const { return m_libFileName.GetFullPath(); }
static LIB_PART* LoadPart( LINE_READER& aReader, int aMajorVersion, int aMinorVersion,
LIB_PART_MAP* aMap = nullptr );
static void SaveSymbol( LIB_PART* aSymbol, OUTPUTFORMATTER& aFormatter,
int aNestLevel = 0, const wxString& aLibName = wxEmptyString );
};
@ -569,6 +567,16 @@ void SCH_SEXPR_PLUGIN::loadFile( const wxString& aFileName, SCH_SHEET* aSheet )
}
void SCH_SEXPR_PLUGIN::LoadContent( LINE_READER& aReader, SCH_SHEET* aSheet, int aFileVersion )
{
wxCHECK( aSheet, /* void */ );
SCH_SEXPR_PARSER parser( &aReader );
parser.ParseSchematic( aSheet, true, aFileVersion );
}
void SCH_SEXPR_PLUGIN::Save( const wxString& aFileName, SCH_SHEET* aSheet, KIWAY* aKiway,
const PROPERTIES* aProperties )
{
@ -1390,16 +1398,6 @@ void SCH_SEXPR_PLUGIN_CACHE::Load()
}
LIB_PART* SCH_SEXPR_PLUGIN_CACHE::LoadPart( LINE_READER& aReader, int aMajorVersion,
int aMinorVersion, LIB_PART_MAP* aMap )
{
std::unique_ptr< LIB_PART > part( new LIB_PART( wxEmptyString ) );
return part.release();
}
void SCH_SEXPR_PLUGIN_CACHE::Save()
{
if( !m_isModified )
@ -2285,10 +2283,15 @@ bool SCH_SEXPR_PLUGIN::IsSymbolLibWritable( const wxString& aLibraryPath )
}
LIB_PART* SCH_SEXPR_PLUGIN::ParsePart( LINE_READER& reader, int aMajorVersion,
int aMinorVersion )
LIB_PART* SCH_SEXPR_PLUGIN::ParsePart( LINE_READER& aReader, int aFileVersion )
{
return SCH_SEXPR_PLUGIN_CACHE::LoadPart( reader, aMajorVersion, aMinorVersion );
LIB_PART_MAP map;
SCH_SEXPR_PARSER parser( &aReader );
parser.NeedLEFT();
parser.NextTok();
return parser.ParseSymbol( map, aFileVersion );
}

View File

@ -24,6 +24,7 @@
#include <memory>
#include <sch_io_mgr.h>
#include <sch_file_versions.h>
#include <stack>
@ -87,8 +88,8 @@ public:
SCH_SHEET* aAppendToMe = nullptr,
const PROPERTIES* aProperties = nullptr ) override;
void LoadContent( LINE_READER& aReader, SCH_SCREEN* aScreen,
int version = EESCHEMA_VERSION );
void LoadContent( LINE_READER& aReader, SCH_SHEET* aSheet,
int aVersion = SEXPR_SCHEMATIC_FILE_VERSION );
void Save( const wxString& aFileName, SCH_SHEET* aSheet, KIWAY* aKiway,
const PROPERTIES* aProperties = nullptr ) override;
@ -121,7 +122,8 @@ public:
const wxString& GetError() const override { return m_error; }
static LIB_PART* ParsePart( LINE_READER& aReader, int majorVersion = 0, int minorVersion = 0 );
static LIB_PART* ParsePart( LINE_READER& aReader,
int aVersion = SEXPR_SCHEMATIC_FILE_VERSION );
static void FormatPart( LIB_PART* aPart, OUTPUTFORMATTER& aFormatter );
private:

View File

@ -38,7 +38,7 @@
#include <dialogs/dialog_edit_one_field.h>
#include <dialogs/dialog_edit_component_in_lib.h>
#include <dialogs/dialog_lib_edit_pin_table.h>
#include <sch_legacy_plugin.h>
#include <sch_sexpr_plugin.h>
#include <lib_text.h>
#include "lib_edit_tool.h"
#include <math/util.h> // for KiROUND
@ -627,7 +627,7 @@ int LIB_EDIT_TOOL::Copy( const TOOL_EVENT& aEvent )
LIB_PART* partCopy = new LIB_PART( *part );
STRING_FORMATTER formatter;
SCH_LEGACY_PLUGIN::FormatPart( partCopy, formatter );
SCH_SEXPR_PLUGIN::FormatPart( partCopy, formatter );
delete partCopy;
@ -654,8 +654,7 @@ int LIB_EDIT_TOOL::Paste( const TOOL_EVENT& aEvent )
try
{
reader.ReadLine();
newPart = SCH_LEGACY_PLUGIN::ParsePart( reader );
newPart = SCH_SEXPR_PLUGIN::ParsePart( reader );
}
catch( IO_ERROR& )
{

View File

@ -38,7 +38,7 @@
#include <netlist_exporters/netlist_exporter_pspice.h>
#include <netlist_object.h>
#include <sch_edit_frame.h>
#include <sch_legacy_plugin.h>
#include <sch_sexpr_plugin.h>
#include <sch_line.h>
#include <sch_painter.h>
#include <sch_sheet.h>
@ -1106,7 +1106,7 @@ bool SCH_EDITOR_CONTROL::doCopy()
}
STRING_FORMATTER formatter;
SCH_LEGACY_PLUGIN plugin;
SCH_SEXPR_PLUGIN plugin;
plugin.Format( &selection, &formatter );
@ -1177,18 +1177,22 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
return 0;
STRING_LINE_READER reader( text, "Clipboard" );
SCH_LEGACY_PLUGIN plugin;
SCH_SEXPR_PLUGIN plugin;
SCH_SCREEN paste_screen( &m_frame->GetScreen()->Kiway() );
SCH_SHEET paste_sheet;
SCH_SCREEN* paste_screen = new SCH_SCREEN( &m_frame->GetScreen()->Kiway() );
// Screen object on heap is owned by the sheet.
paste_sheet.SetScreen( paste_screen );
try
{
plugin.LoadContent( reader, &paste_screen );
plugin.LoadContent( reader, &paste_sheet );
}
catch( IO_ERROR& )
catch( IO_ERROR& ioe )
{
// If it wasn't content, then paste as text
paste_screen.Append( new SCH_TEXT( wxPoint( 0, 0 ), text ) );
paste_screen->Append( new SCH_TEXT( wxPoint( 0, 0 ), text ) );
}
bool forceKeepAnnotations = false;
@ -1206,7 +1210,7 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
if( forceDropAnnotations )
dropAnnotations = true;
// SCH_LEGACY_PLUGIN added the items to the paste screen, but not to the view or anything
// SCH_SEXP_PLUGIN added the items to the paste screen, but not to the view or anything
// else. Pull them back out to start with.
//
EDA_ITEMS loadedItems;
@ -1217,7 +1221,7 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
if( destFn.IsRelative() )
destFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
for( SCH_ITEM* item : paste_screen.Items() )
for( SCH_ITEM* item : paste_screen->Items() )
{
loadedItems.push_back( item );
@ -1258,10 +1262,7 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
}
// Remove the references from our temporary screen to prevent freeing on the DTOR
paste_screen.Clear( false );
// Now we can resolve the components and add everything to the screen, view, etc.
SYMBOL_LIB_TABLE* symLibTable = m_frame->Prj().SchSymbolLibTable();
paste_screen->Clear( false );
for( unsigned i = 0; i < loadedItems.size(); ++i )
{
@ -1271,6 +1272,19 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
{
SCH_COMPONENT* component = (SCH_COMPONENT*) item;
// The library symbol gets set from the cached library symbols in the current
// schematic not the symbol libraries. The cached library symbol may have
// changed from the original library symbol which would cause the copy to
// be incorrect.
SCH_SCREEN* currentScreen = m_frame->GetScreen();
wxCHECK2( currentScreen, continue );
auto it = currentScreen->GetLibSymbols().find( component->GetSchSymbolLibraryName() );
if( it != currentScreen->GetLibSymbols().end() )
component->SetLibSymbol( new LIB_PART( *it->second ) );
if( dropAnnotations )
{
const_cast<KIID&>( component->m_Uuid ) = KIID();
@ -1280,20 +1294,6 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
component->ClearAnnotation( nullptr );
component->SetUnit( unit );
}
LIB_PART* libSymbol = symLibTable->LoadSymbol( component->GetLibId() );
if( libSymbol )
{
component->SetLibSymbol( new LIB_PART( *libSymbol ) );
}
else
{
DisplayError( m_frame,
wxString::Format( _( "Symbol '%s' not found in library '%s'." ),
component->GetLibId().GetLibItemName().wx_str(),
component->GetLibId().GetLibNickname().wx_str() ) );
}
}
else
{