diff options
author | Juergen Funk <juergen.funk_ml@cib.de> | 2022-02-22 09:19:29 +0100 |
---|---|---|
committer | Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de> | 2022-05-10 09:02:01 +0200 |
commit | cf650ceaafb4d3a3f46991dc1b12efa0e37a71f9 (patch) | |
tree | 0bcbc4178c8f940c747507f4d24bef2685dfa399 /embeddedobj/source/commonembedding/miscobj.cxx | |
parent | 63a2f314250b05d484747fafc4a814a4553f461e (diff) |
tdf#147590 update OLE object after document refresh
Regression from b099da78a6f0b3e120f706714003b05d84d11e70
we didn't update linked OLE document after document reload
Change-Id: I8e52f6430f454b276cb43449c6f7a3b0e07e909f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130692
Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>
Tested-by: Jenkins
Diffstat (limited to 'embeddedobj/source/commonembedding/miscobj.cxx')
-rw-r--r-- | embeddedobj/source/commonembedding/miscobj.cxx | 153 |
1 files changed, 136 insertions, 17 deletions
diff --git a/embeddedobj/source/commonembedding/miscobj.cxx b/embeddedobj/source/commonembedding/miscobj.cxx index a5d5573416d1..f41d35957b5d 100644 --- a/embeddedobj/source/commonembedding/miscobj.cxx +++ b/embeddedobj/source/commonembedding/miscobj.cxx @@ -35,6 +35,13 @@ #include <cppuhelper/queryinterface.hxx> #include <comphelper/mimeconfighelper.hxx> +#include <vcl/weld.hxx> +#include <unotools/resmgr.hxx> +#include <vcl/stdtext.hxx> +#include <strings.hrc> +#include <osl/file.hxx> +#include <comphelper/DirectoryHelper.hxx> + #include <vcl/svapp.hxx> #include <tools/diagnose_ex.h> #include <cppuhelper/supportsservice.hxx> @@ -62,7 +69,11 @@ OCommonEmbeddedObject::OCommonEmbeddedObject( const uno::Reference< uno::XCompon , m_bWaitSaveCompleted( false ) , m_bIsLinkURL( false ) , m_bLinkTempFileChanged( false ) +, m_pLinkFile( ) +, m_bOleUpdate( false ) +, m_bInHndFunc( false ) , m_bLinkHasPassword( false ) +, m_aLinkTempFile( ) , m_bHasClonedSize( false ) , m_nClonedMapUnit( 0 ) { @@ -88,7 +99,11 @@ OCommonEmbeddedObject::OCommonEmbeddedObject( , m_bWaitSaveCompleted( false ) , m_bIsLinkURL( true ) , m_bLinkTempFileChanged( false ) +, m_pLinkFile( ) +, m_bOleUpdate( false ) +, m_bInHndFunc( false ) , m_bLinkHasPassword( false ) +, m_aLinkTempFile( ) , m_bHasClonedSize( false ) , m_nClonedMapUnit( 0 ) { @@ -224,26 +239,13 @@ void OCommonEmbeddedObject::LinkInit_Impl( // task-ID above) // // open OLE original data as read input file - uno::Reference< ucb::XSimpleFileAccess3 > xTempAccess( ucb::SimpleFileAccess::create( m_xContext ) ); - uno::Reference< io::XInputStream > xInStream( xTempAccess->openFileRead( m_aLinkURL ) ); - - if(xInStream.is()) + if ( comphelper::DirectoryHelper::fileExists( m_aLinkURL ) ) { // create temporary file - m_aLinkTempFile = io::TempFile::create(m_xContext); - uno::Reference< ucb::XSimpleFileAccess > xTempOutAccess(ucb::SimpleFileAccess::create(m_xContext)); - // if the temp stream is used, then the temp file remains locked - uno::Reference< io::XOutputStream > xOutStream(xTempOutAccess->openFileWrite(m_aLinkTempFile->getUri())); - - if(m_aLinkTempFile.is()) - { - // completely copy content of original OLE data - ::comphelper::OStorageHelper::CopyInputToOutput(xInStream, xOutStream); + m_aLinkTempFile = io::TempFile::create( m_xContext ); - // reset flag m_bLinkTempFileChanged, so it will also work for multiple - // save op's of the containing file/document - m_bLinkTempFileChanged = false; - } + m_pLinkFile.reset( new FileChangedChecker( m_aLinkURL ) ); + handleLinkedOLE( CopyBackToOLELink::CopyLinkToTempInit ); } } @@ -379,6 +381,123 @@ void OCommonEmbeddedObject::PostEvent_Impl( const OUString& aEventName ) } +static int ShowMsgDialog( TranslateId Msg, const OUString& sFileName ) +{ + std::locale aResLocale = Translate::Create( "emo" ); + OUString aMsg = Translate::get( Msg, aResLocale ); + OUString aBtn = Translate::get( BTN_OVERWRITE_TEXT, aResLocale ); + OUString aTemp = sFileName; + + osl::FileBase::getSystemPathFromFileURL( sFileName, aTemp ); + + aMsg = aMsg.replaceFirst( "%{filename}", aTemp ); + weld::Window* pParent = Application::GetFrameWeld( nullptr ); + + std::unique_ptr<weld::MessageDialog> xQueryBox (Application::CreateMessageDialog( pParent, + VclMessageType::Warning, VclButtonsType::NONE, aMsg ) ); + xQueryBox->add_button( aBtn, RET_YES ); + xQueryBox->add_button( GetStandardText( StandardButtonType::Cancel ), RET_CANCEL ); + xQueryBox->set_default_response( RET_CANCEL ); + + return xQueryBox->run(); +} + + +void OCommonEmbeddedObject::handleLinkedOLE( CopyBackToOLELink eState ) +{ + // do not refresh and autosave at the same time + // when refresh all, then get both Link and Ole Update, in this case ignore OLE-refresh + if ( m_bInHndFunc || m_bOleUpdate || !m_aLinkTempFile.is() ) + return; + + m_bInHndFunc = true; + + bool bLnkFileChg = m_pLinkFile->hasFileChanged( false ); + bool bTmpFileChg = m_bLinkTempFileChanged; + + + if ( eState != CopyBackToOLELink::CopyLinkToTempInit && !bLnkFileChg && !bTmpFileChg ) + { + // no changes + eState = CopyBackToOLELink::NoCopy; + } + else if ( ( eState == CopyBackToOLELink::CopyTempToLink ) && bLnkFileChg && !bTmpFileChg ) + { + // Save pressed, but the Link-file is changed, but not the temp-file + // in this case update the object with new link data + eState = CopyBackToOLELink::CopyLinkToTempRefresh; + } + else if ( ( eState == CopyBackToOLELink::CopyTempToLink ) && bLnkFileChg && bTmpFileChg ) + { + // Save pressed, but the Link-file is changed, question to user for overwrite + if ( ShowMsgDialog(STR_OVERWRITE_LINK, m_aLinkURL) == RET_CANCEL ) + eState = CopyBackToOLELink::NoCopy; + } + else if ( ( eState == CopyBackToOLELink::CopyLinkToTemp ) && bTmpFileChg ) + { + // Refresh pressed, but the Temp-file is changed, question to user for overwrite + // it is not importent it has bLnkFileChg, always overwite the temp-file + if ( ShowMsgDialog( STR_OVERWRITE_TEMP, m_aLinkURL ) == RET_CANCEL ) + eState = CopyBackToOLELink::NoCopy; + } + + auto writeFile = [ this ]( const OUString& SrcName, const OUString& DesName ) + { + uno::Reference < ucb::XSimpleFileAccess2 > xWriteAccess( ucb::SimpleFileAccess::create( m_xContext ) ); + uno::Reference < ucb::XSimpleFileAccess > xReadAccess( ucb::SimpleFileAccess::create( m_xContext ) ); + + try + { + uno::Reference < io::XInputStream > xInStream( xReadAccess->openFileRead (SrcName ) ); + + // This is *needed* since OTempFileService calls OTempFileService::readBytes which + // ensures the SvStream mpStream gets/is opened, *but* also sets the mnCachedPos from + // OTempFileService which still points to the end-of-file (from write-cc'ing). + uno::Reference < io::XSeekable > xSeek( xInStream, uno::UNO_QUERY_THROW ); + xSeek->seek( 0 ); + + xWriteAccess->writeFile( DesName, xInStream ); + m_bLinkTempFileChanged = false; + // store the new timestamp + m_pLinkFile->hasFileChanged(); + } + catch ( const uno::Exception& ex ) + { + OUString aMsg; + osl::FileBase::getSystemPathFromFileURL( SrcName, aMsg ); + aMsg = ex.Message + "\n\n" + aMsg; + weld::Window* pParent = Application::GetFrameWeld( nullptr ); + std::unique_ptr<weld::MessageDialog> xQueryBox( Application::CreateMessageDialog( pParent, + VclMessageType::Error, VclButtonsType::Ok, aMsg ) ); + + xQueryBox->run(); + } + }; + + switch ( eState ) + { + case CopyBackToOLELink::NoCopy: + break; + case CopyBackToOLELink::CopyLinkToTemp: // copy Link-File to Temp-File (Refresh) + case CopyBackToOLELink::CopyLinkToTempInit: //create temp file + writeFile( m_aLinkURL, m_aLinkTempFile->getUri() ); + break; + case CopyBackToOLELink::CopyTempToLink: // copy Temp-File to Link-File (Save) + // tdf#141529 if we have a changed copy of the original OLE data we now + // need to write it back 'over' the original OLE data + writeFile( m_aLinkTempFile->getUri(), m_aLinkURL ); + break; + case CopyBackToOLELink::CopyLinkToTempRefresh: // need a Refresh not save + // do nothing + break; + default: + break; + } + + m_bInHndFunc = false; +} + + uno::Any SAL_CALL OCommonEmbeddedObject::queryInterface( const uno::Type& rType ) { uno::Any aReturn; |