summaryrefslogtreecommitdiff
path: root/sc/source/core/data/table3.cxx
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2014-12-01 23:56:44 +0100
committerCaolán McNamara <caolanm@redhat.com>2014-12-02 20:23:57 +0000
commitf70bfe9d6ba27944935865eed731c6fc07649a1a (patch)
treebb129c224db5d39f9eb982c72457ed4a11d27ca6 /sc/source/core/data/table3.cxx
parent63fe27221d110d1bcf49672ad938582b978af921 (diff)
fdo#86762 re-establish listeners to move cell broadcasters
... for UpdateReferenceOnSort=false (cherry picked from commit 6c2111f17089eb667bf526561d7667d17825e822) Conflicts: sc/source/core/data/table3.cxx fdo#86762 broadcast also empty cells after sort (cherry picked from commit 08793e08c7e9cefe594c49130f782725e386c463) Conflicts: sc/inc/column.hxx sc/source/core/data/column.cxx sc/source/core/data/document.cxx sc/source/core/data/table2.cxx sc/source/ui/docshell/dbdocfun.cxx fdo#86762 re-establish listeners on moved broadcasters ... also in SortReorderByColumn() similar to SortReorderByRow() (cherry picked from commit e119f3883513aeaa49f332362620e955dc8b453f) Conflicts: sc/source/core/data/table3.cxx e275a754c530d6039ed14304900dd71416f36e46 7665dcc90d70fcf3b08bef0adb9ab6aaff1cdcdf Change-Id: Id90288660e317d6e47ee01ee3b5ff9058cfa18df Reviewed-on: https://gerrit.libreoffice.org/13275 Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'sc/source/core/data/table3.cxx')
-rw-r--r--sc/source/core/data/table3.cxx245
1 files changed, 163 insertions, 82 deletions
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index e49a4dcdefbd..58621c6454a5 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -663,6 +663,30 @@ public:
typedef ReorderNotifier<sc::RefColReorderHint, sc::ColRowReorderMapType, SCCOL> ColReorderNotifier;
typedef ReorderNotifier<sc::RefRowReorderHint, sc::ColRowReorderMapType, SCROW> RowReorderNotifier;
+class StartListeningNotifier : std::unary_function<SvtListener*, void>
+{
+ sc::RefStartListeningHint maHint;
+public:
+ StartListeningNotifier() {}
+
+ void operator() ( SvtListener* p )
+ {
+ p->Notify(maHint);
+ }
+};
+
+class StopListeningNotifier : std::unary_function<SvtListener*, void>
+{
+ sc::RefStopListeningHint maHint;
+public:
+ StopListeningNotifier() {}
+
+ void operator() ( SvtListener* p )
+ {
+ p->Notify(maHint);
+ }
+};
+
class FormulaGroupPosCollector : std::unary_function<SvtListener*, void>
{
sc::RefQueryFormulaGroup& mrQuery;
@@ -692,6 +716,28 @@ void ScTable::SortReorderByColumn(
for (SCCOL nCol = nStart; nCol <= nLast; ++nCol)
aCol[nCol].SplitFormulaGroupByRelativeRef(aSortRange);
+ // Collect all listeners of cell broadcasters of sorted range.
+ std::vector<SvtListener*> aCellListeners;
+
+ if (!pArray->IsUpdateRefs())
+ {
+ // Collect listeners of cell broadcasters.
+ for (SCCOL nCol = nStart; nCol <= nLast; ++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());
+
+ // 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);
+ }
+
// table to keep track of column index to position in the index table.
std::vector<SCCOLROW> aPosTable(nCount);
for (size_t i = 0; i < nCount; ++i)
@@ -720,38 +766,38 @@ void ScTable::SortReorderByColumn(
for (SCCOL nCol = nStart; nCol <= nLast; ++nCol)
aCol[nCol].ResetFormulaCellPositions(nRow1, nRow2, bUpdateRefs);
- // Set up column reorder map (for later broadcasting of reference updates).
- sc::ColRowReorderMapType aColMap;
- const std::vector<SCCOLROW>& rOldIndices = pArray->GetOrderIndices();
- for (size_t i = 0, n = rOldIndices.size(); i < n; ++i)
- {
- SCCOL nNew = i + nStart;
- SCCOL nOld = rOldIndices[i];
- aColMap.insert(sc::ColRowReorderMapType::value_type(nOld, nNew));
- }
-
- // Collect all listeners within sorted range ahead of time.
- std::vector<SvtListener*> aListeners;
-
- // Get all area listeners that listen on one column within the range and
- // end their listening.
- ScRange aMoveRange( nStart, nRow1, nTab, nLast, nRow2, nTab);
- std::vector<sc::AreaListener> aAreaListeners = pDocument->GetBASM()->GetAllListeners(
- aMoveRange, sc::OneColumnInsideArea);
+ if (pArray->IsUpdateRefs())
{
- std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
- for (; it != itEnd; ++it)
+ // Set up column reorder map (for later broadcasting of reference updates).
+ sc::ColRowReorderMapType aColMap;
+ const std::vector<SCCOLROW>& rOldIndices = pArray->GetOrderIndices();
+ for (size_t i = 0, n = rOldIndices.size(); i < n; ++i)
{
- pDocument->EndListeningArea(it->maArea, it->mpListener);
- aListeners.push_back( it->mpListener);
+ SCCOL nNew = i + nStart;
+ SCCOL nOld = rOldIndices[i];
+ aColMap.insert(sc::ColRowReorderMapType::value_type(nOld, nNew));
}
- }
- if (pArray->IsUpdateRefs())
- {
+ // Collect all listeners within sorted range ahead of time.
+ std::vector<SvtListener*> aListeners;
+
for (SCCOL nCol = nStart; nCol <= nLast; ++nCol)
aCol[nCol].CollectListeners(aListeners, nRow1, nRow2);
+ // Get all area listeners that listen on one column within the range
+ // and end their listening.
+ ScRange aMoveRange( nStart, nRow1, nTab, nLast, nRow2, nTab);
+ std::vector<sc::AreaListener> aAreaListeners = pDocument->GetBASM()->GetAllListeners(
+ aMoveRange, sc::OneColumnInsideArea);
+ {
+ std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+ for (; it != itEnd; ++it)
+ {
+ pDocument->EndListeningArea(it->maArea, it->mpListener);
+ aListeners.push_back( it->mpListener);
+ }
+ }
+
// Remove any duplicate listener entries and notify all listeners
// afterward. We must ensure that we notify each unique listener only
// once.
@@ -759,23 +805,29 @@ void ScTable::SortReorderByColumn(
aListeners.erase(std::unique(aListeners.begin(), aListeners.end()), aListeners.end());
ColReorderNotifier aFunc(aColMap, nTab, nRow1, nRow2);
std::for_each(aListeners.begin(), aListeners.end(), aFunc);
- }
- // Re-start area listeners on the reordered columns.
- {
- std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
- for (; it != itEnd; ++it)
+ // Re-start area listeners on the reordered columns.
{
- ScRange aNewRange = it->maArea;
- sc::ColRowReorderMapType::const_iterator itCol = aColMap.find( aNewRange.aStart.Col());
- if (itCol != aColMap.end())
+ std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+ for (; it != itEnd; ++it)
{
- aNewRange.aStart.SetCol( itCol->second);
- aNewRange.aEnd.SetCol( itCol->second);
+ ScRange aNewRange = it->maArea;
+ sc::ColRowReorderMapType::const_iterator itCol = aColMap.find( aNewRange.aStart.Col());
+ if (itCol != aColMap.end())
+ {
+ aNewRange.aStart.SetCol( itCol->second);
+ aNewRange.aEnd.SetCol( itCol->second);
+ }
+ pDocument->StartListeningArea(aNewRange, it->mpListener);
}
- pDocument->StartListeningArea(aNewRange, it->mpListener);
}
}
+ else // !(pArray->IsUpdateRefs())
+ {
+ // Notify the cells' listeners to (re-)start listening.
+ StartListeningNotifier aFunc;
+ std::for_each(aCellListeners.begin(), aCellListeners.end(), aFunc);
+ }
// Re-join formulas at row boundaries now that all the references have
// been adjusted for column reordering.
@@ -803,6 +855,9 @@ void ScTable::SortReorderByRow(
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
@@ -810,6 +865,22 @@ void ScTable::SortReorderByRow(
// 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);
+
+ // 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. */
+ StopListeningNotifier aFunc;
+ std::for_each(aCellListeners.begin(), aCellListeners.end(), aFunc);
}
// Split formula groups at the sort range boundaries (if applicable).
@@ -889,15 +960,18 @@ void ScTable::SortReorderByRow(
else
rAttrStore.push_back_empty();
- // At this point each broadcaster instance is managed by 2
- // containers. We will release those in the original storage
- // below before transferring them to the document.
- sc::BroadcasterStoreType& rBCStore = aSortedCols.at(j).maBroadcasters;
- if (rCell.mpBroadcaster)
- // A const pointer would be implicitly converted to a bool type.
- rBCStore.push_back(const_cast<SvtBroadcaster*>(rCell.mpBroadcaster));
- else
- rBCStore.push_back_empty();
+ if (pArray->IsUpdateRefs())
+ {
+ // At this point each broadcaster instance is managed by 2
+ // containers. We will release those in the original storage
+ // below before transferring them to the document.
+ sc::BroadcasterStoreType& rBCStore = aSortedCols.at(j).maBroadcasters;
+ if (rCell.mpBroadcaster)
+ // A const pointer would be implicitly converted to a bool type.
+ rBCStore.push_back(const_cast<SvtBroadcaster*>(rCell.mpBroadcaster));
+ else
+ rBCStore.push_back_empty();
+ }
// The same with cell note instances ...
sc::CellNoteStoreType& rNoteStore = aSortedCols.at(j).maCellNotes;
@@ -938,6 +1012,7 @@ void ScTable::SortReorderByRow(
rSrc.transfer(nRow1, nRow2, rDest, nRow1);
}
+ if (pArray->IsUpdateRefs())
{
sc::BroadcasterStoreType& rSrc = aSortedCols[i].maBroadcasters;
sc::BroadcasterStoreType& rDest = aCol[nThisCol].maBroadcasters;
@@ -1003,39 +1078,39 @@ void ScTable::SortReorderByRow(
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;
-
- // 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);
+ if (pArray->IsUpdateRefs())
{
- std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
- for (; it != itEnd; ++it)
+ // 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)
{
- pDocument->EndListeningArea(it->maArea, it->mpListener);
- aListeners.push_back( it->mpListener);
+ SCROW nNew = i + nRow1;
+ SCROW nOld = rOldIndices[i];
+ aRowMap.insert(sc::ColRowReorderMapType::value_type(nOld, nNew));
}
- }
- if (pArray->IsUpdateRefs())
- {
+ // 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)
+ {
+ pDocument->EndListeningArea(it->maArea, it->mpListener);
+ aListeners.push_back( it->mpListener);
+ }
+ }
+
// Remove any duplicate listener entries. We must ensure that we notify
// each unique listener only once.
std::sort(aListeners.begin(), aListeners.end());
@@ -1061,7 +1136,7 @@ void ScTable::SortReorderByRow(
}
}
- // Notify the listeners.
+ // Notify the listeners to update their references.
RowReorderNotifier aFunc(aRowMap, nTab, nCol1, nCol2);
std::for_each(aListeners.begin(), aListeners.end(), aFunc);
@@ -1073,23 +1148,29 @@ void ScTable::SortReorderByRow(
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)
+ // Re-start area listeners on the reordered rows.
{
- ScRange aNewRange = it->maArea;
- sc::ColRowReorderMapType::const_iterator itRow = aRowMap.find( aNewRange.aStart.Row());
- if (itRow != aRowMap.end())
+ std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+ for (; it != itEnd; ++it)
{
- aNewRange.aStart.SetRow( itRow->second);
- aNewRange.aEnd.SetRow( itRow->second);
+ 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->mpListener);
}
- pDocument->StartListeningArea(aNewRange, 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)