sw/qa/extras/layout/data/table-with-hidden-section.fodt |   57 ++++++++++++++++
 sw/qa/extras/layout/layout5.cxx                         |   12 +++
 sw/source/core/doc/docfld.cxx                           |   53 --------------
 3 files changed, 72 insertions(+), 50 deletions(-)

New commits:
commit ca3e88728f29422ad9e4bd7f9bec08b59cdf4192
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Jun 1 16:06:42 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sun Jun 1 18:00:26 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 <mike.kagan...@collabora.com>
    Tested-by: Jenkins

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/layout5.cxx b/sw/qa/extras/layout/layout5.cxx
index ce88823321a9..e0ca92bd4524 100644
--- a/sw/qa/extras/layout/layout5.cxx
+++ b/sw/qa/extras/layout/layout5.cxx
@@ -1739,6 +1739,18 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf165094)
     assertXPath(pXmlDoc, "//page[3]/body/tab", 1);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, 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:
+    createSwDoc("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 9db8b6e038d8..54e28f79b297 100644
--- a/sw/source/core/doc/docfld.cxx
+++ b/sw/source/core/doc/docfld.cxx
@@ -836,9 +836,6 @@ void SwDocUpdateField::MakeFieldList_( SwDoc& rDoc, int 
eGetMode )
     // new version: walk all fields of the attribute pool
     m_pFieldSortList.reset(new SetGetExpFields);
 
-    // remember sections that were unhidden and need to be hidden again
-    std::vector<std::reference_wrapper<SwSection>> aUnhiddenSections;
-
     // consider and unhide sections
     //     with hide condition, only in mode GETFLD_ALL (<eGetMode == 
GETFLD_ALL>)
     //     notes by OD:
@@ -858,56 +855,19 @@ 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<SwNodeOffset> aTmpArr;
-        std::vector<SwNodeOffset>::size_type nArrStt = 0;
-        SwSectionFormats& rArr = rDoc.GetSections();
-        SwSectionNode* pSectNd = nullptr;
-        SwNodeOffset 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() )
                 continue;
-            pSectNd = pSect->GetFormat()->GetSectionNode();
-            if( pSectNd )
+            if (SwSectionNode* pSectNd = pSect->GetFormat()->GetSectionNode())
             {
                 SwNodeOffset 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" );
-
-            auto& rSection = pSectNd->GetSection();
-            // unhide and remember the conditionally hidden sections
-            if (rSection.IsHidden() && !rSection.GetCondition().isEmpty() && 
rSection.IsCondHidden())
-            {
-                aUnhiddenSections.push_back(std::ref(rSection)); // remember 
to later hide again
-                rSection.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" );
-
-            auto& rSection = pSectNd->GetSection();
-            // unhide and remember the conditionally hidden sections
-            if (rSection.IsHidden() && !rSection.GetCondition().isEmpty() && 
rSection.IsCondHidden())
-            {
-                aUnhiddenSections.push_back(std::ref(rSection)); // remember 
to later hide again
-                rSection.SetCondHidden(false);
-            }
-        }
-
         // add all to the list so that they are sorted
         for (const auto &nId : aTmpArr)
         {
@@ -1049,13 +1009,6 @@ void SwDocUpdateField::MakeFieldList_( SwDoc& rDoc, int 
eGetMode )
     }
     m_nFieldListGetMode = eGetMode;
     m_nNodes = rDoc.GetNodes().Count();
-
-    // return the conditional hidden value back to the previous value
-    for (auto& rSectionWrapper : aUnhiddenSections)
-    {
-        auto& rSection = rSectionWrapper.get();
-        rSection.SetCondHidden(true);
-    }
 }
 
 void SwDocUpdateField::GetBodyNode( const SwTextField& rTField, SwFieldIds 
nFieldWhich )

Reply via email to