sc/inc/document.hxx | 1 sc/inc/globstr.hrc | 4 ++ sc/inc/table.hxx | 11 +++++++ sc/source/core/data/documen3.cxx | 40 ++++++++++++++++++++++++++++ sc/source/core/data/table1.cxx | 1 sc/source/core/data/table2.cxx | 54 +++++++++++++++++++++++++++++++++++++++ sc/source/core/data/table5.cxx | 31 ++++++++++++++++++++++ sc/source/ui/src/globstr.src | 4 ++ sc/source/ui/view/cellsh.cxx | 12 ++++++++ 9 files changed, 157 insertions(+), 1 deletion(-)
New commits: commit 3536fe8f4cdbacf5702e743407f34d918b6f4d38 Author: Dennis Francis <dennisfrancis...@gmail.com> Date: Tue Nov 24 01:34:47 2015 +0530 tdf#34873 : Show autofilter row count in status bar Change-Id: I91aa637d654c1f4d828832f2e43ad21f03036ad0 Reviewed-on: https://gerrit.libreoffice.org/20134 Reviewed-by: Eike Rathke <er...@redhat.com> Tested-by: Eike Rathke <er...@redhat.com> diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index f334e3f..ce1017e 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1759,6 +1759,7 @@ public: void GetFormulaEntries( ScTypedCaseStrSet& rStrings ); bool HasAutoFilter( SCCOL nCol, SCROW nRow, SCTAB nTab ); + void GetFilterSelCount( SCCOL nCol, SCROW nRow, SCTAB nTab, SCSIZE& nSelected, SCSIZE& nTotal ); SC_DLLPUBLIC bool HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ); diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc index b51897e..9c98402 100644 --- a/sc/inc/globstr.hrc +++ b/sc/inc/globstr.hrc @@ -705,7 +705,9 @@ #define STR_FUNCTIONS_FOUND 531 -#define SC_GLOBSTR_STR_COUNT 532 /**< the count of permanently resident strings */ +#define STR_FILTER_SELCOUNT 532 + +#define SC_GLOBSTR_STR_COUNT 533 /**< the count of permanently resident strings */ #endif diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index d2672fe..d6111dd 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -117,6 +117,16 @@ class ScHint; class ScTable : private boost::noncopyable { private: + // To store an Autofilter's filtered row count + struct FilteredRowCountData { + SCROW nStartRow; + SCROW nEndRow; + SCSIZE nCount; + FilteredRowCountData(SCROW nRow1, SCROW nRow2, SCSIZE nVal) : + nStartRow(nRow1), nEndRow(nRow2), nCount(nVal) + {} + }; + typedef ::std::vector< ScRange > ScRangeVec; ScColumn aCol[MAXCOLCOUNT]; @@ -151,6 +161,7 @@ private: std::unique_ptr<ScFlatBoolRowSegments> mpHiddenRows; std::unique_ptr<ScFlatBoolColSegments> mpFilteredCols; std::unique_ptr<ScFlatBoolRowSegments> mpFilteredRows; + FilteredRowCountData maFilteredRowCount; ::std::set<SCROW> maRowPageBreaks; ::std::set<SCROW> maRowManualBreaks; diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index 48f01cf..5f632d9 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -1464,6 +1464,46 @@ bool ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, return ValidTab(nTab) && maTabs[nTab] && maTabs[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow ); } +void ScDocument::GetFilterSelCount( SCCOL nCol, SCROW nRow, SCTAB nTab, SCSIZE& nSelected, SCSIZE& nTotal ) +{ + nSelected = 0; + nTotal = 0; + if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) + { + const ScDBData* pDBData = GetDBAtCursor( nCol, nRow, nTab, ScDBDataPortion::AREA ); + if( pDBData && pDBData->HasAutoFilter() ) + { + SCTAB nAreaTab; + SCCOL nStartCol; + SCROW nStartRow; + SCCOL nEndCol; + SCROW nEndRow; + pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow ); + + if( pDBData->HasHeader() ) + ++nStartRow; + + nTotal = nEndRow - nStartRow + 1; + + ScTable::FilteredRowCountData* pFilteredRowCount = &(maTabs[nTab]->maFilteredRowCount); + // Exact range match, cache hit, early exit + if( ( pFilteredRowCount->nStartRow == nStartRow ) && ( pFilteredRowCount->nEndRow == nEndRow ) && + ( pFilteredRowCount->nCount != SCSIZE_MAX ) ) + { + nSelected = nTotal - pFilteredRowCount->nCount; + return; + } + + // Compute the count + nSelected = CountNonFilteredRows( nStartRow, nEndRow, nTab ); + // and store it in the cache + pFilteredRowCount->nStartRow = nStartRow; + pFilteredRowCount->nEndRow = nEndRow; + pFilteredRowCount->nCount = nTotal - nSelected; + } + } +} + /** * Entries for AutoFilter listbox */ diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index 2bc2705..e09018d 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -245,6 +245,7 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const OUString& rNewName, mpHiddenRows(new ScFlatBoolRowSegments), mpFilteredCols(new ScFlatBoolColSegments), mpFilteredRows(new ScFlatBoolRowSegments), + maFilteredRowCount(0, MAXROW, SCSIZE_MAX), pOutlineTable( nullptr ), pSheetEvents( nullptr ), nTableAreaX( 0 ), diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 11c0d58..23121cb 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -171,6 +171,13 @@ void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE mpFilteredRows->insertSegment(nStartRow, nSize, true); mpHiddenRows->insertSegment(nStartRow, nSize, true); + if( ( nStartRow <= maFilteredRowCount.nEndRow ) && ( maFilteredRowCount.nCount != SCSIZE_MAX ) ) + { + if( nStartRow < maFilteredRowCount.nStartRow ) + maFilteredRowCount.nStartRow += nSize; + maFilteredRowCount.nEndRow += nSize; + } + if (!maRowManualBreaks.empty()) { // Copy all breaks up to nStartRow (non-inclusive). @@ -217,6 +224,53 @@ void ScTable::DeleteRow( if (pUndoOutline) *pUndoOutline = true; + if( ( maFilteredRowCount.nCount != SCSIZE_MAX ) && ( nStartRow <= maFilteredRowCount.nEndRow ) ) + { + SCROW nEndRow = nStartRow + nSize - 1; + // rows to be deleted has some overlap with autofilter + if( nEndRow >= maFilteredRowCount.nStartRow ) + { + SCROW nStartRowInside = ( nStartRow >= maFilteredRowCount.nStartRow ) ? nStartRow : maFilteredRowCount.nStartRow; + SCROW nEndRowInside = ( nEndRow <= maFilteredRowCount.nEndRow ) ? nEndRow : maFilteredRowCount.nEndRow; + + // All rows inside the autofilter are to be deleted, so set dirty flag. + if( ( nStartRowInside == maFilteredRowCount.nStartRow ) && ( nEndRowInside == maFilteredRowCount.nEndRow ) ) + maFilteredRowCount.nCount = SCSIZE_MAX; + else + { + SCSIZE nChange = 0; + ScFlatBoolRowSegments::RangeData aData; + SCROW nRowItr = nStartRowInside; + while( nRowItr <= nEndRowInside ) + { + if( !mpFilteredRows->getRangeData( nRowItr, aData ) ) + break; + if( aData.mnRow2 > nEndRowInside ) + aData.mnRow2 = nEndRowInside; + + if( aData.mbValue ) + nChange += aData.mnRow2 - nRowItr + 1; + + nRowItr = aData.mnRow2 + 1; + } + if( nStartRowInside == maFilteredRowCount.nStartRow ) + maFilteredRowCount.nStartRow = ( nEndRowInside + 1 - nSize ); + + if( nEndRowInside == maFilteredRowCount.nEndRow ) + maFilteredRowCount.nEndRow = ( nStartRowInside - 1 ); + else + maFilteredRowCount.nEndRow -= nSize; + maFilteredRowCount.nCount -= nChange; + } + } + // No overlap but the rows to be deleted are above the autofilter area. + else + { + maFilteredRowCount.nStartRow -= nSize; + maFilteredRowCount.nEndRow -= nSize; + } + } + mpFilteredRows->removeSegment(nStartRow, nStartRow+nSize); mpHiddenRows->removeSegment(nStartRow, nStartRow+nSize); diff --git a/sc/source/core/data/table5.cxx b/sc/source/core/data/table5.cxx index 8ba078c..f353383 100644 --- a/sc/source/core/data/table5.cxx +++ b/sc/source/core/data/table5.cxx @@ -859,6 +859,37 @@ void ScTable::CopyRowFiltered(ScTable& rTable, SCROW nStartRow, SCROW nEndRow) void ScTable::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, bool bFiltered) { + // First adjust the maFilteredRowCount cache + if( ( nStartRow >= maFilteredRowCount.nStartRow ) || ( nEndRow <= maFilteredRowCount.nEndRow ) ) + { + if( ( nStartRow >= maFilteredRowCount.nStartRow ) && ( nEndRow <= maFilteredRowCount.nEndRow ) && + ( maFilteredRowCount.nCount != SCSIZE_MAX ) ) + { + SCSIZE nChange = 0; + ScFlatBoolRowSegments::RangeData aData; + SCROW nRowItr = nStartRow; + while( nRowItr <= nEndRow ) + { + if( !mpFilteredRows->getRangeData( nRowItr, aData ) ) + break; + if( aData.mnRow2 > nEndRow ) + aData.mnRow2 = nEndRow; + // rows not filtered and going to be filtered + if( bFiltered && !aData.mbValue ) + nChange += aData.mnRow2 - nRowItr + 1; + // rows filtered and not going to be filtered any more + else if( !bFiltered && aData.mbValue ) + nChange -= aData.mnRow2 - nRowItr + 1; + + nRowItr = aData.mnRow2 + 1; + } + + maFilteredRowCount.nCount += nChange; + } + else + maFilteredRowCount.nCount = SCSIZE_MAX; + } + if (bFiltered) mpFilteredRows->setTrue(nStartRow, nEndRow); else diff --git a/sc/source/ui/src/globstr.src b/sc/source/ui/src/globstr.src index 073c5f9..b1d72d3 100644 --- a/sc/source/ui/src/globstr.src +++ b/sc/source/ui/src/globstr.src @@ -589,6 +589,10 @@ Resource RID_GLOBSTR { Text [ en-US ] = "$1 rows, $2 columns selected"; }; + String STR_FILTER_SELCOUNT + { + Text [ en-US ] = "$1 of $2 records found"; + }; String STR_COLUMN { Text [ en-US ] = "Column" ; diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx index 60a92b6..f381267 100644 --- a/sc/source/ui/view/cellsh.cxx +++ b/sc/source/ui/view/cellsh.cxx @@ -723,6 +723,18 @@ void ScCellShell::GetState(SfxItemSet &rSet) aStr = aStr.replaceAll( "$2", OUString::number( nCol2 - nCol1 + 1 )); rSet.Put( SfxStringItem( nWhich, aStr ) ); } + else + { + SCSIZE nSelected, nTotal; + pDoc->GetFilterSelCount( nPosX, nPosY, nTab, nSelected, nTotal ); + if( nTotal ) + { + OUString aStr = ScGlobal::GetRscString( STR_FILTER_SELCOUNT ); + aStr = aStr.replaceAll( "$1", OUString::number( nSelected ) ); + aStr = aStr.replaceAll( "$2", OUString::number( nTotal ) ); + rSet.Put( SfxStringItem( nWhich, aStr ) ); + } + } } break; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits