summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-12-05 11:11:01 -0500
committerKohei Yoshida <kohei.yoshida@collabora.com>2014-12-05 11:14:38 -0500
commit3617d29dda61c5d5f76b45bdefd0342d5ae286dc (patch)
treedcba4566e2072de976c3d1f8f538e6b808782b90
parentdd4dca78bf9016c3ef89bb27e869011eceb77313 (diff)
Create 2 variants of SortReorderByRow.
One for IsUpdateRefs() true, the other for IsUpdateRefs() false. Change-Id: I2b18e2b8a9770fd9499dd9fc0d26397e67c1e8ae (cherry picked from commit 13d64505214c33555dfbd61dbd9a177906df4981)
-rw-r--r--sc/inc/table.hxx2
-rw-r--r--sc/source/core/data/table3.cxx318
2 files changed, 213 insertions, 107 deletions
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index c7898f1918de..10c703a3fa34 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 bff310e46db9..588464f8cda4 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
{