sw/qa/extras/layout/data/tdf92714_TOC_pageBreak.odt |binary sw/qa/extras/layout/layout5.cxx | 26 +++++++ sw/source/core/doc/doctxm.cxx | 66 ++++++++++++++++++++ 3 files changed, 92 insertions(+)
New commits: commit 441f6354987e2e8cccd58e0cff8408cf6088ad41 Author: Justin Luth <jl...@mail.com> AuthorDate: Wed Sep 17 13:02:55 2025 -0400 Commit: Justin Luth <jl...@mail.com> CommitDate: Thu Sep 18 19:08:47 2025 +0200 tdf#92714 sw: transfer breaks when deleting TOC The table of contents can contain a page break. When deleting a TOC, the page break should be transferred to the following paragraph or table. Something similar happens with DelFullPara and DelTable. make CppunitTest_sw_layoutwriter5 \ CPPUNIT_TEST_NAME=testTdf92714_TOC_pageBreak Change-Id: I3d0e61e0c6a9b7544fe6488f8122316fff37811a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191107 Tested-by: Jenkins Reviewed-by: Justin Luth <jl...@mail.com> diff --git a/sw/qa/extras/layout/data/tdf92714_TOC_pageBreak.odt b/sw/qa/extras/layout/data/tdf92714_TOC_pageBreak.odt new file mode 100644 index 000000000000..cb9b00d76ab9 Binary files /dev/null and b/sw/qa/extras/layout/data/tdf92714_TOC_pageBreak.odt differ diff --git a/sw/qa/extras/layout/layout5.cxx b/sw/qa/extras/layout/layout5.cxx index 6e8cdd59bc6b..880c03d46857 100644 --- a/sw/qa/extras/layout/layout5.cxx +++ b/sw/qa/extras/layout/layout5.cxx @@ -9,18 +9,23 @@ #include <swmodeltestbase.hxx> +#include <com/sun/star/text/XPageCursor.hpp> #include <com/sun/star/text/XTextFrame.hpp> #include <com/sun/star/text/XTextSectionsSupplier.hpp> #include <com/sun/star/text/XTextTable.hpp> #include <com/sun/star/text/XTextTablesSupplier.hpp> +#include <com/sun/star/text/XTextViewCursorSupplier.hpp> #include <com/sun/star/linguistic2/XHyphenator.hpp> #include <com/sun/star/view/XViewSettingsSupplier.hpp> #include <comphelper/scopeguard.hxx> #include <unotools/syslocaleoptions.hxx> #include <editeng/unolingu.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> #include <vcl/scheduler.hxx> +#include <cmdid.h> #include <scriptinfo.hxx> #include <rootfrm.hxx> #include <wrtsh.hxx> @@ -133,6 +138,27 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf72727) assertXPathContent(pXmlDoc, "(//textarray)[3]/text", u"3"); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf92714_TOC_pageBreak) +{ + // Given a document with a ToC that also defines the page style + createSwDoc("tdf92714_TOC_pageBreak.odt"); + + // When deleting the ToC + SwView* pView = getSwDocShell()->GetView(); + SfxDispatcher& rDispatcher = *pView->GetViewFrame().GetDispatcher(); + rDispatcher.Execute(FN_REMOVE_CUR_TOX); + + saveAndReload(u"writer8"_ustr); + + uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier( + xModel->getCurrentController(), uno::UNO_QUERY); + uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), + uno::UNO_QUERY); + // The page style should not be lost + CPPUNIT_ASSERT_EQUAL(u"OrangePage"_ustr, getProperty<OUString>(xCursor, u"PageStyleName"_ustr)); +} + CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf130969) { createSwDoc("tdf130969.docx"); diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx index 36f03f1a792d..1c050d30f2ea 100644 --- a/sw/source/core/doc/doctxm.cxx +++ b/sw/source/core/doc/doctxm.cxx @@ -623,6 +623,72 @@ bool SwDoc::DeleteTOX( const SwTOXBase& rTOXBase, bool bDelNodes ) } } } + else + { + // need to transfer potential TOX page breaks to following node + const SfxPoolItem* pPageDesc = nullptr; + const SfxPoolItem* pBreak = nullptr; + SwNodeIndex aSearchIdx(*pMyNode, 1); // the node after the TOX SectionNode + SwNodeIndex aEndSearchIdx(*pMyNode->EndOfSectionNode()); + + // did the TOC contain a page break? + while (aSearchIdx < aEndSearchIdx) + { + const SwNode& rNode = aSearchIdx.GetNode(); + if (rNode.IsTextNode()) + { + const SfxItemSet* pSet = rNode.GetTextNode()->GetpSwAttrSet(); + if (pSet) + { + pBreak = pSet->GetItemIfSet(RES_BREAK, false); + pPageDesc = pSet->GetItemIfSet(RES_PAGEDESC, false); + if (pBreak || pPageDesc) + break; + } + } + ++aSearchIdx; + } + if (pBreak || pPageDesc) + { + // Apply the page break to the next node + aSearchIdx = aEndSearchIdx; // EndNode of TOX + aEndSearchIdx = *aSearchPam.GetPointNode().EndOfSectionNode(); // EndNode of Cursor + while (aSearchIdx < aEndSearchIdx) + { + ++aSearchIdx; + SwNode& rNode = aSearchIdx.GetNode(); + if (rNode.IsTextNode()) + { + SwTextNode& rTextNode = *rNode.GetTextNode(); + // skip if destination node already defines its own page breaks + if (rTextNode.GetSwAttrSet().GetBreak().GetBreak() != SvxBreak::NONE) + break; + if (rTextNode.GetSwAttrSet().GetPageDesc().GetPageDesc()) + break; + + if (pPageDesc) + rTextNode.SetAttr(*pPageDesc); + if (pBreak) + rTextNode.SetAttr(*pBreak); + break; + } + else if (rNode.IsTableNode()) + { + SwFrameFormat* pTable = rNode.GetTableNode()->GetTable().GetFrameFormat(); + if (!pTable || pTable->GetBreak().GetBreak() != SvxBreak::NONE) + break; + if (pTable->GetPageDesc().GetPageDesc()) + break; + + if (pPageDesc) + pTable->SetFormatAttr(*pPageDesc); + if (pBreak) + pTable->SetFormatAttr(*pBreak); + break; + } + } + } + } DelSectionFormat( const_cast<SwSectionFormat *>(pFormat), bDelNodes );