sw/qa/extras/ooxmlimport/ooxmlimport2.cxx         |   31 +++++---
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |   76 ++++++++++++++--------
 2 files changed, 69 insertions(+), 38 deletions(-)

New commits:
commit 364051901c555d9609ea5f9e9427f3098a2f0bab
Author:     Mike Kaganski <[email protected]>
AuthorDate: Fri Mar 24 11:01:56 2023 +0300
Commit:     Miklos Vajna <[email protected]>
CommitDate: Tue Apr 4 10:55:58 2023 +0200

    tdf#154360: use TOC(N) styles in DOCX as the source of ToC tab stop position
    
    Change-Id: Iab8001f8be8a8af437e8898079d55ff57dd6fa3b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149494
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149548
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx 
b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
index 406812ab7fa5..04d23a4c1bc0 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -1035,39 +1035,46 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf154319)
     CPPUNIT_ASSERT_EQUAL(sal_Int32(11), xLevelFormats->getCount());
 
     const auto checkPropVal = [](const auto& expected, const 
css::beans::PropertyValues& entry,
-                                 const OUString& name) {
+                                 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();
+        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);
     };
 
+    // tdf#154360: check tab stops between the number and the entry text
+    constexpr sal_Int32 levelTabStops[]
+        = { 776, 1270, 1270, 1270, 1270, 1270, 1270, 1270, 1270, 1270 };
+
     //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(8), aLevel.getLength());
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(9), aLevel.getLength());
+
+        checkPropVal(OUString("TokenHyperlinkStart"), aLevel[0], "TokenType", 
nLevel);
 
-        checkPropVal(OUString("TokenHyperlinkStart"), aLevel[0], "TokenType");
+        checkPropVal(OUString("TokenEntryNumber"), aLevel[1], "TokenType", 
nLevel);
 
-        checkPropVal(OUString("TokenEntryNumber"), aLevel[1], "TokenType");
+        checkPropVal(OUString("TokenTabStop"), aLevel[2], "TokenType", nLevel);
+        checkPropVal(levelTabStops[nLevel - 1], aLevel[2], "TabStopPosition", 
nLevel);
 
-        checkPropVal(OUString("TokenEntryText"), aLevel[2], "TokenType");
+        checkPropVal(OUString("TokenEntryText"), aLevel[3], "TokenType", 
nLevel);
 
-        checkPropVal(OUString("TokenTabStop"), aLevel[3], "TokenType");
+        checkPropVal(OUString("TokenTabStop"), aLevel[4], "TokenType", nLevel);
 
-        checkPropVal(OUString("TokenChapterInfo"), aLevel[4], "TokenType");
+        checkPropVal(OUString("TokenChapterInfo"), aLevel[5], "TokenType", 
nLevel);
 
-        checkPropVal(OUString("TokenText"), aLevel[5], "TokenType");
-        checkPropVal(OUString("\""), aLevel[5], "Text");
+        checkPropVal(OUString("TokenText"), aLevel[6], "TokenType", nLevel);
+        checkPropVal(OUString("\""), aLevel[6], "Text", nLevel);
 
-        checkPropVal(OUString("TokenPageNumber"), aLevel[6], "TokenType");
+        checkPropVal(OUString("TokenPageNumber"), aLevel[7], "TokenType", 
nLevel);
 
-        checkPropVal(OUString("TokenHyperlinkEnd"), aLevel[7], "TokenType");
+        checkPropVal(OUString("TokenHyperlinkEnd"), aLevel[8], "TokenType", 
nLevel);
     }
 }
 
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 663e47a1fa70..ebcd8bebbbfa 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -6029,35 +6029,34 @@ void DomainMapper_Impl::handleAuthor
 }
 
 static uno::Sequence< beans::PropertyValues > lcl_createTOXLevelHyperlinks( 
bool bHyperlinks, const OUString& sChapterNoSeparator,
-                                   const uno::Sequence< beans::PropertyValues 
>& aLevel )
+                                   const uno::Sequence< beans::PropertyValues 
>& aLevel, const uno::Sequence<style::TabStop>& tabs)
 {
     //create a copy of the level and add new entries
 
     std::vector<css::beans::PropertyValues> aNewLevel;
-    aNewLevel.reserve(aLevel.getLength() + 4); // at most 4 added items
+    aNewLevel.reserve(aLevel.getLength() + 5); // at most 5 added items
 
     static constexpr OUStringLiteral tokType(u"TokenType");
     static constexpr OUStringLiteral tokHStart(u"TokenHyperlinkStart");
     static constexpr OUStringLiteral tokHEnd(u"TokenHyperlinkEnd");
     static constexpr OUStringLiteral tokPNum(u"TokenPageNumber");
+    static constexpr OUStringLiteral tokENum(u"TokenEntryNumber");
 
     if (bHyperlinks)
         aNewLevel.push_back({ comphelper::makePropertyValue(tokType, 
tokHStart) });
 
     for (const auto& item : aLevel)
     {
-        if (bHyperlinks
-            && std::any_of(item.begin(), item.end(),
-                           [](const css::beans::PropertyValue& p) {
-                               return p.Name == tokType
-                                      && (p.Value == tokHStart || p.Value == 
tokHEnd);
-                           }))
+        OUString tokenType;
+        if (auto it = std::find_if(item.begin(), item.end(),
+                                   [](const auto& p) { return p.Name == 
tokType; });
+            it != item.end())
+            it->Value >>= tokenType;
+
+        if (bHyperlinks && (tokenType == tokHStart || tokenType == tokHEnd))
             continue; // We add hyperlink ourselves, so just skip existing 
hyperlink start / end
 
-        if (!sChapterNoSeparator.isEmpty()
-            && std::any_of(item.begin(), item.end(),
-                           [](const css::beans::PropertyValue& p)
-                           { return p.Name == tokType && p.Value == tokPNum; 
}))
+        if (!sChapterNoSeparator.isEmpty() && tokenType == tokPNum)
         {
             // This is an existing page number token; insert the chapter and 
separator before it
             aNewLevel.push_back(
@@ -6068,6 +6067,14 @@ static uno::Sequence< beans::PropertyValues > 
lcl_createTOXLevelHyperlinks( bool
         }
 
         aNewLevel.push_back(item);
+
+        if (tabs.hasElements() && tokenType == tokENum)
+        {
+            // There is a fixed tab stop position needed in the level after 
the numbering
+            aNewLevel.push_back(
+                { comphelper::makePropertyValue(tokType, 
OUString("TokenTabStop")),
+                  comphelper::makePropertyValue("TabStopPosition", 
tabs[0].Position) });
+        }
     }
 
     if (bHyperlinks)
@@ -6425,22 +6432,39 @@ void DomainMapper_Impl::handleToc
             
xTOC->setPropertyValue(getPropertyName(PROP_CREATE_FROM_LEVEL_PARAGRAPH_STYLES),
 uno::Any( true ));
 
         }
-        if(bHyperlinks  || !sChapterNoSeparator.isEmpty())
+
+        uno::Reference<container::XNameContainer> xStyles;
+        if (uno::Reference<style::XStyleFamiliesSupplier> xStylesSupplier{ 
GetTextDocument(),
+                                                                           
uno::UNO_QUERY })
         {
-            uno::Reference< container::XIndexReplace> xLevelFormats;
-            xTOC->getPropertyValue(getPropertyName(PROP_LEVEL_FORMAT)) >>= 
xLevelFormats;
-            sal_Int32 nLevelCount = xLevelFormats->getCount();
-                            //start with level 1, 0 is the header level
-            for( sal_Int32 nLevel = 1; nLevel < nLevelCount; ++nLevel)
-            {
-                uno::Sequence< beans::PropertyValues > aLevel;
-                xLevelFormats->getByIndex( nLevel ) >>= aLevel;
+            auto xStyleFamilies = xStylesSupplier->getStyleFamilies();
+            xStyleFamilies->getByName(getPropertyName(PROP_PARAGRAPH_STYLES)) 
>>= xStyles;
+        }
+
+        uno::Reference< container::XIndexReplace> xLevelFormats;
+        xTOC->getPropertyValue(getPropertyName(PROP_LEVEL_FORMAT)) >>= 
xLevelFormats;
+        sal_Int32 nLevelCount = xLevelFormats->getCount();
+                        //start with level 1, 0 is the header level
+        for( sal_Int32 nLevel = 1; nLevel < nLevelCount; ++nLevel)
+        {
+            uno::Sequence< beans::PropertyValues > aLevel;
+            xLevelFormats->getByIndex( nLevel ) >>= aLevel;
 
-                uno::Sequence< beans::PropertyValues > aNewLevel = 
lcl_createTOXLevelHyperlinks(
-                                                    bHyperlinks, 
sChapterNoSeparator,
-                                                    aLevel );
-                xLevelFormats->replaceByIndex( nLevel, uno::Any( aNewLevel ) );
+            // Get the tab stops coming from the styles; store to the level 
definitions
+            uno::Sequence<style::TabStop> tabStops;
+            if (xStyles)
+            {
+                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(
+                                                bHyperlinks, 
sChapterNoSeparator,
+                                                aLevel, tabStops);
+            xLevelFormats->replaceByIndex( nLevel, uno::Any( aNewLevel ) );
         }
     }
     else if (bTableOfFigures && xTOC.is())
@@ -6464,7 +6488,7 @@ void DomainMapper_Impl::handleToc
 
             uno::Sequence< beans::PropertyValues > aNewLevel = 
lcl_createTOXLevelHyperlinks(
                                                 bHyperlinks, 
sChapterNoSeparator,
-                                                aLevel );
+                                                aLevel, {});
             xLevelFormats->replaceByIndex( 1, uno::Any( aNewLevel ) );
         }
     }

Reply via email to