sd/qa/unit/data/odp/tdf168109.fodp |   65 +++++++++++++++++++++++++++++++++++++
 sd/qa/unit/import-tests2.cxx       |   31 +++++++++++++++++
 xmloff/source/draw/ximpbody.cxx    |    5 +-
 xmloff/source/draw/ximpnote.cxx    |   17 +++++++++
 xmloff/source/draw/ximpnote.hxx    |   11 +++++-
 xmloff/source/draw/ximpshap.cxx    |    2 -
 xmloff/source/draw/ximpshap.hxx    |    5 ++
 7 files changed, 130 insertions(+), 6 deletions(-)

New commits:
commit 4ae705794f3ecaeb2f238a50f4fc4d50ebdb7590
Author:     Mike Kaganski <[email protected]>
AuthorDate: Thu Feb 12 19:11:29 2026 +0500
Commit:     Adolfo Jayme Barrientos <[email protected]>
CommitDate: Fri Feb 13 04:51:04 2026 +0100

    tdf#168109: Ignore draw:page-number attribute for notes' thumbnails
    
    ODF 1.4 Part 3 sect. 19.203 draw:page-number tells:
    
    > For thumbnails on notes pages, the value of this attribute is fixed
    > to the drawing page of a notes page.
    
    As further clarified in OASIS ODF TC call from 2025-11-24 for issue
    OFFICE-4178, that wording shall be improved to unambiguously point to
    exactly the drawing page of the respective notes page. This means,
    that for thumbnail of DrawingPage's notes page, the actual value of
    the attribute is unimportant. As the bugdoc shows, the attribute may
    be missing. It may also possibly have wrong number. In any case, we
    should not break the default correct reference established between
    the thumbnail object and respective DrawingPage, when thumbnail was
    created.
    
    This change implements just that. For SdXMLPageShapeContext, it adds
    a new method ignorePageNumber, which sets mnPageNumber to -1. Given
    that this value corresponds to draw:page-number, having XML type
    positiveInteger, this special value is safe and cannot coincide with
    any valid value there. Its meaning is "do not set the shape's page
    number", which will keep the mentioned original reference.
    
    ignorePageNumber is only called in the context of DrawingPage/notes
    page: the "ignore" flag is passed through SdXMLNotesContext from
    SdXMLDrawPageContext::createFastChildContext. For notes of master
    page, handled in SdXMLMasterPageContext::createFastChildContext, no
    change is done.
    
    Change-Id: I39ef16d4e0ceda89b38ee994c908157e93c119a2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199283
    Reviewed-by: Mike Kaganski <[email protected]>
    Tested-by: Jenkins
    (cherry picked from commit 5a0d14eb62dcccfd8f6185b9f493d6e1ff3f4bf1)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199303
    Reviewed-by: Adolfo Jayme Barrientos <[email protected]>

diff --git a/sd/qa/unit/data/odp/tdf168109.fodp 
b/sd/qa/unit/data/odp/tdf168109.fodp
new file mode 100644
index 000000000000..9a38821214a3
--- /dev/null
+++ b/sd/qa/unit/data/odp/tdf168109.fodp
@@ -0,0 +1,65 @@
+<?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:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" 
office:version="1.4" 
office:mimetype="application/vnd.oasis.opendocument.presentation">
+ <office:styles>
+  <style:style style:name="standard" style:family="graphic">
+   <style:graphic-properties draw:fill="none"/>
+  </style:style>
+ </office:styles>
+ <office:body>
+  <office:presentation>
+   <draw:page>
+    <draw:frame svg:width="20cm" svg:height="3cm" svg:x="5mm" svg:y="5mm" 
presentation:class="title">
+     <draw:text-box>
+      <text:p>Slide One</text:p>
+     </draw:text-box>
+    </draw:frame>
+    <draw:frame svg:width="20cm" svg:height="9cm" svg:x="5mm" svg:y="4cm" 
presentation:class="outline">
+     <draw:text-box>
+      <text:list>
+       <text:list-item>
+        <text:p>One</text:p>
+       </text:list-item>
+       <text:list-item>
+        <text:p>Two</text:p>
+       </text:list-item>
+      </text:list>
+     </draw:text-box>
+    </draw:frame>
+    <presentation:notes>
+     <!-- First case: the 'draw:page-number' attribute is missing -->
+     <draw:page-thumbnail svg:width="20cm" svg:height="11cm" svg:x="5mm" 
svg:y="5mm" presentation:class="page"/>
+     <draw:frame svg:width="20cm" svg:height="13cm" svg:x="5mm" svg:y="12cm">
+      <draw:text-box/>
+     </draw:frame>
+    </presentation:notes>
+   </draw:page>
+   <draw:page>
+    <draw:frame svg:width="20cm" svg:height="3cm" svg:x="5mm" svg:y="5mm" 
presentation:class="title">
+     <draw:text-box>
+      <text:p>Slide Two</text:p>
+     </draw:text-box>
+    </draw:frame>
+    <draw:frame svg:width="20cm" svg:height="9cm" svg:x="5mm" svg:y="4cm" 
presentation:class="outline">
+     <draw:text-box>
+      <text:list>
+       <text:list-item>
+        <text:p>Foo</text:p>
+       </text:list-item>
+       <text:list-item>
+        <text:p>Bar</text:p>
+       </text:list-item>
+      </text:list>
+     </draw:text-box>
+    </draw:frame>
+    <presentation:notes>
+     <!-- Second case: the 'draw:page-number' attribute is wrong -->
+     <draw:page-thumbnail svg:width="20cm" svg:height="11cm" svg:x="5mm" 
svg:y="5mm" draw:page-number="1" presentation:class="page"/>
+     <draw:frame svg:width="20cm" svg:height="13cm" svg:x="5mm" svg:y="12cm">
+      <draw:text-box/>
+     </draw:frame>
+    </presentation:notes>
+   </draw:page>
+  </office:presentation>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sd/qa/unit/import-tests2.cxx b/sd/qa/unit/import-tests2.cxx
index cdae01a52184..5d534dc490a6 100644
--- a/sd/qa/unit/import-tests2.cxx
+++ b/sd/qa/unit/import-tests2.cxx
@@ -2298,6 +2298,37 @@ CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf169524)
     CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nLeftMargin);
 }
 
+CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf168109)
+{
+    createSdImpressDoc("odp/tdf168109.fodp");
+
+    // Slide 1
+    {
+        auto xPage = getPage(0).queryThrow<presentation::XPresentationPage>();
+        auto xNotesPage = xPage->getNotesPage();
+        auto xThumbnail = getShape(0, xNotesPage);
+        auto xDescriptor = xThumbnail.queryThrow<drawing::XShapeDescriptor>();
+
+        CPPUNIT_ASSERT_EQUAL(u"com.sun.star.presentation.PageShape"_ustr,
+                             xDescriptor->getShapeType());
+        CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(1)),
+                             xThumbnail->getPropertyValue(u"PageNumber"_ustr));
+    }
+
+    // Slide 2
+    {
+        auto xPage = getPage(1).queryThrow<presentation::XPresentationPage>();
+        auto xNotesPage = xPage->getNotesPage();
+        auto xThumbnail = getShape(0, xNotesPage);
+        auto xDescriptor = xThumbnail.queryThrow<drawing::XShapeDescriptor>();
+
+        CPPUNIT_ASSERT_EQUAL(u"com.sun.star.presentation.PageShape"_ustr,
+                             xDescriptor->getShapeType());
+        CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(2)),
+                             xThumbnail->getPropertyValue(u"PageNumber"_ustr));
+    }
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/draw/ximpbody.cxx b/xmloff/source/draw/ximpbody.cxx
index f1f19a156ffa..591832735414 100644
--- a/xmloff/source/draw/ximpbody.cxx
+++ b/xmloff/source/draw/ximpbody.cxx
@@ -247,8 +247,9 @@ css::uno::Reference< css::xml::sax::XFastContextHandler >  
SdXMLDrawPageContext:
                     uno::Reference< drawing::XDrawPage > xNotesDrawPage = 
xPresPage->getNotesPage();
                     if(xNotesDrawPage.is())
                     {
-                        // presentation:notes inside draw:page context
-                        return new SdXMLNotesContext( GetSdImport(), 
xAttrList, xNotesDrawPage);
+                        // presentation:notes inside draw:page context. Inside 
notes, thumbnails
+                        // are fixed to this page, and actual page number 
attribute must be ignored
+                        return new SdXMLNotesContext(GetSdImport(), xAttrList, 
xNotesDrawPage, true);
                     }
                 }
             }
diff --git a/xmloff/source/draw/ximpnote.cxx b/xmloff/source/draw/ximpnote.cxx
index d855e85bf4ad..9035648cb9ed 100644
--- a/xmloff/source/draw/ximpnote.cxx
+++ b/xmloff/source/draw/ximpnote.cxx
@@ -18,6 +18,7 @@
  */
 
 #include "ximpnote.hxx"
+#include "ximpshap.hxx"
 #include <xmloff/xmlnamespace.hxx>
 
 using namespace ::com::sun::star;
@@ -25,8 +26,9 @@ using namespace ::xmloff::token;
 
 SdXMLNotesContext::SdXMLNotesContext(
     SdXMLImport& rImport, const 
css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList,
-    uno::Reference<drawing::XShapes> const& rShapes)
+    uno::Reference<drawing::XShapes> const& rShapes, bool 
ignorePageNumberInThumbnail)
     : SdXMLGenericPageContext(rImport, xAttrList, rShapes)
+    , mbIgnorePageNumberInThumbnail(ignorePageNumberInThumbnail)
 {
     OUString sStyleName, sPageMasterName;
 
@@ -89,4 +91,17 @@ SdXMLNotesContext::SdXMLNotesContext(
 
 SdXMLNotesContext::~SdXMLNotesContext() {}
 
+uno::Reference<xml::sax::XFastContextHandler> 
SdXMLNotesContext::createFastChildContext(
+    sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& 
xAttrList)
+{
+    auto pContext = SdXMLGenericPageContext::createFastChildContext(nElement, 
xAttrList);
+    if (nElement == XML_ELEMENT(DRAW, XML_PAGE_THUMBNAIL) && 
mbIgnorePageNumberInThumbnail)
+    {
+        assert(dynamic_cast<SdXMLPageShapeContext*>(pContext.get()));
+        auto pPageShapeContext = 
static_cast<SdXMLPageShapeContext*>(pContext.get());
+        pPageShapeContext->ignorePageNumber();
+    }
+    return pContext;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/draw/ximpnote.hxx b/xmloff/source/draw/ximpnote.hxx
index d7fe276b84eb..2048fc36ea62 100644
--- a/xmloff/source/draw/ximpnote.hxx
+++ b/xmloff/source/draw/ximpnote.hxx
@@ -29,8 +29,17 @@ class SdXMLNotesContext : public SdXMLGenericPageContext
 public:
     SdXMLNotesContext( SdXMLImport& rImport,
         const css::uno::Reference< css::xml::sax::XFastAttributeList>& 
xAttrList,
-        css::uno::Reference< css::drawing::XShapes > const & rShapes);
+        css::uno::Reference< css::drawing::XShapes > const & rShapes,
+        bool ignorePageNumberInThumbnail = false);
     virtual ~SdXMLNotesContext() override;
+
+    // XFastContextHandler
+    virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL 
createFastChildContext(
+        sal_Int32 nElement,
+        const css::uno::Reference<css::xml::sax::XFastAttributeList>& 
xAttrList) override;
+
+private:
+    bool mbIgnorePageNumberInThumbnail;
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx
index 9e9a0ff55024..9675810e3f76 100644
--- a/xmloff/source/draw/ximpshap.cxx
+++ b/xmloff/source/draw/ximpshap.cxx
@@ -2246,7 +2246,7 @@ void SdXMLPageShapeContext::startFastElement (sal_Int32 
nElement,
     SetTransformation();
 
     uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
-    if(xPropSet.is())
+    if (xPropSet.is() && mnPageNumber >= 0) // mnPageNumber < 0 means "ignore"
     {
         uno::Reference< beans::XPropertySetInfo > xPropSetInfo( 
xPropSet->getPropertySetInfo() );
         static constexpr OUString aPageNumberStr(u"PageNumber"_ustr);
diff --git a/xmloff/source/draw/ximpshap.hxx b/xmloff/source/draw/ximpshap.hxx
index 6a00cb252e5f..640cf26fdb5b 100644
--- a/xmloff/source/draw/ximpshap.hxx
+++ b/xmloff/source/draw/ximpshap.hxx
@@ -340,7 +340,7 @@ public:
     virtual bool processAttribute( const 
sax_fastparser::FastAttributeList::FastAttributeIter & ) override;
 };
 
-// draw:page context
+// draw:thumbnail context
 
 class SdXMLPageShapeContext : public SdXMLShapeContext
 {
@@ -359,6 +359,9 @@ public:
 
     // this is called from the parent group for each unparsed attribute in the 
attribute list
     virtual bool processAttribute( const 
sax_fastparser::FastAttributeList::FastAttributeIter & ) override;
+
+    // Do not try to set page number to the thumbnail (keep the default 
association)
+    void ignorePageNumber() { mnPageNumber = -1; }
 };
 
 // draw:caption context

Reply via email to