[Libreoffice-commits] core.git: Branch 'libreoffice-4-4' - sc/inc sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Fri Dec 5 08:15:28 PST 2014


 sc/inc/table.hxx               |    2 
 sc/source/core/data/table3.cxx |  318 +++++++++++++++++++++++++++--------------
 2 files changed, 213 insertions(+), 107 deletions(-)

New commits:
commit 3617d29dda61c5d5f76b45bdefd0342d5ae286dc
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Dec 5 11:11:01 2014 -0500

    Create 2 variants of SortReorderByRow.
    
    One for IsUpdateRefs() true, the other for IsUpdateRefs() false.
    
    Change-Id: I2b18e2b8a9770fd9499dd9fc0d26397e67c1e8ae
    (cherry picked from commit 13d64505214c33555dfbd61dbd9a177906df4981)

diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index c7898f1..10c703a 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -1053,7 +1053,9 @@ private:
         bool bKeepQuery, bool bUpdateRefs );
     void        QuickSort( ScSortInfoArray*, SCsCOLROW nLo, SCsCOLROW nHi);
     void SortReorderByColumn( ScSortInfoArray* pArray, SCROW nRow1, SCROW nRow2, bool bPattern, ScProgress* pProgress );
+
     void SortReorderByRow( ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress );
+    void SortReorderByRowRefUpdate( ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress );
 
     bool        CreateExcelQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam);
     bool        CreateStarQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam);
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index bff310e..588464f 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -714,7 +714,6 @@ void fillSortedColumnArray(
     ScSortInfoArray* pArray, SCTAB nTab, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress )
 {
     SCROW nRow1 = pArray->GetStart();
-    SCROW nRow2 = pArray->GetLast();
     ScSortInfoArray::RowsType* pRows = pArray->GetDataRows();
 
     size_t nColCount = nCol2 - nCol1 + 1;
@@ -970,38 +969,39 @@ void ScTable::SortReorderByColumn(
 void ScTable::SortReorderByRow(
     ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress )
 {
+    assert(!pArray->IsUpdateRefs());
+
     if (nCol2 < nCol1)
         return;
 
     SCROW nRow1 = pArray->GetStart();
     SCROW nRow2 = pArray->GetLast();
-    ScSortInfoArray::RowsType* pRows = pArray->GetDataRows();
-    assert(pRows); // In sort-by-row mode we must have data rows already populated.
 
     // Collect all listeners of cell broadcasters of sorted range.
     std::vector<SvtListener*> aCellListeners;
 
-    if (!pArray->IsUpdateRefs())
+    // When the update ref mode is disabled, we need to detach all formula
+    // cells in the sorted range before reordering, and re-start them
+    // afterward.
     {
-        // When the update ref mode is disabled, we need to detach all formula
-        // cells in the sorted range before reordering, and re-start them
-        // afterward.
         sc::EndListeningContext aCxt(*pDocument);
         DetachFormulaCells(aCxt, nCol1, nRow1, nCol2, nRow2);
+    }
 
-        // Collect listeners of cell broadcasters.
-        for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
-            aCol[nCol].CollectListeners(aCellListeners, nRow1, nRow2);
+    // Collect listeners of cell broadcasters.
+    for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+        aCol[nCol].CollectListeners(aCellListeners, nRow1, nRow2);
 
-        // Remove any duplicate listener entries.  We must ensure that we notify
-        // each unique listener only once.
-        std::sort(aCellListeners.begin(), aCellListeners.end());
-        aCellListeners.erase(std::unique(aCellListeners.begin(), aCellListeners.end()), aCellListeners.end());
+    // Remove any duplicate listener entries.  We must ensure that we notify
+    // each unique listener only once.
+    std::sort(aCellListeners.begin(), aCellListeners.end());
+    aCellListeners.erase(std::unique(aCellListeners.begin(), aCellListeners.end()), aCellListeners.end());
 
-        // Notify the cells' listeners to stop listening.
-        /* TODO: for performance this could be enhanced to stop and later
-         * restart only listening to within the reordered range and keep
-         * listening to everything outside untouched. */
+    // Notify the cells' listeners to stop listening.
+    /* TODO: for performance this could be enhanced to stop and later
+     * restart only listening to within the reordered range and keep
+     * listening to everything outside untouched. */
+    {
         StopListeningNotifier aFunc;
         std::for_each(aCellListeners.begin(), aCellListeners.end(), aFunc);
     }
@@ -1036,18 +1036,6 @@ void ScTable::SortReorderByRow(
             rSrc.transfer(nRow1, nRow2, rDest, nRow1);
         }
 
-        if (pArray->IsUpdateRefs())
-        {
-            sc::BroadcasterStoreType& rSrc = aSortedCols[i].maBroadcasters;
-            sc::BroadcasterStoreType& rDest = aCol[nThisCol].maBroadcasters;
-
-            // Release current broadcasters first, to prevent them from getting deleted.
-            rDest.release_range(nRow1, nRow2);
-
-            // Transfer sorted broadcaster segment to the document.
-            rSrc.transfer(nRow1, nRow2, rDest, nRow1);
-        }
-
         {
             sc::CellNoteStoreType& rSrc = aSortedCols[i].maCellNotes;
             sc::CellNoteStoreType& rDest = aCol[nThisCol].maCellNotes;
@@ -1104,109 +1092,219 @@ void ScTable::SortReorderByRow(
             SetRowFiltered(it->mnRow1, it->mnRow2, true);
     }
 
-    if (pArray->IsUpdateRefs())
+    // Notify the cells' listeners to (re-)start listening.
     {
-        // Set up row reorder map (for later broadcasting of reference updates).
-        sc::ColRowReorderMapType aRowMap;
-        const std::vector<SCCOLROW>& rOldIndices = pArray->GetOrderIndices();
-        for (size_t i = 0, n = rOldIndices.size(); i < n; ++i)
+        StartListeningNotifier aFunc;
+        std::for_each(aCellListeners.begin(), aCellListeners.end(), aFunc);
+    }
+
+    // Re-group columns in the sorted range too.
+    for (SCCOL i = nCol1; i <= nCol2; ++i)
+        aCol[i].RegroupFormulaCells();
+
+    {
+        sc::StartListeningContext aCxt(*pDocument);
+        AttachFormulaCells(aCxt, nCol1, nRow1, nCol2, nRow2);
+    }
+}
+
+void ScTable::SortReorderByRowRefUpdate(
+    ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress )
+{
+    assert(pArray->IsUpdateRefs());
+
+    if (nCol2 < nCol1)
+        return;
+
+    SCROW nRow1 = pArray->GetStart();
+    SCROW nRow2 = pArray->GetLast();
+
+    // Collect all listeners of cell broadcasters of sorted range.
+    std::vector<SvtListener*> aCellListeners;
+
+    // Split formula groups at the sort range boundaries (if applicable).
+    std::vector<SCROW> aRowBounds;
+    aRowBounds.reserve(2);
+    aRowBounds.push_back(nRow1);
+    aRowBounds.push_back(nRow2+1);
+    for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+        SplitFormulaGroups(nCol, aRowBounds);
+
+    // Cells in the data rows only reference values in the document. Make
+    // a copy before updating the document.
+    boost::ptr_vector<SortedColumn> aSortedCols; // storage for copied cells.
+    SortedRowFlags aRowFlags;
+    fillSortedColumnArray(aSortedCols, aRowFlags, pArray, nTab, nCol1, nCol2, pProgress);
+
+    for (size_t i = 0, n = aSortedCols.size(); i < n; ++i)
+    {
+        SCCOL nThisCol = i + nCol1;
+
         {
-            SCROW nNew = i + nRow1;
-            SCROW nOld = rOldIndices[i];
-            aRowMap.insert(sc::ColRowReorderMapType::value_type(nOld, nNew));
+            sc::CellStoreType& rDest = aCol[nThisCol].maCells;
+            sc::CellStoreType& rSrc = aSortedCols[i].maCells;
+            rSrc.transfer(nRow1, nRow2, rDest, nRow1);
         }
 
-        // Collect all listeners within sorted range ahead of time.
-        std::vector<SvtListener*> aListeners;
+        {
+            sc::CellTextAttrStoreType& rDest = aCol[nThisCol].maCellTextAttrs;
+            sc::CellTextAttrStoreType& rSrc = aSortedCols[i].maCellTextAttrs;
+            rSrc.transfer(nRow1, nRow2, rDest, nRow1);
+        }
 
-        // Collect listeners of cell broadcasters.
-        for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
-            aCol[nCol].CollectListeners(aListeners, nRow1, nRow2);
+        sc::BroadcasterStoreType& rSrc = aSortedCols[i].maBroadcasters;
+        sc::BroadcasterStoreType& rDest = aCol[nThisCol].maBroadcasters;
+
+        // Release current broadcasters first, to prevent them from getting deleted.
+        rDest.release_range(nRow1, nRow2);
+
+        // Transfer sorted broadcaster segment to the document.
+        rSrc.transfer(nRow1, nRow2, rDest, nRow1);
 
-        // Get all area listeners that listen on one row within the range and end
-        // their listening.
-        ScRange aMoveRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab);
-        std::vector<sc::AreaListener> aAreaListeners = pDocument->GetBASM()->GetAllListeners(
-                aMoveRange, sc::OneRowInsideArea);
         {
-            std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+            sc::CellNoteStoreType& rSrc = aSortedCols[i].maCellNotes;
+            sc::CellNoteStoreType& rDest = aCol[nThisCol].maCellNotes;
+
+            // Do the same as broadcaster storage transfer (to prevent double deletion).
+            rDest.release_range(nRow1, nRow2);
+            rSrc.transfer(nRow1, nRow2, rDest, nRow1);
+            aCol[nThisCol].UpdateNoteCaptions(nRow1, nRow2);
+        }
+
+        {
+            // Get all row spans where the pattern is not NULL.
+            std::vector<PatternSpan> aSpans =
+                sc::toSpanArrayWithValue<SCROW,const ScPatternAttr*,PatternSpan>(
+                    aSortedCols[i].maPatterns);
+
+            std::vector<PatternSpan>::iterator it = aSpans.begin(), itEnd = aSpans.end();
             for (; it != itEnd; ++it)
             {
-                pDocument->EndListeningArea(it->maArea, it->mbGroupListening, it->mpListener);
-                aListeners.push_back( it->mpListener);
+                assert(it->mpPattern); // should never be NULL.
+                pDocument->GetPool()->Put(*it->mpPattern);
+            }
+
+            for (it = aSpans.begin(); it != itEnd; ++it)
+            {
+                aCol[nThisCol].SetPatternArea(it->mnRow1, it->mnRow2, *it->mpPattern, true);
+                pDocument->GetPool()->Remove(*it->mpPattern);
             }
         }
 
-        // Remove any duplicate listener entries.  We must ensure that we notify
-        // each unique listener only once.
-        std::sort(aListeners.begin(), aListeners.end());
-        aListeners.erase(std::unique(aListeners.begin(), aListeners.end()), aListeners.end());
+        aCol[nThisCol].CellStorageModified();
+    }
+
+    if (pArray->IsKeepQuery())
+    {
+        aRowFlags.maRowsHidden.build_tree();
+        aRowFlags.maRowsFiltered.build_tree();
 
-        // Collect positions of all shared formula cells outside the sorted range,
-        // and make them unshared before notifying them.
-        sc::RefQueryFormulaGroup aFormulaGroupPos;
-        aFormulaGroupPos.setSkipRange(ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab));
+        // Remove all flags in the range first.
+        SetRowHidden(nRow1, nRow2, false);
+        SetRowFiltered(nRow1, nRow2, false);
 
-        std::for_each(aListeners.begin(), aListeners.end(), FormulaGroupPosCollector(aFormulaGroupPos));
-        const sc::RefQueryFormulaGroup::TabsType& rGroupTabs = aFormulaGroupPos.getAllPositions();
-        sc::RefQueryFormulaGroup::TabsType::const_iterator itGroupTab = rGroupTabs.begin(), itGroupTabEnd = rGroupTabs.end();
-        for (; itGroupTab != itGroupTabEnd; ++itGroupTab)
+        std::vector<sc::RowSpan> aSpans =
+            sc::toSpanArray<SCROW,sc::RowSpan>(aRowFlags.maRowsHidden, nRow1);
+
+        std::vector<sc::RowSpan>::const_iterator it = aSpans.begin(), itEnd = aSpans.end();
+        for (; it != itEnd; ++it)
+            SetRowHidden(it->mnRow1, it->mnRow2, true);
+
+        aSpans = sc::toSpanArray<SCROW,sc::RowSpan>(aRowFlags.maRowsFiltered, nRow1);
+
+        it = aSpans.begin(), itEnd = aSpans.end();
+        for (; it != itEnd; ++it)
+            SetRowFiltered(it->mnRow1, it->mnRow2, true);
+    }
+
+    // Set up row reorder map (for later broadcasting of reference updates).
+    sc::ColRowReorderMapType aRowMap;
+    const std::vector<SCCOLROW>& rOldIndices = pArray->GetOrderIndices();
+    for (size_t i = 0, n = rOldIndices.size(); i < n; ++i)
+    {
+        SCROW nNew = i + nRow1;
+        SCROW nOld = rOldIndices[i];
+        aRowMap.insert(sc::ColRowReorderMapType::value_type(nOld, nNew));
+    }
+
+    // Collect all listeners within sorted range ahead of time.
+    std::vector<SvtListener*> aListeners;
+
+    // Collect listeners of cell broadcasters.
+    for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+        aCol[nCol].CollectListeners(aListeners, nRow1, nRow2);
+
+    // Get all area listeners that listen on one row within the range and end
+    // their listening.
+    ScRange aMoveRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab);
+    std::vector<sc::AreaListener> aAreaListeners = pDocument->GetBASM()->GetAllListeners(
+            aMoveRange, sc::OneRowInsideArea);
+    {
+        std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+        for (; it != itEnd; ++it)
         {
-            const sc::RefQueryFormulaGroup::ColsType& rCols = itGroupTab->second;
-            sc::RefQueryFormulaGroup::ColsType::const_iterator itCol = rCols.begin(), itColEnd = rCols.end();
-            for (; itCol != itColEnd; ++itCol)
-            {
-                const sc::RefQueryFormulaGroup::ColType& rCol = itCol->second;
-                std::vector<SCROW> aBounds(rCol);
-                pDocument->UnshareFormulaCells(itGroupTab->first, itCol->first, aBounds);
-            }
+            pDocument->EndListeningArea(it->maArea, it->mbGroupListening, it->mpListener);
+            aListeners.push_back( it->mpListener);
         }
+    }
 
-        // Notify the listeners to update their references.
-        RowReorderNotifier aFunc(aRowMap, nTab, nCol1, nCol2);
-        std::for_each(aListeners.begin(), aListeners.end(), aFunc);
+    // Remove any duplicate listener entries.  We must ensure that we notify
+    // each unique listener only once.
+    std::sort(aListeners.begin(), aListeners.end());
+    aListeners.erase(std::unique(aListeners.begin(), aListeners.end()), aListeners.end());
+
+    // Collect positions of all shared formula cells outside the sorted range,
+    // and make them unshared before notifying them.
+    sc::RefQueryFormulaGroup aFormulaGroupPos;
+    aFormulaGroupPos.setSkipRange(ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab));
 
-        // Re-group formulas in affected columns.
-        for (itGroupTab = rGroupTabs.begin(); itGroupTab != itGroupTabEnd; ++itGroupTab)
+    std::for_each(aListeners.begin(), aListeners.end(), FormulaGroupPosCollector(aFormulaGroupPos));
+    const sc::RefQueryFormulaGroup::TabsType& rGroupTabs = aFormulaGroupPos.getAllPositions();
+    sc::RefQueryFormulaGroup::TabsType::const_iterator itGroupTab = rGroupTabs.begin(), itGroupTabEnd = rGroupTabs.end();
+    for (; itGroupTab != itGroupTabEnd; ++itGroupTab)
+    {
+        const sc::RefQueryFormulaGroup::ColsType& rCols = itGroupTab->second;
+        sc::RefQueryFormulaGroup::ColsType::const_iterator itCol = rCols.begin(), itColEnd = rCols.end();
+        for (; itCol != itColEnd; ++itCol)
         {
-            const sc::RefQueryFormulaGroup::ColsType& rCols = itGroupTab->second;
-            sc::RefQueryFormulaGroup::ColsType::const_iterator itCol = rCols.begin(), itColEnd = rCols.end();
-            for (; itCol != itColEnd; ++itCol)
-                pDocument->RegroupFormulaCells(itGroupTab->first, itCol->first);
+            const sc::RefQueryFormulaGroup::ColType& rCol = itCol->second;
+            std::vector<SCROW> aBounds(rCol);
+            pDocument->UnshareFormulaCells(itGroupTab->first, itCol->first, aBounds);
         }
+    }
+
+    // Notify the listeners to update their references.
+    RowReorderNotifier aFunc(aRowMap, nTab, nCol1, nCol2);
+    std::for_each(aListeners.begin(), aListeners.end(), aFunc);
 
-        // Re-start area listeners on the reordered rows.
+    // Re-group formulas in affected columns.
+    for (itGroupTab = rGroupTabs.begin(); itGroupTab != itGroupTabEnd; ++itGroupTab)
+    {
+        const sc::RefQueryFormulaGroup::ColsType& rCols = itGroupTab->second;
+        sc::RefQueryFormulaGroup::ColsType::const_iterator itCol = rCols.begin(), itColEnd = rCols.end();
+        for (; itCol != itColEnd; ++itCol)
+            pDocument->RegroupFormulaCells(itGroupTab->first, itCol->first);
+    }
+
+    // Re-start area listeners on the reordered rows.
+    {
+        std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+        for (; it != itEnd; ++it)
         {
-            std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
-            for (; it != itEnd; ++it)
+            ScRange aNewRange = it->maArea;
+            sc::ColRowReorderMapType::const_iterator itRow = aRowMap.find( aNewRange.aStart.Row());
+            if (itRow != aRowMap.end())
             {
-                ScRange aNewRange = it->maArea;
-                sc::ColRowReorderMapType::const_iterator itRow = aRowMap.find( aNewRange.aStart.Row());
-                if (itRow != aRowMap.end())
-                {
-                    aNewRange.aStart.SetRow( itRow->second);
-                    aNewRange.aEnd.SetRow( itRow->second);
-                }
-                pDocument->StartListeningArea(aNewRange, it->mbGroupListening, it->mpListener);
+                aNewRange.aStart.SetRow( itRow->second);
+                aNewRange.aEnd.SetRow( itRow->second);
             }
+            pDocument->StartListeningArea(aNewRange, it->mbGroupListening, it->mpListener);
         }
     }
-    else    // !(pArray->IsUpdateRefs())
-    {
-        // Notify the cells' listeners to (re-)start listening.
-        StartListeningNotifier aFunc;
-        std::for_each(aCellListeners.begin(), aCellListeners.end(), aFunc);
-    }
 
     // Re-group columns in the sorted range too.
     for (SCCOL i = nCol1; i <= nCol2; ++i)
         aCol[i].RegroupFormulaCells();
-
-    if (!pArray->IsUpdateRefs())
-    {
-        sc::StartListeningContext aCxt(*pDocument);
-        AttachFormulaCells(aCxt, nCol1, nRow1, nCol2, nRow2);
-    }
 }
 
 short ScTable::CompareCell(
@@ -1461,7 +1559,10 @@ void ScTable::Sort(
                 DecoladeRow(pArray.get(), nRow1, nLastRow);
 
             QuickSort(pArray.get(), nRow1, nLastRow);
-            SortReorderByRow(pArray.get(), aSortParam.nCol1, aSortParam.nCol2, pProgress);
+            if (pArray->IsUpdateRefs())
+                SortReorderByRowRefUpdate(pArray.get(), aSortParam.nCol1, aSortParam.nCol2, pProgress);
+            else
+                SortReorderByRow(pArray.get(), aSortParam.nCol1, aSortParam.nCol2, pProgress);
 
             if (pUndo)
             {
@@ -1512,9 +1613,12 @@ void ScTable::Reorder( const sc::ReorderParam& rParam, ScProgress* pProgress )
     {
         // Re-play sorting from the known sort indices.
         pArray->ReorderByRow(rParam.maOrderIndices);
-
-        SortReorderByRow(
-            pArray.get(), rParam.maSortRange.aStart.Col(), rParam.maSortRange.aEnd.Col(), pProgress);
+        if (pArray->IsUpdateRefs())
+            SortReorderByRowRefUpdate(
+                pArray.get(), rParam.maSortRange.aStart.Col(), rParam.maSortRange.aEnd.Col(), pProgress);
+        else
+            SortReorderByRow(
+                pArray.get(), rParam.maSortRange.aStart.Col(), rParam.maSortRange.aEnd.Col(), pProgress);
     }
     else
     {


More information about the Libreoffice-commits mailing list