summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorNiklas Nebel <nn@openoffice.org>2011-01-05 11:30:14 +0100
committerNiklas Nebel <nn@openoffice.org>2011-01-05 11:30:14 +0100
commitdc1685728a142b05bb2c7d97b6d6577f6f35ae8a (patch)
tree4a0ef1522ce6eed2bfe46f01ea6f92fb6dba9e73 /sc
parent60851227548d3576a92898b13b0e1c15cc719f44 (diff)
calc64: #i116164# performance of filters with many filtered ranges
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/drwlayer.hxx2
-rw-r--r--sc/inc/table.hxx13
-rw-r--r--sc/source/core/data/drwlayer.cxx6
-rw-r--r--sc/source/core/data/table2.cxx76
-rw-r--r--sc/source/core/data/table3.cxx69
-rw-r--r--sc/source/filter/xml/xmlrowi.cxx17
6 files changed, 161 insertions, 22 deletions
diff --git a/sc/inc/drwlayer.hxx b/sc/inc/drwlayer.hxx
index 7dd9903f82a1..eed492c6e6c2 100644
--- a/sc/inc/drwlayer.hxx
+++ b/sc/inc/drwlayer.hxx
@@ -159,7 +159,7 @@ public:
void WidthChanged( SCTAB nTab, SCCOL nCol, long nDifTwips );
void HeightChanged( SCTAB nTab, SCROW nRow, long nDifTwips );
- BOOL HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow );
+ BOOL HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow, bool bIncludeNotes = true );
void DeleteObjectsInArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1,
SCCOL nCol2,SCROW nRow2 );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 63cefe22626a..042715c1f6a2 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -86,6 +86,17 @@ class ScFlatBoolRowSegments;
class ScFlatBoolColSegments;
+struct ScShowRowsEntry
+{
+ SCROW mnRow1;
+ SCROW mnRow2;
+ bool mbShow;
+
+ ScShowRowsEntry( SCROW nR1, SCROW nR2, bool bS ) :
+ mnRow1(nR1), mnRow2(nR2), mbShow(bS) {}
+};
+
+
class ScTable
{
private:
@@ -657,7 +668,7 @@ public:
void DBShowRow(SCROW nRow, bool bShow);
void ShowRows(SCROW nRow1, SCROW nRow2, bool bShow);
- void DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow);
+ void DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow, bool bSetFlags); // if bSetFlags=false, no SetRowHidden/SetRowFiltered
void SetColFlags( SCCOL nCol, BYTE nNewFlags );
void SetRowFlags( SCROW nRow, BYTE nNewFlags );
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index 4df709768279..b4e1cc71dc3d 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -1137,7 +1137,7 @@ void ScDrawLayer::HeightChanged( SCTAB nTab, SCROW nRow, long nDifTwips )
MoveAreaTwips( nTab, aRect, Point( 0,nDifTwips ), aTopLeft );
}
-BOOL ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow )
+BOOL ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow, bool bIncludeNotes )
{
DBG_ASSERT( pDoc, "ScDrawLayer::HasObjectsInRows without document" );
if ( !pDoc )
@@ -1178,7 +1178,9 @@ BOOL ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow )
while ( pObject && !bFound )
{
aObjRect = pObject->GetSnapRect(); //! GetLogicRect ?
- if (aTestRect.IsInside(aObjRect.TopLeft()) || aTestRect.IsInside(aObjRect.BottomLeft()))
+ // #i116164# note captions are handled separately, don't have to be included for each single row height change
+ if ( (aTestRect.IsInside(aObjRect.TopLeft()) || aTestRect.IsInside(aObjRect.BottomLeft())) &&
+ (bIncludeNotes || !IsNoteCaption(pObject)) )
bFound = TRUE;
pObject = aIter.Next();
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 9bb22b68d2ad..1b2674531895 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -774,6 +774,9 @@ void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
pDestTab->pRowFlags->CopyFrom(*pRowFlags, nRow1, nRow2);
// Hidden flags.
+ // #i116164# Collect information first, then apply the changes,
+ // so RowHidden doesn't rebuild the tree for each row range.
+ std::vector<ScShowRowsEntry> aEntries;
for (SCROW i = nRow1; i <= nRow2; ++i)
{
SCROW nThisLastRow, nDestLastRow;
@@ -786,7 +789,8 @@ void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
// the last row shouldn't exceed the upper bound the caller specified.
nLastRow = nRow2;
- pDestTab->SetRowHidden(i, nLastRow, bThisHidden);
+ //pDestTab->SetRowHidden(i, nLastRow, bThisHidden);
+ aEntries.push_back(ScShowRowsEntry(i, nLastRow, bThisHidden));
bool bThisHiddenChange = (bThisHidden != bDestHidden);
if (bThisHiddenChange && pCharts)
@@ -802,6 +806,19 @@ void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
i = nLastRow;
}
+ std::vector<ScShowRowsEntry>::const_iterator aEnd = aEntries.end();
+ std::vector<ScShowRowsEntry>::const_iterator aIter = aEntries.begin();
+ if ( aIter != aEnd )
+ {
+ pDestTab->mpHiddenRows->setInsertFromBack(true); // important for undo document
+ while (aIter != aEnd)
+ {
+ pDestTab->SetRowHidden(aIter->mnRow1, aIter->mnRow2, !aIter->mbShow);
+ ++aIter;
+ }
+ pDestTab->mpHiddenRows->setInsertFromBack(false);
+ }
+
// Filtered flags.
for (SCROW i = nRow1; i <= nRow2; ++i)
{
@@ -2625,10 +2642,10 @@ void ScTable::DBShowRow(SCROW nRow, bool bShow)
}
-void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
+void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow, bool bSetFlags)
{
+ // #i116164# IncRecalcLevel/DecRecalcLevel is in ScTable::Query
SCROW nStartRow = nRow1;
- IncRecalcLevel();
InitializeNoteCaptions();
while (nStartRow <= nRow2)
{
@@ -2638,7 +2655,7 @@ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
nEndRow = nRow2;
BOOL bChanged = ( bWasVis != bShow );
- if ( bChanged )
+ if ( bChanged && bSetFlags )
{
ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
if (pDrawLayer)
@@ -2651,8 +2668,13 @@ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
}
}
- SetRowHidden(nStartRow, nEndRow, !bShow);
- SetRowFiltered(nStartRow, nEndRow, !bShow);
+ // #i116164# Directly modify the flags only if there are drawing objects within the area.
+ // Otherwise, all modifications are made together in ScTable::Query, so the tree isn't constantly rebuilt.
+ if ( bSetFlags )
+ {
+ SetRowHidden(nStartRow, nEndRow, !bShow);
+ SetRowFiltered(nStartRow, nEndRow, !bShow);
+ }
if ( bChanged )
{
@@ -2669,8 +2691,6 @@ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
// to be done here.
if (pOutlineTable)
UpdateOutlineRow( nRow1, nRow2, bShow );
-
- DecRecalcLevel();
}
@@ -2679,6 +2699,14 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
SCROW nStartRow = nRow1;
IncRecalcLevel();
InitializeNoteCaptions();
+
+ // #i116164# if there are no drawing objects within the row range, a single HeightChanged call is enough
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, nRow1, nRow2, false );
+ long nOldHeight = 0;
+ if ( pDrawLayer && !bHasObjects )
+ nOldHeight = static_cast<long>(GetRowHeight(nRow1, nRow2));
+
while (nStartRow <= nRow2)
{
SCROW nEndRow = -1;
@@ -2687,7 +2715,7 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
nEndRow = nRow2;
BOOL bChanged = ( bWasVis != bShow );
- if ( bChanged )
+ if ( bChanged && bHasObjects )
{
ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
if (pDrawLayer)
@@ -2700,9 +2728,14 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
}
}
- SetRowHidden(nStartRow, nEndRow, !bShow);
- if (bShow)
- SetRowFiltered(nStartRow, nEndRow, false);
+ // #i116164# Directly modify the flags only if there are drawing objects within the area.
+ // Otherwise, all rows are modified together after the loop, so the tree isn't constantly rebuilt.
+ if ( bHasObjects )
+ {
+ SetRowHidden(nStartRow, nEndRow, !bShow);
+ if (bShow)
+ SetRowFiltered(nStartRow, nEndRow, false);
+ }
if ( bChanged )
{
@@ -2715,6 +2748,25 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
nStartRow = nEndRow + 1;
}
+
+ if ( !bHasObjects )
+ {
+ // #i116164# set the flags for the whole range at once
+ SetRowHidden(nRow1, nRow2, !bShow);
+ if (bShow)
+ SetRowFiltered(nRow1, nRow2, false);
+
+ if ( pDrawLayer )
+ {
+ // if there are no objects in the range, a single HeightChanged call is enough
+ long nNewHeight = 0;
+ if ( bShow )
+ nNewHeight = static_cast<long>(GetRowHeight(nRow1, nRow2));
+ if ( nNewHeight != nOldHeight )
+ pDrawLayer->HeightChanged( nTab, nRow1, nNewHeight - nOldHeight );
+ }
+ }
+
DecRecalcLevel();
}
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index bd6a2c92c442..8828d8ab2449 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -59,6 +59,8 @@
#include "cellform.hxx"
#include "postit.hxx"
#include "queryparam.hxx"
+#include "segmenttree.hxx"
+#include "drwlayer.hxx"
#include <vector>
@@ -1489,6 +1491,14 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
}
+ if (aParam.bInplace)
+ IncRecalcLevel(); // #i116164# once for all entries
+
+ // #i116164# If there are no drawing objects within the area, call SetRowHidden/SetRowFiltered for all rows at the end
+ std::vector<ScShowRowsEntry> aEntries;
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, aParam.nRow1 + nHeader, aParam.nRow2, false );
+
for (SCROW j=aParam.nRow1 + nHeader; j<=aParam.nRow2; j++)
{
BOOL bResult; // Filterergebnis
@@ -1544,7 +1554,11 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
else
{
if (bStarted)
- DBShowRows(nOldStart,nOldEnd, bOldResult);
+ {
+ DBShowRows(nOldStart,nOldEnd, bOldResult, bHasObjects);
+ if (!bHasObjects)
+ aEntries.push_back(ScShowRowsEntry(nOldStart, nOldEnd, bOldResult));
+ }
nOldStart = nOldEnd = j;
bOldResult = bResult;
}
@@ -1563,7 +1577,58 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
}
if (aParam.bInplace && bStarted)
- DBShowRows(nOldStart,nOldEnd, bOldResult);
+ {
+ DBShowRows(nOldStart,nOldEnd, bOldResult, bHasObjects);
+ if (!bHasObjects)
+ aEntries.push_back(ScShowRowsEntry(nOldStart, nOldEnd, bOldResult));
+ }
+
+ // #i116164# execute the collected SetRowHidden/SetRowFiltered calls
+ if (!bHasObjects)
+ {
+ std::vector<ScShowRowsEntry>::const_iterator aEnd = aEntries.end();
+ std::vector<ScShowRowsEntry>::const_iterator aIter = aEntries.begin();
+ if ( aIter != aEnd )
+ {
+ // do only one HeightChanged call with the final difference in heights
+ long nOldHeight = 0;
+ if ( pDrawLayer )
+ nOldHeight = static_cast<long>(GetRowHeight(aParam.nRow1 + nHeader, aParam.nRow2));
+
+ // clear the range first instead of many changes in the middle of the filled array
+ SetRowHidden(aParam.nRow1 + nHeader, aParam.nRow2, false);
+ SetRowFiltered(aParam.nRow1 + nHeader, aParam.nRow2, false);
+
+ // insert from back, in case the filter range is large
+ mpHiddenRows->setInsertFromBack(true);
+ mpFilteredRows->setInsertFromBack(true);
+
+ while (aIter != aEnd)
+ {
+ if (!aIter->mbShow)
+ {
+ SCROW nStartRow = aIter->mnRow1;
+ SCROW nEndRow = aIter->mnRow2;
+ SetRowHidden(nStartRow, nEndRow, true);
+ SetRowFiltered(nStartRow, nEndRow, true);
+ }
+ ++aIter;
+ }
+
+ mpHiddenRows->setInsertFromBack(false);
+ mpFilteredRows->setInsertFromBack(false);
+
+ if ( pDrawLayer )
+ {
+ // if there are no objects in the filtered range, a single HeightChanged call is enough
+ long nNewHeight = static_cast<long>(GetRowHeight(aParam.nRow1 + nHeader, aParam.nRow2));
+ pDrawLayer->HeightChanged( nTab, aParam.nRow1 + nHeader, nNewHeight - nOldHeight );
+ }
+ }
+ }
+
+ if (aParam.bInplace)
+ DecRecalcLevel();
delete[] pSpecial;
diff --git a/sc/source/filter/xml/xmlrowi.cxx b/sc/source/filter/xml/xmlrowi.cxx
index 341445431cc8..a2ce08890c30 100644
--- a/sc/source/filter/xml/xmlrowi.cxx
+++ b/sc/source/filter/xml/xmlrowi.cxx
@@ -171,6 +171,7 @@ void ScXMLTableRowContext::EndElement()
sal_Int32 nSheet = rXMLImport.GetTables().GetCurrentSheet();
sal_Int32 nCurrentRow(rXMLImport.GetTables().GetCurrentRow());
uno::Reference<sheet::XSpreadsheet> xSheet(rXMLImport.GetTables().GetCurrentXSheet());
+ ScDocument* pDoc = rXMLImport.GetDocument();
if(xSheet.is())
{
sal_Int32 nFirstRow(nCurrentRow - nRepeatedRows + 1);
@@ -218,10 +219,18 @@ void ScXMLTableRowContext::EndElement()
bVisible = sal_False;
bFiltered = sal_True;
}
- if (!bVisible)
- xRowProperties->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ISVISIBLE)), uno::makeAny(bVisible));
- if (bFiltered)
- xRowProperties->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ISFILTERED)), uno::makeAny(bFiltered));
+
+ // #i116164# call SetRowHidden/SetRowFiltered directly, so the tree doesn't have to be rebuilt
+ // to compare with existing hidden flags.
+ if (!bVisible && pDoc)
+ pDoc->SetRowHidden((SCROW)nFirstRow, (SCROW)nCurrentRow, (SCTAB)nSheet, true);
+ if (bFiltered && pDoc)
+ pDoc->SetRowFiltered((SCROW)nFirstRow, (SCROW)nCurrentRow, (SCTAB)nSheet, true);
+
+ //if (!bVisible)
+ // xRowProperties->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ISVISIBLE)), uno::makeAny(bVisible));
+ //if (bFiltered)
+ // xRowProperties->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ISFILTERED)), uno::makeAny(bFiltered));
}
}
}