sc/inc/conditio.hxx                     |   20 ++++++++++++++++++++
 sc/qa/unit/subsequent_filters_test3.cxx |    5 +++++
 sc/source/core/data/conditio.cxx        |   15 ++++++++++-----
 3 files changed, 35 insertions(+), 5 deletions(-)

New commits:
commit cea900fe9864bbc5314415cb369fc7b6111cd050
Author:     Szymon Kłos <szymon.k...@collabora.com>
AuthorDate: Wed Sep 13 14:57:23 2023 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Mon Sep 18 17:45:47 2023 +0200

    Schedule conditional formating repaint after filtering is completed
    
    When we have sheet with lots of data with applied conditional formatting
    and that data is used with autofilter feature - filtering is very slow.
    That was caused by repaints synchronously called on every row show/hide.
    
    ScConditionalFormat::DoRepaint()   called by ScFormulaListener callback
    ...
    ScDocument::Broadcast
    ScColumn::BroadcastRows
    ScTable::SetRowHidden
    ScTable::DBShowRows
    
    This patch schedules repaint in the Idle so we do that after all changes
    are already applied.
    
    Change-Id: If0876ada0f336a41b69560db6a581d6e24d7ac16
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157016
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sc/inc/conditio.hxx b/sc/inc/conditio.hxx
index 47f5fdb3addb..8e5af1dd3c3c 100644
--- a/sc/inc/conditio.hxx
+++ b/sc/inc/conditio.hxx
@@ -40,6 +40,7 @@
 #include <memory>
 #include <set>
 
+class RepaintInIdle;
 class ScFormulaCell;
 class ScTokenArray;
 struct ScRefCellValue;
@@ -442,6 +443,8 @@ private:
     };
 
     mutable std::unique_ptr<ScConditionEntryCache> mpCache;
+
+    std::unique_ptr<RepaintInIdle> mpRepaintTask;
 };
 
 //  single condition entry for conditional formatting
@@ -605,6 +608,23 @@ public:
     void CalcAll();
 };
 
+class RepaintInIdle final : public Idle
+{
+    ScConditionalFormat* mpCondFormat;
+
+public:
+    RepaintInIdle(ScConditionalFormat* pCondFormat)
+    : Idle("Contitional Format Repaint Idle")
+    , mpCondFormat(pCondFormat)
+    {}
+
+    void Invoke() override
+    {
+        if (mpCondFormat)
+            mpCondFormat->DoRepaint();
+    }
+};
+
 struct CompareScConditionalFormat
 {
     using is_transparent = void;
diff --git a/sc/qa/unit/subsequent_filters_test3.cxx 
b/sc/qa/unit/subsequent_filters_test3.cxx
index ff19d3d55c3c..3a46b9926bf6 100644
--- a/sc/qa/unit/subsequent_filters_test3.cxx
+++ b/sc/qa/unit/subsequent_filters_test3.cxx
@@ -19,6 +19,7 @@
 #include <svx/xflclit.hxx>
 #include <svx/xflgrit.hxx>
 #include <svx/xflhtit.hxx>
+#include <vcl/scheduler.hxx>
 #include <editeng/borderline.hxx>
 #include <editeng/lineitem.hxx>
 #include <dbdata.hxx>
@@ -419,6 +420,8 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest3, 
testCondFormatFormulaListenerXLSX)
     pDoc->SetDocVisible(true);
     pDoc->SetValue(0, 0, 0, 2.0);
 
+    Scheduler::ProcessEventsToIdle();
+
     CPPUNIT_ASSERT(aListener.mbCalled);
 }
 
@@ -439,6 +442,8 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest3, testTdf131471)
     pDoc->SetDocVisible(true);
     pDoc->SetValue(0, 0, 0, 1.0);
 
+    Scheduler::ProcessEventsToIdle();
+
     CPPUNIT_ASSERT(aListener.mbCalled);
 }
 
diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx
index b70f9579d0e8..93094e929bf4 100644
--- a/sc/source/core/data/conditio.cxx
+++ b/sc/source/core/data/conditio.cxx
@@ -160,12 +160,13 @@ void ScConditionEntry::StartListening()
     if (!pCondFormat)
         return;
 
+    mpRepaintTask = std::make_unique<RepaintInIdle>(pCondFormat);
     const ScRangeList& rRanges = pCondFormat->GetRange();
     mpListener->stopListening();
     start_listen_to(*mpListener, pFormula1.get(), rRanges);
     start_listen_to(*mpListener, pFormula2.get(), rRanges);
 
-    mpListener->setCallback([&]() { pCondFormat->DoRepaint();});
+    mpListener->setCallback([&]() { mpRepaintTask->Start();});
 }
 
 void ScConditionEntry::SetParent(ScConditionalFormat* pParent)
@@ -195,7 +196,8 @@ ScConditionEntry::ScConditionEntry( const ScConditionEntry& 
r ) :
     bFirstRun(true),
     mpListener(new ScFormulaListener(*r.mpDoc)),
     eConditionType( r.eConditionType ),
-    pCondFormat(r.pCondFormat)
+    pCondFormat(r.pCondFormat),
+    mpRepaintTask()
 {
     // ScTokenArray copy ctor creates a flat copy
     if (r.pFormula1)
@@ -228,7 +230,8 @@ ScConditionEntry::ScConditionEntry( ScDocument& rDocument, 
const ScConditionEntr
     bFirstRun(true),
     mpListener(new ScFormulaListener(rDocument)),
     eConditionType( r.eConditionType),
-    pCondFormat(r.pCondFormat)
+    pCondFormat(r.pCondFormat),
+    mpRepaintTask()
 {
     // Real copy of the formulas (for Ref Undo)
     if (r.pFormula1)
@@ -262,7 +265,8 @@ ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
     bFirstRun(true),
     mpListener(new ScFormulaListener(rDocument)),
     eConditionType(eType),
-    pCondFormat(nullptr)
+    pCondFormat(nullptr),
+    mpRepaintTask()
 {
     Compile( rExpr1, rExpr2, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2, 
false );
 
@@ -287,7 +291,8 @@ ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
     bFirstRun(true),
     mpListener(new ScFormulaListener(rDocument)),
     eConditionType(ScFormatEntry::Type::Condition),
-    pCondFormat(nullptr)
+    pCondFormat(nullptr),
+    mpRepaintTask()
 {
     if ( pArr1 )
     {

Reply via email to