diff options
author | Xisco Fauli <xiscofauli@libreoffice.org> | 2024-11-21 01:01:19 +0100 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2024-11-21 09:24:03 +0100 |
commit | 5c585cd975e8566a952651670a1e6b1865c22114 (patch) | |
tree | 0dd5e34955dad04a1f09a66225b2d3441bb8454a | |
parent | 4d41da669d443ecaffb344964a272630ccdca634 (diff) |
CppunitTest_sc_tiledrendering: factor out common code
Change-Id: If9f3ff5d9699876290fb643ed14ba64108cd191c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176877
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
-rw-r--r-- | sc/qa/unit/tiledrendering/tiledrendering.cxx | 456 | ||||
-rw-r--r-- | sc/qa/unit/tiledrendering/tiledrendering2.cxx | 142 | ||||
-rw-r--r-- | sc/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx | 465 |
3 files changed, 469 insertions, 594 deletions
diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index 8c63f99d82df..ca4c5191c1c5 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -7,17 +7,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <test/unoapixml_test.hxx> +#include "tiledrenderingmodeltestbase.cxx" #include <test/helper/transferable.hxx> -#include <boost/property_tree/json_parser.hpp> -#include <LibreOfficeKit/LibreOfficeKitEnums.h> #include <com/sun/star/datatransfer/clipboard/LokClipboard.hpp> #include <com/sun/star/util/URLTransformer.hpp> #include <comphelper/processfactory.hxx> #include <comphelper/propertysequence.hxx> #include <comphelper/servicehelper.hxx> -#include <osl/conditn.hxx> #include <sfx2/dispatch.hxx> #include <sfx2/viewfrm.hxx> #include <svl/stritem.hxx> @@ -35,24 +32,18 @@ #include <vcl/vclevent.hxx> #include <vcl/virdev.hxx> #include <sc.hrc> -#include <comphelper/string.hxx> #include <tools/json_writer.hxx> #include <postit.hxx> -#include <test/lokcallback.hxx> #include <unotools/syslocaleoptions.hxx> #include <attrib.hxx> #include <scitems.hxx> -#include <tabvwsh.hxx> -#include <docsh.hxx> #include <document.hxx> #include <docuno.hxx> #include <drwlayer.hxx> #include <editutil.hxx> #include <undomanager.hxx> -using namespace css; - static std::ostream& operator<<(std::ostream& os, ViewShellId const & id) { os << static_cast<sal_Int32>(id); return os; @@ -84,103 +75,6 @@ inline std::string toString(const ColRowZoom& item) } CPPUNIT_NS_END -namespace { -class ViewCallback; -} - -class ScTiledRenderingTest : public UnoApiXmlTest -{ -public: - ScTiledRenderingTest(); - virtual void setUp() override; - virtual void tearDown() override; - - void checkSampleInvalidation(const ViewCallback& rView, bool bFullRow); - void cellInvalidationHelper(ScModelObj* pModelObj, ScTabViewShell* pView, - const ScAddress& rAdr, bool bAddText, - bool bFullRow); - - ScModelObj* createDoc(const char* pName); - void setupLibreOfficeKitViewCallback(SfxViewShell* pViewShell); - static void callback(int nType, const char* pPayload, void* pData); - void callbackImpl(int nType, const char* pPayload); - - /// document size changed callback. - osl::Condition m_aDocSizeCondition; - Size m_aDocumentSize; - - TestLokCallbackWrapper m_callbackWrapper; -}; - -ScTiledRenderingTest::ScTiledRenderingTest() - : UnoApiXmlTest(u"/sc/qa/unit/tiledrendering/data/"_ustr), - m_callbackWrapper(&callback, this) -{ -} - -void ScTiledRenderingTest::setUp() -{ - UnoApiXmlTest::setUp(); - - comphelper::LibreOfficeKit::setActive(true); -} - -void ScTiledRenderingTest::tearDown() -{ - if (mxComponent.is()) - { - mxComponent->dispose(); - mxComponent.clear(); - } - - m_callbackWrapper.clear(); - - comphelper::LibreOfficeKit::resetCompatFlag(); - - comphelper::LibreOfficeKit::setActive(false); - - UnoApiXmlTest::tearDown(); -} - -ScModelObj* ScTiledRenderingTest::createDoc(const char* pName) -{ - loadFromFile(OUString::createFromAscii(pName)); - - ScModelObj* pModelObj = comphelper::getFromUnoTunnel<ScModelObj>(mxComponent); - CPPUNIT_ASSERT(pModelObj); - pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - return pModelObj; -} - -void ScTiledRenderingTest::setupLibreOfficeKitViewCallback(SfxViewShell* pViewShell) -{ - pViewShell->setLibreOfficeKitViewCallback(&m_callbackWrapper); - m_callbackWrapper.setLOKViewId(SfxLokHelper::getView(pViewShell)); -} - -void ScTiledRenderingTest::callback(int nType, const char* pPayload, void* pData) -{ - static_cast<ScTiledRenderingTest*>(pData)->callbackImpl(nType, pPayload); -} - -void ScTiledRenderingTest::callbackImpl(int nType, const char* pPayload) -{ - switch (nType) - { - case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED: - { - OString aPayload(pPayload); - sal_Int32 nIndex = 0; - OString aToken = aPayload.getToken(0, ',', nIndex); - m_aDocumentSize.setWidth(aToken.toInt32()); - aToken = aPayload.getToken(0, ',', nIndex); - m_aDocumentSize.setHeight(aToken.toInt32()); - m_aDocSizeCondition.set(); - } - break; - } -} - CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testRowColumnSelections) { ScModelObj* pModelObj = createDoc("select-row-cols.ods"); @@ -311,354 +205,6 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testEmptyColumnSelection) CPPUNIT_ASSERT_EQUAL(OString(), apitest::helper::transferable::getTextSelection(pModelObj->getSelection(), "text/plain;charset=utf-8"_ostr)); } -namespace -{ -struct EditCursorMessage final { - tools::Rectangle m_aRelRect; - Point m_aRefPoint; - - void clear() - { - m_aRelRect.SetEmpty(); - m_aRefPoint = Point(-1, -1); - } - - bool empty() - { - return m_aRelRect.IsEmpty() && - m_aRefPoint.X() == -1 && - m_aRefPoint.Y() == -1; - } - - void parseMessage(const char* pMessage) - { - clear(); - if (!pMessage || !comphelper::LibreOfficeKit::isCompatFlagSet( - comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs) || - !comphelper::LibreOfficeKit::isViewIdForVisCursorInvalidation()) - return; - - std::stringstream aStream(pMessage); - boost::property_tree::ptree aTree; - boost::property_tree::read_json(aStream, aTree); - std::string aVal; - boost::property_tree::ptree::const_assoc_iterator it = aTree.find("refpoint"); - if (it != aTree.not_found()) - aVal = aTree.get_child("refpoint").get_value<std::string>(); - else - return; // happens in testTextBoxInsert test - - uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(OUString::createFromAscii(aVal)); - CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aSeq.getLength()); - m_aRefPoint.setX(aSeq[0].toInt32()); - m_aRefPoint.setY(aSeq[1].toInt32()); - - aVal = aTree.get_child("relrect").get_value<std::string>(); - aSeq = comphelper::string::convertCommaSeparated(OUString::createFromAscii(aVal)); - CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aSeq.getLength()); - m_aRelRect.SetLeft(aSeq[0].toInt32()); - m_aRelRect.SetTop(aSeq[1].toInt32()); - m_aRelRect.setWidth(aSeq[2].toInt32()); - m_aRelRect.setHeight(aSeq[3].toInt32()); - } - - tools::Rectangle getBounds() - { - tools::Rectangle aBounds = m_aRelRect; - aBounds.Move(m_aRefPoint.X(), m_aRefPoint.Y()); - return aBounds; - } -}; - -struct TextSelectionMessage -{ - std::vector<tools::Rectangle> m_aRelRects; - Point m_aRefPoint; - - void clear() { - m_aRefPoint.setX(0); - m_aRefPoint.setY(0); - m_aRelRects.clear(); - } - - bool empty() { - return m_aRelRects.empty(); - } - - void parseMessage(const char* pMessage) - { - clear(); - if (!pMessage) - return; - - std::string aStr(pMessage); - if (aStr.find(",") == std::string::npos) - return; - - size_t nRefDelimStart = aStr.find("::"); - std::string aRectListString = (nRefDelimStart == std::string::npos) ? aStr : aStr.substr(0, nRefDelimStart); - std::string aRefPointString = (nRefDelimStart == std::string::npos) ? - std::string("0, 0") : - aStr.substr(nRefDelimStart + 2, aStr.length() - 2 - nRefDelimStart); - uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(OUString::createFromAscii(aRefPointString)); - CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aSeq.getLength()); - m_aRefPoint.setX(aSeq[0].toInt32()); - m_aRefPoint.setY(aSeq[1].toInt32()); - - size_t nStart = 0; - size_t nEnd = aRectListString.find(";"); - if (nEnd == std::string::npos) - nEnd = aRectListString.length(); - do - { - std::string aRectString = aRectListString.substr(nStart, nEnd - nStart); - { - aSeq = comphelper::string::convertCommaSeparated(OUString::createFromAscii(aRectString)); - CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aSeq.getLength()); - tools::Rectangle aRect; - aRect.SetLeft(aSeq[0].toInt32()); - aRect.SetTop(aSeq[1].toInt32()); - aRect.setWidth(aSeq[2].toInt32()); - aRect.setHeight(aSeq[3].toInt32()); - - m_aRelRects.push_back(aRect); - } - - nStart = nEnd + 1; - nEnd = aRectListString.find(";", nStart); - } - while(nEnd != std::string::npos); - } - - tools::Rectangle getBounds(size_t nIndex) - { - if (nIndex >= m_aRelRects.size()) - return tools::Rectangle(); - - tools::Rectangle aBounds = m_aRelRects[nIndex]; - aBounds.Move(m_aRefPoint.X(), m_aRefPoint.Y()); - return aBounds; - } - -}; - -/// A view callback tracks callbacks invoked on one specific view. -class ViewCallback final -{ - SfxViewShell* mpViewShell; - int mnView; -public: - bool m_bOwnCursorInvalidated; - bool m_bViewCursorInvalidated; - bool m_bTextViewSelectionInvalidated; - bool m_bGraphicSelection; - bool m_bGraphicViewSelection; - bool m_bFullInvalidateTiles; - bool m_bInvalidateTiles; - std::vector<tools::Rectangle> m_aInvalidations; - tools::Rectangle m_aCellCursorBounds; - std::vector<int> m_aInvalidationsParts; - std::vector<int> m_aInvalidationsMode; - bool m_bViewLock; - OString m_sCellFormula; - boost::property_tree::ptree m_aCommentCallbackResult; - EditCursorMessage m_aInvalidateCursorResult; - TextSelectionMessage m_aTextSelectionResult; - OString m_sInvalidateHeader; - OString m_sInvalidateSheetGeometry; - OString m_aHyperlinkClicked; - OString m_ShapeSelection; - std::map<std::string, boost::property_tree::ptree> m_aStateChanges; - TestLokCallbackWrapper m_callbackWrapper; - - ViewCallback(bool bDeleteListenerOnDestruct=true) - : m_bOwnCursorInvalidated(false), - m_bViewCursorInvalidated(false), - m_bTextViewSelectionInvalidated(false), - m_bGraphicSelection(false), - m_bGraphicViewSelection(false), - m_bFullInvalidateTiles(false), - m_bInvalidateTiles(false), - m_bViewLock(false), - m_callbackWrapper(&callback, this) - { - mpViewShell = SfxViewShell::Current(); - mpViewShell->setLibreOfficeKitViewCallback(&m_callbackWrapper); - mnView = SfxLokHelper::getView(); - m_callbackWrapper.setLOKViewId( mnView ); - if (!bDeleteListenerOnDestruct) - mpViewShell = nullptr; - } - - ~ViewCallback() - { - if (mpViewShell) - { - 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_CELL_CURSOR: - { - m_bOwnCursorInvalidated = true; - uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(OUString::createFromAscii(pPayload)); - m_aCellCursorBounds = tools::Rectangle(); - if (aSeq.getLength() == 6) { - m_aCellCursorBounds.SetLeft(aSeq[0].toInt32()); - m_aCellCursorBounds.SetTop(aSeq[1].toInt32()); - m_aCellCursorBounds.setWidth(aSeq[2].toInt32()); - m_aCellCursorBounds.setHeight(aSeq[3].toInt32()); - } - } - break; - case LOK_CALLBACK_CELL_VIEW_CURSOR: - { - m_bViewCursorInvalidated = true; - } - break; - case LOK_CALLBACK_TEXT_VIEW_SELECTION: - { - m_bTextViewSelectionInvalidated = true; - } - 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_GRAPHIC_SELECTION: - { - m_bGraphicSelection = true; - m_ShapeSelection = OString(pPayload); - } - break; - case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION: - { - m_bGraphicViewSelection = true; - } - break; - case LOK_CALLBACK_INVALIDATE_TILES: - { - OString text(pPayload); - if (text.startsWith("EMPTY")) - { - m_bFullInvalidateTiles = true; - } - else - { - uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(OUString::createFromAscii(pPayload)); - CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 6); - 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); - if (aSeq.getLength() == 6) - { - m_aInvalidationsParts.push_back(aSeq[4].toInt32()); - m_aInvalidationsMode.push_back(aSeq[5].toInt32()); - } - m_bInvalidateTiles = true; - } - } - break; - case LOK_CALLBACK_CELL_FORMULA: - { - m_sCellFormula = pPayload; - } - 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_INVALIDATE_HEADER: - { - m_sInvalidateHeader = pPayload; - } - break; - case LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY: - { - m_sInvalidateSheetGeometry = pPayload; - } - break; - case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR: - { - m_aInvalidateCursorResult.parseMessage(pPayload); - } - break; - case LOK_CALLBACK_HYPERLINK_CLICKED: - { - m_aHyperlinkClicked = pPayload; - } - break; - case LOK_CALLBACK_TEXT_SELECTION: - { - m_aTextSelectionResult.parseMessage(pPayload); - } - break; - case LOK_CALLBACK_STATE_CHANGED: - { - std::stringstream aStream(pPayload); - boost::property_tree::ptree aTree; - std::string aCommandName; - - if (aStream.str().starts_with("{")) - { - boost::property_tree::read_json(aStream, aTree); - auto it = aTree.find("commandName"); - if (it == aTree.not_found()) - { - break; - } - - aCommandName = it->second.get_value<std::string>(); - } - else - { - std::string aState = aStream.str(); - auto it = aState.find("="); - if (it == std::string::npos) - { - break; - } - aCommandName = aState.substr(0, it); - aTree.put("state", aState.substr(it + 1)); - } - - m_aStateChanges[aCommandName] = aTree; - } - break; - } - } - - void ClearAllInvalids() - { - m_bInvalidateTiles = false; - m_aInvalidations.clear(); - m_aInvalidationsParts.clear(); - m_aInvalidationsMode.clear(); - } -}; -} //namespace - CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testViewCursors) { ScModelObj* pModelObj = createDoc("select-row-cols.ods"); diff --git a/sc/qa/unit/tiledrendering/tiledrendering2.cxx b/sc/qa/unit/tiledrendering/tiledrendering2.cxx index 878379b089fe..6e8ce9ea9def 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering2.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering2.cxx @@ -7,151 +7,16 @@ * 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 "tiledrenderingmodeltestbase.cxx" #include <com/sun/star/datatransfer/XTransferable2.hpp> -#include <LibreOfficeKit/LibreOfficeKitEnums.h> -#include <comphelper/lok.hxx> -#include <comphelper/servicehelper.hxx> -#include <sfx2/lokhelper.hxx> -#include <test/lokcallback.hxx> #include <vcl/scheduler.hxx> #include <comphelper/propertyvalue.hxx> -#include <comphelper/string.hxx> - -#include <docuno.hxx> using namespace com::sun::star; -namespace -{ -class Test : public UnoApiXmlTest -{ -public: - Test(); - void setUp() override; - void tearDown() override; - - ScModelObj* createDoc(const char* pName); -}; - -Test::Test() - : UnoApiXmlTest(u"/sc/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::resetCompatFlag(); - - comphelper::LibreOfficeKit::setActive(false); - - UnoApiXmlTest::tearDown(); -} - -ScModelObj* Test::createDoc(const char* pName) -{ - loadFromFile(OUString::createFromAscii(pName)); - - ScModelObj* pModelObj = comphelper::getFromUnoTunnel<ScModelObj>(mxComponent); - CPPUNIT_ASSERT(pModelObj); - pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - return pModelObj; -} - -/// 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; - tools::Rectangle m_aCellCursorBounds; - TestLokCallbackWrapper m_callbackWrapper; - - ViewCallback() - : m_callbackWrapper(&callback, this) - { - mpViewShell = SfxViewShell::Current(); - mpViewShell->setLibreOfficeKitViewCallback(&m_callbackWrapper); - mnView = SfxLokHelper::getView(); - m_callbackWrapper.setLOKViewId(mnView); - } - - ~ViewCallback() - { - if (mpViewShell) - { - 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_CELL_CURSOR: - { - uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated( - OUString::createFromAscii(pPayload)); - m_aCellCursorBounds = tools::Rectangle(); - if (aSeq.getLength() >= 4) - { - m_aCellCursorBounds.SetLeft(aSeq[0].toInt32()); - m_aCellCursorBounds.SetTop(aSeq[1].toInt32()); - m_aCellCursorBounds.setWidth(aSeq[2].toInt32()); - m_aCellCursorBounds.setHeight(aSeq[3].toInt32()); - } - } - 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(Test, testSidebarLocale) +CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testSidebarLocale) { ScModelObj* pModelObj = createDoc("chart.ods"); int nView1 = SfxLokHelper::getView(); @@ -179,7 +44,7 @@ CPPUNIT_TEST_FIXTURE(Test, testSidebarLocale) CPPUNIT_ASSERT_EQUAL(std::string("de-DE"), aLocale); } -CPPUNIT_TEST_FIXTURE(Test, testCopyMultiSelection) +CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCopyMultiSelection) { // Given a document with A1 and A3 as selected cells: ScModelObj* pModelObj = createDoc("multi-selection.ods"); @@ -212,7 +77,6 @@ CPPUNIT_TEST_FIXTURE(Test, testCopyMultiSelection) // Without the fix, the text selection was complex. CPPUNIT_ASSERT(!xTransferable2->isComplex()); } -} CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx b/sc/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx new file mode 100644 index 000000000000..9fa272789780 --- /dev/null +++ b/sc/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx @@ -0,0 +1,465 @@ +/* -*- 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 <osl/conditn.hxx> +#include <sfx2/lokhelper.hxx> +#include <comphelper/string.hxx> +#include <tabvwsh.hxx> +#include <test/lokcallback.hxx> +#include <docuno.hxx> + +using namespace css; + +class ViewCallback; + +class ScTiledRenderingTest : public UnoApiXmlTest +{ +public: + ScTiledRenderingTest(); + virtual void setUp() override; + virtual void tearDown() override; + + void checkSampleInvalidation(const ViewCallback& rView, bool bFullRow); + void cellInvalidationHelper(ScModelObj* pModelObj, ScTabViewShell* pView, const ScAddress& rAdr, + bool bAddText, bool bFullRow); + + ScModelObj* createDoc(const char* pName); + void setupLibreOfficeKitViewCallback(SfxViewShell* pViewShell); + static void callback(int nType, const char* pPayload, void* pData); + void callbackImpl(int nType, const char* pPayload); + + /// document size changed callback. + osl::Condition m_aDocSizeCondition; + Size m_aDocumentSize; + + TestLokCallbackWrapper m_callbackWrapper; +}; + +ScTiledRenderingTest::ScTiledRenderingTest() + : UnoApiXmlTest(u"/sc/qa/unit/tiledrendering/data/"_ustr) + , m_callbackWrapper(&callback, this) +{ +} + +void ScTiledRenderingTest::setUp() +{ + UnoApiXmlTest::setUp(); + + comphelper::LibreOfficeKit::setActive(true); +} + +void ScTiledRenderingTest::tearDown() +{ + if (mxComponent.is()) + { + mxComponent->dispose(); + mxComponent.clear(); + } + + m_callbackWrapper.clear(); + + comphelper::LibreOfficeKit::resetCompatFlag(); + + comphelper::LibreOfficeKit::setActive(false); + + UnoApiXmlTest::tearDown(); +} + +ScModelObj* ScTiledRenderingTest::createDoc(const char* pName) +{ + loadFromFile(OUString::createFromAscii(pName)); + + ScModelObj* pModelObj = comphelper::getFromUnoTunnel<ScModelObj>(mxComponent); + CPPUNIT_ASSERT(pModelObj); + pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + return pModelObj; +} + +void ScTiledRenderingTest::setupLibreOfficeKitViewCallback(SfxViewShell* pViewShell) +{ + pViewShell->setLibreOfficeKitViewCallback(&m_callbackWrapper); + m_callbackWrapper.setLOKViewId(SfxLokHelper::getView(pViewShell)); +} + +void ScTiledRenderingTest::callback(int nType, const char* pPayload, void* pData) +{ + static_cast<ScTiledRenderingTest*>(pData)->callbackImpl(nType, pPayload); +} + +void ScTiledRenderingTest::callbackImpl(int nType, const char* pPayload) +{ + switch (nType) + { + case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED: + { + OString aPayload(pPayload); + sal_Int32 nIndex = 0; + OString aToken = aPayload.getToken(0, ',', nIndex); + m_aDocumentSize.setWidth(aToken.toInt32()); + aToken = aPayload.getToken(0, ',', nIndex); + m_aDocumentSize.setHeight(aToken.toInt32()); + m_aDocSizeCondition.set(); + } + break; + } +} + +struct EditCursorMessage final +{ + tools::Rectangle m_aRelRect; + Point m_aRefPoint; + + void clear() + { + m_aRelRect.SetEmpty(); + m_aRefPoint = Point(-1, -1); + } + + bool empty() { return m_aRelRect.IsEmpty() && m_aRefPoint.X() == -1 && m_aRefPoint.Y() == -1; } + + void parseMessage(const char* pMessage) + { + clear(); + if (!pMessage + || !comphelper::LibreOfficeKit::isCompatFlagSet( + comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs) + || !comphelper::LibreOfficeKit::isViewIdForVisCursorInvalidation()) + return; + + std::stringstream aStream(pMessage); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + std::string aVal; + boost::property_tree::ptree::const_assoc_iterator it = aTree.find("refpoint"); + if (it != aTree.not_found()) + aVal = aTree.get_child("refpoint").get_value<std::string>(); + else + return; // happens in testTextBoxInsert test + + uno::Sequence<OUString> aSeq + = comphelper::string::convertCommaSeparated(OUString::createFromAscii(aVal)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aSeq.getLength()); + m_aRefPoint.setX(aSeq[0].toInt32()); + m_aRefPoint.setY(aSeq[1].toInt32()); + + aVal = aTree.get_child("relrect").get_value<std::string>(); + aSeq = comphelper::string::convertCommaSeparated(OUString::createFromAscii(aVal)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aSeq.getLength()); + m_aRelRect.SetLeft(aSeq[0].toInt32()); + m_aRelRect.SetTop(aSeq[1].toInt32()); + m_aRelRect.setWidth(aSeq[2].toInt32()); + m_aRelRect.setHeight(aSeq[3].toInt32()); + } + + tools::Rectangle getBounds() + { + tools::Rectangle aBounds = m_aRelRect; + aBounds.Move(m_aRefPoint.X(), m_aRefPoint.Y()); + return aBounds; + } +}; + +struct TextSelectionMessage +{ + std::vector<tools::Rectangle> m_aRelRects; + Point m_aRefPoint; + + void clear() + { + m_aRefPoint.setX(0); + m_aRefPoint.setY(0); + m_aRelRects.clear(); + } + + bool empty() { return m_aRelRects.empty(); } + + void parseMessage(const char* pMessage) + { + clear(); + if (!pMessage) + return; + + std::string aStr(pMessage); + if (aStr.find(",") == std::string::npos) + return; + + size_t nRefDelimStart = aStr.find("::"); + std::string aRectListString + = (nRefDelimStart == std::string::npos) ? aStr : aStr.substr(0, nRefDelimStart); + std::string aRefPointString + = (nRefDelimStart == std::string::npos) + ? std::string("0, 0") + : aStr.substr(nRefDelimStart + 2, aStr.length() - 2 - nRefDelimStart); + uno::Sequence<OUString> aSeq + = comphelper::string::convertCommaSeparated(OUString::createFromAscii(aRefPointString)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aSeq.getLength()); + m_aRefPoint.setX(aSeq[0].toInt32()); + m_aRefPoint.setY(aSeq[1].toInt32()); + + size_t nStart = 0; + size_t nEnd = aRectListString.find(";"); + if (nEnd == std::string::npos) + nEnd = aRectListString.length(); + do + { + std::string aRectString = aRectListString.substr(nStart, nEnd - nStart); + { + aSeq = comphelper::string::convertCommaSeparated( + OUString::createFromAscii(aRectString)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aSeq.getLength()); + tools::Rectangle aRect; + aRect.SetLeft(aSeq[0].toInt32()); + aRect.SetTop(aSeq[1].toInt32()); + aRect.setWidth(aSeq[2].toInt32()); + aRect.setHeight(aSeq[3].toInt32()); + + m_aRelRects.push_back(aRect); + } + + nStart = nEnd + 1; + nEnd = aRectListString.find(";", nStart); + } while (nEnd != std::string::npos); + } + + tools::Rectangle getBounds(size_t nIndex) + { + if (nIndex >= m_aRelRects.size()) + return tools::Rectangle(); + + tools::Rectangle aBounds = m_aRelRects[nIndex]; + aBounds.Move(m_aRefPoint.X(), m_aRefPoint.Y()); + return aBounds; + } +}; + +/// A view callback tracks callbacks invoked on one specific view. +class ViewCallback final +{ + SfxViewShell* mpViewShell; + int mnView; + +public: + bool m_bOwnCursorInvalidated; + bool m_bViewCursorInvalidated; + bool m_bTextViewSelectionInvalidated; + bool m_bGraphicSelection; + bool m_bGraphicViewSelection; + bool m_bFullInvalidateTiles; + bool m_bInvalidateTiles; + std::vector<tools::Rectangle> m_aInvalidations; + tools::Rectangle m_aCellCursorBounds; + std::vector<int> m_aInvalidationsParts; + std::vector<int> m_aInvalidationsMode; + bool m_bViewLock; + OString m_sCellFormula; + boost::property_tree::ptree m_aCommentCallbackResult; + EditCursorMessage m_aInvalidateCursorResult; + TextSelectionMessage m_aTextSelectionResult; + OString m_sInvalidateHeader; + OString m_sInvalidateSheetGeometry; + OString m_aHyperlinkClicked; + OString m_ShapeSelection; + std::map<std::string, boost::property_tree::ptree> m_aStateChanges; + TestLokCallbackWrapper m_callbackWrapper; + + ViewCallback(bool bDeleteListenerOnDestruct = true) + : m_bOwnCursorInvalidated(false) + , m_bViewCursorInvalidated(false) + , m_bTextViewSelectionInvalidated(false) + , m_bGraphicSelection(false) + , m_bGraphicViewSelection(false) + , m_bFullInvalidateTiles(false) + , m_bInvalidateTiles(false) + , m_bViewLock(false) + , m_callbackWrapper(&callback, this) + { + mpViewShell = SfxViewShell::Current(); + mpViewShell->setLibreOfficeKitViewCallback(&m_callbackWrapper); + mnView = SfxLokHelper::getView(); + m_callbackWrapper.setLOKViewId(mnView); + if (!bDeleteListenerOnDestruct) + mpViewShell = nullptr; + } + + ~ViewCallback() + { + if (mpViewShell) + { + 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_CELL_CURSOR: + { + m_bOwnCursorInvalidated = true; + uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated( + OUString::createFromAscii(pPayload)); + m_aCellCursorBounds = tools::Rectangle(); + if (aSeq.getLength() == 6) + { + m_aCellCursorBounds.SetLeft(aSeq[0].toInt32()); + m_aCellCursorBounds.SetTop(aSeq[1].toInt32()); + m_aCellCursorBounds.setWidth(aSeq[2].toInt32()); + m_aCellCursorBounds.setHeight(aSeq[3].toInt32()); + } + } + break; + case LOK_CALLBACK_CELL_VIEW_CURSOR: + { + m_bViewCursorInvalidated = true; + } + break; + case LOK_CALLBACK_TEXT_VIEW_SELECTION: + { + m_bTextViewSelectionInvalidated = true; + } + 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_GRAPHIC_SELECTION: + { + m_bGraphicSelection = true; + m_ShapeSelection = OString(pPayload); + } + break; + case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION: + { + m_bGraphicViewSelection = true; + } + break; + case LOK_CALLBACK_INVALIDATE_TILES: + { + OString text(pPayload); + if (text.startsWith("EMPTY")) + { + m_bFullInvalidateTiles = true; + } + else + { + uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated( + OUString::createFromAscii(pPayload)); + CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 6); + 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); + if (aSeq.getLength() == 6) + { + m_aInvalidationsParts.push_back(aSeq[4].toInt32()); + m_aInvalidationsMode.push_back(aSeq[5].toInt32()); + } + m_bInvalidateTiles = true; + } + } + break; + case LOK_CALLBACK_CELL_FORMULA: + { + m_sCellFormula = pPayload; + } + 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_INVALIDATE_HEADER: + { + m_sInvalidateHeader = pPayload; + } + break; + case LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY: + { + m_sInvalidateSheetGeometry = pPayload; + } + break; + case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR: + { + m_aInvalidateCursorResult.parseMessage(pPayload); + } + break; + case LOK_CALLBACK_HYPERLINK_CLICKED: + { + m_aHyperlinkClicked = pPayload; + } + break; + case LOK_CALLBACK_TEXT_SELECTION: + { + m_aTextSelectionResult.parseMessage(pPayload); + } + break; + case LOK_CALLBACK_STATE_CHANGED: + { + std::stringstream aStream(pPayload); + boost::property_tree::ptree aTree; + std::string aCommandName; + + if (aStream.str().starts_with("{")) + { + boost::property_tree::read_json(aStream, aTree); + auto it = aTree.find("commandName"); + if (it == aTree.not_found()) + { + break; + } + + aCommandName = it->second.get_value<std::string>(); + } + else + { + std::string aState = aStream.str(); + auto it = aState.find("="); + if (it == std::string::npos) + { + break; + } + aCommandName = aState.substr(0, it); + aTree.put("state", aState.substr(it + 1)); + } + + m_aStateChanges[aCommandName] = aTree; + } + break; + } + } + + void ClearAllInvalids() + { + m_bInvalidateTiles = false; + m_aInvalidations.clear(); + m_aInvalidationsParts.clear(); + m_aInvalidationsMode.clear(); + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |