sd/qa/unit/tiledrendering/CallbackRecorder.hxx            |  152 -----
 sd/qa/unit/tiledrendering/LOKitSearchTest.cxx             |  370 +++++--------
 sd/qa/unit/tiledrendering/tiledrendering.cxx              |  370 -------------
 sd/qa/unit/tiledrendering/tiledrendering2.cxx             |  124 ----
 sd/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx |  389 ++++++++++++++
 5 files changed, 547 insertions(+), 858 deletions(-)

New commits:
commit bf2c6653164073c542fd04e19a5f3dd7f934078a
Author:     Xisco Fauli <xiscofa...@libreoffice.org>
AuthorDate: Thu Nov 21 10:07:33 2024 +0100
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Fri Nov 22 14:02:04 2024 +0100

    CppunitTest_sd_tiledrendering: factor out common code
    
    Change-Id: I8ba7871cd3ca7580230c31dedf468aaa8219241a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176915
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sd/qa/unit/tiledrendering/CallbackRecorder.hxx 
b/sd/qa/unit/tiledrendering/CallbackRecorder.hxx
deleted file mode 100644
index ad64f5ab3924..000000000000
--- a/sd/qa/unit/tiledrendering/CallbackRecorder.hxx
+++ /dev/null
@@ -1,152 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-#pragma once
-
-#include <cppunit/TestAssert.h>
-
-#include <LibreOfficeKit/LibreOfficeKitEnums.h>
-#include <boost/property_tree/json_parser.hpp>
-#include <comphelper/string.hxx>
-#include <osl/conditn.hxx>
-#include <sfx2/viewsh.hxx>
-#include <test/lokcallback.hxx>
-#include <o3tl/string_view.hxx>
-
-using namespace css;
-
-namespace
-{
-std::vector<OUString> lcl_convertSeparated(std::u16string_view rString, 
sal_Unicode nSeparator)
-{
-    std::vector<OUString> aRet;
-
-    sal_Int32 nIndex = 0;
-    do
-    {
-        OUString aToken(o3tl::trim(o3tl::getToken(rString, 0, nSeparator, 
nIndex)));
-        if (!aToken.isEmpty())
-            aRet.push_back(aToken);
-    } while (nIndex >= 0);
-
-    return aRet;
-}
-
-void lcl_convertRectangle(std::u16string_view rString, tools::Rectangle& 
rRectangle)
-{
-    uno::Sequence<OUString> aSeq = 
comphelper::string::convertCommaSeparated(rString);
-    CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 5);
-    rRectangle.SetLeft(aSeq[0].toInt32());
-    rRectangle.SetTop(aSeq[1].toInt32());
-    rRectangle.setWidth(aSeq[2].toInt32());
-    rRectangle.setHeight(aSeq[3].toInt32());
-}
-}
-
-struct CallbackRecorder
-{
-    CallbackRecorder()
-        : m_bFound(true)
-        , m_nPart(0)
-        , m_nSelectionBeforeSearchResult(0)
-        , m_nSelectionAfterSearchResult(0)
-        , m_nSearchResultCount(0)
-        , m_callbackWrapper(&callback, this)
-    {
-    }
-
-    tools::Rectangle m_aInvalidation;
-    std::vector<::tools::Rectangle> m_aSelection;
-    bool m_bFound;
-    sal_Int32 m_nPart;
-    std::vector<OString> m_aSearchResultSelection;
-    std::vector<int> m_aSearchResultPart;
-    int m_nSelectionBeforeSearchResult;
-    int m_nSelectionAfterSearchResult;
-    int m_nSearchResultCount;
-    /// For document size changed callback.
-    osl::Condition m_aDocumentSizeCondition;
-    TestLokCallbackWrapper m_callbackWrapper;
-
-    static void callback(int nType, const char* pPayload, void* pData)
-    {
-        static_cast<CallbackRecorder*>(pData)->processCallback(nType, 
pPayload);
-    }
-
-    void processCallback(int nType, const char* pPayload)
-    {
-        switch (nType)
-        {
-            case LOK_CALLBACK_INVALIDATE_TILES:
-            {
-                OUString aPayload = OUString::createFromAscii(pPayload);
-                if (aPayload != "EMPTY" && m_aInvalidation.IsEmpty())
-                    lcl_convertRectangle(aPayload, m_aInvalidation);
-            }
-            break;
-            case LOK_CALLBACK_TEXT_SELECTION:
-            {
-                OUString aPayload = OUString::createFromAscii(pPayload);
-                m_aSelection.clear();
-                for (const OUString& rString : lcl_convertSeparated(aPayload, 
u';'))
-                {
-                    ::tools::Rectangle aRectangle;
-                    lcl_convertRectangle(rString, aRectangle);
-                    m_aSelection.push_back(aRectangle);
-                }
-                if (m_aSearchResultSelection.empty())
-                    ++m_nSelectionBeforeSearchResult;
-                else
-                    ++m_nSelectionAfterSearchResult;
-            }
-            break;
-            case LOK_CALLBACK_SEARCH_NOT_FOUND:
-            {
-                m_bFound = false;
-            }
-            break;
-            case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
-            {
-                m_aDocumentSizeCondition.set();
-            }
-            break;
-            case LOK_CALLBACK_SET_PART:
-            {
-                OUString aPayload = OUString::createFromAscii(pPayload);
-                m_nPart = aPayload.toInt32();
-            }
-            break;
-            case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
-            {
-                m_nSearchResultCount++;
-                m_aSearchResultSelection.clear();
-                m_aSearchResultPart.clear();
-                boost::property_tree::ptree aTree;
-                std::stringstream aStream(pPayload);
-                boost::property_tree::read_json(aStream, aTree);
-                for (const boost::property_tree::ptree::value_type& rValue :
-                     aTree.get_child("searchResultSelection"))
-                {
-                    m_aSearchResultSelection.emplace_back(
-                        rValue.second.get<std::string>("rectangles").c_str());
-                    m_aSearchResultPart.push_back(
-                        
std::atoi(rValue.second.get<std::string>("part").c_str()));
-                }
-            }
-            break;
-        }
-    }
-
-    void registerCallbacksFor(SfxViewShell& rViewShell)
-    {
-        rViewShell.setLibreOfficeKitViewCallback(&m_callbackWrapper);
-    }
-};
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx 
b/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx
index 0e8bd2ad3de6..aff3deafc5be 100644
--- a/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx
+++ b/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx
@@ -7,13 +7,11 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include "CallbackRecorder.hxx"
-#include <test/unoapi_test.hxx>
+#include "tiledrenderingmodeltestbase.cxx"
 
 #include <test/helper/transferable.hxx>
 
 #include <comphelper/propertysequence.hxx>
-#include <comphelper/lok.hxx>
 #include <svl/srchitem.hxx>
 #include <vcl/scheduler.hxx>
 #include <ViewShellBase.hxx>
@@ -28,61 +26,19 @@
 
 using namespace css;
 
-class LOKitSearchTest : public UnoApiTest
+class LOKitSearchTest : public SdTiledRenderingTest
 {
 public:
     LOKitSearchTest()
-        : UnoApiTest(u"/sd/qa/unit/tiledrendering/data/"_ustr)
+        : SdTiledRenderingTest()
     {
     }
 
-    virtual void setUp() override;
-    virtual void tearDown() override;
-
 protected:
-    SdXImpressDocument* createDoc(const char* pName,
-                                  const uno::Sequence<beans::PropertyValue>& 
rArguments
-                                  = uno::Sequence<beans::PropertyValue>());
     void lcl_search(const OUString& rKey, bool bFindAll = false, bool 
bBackwards = false);
     void lcl_replace(const OUString& rKey, const OUString& rReplace, bool bAll 
= false);
-
-    std::unique_ptr<CallbackRecorder> mpCallbackRecorder;
 };
 
-void LOKitSearchTest::setUp()
-{
-    UnoApiTest::setUp();
-
-    // prevent showing warning message box
-    setenv("OOX_NO_SMARTART_WARNING", "1", 1);
-    comphelper::LibreOfficeKit::setActive(true);
-
-    mpCallbackRecorder = std::make_unique<CallbackRecorder>();
-}
-
-void LOKitSearchTest::tearDown()
-{
-    if (mxComponent.is())
-    {
-        mxComponent->dispose();
-        mxComponent.clear();
-    }
-
-    comphelper::LibreOfficeKit::setActive(false);
-
-    UnoApiTest::tearDown();
-}
-
-SdXImpressDocument*
-LOKitSearchTest::createDoc(const char* pName, const 
uno::Sequence<beans::PropertyValue>& rArguments)
-{
-    loadFromFile(OUString::createFromAscii(pName));
-    SdXImpressDocument* pImpressDocument = 
dynamic_cast<SdXImpressDocument*>(mxComponent.get());
-    CPPUNIT_ASSERT(pImpressDocument);
-    pImpressDocument->initializeForTiledRendering(rArguments);
-    return pImpressDocument;
-}
-
 void LOKitSearchTest::lcl_search(const OUString& rKey, bool bFindAll, bool 
bBackwards)
 {
     Scheduler::ProcessEventsToIdle();
@@ -129,7 +85,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, Search)
 {
     SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
     uno::Reference<container::XIndexAccess> xDrawPage(
         pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
     uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), 
uno::UNO_QUERY);
@@ -143,28 +99,27 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, Search)
     CPPUNIT_ASSERT_EQUAL(u"bbb"_ustr, rEditView.GetSelected());
 
     // Did the selection callback fire?
-    CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), 
mpCallbackRecorder->m_aSelection.size());
+    CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), m_aSelection.size());
 
     // Search for something on the second slide, and make sure that the 
set-part callback fired.
     lcl_search(u"bbb"_ustr);
-    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), 
mpCallbackRecorder->m_nPart);
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), m_nPart);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
     // This was 0; should be 1 match for "find".
-    CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1),
-                         mpCallbackRecorder->m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), 
m_aSearchResultSelection.size());
     // Result is on the second slide.
-    CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_aSearchResultPart[0]);
+    CPPUNIT_ASSERT_EQUAL(1, m_aSearchResultPart[0]);
 
     // This should trigger the not-found callback.
     lcl_search(u"ccc"_ustr);
-    CPPUNIT_ASSERT_EQUAL(false, mpCallbackRecorder->m_bFound);
+    CPPUNIT_ASSERT_EQUAL(false, m_bFound);
 }
 
 CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchAll)
 {
     SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     lcl_search(u"match"_ustr, /*bFindAll=*/true);
 
@@ -174,43 +129,43 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchAll)
                              pXImpressDocument->getSelection(), 
"text/plain;charset=utf-8"_ostr));
 
     // We're on the first slide, search for something on the second slide and 
make sure we get a SET_PART.
-    mpCallbackRecorder->m_nPart = 0;
+    m_nPart = 0;
     lcl_search(u"second"_ustr, /*bFindAll=*/true);
     // This was 0: no SET_PART was emitted.
-    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), 
mpCallbackRecorder->m_nPart);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), m_nPart);
 }
 
 CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchAllSelections)
 {
     SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     lcl_search(u"third"_ustr, /*bFindAll=*/true);
     // Make sure this is found on the 3rd slide.
-    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), 
mpCallbackRecorder->m_nPart);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), m_nPart);
     // This was 1: only the first match was highlighted.
-    CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), 
mpCallbackRecorder->m_aSelection.size());
+    CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), m_aSelection.size());
 }
 
 CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchAllNotifications)
 {
     SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     lcl_search(u"third"_ustr, /*bFindAll=*/true);
     // Make sure that we get no notifications about selection changes during 
search.
-    CPPUNIT_ASSERT_EQUAL(0, 
mpCallbackRecorder->m_nSelectionBeforeSearchResult);
+    CPPUNIT_ASSERT_EQUAL(0, m_nSelectionBeforeSearchResult);
     // But we do get the selection of the first hit.
-    CPPUNIT_ASSERT(mpCallbackRecorder->m_nSelectionAfterSearchResult > 0);
+    CPPUNIT_ASSERT(m_nSelectionAfterSearchResult > 0);
 }
 
 CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchAllFollowedBySearch)
 {
     SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     lcl_search(u"third"_ustr, /*bFindAll=*/true);
     lcl_search(u"match"_ustr /*,bFindAll=false*/);
@@ -226,12 +181,12 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, 
DontSearchInMasterPages)
 {
     SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     // This should trigger the not-found callback ("date" is present only on
     // the master page)
     lcl_search(u"date"_ustr);
-    CPPUNIT_ASSERT_EQUAL(false, mpCallbackRecorder->m_bFound);
+    CPPUNIT_ASSERT_EQUAL(false, m_bFound);
 }
 
 CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchInPDFNonExisting)
@@ -245,7 +200,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, 
SearchInPDFNonExisting)
     SdXImpressDocument* pXImpressDocument = createDoc("PDFSearch.pdf");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
     CPPUNIT_ASSERT(pViewShell);
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     SdPage* pPage = pViewShell->GetActualPage();
     CPPUNIT_ASSERT(pPage);
@@ -263,7 +218,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, 
SearchInPDFNonExisting)
 
     lcl_search(u"NonExisting"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(false, mpCallbackRecorder->m_bFound);
+    CPPUNIT_ASSERT_EQUAL(false, m_bFound);
 }
 
 CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchInPDF)
@@ -277,7 +232,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchInPDF)
     SdXImpressDocument* pXImpressDocument = createDoc("PDFSearch.pdf");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
     CPPUNIT_ASSERT(pViewShell);
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     SdPage* pPage = pViewShell->GetActualPage();
     CPPUNIT_ASSERT(pPage);
@@ -296,26 +251,22 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchInPDF)
     // Search
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(1, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL("3763, 1331, 1432, 483"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
-    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(3763, 1331), Size(1433, 484)),
-                         mpCallbackRecorder->m_aSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL("3763, 1331, 1432, 483"_ostr, 
m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(3763, 1331), Size(1433, 484)), 
m_aSelection[0]);
 
     // Search again - same result
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(2, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL("3763, 1331, 1432, 483"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
-    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(3763, 1331), Size(1433, 484)),
-                         mpCallbackRecorder->m_aSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL("3763, 1331, 1432, 483"_ostr, 
m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(3763, 1331), Size(1433, 484)), 
m_aSelection[0]);
 }
 
 CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchInPDFOnePDFObject)
@@ -329,7 +280,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, 
SearchInPDFOnePDFObject)
     SdXImpressDocument* pXImpressDocument = createDoc("OnePDFObject.odg");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
     CPPUNIT_ASSERT(pViewShell);
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     SdPage* pPage = pViewShell->GetActualPage();
     CPPUNIT_ASSERT(pPage);
@@ -348,14 +299,14 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, 
SearchInPDFOnePDFObject)
     // Search down
     lcl_search(u"ABC"_ustr, false, false);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(1, m_nSearchResultCount);
 
     // Search up
     lcl_search(u"ABC"_ustr, false, true); // This caused a crash
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(2, m_nSearchResultCount);
 }
 
 CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchInPDFInMultiplePages)
@@ -369,7 +320,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, 
SearchInPDFInMultiplePages)
     SdXImpressDocument* pXImpressDocument = createDoc("PDFSearch.pdf");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
     CPPUNIT_ASSERT(pViewShell);
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     SdPage* pPage = pViewShell->GetActualPage();
     CPPUNIT_ASSERT(pPage);
@@ -390,67 +341,62 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, 
SearchInPDFInMultiplePages)
     // Search for "him"
     lcl_search(u"him"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(1, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
-    CPPUNIT_ASSERT_EQUAL("9463, 3382, 1099, 499"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(0, m_aSearchResultPart[0]);
+    CPPUNIT_ASSERT_EQUAL("9463, 3382, 1099, 499"_ostr, 
m_aSearchResultSelection[0]);
 
     // Search for "him"
     lcl_search(u"him"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(2, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
-    CPPUNIT_ASSERT_EQUAL("5592, 5038, 1100, 499"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(0, m_aSearchResultPart[0]);
+    CPPUNIT_ASSERT_EQUAL("5592, 5038, 1100, 499"_ostr, 
m_aSearchResultSelection[0]);
 
     // Search for "him"
     lcl_search(u"him"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(3, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(3, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_aSearchResultPart[0]);
-    CPPUNIT_ASSERT_EQUAL("9463, 1308, 1099, 499"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(1, m_aSearchResultPart[0]);
+    CPPUNIT_ASSERT_EQUAL("9463, 1308, 1099, 499"_ostr, 
m_aSearchResultSelection[0]);
 
     // Search for "him"
     lcl_search(u"him"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(4, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(4, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_aSearchResultPart[0]);
-    CPPUNIT_ASSERT_EQUAL("5592, 2964, 1100, 499"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(1, m_aSearchResultPart[0]);
+    CPPUNIT_ASSERT_EQUAL("5592, 2964, 1100, 499"_ostr, 
m_aSearchResultSelection[0]);
 
     // Search for "him" - back to start
     lcl_search(u"him"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(5, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(5, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
-    CPPUNIT_ASSERT_EQUAL("9463, 3382, 1099, 499"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(0, m_aSearchResultPart[0]);
+    CPPUNIT_ASSERT_EQUAL("9463, 3382, 1099, 499"_ostr, 
m_aSearchResultSelection[0]);
 }
 
 CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchInPDFInMultiplePagesBackwards)
@@ -464,7 +410,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, 
SearchInPDFInMultiplePagesBackwards)
     SdXImpressDocument* pXImpressDocument = createDoc("PDFSearch.pdf");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
     CPPUNIT_ASSERT(pViewShell);
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     SdPage* pPage = pViewShell->GetActualPage();
     CPPUNIT_ASSERT(pPage);
@@ -493,67 +439,62 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, 
SearchInPDFInMultiplePagesBackwards)
     // Search for "him"
     lcl_search(u"him"_ustr, /*FindAll*/ false, /*Backwards*/ true);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(1, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
-    CPPUNIT_ASSERT_EQUAL("5592, 5038, 1100, 499"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(0, m_aSearchResultPart[0]);
+    CPPUNIT_ASSERT_EQUAL("5592, 5038, 1100, 499"_ostr, 
m_aSearchResultSelection[0]);
 
     // Search for "him"
     lcl_search(u"him"_ustr, /*FindAll*/ false, /*Backwards*/ true);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(2, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
-    CPPUNIT_ASSERT_EQUAL("9463, 3382, 1099, 499"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(0, m_aSearchResultPart[0]);
+    CPPUNIT_ASSERT_EQUAL("9463, 3382, 1099, 499"_ostr, 
m_aSearchResultSelection[0]);
 
     // Search for "him"
     lcl_search(u"him"_ustr, /*FindAll*/ false, /*Backwards*/ true);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(3, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(3, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_aSearchResultPart[0]);
-    CPPUNIT_ASSERT_EQUAL("5592, 2964, 1100, 499"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(1, m_aSearchResultPart[0]);
+    CPPUNIT_ASSERT_EQUAL("5592, 2964, 1100, 499"_ostr, 
m_aSearchResultSelection[0]);
 
     // Search for "him"
     lcl_search(u"him"_ustr, /*FindAll*/ false, /*Backwards*/ true);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(4, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(4, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_aSearchResultPart[0]);
-    CPPUNIT_ASSERT_EQUAL("9463, 1308, 1099, 499"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(1, m_aSearchResultPart[0]);
+    CPPUNIT_ASSERT_EQUAL("9463, 1308, 1099, 499"_ostr, 
m_aSearchResultSelection[0]);
 
     // Search for "him" - back to start
     lcl_search(u"him"_ustr, /*FindAll*/ false, /*Backwards*/ true);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(5, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(5, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
-    CPPUNIT_ASSERT_EQUAL("5592, 5038, 1100, 499"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL(0, m_aSearchResultPart[0]);
+    CPPUNIT_ASSERT_EQUAL("5592, 5038, 1100, 499"_ostr, 
m_aSearchResultSelection[0]);
 }
 
 // Test searching in document with mixed objects.
@@ -571,7 +512,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchIn2MixedObjects)
     CPPUNIT_ASSERT(pViewShell);
     SdDrawDocument* pDocument = pXImpressDocument->GetDocShell()->GetDoc();
     CPPUNIT_ASSERT(pDocument);
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     // Check we have one page
     CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), 
pDocument->GetSdPageCount(PageKind::Standard));
@@ -611,40 +552,37 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, 
SearchIn2MixedObjects)
 
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(1, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL("3545, 3174, 740, 402"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL("3545, 3174, 740, 402"_ostr, 
m_aSearchResultSelection[0]);
 
     // Search next
 
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(2, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL("8412, 6385, 519, 174"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL("8412, 6385, 519, 174"_ostr, 
m_aSearchResultSelection[0]);
 
     // Search next again - we should get the first object again
 
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(3, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(3, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
 
-    CPPUNIT_ASSERT_EQUAL("3545, 3174, 740, 402"_ostr,
-                         mpCallbackRecorder->m_aSearchResultSelection[0]);
+    CPPUNIT_ASSERT_EQUAL("3545, 3174, 740, 402"_ostr, 
m_aSearchResultSelection[0]);
 }
 
 // Test searching in document with mixed objects. We have 6 objects.
@@ -661,7 +599,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, SearchIn6MixedObjects)
     CPPUNIT_ASSERT(pViewShell);
     SdDrawDocument* pDocument = pXImpressDocument->GetDocShell()->GetDoc();
     CPPUNIT_ASSERT(pDocument);
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     // Check we have one page
     CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), 
pDocument->GetSdPageCount(PageKind::Standard));
@@ -736,81 +674,81 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, 
SearchIn6MixedObjects)
     // Object 1
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(1, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
     CPPUNIT_ASSERT_EQUAL(pPage->GetObj(0), lclGetSelectedObject(pViewShell));
 
     // Object 2
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(2, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
     CPPUNIT_ASSERT_EQUAL(pPage->GetObj(1), lclGetSelectedObject(pViewShell));
 
     // Object 3
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(3, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(3, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
     CPPUNIT_ASSERT_EQUAL(pPage->GetObj(2), lclGetSelectedObject(pViewShell));
 
     // Object 3 again
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(4, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(4, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
     CPPUNIT_ASSERT_EQUAL(pPage->GetObj(2), lclGetSelectedObject(pViewShell));
 
     // Object 4
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(5, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(5, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
     CPPUNIT_ASSERT_EQUAL(pPage->GetObj(3), lclGetSelectedObject(pViewShell));
 
     // Object 5
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(6, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(6, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
     CPPUNIT_ASSERT_EQUAL(pPage->GetObj(4), lclGetSelectedObject(pViewShell));
 
     // Object 6
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(7, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(7, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
     CPPUNIT_ASSERT_EQUAL(pPage->GetObj(5), lclGetSelectedObject(pViewShell));
 
     // Loop to Object 1 again
     lcl_search(u"ABC"_ustr);
 
-    CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
-    CPPUNIT_ASSERT_EQUAL(8, mpCallbackRecorder->m_nSearchResultCount);
+    CPPUNIT_ASSERT_EQUAL(true, m_bFound);
+    CPPUNIT_ASSERT_EQUAL(8, m_nSearchResultCount);
 
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultSelection.size());
-    CPPUNIT_ASSERT_EQUAL(size_t(1), 
mpCallbackRecorder->m_aSearchResultPart.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultSelection.size());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), m_aSearchResultPart.size());
     CPPUNIT_ASSERT_EQUAL(pPage->GetObj(0), lclGetSelectedObject(pViewShell));
 }
 namespace
@@ -829,7 +767,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, Replace)
 {
     SdXImpressDocument* pXImpressDocument = createDoc("ReplaceTest.odp");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     CPPUNIT_ASSERT_EQUAL(u"bbb"_ustr, getShapeText(pXImpressDocument, 0, 0));
     CPPUNIT_ASSERT_EQUAL(u"Bbb bbb bbb bbb"_ustr, 
getShapeText(pXImpressDocument, 1, 0));
@@ -858,7 +796,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, ReplaceAll)
 {
     SdXImpressDocument* pXImpressDocument = createDoc("ReplaceTest.odp");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     CPPUNIT_ASSERT_EQUAL(u"bbb"_ustr, getShapeText(pXImpressDocument, 0, 0));
     CPPUNIT_ASSERT_EQUAL(u"Bbb bbb bbb bbb"_ustr, 
getShapeText(pXImpressDocument, 1, 0));
@@ -887,7 +825,7 @@ CPPUNIT_TEST_FIXTURE(LOKitSearchTest, ReplaceCombined)
 {
     SdXImpressDocument* pXImpressDocument = createDoc("ReplaceTest.odp");
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
-    mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+    setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
 
     lcl_replace(u"bbb"_ustr, u"aaa"_ustr, false); // select
     lcl_replace(u"bbb"_ustr, u"aaa"_ustr, false); // replace
diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx 
b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index cf228cf54b5c..49812ce6788f 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -7,14 +7,13 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include <test/unoapixml_test.hxx>
+#include "tiledrenderingmodeltestbase.cxx"
 
 #include <app.hrc>
 #include <test/helper/transferable.hxx>
 #include <boost/property_tree/json_parser.hpp>
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <sal/log.hxx>
-#include <sfx2/lokhelper.hxx>
 #include <comphelper/propertysequence.hxx>
 #include <comphelper/propertyvalue.hxx>
 #include <comphelper/string.hxx>
@@ -31,19 +30,15 @@
 #include <sfx2/viewfrm.hxx>
 #include <svl/stritem.hxx>
 #include <svl/intitem.hxx>
-#include <comphelper/lok.hxx>
 #include <svx/svdotable.hxx>
 #include <svx/svdoutl.hxx>
 #include <unotools/datetime.hxx>
-#include <test/lokcallback.hxx>
 
 #include <DrawDocShell.hxx>
 #include <ViewShellBase.hxx>
 #include <ViewShell.hxx>
 #include <SlideshowLayerRenderer.hxx>
 #include <sdpage.hxx>
-#include <unomodel.hxx>
-#include <drawdoc.hxx>
 #include <undo/undomanager.hxx>
 #include <sfx2/request.hxx>
 #include <svx/svxids.hrc>
@@ -54,7 +49,6 @@
 #include <vcl/vclevent.hxx>
 #include <vcl/BitmapReadAccess.hxx>
 #include <vcl/virdev.hxx>
-#include <o3tl/string_view.hxx>
 #include <sfx2/sidebar/Sidebar.hxx>
 #include <vcl/BitmapTools.hxx>
 #include <vcl/filter/PngImageWriter.hxx>
@@ -71,207 +65,6 @@ static std::ostream& operator<<(std::ostream& os, 
ViewShellId id)
     return os;
 }
 
-class SdTiledRenderingTest : public UnoApiXmlTest
-{
-public:
-    SdTiledRenderingTest();
-    virtual void setUp() override;
-    virtual void tearDown() override;
-
-protected:
-    SdXImpressDocument* createDoc(const char* pName, const 
uno::Sequence<beans::PropertyValue>& rArguments = 
uno::Sequence<beans::PropertyValue>());
-    void setupLibreOfficeKitViewCallback(SfxViewShell& pViewShell);
-    static void callback(int nType, const char* pPayload, void* pData);
-    void callbackImpl(int nType, const char* pPayload);
-    xmlDocUniquePtr parseXmlDump();
-
-    ::tools::Rectangle m_aInvalidation;
-    std::vector<::tools::Rectangle> m_aSelection;
-    bool m_bFound;
-    sal_Int32 m_nPart;
-    std::vector<OString> m_aSearchResultSelection;
-    std::vector<int> m_aSearchResultPart;
-    int m_nSelectionBeforeSearchResult;
-    int m_nSelectionAfterSearchResult;
-
-    /// For document size changed callback.
-    osl::Condition m_aDocumentSizeCondition;
-    xmlBufferPtr m_pXmlBuffer;
-    TestLokCallbackWrapper m_callbackWrapper;
-};
-
-SdTiledRenderingTest::SdTiledRenderingTest()
-    : UnoApiXmlTest(u"/sd/qa/unit/tiledrendering/data/"_ustr),
-      m_bFound(true),
-      m_nPart(0),
-      m_nSelectionBeforeSearchResult(0),
-      m_nSelectionAfterSearchResult(0),
-      m_pXmlBuffer(nullptr),
-      m_callbackWrapper(&callback, this)
-{
-}
-
-void SdTiledRenderingTest::setUp()
-{
-    UnoApiXmlTest::setUp();
-
-    // prevent showing warning message box
-    setenv("OOX_NO_SMARTART_WARNING", "1", 1);
-    comphelper::LibreOfficeKit::setActive(true);
-}
-
-void SdTiledRenderingTest::tearDown()
-{
-    if (mxComponent.is())
-    {
-        mxComponent->dispose();
-        mxComponent.clear();
-    }
-
-    if (m_pXmlBuffer)
-        xmlBufferFree(m_pXmlBuffer);
-
-    m_callbackWrapper.clear();
-    comphelper::LibreOfficeKit::setActive(false);
-
-    UnoApiXmlTest::tearDown();
-}
-
-SdXImpressDocument* SdTiledRenderingTest::createDoc(const char* pName, const 
uno::Sequence<beans::PropertyValue>& rArguments)
-{
-    loadFromFile(OUString::createFromAscii(pName));
-    SdXImpressDocument* pImpressDocument = 
dynamic_cast<SdXImpressDocument*>(mxComponent.get());
-    CPPUNIT_ASSERT(pImpressDocument);
-    pImpressDocument->initializeForTiledRendering(rArguments);
-    return pImpressDocument;
-}
-
-void SdTiledRenderingTest::setupLibreOfficeKitViewCallback(SfxViewShell& 
pViewShell)
-{
-    pViewShell.setLibreOfficeKitViewCallback(&m_callbackWrapper);
-    m_callbackWrapper.setLOKViewId(SfxLokHelper::getView(&pViewShell));
-}
-
-void SdTiledRenderingTest::callback(int nType, const char* pPayload, void* 
pData)
-{
-    static_cast<SdTiledRenderingTest*>(pData)->callbackImpl(nType, pPayload);
-}
-
-namespace
-{
-
-std::vector<OUString> lcl_convertSeparated(std::u16string_view rString, 
sal_Unicode nSeparator)
-{
-    std::vector<OUString> aRet;
-
-    sal_Int32 nIndex = 0;
-    do
-    {
-        OUString aToken( o3tl::trim(o3tl::getToken(rString, 0, nSeparator, 
nIndex)) );
-        if (!aToken.isEmpty())
-            aRet.push_back(aToken);
-    }
-    while (nIndex >= 0);
-
-    return aRet;
-}
-
-void lcl_convertRectangle(std::u16string_view rString, ::tools::Rectangle& 
rRectangle)
-{
-    uno::Sequence<OUString> aSeq = 
comphelper::string::convertCommaSeparated(rString);
-    CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 5);
-    rRectangle.SetLeft(aSeq[0].toInt32());
-    rRectangle.SetTop(aSeq[1].toInt32());
-    rRectangle.setWidth(aSeq[2].toInt32());
-    rRectangle.setHeight(aSeq[3].toInt32());
-}
-
-} // end anonymous namespace
-
-void SdTiledRenderingTest::callbackImpl(int nType, const char* pPayload)
-{
-    switch (nType)
-    {
-    case LOK_CALLBACK_INVALIDATE_TILES:
-    {
-        OUString aPayload = OUString::createFromAscii(pPayload);
-        if (aPayload != "EMPTY" && m_aInvalidation.IsEmpty())
-            lcl_convertRectangle(aPayload, m_aInvalidation);
-    }
-    break;
-    case LOK_CALLBACK_TEXT_SELECTION:
-    {
-        OUString aPayload = OUString::createFromAscii(pPayload);
-        m_aSelection.clear();
-        for (const OUString& rString : lcl_convertSeparated(aPayload, u';'))
-        {
-            ::tools::Rectangle aRectangle;
-            lcl_convertRectangle(rString, aRectangle);
-            m_aSelection.push_back(aRectangle);
-        }
-        if (m_aSearchResultSelection.empty())
-            ++m_nSelectionBeforeSearchResult;
-        else
-            ++m_nSelectionAfterSearchResult;
-    }
-    break;
-    case LOK_CALLBACK_SEARCH_NOT_FOUND:
-    {
-        m_bFound = false;
-    }
-    break;
-    case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
-    {
-        m_aDocumentSizeCondition.set();
-    }
-    break;
-    case LOK_CALLBACK_SET_PART:
-    {
-        OUString aPayload = OUString::createFromAscii(pPayload);
-        m_nPart = aPayload.toInt32();
-    }
-    break;
-    case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
-    {
-        m_aSearchResultSelection.clear();
-        m_aSearchResultPart.clear();
-        boost::property_tree::ptree aTree;
-        std::stringstream aStream(pPayload);
-        boost::property_tree::read_json(aStream, aTree);
-        for (const boost::property_tree::ptree::value_type& rValue : 
aTree.get_child("searchResultSelection"))
-        {
-            
m_aSearchResultSelection.emplace_back(rValue.second.get<std::string>("rectangles").c_str());
-            
m_aSearchResultPart.push_back(std::atoi(rValue.second.get<std::string>("part").c_str()));
-        }
-    }
-    break;
-    }
-}
-
-xmlDocUniquePtr SdTiledRenderingTest::parseXmlDump()
-{
-    if (m_pXmlBuffer)
-        xmlBufferFree(m_pXmlBuffer);
-
-    // Create the xml writer.
-    m_pXmlBuffer = xmlBufferCreate();
-    xmlTextWriterPtr pXmlWriter = xmlNewTextWriterMemory(m_pXmlBuffer, 0);
-    (void)xmlTextWriterStartDocument(pXmlWriter, nullptr, nullptr, nullptr);
-
-    // Create the dump.
-    SdXImpressDocument* pImpressDocument = 
dynamic_cast<SdXImpressDocument*>(mxComponent.get());
-    CPPUNIT_ASSERT(pImpressDocument);
-    pImpressDocument->GetDoc()->dumpAsXml(pXmlWriter);
-
-    // Delete the xml writer.
-    (void)xmlTextWriterEndDocument(pXmlWriter);
-    xmlFreeTextWriter(pXmlWriter);
-
-    auto pCharBuffer = xmlBufferContent(m_pXmlBuffer);
-    SAL_INFO("test", "SdTiledRenderingTest::parseXmlDump: pCharBuffer is '" << 
pCharBuffer << "'");
-    return xmlDocUniquePtr(xmlParseDoc(pCharBuffer));
-}
-
 CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCreateDestroy)
 {
     createDoc("dummy.odp");
@@ -765,167 +558,6 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testResizeTableColumn)
     pXmlDoc = nullptr;
 }
 
-namespace {
-
-/// A view callback tracks callbacks invoked on one specific view.
-class ViewCallback final
-{
-    SfxViewShell* mpViewShell;
-    int mnView;
-public:
-    bool m_bGraphicSelectionInvalidated;
-    bool m_bGraphicViewSelectionInvalidated;
-    /// Our current part, to be able to decide if a view cursor/selection is 
relevant for us.
-    int m_nPart;
-    bool m_bCursorVisibleChanged;
-    bool m_bCursorVisible;
-    bool m_bViewLock;
-    bool m_bTilesInvalidated;
-    std::vector<tools::Rectangle> m_aInvalidations;
-    std::map<int, bool> m_aViewCursorInvalidations;
-    std::map<int, bool> m_aViewCursorVisibilities;
-    bool m_bViewSelectionSet;
-    boost::property_tree::ptree m_aCommentCallbackResult;
-    OString m_ShapeSelection;
-    std::map<std::string, boost::property_tree::ptree> m_aStateChanges;
-    TestLokCallbackWrapper m_callbackWrapper;
-
-    ViewCallback()
-        : m_bGraphicSelectionInvalidated(false),
-          m_bGraphicViewSelectionInvalidated(false),
-          m_nPart(0),
-          m_bCursorVisibleChanged(false),
-          m_bCursorVisible(false),
-          m_bViewLock(false),
-          m_bTilesInvalidated(false),
-          m_bViewSelectionSet(false),
-          m_callbackWrapper(&callback, this)
-    {
-        mpViewShell = SfxViewShell::Current();
-        mpViewShell->setLibreOfficeKitViewCallback(&m_callbackWrapper);
-        mnView = SfxLokHelper::getView();
-        m_callbackWrapper.setLOKViewId( mnView );
-    }
-
-    ~ViewCallback()
-    {
-        SfxLokHelper::setView(mnView);
-        mpViewShell->setLibreOfficeKitViewCallback(nullptr);
-    }
-
-    static void callback(int nType, const char* pPayload, void* pData)
-    {
-        static_cast<ViewCallback*>(pData)->callbackImpl(nType, pPayload);
-    }
-
-    void callbackImpl(int nType, const char* pPayload)
-    {
-        switch (nType)
-        {
-        case LOK_CALLBACK_INVALIDATE_TILES:
-        {
-            m_bTilesInvalidated = true;
-            OString text(pPayload);
-            if (!text.startsWith("EMPTY"))
-            {
-                uno::Sequence<OUString> aSeq = 
comphelper::string::convertCommaSeparated(OUString::createFromAscii(pPayload));
-                CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 5);
-                tools::Rectangle aInvalidationRect;
-                aInvalidationRect.SetLeft(aSeq[0].toInt32());
-                aInvalidationRect.SetTop(aSeq[1].toInt32());
-                aInvalidationRect.setWidth(aSeq[2].toInt32());
-                aInvalidationRect.setHeight(aSeq[3].toInt32());
-                m_aInvalidations.push_back(aInvalidationRect);
-            }
-        }
-        break;
-        case LOK_CALLBACK_GRAPHIC_SELECTION:
-        {
-            m_bGraphicSelectionInvalidated = true;
-            m_ShapeSelection = OString(pPayload);
-        }
-        break;
-        case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
-        {
-            std::stringstream aStream(pPayload);
-            boost::property_tree::ptree aTree;
-            boost::property_tree::read_json(aStream, aTree);
-            if (aTree.get_child("part").get_value<int>() == m_nPart)
-                // Ignore callbacks which are for a different part.
-                m_bGraphicViewSelectionInvalidated = true;
-        }
-        break;
-        case LOK_CALLBACK_CURSOR_VISIBLE:
-        {
-            m_bCursorVisibleChanged = true;
-            m_bCursorVisible = (std::string_view("true") == pPayload);
-        }
-        break;
-        case LOK_CALLBACK_VIEW_LOCK:
-        {
-            std::stringstream aStream(pPayload);
-            boost::property_tree::ptree aTree;
-            boost::property_tree::read_json(aStream, aTree);
-            m_bViewLock = 
aTree.get_child("rectangle").get_value<std::string>() != "EMPTY";
-        }
-        break;
-        case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR:
-        {
-            std::stringstream aStream(pPayload);
-            boost::property_tree::ptree aTree;
-            boost::property_tree::read_json(aStream, aTree);
-            int nViewId = aTree.get_child("viewId").get_value<int>();
-            m_aViewCursorInvalidations[nViewId] = true;
-        }
-        break;
-        case LOK_CALLBACK_VIEW_CURSOR_VISIBLE:
-        {
-            std::stringstream aStream(pPayload);
-            boost::property_tree::ptree aTree;
-            boost::property_tree::read_json(aStream, aTree);
-            const int nViewId = aTree.get_child("viewId").get_value<int>();
-            m_aViewCursorVisibilities[nViewId] = std::string_view("true") == 
pPayload;
-        }
-        break;
-        case LOK_CALLBACK_TEXT_VIEW_SELECTION:
-        {
-            m_bViewSelectionSet = true;
-        }
-        break;
-        case LOK_CALLBACK_COMMENT:
-        {
-            m_aCommentCallbackResult.clear();
-            std::stringstream aStream(pPayload);
-            boost::property_tree::read_json(aStream, m_aCommentCallbackResult);
-            m_aCommentCallbackResult = 
m_aCommentCallbackResult.get_child("comment");
-        }
-        break;
-        case LOK_CALLBACK_STATE_CHANGED:
-        {
-            std::stringstream aStream(pPayload);
-            if (!aStream.str().starts_with("{"))
-            {
-                break;
-            }
-
-            boost::property_tree::ptree aTree;
-            boost::property_tree::read_json(aStream, aTree);
-            auto it = aTree.find("commandName");
-            if (it == aTree.not_found())
-            {
-                break;
-            }
-
-            std::string aCommandName = it->second.get_value<std::string>();
-            m_aStateChanges[aCommandName] = aTree;
-        }
-        break;
-        }
-    }
-};
-
-}
-
 CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testViewCursors)
 {
     // Create two views.
diff --git a/sd/qa/unit/tiledrendering/tiledrendering2.cxx 
b/sd/qa/unit/tiledrendering/tiledrendering2.cxx
index a9b0b6e5b8ff..28860a293b41 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering2.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering2.cxx
@@ -7,130 +7,12 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include <test/unoapixml_test.hxx>
+#include "tiledrenderingmodeltestbase.cxx"
 
-#include <boost/property_tree/json_parser.hpp>
-
-#include <LibreOfficeKit/LibreOfficeKitEnums.h>
-#include <comphelper/lok.hxx>
-#include <sfx2/lokhelper.hxx>
 #include <sfx2/sidebar/Sidebar.hxx>
-#include <test/lokcallback.hxx>
 #include <vcl/scheduler.hxx>
 
-#include <unomodel.hxx>
-
-using namespace css;
-
-namespace
-{
-/// Impress tests with comphelper::LibreOfficeKit::isActive() enabled, part 2.
-class Test : public UnoApiXmlTest
-{
-public:
-    Test();
-    virtual void setUp() override;
-    virtual void tearDown() override;
-
-protected:
-    SdXImpressDocument* createDoc(const char* pName,
-                                  const uno::Sequence<beans::PropertyValue>& 
rArguments = {});
-};
-
-Test::Test()
-    : UnoApiXmlTest(u"/sd/qa/unit/tiledrendering/data/"_ustr)
-{
-}
-
-void Test::setUp()
-{
-    UnoApiXmlTest::setUp();
-
-    comphelper::LibreOfficeKit::setActive(true);
-}
-
-void Test::tearDown()
-{
-    if (mxComponent.is())
-    {
-        mxComponent->dispose();
-        mxComponent.clear();
-    }
-
-    comphelper::LibreOfficeKit::setActive(false);
-
-    UnoApiXmlTest::tearDown();
-}
-
-SdXImpressDocument* Test::createDoc(const char* pName,
-                                    const uno::Sequence<beans::PropertyValue>& 
rArguments)
-{
-    loadFromFile(OUString::createFromAscii(pName));
-    SdXImpressDocument* pImpressDocument = 
dynamic_cast<SdXImpressDocument*>(mxComponent.get());
-    CPPUNIT_ASSERT(pImpressDocument);
-    pImpressDocument->initializeForTiledRendering(rArguments);
-    return pImpressDocument;
-}
-
-/// A view callback tracks callbacks invoked on one specific view.
-class ViewCallback final
-{
-    SfxViewShell* mpViewShell;
-    int mnView;
-
-public:
-    std::map<std::string, boost::property_tree::ptree> m_aStateChanges;
-    TestLokCallbackWrapper m_callbackWrapper;
-
-    ViewCallback()
-        : m_callbackWrapper(&callback, this)
-    {
-        mpViewShell = SfxViewShell::Current();
-        mpViewShell->setLibreOfficeKitViewCallback(&m_callbackWrapper);
-        mnView = SfxLokHelper::getView();
-        m_callbackWrapper.setLOKViewId(mnView);
-    }
-
-    ~ViewCallback()
-    {
-        SfxLokHelper::setView(mnView);
-        mpViewShell->setLibreOfficeKitViewCallback(nullptr);
-    }
-
-    static void callback(int nType, const char* pPayload, void* pData)
-    {
-        static_cast<ViewCallback*>(pData)->callbackImpl(nType, pPayload);
-    }
-
-    void callbackImpl(int nType, const char* pPayload)
-    {
-        switch (nType)
-        {
-            case LOK_CALLBACK_STATE_CHANGED:
-            {
-                std::stringstream aStream(pPayload);
-                if (!aStream.str().starts_with("{"))
-                {
-                    break;
-                }
-
-                boost::property_tree::ptree aTree;
-                boost::property_tree::read_json(aStream, aTree);
-                auto it = aTree.find("commandName");
-                if (it == aTree.not_found())
-                {
-                    break;
-                }
-
-                std::string aCommandName = it->second.get_value<std::string>();
-                m_aStateChanges[aCommandName] = aTree;
-            }
-            break;
-        }
-    }
-};
-
-CPPUNIT_TEST_FIXTURE(Test, testSidebarSwitchDeck)
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSidebarSwitchDeck)
 {
     // Given an impress document, with a visible sidebar (ModifyPage deck):
     createDoc("dummy.odp");
@@ -153,7 +35,7 @@ CPPUNIT_TEST_FIXTURE(Test, testSidebarSwitchDeck)
     it = aView.m_aStateChanges.find(".uno:MasterSlidesPanel");
     CPPUNIT_ASSERT(it != aView.m_aStateChanges.end());
 }
-}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx 
b/sd/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx
new file mode 100644
index 000000000000..8d134ae2143f
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx
@@ -0,0 +1,389 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/unoapixml_test.hxx>
+
+#include <boost/property_tree/json_parser.hpp>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <comphelper/string.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <test/lokcallback.hxx>
+#include <comphelper/lok.hxx>
+#include <osl/conditn.hxx>
+#include <drawdoc.hxx>
+#include <unomodel.hxx>
+#include <o3tl/string_view.hxx>
+
+using namespace css;
+
+class SdTiledRenderingTest : public UnoApiXmlTest
+{
+public:
+    SdTiledRenderingTest();
+    virtual void setUp() override;
+    virtual void tearDown() override;
+
+protected:
+    SdXImpressDocument* createDoc(const char* pName,
+                                  const uno::Sequence<beans::PropertyValue>& 
rArguments
+                                  = uno::Sequence<beans::PropertyValue>());
+    void setupLibreOfficeKitViewCallback(SfxViewShell& pViewShell);
+    static void callback(int nType, const char* pPayload, void* pData);
+    void callbackImpl(int nType, const char* pPayload);
+    xmlDocUniquePtr parseXmlDump();
+
+    ::tools::Rectangle m_aInvalidation;
+    std::vector<::tools::Rectangle> m_aSelection;
+    bool m_bFound;
+    sal_Int32 m_nPart;
+    std::vector<OString> m_aSearchResultSelection;
+    std::vector<int> m_aSearchResultPart;
+    int m_nSelectionBeforeSearchResult;
+    int m_nSelectionAfterSearchResult;
+    int m_nSearchResultCount;
+
+    /// For document size changed callback.
+    osl::Condition m_aDocumentSizeCondition;
+    xmlBufferPtr m_pXmlBuffer;
+    TestLokCallbackWrapper m_callbackWrapper;
+};
+
+SdTiledRenderingTest::SdTiledRenderingTest()
+    : UnoApiXmlTest(u"/sd/qa/unit/tiledrendering/data/"_ustr)
+    , m_bFound(true)
+    , m_nPart(0)
+    , m_nSelectionBeforeSearchResult(0)
+    , m_nSelectionAfterSearchResult(0)
+    , m_nSearchResultCount(0)
+    , m_pXmlBuffer(nullptr)
+    , m_callbackWrapper(&callback, this)
+{
+}
+
+void SdTiledRenderingTest::setUp()
+{
+    UnoApiXmlTest::setUp();
+
+    // prevent showing warning message box
+    setenv("OOX_NO_SMARTART_WARNING", "1", 1);
+    comphelper::LibreOfficeKit::setActive(true);
+}
+
+void SdTiledRenderingTest::tearDown()
+{
+    if (mxComponent.is())
+    {
+        mxComponent->dispose();
+        mxComponent.clear();
+    }
+
+    if (m_pXmlBuffer)
+        xmlBufferFree(m_pXmlBuffer);
+
+    m_callbackWrapper.clear();
+    comphelper::LibreOfficeKit::setActive(false);
+
+    UnoApiXmlTest::tearDown();
+}
+
+SdXImpressDocument*
+SdTiledRenderingTest::createDoc(const char* pName,
+                                const uno::Sequence<beans::PropertyValue>& 
rArguments)
+{
+    loadFromFile(OUString::createFromAscii(pName));
+    SdXImpressDocument* pImpressDocument = 
dynamic_cast<SdXImpressDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pImpressDocument);
+    pImpressDocument->initializeForTiledRendering(rArguments);
+    return pImpressDocument;
+}
+
+void SdTiledRenderingTest::setupLibreOfficeKitViewCallback(SfxViewShell& 
pViewShell)
+{
+    pViewShell.setLibreOfficeKitViewCallback(&m_callbackWrapper);
+    m_callbackWrapper.setLOKViewId(SfxLokHelper::getView(&pViewShell));
+}
+
+void SdTiledRenderingTest::callback(int nType, const char* pPayload, void* 
pData)
+{
+    static_cast<SdTiledRenderingTest*>(pData)->callbackImpl(nType, pPayload);
+}
+
+std::vector<OUString> lcl_convertSeparated(std::u16string_view rString, 
sal_Unicode nSeparator)
+{
+    std::vector<OUString> aRet;
+
+    sal_Int32 nIndex = 0;
+    do
+    {
+        OUString aToken(o3tl::trim(o3tl::getToken(rString, 0, nSeparator, 
nIndex)));
+        if (!aToken.isEmpty())
+            aRet.push_back(aToken);
+    } while (nIndex >= 0);
+
+    return aRet;
+}
+
+void lcl_convertRectangle(std::u16string_view rString, ::tools::Rectangle& 
rRectangle)
+{
+    uno::Sequence<OUString> aSeq = 
comphelper::string::convertCommaSeparated(rString);
+    CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 5);
+    rRectangle.SetLeft(aSeq[0].toInt32());
+    rRectangle.SetTop(aSeq[1].toInt32());
+    rRectangle.setWidth(aSeq[2].toInt32());
+    rRectangle.setHeight(aSeq[3].toInt32());
+}
+
+void SdTiledRenderingTest::callbackImpl(int nType, const char* pPayload)
+{
+    switch (nType)
+    {
+        case LOK_CALLBACK_INVALIDATE_TILES:
+        {
+            OUString aPayload = OUString::createFromAscii(pPayload);
+            if (aPayload != "EMPTY" && m_aInvalidation.IsEmpty())
+                lcl_convertRectangle(aPayload, m_aInvalidation);
+        }
+        break;
+        case LOK_CALLBACK_TEXT_SELECTION:
+        {
+            OUString aPayload = OUString::createFromAscii(pPayload);
+            m_aSelection.clear();
+            for (const OUString& rString : lcl_convertSeparated(aPayload, 
u';'))
+            {
+                ::tools::Rectangle aRectangle;
+                lcl_convertRectangle(rString, aRectangle);
+                m_aSelection.push_back(aRectangle);
+            }
+            if (m_aSearchResultSelection.empty())
+                ++m_nSelectionBeforeSearchResult;
+            else
+                ++m_nSelectionAfterSearchResult;
+        }
+        break;
+        case LOK_CALLBACK_SEARCH_NOT_FOUND:
+        {
+            m_bFound = false;
+        }
+        break;
+        case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
+        {
+            m_aDocumentSizeCondition.set();
+        }
+        break;
+        case LOK_CALLBACK_SET_PART:
+        {
+            OUString aPayload = OUString::createFromAscii(pPayload);
+            m_nPart = aPayload.toInt32();
+        }
+        break;
+        case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
+        {
+            m_nSearchResultCount++;
+            m_aSearchResultSelection.clear();
+            m_aSearchResultPart.clear();
+            boost::property_tree::ptree aTree;
+            std::stringstream aStream(pPayload);
+            boost::property_tree::read_json(aStream, aTree);
+            for (const boost::property_tree::ptree::value_type& rValue :
+                 aTree.get_child("searchResultSelection"))
+            {
+                m_aSearchResultSelection.emplace_back(
+                    rValue.second.get<std::string>("rectangles").c_str());
+                m_aSearchResultPart.push_back(
+                    std::atoi(rValue.second.get<std::string>("part").c_str()));
+            }
+        }
+        break;
+    }
+}
+
+xmlDocUniquePtr SdTiledRenderingTest::parseXmlDump()
+{
+    if (m_pXmlBuffer)
+        xmlBufferFree(m_pXmlBuffer);
+
+    // Create the xml writer.
+    m_pXmlBuffer = xmlBufferCreate();
+    xmlTextWriterPtr pXmlWriter = xmlNewTextWriterMemory(m_pXmlBuffer, 0);
+    (void)xmlTextWriterStartDocument(pXmlWriter, nullptr, nullptr, nullptr);
+
+    // Create the dump.
+    SdXImpressDocument* pImpressDocument = 
dynamic_cast<SdXImpressDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pImpressDocument);
+    pImpressDocument->GetDoc()->dumpAsXml(pXmlWriter);
+
+    // Delete the xml writer.
+    (void)xmlTextWriterEndDocument(pXmlWriter);
+    xmlFreeTextWriter(pXmlWriter);
+
+    auto pCharBuffer = xmlBufferContent(m_pXmlBuffer);
+    SAL_INFO("test", "SdTiledRenderingTest::parseXmlDump: pCharBuffer is '" << 
pCharBuffer << "'");
+    return xmlDocUniquePtr(xmlParseDoc(pCharBuffer));
+}
+
+/// A view callback tracks callbacks invoked on one specific view.
+class ViewCallback final
+{
+    SfxViewShell* mpViewShell;
+    int mnView;
+
+public:
+    bool m_bGraphicSelectionInvalidated;
+    bool m_bGraphicViewSelectionInvalidated;
+    /// Our current part, to be able to decide if a view cursor/selection is 
relevant for us.
+    int m_nPart;
+    bool m_bCursorVisibleChanged;
+    bool m_bCursorVisible;
+    bool m_bViewLock;
+    bool m_bTilesInvalidated;
+    std::vector<tools::Rectangle> m_aInvalidations;
+    std::map<int, bool> m_aViewCursorInvalidations;
+    std::map<int, bool> m_aViewCursorVisibilities;
+    bool m_bViewSelectionSet;
+    boost::property_tree::ptree m_aCommentCallbackResult;
+    OString m_ShapeSelection;
+    std::map<std::string, boost::property_tree::ptree> m_aStateChanges;
+    TestLokCallbackWrapper m_callbackWrapper;
+
+    ViewCallback()
+        : m_bGraphicSelectionInvalidated(false)
+        , m_bGraphicViewSelectionInvalidated(false)
+        , m_nPart(0)
+        , m_bCursorVisibleChanged(false)
+        , m_bCursorVisible(false)
+        , m_bViewLock(false)
+        , m_bTilesInvalidated(false)
+        , m_bViewSelectionSet(false)
+        , m_callbackWrapper(&callback, this)
+    {
+        mpViewShell = SfxViewShell::Current();
+        mpViewShell->setLibreOfficeKitViewCallback(&m_callbackWrapper);
+        mnView = SfxLokHelper::getView();
+        m_callbackWrapper.setLOKViewId(mnView);
+    }
+
+    ~ViewCallback()
+    {
+        SfxLokHelper::setView(mnView);
+        mpViewShell->setLibreOfficeKitViewCallback(nullptr);
+    }
+
+    static void callback(int nType, const char* pPayload, void* pData)
+    {
+        static_cast<ViewCallback*>(pData)->callbackImpl(nType, pPayload);
+    }
+
+    void callbackImpl(int nType, const char* pPayload)
+    {
+        switch (nType)
+        {
+            case LOK_CALLBACK_INVALIDATE_TILES:
+            {
+                m_bTilesInvalidated = true;
+                OString text(pPayload);
+                if (!text.startsWith("EMPTY"))
+                {
+                    uno::Sequence<OUString> aSeq = 
comphelper::string::convertCommaSeparated(
+                        OUString::createFromAscii(pPayload));
+                    CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() 
== 5);
+                    tools::Rectangle aInvalidationRect;
+                    aInvalidationRect.SetLeft(aSeq[0].toInt32());
+                    aInvalidationRect.SetTop(aSeq[1].toInt32());
+                    aInvalidationRect.setWidth(aSeq[2].toInt32());
+                    aInvalidationRect.setHeight(aSeq[3].toInt32());
+                    m_aInvalidations.push_back(aInvalidationRect);
+                }
+            }
+            break;
+            case LOK_CALLBACK_GRAPHIC_SELECTION:
+            {
+                m_bGraphicSelectionInvalidated = true;
+                m_ShapeSelection = OString(pPayload);
+            }
+            break;
+            case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
+            {
+                std::stringstream aStream(pPayload);
+                boost::property_tree::ptree aTree;
+                boost::property_tree::read_json(aStream, aTree);
+                if (aTree.get_child("part").get_value<int>() == m_nPart)
+                    // Ignore callbacks which are for a different part.
+                    m_bGraphicViewSelectionInvalidated = true;
+            }
+            break;
+            case LOK_CALLBACK_CURSOR_VISIBLE:
+            {
+                m_bCursorVisibleChanged = true;
+                m_bCursorVisible = (std::string_view("true") == pPayload);
+            }
+            break;
+            case LOK_CALLBACK_VIEW_LOCK:
+            {
+                std::stringstream aStream(pPayload);
+                boost::property_tree::ptree aTree;
+                boost::property_tree::read_json(aStream, aTree);
+                m_bViewLock = 
aTree.get_child("rectangle").get_value<std::string>() != "EMPTY";
+            }
+            break;
+            case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR:
+            {
+                std::stringstream aStream(pPayload);
+                boost::property_tree::ptree aTree;
+                boost::property_tree::read_json(aStream, aTree);
+                int nViewId = aTree.get_child("viewId").get_value<int>();
+                m_aViewCursorInvalidations[nViewId] = true;
+            }
+            break;
+            case LOK_CALLBACK_VIEW_CURSOR_VISIBLE:
+            {
+                std::stringstream aStream(pPayload);
+                boost::property_tree::ptree aTree;
+                boost::property_tree::read_json(aStream, aTree);
+                const int nViewId = aTree.get_child("viewId").get_value<int>();
+                m_aViewCursorVisibilities[nViewId] = std::string_view("true") 
== pPayload;
+            }
+            break;
+            case LOK_CALLBACK_TEXT_VIEW_SELECTION:
+            {
+                m_bViewSelectionSet = true;
+            }
+            break;
+            case LOK_CALLBACK_COMMENT:
+            {
+                m_aCommentCallbackResult.clear();
+                std::stringstream aStream(pPayload);
+                boost::property_tree::read_json(aStream, 
m_aCommentCallbackResult);
+                m_aCommentCallbackResult = 
m_aCommentCallbackResult.get_child("comment");
+            }
+            break;
+            case LOK_CALLBACK_STATE_CHANGED:
+            {
+                std::stringstream aStream(pPayload);
+                if (!aStream.str().starts_with("{"))
+                {
+                    break;
+                }
+
+                boost::property_tree::ptree aTree;
+                boost::property_tree::read_json(aStream, aTree);
+                auto it = aTree.find("commandName");
+                if (it == aTree.not_found())
+                {
+                    break;
+                }
+
+                std::string aCommandName = it->second.get_value<std::string>();
+                m_aStateChanges[aCommandName] = aTree;
+            }
+            break;
+        }
+    }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to