diff options
author | Eike Rathke <erack@redhat.com> | 2014-12-01 23:56:44 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2014-12-02 20:23:57 +0000 |
commit | f70bfe9d6ba27944935865eed731c6fc07649a1a (patch) | |
tree | bb129c224db5d39f9eb982c72457ed4a11d27ca6 /sc/source/core/data/table3.cxx | |
parent | 63fe27221d110d1bcf49672ad938582b978af921 (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.cxx | 245 |
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) |