sw/qa/extras/ooxmlimport/data/tdf154695-ToC_no_numbers.docx |binary
 sw/qa/extras/ooxmlimport/ooxmlimport2.cxx                   |   80 ++++++++++--
 writerfilter/source/dmapper/DomainMapper_Impl.cxx           |   37 ++++-
 3 files changed, 98 insertions(+), 19 deletions(-)

New commits:
commit 8914765ec9330d250e220b1ef51f7c62b82b8e2f
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sat Apr 8 00:03:31 2023 +0300
Commit:     Adolfo Jayme Barrientos <fit...@ubuntu.com>
CommitDate: Sat Apr 8 23:18:53 2023 +0200

    tdf#154695: use Chapter Numbering Rules to confirm that ToC needs tabs
    
    Indeed, this still can't handle it per-element, like Word does: the latter
    would omit both the number and the tab for headings without numbering. But
    at least the most common case should be handled better now.
    
    Change-Id: I0be5d61a5d2cbbf778ee88a11129a6e7655593ec
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150133
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    (cherry picked from commit b6a5f16a9bf3227867bf46b88d012440138b6f24)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150142
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/sw/qa/extras/ooxmlimport/data/tdf154695-ToC_no_numbers.docx 
b/sw/qa/extras/ooxmlimport/data/tdf154695-ToC_no_numbers.docx
new file mode 100644
index 000000000000..fb86250fd415
Binary files /dev/null and 
b/sw/qa/extras/ooxmlimport/data/tdf154695-ToC_no_numbers.docx differ
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx 
b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
index 532ad030b28d..37f1a48ca834 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -1045,8 +1045,9 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf154319)
     };
 
     // tdf#154360: check tab stops between the number and the entry text
+    // The last (10th) level does not correspont to any MS level (only 9 
levels there)
     constexpr sal_Int32 levelTabStops[]
-        = { 776, 1270, 1270, 1270, 1270, 1270, 1270, 1270, 1270, 1270 };
+        = { 776, 1270, 1270, 1270, 1270, 1270, 1270, 1270, 1270, -1 };
 
     //start with level 1, 0 is the header level
     for (sal_Int32 nLevel = 1; nLevel < xLevelFormats->getCount(); ++nLevel)
@@ -1054,27 +1055,80 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf154319)
         css::uno::Sequence<css::beans::PropertyValues> aLevel;
         xLevelFormats->getByIndex(nLevel) >>= aLevel;
 
-        CPPUNIT_ASSERT_EQUAL(sal_Int32(9), aLevel.getLength());
+        sal_Int32 nTabStop = levelTabStops[nLevel - 1];
+        sal_Int32 nExpectedTokens = nTabStop < 0 ? 8 : 9;
+        CPPUNIT_ASSERT_EQUAL(nExpectedTokens, aLevel.getLength());
+        sal_Int32 nIndex = 0;
 
-        checkPropVal(OUString("TokenHyperlinkStart"), aLevel[0], "TokenType", 
nLevel);
+        checkPropVal(OUString("TokenHyperlinkStart"), aLevel[nIndex++], 
"TokenType", nLevel);
 
-        checkPropVal(OUString("TokenEntryNumber"), aLevel[1], "TokenType", 
nLevel);
+        checkPropVal(OUString("TokenEntryNumber"), aLevel[nIndex++], 
"TokenType", nLevel);
+
+        if (nTabStop >= 0)
+        {
+            checkPropVal(OUString("TokenTabStop"), aLevel[nIndex], 
"TokenType", nLevel);
+            checkPropVal(levelTabStops[nLevel - 1], aLevel[nIndex++], 
"TabStopPosition", nLevel);
+        }
+
+        checkPropVal(OUString("TokenEntryText"), aLevel[nIndex++], 
"TokenType", nLevel);
+
+        checkPropVal(OUString("TokenTabStop"), aLevel[nIndex++], "TokenType", 
nLevel);
+
+        checkPropVal(OUString("TokenChapterInfo"), aLevel[nIndex++], 
"TokenType", nLevel);
+
+        checkPropVal(OUString("TokenText"), aLevel[nIndex], "TokenType", 
nLevel);
+        checkPropVal(OUString("\""), aLevel[nIndex++], "Text", nLevel);
+
+        checkPropVal(OUString("TokenPageNumber"), aLevel[nIndex++], 
"TokenType", nLevel);
+
+        checkPropVal(OUString("TokenHyperlinkEnd"), aLevel[nIndex++], 
"TokenType", nLevel);
+    }
+}
 
-        checkPropVal(OUString("TokenTabStop"), aLevel[2], "TokenType", nLevel);
-        checkPropVal(levelTabStops[nLevel - 1], aLevel[2], "TabStopPosition", 
nLevel);
+CPPUNIT_TEST_FIXTURE(Test, testTdf154695)
+{
+    createSwDoc("tdf154695-ToC_no_numbers.docx");
 
-        checkPropVal(OUString("TokenEntryText"), aLevel[3], "TokenType", 
nLevel);
+    css::uno::Reference<css::text::XDocumentIndexesSupplier> 
xSupplier(mxComponent,
+                                                                       
css::uno::UNO_QUERY_THROW);
+    auto xIndexes = xSupplier->getDocumentIndexes();
+    css::uno::Reference<css::beans::XPropertySet> 
xTOCIndex(xIndexes->getByIndex(0),
+                                                            
css::uno::UNO_QUERY_THROW);
+    css::uno::Reference<css::container::XIndexReplace> xLevelFormats;
+    CPPUNIT_ASSERT(xTOCIndex->getPropertyValue("LevelFormat") >>= 
xLevelFormats);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(11), xLevelFormats->getCount());
+
+    const auto checkPropVal = [](const auto& expected, const 
css::beans::PropertyValues& entry,
+                                 const OUString& name, sal_Int32 level) {
+        auto it
+            = std::find_if(entry.begin(), entry.end(),
+                           [&name](const css::beans::PropertyValue& p) { 
return p.Name == name; });
+        OString msg = "Property: " + name.toUtf8() + ", level: " + 
OString::number(level);
+        CPPUNIT_ASSERT_MESSAGE(msg.getStr(), it != entry.end());
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.getStr(), css::uno::Any(expected), 
it->Value);
+    };
+
+    //start with level 1, 0 is the header level
+    for (sal_Int32 nLevel = 1; nLevel < xLevelFormats->getCount(); ++nLevel)
+    {
+        css::uno::Sequence<css::beans::PropertyValues> aLevel;
+        xLevelFormats->getByIndex(nLevel) >>= aLevel;
+
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aLevel.getLength());
+
+        checkPropVal(OUString("TokenHyperlinkStart"), aLevel[0], "TokenType", 
nLevel);
+
+        checkPropVal(OUString("TokenEntryNumber"), aLevel[1], "TokenType", 
nLevel);
 
-        checkPropVal(OUString("TokenTabStop"), aLevel[4], "TokenType", nLevel);
+        // There's no tab stop between [#E] and [E]!
 
-        checkPropVal(OUString("TokenChapterInfo"), aLevel[5], "TokenType", 
nLevel);
+        checkPropVal(OUString("TokenEntryText"), aLevel[2], "TokenType", 
nLevel);
 
-        checkPropVal(OUString("TokenText"), aLevel[6], "TokenType", nLevel);
-        checkPropVal(OUString("\""), aLevel[6], "Text", nLevel);
+        checkPropVal(OUString("TokenTabStop"), aLevel[3], "TokenType", nLevel);
 
-        checkPropVal(OUString("TokenPageNumber"), aLevel[7], "TokenType", 
nLevel);
+        checkPropVal(OUString("TokenPageNumber"), aLevel[4], "TokenType", 
nLevel);
 
-        checkPropVal(OUString("TokenHyperlinkEnd"), aLevel[8], "TokenType", 
nLevel);
+        checkPropVal(OUString("TokenHyperlinkEnd"), aLevel[5], "TokenType", 
nLevel);
     }
 }
 
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index ebcd8bebbbfa..3b774608756a 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -51,6 +51,7 @@
 #include <com/sun/star/text/XFootnotesSupplier.hpp>
 #include <com/sun/star/text/XLineNumberingProperties.hpp>
 #include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/text/LabelFollow.hpp>
 #include <com/sun/star/text/PageNumberType.hpp>
 #include <com/sun/star/text/HoriOrientation.hpp>
 #include <com/sun/star/text/VertOrientation.hpp>
@@ -60,6 +61,7 @@
 #include <com/sun/star/text/SizeType.hpp>
 #include <com/sun/star/text/TextContentAnchorType.hpp>
 #include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
 #include <com/sun/star/text/XDependentTextField.hpp>
 #include <com/sun/star/text/XParagraphCursor.hpp>
 #include <com/sun/star/text/XRedline.hpp>
@@ -6433,6 +6435,10 @@ void DomainMapper_Impl::handleToc
 
         }
 
+        uno::Reference<container::XIndexAccess> xChapterNumberingRules;
+        if (uno::Reference<text::XChapterNumberingSupplier> xSupplier{ 
GetTextDocument(),
+                                                                       
uno::UNO_QUERY })
+            xChapterNumberingRules = xSupplier->getChapterNumberingRules();
         uno::Reference<container::XNameContainer> xStyles;
         if (uno::Reference<style::XStyleFamiliesSupplier> xStylesSupplier{ 
GetTextDocument(),
                                                                            
uno::UNO_QUERY })
@@ -6452,13 +6458,32 @@ void DomainMapper_Impl::handleToc
 
             // Get the tab stops coming from the styles; store to the level 
definitions
             uno::Sequence<style::TabStop> tabStops;
-            if (xStyles)
+            if (xChapterNumberingRules && xStyles)
             {
-                OUString style;
-                xTOC->getPropertyValue("ParaStyleLevel" + 
OUString::number(nLevel)) >>= style;
-                uno::Reference<beans::XPropertySet> xStyle;
-                if (xStyles->getByName(style) >>= xStyle)
-                    xStyle->getPropertyValue("ParaTabStops") >>= tabStops;
+                // This relies on the chapter numbering rules already defined
+                // (see ListDef::CreateNumberingRules)
+                uno::Sequence<beans::PropertyValue> props;
+                xChapterNumberingRules->getByIndex(nLevel - 1) >>= props;
+                bool bHasNumbering = false;
+                bool bUseTabStop = false;
+                for (const auto& propval : props)
+                {
+                    // We rely on PositionAndSpaceMode being always equal to 
LABEL_ALIGNMENT,
+                    // because ListDef::CreateNumberingRules doesn't create 
legacy lists
+                    if (propval.Name == "NumberingType")
+                        bHasNumbering = propval.Value != 
style::NumberingType::NUMBER_NONE;
+                    else if (propval.Name == "LabelFollowedBy")
+                        bUseTabStop = propval.Value == 
text::LabelFollow::LISTTAB;
+                    // Do not use FirstLineIndent property from the rules, 
because it is unreliable
+                }
+                if (bHasNumbering && bUseTabStop)
+                {
+                    OUString style;
+                    xTOC->getPropertyValue("ParaStyleLevel" + 
OUString::number(nLevel)) >>= style;
+                    uno::Reference<beans::XPropertySet> xStyle;
+                    if (xStyles->getByName(style) >>= xStyle)
+                        xStyle->getPropertyValue("ParaTabStops") >>= tabStops;
+                }
             }
 
             uno::Sequence< beans::PropertyValues > aNewLevel = 
lcl_createTOXLevelHyperlinks(

Reply via email to