sw/qa/extras/uiwriter/data/IndexElementsInHiddenSections.fodt | 63 +++++++ sw/qa/extras/uiwriter/uiwriter9.cxx | 43 +++++ sw/source/core/doc/doctxm.cxx | 79 ++++++---- sw/source/core/tox/tox.cxx | 3 4 files changed, 158 insertions(+), 30 deletions(-)
New commits: commit a5edc358b158ec017f26ab83ca42e0af31ce0147 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sat Nov 23 11:02:07 2024 +0500 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Mon Nov 25 10:25:02 2024 +0100 tdf#162195: use SwFrame::IsHiddenNow when building index Before commit 0c96119895b347f8eb5bb89f393351bd3c02b9f1 (tdf#159565 prerequisite: make hidden sections have zero-height frames, 2024-02-15), the hidden sections were absent from layout, so didn't appear in the SwTOXBaseSection::Update* functions. Now they are zero-height, but present, so their visibility must be taken into account explicitly. Change-Id: I95cc72b383a99e1f65152579c5458e253a3f60ea Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177079 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177102 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sw/qa/extras/uiwriter/data/IndexElementsInHiddenSections.fodt b/sw/qa/extras/uiwriter/data/IndexElementsInHiddenSections.fodt new file mode 100644 index 000000000000..5fb3d809404f --- /dev/null +++ b/sw/qa/extras/uiwriter/data/IndexElementsInHiddenSections.fodt @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:styles> + <style:style style:name="CustomTOCStyle" style:family="paragraph" style:class="text"/> + </office:styles> + <office:body> + <office:text> + <text:table-of-content> + <text:table-of-content-source text:outline-level="1" text:use-index-source-styles="true"> + <text:index-title-template text:style-name="Contents_20_Heading">Table of Contents</text:index-title-template> + <text:table-of-content-entry-template text:outline-level="1" text:style-name="Contents_20_1"> + <text:index-entry-link-start text:style-name="Index_20_Link"/> + <text:index-entry-chapter/> + <text:index-entry-text/> + <text:index-entry-tab-stop style:type="right" style:leader-char="."/> + <text:index-entry-page-number/> + <text:index-entry-link-end/> + </text:table-of-content-entry-template> + <text:index-source-styles text:outline-level="1"> + <text:index-source-style text:style-name="CustomTOCStyle"/> + </text:index-source-styles> + </text:table-of-content-source> + </text:table-of-content> + <text:section text:name="Section Visible"> + <text:h text:outline-level="1">Section Visible</text:h> + <text:p>foo</text:p> + <table:table table:name="Table1"> + <table:table-column/> + <table:table-row> + <table:table-cell/> + </table:table-row> + </table:table> + </text:section> + <text:section text:name="Section Hidden" text:display="none"> + <text:h text:outline-level="1">Section Hidden</text:h> + <text:p>bar</text:p> + <text:p/> + <text:p>A level-1 <text:toc-mark-start text:id="IMark1" text:outline-level="1"/>entry<text:toc-mark-end text:id="IMark1"/></text:p> + <text:p/> + <text:p text:style-name="CustomTOCStyle">CustomTOCStyle paragraph</text:p> + <table:table table:name="Table2"> + <table:table-column/> + <table:table-row> + <table:table-cell/> + </table:table-row> + </table:table> + </text:section> + <text:table-index> + <text:table-index-source text:use-caption="false" text:caption-sequence-name="Table" text:caption-sequence-format="text"> + <text:index-title-template text:style-name="Table_20_index_20_heading">Index of Tables</text:index-title-template> + <text:table-index-entry-template text:style-name="Table_20_index_20_1"> + <text:index-entry-link-start text:style-name="Index_20_Link"/> + <text:index-entry-text/> + <text:index-entry-tab-stop style:type="right" style:leader-char="."/> + <text:index-entry-page-number/> + <text:index-entry-link-end/> + </text:table-index-entry-template> + </text:table-index-source> + </text:table-index> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/sw/qa/extras/uiwriter/uiwriter9.cxx b/sw/qa/extras/uiwriter/uiwriter9.cxx index 8523bd95c9eb..2f8d9b68ba2f 100644 --- a/sw/qa/extras/uiwriter/uiwriter9.cxx +++ b/sw/qa/extras/uiwriter/uiwriter9.cxx @@ -677,6 +677,49 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf144752) CPPUNIT_ASSERT_EQUAL(u"Word"_ustr, pWrtShell->GetSelText()); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf162195) +{ + // Given a document, which has some index entries in a hidden section + createSwDoc("IndexElementsInHiddenSections.fodt"); + + auto xIndexSupplier(mxComponent.queryThrow<css::text::XDocumentIndexesSupplier>()); + auto xIndexes = xIndexSupplier->getDocumentIndexes(); + CPPUNIT_ASSERT(xIndexes); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexes->getCount()); // A ToC and a table index + + auto xToC(xIndexes->getByIndex(0).queryThrow<css::text::XDocumentIndex>()); + xToC->update(); + // Without the fix, all the elements from the hidden section appeared in the index + CPPUNIT_ASSERT_EQUAL(u"Table of Contents" SAL_NEWLINE_STRING "Section Visible 1"_ustr, + xToC->getAnchor()->getString()); + + auto xTables(xIndexes->getByIndex(1).queryThrow<css::text::XDocumentIndex>()); + xTables->update(); + // Without the fix, all the elements from the hidden section appeared in the index + CPPUNIT_ASSERT_EQUAL(u"Index of Tables" SAL_NEWLINE_STRING "Table1 1"_ustr, + xTables->getAnchor()->getString()); + + // Show the hidden section + auto xTextSectionsSupplier = mxComponent.queryThrow<css::text::XTextSectionsSupplier>(); + auto xSections = xTextSectionsSupplier->getTextSections(); + CPPUNIT_ASSERT(xSections); + auto xSection + = xSections->getByName(u"Section Hidden"_ustr).queryThrow<css::beans::XPropertySet>(); + xSection->setPropertyValue(u"IsVisible"_ustr, css::uno::Any(true)); + + xToC->update(); + CPPUNIT_ASSERT_EQUAL(u"Table of Contents" SAL_NEWLINE_STRING + "Section Visible 1" SAL_NEWLINE_STRING + "Section Hidden 1" SAL_NEWLINE_STRING "entry 1" SAL_NEWLINE_STRING + "CustomTOCStyle paragraph 1"_ustr, + xToC->getAnchor()->getString()); + + xTables->update(); + CPPUNIT_ASSERT_EQUAL(u"Index of Tables" SAL_NEWLINE_STRING "Table1 1" SAL_NEWLINE_STRING + "Table2 1"_ustr, + xTables->getAnchor()->getString()); +} + } // end of anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx index 4463bdc7c29b..2c82418d5c96 100644 --- a/sw/source/core/doc/doctxm.cxx +++ b/sw/source/core/doc/doctxm.cxx @@ -1350,6 +1350,48 @@ void SwTOXBaseSection::UpdateMarks(const SwTOXInternational& rIntl, } } +static SwContentFrame* useContentNodeForIndex(const SwContentNode* node, bool fromChapter, + const SwTextNode* chapter, const SwRootFrame* layout) +{ + if (!node) + return nullptr; + if (!node->HasWriterListeners()) + return nullptr; + if (!node->GetNodes().IsDocNodes()) + return nullptr; + if (layout && layout->HasMergedParas() && node->GetRedlineMergeFlag() == SwNode::Merge::Hidden) + return nullptr; + auto pFrame = node->getLayoutFrame(layout); + if (!pFrame) + return nullptr; + if (fromChapter && !IsHeadingContained(chapter, *node)) + return nullptr; + if (pFrame->IsHiddenNow()) + return nullptr; + + return pFrame; +} + +static bool useTextNodeForIndex(const SwTextNode* node, int maxLevel, bool fromChapter, + const SwTextNode* chapter, const SwRootFrame* layout) +{ + auto pTextFrame = static_cast<const SwTextFrame*>(useContentNodeForIndex(node, fromChapter, chapter, layout)); + if (!pTextFrame) + return false; + if (node->Len() == 0) + return false; + if (maxLevel >= 0 && node->GetAttrOutlineLevel() > maxLevel) + return false; + if (node->IsHiddenByParaField()) + return false; + if (node->HasHiddenCharAttribute(true)) + return false; + if (layout && layout->HasMergedParas() && pTextFrame->GetTextNodeForParaProps() != node) + return false; + + return true; +} + /// Generate table of contents from outline void SwTOXBaseSection::UpdateOutline( const SwTextNode* pOwnChapterNode, SwRootFrame const*const pLayout) @@ -1362,14 +1404,7 @@ void SwTOXBaseSection::UpdateOutline( const SwTextNode* pOwnChapterNode, { ::SetProgressState( 0, pDoc->GetDocShell() ); SwTextNode* pTextNd = pOutlineNode->GetTextNode(); - if( pTextNd && pTextNd->Len() && pTextNd->HasWriterListeners() && - o3tl::make_unsigned( pTextNd->GetAttrOutlineLevel()) <= GetLevel() && - pTextNd->getLayoutFrame(pLayout) && - !pTextNd->IsHiddenByParaField() && - !pTextNd->HasHiddenCharAttribute( true ) && - (!pLayout || !pLayout->HasMergedParas() - || static_cast<SwTextFrame*>(pTextNd->getLayoutFrame(pLayout))->GetTextNodeForParaProps() == pTextNd) && - ( !IsFromChapter() || IsHeadingContained(pOwnChapterNode, *pTextNd) )) + if (useTextNodeForIndex(pTextNd, GetLevel(), IsFromChapter(), pOwnChapterNode, pLayout)) { InsertSorted(MakeSwTOXSortTabBase<SwTOXPara>(pLayout, *pTextNd, SwTOXElement::OutlineLevel)); } @@ -1380,6 +1415,7 @@ void SwTOXBaseSection::UpdateOutline( const SwTextNode* pOwnChapterNode, void SwTOXBaseSection::UpdateTemplate(const SwTextNode* pOwnChapterNode, SwRootFrame const*const pLayout) { + int nMaxLevel = SwTOXBase::GetType() == TOX_CONTENT ? GetLevel() : -1; SwDoc* pDoc = GetFormat()->GetDoc(); for(sal_uInt16 i = 0; i < MAXLEVEL; i++) { @@ -1404,15 +1440,7 @@ void SwTOXBaseSection::UpdateTemplate(const SwTextNode* pOwnChapterNode, { ::SetProgressState( 0, pDoc->GetDocShell() ); - if (pTextNd->GetText().getLength() && - pTextNd->getLayoutFrame(pLayout) && - pTextNd->GetNodes().IsDocNodes() && - // tdf#40142 - consider level settings of the various text nodes - (TOX_CONTENT != SwTOXBase::GetType() || - o3tl::make_unsigned(pTextNd->GetAttrOutlineLevel()) <= GetLevel()) && - (!pLayout || !pLayout->HasMergedParas() - || static_cast<SwTextFrame*>(pTextNd->getLayoutFrame(pLayout))->GetTextNodeForParaProps() == pTextNd) && - (!IsFromChapter() || IsHeadingContained(pOwnChapterNode, *pTextNd))) + if (useTextNodeForIndex(pTextNd, nMaxLevel, IsFromChapter(), pOwnChapterNode, pLayout)) { InsertSorted(MakeSwTOXSortTabBase<SwTOXPara>(pLayout, *pTextNd, SwTOXElement::Template, i + 1)); } @@ -1438,9 +1466,7 @@ void SwTOXBaseSection::UpdateSequence(const SwTextNode* pOwnChapterNode, SwTextNode& rTextNode = pTextField->GetTextNode(); ::SetProgressState( 0, pDoc->GetDocShell() ); - if (rTextNode.GetText().getLength() && - rTextNode.getLayoutFrame(pLayout) && - ( !IsFromChapter() || IsHeadingContained(pOwnChapterNode, rTextNode)) + if (useTextNodeForIndex(&rTextNode, -1, IsFromChapter(), pOwnChapterNode, pLayout) && (!pLayout || !pLayout->IsHideRedlines() || !sw::IsFieldDeletedInModel(pDoc->getIDocumentRedlineAccess(), *pTextField))) { @@ -1481,8 +1507,7 @@ void SwTOXBaseSection::UpdateAuthorities(const SwTOXInternational& rIntl, const SwTextNode& rTextNode = pFormatField->GetTextField()->GetTextNode(); ::SetProgressState( 0, pDoc->GetDocShell() ); - if (rTextNode.GetText().getLength() && - rTextNode.getLayoutFrame(pLayout) && + if (useTextNodeForIndex(&rTextNode, -1, false, nullptr, pLayout) && (!pLayout || !pLayout->IsHideRedlines() || !sw::IsFieldDeletedInModel(pDoc->getIDocumentRedlineAccess(), *pTextField))) { @@ -1630,10 +1655,7 @@ void SwTOXBaseSection::UpdateContent( SwTOXElement eMyType, } } - if (pCNd->getLayoutFrame(pLayout) - && (!pLayout || !pLayout->HasMergedParas() - || pCNd->GetRedlineMergeFlag() != SwNode::Merge::Hidden) - && ( !IsFromChapter() || IsHeadingContained(pOwnChapterNode, *pCNd))) + if (useContentNodeForIndex(pCNd, IsFromChapter(), pOwnChapterNode, pLayout)) { std::unique_ptr<SwTOXPara> pNew( MakeSwTOXSortTabBase<SwTOXPara>( pLayout, *pCNd, eMyType, @@ -1670,10 +1692,7 @@ void SwTOXBaseSection::UpdateTable(const SwTextNode* pOwnChapterNode, while( nullptr != ( pCNd = SwNodes::GoNext( &aContentIdx ) ) && aContentIdx.GetIndex() < pTableNd->EndOfSectionIndex() ) { - if (pCNd->getLayoutFrame(pLayout) - && (!pLayout || !pLayout->HasMergedParas() - || pCNd->GetRedlineMergeFlag() != SwNode::Merge::Hidden) - && (!IsFromChapter() || IsHeadingContained(pOwnChapterNode, *pCNd))) + if (useContentNodeForIndex(pCNd, IsFromChapter(), pOwnChapterNode, pLayout)) { std::unique_ptr<SwTOXTable> pNew(new SwTOXTable( *pCNd )); if( IsLevelFromChapter() && TOX_TABLES != SwTOXBase::GetType()) diff --git a/sw/source/core/tox/tox.cxx b/sw/source/core/tox/tox.cxx index ef38ff3a17b6..476ecd804166 100644 --- a/sw/source/core/tox/tox.cxx +++ b/sw/source/core/tox/tox.cxx @@ -197,6 +197,9 @@ void SwTOXMark::Notify(const SfxHint& rHint) // Check for being hidden by hidden redlines if (pLayout && pLayout->HasMergedParas() && sw::IsMarkHintHidden(*pLayout, rNode, rTextMark)) return; + // Check for being hidden by hidden sections + if (auto pFrame(rNode.getLayoutFrame(pLayout)); !pFrame || pFrame->IsHiddenNow()) + return; pCollectLayoutHint->m_rMarks.push_back(rTextMark); } }