[Libreoffice-commits] core.git: sc/inc sc/source

Dennis Francis dennisfrancis.in at gmail.com
Thu Jan 21 12:48:41 PST 2016


 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.in at 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 <erack at redhat.com>
    Tested-by: Eike Rathke <erack at 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;
 


More information about the Libreoffice-commits mailing list