diff --git a/eeschema/lib_manager.cpp b/eeschema/lib_manager.cpp index 170ad695ce..013b74b7dc 100644 --- a/eeschema/lib_manager.cpp +++ b/eeschema/lib_manager.cpp @@ -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_MANAGER::getOriginalParts( const wxString& aLibrary ) +{ + wxArrayString aliases; + std::set 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 processed; - for( const auto& aliasName : aliases ) - { - 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 ); - } - } + for( auto part : getOriginalParts( aLibrary ) ) + buf.CreateBuffer( new LIB_PART( *part, nullptr ), new SCH_SCREEN( &m_frame.Kiway() ) ); 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 ); + 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(); wxCHECK( part, false ); - // TODO Enable buffering to avoid to disable too frequent file saves - //PROPERTIES properties; - //properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" ); + // set properties to prevent save file on every symbol save + 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; + // 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; } diff --git a/eeschema/lib_manager.h b/eeschema/lib_manager.h index cbab69818b..39f4f67858 100644 --- a/eeschema/lib_manager.h +++ b/eeschema/lib_manager.h @@ -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 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 ); diff --git a/eeschema/libedit.cpp b/eeschema/libedit.cpp index 260ce97723..1c553dc78b 100644 --- a/eeschema/libedit.cpp +++ b/eeschema/libedit.cpp @@ -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,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( aNewFile ) + if( !m_libMgr->SaveLibrary( aLibrary, libFileName.GetFullPath() ) ) { - 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 ) ) - { - msg.Printf( _( "Failed to save changes to symbol library file '%s'" ), - libFileName.GetFullPath() ); - DisplayErrorMessage( this, _( "Error saving library" ), msg ); - return false; - } + 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() );