[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - sc/inc sc/qa sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Thu Mar 14 09:15:38 PDT 2013


 sc/inc/column.hxx                      |    2 
 sc/inc/columniterator.hxx              |   11 +++
 sc/inc/document.hxx                    |    2 
 sc/inc/table.hxx                       |    2 
 sc/qa/unit/ucalc.cxx                   |   79 +++++++++++++++++++++
 sc/source/core/data/columniterator.cxx |  119 ++++++++++++++++++---------------
 sc/source/core/data/document.cxx       |    9 ++
 7 files changed, 171 insertions(+), 53 deletions(-)

New commits:
commit c6eb99af79b498fb201610502dfe23b46067ba8a
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Mar 14 12:14:40 2013 -0400

    Unit test for the new column-based text width storage, via new iterator.
    
    Change-Id: Ibf1e254e34df98ad5c46a46252168787b07d161c

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 93ae44f..114a39b 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -97,7 +97,6 @@ class ScColumn
     ScAttrArray*       pAttrArray;
     ScDocument*                pDocument;
 
-friend class ScColumnTextWidthIterator;
 friend class ScDocument;                                       // for FillInfo
 friend class ScDocumentIterator;
 friend class ScValueIterator;
@@ -109,6 +108,7 @@ friend class ScMarkedDataIter;
 friend class ScCellIterator;
 friend class ScHorizontalCellIterator;
 friend class ScHorizontalAttrIterator;
+friend class ScColumnTextWidthIterator;
 
     ScColumn(const ScColumn&); // disabled
     ScColumn& operator= (const ScColumn&); // disabled
diff --git a/sc/inc/columniterator.hxx b/sc/inc/columniterator.hxx
index a70567c56..7bd645d 100644
--- a/sc/inc/columniterator.hxx
+++ b/sc/inc/columniterator.hxx
@@ -31,6 +31,16 @@ class ScColumnTextWidthIterator : boost::noncopyable
 public:
     ScColumnTextWidthIterator(ScColumn& rCol, SCROW nStartRow, SCROW nEndRow);
 
+    /**
+     * @param rDoc document instance.
+     * @param rStartPos position of the first cell from which to start
+     *                  iteration. Note that the caller must ensure that this
+     *                  position is valid; the constructor does not check its
+     *                  validity.
+     * @param nEndRow end row position.
+     */
+    ScColumnTextWidthIterator(ScDocument& rDoc, const ScAddress& rStartPos, SCROW nEndRow);
+
     void next();
     bool hasCell() const;
     SCROW getPos() const;
@@ -38,6 +48,7 @@ public:
     void setValue(sal_uInt16 nVal);
 
 private:
+    void init(SCROW nStartRow, SCROW nEndRow);
     void getDataIterators(size_t nOffsetInBlock);
     void checkEndRow();
 };
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 2f59ef1..541ec05 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -214,6 +214,7 @@ friend class ScDocAttrIterator;
 friend class ScAttrRectIterator;
 friend class ScDocShell;
 friend class ScDocRowHeightUpdater;
+friend class ScColumnTextWidthIterator;
 
     typedef ::std::vector<ScTable*> TableContainer;
 private:
@@ -1844,6 +1845,7 @@ public:
     void RemoveSubTotalCell(ScFormulaCell* pCell);
     void SetSubTotalCellsDirty(const ScRange& rDirtyRange);
 
+    sal_uInt16 GetTextWidth( const ScAddress& rPos ) const;
     void SetTextWidth( const ScAddress& rPos, sal_uInt16 nWidth );
 
 private: // CLOOK-Impl-methods
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 8786ccf..3e4d1eb 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -187,7 +187,7 @@ friend class ScHorizontalCellIterator;
 friend class ScHorizontalAttrIterator;
 friend class ScDocAttrIterator;
 friend class ScAttrRectIterator;
-
+friend class ScColumnTextWidthIterator;
 
 public:
                 ScTable( ScDocument* pDoc, SCTAB nNewTab, const rtl::OUString& rNewName,
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 232a501..57b00f4 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -65,6 +65,7 @@
 #include "dpfilteredcache.hxx"
 #include "calcconfig.hxx"
 #include "interpre.hxx"
+#include "columniterator.hxx"
 
 #include "formula/IFunctionDescription.hxx"
 
@@ -262,6 +263,7 @@ public:
     void testDeleteRow();
     void testDeleteCol();
     void testAnchoredRotatedShape();
+    void testCellTextWidth();
 
     CPPUNIT_TEST_SUITE(Test);
     CPPUNIT_TEST(testCollator);
@@ -323,6 +325,7 @@ public:
     CPPUNIT_TEST(testDeleteRow);
     CPPUNIT_TEST(testDeleteCol);
     CPPUNIT_TEST(testAnchoredRotatedShape);
+    CPPUNIT_TEST(testCellTextWidth);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -6025,6 +6028,82 @@ void Test::testAnchoredRotatedShape()
     m_pDoc->DeleteTab(0);
 }
 
+void Test::testCellTextWidth()
+{
+    m_pDoc->InsertTab(0, "Test");
+
+    ScAddress aTopCell(0, 0, 0);
+
+    // Sheet is empty.
+    boost::scoped_ptr<ScColumnTextWidthIterator> pIter(new ScColumnTextWidthIterator(*m_pDoc, aTopCell, MAXROW));
+    CPPUNIT_ASSERT_MESSAGE("Column should have no text widths stored.", !pIter->hasCell());
+
+    // Sheet only has one cell.
+    m_pDoc->SetString(0, 0, 0, "Only one cell");
+    pIter.reset(new ScColumnTextWidthIterator(*m_pDoc, aTopCell, MAXROW));
+    CPPUNIT_ASSERT_MESSAGE("Column should have a cell.", pIter->hasCell());
+    CPPUNIT_ASSERT_EQUAL(0, pIter->getPos());
+
+    // Setting a text width here should commit it to the column.
+    sal_uInt16 nTestVal = 432;
+    pIter->setValue(nTestVal);
+    CPPUNIT_ASSERT_EQUAL(nTestVal, m_pDoc->GetTextWidth(aTopCell));
+
+    // Set values to row 2 through 6.
+    for (SCROW i = 2; i <= 6; ++i)
+        m_pDoc->SetString(0, i, 0, "foo");
+
+    // Set values to row 10 through 18.
+    for (SCROW i = 10; i <= 18; ++i)
+        m_pDoc->SetString(0, i, 0, "foo");
+
+    {
+        // Full range.
+        pIter.reset(new ScColumnTextWidthIterator(*m_pDoc, aTopCell, MAXROW));
+        SCROW aRows[] = { 0, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
+        size_t n = SAL_N_ELEMENTS(aRows);
+        for (size_t i = 0; i < n; ++i, pIter->next())
+        {
+            CPPUNIT_ASSERT_MESSAGE("Cell expected, but not there.", pIter->hasCell());
+            CPPUNIT_ASSERT_EQUAL(aRows[i], pIter->getPos());
+        }
+        CPPUNIT_ASSERT_MESSAGE("Iterator should have ended.", !pIter->hasCell());
+    }
+
+    {
+        // Specify start and end rows (6 - 16)
+        ScAddress aStart = aTopCell;
+        aStart.SetRow(6);
+        pIter.reset(new ScColumnTextWidthIterator(*m_pDoc, aStart, 16));
+        SCROW aRows[] = { 6, 10, 11, 12, 13, 14, 15, 16 };
+        size_t n = SAL_N_ELEMENTS(aRows);
+        for (size_t i = 0; i < n; ++i, pIter->next())
+        {
+            CPPUNIT_ASSERT_MESSAGE("Cell expected, but not there.", pIter->hasCell());
+            CPPUNIT_ASSERT_EQUAL(aRows[i], pIter->getPos());
+        }
+        CPPUNIT_ASSERT_MESSAGE("Iterator should have ended.", !pIter->hasCell());
+    }
+
+    // Clear from row 3 to row 17. After this, we should only have cells at rows 0, 2 and 18.
+    clearRange(m_pDoc, ScRange(0, 3, 0, 0, 17, 0));
+
+    {
+        // Full range again.
+        pIter.reset(new ScColumnTextWidthIterator(*m_pDoc, aTopCell, MAXROW));
+        SCROW aRows[] = { 0, 2, 18 };
+        size_t n = SAL_N_ELEMENTS(aRows);
+        for (size_t i = 0; i < n; ++i, pIter->next())
+        {
+            CPPUNIT_ASSERT_MESSAGE("Cell expected, but not there.", pIter->hasCell());
+            CPPUNIT_ASSERT_EQUAL(aRows[i], pIter->getPos());
+        }
+        CPPUNIT_ASSERT_MESSAGE("Iterator should have ended.", !pIter->hasCell());
+    }
+
+    m_pDoc->DeleteTab(0);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(Test);
 
 }
diff --git a/sc/source/core/data/columniterator.cxx b/sc/source/core/data/columniterator.cxx
index 31298bc..24b8c05 100644
--- a/sc/source/core/data/columniterator.cxx
+++ b/sc/source/core/data/columniterator.cxx
@@ -9,6 +9,8 @@
 
 #include "columniterator.hxx"
 #include "column.hxx"
+#include "document.hxx"
+#include "table.hxx"
 
 ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScColumn& rCol, SCROW nStartRow, SCROW nEndRow) :
     mrTextWidths(rCol.maTextWidths),
@@ -17,58 +19,17 @@ ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScColumn& rCol, SCROW nStar
     miBlockCur(mrTextWidths.begin()),
     miBlockEnd(mrTextWidths.end())
 {
-    if (!ValidRow(nStartRow) || !ValidRow(nEndRow))
-        miBlockCur = miBlockEnd;
-
-    size_t nStart = static_cast<size_t>(nStartRow);
-
-    // Locate the start row position.
-    size_t nBlockStart = 0, nBlockEnd = 0;
-    for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd)
-    {
-        nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point.
-        if (nBlockStart <= nStart && nStart < nBlockEnd)
-        {
-            // Initial block is found!
-            break;
-        }
-    }
-
-    if (miBlockCur == miBlockEnd)
-        // Initial block not found for whatever reason... Bail out.
-        return;
-
-    // Locate the initial row position within this block.
-    if (miBlockCur->type == mdds::mtv::element_type_ushort)
-    {
-        // This block stores text widths for non-empty cells.
-        size_t nOffsetInBlock = nStart - nBlockStart;
-        mnCurPos = nStart;
-        getDataIterators(nOffsetInBlock);
-        checkEndRow();
-        return;
-    }
-
-    // Current block is not of ushort type.  Skip to the next block.
-    nBlockStart = nBlockEnd;
-    ++miBlockCur;
-
-    // Look for the first ushort block.
-    for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd)
-    {
-        nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point.
-        if (miBlockCur->type != mdds::mtv::element_type_ushort)
-            continue;
-
-        // Found!
-        mnCurPos = nBlockStart;
-        getDataIterators(0);
-        checkEndRow();
-        return;
-    }
+    init(nStartRow, nEndRow);
+}
 
-    // Not found.
-    OSL_ASSERT(miBlockCur == miBlockEnd);
+ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScDocument& rDoc, const ScAddress& rStartPos, SCROW nEndRow) :
+    mrTextWidths(rDoc.maTabs[rStartPos.Tab()]->aCol[rStartPos.Col()].maTextWidths),
+    mnEnd(static_cast<size_t>(nEndRow)),
+    mnCurPos(0),
+    miBlockCur(mrTextWidths.begin()),
+    miBlockEnd(mrTextWidths.end())
+{
+    init(rStartPos.Row(), nEndRow);
 }
 
 void ScColumnTextWidthIterator::next()
@@ -125,6 +86,62 @@ void ScColumnTextWidthIterator::setValue(sal_uInt16 nVal)
     *miDataCur = nVal;
 }
 
+void ScColumnTextWidthIterator::init(SCROW nStartRow, SCROW nEndRow)
+{
+    if (!ValidRow(nStartRow) || !ValidRow(nEndRow))
+        miBlockCur = miBlockEnd;
+
+    size_t nStart = static_cast<size_t>(nStartRow);
+
+    // Locate the start row position.
+    size_t nBlockStart = 0, nBlockEnd = 0;
+    for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd)
+    {
+        nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point.
+        if (nBlockStart <= nStart && nStart < nBlockEnd)
+        {
+            // Initial block is found!
+            break;
+        }
+    }
+
+    if (miBlockCur == miBlockEnd)
+        // Initial block not found for whatever reason... Bail out.
+        return;
+
+    // Locate the initial row position within this block.
+    if (miBlockCur->type == mdds::mtv::element_type_ushort)
+    {
+        // This block stores text widths for non-empty cells.
+        size_t nOffsetInBlock = nStart - nBlockStart;
+        mnCurPos = nStart;
+        getDataIterators(nOffsetInBlock);
+        checkEndRow();
+        return;
+    }
+
+    // Current block is not of ushort type.  Skip to the next block.
+    nBlockStart = nBlockEnd;
+    ++miBlockCur;
+
+    // Look for the first ushort block.
+    for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd)
+    {
+        nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point.
+        if (miBlockCur->type != mdds::mtv::element_type_ushort)
+            continue;
+
+        // Found!
+        mnCurPos = nBlockStart;
+        getDataIterators(0);
+        checkEndRow();
+        return;
+    }
+
+    // Not found.
+    OSL_ASSERT(miBlockCur == miBlockEnd);
+}
+
 void ScColumnTextWidthIterator::getDataIterators(size_t nOffsetInBlock)
 {
     OSL_ENSURE(miBlockCur != miBlockEnd, "block is at end position");
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index acce598..a73cd60 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -5695,6 +5695,15 @@ void ScDocument::SetSubTotalCellsDirty(const ScRange& rDirtyRange)
     maSubTotalCells.swap(aNewSet); // update the list.
 }
 
+sal_uInt16 ScDocument::GetTextWidth( const ScAddress& rPos ) const
+{
+    SCTAB nTab = rPos.Tab();
+    if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
+        return maTabs[nTab]->GetTextWidth(rPos.Col(), rPos.Row());
+
+    return 0;
+}
+
 void ScDocument::SetTextWidth( const ScAddress& rPos, sal_uInt16 nWidth )
 {
     SCTAB nTab = rPos.Tab();


More information about the Libreoffice-commits mailing list