Library Editor: enable part buffering for faster save, better 'save as' implementation

Previous 'save as' implementation simply copied the original file, so
the buffered changes were not save.
This commit is contained in:
Maciej Suminski 2017-11-13 14:58:39 +01:00
parent 9fcaa83b7d
commit f6f1dff9d0
3 changed files with 106 additions and 63 deletions

View File

@ -136,6 +136,47 @@ bool LIB_MANAGER::FlushLibrary( const wxString& aLibrary )
}
bool LIB_MANAGER::SaveLibrary( const wxString& aLibrary, const wxString& aFileName )
{
wxCHECK( LibraryExists( aLibrary ), false );
wxFileName fn( aFileName );
wxCHECK( !fn.FileExists() || fn.IsFileWritable(), false );
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
bool res = true; // assume all libraries are successfully saved
auto it = m_libs.find( aLibrary );
if( it != m_libs.end() )
{
// Handle buffered library
LIB_BUFFER& libBuf = it->second;
const auto& partBuffers = libBuf.GetBuffers();
for( const auto& partBuf : partBuffers )
{
if( !libBuf.SaveBuffer( partBuf, &*pi, true ) )
{
// Something went wrong, but try to save other libraries
res = false;
}
}
}
else
{
// Handle original library
PROPERTIES properties;
properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
for( auto part : getOriginalParts( aLibrary ) )
pi->SaveSymbol( aLibrary, new LIB_PART( *part ), &properties );
}
pi->SaveLibrary( aFileName );
return res;
}
bool LIB_MANAGER::IsLibraryModified( const wxString& aLibrary ) const
{
wxCHECK( LibraryExists( aLibrary ), false );
@ -465,6 +506,22 @@ bool LIB_MANAGER::addLibrary( const wxString& aFilePath, bool aCreate )
}
std::set<LIB_PART*> LIB_MANAGER::getOriginalParts( const wxString& aLibrary )
{
wxArrayString aliases;
std::set<LIB_PART*> parts;
m_symbolTable->EnumerateSymbolLib( aLibrary, aliases );
for( const auto& aliasName : aliases )
{
LIB_ALIAS* alias = m_symbolTable->LoadSymbol( aLibrary, aliasName );
parts.insert( alias->GetPart() );
}
return parts;
}
LIB_MANAGER::LIB_BUFFER& LIB_MANAGER::getLibraryBuffer( const wxString& aLibrary )
{
auto it = m_libs.find( aLibrary );
@ -472,24 +529,11 @@ LIB_MANAGER::LIB_BUFFER& LIB_MANAGER::getLibraryBuffer( const wxString& aLibrary
if( it != m_libs.end() )
return it->second;
wxArrayString aliases;
auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) );
LIB_BUFFER& buf = ret.first->second;
m_symbolTable->EnumerateSymbolLib( aLibrary, aliases );
// set collecting the processed LIB_PARTs
std::set<LIB_PART*> processed;
for( const auto& aliasName : aliases )
{
LIB_ALIAS* alias = m_symbolTable->LoadSymbol( aLibrary, aliasName );
LIB_PART* part = alias->GetPart();
if( !processed.count( part ) )
{
for( auto part : getOriginalParts( aLibrary ) )
buf.CreateBuffer( new LIB_PART( *part, nullptr ), new SCH_SCREEN( &m_frame.Kiway() ) );
processed.insert( part );
}
}
return buf;
}
@ -555,7 +599,6 @@ bool LIB_MANAGER::LIB_BUFFER::CreateBuffer( LIB_PART* aCopy, SCH_SCREEN* aScreen
// Set the parent library name,
// otherwise it is empty as no library has been given as the owner during object construction
// TODO create a class derived from
LIB_ID& libId = (LIB_ID&) aCopy->GetLibId();
libId.SetLibNickname( m_libName );
++m_hash;
@ -593,23 +636,34 @@ bool LIB_MANAGER::LIB_BUFFER::SaveBuffer( LIB_MANAGER::PART_BUFFER::PTR aPartBuf
SYMBOL_LIB_TABLE* aLibTable )
{
wxCHECK( aPartBuf, false );
LIB_PART* part = aPartBuf->GetPart();
wxCHECK( part, false );
wxCHECK( aLibTable->SaveSymbol( m_libName, new LIB_PART( *part ) ) != SYMBOL_LIB_TABLE::SAVE_OK, false );
// TODO Enable buffering to avoid to disable too frequent file saves
//PROPERTIES properties;
//properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
if( aLibTable->SaveSymbol( m_libName, new LIB_PART( *part ) ) == SYMBOL_LIB_TABLE::SAVE_OK )
{
aPartBuf->GetScreen()->ClrModify();
aPartBuf->SetOriginal( new LIB_PART( *part ) );
++m_hash;
return true;
}
return false;
bool LIB_MANAGER::LIB_BUFFER::SaveBuffer( LIB_MANAGER::PART_BUFFER::PTR aPartBuf,
SCH_PLUGIN* aPlugin, bool aBuffer )
{
wxCHECK( aPartBuf, false );
LIB_PART* part = aPartBuf->GetPart();
wxCHECK( part, false );
// set properties to prevent save file on every symbol save
PROPERTIES properties;
properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
// TODO there is no way to check if symbol has been successfully saved
aPlugin->SaveSymbol( m_libName, new LIB_PART( *part ), aBuffer ? &properties : nullptr );
aPartBuf->GetScreen()->ClrModify();
aPartBuf->SetOriginal( new LIB_PART( *part ) );
++m_hash;
return true;
}

View File

@ -38,6 +38,7 @@ class LIB_PART;
class LIB_BUFFER;
class PART_LIB;
class SCH_SCREEN;
class SCH_PLUGIN;
class LIB_EDIT_FRAME;
class SYMBOL_LIB_TABLE;
@ -163,6 +164,14 @@ public:
*/
bool FlushLibrary( const wxString& aLibrary );
/**
* Saves library to a file, including unsaved changes.
* @param aLibrary is the library name.
* @param aFileName is the target file name.
* @return True on success, false otherwise.
*/
bool SaveLibrary( const wxString& aLibrary, const wxString& aFileName );
/**
* Saves all changes to libraries.
* @return True if all changes have been flushed successfully, false otherwise.
@ -328,9 +337,14 @@ private:
m_deleted.clear();
}
///> Saves stored modifications to a Symbol Library Table
///> Saves stored modifications to Symbol Lib Table. It may result in saving the symbol
///> to disk as well, depending on the row properties.
bool SaveBuffer( PART_BUFFER::PTR aPartBuf, SYMBOL_LIB_TABLE* aLibTable );
///> Saves stored modificatiosn using a plugin. aBuffer decides whether the changes
///> should be cached or stored directly to the disk (for SCH_LEGACY_PLUGIN).
bool SaveBuffer( PART_BUFFER::PTR aPartBuf, SCH_PLUGIN* aPlugin, bool aBuffer );
///> Returns a part buffer with LIB_PART holding a particular alias
PART_BUFFER::PTR GetBuffer( const wxString& aAlias ) const
{
@ -371,6 +385,9 @@ private:
friend class PART_BUFFER;
};
///> Returns a set of LIB_PART objects belonging to the original library
std::set<LIB_PART*> getOriginalParts( const wxString& aLibrary );
///> Returns an existing library buffer or creates one to using
///> Symbol Library Table to get the original data.
LIB_BUFFER& getLibraryBuffer( const wxString& aLibrary );

View File

@ -535,10 +535,9 @@ bool LIB_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
}
wxFileName docFileName = libFileName;
docFileName.SetExt( DOC_EXT );
// Copy .dcm file to .bck.
// Copy .dcm file to .bck. // handle
if( docFileName.FileExists() )
{
backupFileName.SetExt( "bck" );
@ -555,40 +554,13 @@ bool LIB_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
}
}
// Copy the library and document files to the new destination library files.
if( aNewFile )
{
wxFileName src = prj.SchSymbolLibTable()->GetFullURI( GetCurLib() );
if( !wxCopyFile( src.GetFullPath(), libFileName.GetFullPath() ) )
{
msg.Printf( _( "Failed to copy symbol library file '%s'" ), libFileName.GetFullPath() );
DisplayError( this, msg );
return false;
}
src.SetExt( DOC_EXT );
if( !wxCopyFile( src.GetFullPath(), docFileName.GetFullPath() ) )
{
msg.Printf( _( "Failed to copy symbol library document file '%s'" ),
docFileName.GetFullPath() );
DisplayError( this, msg );
return false;
}
}
// Update symbol changes in library.
if( GetScreen()->IsModify() )
{
if( !m_libMgr->FlushLibrary( aLibrary ) )
if( !m_libMgr->SaveLibrary( aLibrary, libFileName.GetFullPath() ) )
{
msg.Printf( _( "Failed to save changes to symbol library file '%s'" ),
libFileName.GetFullPath() );
DisplayErrorMessage( this, _( "Error saving library" ), msg );
return false;
}
}
msg.Printf( _( "Symbol library file '%s' saved" ), libFileName.GetFullPath() );
wxString msg1;