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 bool LIB_MANAGER::IsLibraryModified( const wxString& aLibrary ) const
{ {
wxCHECK( LibraryExists( aLibrary ), false ); 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 ) LIB_MANAGER::LIB_BUFFER& LIB_MANAGER::getLibraryBuffer( const wxString& aLibrary )
{ {
auto it = m_libs.find( 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() ) if( it != m_libs.end() )
return it->second; return it->second;
wxArrayString aliases;
auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) ); auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) );
LIB_BUFFER& buf = ret.first->second; 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 ) for( auto part : getOriginalParts( aLibrary ) )
{ buf.CreateBuffer( new LIB_PART( *part, nullptr ), new SCH_SCREEN( &m_frame.Kiway() ) );
LIB_ALIAS* alias = m_symbolTable->LoadSymbol( aLibrary, aliasName );
LIB_PART* part = alias->GetPart();
if( !processed.count( part ) )
{
buf.CreateBuffer( new LIB_PART( *part, nullptr ), new SCH_SCREEN( &m_frame.Kiway() ) );
processed.insert( part );
}
}
return buf; return buf;
} }
@ -555,7 +599,6 @@ bool LIB_MANAGER::LIB_BUFFER::CreateBuffer( LIB_PART* aCopy, SCH_SCREEN* aScreen
// Set the parent library name, // Set the parent library name,
// otherwise it is empty as no library has been given as the owner during object construction // 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(); LIB_ID& libId = (LIB_ID&) aCopy->GetLibId();
libId.SetLibNickname( m_libName ); libId.SetLibNickname( m_libName );
++m_hash; ++m_hash;
@ -593,23 +636,34 @@ bool LIB_MANAGER::LIB_BUFFER::SaveBuffer( LIB_MANAGER::PART_BUFFER::PTR aPartBuf
SYMBOL_LIB_TABLE* aLibTable ) SYMBOL_LIB_TABLE* aLibTable )
{ {
wxCHECK( aPartBuf, false ); 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 );
aPartBuf->GetScreen()->ClrModify();
aPartBuf->SetOriginal( new LIB_PART( *part ) );
++m_hash;
return true;
}
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(); LIB_PART* part = aPartBuf->GetPart();
wxCHECK( part, false ); wxCHECK( part, false );
// TODO Enable buffering to avoid to disable too frequent file saves // set properties to prevent save file on every symbol save
//PROPERTIES properties; PROPERTIES properties;
//properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" ); properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" );
if( aLibTable->SaveSymbol( m_libName, new LIB_PART( *part ) ) == SYMBOL_LIB_TABLE::SAVE_OK ) // 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->GetScreen()->ClrModify();
aPartBuf->SetOriginal( new LIB_PART( *part ) ); aPartBuf->SetOriginal( new LIB_PART( *part ) );
++m_hash; ++m_hash;
return true; return true;
}
return false;
} }

View File

@ -38,6 +38,7 @@ class LIB_PART;
class LIB_BUFFER; class LIB_BUFFER;
class PART_LIB; class PART_LIB;
class SCH_SCREEN; class SCH_SCREEN;
class SCH_PLUGIN;
class LIB_EDIT_FRAME; class LIB_EDIT_FRAME;
class SYMBOL_LIB_TABLE; class SYMBOL_LIB_TABLE;
@ -163,6 +164,14 @@ public:
*/ */
bool FlushLibrary( const wxString& aLibrary ); 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. * Saves all changes to libraries.
* @return True if all changes have been flushed successfully, false otherwise. * @return True if all changes have been flushed successfully, false otherwise.
@ -328,9 +337,14 @@ private:
m_deleted.clear(); 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 ); 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 ///> Returns a part buffer with LIB_PART holding a particular alias
PART_BUFFER::PTR GetBuffer( const wxString& aAlias ) const PART_BUFFER::PTR GetBuffer( const wxString& aAlias ) const
{ {
@ -371,6 +385,9 @@ private:
friend class PART_BUFFER; 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 ///> Returns an existing library buffer or creates one to using
///> Symbol Library Table to get the original data. ///> Symbol Library Table to get the original data.
LIB_BUFFER& getLibraryBuffer( const wxString& aLibrary ); 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; wxFileName docFileName = libFileName;
docFileName.SetExt( DOC_EXT ); docFileName.SetExt( DOC_EXT );
// Copy .dcm file to .bck. // Copy .dcm file to .bck. // handle
if( docFileName.FileExists() ) if( docFileName.FileExists() )
{ {
backupFileName.SetExt( "bck" ); backupFileName.SetExt( "bck" );
@ -555,39 +554,12 @@ bool LIB_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
} }
} }
// Copy the library and document files to the new destination library files. if( !m_libMgr->SaveLibrary( aLibrary, libFileName.GetFullPath() ) )
if( aNewFile )
{ {
wxFileName src = prj.SchSymbolLibTable()->GetFullURI( GetCurLib() ); msg.Printf( _( "Failed to save changes to symbol library file '%s'" ),
libFileName.GetFullPath() );
if( !wxCopyFile( src.GetFullPath(), libFileName.GetFullPath() ) ) DisplayErrorMessage( this, _( "Error saving library" ), msg );
{ return false;
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 ) )
{
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() ); msg.Printf( _( "Symbol library file '%s' saved" ), libFileName.GetFullPath() );