[Libreoffice-commits] core.git: sc/inc sc/source

Kohei Yoshida (via logerrit) logerrit at kemper.freedesktop.org
Wed Aug 21 23:56:16 UTC 2019


 sc/inc/documentimport.hxx               |    2 +
 sc/source/core/data/documentimport.cxx  |   35 ++++++++++++++++++++++++++
 sc/source/filter/inc/orcusinterface.hxx |    4 ++
 sc/source/filter/orcus/interface.cxx    |   19 ++++++++++++--
 sc/source/ui/xmlsource/xmlsourcedlg.cxx |   43 +++++++++++---------------------
 5 files changed, 72 insertions(+), 31 deletions(-)

New commits:
commit 52cff86bc74cec1a6755809c6b5434afa32a274c
Author:     Kohei Yoshida <kohei at libreoffice.org>
AuthorDate: Tue Aug 20 22:11:03 2019 -0400
Commit:     Kohei Yoshida <kohei at libreoffice.org>
CommitDate: Thu Aug 22 01:55:00 2019 +0200

    Fully support importing of XML with nested repeat elements.
    
    With this change, Calc's XML Source will allow importing XML that
    contains nested repeat elements.  It is something the old implementation
    did not support.
    
    Change-Id: I73fa1087ccd727390a47007bcfabd411cf007621
    Reviewed-on: https://gerrit.libreoffice.org/77941
    Tested-by: Jenkins
    Reviewed-by: Kohei Yoshida <kohei at libreoffice.org>

diff --git a/sc/inc/documentimport.hxx b/sc/inc/documentimport.hxx
index 7680f7880dae..758469f258a6 100644
--- a/sc/inc/documentimport.hxx
+++ b/sc/inc/documentimport.hxx
@@ -112,6 +112,8 @@ public:
 
     void setTableOpCells(const ScRange& rRange, const ScTabOpParam& rParam);
 
+    void fillDownCells(const ScAddress& rPos, SCROW nFillSize);
+
     /**
      * Set an array of cell attributes to specified column.  This call
      * transfers the ownership of the ScAttrEntry array from the caller to the
diff --git a/sc/source/core/data/documentimport.cxx b/sc/source/core/data/documentimport.cxx
index ebe1b8a6dfc8..d4c3227a8b72 100644
--- a/sc/source/core/data/documentimport.cxx
+++ b/sc/source/core/data/documentimport.cxx
@@ -537,6 +537,41 @@ void ScDocumentImport::setTableOpCells(const ScRange& rRange, const ScTabOpParam
     }
 }
 
+void ScDocumentImport::fillDownCells(const ScAddress& rPos, SCROW nFillSize)
+{
+    ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
+    if (!pTab)
+        return;
+
+    sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
+
+    if (!pBlockPos)
+        return;
+
+    sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
+    ScRefCellValue aRefCell = pTab->aCol[rPos.Col()].GetCellValue(*pBlockPos, rPos.Row());
+
+    switch (aRefCell.meType)
+    {
+        case CELLTYPE_VALUE:
+        {
+            std::vector<double> aCopied(nFillSize, aRefCell.mfValue);
+            pBlockPos->miCellPos = rCells.set(
+                pBlockPos->miCellPos, rPos.Row()+1, aCopied.begin(), aCopied.end());
+            break;
+        }
+        case CELLTYPE_STRING:
+        {
+            std::vector<svl::SharedString> aCopied(nFillSize, *aRefCell.mpString);
+            pBlockPos->miCellPos = rCells.set(
+                pBlockPos->miCellPos, rPos.Row()+1, aCopied.begin(), aCopied.end());
+            break;
+        }
+        default:
+            break;
+    }
+}
+
 void ScDocumentImport::setAttrEntries( SCTAB nTab, SCCOL nCol, Attrs&& rAttrs )
 {
     ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
diff --git a/sc/source/filter/inc/orcusinterface.hxx b/sc/source/filter/inc/orcusinterface.hxx
index 7c7c4f20bb3c..ecf8f21168ec 100644
--- a/sc/source/filter/inc/orcusinterface.hxx
+++ b/sc/source/filter/inc/orcusinterface.hxx
@@ -587,7 +587,8 @@ class ScOrcusFactory : public orcus::spreadsheet::iface::import_factory
             FormulaWithResult,
             SharedFormula,
             SharedFormulaWithResult,
-            Matrix
+            Matrix,
+            FillDownCells
         };
 
         ScAddress const maPos;
@@ -650,6 +651,7 @@ public:
     void pushCellStoreToken( const ScAddress& rPos, double fValue );
     void pushCellStoreToken(
         const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar );
+    void pushFillDownCellsToken( const ScAddress& rPos, uint32_t nFillSize );
 
     void pushSharedFormulaToken( const ScAddress& rPos, uint32_t nIndex );
     void pushMatrixFormulaToken(
diff --git a/sc/source/filter/orcus/interface.cxx b/sc/source/filter/orcus/interface.cxx
index 23f17a1dc854..fbd384be5a76 100644
--- a/sc/source/filter/orcus/interface.cxx
+++ b/sc/source/filter/orcus/interface.cxx
@@ -470,6 +470,14 @@ void ScOrcusFactory::finalize()
                 maDoc.setMatrixCells(aRange, *pArray, rToken.meGrammar);
                 break;
             }
+            case CellStoreToken::Type::FillDownCells:
+            {
+                if (!rToken.mnIndex1)
+                    break;
+
+                maDoc.fillDownCells(rToken.maPos, rToken.mnIndex1);
+                break;
+            }
             default:
                 ;
         }
@@ -538,6 +546,12 @@ void ScOrcusFactory::pushCellStoreToken(
     maCellStoreTokens.emplace_back(rPos, rFormula, eGrammar);
 }
 
+void ScOrcusFactory::pushFillDownCellsToken( const ScAddress& rPos, uint32_t nFillSize )
+{
+    maCellStoreTokens.emplace_back(rPos, CellStoreToken::Type::FillDownCells);
+    maCellStoreTokens.back().mnIndex1 = nFillSize;
+}
+
 void ScOrcusFactory::pushSharedFormulaToken( const ScAddress& rPos, uint32_t nIndex )
 {
     maCellStoreTokens.emplace_back(rPos, CellStoreToken::Type::SharedFormula);
@@ -1187,9 +1201,10 @@ orcus::spreadsheet::range_size_t ScOrcusSheet::get_sheet_size() const
     return ret;
 }
 
-void ScOrcusSheet::fill_down_cells(os::row_t /*row*/, os::col_t /*col*/, os::row_t /*range_size*/)
+void ScOrcusSheet::fill_down_cells(os::row_t row, os::col_t col, os::row_t range_size)
 {
-    // TODO : implement this.
+    mrFactory.pushFillDownCellsToken(ScAddress(col, row, mnTab), range_size);
+    cellInserted();
 }
 
 const sc::SharedFormulaGroups& ScOrcusSheet::getSharedFormulaGroups() const
diff --git a/sc/source/ui/xmlsource/xmlsourcedlg.cxx b/sc/source/ui/xmlsource/xmlsourcedlg.cxx
index dd78ab5e18b9..0cd202c8dec6 100644
--- a/sc/source/ui/xmlsource/xmlsourcedlg.cxx
+++ b/sc/source/ui/xmlsource/xmlsourcedlg.cxx
@@ -205,10 +205,10 @@ void ScXMLSourceDlg::LoadSourceFileStructure(const OUString& rPath)
 namespace {
 
 /**
- * When the current entry is a direct or indirect child of a mappable
- * repeat element entry, that entry becomes the reference entry.
- * Otherwise the reference entry equals the current entry.  A reference
- * entry is the entry that stores mapped cell position.
+ * The current entry is the reference entry for a cell link.  For a range
+ * link, the reference entry is the shallowest repeat element entry up from
+ * the current entry position.  The mapped cell position for a range link is
+ * stored with the reference entry.
  */
 std::unique_ptr<weld::TreeIter> getReferenceEntry(const weld::TreeView& rTree, weld::TreeIter& rCurEntry)
 {
@@ -221,14 +221,7 @@ std::unique_ptr<weld::TreeIter> getReferenceEntry(const weld::TreeView& rTree, w
         OSL_ASSERT(pUserData);
         if (pUserData->meType == ScOrcusXMLTreeParam::ElementRepeat)
         {
-            // This is a repeat element.
-            if (xRefEntry)
-            {
-                // Second repeat element encountered. Not good.
-                std::unique_ptr<weld::TreeIter> xCurEntry(rTree.make_iterator(&rCurEntry));
-                return xCurEntry;
-            }
-
+            // This is a repeat element - a potential reference entry.
             xRefEntry = rTree.make_iterator(xParent.get());
         }
         bParent = rTree.iter_parent(*xParent);
@@ -332,9 +325,7 @@ void ScXMLSourceDlg::RepeatElementSelected(weld::TreeIter& rEntry)
     }
 
     // Check all its child elements / attributes and make sure non of them are
-    // linked or repeat elements.  In the future we will support range linking
-    // of repeat element who has another repeat elements. But first I need to
-    // support that scenario in orcus.
+    // linked.
 
     if (IsChildrenDirty(&rEntry))
     {
@@ -420,11 +411,6 @@ bool ScXMLSourceDlg::IsParentDirty(weld::TreeIter* pEntry) const
             // This parent is already linked.
             return true;
         }
-        if (pUserData->meType == ScOrcusXMLTreeParam::ElementRepeat)
-        {
-            // This is a repeat element.
-            return true;
-        }
     }
     while (mxLbTree->iter_parent(*xParent));
     return false;
@@ -444,10 +430,6 @@ bool ScXMLSourceDlg::IsChildrenDirty(weld::TreeIter* pEntry) const
             // Already linked.
             return true;
 
-        if (pUserData->meType == ScOrcusXMLTreeParam::ElementRepeat)
-            // We don't support linking of nested repeat elements (yet).
-            return true;
-
         if (pUserData->meType == ScOrcusXMLTreeParam::ElementDefault)
         {
             // Check recursively.
@@ -478,9 +460,14 @@ void getFieldLinks(
         OUString aPath = getXPath(rTree, *xChild, rNamespaces);
         const ScOrcusXMLTreeParam::EntryData* pUserData = ScOrcusXMLTreeParam::getUserData(rTree, *xChild);
 
-        if (pUserData && pUserData->mbLeafNode)
+        if (pUserData)
         {
-            if (!aPath.isEmpty())
+            if (pUserData->meType == ScOrcusXMLTreeParam::ElementRepeat)
+                // nested repeat element automatically becomes a row-group node.
+                rRangeLink.maRowGroups.push_back(
+                    OUStringToOString(aPath, RTL_TEXTENCODING_UTF8));
+
+            if (pUserData->mbLeafNode && !aPath.isEmpty())
                 // XPath should never be empty anyway, but it won't hurt to check...
                 rRangeLink.maFieldPaths.push_back(OUStringToOString(aPath, RTL_TEXTENCODING_UTF8));
         }
@@ -533,8 +520,8 @@ void ScXMLSourceDlg::OkPressed()
             // Go through all its child elements.
             getFieldLinks(aRangeLink, aParam.maNamespaces, *mxLbTree, *rEntry);
 
-            // Add the anchor node as a grouping node, which will be used as a
-            // row position increment point.
+            // Add the reference entry as a row-group node, which will be used
+            // as a row position increment point.
             OUString aThisEntry = getXPath(*mxLbTree, *rEntry, aParam.maNamespaces);
             aRangeLink.maRowGroups.push_back(
                 OUStringToOString(aThisEntry, RTL_TEXTENCODING_UTF8));


More information about the Libreoffice-commits mailing list