diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2021-11-25 14:53:04 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2021-11-26 13:41:12 +0100 |
commit | 18a2d02f7969878fa90e0dcffd15ea5261b2369f (patch) | |
tree | 99bb768cb57a45477f31d04c9d016d9d591bc3be | |
parent | 1cc5c6587e72581c83f7289a95e906a3a1be38b6 (diff) |
sw: allow viewing OLE objects in protected sections
The problem was that we don't allow even opening embedded objects in
protected sections, which means the content of multi-page embedded
objects can't even be viewed in protected sections, which probably goes
too far.
Fix this relaxing the condition in SwEditWin::MouseButtonDown() to allow
launching the OLE object on double-click, and then make sure that the
native data is not updated in SfxInPlaceClient_Impl::saveObject() and
the replacement image is not updated in
svt::EmbedEventListener_Impl::stateChanged().
This is complicated by only the Writer layout knowing if a given OLE
object is anchored in a protected frame, so pass down a callback to
sfx2/ and svtools/ to check if the OLE object is protected.
Not copying the protected bit has the benefit of behaving correctly if
the section turns into non-protected: copying would not work properly,
as SfxInPlaceClient is created on demand, so not re-created when the
protectedness of the section is changed.
(cherry picked from commit 4f9f1ac33366817df61c488a9f36b09c592ee939)
Conflicts:
sw/source/core/ole/ndole.cxx
Change-Id: Ib3a8f2092d27dc1ebd3ef355c95a4a473988b163
-rw-r--r-- | include/sfx2/ipclient.hxx | 2 | ||||
-rw-r--r-- | include/svtools/embedhlp.hxx | 4 | ||||
-rw-r--r-- | sfx2/source/view/ipclient.cxx | 4 | ||||
-rw-r--r-- | svtools/source/misc/embedhlp.cxx | 21 | ||||
-rw-r--r-- | sw/inc/ndole.hxx | 3 | ||||
-rw-r--r-- | sw/inc/swcli.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/ole/ndole.cxx | 32 | ||||
-rw-r--r-- | sw/source/uibase/app/docsh.cxx | 16 | ||||
-rw-r--r-- | sw/source/uibase/docvw/edtwin.cxx | 14 | ||||
-rw-r--r-- | sw/source/uibase/uiview/swcli.cxx | 25 |
10 files changed, 114 insertions, 9 deletions
diff --git a/include/sfx2/ipclient.hxx b/include/sfx2/ipclient.hxx index 62c421c3c783..a7a85270c5e0 100644 --- a/include/sfx2/ipclient.hxx +++ b/include/sfx2/ipclient.hxx @@ -87,6 +87,8 @@ public: bool IsUIActive() const; virtual void FormatChanged(); // object format was changed (used for StarMath formulas aligning) + + virtual bool IsProtected() const; }; #endif diff --git a/include/svtools/embedhlp.hxx b/include/svtools/embedhlp.hxx index 12a8a2367a4b..09addf47f026 100644 --- a/include/svtools/embedhlp.hxx +++ b/include/svtools/embedhlp.hxx @@ -108,6 +108,10 @@ public: bool is() const; bool IsLocked() const; + + void SetIsProtectedHdl(const Link<LinkParamNone*, bool>& rProtectedHdl); + Link<LinkParamNone*, bool> GetIsProtectedHdl() const; + bool IsChart() const; OUString GetChartType(); diff --git a/sfx2/source/view/ipclient.cxx b/sfx2/source/view/ipclient.cxx index 5dc6267e5c94..d98ade7bd398 100644 --- a/sfx2/source/view/ipclient.cxx +++ b/sfx2/source/view/ipclient.cxx @@ -217,7 +217,7 @@ uno::Reference < frame::XFrame > const & SfxInPlaceClient_Impl::GetFrame() const void SAL_CALL SfxInPlaceClient_Impl::saveObject() { - if ( !m_bStoreObject ) + if (!m_bStoreObject || m_pClient->IsProtected()) // client wants to discard the object (usually it means the container document is closed while an object is active // and the user didn't request saving the changes return; @@ -1040,6 +1040,8 @@ void SfxInPlaceClient::FormatChanged() // dummy implementation } +bool SfxInPlaceClient::IsProtected() const { return false; } + void SfxInPlaceClient::DeactivateObject() { if ( !GetObject().is() ) diff --git a/svtools/source/misc/embedhlp.cxx b/svtools/source/misc/embedhlp.cxx index f8dcf1356621..d71754238cea 100644 --- a/svtools/source/misc/embedhlp.cxx +++ b/svtools/source/misc/embedhlp.cxx @@ -135,9 +135,16 @@ void SAL_CALL EmbedEventListener_Impl::stateChanged( const lang::EventObject&, uno::Reference < util::XModifiable > xMod( pObject->GetObject()->getComponent(), uno::UNO_QUERY ); if ( nNewState == embed::EmbedStates::RUNNING ) { + bool bProtected = false; + if (pObject->GetIsProtectedHdl().IsSet()) + { + bProtected = pObject->GetIsProtectedHdl().Call(nullptr); + } + // TODO/LATER: container must be set before! // When is this event created? Who sets the new container when it changed? - if( ( pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON ) && nOldState != embed::EmbedStates::LOADED && !pObject->IsChart() ) + if ((pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON) + && nOldState != embed::EmbedStates::LOADED && !pObject->IsChart() && !bProtected) // get new replacement after deactivation pObject->UpdateReplacement(); @@ -239,6 +246,8 @@ struct EmbeddedObjectRef_Impl sal_uInt32 mnGraphicVersion; awt::Size aDefaultSizeForChart_In_100TH_MM;//#i103460# charts do not necessarily have an own size within ODF files, in this case they need to use the size settings from the surrounding frame, which is made available with this member + Link<LinkParamNone*, bool> m_aIsProtectedHdl; + EmbeddedObjectRef_Impl() : pContainer(nullptr), nViewAspect(embed::Aspects::MSOLE_CONTENT), @@ -394,6 +403,16 @@ bool EmbeddedObjectRef::IsLocked() const return mpImpl->bIsLocked; } +void EmbeddedObjectRef::SetIsProtectedHdl(const Link<LinkParamNone*, bool>& rProtectedHdl) +{ + mpImpl->m_aIsProtectedHdl = rProtectedHdl; +} + +Link<LinkParamNone*, bool> EmbeddedObjectRef::GetIsProtectedHdl() const +{ + return mpImpl->m_aIsProtectedHdl; +} + void EmbeddedObjectRef::GetReplacement( bool bUpdate ) { Graphic aOldGraphic; diff --git a/sw/inc/ndole.hxx b/sw/inc/ndole.hxx index 8382a42e58dc..e8c7506184f3 100644 --- a/sw/inc/ndole.hxx +++ b/sw/inc/ndole.hxx @@ -52,6 +52,8 @@ class SW_DLLPUBLIC SwOLEObj void SetNode( SwOLENode* pNode ); + DECL_LINK(IsProtectedHdl, LinkParamNone*, bool); + public: SwOLEObj( const svt::EmbeddedObjectRef& pObj ); SwOLEObj( const OUString &rName, sal_Int64 nAspect ); @@ -69,6 +71,7 @@ public: const OUString& GetCurrentPersistName() const { return m_aName; } OUString GetStyleString(); bool IsOleRef() const; ///< To avoid unnecessary loading of object. + bool IsProtected() const; // try to get OLE visualization in form of a Primitive2DSequence // and the corresponding B2DRange. This data may be locally buffered diff --git a/sw/inc/swcli.hxx b/sw/inc/swcli.hxx index 0a6b65a33897..fc77d0885d1e 100644 --- a/sw/inc/swcli.hxx +++ b/sw/inc/swcli.hxx @@ -44,6 +44,8 @@ public: bool IsCheckForOLEInCaption() const { return m_IsOldCheckForOLEInCaption; } virtual void FormatChanged() override; + + bool IsProtected() const override; }; #endif diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx index 1927872ed0d9..f6ca51279a29 100644 --- a/sw/source/core/ole/ndole.cxx +++ b/sw/source/core/ole/ndole.cxx @@ -54,6 +54,7 @@ #include <atomic> #include <deque> #include <libxml/xmlwriter.h> +#include <flyfrm.hxx> using namespace utl; using namespace com::sun::star::uno; @@ -909,6 +910,36 @@ bool SwOLEObj::IsOleRef() const return m_xOLERef.is(); } +IMPL_LINK_NOARG(SwOLEObj, IsProtectedHdl, LinkParamNone*, bool) { return IsProtected(); } + +bool SwOLEObj::IsProtected() const +{ + if (!m_pOLENode) + { + return false; + } + + SwFrame* pFrame = m_pOLENode->getLayoutFrame(nullptr); + if (!pFrame) + { + return false; + } + SwFrame* pUpper = pFrame->GetUpper(); + if (!pUpper || !pUpper->IsFlyFrame()) + { + return false; + } + + auto pFlyFrame = static_cast<SwFlyFrame*>(pUpper); + const SwFrame* pAnchor = pFlyFrame->GetAnchorFrame(); + if (!pAnchor) + { + return false; + } + + return pAnchor->IsProtected(); +} + uno::Reference < embed::XEmbeddedObject > const & SwOLEObj::GetOleRef() { if( !m_xOLERef.is() ) @@ -942,6 +973,7 @@ uno::Reference < embed::XEmbeddedObject > const & SwOLEObj::GetOleRef() } if (xObj.is()) { + m_xOLERef.SetIsProtectedHdl(LINK(this, SwOLEObj, IsProtectedHdl)); m_xOLERef.Assign( xObj, m_xOLERef.GetViewAspect() ); m_xOLERef.AssignToContainer( &p->GetEmbeddedObjectContainer(), m_aName ); m_xListener = new SwOLEListener_Impl( this ); diff --git a/sw/source/uibase/app/docsh.cxx b/sw/source/uibase/app/docsh.cxx index aeb522be5fc9..71033ee0af69 100644 --- a/sw/source/uibase/app/docsh.cxx +++ b/sw/source/uibase/app/docsh.cxx @@ -1134,6 +1134,22 @@ void SwDocShell::GetState(SfxItemSet& rSet) // OLE-Hdls IMPL_LINK( SwDocShell, Ole2ModifiedHdl, bool, bNewStatus, void ) { + if (m_pWrtShell) + { + SwOLENode* pOLENode = nullptr; + if (!m_pWrtShell->IsTableMode()) + { + pOLENode = m_pWrtShell->GetCursor()->GetNode().GetOLENode(); + } + if (pOLENode) + { + if (pOLENode->GetOLEObj().IsProtected()) + { + return; + } + } + } + if( IsEnableSetModified() ) SetModified( bNewStatus ); } diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index 507919f601d7..001ea389f497 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -3245,8 +3245,11 @@ void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt) case 2: { g_bFrameDrag = false; - if ( !bIsDocReadOnly && rSh.IsInsideSelectedObj(aDocPos) && - FlyProtectFlags::NONE == rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) ) + if (!bIsDocReadOnly && rSh.IsInsideSelectedObj(aDocPos) + && (FlyProtectFlags::NONE + == rSh.IsSelObjProtected(FlyProtectFlags::Content + | FlyProtectFlags::Parent) + || rSh.GetSelectionType() == SelectionType::Ole)) { /* This is no good: on the one hand GetSelectionType is used as flag field * (take a look into the GetSelectionType method) and on the other hand the @@ -3266,11 +3269,8 @@ void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt) // double click on OLE object --> OLE-InPlace case SelectionType::Ole: - if (rSh.IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE) - { - RstMBDownFlags(); - rSh.LaunchOLEObj(); - } + RstMBDownFlags(); + rSh.LaunchOLEObj(); return; case SelectionType::Frame: diff --git a/sw/source/uibase/uiview/swcli.cxx b/sw/source/uibase/uiview/swcli.cxx index 05f5f6ccc95a..4dc86bee5faf 100644 --- a/sw/source/uibase/uiview/swcli.cxx +++ b/sw/source/uibase/uiview/swcli.cxx @@ -29,6 +29,8 @@ #include <toolkit/helper/vclunohelper.hxx> +#include <ndole.hxx> + using namespace com::sun::star; SwOleClient::SwOleClient(SwView *pView, SwEditWin *pWin, const svt::EmbeddedObjectRef& xObj) @@ -164,4 +166,27 @@ void SwOleClient::FormatChanged() } } +bool SwOleClient::IsProtected() const +{ + auto pView = dynamic_cast<SwView*>(GetViewShell()); + if (!pView) + { + return false; + } + + SwWrtShell& rWrtSh = pView->GetWrtShell(); + if (rWrtSh.IsTableMode()) + { + return false; + } + + SwOLENode* pOLENode = rWrtSh.GetCursor()->GetNode().GetOLENode(); + if (!pOLENode) + { + return false; + } + + return pOLENode->GetOLEObj().IsProtected(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |