summaryrefslogtreecommitdiff
path: root/embeddedobj
diff options
context:
space:
mode:
authorJuergen Funk <juergen.funk_ml@cib.de>2022-02-22 09:19:29 +0100
committerSamuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>2022-05-10 09:02:01 +0200
commitcf650ceaafb4d3a3f46991dc1b12efa0e37a71f9 (patch)
tree0bcbc4178c8f940c747507f4d24bef2685dfa399 /embeddedobj
parent63a2f314250b05d484747fafc4a814a4553f461e (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')
-rw-r--r--embeddedobj/Library_embobj.mk4
-rw-r--r--embeddedobj/source/commonembedding/embedobj.cxx7
-rw-r--r--embeddedobj/source/commonembedding/miscobj.cxx153
-rw-r--r--embeddedobj/source/commonembedding/persistence.cxx31
-rw-r--r--embeddedobj/source/inc/commonembobj.hxx20
-rw-r--r--embeddedobj/source/inc/strings.hrc19
6 files changed, 195 insertions, 39 deletions
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 <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;
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 <comphelper/mimeconfighelper.hxx>
#include <comphelper/namedvaluecollection.hxx>
#include <comphelper/propertyvalue.hxx>
+#include <unotools/mediadescriptor.hxx>
#include <tools/diagnose_ex.h>
#include <sal/log.hxx>
@@ -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 <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <cppuhelper/weak.hxx>
+#include <embeddedobj/embeddedupdate.hxx>
#include <rtl/ref.hxx>
#include <map>
#include <memory>
+#include <svtools/filechangedchecker.hxx>
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<char const *>(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: */