sw/qa/extras/uiwriter/data/tdf113877_insert_numbered_list_abcd.odt |binary
 sw/qa/extras/uiwriter/uiwriter.cxx                                 |   51 +-
 sw/source/filter/xml/xmlimp.cxx                                    |  240 
+++++++---
 sw/source/filter/xml/xmlimp.hxx                                    |    1 
 4 files changed, 228 insertions(+), 64 deletions(-)

New commits:
commit 1b04fae2b10d258d71e9e29ea659495b6d949367
Author: Serge Krot <serge.k...@cib.de>
Date:   Fri Jan 12 13:55:59 2018 +0100

    tdf#113877 Insert document: merge two lists into one
    
    When inserting a new document into current position we need to
    concat to lists into one only when they have the same list
    properties.
    
    (cherry picked from commit 311ea730cb225bca167af2e4111445608a14a263)
    
    Change-Id: I2766d5856418338fd5920968ac136899eeac7d74
    Reviewed-on: https://gerrit.libreoffice.org/47913
    Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de>
    Tested-by: Thorsten Behrens <thorsten.behr...@cib.de>

diff --git a/sw/qa/extras/uiwriter/data/tdf113877_insert_numbered_list_abcd.odt 
b/sw/qa/extras/uiwriter/data/tdf113877_insert_numbered_list_abcd.odt
new file mode 100755
index 000000000000..47fe7e0760fe
Binary files /dev/null and 
b/sw/qa/extras/uiwriter/data/tdf113877_insert_numbered_list_abcd.odt differ
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx 
b/sw/qa/extras/uiwriter/uiwriter.cxx
index 39190dffc906..90c13315ad77 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -208,6 +208,7 @@ public:
     void testTdf112025();
     void testTdf114306();
     void testTdf113877();
+    void testTdf113877NoMerge();
 
     CPPUNIT_TEST_SUITE(SwUiWriterTest);
     CPPUNIT_TEST(testReplaceForward);
@@ -315,6 +316,7 @@ public:
     CPPUNIT_TEST(testTdf112025);
     CPPUNIT_TEST(testTdf114306);
     CPPUNIT_TEST(testTdf113877);
+    CPPUNIT_TEST(testTdf113877NoMerge);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -3814,6 +3816,8 @@ void SwUiWriterTest::testTdf114306()
     xmlXPathFreeObject(pXmlObj);
 }
 
+// During insert of the document with list inside into the main document 
inside the list
+// we should merge both lists into one, when they have the same list properties
 void SwUiWriterTest::testTdf113877()
 {
     load(DATA_DIRECTORY, "tdf113877_insert_numbered_list.odt");
@@ -3831,13 +3835,52 @@ void SwUiWriterTest::testTdf113877()
         lcl_dispatchCommand(mxComponent, ".uno:InsertDoc", aPropertyValues);
     }
 
+    const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
+    const OUString listId4 = getProperty<OUString>(getParagraph(4), "ListId");
+    const OUString listId5 = getProperty<OUString>(getParagraph(5), "ListId");
+    const OUString listId6 = getProperty<OUString>(getParagraph(6), "ListId");
+    const OUString listId7 = getProperty<OUString>(getParagraph(7), "ListId");
+
+    // the initial list with 4 list items
+    CPPUNIT_ASSERT_EQUAL(listId1, listId4);
+
+    // the last of the first list, and the first of the inserted list
+    CPPUNIT_ASSERT_EQUAL(listId4, listId5);
+    CPPUNIT_ASSERT_EQUAL(listId5, listId6);
+    CPPUNIT_ASSERT_EQUAL(listId6, listId7);
+}
+
+// The same test as testTdf113877() but merging of two list should not be 
performed.
+void SwUiWriterTest::testTdf113877NoMerge()
+{
+    load(DATA_DIRECTORY, "tdf113877_insert_numbered_list.odt");
+
+    // set a page cursor into the end of the document
+    uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+    uno::Reference<text::XTextViewCursorSupplier> 
xTextViewCursorSupplier(xModel->getCurrentController(), uno::UNO_QUERY);
+    uno::Reference<text::XPageCursor> 
xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY);
+    xCursor->jumpToEndOfPage();
+
+    // insert the same document at current cursor position
+    {
+        const OUString insertFileid = 
m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"tdf113877_insert_numbered_list_abcd.odt";
+        uno::Sequence<beans::PropertyValue> 
aPropertyValues(comphelper::InitPropertySequence({ { "Name", 
uno::makeAny(insertFileid) } }));
+        lcl_dispatchCommand(mxComponent, ".uno:InsertDoc", aPropertyValues);
+    }
+
+    const OUString listId1 = getProperty<OUString>(getParagraph(1), "ListId");
+    const OUString listId4 = getProperty<OUString>(getParagraph(4), "ListId");
+    const OUString listId5 = getProperty<OUString>(getParagraph(5), "ListId");
+    const OUString listId6 = getProperty<OUString>(getParagraph(6), "ListId");
+    const OUString listId7 = getProperty<OUString>(getParagraph(7), "ListId");
+
     // the initial list with 4 list items
-    CPPUNIT_ASSERT_EQUAL(getProperty<OUString>(getParagraph(1), "ListId"), 
getProperty<OUString>(getParagraph(4), "ListId"));
+    CPPUNIT_ASSERT_EQUAL(listId1, listId4);
 
     // the last of the first list, and the first of the inserted list
-    CPPUNIT_ASSERT_EQUAL(getProperty<OUString>(getParagraph(4), "ListId"), 
getProperty<OUString>(getParagraph(5), "ListId"));
-    CPPUNIT_ASSERT_EQUAL(getProperty<OUString>(getParagraph(5), "ListId"), 
getProperty<OUString>(getParagraph(6), "ListId"));
-    CPPUNIT_ASSERT_EQUAL(getProperty<OUString>(getParagraph(6), "ListId"), 
getProperty<OUString>(getParagraph(7), "ListId"));
+    CPPUNIT_ASSERT(listId4 != listId5);
+    CPPUNIT_ASSERT_EQUAL(listId5, listId6);
+    CPPUNIT_ASSERT(listId6 != listId7);
 }
 
 CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest);
diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx
index 824d9aa6b488..d306fe06c601 100644
--- a/sw/source/filter/xml/xmlimp.cxx
+++ b/sw/source/filter/xml/xmlimp.cxx
@@ -41,6 +41,7 @@
 #include <drawdoc.hxx>
 #include <IDocumentSettingAccess.hxx>
 #include <IDocumentDeviceAccess.hxx>
+#include <IDocumentListsAccess.hxx>
 #include <IDocumentStylePoolAccess.hxx>
 #include <IDocumentDrawModelAccess.hxx>
 #include <unofreg.hxx>
@@ -51,8 +52,11 @@
 #include <poolfmt.hxx>
 #include <ndtxt.hxx>
 #include <editsh.hxx>
+#include <svl/stritem.hxx>
 #include "xmlimp.hxx"
 #include "xmltexti.hxx"
+#include <list.hxx>
+#include <swdll.hxx>
 #include <xmloff/DocumentSettingsContext.hxx>
 #include <docsh.hxx>
 #include <editeng/unolingu.hxx>
@@ -846,7 +850,7 @@ void SwXMLImport::endDocument()
 
             // tdf#113877
             // when we insert one document with list inside into another one 
with list at the insert position,
-            // the resulting numbering in these lists are not consequent.
+            // the resulting numbering in these lists is not consequent.
             //
             // Main document:
             //  1. One
@@ -869,65 +873,7 @@ void SwXMLImport::endDocument()
             //  6. Three
             //  7.
             //
-            if (IsInsertMode() && m_pSttNdIdx->GetIndex())
-            {
-                sal_uLong index = 1;
-
-                // the last node of the main document where we have inserted a 
document
-                SwNode * p1 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + 0];
-
-                // the first node of the inserted document
-                SwNode * p2 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + 
index];
-
-                // the first node of the inserted document,
-                // which will be used to detect if inside inserted document a 
new list was started
-                const SfxPoolItem* listId2Initial = nullptr;
-
-                while (
-                    p1 && p2
-                    && (p1->GetNodeType() == p2->GetNodeType())
-                    && (p1->IsTextNode() == p2->IsTextNode())
-                    )
-                {
-                    SwContentNode * c1 = static_cast<SwContentNode *>(p1);
-                    SwContentNode * c2 = static_cast<SwContentNode *>(p2);
-
-                    const SfxPoolItem* listId1 = 
c1->GetNoCondAttr(RES_PARATR_LIST_ID, false);
-                    const SfxPoolItem* listId2 = 
c2->GetNoCondAttr(RES_PARATR_LIST_ID, false);
-
-                    if (!listId2Initial)
-                    {
-                        listId2Initial = listId2;
-                    }
-
-                    if (! (listId2Initial && listId2 && (*listId2Initial == 
*listId2)) )
-                    {
-                        // no more list items of the first list inside 
inserted document
-                        break;
-                    }
-
-                    if (listId1 && listId2)
-                    {
-                        c2->SetAttr(*listId1);
-                    }
-                    else
-                    {
-                        // no more appropriate list items
-                        break;
-                    }
-
-                    // get next item
-                    index++;
-                    if (index >= pDoc->GetNodes().Count())
-                    {
-                        // no more items
-                        break;
-                    }
-
-                    p2 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + index];
-                }
-            }
-
+            MergeListsAtDocumentInsertPosition(pDoc);
         }
     }
 
@@ -1002,6 +948,180 @@ void SwXMLImport::endDocument()
     ClearTextImport();
 }
 
+// tdf#113877
+// when we insert one document with list inside into another one with list at 
the insert position,
+// the resulting numbering in these lists is not consequent.
+//
+// CASE-1: Main document:
+//  1. One
+//  2. Two
+//  3. Three
+//  4.                      <-- insert position
+//
+// Inserted document:
+//  1. One
+//  2. Two
+//  3. Three
+//  4.
+//
+// Expected result
+//  1. One
+//  2. Two
+//  3. Three
+//  4. One
+//  5. Two
+//  6. Three
+//  7.
+//
+// CASE-2: Main document:
+//  1. One
+//  2. Two
+//  3. Three
+//  4.                      <-- insert position
+//
+// Inserted document:
+//  A) One
+//  B) Two
+//  C) Three
+//  D)
+//
+// Expected result
+//  1. One
+//  2. Two
+//  3. Three
+//  4. One
+//  A) Two
+//  B) Three
+//  5.
+//
+void SwXMLImport::MergeListsAtDocumentInsertPosition(SwDoc *pDoc)
+{
+    // 1. check enviroment
+    if (! pDoc)
+        return;
+
+    if (! IsInsertMode() || ! m_pSttNdIdx->GetIndex())
+        return;
+
+    sal_uLong index = 1;
+
+    // the last node of the main document where we have inserted a document
+    const SwNodePtr node1 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + 0];
+
+    // the first node of the inserted document
+    SwNodePtr node2 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + index];
+
+    if (! (node1 && node2
+        && (node1->GetNodeType() == node2->GetNodeType())
+        && (node1->IsTextNode() == node2->IsTextNode())
+        ))
+    {
+        // not a text node at insert position
+        return;
+    }
+
+    // 2. get the first node of the inserted document,
+    // which will be used to detect if inside inserted document a new list was 
started after the first list
+    const SfxPoolItem* pListId2Initial = nullptr;
+    {
+        SwContentNode* contentNode1 = static_cast<SwContentNode *>(node1);
+        SwContentNode* contentNode2 = static_cast<SwContentNode *>(node2);
+
+        // check if both lists have the same list properties
+        const SfxPoolItem* pListId1 = contentNode1->GetNoCondAttr( 
RES_PARATR_LIST_ID, false );
+        const SfxPoolItem* pListId2 = contentNode2->GetNoCondAttr( 
RES_PARATR_LIST_ID, false );
+
+        if (! pListId1)
+            return;
+        if (! pListId2)
+            return;
+
+        const OUString& sListId1 = dynamic_cast<const 
SfxStringItem*>(pListId1)->GetValue();
+        const OUString& sListId2 = dynamic_cast<const 
SfxStringItem*>(pListId2)->GetValue();
+
+        const SwList* pList1 = pDoc->getIDocumentListsAccess().getListByName( 
sListId1 );
+        const SwList* pList2 = pDoc->getIDocumentListsAccess().getListByName( 
sListId2 );
+
+        if (! pList1)
+            return;
+        if (! pList2)
+            return;
+
+        const OUString& sDefaultListStyleName1 = 
pList1->GetDefaultListStyleName();
+        const OUString& sDefaultListStyleName2 = 
pList2->GetDefaultListStyleName();
+
+        if (sDefaultListStyleName1 != sDefaultListStyleName2)
+        {
+            const SwNumRule* pNumRule1 = pDoc->FindNumRulePtr( 
sDefaultListStyleName1 );
+            const SwNumRule* pNumRule2 = pDoc->FindNumRulePtr( 
sDefaultListStyleName2 );
+
+            if (pNumRule1 && pNumRule2)
+            {
+                // check style of the each list level
+                for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
+                {
+                    if( !( pNumRule1->Get( n ) == pNumRule2->Get( n ) ))
+                    {
+                        return;
+                    }
+                }
+
+                // our list should be merged
+                pListId2Initial = pListId2;
+            }
+        }
+        else
+        {
+            // our list should be merged
+            pListId2Initial = pListId2;
+        }
+    }
+
+    if (! pListId2Initial)
+    {
+        // two lists have different styles => they should not be merged
+        return;
+    }
+
+    // 3. merge two lists
+    while (
+        node1 && node2
+        && (node1->GetNodeType() == node2->GetNodeType())
+        && (node1->IsTextNode() == node2->IsTextNode())
+        )
+    {
+        SwContentNode* contentNode1 = static_cast<SwContentNode *>( node1 );
+        SwContentNode* contentNode2 = static_cast<SwContentNode *>( node2 );
+
+        const SfxPoolItem* pListId1 = contentNode1->GetNoCondAttr( 
RES_PARATR_LIST_ID, false );
+        const SfxPoolItem* pListId2 = contentNode2->GetNoCondAttr( 
RES_PARATR_LIST_ID, false );
+
+        if (! pListId1)
+            return;
+        if (! pListId2)
+            return;
+
+        if (*pListId2Initial != *pListId2)
+        {
+            // no more list items of the first list inside inserted document
+            return;
+        }
+
+        // set list style to this list element
+        contentNode2->SetAttr(*pListId1);
+
+        // get next item
+        index++;
+        if (index >= pDoc->GetNodes().Count())
+        {
+            // no more items
+            return;
+        }
+
+        node2 = pDoc->GetNodes()[m_pSttNdIdx->GetIndex() + index];
+    }
+}
+
 // Locally derive XMLTextShapeImportHelper, so we can take care of the
 // form import This is Writer, but not text specific, so it should go
 // here!
diff --git a/sw/source/filter/xml/xmlimp.hxx b/sw/source/filter/xml/xmlimp.hxx
index a3d335f84a95..6715b29ce8bb 100644
--- a/sw/source/filter/xml/xmlimp.hxx
+++ b/sw/source/filter/xml/xmlimp.hxx
@@ -179,6 +179,7 @@ public:
                              const OUString& rName,
                              const SfxItemSet **ppItemSet=nullptr,
                              OUString *pParent=nullptr ) const;
+    void MergeListsAtDocumentInsertPosition(SwDoc *pDoc);
 
     virtual void SetStatistics(
         const css::uno::Sequence< css::beans::NamedValue> & i_rStats) override;
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to