sw/qa/extras/layout/data/table-with-hidden-section.fodt |   57 ++++++++++++++++
 sw/qa/extras/layout/data/tdf166210.fodt                 |   22 ++++++
 sw/qa/extras/layout/layout2.cxx                         |   47 +++++++++++++
 sw/source/core/doc/docfld.cxx                           |   29 +-------
 sw/source/core/layout/sectfrm.cxx                       |    1 
 5 files changed, 131 insertions(+), 25 deletions(-)

New commits:
commit 9a15d11d9cee86b71982a27ea4e008ef566c7b2b
Author:     Mike Kaganski <[email protected]>
AuthorDate: Sun Jun 1 16:06:42 2025 +0500
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Oct 14 20:04:52 2025 +0200

    tdf#166691: don't unhide sections temporarily to create their frames
    
    Commit 0c96119895b347f8eb5bb89f393351bd3c02b9f1 (tdf#159565 prerequisite:
    make hidden sections have zero-height frames, 2024-02-14) made hidden
    sections have frames. This removes the need to unhide them to get their
    frames, which happened in SwDocUpdateField::MakeFieldList_.
    
    Commit 6db63bb533a5c7436793eab86e83f92322b37044 (tdf#166210: invalidate
    parent's size when hiding section, 2025-04-28) started to invalidate the
    section frame's parent size on section hidden state change. This created
    a loop, where a calculation of the condition, that made a section hidden,
    caused the section to unhide then hide, invalidating parent frame; that
    caused repagination, and then another recalculation (because the number
    of pages may affect the conditions).
    
    This change drops the code in SwDocUpdateField::MakeFieldList_, that did
    the work to unhide then hide sections again, as obsolete.
    
    Change-Id: Ia144835548defaa38d53f03520ac0cc550bdfc23
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186108
    Reviewed-by: Mike Kaganski <[email protected]>
    Tested-by: Jenkins
    (cherry picked from commit ca3e88728f29422ad9e4bd7f9bec08b59cdf4192)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186124
    Reviewed-by: Xisco Fauli <[email protected]>
    (cherry picked from commit 65684ffbe89638407cc855e38838c5ae20cc38ee)
    
    Conflicts: sw/source/core/doc/docfld.cxx
    Change-Id: I01f57d891db7dd53f38d04b25866d1a9cec12eb6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191739
    Tested-by: allotropia jenkins <[email protected]>
    Reviewed-by: Michael Stahl <[email protected]>

diff --git a/sw/qa/extras/layout/data/table-with-hidden-section.fodt 
b/sw/qa/extras/layout/data/table-with-hidden-section.fodt
new file mode 100644
index 000000000000..1360b872aef2
--- /dev/null
+++ b/sw/qa/extras/layout/data/table-with-hidden-section.fodt
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible: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:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:ooow="http://openoffice.org/2004/writer"; office:version="1.4" 
office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+  <style:font-face style:name="Liberation Serif" 
svg:font-family="&apos;Liberation Serif&apos;" 
style:font-family-generic="roman" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="paragraph">
+   <style:paragraph-properties fo:orphans="2" fo:widows="2" 
style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" 
style:line-break="strict" style:writing-mode="page"/>
+   <style:text-properties style:font-name="Liberation Serif" 
fo:font-size="12pt" fo:language="zxx" fo:country="none" 
style:letter-kerning="true" fo:hyphenate="false"/>
+  </style:default-style>
+  <style:style style:name="Standard" style:family="paragraph" 
style:class="text"/>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="Table1" style:family="table">
+   <style:table-properties table:align="margins" 
style:may-break-between-rows="false"/>
+  </style:style>
+  <style:style style:name="Table1.1" style:family="table-row">
+   <style:table-row-properties fo:keep-together="always"/>
+  </style:style>
+  <style:style style:name="Table1.A1" style:family="table-cell">
+   <style:table-cell-properties fo:padding="1mm" fo:border="0.5pt solid 
#000000"/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="210mm" fo:page-height="297mm" 
style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" 
fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb"/>
+  </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+  <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+  <office:text>
+   <text:user-field-decls>
+    <text:user-field-decl office:value-type="float" office:value="1" 
text:name="MyVariable"/>
+   </text:user-field-decls>
+   <text:p>User variable used in section's hide condition: 
<text:user-field-get style:data-style-name="N0" 
text:name="MyVariable">1</text:user-field-get></text:p>
+   <text:p>He heard quiet steps behind him. That didn&apos;t bode well. Who 
could be following him this late at night and in this deadbeat part of town? 
And at this particular moment, just after he pulled off the big time and was 
making off with the greenbacks. Was there another crook who&apos;d had the same 
idea, and was now watching him and waiting for a chance to grab the fruit of 
his labour? Or did the steps behind him mean that one of many law officers in 
town was on to him and just waiting to pounce and snap those cuffs on his 
wrists? He nervously looked all around. Suddenly he saw the alley. Like 
lightning he darted off to the left and disappeared between the two warehouses 
almost falling over the bin lying in the middle of the pavement. He tried to 
nervously tap his way along in the inky darkness and suddenly stiffened: it was 
a dead-end, he would have to go back the way he had come. The steps got louder 
and louder, he saw the black outline of a figure coming around the corn
 er. Is this the end of the line? he thought pressing himself back against the 
wall trying to make himself invisible in the dark, was all that planning and 
energy wasted? He was dripping with sweat now, cold and wet, he could smell the 
fear coming off his clothes. Suddenly next to him, with a barely noticeable 
squeak, a door swung quietly to and fro in the night&apos;s breeze. Could this 
be the haven he&apos;d prayed for? Slowly he slid toward the door, pressing 
himself more and more into the wall, into the dark, away from his enemy. Would 
this door save his hide?</text:p>
+   <table:table table:name="Table1" table:style-name="Table1">
+    <table:table-column/>
+    <table:table-row table:style-name="Table1.1">
+     <table:table-cell table:style-name="Table1.A1" office:value-type="string">
+      <text:p>Some text in the cell above the hidden section. The total height 
of the single table cell, when the inner section is unhidden, is tall enough to 
not fit to the first page; and since the table rows aren't allowed to split 
across pages, the whole table would move to page 2. But with the section 
hidden, the cell is short enough to fit to the first page, and must appear 
there immediately below the dummy text.</text:p>
+      <text:section text:name="Section1" text:condition="ooow:MyVariable" 
text:is-hidden="true" text:display="condition">
+       <text:p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
Vestibulum consequat mi quis pretium semper. Proin luctus orci ac neque 
venenatis, quis commodo dolor posuere. Curabitur dignissim sapien quis cursus 
egestas. Donec blandit auctor arcu, nec pellentesque eros molestie eget. In 
consectetur aliquam hendrerit. Sed cursus mauris vitae ligula pellentesque, non 
pellentesque urna aliquet. Fusce placerat mauris enim, nec rutrum purus semper 
vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce pellentesque est 
orci.</text:p>
+       <text:p>Integer sodales tincidunt tristique. Sed a metus posuere, 
adipiscing nunc et, viverra odio. Donec auctor molestie sem, sit amet tristique 
lectus hendrerit sed. Cras sodales nisl sed orci mattis iaculis. Nunc eget 
dolor accumsan, pharetra risus a, vestibulum mauris. Nunc vulputate lobortis 
mollis. Vivamus nec tellus faucibus, tempor magna nec, facilisis felis. Donec 
commodo enim a vehicula pellentesque. Nullam vehicula vestibulum est vel 
ultricies.</text:p>
+       <text:p>Aliquam velit massa, laoreet vel leo nec, volutpat facilisis 
eros. Donec consequat arcu ut diam tempor luctus. Cum sociis natoque penatibus 
et magnis dis parturient montes, nascetur ridiculus mus. Praesent vitae lacus 
vel leo sodales pharetra a a nibh. Vestibulum ante ipsum primis in faucibus 
orci luctus et ultrices posuere cubilia Curae; Nam luctus tempus nibh, 
fringilla dictum augue consectetur eget. Curabitur at ante sit amet tortor 
pharetra molestie eu nec ante. Mauris tincidunt, nibh eu sollicitudin molestie, 
dolor sapien congue tortor, a pulvinar sapien turpis sed ante. Donec nec est 
elementum, euismod nulla in, mollis nunc.</text:p>
+      </text:section>
+      <text:p>Some text in the cell below the hidden section.</text:p>
+      <text:p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
Vestibulum consequat mi quis pretium semper. Proin luctus orci ac neque 
venenatis, quis commodo dolor posuere. Curabitur dignissim sapien quis cursus 
egestas. Donec blandit auctor arcu, nec pellentesque eros molestie eget. In 
consectetur aliquam hendrerit. Sed cursus mauris vitae ligula pellentesque, non 
pellentesque urna aliquet. Fusce placerat mauris enim, nec rutrum purus semper 
vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce pellentesque est 
orci.</text:p>
+      <text:p>Integer sodales tincidunt tristique. Sed a metus posuere, 
adipiscing nunc et, viverra odio. Donec auctor molestie sem, sit amet tristique 
lectus hendrerit sed. Cras sodales nisl sed orci mattis iaculis. Nunc eget 
dolor accumsan, pharetra risus a, vestibulum mauris. Nunc vulputate lobortis 
mollis. Vivamus nec tellus faucibus, tempor magna nec, facilisis felis. Donec 
commodo enim a vehicula pellentesque. Nullam vehicula vestibulum est vel 
ultricies.</text:p>
+      <text:p>Aliquam velit massa, laoreet vel leo nec, volutpat facilisis 
eros. Donec consequat arcu ut diam tempor luctus. Cum sociis natoque penatibus 
et magnis dis parturient montes, nascetur ridiculus mus. Praesent vitae lacus 
vel leo sodales pharetra a a nibh. Vestibulum ante ipsum primis in faucibus 
orci luctus et ultrices posuere cubilia Curae; Nam luctus tempus nibh, 
fringilla dictum augue consectetur eget. Curabitur at ante sit amet tortor 
pharetra molestie eu nec ante. Mauris tincidunt, nibh eu sollicitudin molestie, 
dolor sapien congue tortor, a pulvinar sapien turpis sed ante. Donec nec est 
elementum, euismod nulla in, mollis nunc.</text:p>
+     </table:table-cell>
+    </table:table-row>
+   </table:table>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 0df517ed668e..b98638c376a7 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -985,6 +985,18 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf166210)
     discardDumpedLayout();
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf166691)
+{
+    // Given a document with a table which disallows breaking across pages, 
and that has a cell
+    // with an inner section with hide condition (evaluated to true), such as 
to have the cell
+    // height enough to fit on page 1, when the section is hidden, but too 
tall when it's shown:
+    createDoc("table-with-hidden-section.fodt");
+    auto pXmlDoc = parseLayoutDump();
+
+    // Check that there is only a single page
+    assertXPath(pXmlDoc, "//page", 1);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docfld.cxx b/sw/source/core/doc/docfld.cxx
index 8b5f7d467328..d26374f8ccc6 100644
--- a/sw/source/core/doc/docfld.cxx
+++ b/sw/source/core/doc/docfld.cxx
@@ -825,41 +825,20 @@ void SwDocUpdateField::MakeFieldList_( SwDoc& rDoc, int 
eGetMode )
     {
         // In order for the frames to be created the right way, they have to 
be expanded
         // from top to bottom
+
         std::vector<sal_uLong> aTmpArr;
-        std::vector<sal_uLong>::size_type nArrStt = 0;
-        SwSectionFormats& rArr = rDoc.GetSections();
         SwSectionNode* pSectNd = nullptr;
-        sal_uLong nSttContent = rDoc.GetNodes().GetEndOfExtras().GetIndex();
-
-        for (SwSectionFormats::size_type n = rArr.size(); n; )
+        for (const auto& rFormat : rDoc.GetSections())
         {
-            SwSection* pSect = rArr[ --n ]->GetSection();
+            SwSection* pSect = rFormat->GetSection();
             if( pSect && pSect->IsHidden() && !pSect->GetCondition().isEmpty() 
&&
-                nullptr != ( pSectNd = pSect->GetFormat()->GetSectionNode() ))
-            {
+                nullptr != ( pSectNd = pSect->GetFormat()->GetSectionNode() )) 
           {
                 sal_uLong nIdx = pSectNd->GetIndex();
                 aTmpArr.push_back( nIdx );
-                if( nIdx < nSttContent )
-                    ++nArrStt;
             }
         }
         std::sort(aTmpArr.begin(), aTmpArr.end());
 
-        // Display all first so that we have frames. The BodyAnchor is defined 
by that.
-        // First the ContentArea, then the special areas!
-        for (std::vector<sal_uLong>::size_type n = nArrStt; n < 
aTmpArr.size(); ++n)
-        {
-            pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
-            OSL_ENSURE( pSectNd, "Where is my SectionNode" );
-            pSectNd->GetSection().SetCondHidden( false );
-        }
-        for (std::vector<sal_uLong>::size_type n = 0; n < nArrStt; ++n)
-        {
-            pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
-            OSL_ENSURE( pSectNd, "Where is my SectionNode" );
-            pSectNd->GetSection().SetCondHidden( false );
-        }
-
         // add all to the list so that they are sorted
         for (const auto &nId : aTmpArr)
         {
commit d2303591468250f5eb420e9f8c7f4d1af9d578e8
Author:     Mike Kaganski <[email protected]>
AuthorDate: Mon Apr 28 16:15:04 2025 +0200
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Oct 14 20:04:41 2025 +0200

    tdf#166210: invalidate parent's size when hiding section
    
    Regression from commit 0c96119895b347f8eb5bb89f393351bd3c02b9f1
    
    Change-Id: I4469749c9ff3d9fae43f00e01276c241e7c49f61
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184720
    Reviewed-by: Mike Kaganski <[email protected]>
    Tested-by: Jenkins
    Signed-off-by: Xisco Fauli <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184754
    (cherry picked from commit 819d73d5ac75487d2ca1d163c986e811a32e3fb7)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191690
    Tested-by: allotropia jenkins <[email protected]>
    Reviewed-by: Michael Stahl <[email protected]>

diff --git a/sw/qa/extras/layout/data/tdf166210.fodt 
b/sw/qa/extras/layout/data/tdf166210.fodt
new file mode 100644
index 000000000000..7e53241b76f5
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf166210.fodt
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:ooow="http://openoffice.org/2004/writer"; office:version="1.4" 
office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:body>
+  <office:text>
+   <table:table>
+    <table:table-column/>
+    <table:table-row>
+     <table:table-cell>
+      <text:section text:name="Section1" text:condition="ooow:0" 
text:display="condition">
+       <text:p>Conditional section 1</text:p>
+      </text:section>
+      <text:p>Text between sections</text:p>
+      <text:section text:name="Section2" text:condition="ooow:0" 
text:display="condition">
+       <text:p>Conditional section 2</text:p>
+      </text:section>
+     </table:table-cell>
+    </table:table-row>
+   </table:table>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 5471ea3b737a..0df517ed668e 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -950,6 +950,41 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, 
testUserFieldTypeLanguage)
                 "1,234.56");
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf166210)
+{
+    // Given a document with a table, inside which there are two conditionally 
hidden sections
+    createDoc("tdf166210.fodt");
+
+    uno::Reference<text::XTextSectionsSupplier> 
xTextSectionsSupplier(mxComponent, uno::UNO_QUERY_THROW);
+    auto xSections = xTextSectionsSupplier->getTextSections();
+    CPPUNIT_ASSERT(xSections);
+    uno::Reference<beans::XPropertySet> 
xSection1(xSections->getByName("Section1"), uno::UNO_QUERY_THROW);
+    uno::Reference<beans::XPropertySet> 
xSection2(xSections->getByName("Section2"), uno::UNO_QUERY_THROW);
+
+    Scheduler::ProcessEventsToIdle();
+    auto pXmlDoc = parseLayoutDump();
+    auto rowHeight1 = getXPath(pXmlDoc, "//body/tab/infos/bounds", 
"height").toInt32();
+    discardDumpedLayout();
+
+    // Hide first section
+    xSection1->setPropertyValue("Condition", css::uno::Any(OUString("1")));
+    Scheduler::ProcessEventsToIdle();
+    pXmlDoc = parseLayoutDump();
+    auto rowHeight2 = getXPath(pXmlDoc, "//body/tab/infos/bounds", 
"height").toInt32();
+    // Make sure that the table has shrunk its height
+    CPPUNIT_ASSERT_LESS(rowHeight1, rowHeight2);
+    discardDumpedLayout();
+
+    // Hide second section
+    xSection2->setPropertyValue("Condition", css::uno::Any(OUString("1")));
+    Scheduler::ProcessEventsToIdle();
+    pXmlDoc = parseLayoutDump();
+    auto rowHeight3 = getXPath(pXmlDoc, "//body/tab/infos/bounds", 
"height").toInt32();
+    // Make sure that the table has shrunk its height
+    CPPUNIT_ASSERT_LESS(rowHeight2, rowHeight3);
+    discardDumpedLayout();
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/sectfrm.cxx 
b/sw/source/core/layout/sectfrm.cxx
index ac2120e7837b..bbb375678e97 100644
--- a/sw/source/core/layout/sectfrm.cxx
+++ b/sw/source/core/layout/sectfrm.cxx
@@ -2692,6 +2692,7 @@ void SwSectionFrame::Modify( const SfxPoolItem* pOld, 
const SfxPoolItem * pNew )
             SwFrameAreaDefinition::FrameAreaWriteAccess area(*this);
             SwRectFnSet(this).SetHeight(area, HUGE_POSITIVE);
         }
+        GetUpper()->InvalidateSize();
 
         InvalidateFramesInSection(Lower());
         if (Lower())

Reply via email to