diff options
Diffstat (limited to 'embeddedobj/source/commonembedding/miscobj.cxx')
-rw-r--r-- | embeddedobj/source/commonembedding/miscobj.cxx | 203 |
1 files changed, 143 insertions, 60 deletions
diff --git a/embeddedobj/source/commonembedding/miscobj.cxx b/embeddedobj/source/commonembedding/miscobj.cxx index d65380cdc87e..f34a35a2c1ac 100644 --- a/embeddedobj/source/commonembedding/miscobj.cxx +++ b/embeddedobj/source/commonembedding/miscobj.cxx @@ -35,8 +35,15 @@ #include <cppuhelper/queryinterface.hxx> #include <comphelper/mimeconfighelper.hxx> +#include <utility> +#include <vcl/weld.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 <comphelper/diagnose_ex.hxx> #include <cppuhelper/supportsservice.hxx> #include <comphelper/sequenceashashmap.hxx> @@ -47,7 +54,7 @@ using namespace ::com::sun::star; -OCommonEmbeddedObject::OCommonEmbeddedObject( const uno::Reference< uno::XComponentContext >& rxContext, +OCommonEmbeddedObject::OCommonEmbeddedObject( uno::Reference< uno::XComponentContext > xContext, const uno::Sequence< beans::NamedValue >& aObjProps ) : m_bReadOnly( false ) , m_bDisposed( false ) @@ -55,14 +62,18 @@ OCommonEmbeddedObject::OCommonEmbeddedObject( const uno::Reference< uno::XCompon , m_nObjectState( -1 ) , m_nTargetState( -1 ) , m_nUpdateMode ( embed::EmbedUpdateModes::ALWAYS_UPDATE ) -, m_xContext( rxContext ) +, m_xContext(std::move( xContext )) , m_nMiscStatus( 0 ) , m_bEmbeddedScriptSupport( true ) , m_bDocumentRecoverySupport( true ) , 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 ) { @@ -71,7 +82,7 @@ OCommonEmbeddedObject::OCommonEmbeddedObject( const uno::Reference< uno::XCompon OCommonEmbeddedObject::OCommonEmbeddedObject( - const uno::Reference< uno::XComponentContext >& rxContext, + uno::Reference< uno::XComponentContext > xContext, const uno::Sequence< beans::NamedValue >& aObjProps, const uno::Sequence< beans::PropertyValue >& aMediaDescr, const uno::Sequence< beans::PropertyValue >& aObjectDescr ) @@ -81,14 +92,18 @@ OCommonEmbeddedObject::OCommonEmbeddedObject( , m_nObjectState( embed::EmbedStates::LOADED ) , m_nTargetState( -1 ) , m_nUpdateMode ( embed::EmbedUpdateModes::ALWAYS_UPDATE ) -, m_xContext( rxContext ) +, m_xContext(std::move( xContext )) , m_nMiscStatus( 0 ) , m_bEmbeddedScriptSupport( true ) , m_bDocumentRecoverySupport( true ) , 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 ) { @@ -103,7 +118,7 @@ void OCommonEmbeddedObject::CommonInit_Impl( const uno::Sequence< beans::NamedVa if ( !m_xContext.is() ) throw uno::RuntimeException(); - m_xDocHolder = new DocumentHolder( m_xContext, this ); + m_xDocHolder = new embeddedobj::DocumentHolder( m_xContext, this ); // parse configuration entries // TODO/LATER: in future UI names can be also provided here @@ -124,44 +139,8 @@ void OCommonEmbeddedObject::CommonInit_Impl( const uno::Sequence< beans::NamedVa if ( m_aClassID.getLength() != 16 /*|| !m_aDocServiceName.getLength()*/ ) throw uno::RuntimeException(); // something goes really wrong - // accepted states - m_aAcceptedStates = { /* [0] */ embed::EmbedStates::LOADED, - /* [1] */ embed::EmbedStates::RUNNING, - /* [2] */ embed::EmbedStates::INPLACE_ACTIVE, - /* [3] */ embed::EmbedStates::UI_ACTIVE, - /* [4] */ embed::EmbedStates::ACTIVE }; - assert(m_aAcceptedStates.getLength() == NUM_SUPPORTED_STATES); - - - // intermediate states - // In the following table the first index points to starting state, - // the second one to the target state, and the sequence referenced by - // first two indexes contains intermediate states, that should be - // passed by object to reach the target state. - // If the sequence is empty that means that indirect switch from start - // state to the target state is forbidden, only if direct switch is possible - // the state can be reached. - - m_pIntermediateStatesSeqs[0][2] = { embed::EmbedStates::RUNNING }; - - m_pIntermediateStatesSeqs[0][3] = { embed::EmbedStates::RUNNING, - embed::EmbedStates::INPLACE_ACTIVE }; - - m_pIntermediateStatesSeqs[0][4] = {embed::EmbedStates::RUNNING}; - - m_pIntermediateStatesSeqs[1][3] = { embed::EmbedStates::INPLACE_ACTIVE }; - - m_pIntermediateStatesSeqs[2][0] = { embed::EmbedStates::RUNNING }; - - m_pIntermediateStatesSeqs[3][0] = { embed::EmbedStates::INPLACE_ACTIVE, - embed::EmbedStates::RUNNING }; - - m_pIntermediateStatesSeqs[3][1] = { embed::EmbedStates::INPLACE_ACTIVE }; - - m_pIntermediateStatesSeqs[4][0] = { embed::EmbedStates::RUNNING }; - // verbs table - for ( auto const & verb : std::as_const(m_aObjectVerbs) ) + for (auto const& verb : m_aObjectVerbs) { if ( verb.VerbID == embed::EmbedVerbs::MS_OLEVERB_PRIMARY ) { @@ -224,26 +203,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); + m_aLinkTempFile = io::TempFile::create( m_xContext ); - if(m_aLinkTempFile.is()) - { - // completely copy content of original OLE data - uno::Reference < io::XOutputStream > xTempOut = m_aLinkTempFile->getOutputStream(); - ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOut ); - xTempOut->flush(); - xTempOut->closeOutput(); - - // 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 +345,123 @@ void OCommonEmbeddedObject::PostEvent_Impl( const OUString& aEventName ) } +int OCommonEmbeddedObject::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(m_xClientWindow); + + 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 important it has bLnkFileChg, always overwrite 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(m_xClientWindow); + 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; |