diff --git a/comphelper/source/container/embeddedobjectcontainer.cxx b/comphelper/source/container/embeddedobjectcontainer.cxx index 2d85b73f44ba..094597fe6d06 100644 --- a/comphelper/source/container/embeddedobjectcontainer.cxx +++ b/comphelper/source/container/embeddedobjectcontainer.cxx @@ -1158,7 +1158,8 @@ namespace { } -bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEmbedded,const uno::Reference < embed::XStorage >& _xStorage) +bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEmbedded, bool _bAutoSaveEvent, + const uno::Reference < embed::XStorage >& _xStorage) { bool bResult = false; try @@ -1222,7 +1223,7 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); if ( xPersist.is() ) { - uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 2 : 3 ); + uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 3 : 4 ); auto pArgs = aArgs.getArray(); pArgs[0].Name = "StoreVisualReplacement"; pArgs[0].Value <<= !_bOasisFormat; @@ -1230,11 +1231,15 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm // if it is an embedded object or the optimized inserting fails the normal inserting should be done pArgs[1].Name = "CanTryOptimization"; pArgs[1].Value <<= !_bCreateEmbedded; + + pArgs[2].Name = "AutoSaveEvent"; + pArgs[2].Value <<= _bAutoSaveEvent; + if ( !_bOasisFormat ) { // if object has no cached replacement it will use this one - pArgs[2].Name = "VisualReplacement"; - pArgs[2].Value <<= xStream; + pArgs[3].Name = "VisualReplacement"; + pArgs[3].Value <<= xStream; } try diff --git a/embeddedobj/Library_embobj.mk b/embeddedobj/Library_embobj.mk index 35a654835dae..18cf55518d44 100644 --- a/embeddedobj/Library_embobj.mk +++ b/embeddedobj/Library_embobj.mk @@ -21,6 +21,10 @@ $(eval $(call gb_Library_set_include,embobj,\ $$(INCLUDE) \ )) +$(eval $(call gb_Library_add_defs,embobj,\ + -DEMBOBJ_DLLIMPLEMENTATION \ +)) + $(eval $(call gb_Library_use_external,embobj,boost_headers)) $(eval $(call gb_Library_use_sdk_api,embobj)) diff --git a/embeddedobj/source/commonembedding/embedobj.cxx b/embeddedobj/source/commonembedding/embedobj.cxx index 223f25e6302c..240112b2483e 100644 --- a/embeddedobj/source/commonembedding/embedobj.cxx +++ b/embeddedobj/source/commonembedding/embedobj.cxx @@ -639,6 +639,13 @@ void SAL_CALL OCommonEmbeddedObject::setContainerName( const OUString& sName ) m_aContainerName = sName; } +void OCommonEmbeddedObject::SetOleState(bool bIsOleUpdate) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_bOleUpdate = bIsOleUpdate; +} + css::uno::Reference< css::uno::XInterface > SAL_CALL OCommonEmbeddedObject::getParent() { return m_xParent; 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 #include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -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())); + m_aLinkTempFile = io::TempFile::create( m_xContext ); - if(m_aLinkTempFile.is()) - { - // completely copy content of original OLE data - ::comphelper::OStorageHelper::CopyInputToOutput(xInStream, xOutStream); - - // 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 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 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; diff --git a/embeddedobj/source/commonembedding/persistence.cxx b/embeddedobj/source/commonembedding/persistence.cxx index 77bc947650af..b32d07f1c59c 100644 --- a/embeddedobj/source/commonembedding/persistence.cxx +++ b/embeddedobj/source/commonembedding/persistence.cxx @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -392,6 +393,8 @@ uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadLink_Impl() try { + handleLinkedOLE(CopyBackToOLELink::CopyLinkToTemp); + // the document is not really an embedded one, it is a link EmbedAndReparentDoc_Impl( xDocument ); @@ -1254,12 +1257,14 @@ void SAL_CALL OCommonEmbeddedObject::storeAsEntry( const uno::Reference< embed:: const uno::Sequence< beans::PropertyValue >& lArguments, const uno::Sequence< beans::PropertyValue >& lObjArgs ) { - // TODO: use lObjArgs - ::osl::ResettableMutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO + bool AutoSaveEvent = false; + utl::MediaDescriptor lArgs(lObjArgs); + lArgs[utl::MediaDescriptor::PROP_AUTOSAVEEVENT] >>= AutoSaveEvent; + if ( m_nObjectState == -1 ) { // the object is still not loaded @@ -1279,26 +1284,8 @@ void SAL_CALL OCommonEmbeddedObject::storeAsEntry( const uno::Reference< embed:: { m_aNewEntryName = sEntName; - if(m_aLinkTempFile.is() && m_bLinkTempFileChanged) - { - // 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 - uno::Reference < ucb::XSimpleFileAccess2 > xFileAccess(ucb::SimpleFileAccess::create( m_xContext )); - - uno::Reference< ucb::XSimpleFileAccess > xTempAccess(ucb::SimpleFileAccess::create(m_xContext)); - // if the temp stream is used, then the temp file remains locked - uno::Reference< io::XInputStream > xInStream(xTempAccess->openFileRead(m_aLinkTempFile->getUri())); - // 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); - - xFileAccess->writeFile(m_aLinkURL, xInStream); - - // reset flag m_bLinkTempFileChanged - m_bLinkTempFileChanged = false; - } + if ( !AutoSaveEvent ) + handleLinkedOLE(CopyBackToOLELink::CopyTempToLink); return; } diff --git a/embeddedobj/source/inc/commonembobj.hxx b/embeddedobj/source/inc/commonembobj.hxx index 785a28eaf0fd..61abe0299ee1 100644 --- a/embeddedobj/source/inc/commonembobj.hxx +++ b/embeddedobj/source/inc/commonembobj.hxx @@ -36,9 +36,11 @@ #include #include #include +#include #include #include #include +#include namespace com::sun::star { namespace embed { @@ -76,6 +78,7 @@ class Interceptor; * document model successfully. */ class OCommonEmbeddedObject : public css::embed::XEmbeddedObject + , public css::embed::EmbeddedUpdate , public css::embed::XEmbedPersist2 , public css::embed::XLinkageSupport , public css::embed::XInplaceObject @@ -141,6 +144,9 @@ protected: bool m_bIsLinkURL; bool m_bLinkTempFileChanged; + ::std::unique_ptr< FileChangedChecker > m_pLinkFile; + bool m_bOleUpdate; + bool m_bInHndFunc; // embedded object related stuff OUString m_aEntryName; @@ -193,6 +199,16 @@ private: void Deactivate(); + // when State = CopyTempToLink -> the user pressed the save button + // when change in embedded part then copy to the linked-file + // CopyLinkToTemp -> the user pressed the refresh button + // when change in linked-file then copy to the embedded part (temp-file) + // CopyLinkToTempInit -> create the temp file + // CopyLinkToTempRefresh -> when save and Link change but not temp then update temp + enum class CopyBackToOLELink {NoCopy, CopyTempToLink, CopyLinkToTemp, CopyLinkToTempInit, CopyLinkToTempRefresh}; + + void handleLinkedOLE( CopyBackToOLELink eState ); + void StateChangeNotification_Impl( bool bBeforeChange, sal_Int32 nOldState, sal_Int32 nNewState,::osl::ResettableMutexGuard& _rGuard ); void SwitchStateTo_Impl( sal_Int32 nNextState ); @@ -294,6 +310,10 @@ public: virtual void SAL_CALL setContainerName( const OUString& sName ) override; +// EmbeddedUpdate + + virtual void SetOleState(bool bIsOleUpdate) override; + // XVisualObject diff --git a/embeddedobj/source/inc/strings.hrc b/embeddedobj/source/inc/strings.hrc new file mode 100644 index 000000000000..a3b323c54cf3 --- /dev/null +++ b/embeddedobj/source/inc/strings.hrc @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#define NC_(Context, String) TranslateId(Context, reinterpret_cast(u8##String)) + +#define BTN_OVERWRITE_TEXT NC_("BTN_OVERWRITE_TEXT", "Overwrite") +#define STR_OVERWRITE_LINK NC_("STR_OVERWRITE_LINK", "You have made changes to the %{filename}, saving will overwrite the data from the inserted object.\n\nDo you still want to overwrite this data?") +#define STR_OVERWRITE_TEMP NC_("STR_OVERWRITE_TEMP", "You have changed the data in the inserted object which will be overwritten by updating the %{filename}.\n\nDo you still want to overwrite this data?") + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx index 86715bda0057..e3321773256f 100644 --- a/framework/source/services/autorecovery.cxx +++ b/framework/source/services/autorecovery.cxx @@ -3008,6 +3008,8 @@ void AutoRecovery::implts_saveOneDoc(const OUString& // for make hyperlinks working lNewArgs[utl::MediaDescriptor::PROP_DOCUMENTBASEURL] <<= OUString(); + lNewArgs[utl::MediaDescriptor::PROP_AUTOSAVEEVENT] <<= true; + // try to save this document as a new temp file every time. // Mark AutoSave state as "INCOMPLETE" if it failed. // Because the last temp file is too old and does not include all changes. diff --git a/include/comphelper/embeddedobjectcontainer.hxx b/include/comphelper/embeddedobjectcontainer.hxx index c477a6fbe8c2..cc040da152c3 100644 --- a/include/comphelper/embeddedobjectcontainer.hxx +++ b/include/comphelper/embeddedobjectcontainer.hxx @@ -166,6 +166,7 @@ public: bool StoreChildren(bool _bOasisFormat,bool _bObjectsOnly); bool StoreAsChildren( bool _bOasisFormat ,bool _bCreateEmbedded + ,bool _bAutoSaveEvent ,const css::uno::Reference < css::embed::XStorage >& _xStorage); static css::uno::Reference< css::io::XInputStream > GetGraphicReplacementStream( diff --git a/include/embeddedobj/embeddedupdate.hxx b/include/embeddedobj/embeddedupdate.hxx new file mode 100644 index 000000000000..1db3f36d61dc --- /dev/null +++ b/include/embeddedobj/embeddedupdate.hxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace embed +{ +/** This class is only used to tell the OCommonEmbeddedObject class + that the following call is an Link- / Ole-refresh. + + @since LibreOffice 7.4 + */ +class EMBOBJ_DLLPUBLIC EmbeddedUpdate +{ + /** By "Refresh all" is used to perform an OLE update and a link update. + In the case of a link update, the class OCommonEmbeddedObject is + informed with true that a link update will take place next + + @param bIsOleUpdate + what kind of update, when true is OLE-Object + when false is Link-Object + */ +public: + virtual void SetOleState(bool bIsOleUpdate) = 0; + + EmbeddedUpdate() = default; + virtual ~EmbeddedUpdate() = default; + +private: + EmbeddedUpdate(const EmbeddedUpdate&) = delete; + EmbeddedUpdate& operator=(const EmbeddedUpdate&) = delete; +}; +}; +}; +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/embeddedobj/embobjdllapi.h b/include/embeddedobj/embobjdllapi.h new file mode 100644 index 000000000000..36aa54217fb9 --- /dev/null +++ b/include/embeddedobj/embobjdllapi.h @@ -0,0 +1,20 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#if defined(EMBOBJ_DLLIMPLEMENTATION) +#define EMBOBJ_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define EMBOBJ_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/svtools/embedhlp.hxx b/include/svtools/embedhlp.hxx index 9d4cb8e85c39..4930e5b7630b 100644 --- a/include/svtools/embedhlp.hxx +++ b/include/svtools/embedhlp.hxx @@ -49,6 +49,7 @@ class SVT_DLLPUBLIC EmbeddedObjectRef SVT_DLLPRIVATE std::unique_ptr GetGraphicStream( bool bUpdate ) const; SVT_DLLPRIVATE void GetReplacement( bool bUpdate ); + SVT_DLLPRIVATE void UpdateOleObject( bool bUpdateOle); EmbeddedObjectRef& operator = ( const EmbeddedObjectRef& ) = delete; @@ -101,7 +102,9 @@ public: const css::uno::Reference< css::io::XInputStream >& xInGrStream, const OUString& rMediaType ); - void UpdateReplacement(); + // bUpdateOle = false udate the Link-Objects + // = true update the OLE-Objects + void UpdateReplacement( bool bUpdateOle = false ); void UpdateReplacementOnDemand(); void Lock( bool bLock = true ); void Clear(); diff --git a/include/svtools/filechangedchecker.hxx b/include/svtools/filechangedchecker.hxx index d63d146688c6..9800654678fa 100644 --- a/include/svtools/filechangedchecker.hxx +++ b/include/svtools/filechangedchecker.hxx @@ -35,7 +35,11 @@ private: public: void resetTimer(); - bool hasFileChanged(); + // bUpdate = true when file has changed, get the return and the object get the new time + // = false when file has changed, only get the return, not change the object + bool hasFileChanged(bool bUpdate = true); FileChangedChecker(const OUString& rFilename, const ::std::function& rCallback); + // with out Timer function + FileChangedChecker(const OUString& rFilename); }; diff --git a/include/unotools/mediadescriptor.hxx b/include/unotools/mediadescriptor.hxx index 1e4b3c064d1c..92728fa51972 100644 --- a/include/unotools/mediadescriptor.hxx +++ b/include/unotools/mediadescriptor.hxx @@ -101,6 +101,7 @@ class UNOTOOLS_DLLPUBLIC MediaDescriptor : public comphelper::SequenceAsHashMap static constexpr OUStringLiteral PROP_VIEWONLY = u"ViewOnly"; static constexpr OUStringLiteral PROP_DOCUMENTBASEURL = u"DocumentBaseURL"; static constexpr OUStringLiteral PROP_SUGGESTEDSAVEASNAME = u"SuggestedSaveAsName"; + static constexpr OUStringLiteral PROP_AUTOSAVEEVENT = u"AutoSaveEvent"; // interface public: diff --git a/reportdesign/source/core/api/ReportDefinition.cxx b/reportdesign/source/core/api/ReportDefinition.cxx index 638b7a87a631..e9f5393a5e7c 100644 --- a/reportdesign/source/core/api/ReportDefinition.cxx +++ b/reportdesign/source/core/api/ReportDefinition.cxx @@ -1291,6 +1291,8 @@ void SAL_CALL OReportDefinition::storeToStorage( const uno::Reference< embed::XS uno::Sequence< uno::Any > aDelegatorArguments; utl::MediaDescriptor aDescriptor( _aMediaDescriptor ); lcl_extractAndStartStatusIndicator( aDescriptor, xStatusIndicator, aDelegatorArguments ); + bool AutoSaveEvent = false; + aDescriptor[utl::MediaDescriptor::PROP_AUTOSAVEEVENT] >>= AutoSaveEvent; // properties uno::Sequence < beans::PropertyValue > aProps; @@ -1382,7 +1384,7 @@ void SAL_CALL OReportDefinition::storeToStorage( const uno::Reference< embed::XS if ( _xStorageToSaveTo == m_pImpl->m_xStorage ) bPersist = m_pImpl->m_pObjectContainer->StoreChildren(true,false); else - bPersist = m_pImpl->m_pObjectContainer->StoreAsChildren(true,true,_xStorageToSaveTo); + bPersist = m_pImpl->m_pObjectContainer->StoreAsChildren(true,true,AutoSaveEvent,_xStorageToSaveTo); if( bPersist ) m_pImpl->m_pObjectContainer->SetPersistentEntries(m_pImpl->m_xStorage); diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx index fec08d32a0ba..288b6a7ae6a9 100644 --- a/sfx2/source/doc/objstor.cxx +++ b/sfx2/source/doc/objstor.cxx @@ -76,6 +76,7 @@ #include #include #include +#include #include #include #include @@ -3242,10 +3243,14 @@ bool SfxObjectShell::SaveAsChildren( SfxMedium& rMedium ) return true; } + bool AutoSaveEvent = false; + utl::MediaDescriptor lArgs(rMedium.GetArgs()); + lArgs[utl::MediaDescriptor::PROP_AUTOSAVEEVENT] >>= AutoSaveEvent; + if ( pImpl->mxObjectContainer ) { bool bOasis = ( SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60 ); - GetEmbeddedObjectContainer().StoreAsChildren(bOasis,SfxObjectCreateMode::EMBEDDED == eCreateMode,xStorage); + GetEmbeddedObjectContainer().StoreAsChildren(bOasis,SfxObjectCreateMode::EMBEDDED == eCreateMode,AutoSaveEvent,xStorage); } uno::Sequence aExceptions; diff --git a/svtools/source/misc/embedhlp.cxx b/svtools/source/misc/embedhlp.cxx index 29e427799c82..809a2b155790 100644 --- a/svtools/source/misc/embedhlp.cxx +++ b/svtools/source/misc/embedhlp.cxx @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -878,7 +879,7 @@ bool EmbeddedObjectRef::IsChart(const css::uno::Reference < css::embed::XEmbedde || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId; } -void EmbeddedObjectRef::UpdateReplacement() +void EmbeddedObjectRef::UpdateReplacement( bool bUpdateOle ) { if (mpImpl->bUpdating) { @@ -886,10 +887,20 @@ void EmbeddedObjectRef::UpdateReplacement() return; } mpImpl->bUpdating = true; + UpdateOleObject( bUpdateOle ); GetReplacement(true); + UpdateOleObject( false ); mpImpl->bUpdating = false; } +void EmbeddedObjectRef::UpdateOleObject( bool bUpdateOle ) +{ + embed::EmbeddedUpdate* pObj = dynamic_cast (GetObject().get()); + if( pObj ) + pObj->SetOleState( bUpdateOle ); +} + + void EmbeddedObjectRef::UpdateReplacementOnDemand() { mpImpl->pGraphic.reset(); diff --git a/svtools/source/misc/filechangedchecker.cxx b/svtools/source/misc/filechangedchecker.cxx index 8536eb0bda57..dd7cf22b924c 100644 --- a/svtools/source/misc/filechangedchecker.cxx +++ b/svtools/source/misc/filechangedchecker.cxx @@ -21,7 +21,7 @@ FileChangedChecker::FileChangedChecker(const OUString& rFilename, , mLastModTime() , mpCallback(rCallback) { - // Get the curren last file modified Status + // Get the current last file modified Status getCurrentModTime(mLastModTime); // associate the callback function for the Timer @@ -34,10 +34,23 @@ FileChangedChecker::FileChangedChecker(const OUString& rFilename, resetTimer(); } +FileChangedChecker::FileChangedChecker(const OUString& rFilename) + : mTimer("") + , mFileName(rFilename) + , mLastModTime() + , mpCallback(nullptr) +{ + // Get the current last file modified Status + getCurrentModTime(mLastModTime); +} + void FileChangedChecker::resetTimer() { + if (mpCallback == nullptr) + return; + // Start the Idle if it's not active - if(!mTimer.IsActive()) + if (!mTimer.IsActive()) mTimer.Start(); // Set lowest Priority @@ -61,7 +74,7 @@ bool FileChangedChecker::getCurrentModTime(TimeValue& o_rValue) const return true; } -bool FileChangedChecker::hasFileChanged() +bool FileChangedChecker::hasFileChanged(bool bUpdate) { // Get the current file Status TimeValue newTime={0,0}; @@ -75,7 +88,8 @@ bool FileChangedChecker::hasFileChanged() { // Since the file has changed, set the new status as the file status and // return True - mLastModTime = newTime ; + if(bUpdate) + mLastModTime = newTime ; return true; } diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx index b2415419eb5e..3358043a2b8d 100644 --- a/sw/source/core/view/viewsh.cxx +++ b/sw/source/core/view/viewsh.cxx @@ -757,7 +757,7 @@ void SwViewShell::UpdateOleObjectPreviews() SwOLEObj& rOleObj = pOleNode->GetOLEObj(); svt::EmbeddedObjectRef& rObject = rOleObj.GetObject(); - rObject.UpdateReplacement(); + rObject.UpdateReplacement( true ); // Trigger the repaint. pOleNode->SetChanged(); }