diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-04-22 00:36:40 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-04-23 21:08:24 -0400 |
commit | 94cf534a89634290201141a08e19d156bb3b9a19 (patch) | |
tree | 8a8aa794f7bddbaaa0870c459263c7dae5ebdedc /sc/source | |
parent | aa3e2b7ae90c0fdad28dfd097a230e8ab4cb2565 (diff) |
Handle reordering of row hidden and filtered flags during sort.
Only when the "keep query" flag is set.
Change-Id: Ia799f62ec53a08cfd92e93c546965002c030b324
Diffstat (limited to 'sc/source')
-rw-r--r-- | sc/source/core/data/table3.cxx | 136 |
1 files changed, 112 insertions, 24 deletions
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index b1a40d0e40b4..a672303acc5c 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -57,6 +57,7 @@ #include "mtvcellfunc.hxx" #include "columnspanset.hxx" #include <stlalgorithm.hxx> +#include <fstalgorithm.hxx> #include <listenercontext.hxx> #include <sharedformula.hxx> @@ -234,8 +235,17 @@ public: Cell() : mpAttr(NULL), mpBroadcaster(NULL), mpNote(NULL), mpPattern(NULL) {} }; - typedef std::vector<Cell> RowType; - typedef std::vector<RowType*> RowsType; + struct Row + { + std::vector<Cell> maCells; + + bool mbHidden:1; + bool mbFiltered:1; + + Row( size_t nColSize ) : maCells(nColSize, Cell()), mbHidden(false), mbFiltered(false) {} + }; + + typedef std::vector<Row*> RowsType; private: boost::scoped_ptr<RowsType> mpRows; /// row-wise data table for sort by row operation. @@ -246,21 +256,24 @@ private: SCCOLROW mnLastIndex; /// index of last non-empty cell position. sal_uInt16 nUsedSorts; + bool mbKeepQuery; + public: ScSortInfoArray( sal_uInt16 nSorts, SCCOLROW nInd1, SCCOLROW nInd2 ) : - pppInfo( new ScSortInfo**[nSorts]), - nCount( nInd2 - nInd1 + 1 ), nStart( nInd1 ), - mnLastIndex(nInd2), - nUsedSorts( nSorts ) + pppInfo( new ScSortInfo**[nSorts]), + nCount( nInd2 - nInd1 + 1 ), nStart( nInd1 ), + mnLastIndex(nInd2), + nUsedSorts(nSorts), + mbKeepQuery(false) + { + for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ ) { - for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ ) - { - ScSortInfo** ppInfo = new ScSortInfo* [nCount]; - for ( SCSIZE j = 0; j < nCount; j++ ) - ppInfo[j] = new ScSortInfo; - pppInfo[nSort] = ppInfo; - } + ScSortInfo** ppInfo = new ScSortInfo* [nCount]; + for ( SCSIZE j = 0; j < nCount; j++ ) + ppInfo[j] = new ScSortInfo; + pppInfo[nSort] = ppInfo; } + } ~ScSortInfoArray() { @@ -274,9 +287,13 @@ public: delete[] pppInfo; if (mpRows) - std::for_each(mpRows->begin(), mpRows->end(), ScDeleteObjectByPtr<RowType>()); + std::for_each(mpRows->begin(), mpRows->end(), ScDeleteObjectByPtr<Row>()); } + void SetKeepQuery( bool b ) { mbKeepQuery = b; } + + bool IsKeepQuery() const { return mbKeepQuery; } + ScSortInfo* Get( sal_uInt16 nSort, SCCOLROW nInd ) { return (pppInfo[nSort])[ nInd - nStart ]; } @@ -311,7 +328,7 @@ public: mpRows.reset(new RowsType); mpRows->reserve(nRowSize); for (size_t i = 0; i < nRowSize; ++i) - mpRows->push_back(new RowType(nColSize, Cell())); + mpRows->push_back(new Row(nColSize)); return *mpRows; } @@ -322,12 +339,14 @@ public: } }; -ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 ) +ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2, bool bKeepQuery ) { sal_uInt16 nUsedSorts = 1; while ( nUsedSorts < aSortParam.GetSortKeyCount() && aSortParam.maKeyState[nUsedSorts].bDoSort ) nUsedSorts++; ScSortInfoArray* pArray = new ScSortInfoArray( nUsedSorts, nInd1, nInd2 ); + pArray->SetKeepQuery(bKeepQuery); + if ( aSortParam.bByRow ) { for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ ) @@ -355,8 +374,8 @@ ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 ) rCol.InitBlockPosition(aBlockPos); for (SCROW nRow = nInd1; nRow <= nInd2; ++nRow) { - ScSortInfoArray::RowType& rRow = *rRows[nRow-nInd1]; - ScSortInfoArray::Cell& rCell = rRow[nCol-aSortParam.nCol1]; + ScSortInfoArray::Row& rRow = *rRows[nRow-nInd1]; + ScSortInfoArray::Cell& rCell = rRow.maCells[nCol-aSortParam.nCol1]; rCell.maCell = rCol.GetCellValue(aBlockPos, nRow); rCell.mpAttr = rCol.GetCellTextAttr(aBlockPos, nRow); @@ -367,6 +386,16 @@ ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 ) rCell.mpPattern = rCol.GetPattern(nRow); } } + + if (bKeepQuery) + { + for (SCROW nRow = nInd1; nRow <= nInd2; ++nRow) + { + ScSortInfoArray::Row& rRow = *rRows[nRow-nInd1]; + rRow.mbHidden = RowHidden(nRow); + rRow.mbFiltered = RowFiltered(nRow); + } + } } else { @@ -389,6 +418,7 @@ namespace { struct SortedColumn : boost::noncopyable { + sc::CellStoreType maCells; sc::CellTextAttrStoreType maCellTextAttrs; sc::BroadcasterStoreType maBroadcasters; @@ -401,6 +431,32 @@ struct SortedColumn : boost::noncopyable maCellNotes(nTopEmptyRows) {} }; +struct SortedRowFlags +{ + typedef mdds::flat_segment_tree<SCROW,bool> FlagsType; + + FlagsType maRowsHidden; + FlagsType maRowsFiltered; + FlagsType::const_iterator miPosHidden; + FlagsType::const_iterator miPosFiltered; + + SortedRowFlags() : + maRowsHidden(0, MAXROWCOUNT, false), + maRowsFiltered(0, MAXROWCOUNT, false), + miPosHidden(maRowsHidden.begin()), + miPosFiltered(maRowsFiltered.begin()) {} + + void setRowHidden( SCROW nRow, bool b ) + { + miPosHidden = maRowsHidden.insert(miPosHidden, nRow, nRow+1, b).first; + } + + void setRowFiltered( SCROW nRow, bool b ) + { + miPosFiltered = maRowsFiltered.insert(miPosFiltered, nRow, nRow+1, b).first; + } +}; + } bool ScTable::IsSortCollatorGlobal() const @@ -461,6 +517,7 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress ) size_t nColCount = aSortParam.nCol2 - aSortParam.nCol1 + 1; boost::ptr_vector<SortedColumn> aSortedCols; // storage for copied cells. + SortedRowFlags aRowFlags; aSortedCols.reserve(nColCount); for (size_t i = 0; i < nColCount; ++i) { @@ -472,12 +529,12 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress ) for (size_t i = 0; i < pRows->size(); ++i) { - ScSortInfoArray::RowType* pRow = (*pRows)[i]; - for (size_t j = 0; j < pRow->size(); ++j) + ScSortInfoArray::Row* pRow = (*pRows)[i]; + for (size_t j = 0; j < pRow->maCells.size(); ++j) { ScAddress aCellPos(aSortParam.nCol1 + j, nRow1 + i, nTab); - ScSortInfoArray::Cell& rCell = (*pRow)[j]; + ScSortInfoArray::Cell& rCell = pRow->maCells[j]; sc::CellStoreType& rCellStore = aSortedCols.at(j).maCells; switch (rCell.maCell.meType) @@ -539,6 +596,14 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress ) aCol[aCellPos.Col()].SetPattern(aCellPos.Row(), *rCell.mpPattern, true); } + if (pArray->IsKeepQuery()) + { + // Hidden and filtered flags are first converted to segments. + SCROW nRow = nRow1 + i; + aRowFlags.setRowHidden(nRow, pRow->mbHidden); + aRowFlags.setRowFiltered(nRow, pRow->mbFiltered); + } + if (pProgress) pProgress->SetStateOnPercent(i); } @@ -583,6 +648,29 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress ) aCol[nThisCol].CellStorageModified(); } + if (pArray->IsKeepQuery()) + { + aRowFlags.maRowsHidden.build_tree(); + aRowFlags.maRowsFiltered.build_tree(); + + // Remove all flags in the range first. + SetRowHidden(nRow1, nRow2, false); + SetRowFiltered(nRow1, nRow2, false); + + 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); + } + // Attach all formula cells within sorted range, to have them start listening again. sc::StartListeningContext aStartListenCxt(*pDocument); AttachFormulaCells( @@ -906,7 +994,7 @@ void ScTable::Sort(const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* p if(pProgress) pProgress->SetState( 0, nLastRow-nRow1 ); - boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(nRow1, nLastRow)); + boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(nRow1, nLastRow, bKeepQuery)); if ( nLastRow - nRow1 > 255 ) DecoladeRow(pArray.get(), nRow1, nLastRow); @@ -931,7 +1019,7 @@ void ScTable::Sort(const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* p if(pProgress) pProgress->SetState( 0, nLastCol-nCol1 ); - boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(nCol1, nLastCol)); + boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(nCol1, nLastCol, bKeepQuery)); QuickSort(pArray.get(), nCol1, nLastCol); SortReorder(pArray.get(), pProgress); @@ -1932,7 +2020,7 @@ void ScTable::TopTenQuery( ScQueryParam& rParam ) bSortCollatorInitialized = true; InitSortCollator( aLocalSortParam ); } - ScSortInfoArray* pArray = CreateSortInfoArray( nRow1, rParam.nRow2 ); + ScSortInfoArray* pArray = CreateSortInfoArray(nRow1, rParam.nRow2, bGlobalKeepQuery); DecoladeRow( pArray, nRow1, rParam.nRow2 ); QuickSort( pArray, nRow1, rParam.nRow2 ); ScSortInfo** ppInfo = pArray->GetFirstArray(); |