sw/qa/core/undo/data/image-as-character.odt |binary sw/qa/core/undo/undo.cxx | 46 ++++++++++++++++++++++++++++ sw/source/core/doc/docfly.cxx | 15 --------- sw/source/core/inc/UndoAttribute.hxx | 10 ++++++ sw/source/core/undo/unattr.cxx | 23 +++++++++++++- sw/source/core/unocore/unoframe.cxx | 10 ++++-- 6 files changed, 86 insertions(+), 18 deletions(-)
New commits: commit fa97a6f9beac927d64cd7be6188338ae46de9a19 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Thu Feb 2 09:41:23 2023 +0300 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Feb 2 16:05:47 2023 +0000 tdf#153304: Add undo entries and set modified in SwXFrame::setProperty* Similar to SwDoc::SetFlyFrameAttr; the latter should only set modified state on actual changes. Change-Id: I66982e68fa9132fda132d811f7a48b4461645df4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146484 Tested-by: Mike Kaganski <mike.kagan...@collabora.com> Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> (cherry picked from commit 333183d9a72d1e2b7ae65145092efec5e357ad14) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146514 Tested-by: Miklos Vajna <vmik...@collabora.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/core/undo/data/image-as-character.odt b/sw/qa/core/undo/data/image-as-character.odt new file mode 100644 index 000000000000..0b1aa6a21fb2 Binary files /dev/null and b/sw/qa/core/undo/data/image-as-character.odt differ diff --git a/sw/qa/core/undo/undo.cxx b/sw/qa/core/undo/undo.cxx index 583458d30127..154226d2129f 100644 --- a/sw/qa/core/undo/undo.cxx +++ b/sw/qa/core/undo/undo.cxx @@ -106,6 +106,52 @@ CPPUNIT_TEST_FIXTURE(SwCoreUndoTest, testTableCopyRedline) pWrtShell->Undo(); } +CPPUNIT_TEST_FIXTURE(SwCoreUndoTest, testImagePropsCreateUndoAndModifyDoc) +{ + createSwDoc("image-as-character.odt"); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + SwDocShell* pDocShell = pTextDoc->GetDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + css::uno::Reference<css::beans::XPropertySet> xImage( + pTextDoc->getGraphicObjects()->getByName("Image1"), css::uno::UNO_QUERY_THROW); + + CPPUNIT_ASSERT(pTextDoc->isSetModifiedEnabled()); + CPPUNIT_ASSERT(!pTextDoc->isModified()); + CPPUNIT_ASSERT(!pWrtShell->GetLastUndoInfo(nullptr, nullptr, nullptr)); + + // Check that modifications of the geometry mark document dirty, and create an undo + + xImage->setPropertyValue("RelativeWidth", css::uno::Any(sal_Int16(80))); + + // Without the fix, this would fail + CPPUNIT_ASSERT(pTextDoc->isModified()); + CPPUNIT_ASSERT(pWrtShell->GetLastUndoInfo(nullptr, nullptr, nullptr)); + + pWrtShell->Undo(); + CPPUNIT_ASSERT(!pTextDoc->isModified()); + CPPUNIT_ASSERT(!pWrtShell->GetLastUndoInfo(nullptr, nullptr, nullptr)); + + // Check that modifications of anchor mark document dirty, and create an undo + + xImage->setPropertyValue("AnchorType", + css::uno::Any(css::text::TextContentAnchorType_AT_PARAGRAPH)); + + CPPUNIT_ASSERT(pTextDoc->isModified()); + CPPUNIT_ASSERT(pWrtShell->GetLastUndoInfo(nullptr, nullptr, nullptr)); + + pWrtShell->Undo(); + CPPUNIT_ASSERT(!pTextDoc->isModified()); + CPPUNIT_ASSERT(!pWrtShell->GetLastUndoInfo(nullptr, nullptr, nullptr)); + + // Check that setting the same values do not make it dirty and do not add undo + + xImage->setPropertyValue("RelativeWidth", xImage->getPropertyValue("RelativeWidth")); + xImage->setPropertyValue("AnchorType", xImage->getPropertyValue("AnchorType")); + + CPPUNIT_ASSERT(!pTextDoc->isModified()); + CPPUNIT_ASSERT(!pWrtShell->GetLastUndoInfo(nullptr, nullptr, nullptr)); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx index 7bf5c31681ac..5ddc713ff4af 100644 --- a/sw/source/core/doc/docfly.cxx +++ b/sw/source/core/doc/docfly.cxx @@ -555,23 +555,10 @@ bool SwDoc::SetFlyFrameAttr( SwFrameFormat& rFlyFormat, SfxItemSet& rSet ) if( !rSet.Count() ) return false; - std::unique_ptr<SwUndoFormatAttrHelper> pSaveUndo; - - if (GetIDocumentUndoRedo().DoesUndo()) - { - GetIDocumentUndoRedo().ClearRedo(); // AppendUndo far below, so leave it - pSaveUndo.reset( new SwUndoFormatAttrHelper( rFlyFormat ) ); - } + SwDocModifyAndUndoGuard guard(rFlyFormat); bool const bRet = lcl_SetFlyFrameAttr(*this, &SwDoc::SetFlyFrameAnchor, rFlyFormat, rSet); - if (pSaveUndo && pSaveUndo->GetUndo() ) - { - GetIDocumentUndoRedo().AppendUndo( pSaveUndo->ReleaseUndo() ); - } - - getIDocumentState().SetModified(); - //SwTextBoxHelper::syncFlyFrameAttr(rFlyFormat, rSet); return bRet; diff --git a/sw/source/core/inc/UndoAttribute.hxx b/sw/source/core/inc/UndoAttribute.hxx index e3c40b7f0e87..178a17f5a2fd 100644 --- a/sw/source/core/inc/UndoAttribute.hxx +++ b/sw/source/core/inc/UndoAttribute.hxx @@ -176,6 +176,16 @@ public: std::unique_ptr<SwUndoFormatAttr> ReleaseUndo() { return std::move(m_pUndo); } }; +class SwDocModifyAndUndoGuard final +{ + SwDoc* doc; + std::unique_ptr<SwUndoFormatAttrHelper> helper; + +public: + SwDocModifyAndUndoGuard(SwFormat& format); + ~SwDocModifyAndUndoGuard(); +}; + class SwUndoMoveLeftMargin final : public SwUndo, private SwUndRng { const std::unique_ptr<SwHistory> m_pHistory; diff --git a/sw/source/core/undo/unattr.cxx b/sw/source/core/undo/unattr.cxx index 60df048d22b3..ac57fe8adcba 100644 --- a/sw/source/core/undo/unattr.cxx +++ b/sw/source/core/undo/unattr.cxx @@ -37,6 +37,8 @@ #include <doc.hxx> #include <IDocumentLayoutAccess.hxx> #include <IDocumentRedlineAccess.hxx> +#include <IDocumentState.hxx> +#include <IDocumentUndoRedo.hxx> #include <IShellCursorSupplier.hxx> #include <docary.hxx> #include <swcrsr.hxx> @@ -93,6 +95,24 @@ void SwUndoFormatAttrHelper::SwClientNotify(const SwModify&, const SfxHint& rHin } } +SwDocModifyAndUndoGuard::SwDocModifyAndUndoGuard(SwFormat& format) + : doc(format.GetName().isEmpty() ? nullptr : format.GetDoc()) + , helper(doc ? new SwUndoFormatAttrHelper(format) : nullptr) +{ +} + +SwDocModifyAndUndoGuard::~SwDocModifyAndUndoGuard() +{ + if (helper && helper->GetUndo()) + { + // helper tracks changes, even when DoesUndo is false, to detect modified state + if (doc->GetIDocumentUndoRedo().DoesUndo()) + doc->GetIDocumentUndoRedo().AppendUndo(helper->ReleaseUndo()); + + doc->getIDocumentState().SetModified(); + } +} + SwUndoFormatAttr::SwUndoFormatAttr( SfxItemSet&& rOldSet, SwFormat& rChgFormat, bool bSaveDrawPt ) @@ -142,7 +162,8 @@ void SwUndoFormatAttr::Init( const SwFormat & rFormat ) ->FindTableNode()->GetIndex(); } } else if (dynamic_cast<const SwSectionFormat*>(&rFormat)) { - m_nNodeIndex = rFormat.GetContent().GetContentIdx()->GetIndex(); + if (auto pContentIndex = rFormat.GetContent().GetContentIdx()) + m_nNodeIndex = pContentIndex->GetIndex(); } else if(auto pBoxFormat = dynamic_cast<const SwTableBoxFormat*>(&rFormat)) { auto pTableBox = pBoxFormat->GetTableBox(); diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx index d81ed0ff6b63..381109f4e97e 100644 --- a/sw/source/core/unocore/unoframe.cxx +++ b/sw/source/core/unocore/unoframe.cxx @@ -46,6 +46,7 @@ #include <IDocumentDrawModelAccess.hxx> #include <IDocumentLayoutAccess.hxx> #include <IDocumentStylePoolAccess.hxx> +#include <UndoAttribute.hxx> #include <docsh.hxx> #include <editsh.hxx> #include <ndindex.hxx> @@ -1405,6 +1406,7 @@ void SwXFrame::setPropertyValue(const OUString& rPropertyName, const ::uno::Any& { if (pFormat) { + SwDocModifyAndUndoGuard guard(*pFormat); SvxFrameDirectionItem aItem(SvxFrameDirection::Environment, RES_FRAMEDIR); aItem.PutValue(_rValue, 0); GetFrameFormat()->SetFormatAttr(aItem); @@ -1934,6 +1936,7 @@ void SwXFrame::setPropertyValue(const OUString& rPropertyName, const ::uno::Any& } else { + SwDocModifyAndUndoGuard guard(*pFormat); pFormat->SetFormatAttr(aSet); } } @@ -2534,6 +2537,7 @@ void SwXFrame::setPropertyToDefault( const OUString& rPropertyName ) aSet.ClearItem(XATTR_FILLBMP_STRETCH); aSet.ClearItem(XATTR_FILLBMP_TILE); + SwDocModifyAndUndoGuard guard(*pFormat); pFormat->SetFormatAttr(aSet); } else if( pEntry->nWID && @@ -2570,14 +2574,14 @@ void SwXFrame::setPropertyToDefault( const OUString& rPropertyName ) GetOrCreateSdrObject(rFlyFormat); rFlyFormat.GetDoc()->SetFlyFrameDescription(rFlyFormat, OUString()); } - else + else if (rPropertyName != UNO_NAME_ANCHOR_TYPE) { SwDoc* pDoc = pFormat->GetDoc(); SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END - 1> aSet( pDoc->GetAttrPool() ); aSet.SetParent(&pFormat->GetAttrSet()); aSet.ClearItem(pEntry->nWID); - if(rPropertyName != UNO_NAME_ANCHOR_TYPE) - pFormat->SetFormatAttr(aSet); + SwDocModifyAndUndoGuard guard(*pFormat); + pFormat->SetFormatAttr(aSet); } } else