sc/CppunitTest_sc_tiledrendering.mk | 2 sc/CppunitTest_sc_tiledrendering2.mk | 2 sc/Library_scqahelper.mk | 2 sc/qa/unit/helper/sctestviewcallback.cxx | 360 +++++++++ sc/qa/unit/helper/sctestviewcallback.hxx | 94 ++ sc/qa/unit/helper/sctiledrenderingtest.cxx | 171 ++++ sc/qa/unit/helper/sctiledrenderingtest.hxx | 53 + sc/qa/unit/tiledrendering/tiledrendering.cxx | 247 ++---- sc/qa/unit/tiledrendering/tiledrendering2.cxx | 21 sc/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx | 521 -------------- 10 files changed, 799 insertions(+), 674 deletions(-)
New commits: commit 36c01a613866e2c3208c376175b77d1d3ec8d841 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Apr 14 15:59:50 2025 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Apr 15 09:15:43 2025 +0200 sc: move ScTiledRenderingTest to Library_scqahelper Allows not including .cxx files in Calc tests. [ Pick to co-25.04, to reduce conflicts vs master. ] Change-Id: Ib68cd406df1ed1c9d36cbab9701a47bd016eaab4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184191 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sc/CppunitTest_sc_tiledrendering.mk b/sc/CppunitTest_sc_tiledrendering.mk index 5a2f4d971332..a00fdb0259f0 100644 --- a/sc/CppunitTest_sc_tiledrendering.mk +++ b/sc/CppunitTest_sc_tiledrendering.mk @@ -31,6 +31,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sc_tiledrendering, \ sc \ scfilt \ scui \ + scqahelper \ subsequenttest \ test \ unotest \ @@ -49,6 +50,7 @@ $(eval $(call gb_CppunitTest_use_externals,sc_tiledrendering,\ $(eval $(call gb_CppunitTest_set_include,sc_tiledrendering,\ -I$(SRCDIR)/sc/source/ui/inc \ -I$(SRCDIR)/sc/inc \ + -I$(SRCDIR)/sc/qa/unit/helper \ $$(INCLUDE) \ )) diff --git a/sc/CppunitTest_sc_tiledrendering2.mk b/sc/CppunitTest_sc_tiledrendering2.mk index 9acb0bffe924..2d70c6dcbb47 100644 --- a/sc/CppunitTest_sc_tiledrendering2.mk +++ b/sc/CppunitTest_sc_tiledrendering2.mk @@ -31,6 +31,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sc_tiledrendering2, \ sc \ scfilt \ scui \ + scqahelper \ subsequenttest \ test \ unotest \ @@ -49,6 +50,7 @@ $(eval $(call gb_CppunitTest_use_externals,sc_tiledrendering2,\ $(eval $(call gb_CppunitTest_set_include,sc_tiledrendering2,\ -I$(SRCDIR)/sc/source/ui/inc \ -I$(SRCDIR)/sc/inc \ + -I$(SRCDIR)/sc/qa/unit/helper \ $$(INCLUDE) \ )) diff --git a/sc/Library_scqahelper.mk b/sc/Library_scqahelper.mk index 6e8c9eca7327..071a69dcfbc2 100644 --- a/sc/Library_scqahelper.mk +++ b/sc/Library_scqahelper.mk @@ -69,6 +69,8 @@ $(eval $(call gb_Library_use_libraries,scqahelper,\ $(eval $(call gb_Library_add_exception_objects,scqahelper,\ sc/qa/unit/helper/qahelper \ sc/qa/unit/helper/scfiltertestbase \ + sc/qa/unit/helper/sctiledrenderingtest \ + sc/qa/unit/helper/sctestviewcallback \ sc/qa/unit/functions_test \ )) diff --git a/sc/qa/unit/helper/sctestviewcallback.cxx b/sc/qa/unit/helper/sctestviewcallback.cxx new file mode 100644 index 000000000000..f590c79879cf --- /dev/null +++ b/sc/qa/unit/helper/sctestviewcallback.cxx @@ -0,0 +1,360 @@ +/* -*- 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 "sctestviewcallback.hxx" + +#include <boost/property_tree/json_parser.hpp> + +#include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <comphelper/lok.hxx> +#include <comphelper/string.hxx> +#include <test/unoapixml_test.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/lokhelper.hxx> + +using namespace com::sun::star; + +void ScTestEditCursorMessage::clear() +{ + m_aRelRect.SetEmpty(); + m_aRefPoint = Point(-1, -1); +} + +bool ScTestEditCursorMessage::empty() +{ + return m_aRelRect.IsEmpty() && m_aRefPoint.X() == -1 && m_aRefPoint.Y() == -1; +} + +void ScTestEditCursorMessage::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 ScTestEditCursorMessage::getBounds() +{ + tools::Rectangle aBounds = m_aRelRect; + aBounds.Move(m_aRefPoint.X(), m_aRefPoint.Y()); + return aBounds; +} + +void ScTestTextSelectionMessage::clear() +{ + m_aRefPoint.setX(0); + m_aRefPoint.setY(0); + m_aRelRects.clear(); +} + +bool ScTestTextSelectionMessage::empty() { return m_aRelRects.empty(); } + +void ScTestTextSelectionMessage::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 ScTestTextSelectionMessage::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; +} + +ScTestViewCallback::ScTestViewCallback(bool bDeleteListenerOnDestruct) + : m_bOwnCursorInvalidated(false) + , m_bViewCursorInvalidated(false) + , m_textCursorVisible(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; +} + +ScTestViewCallback::~ScTestViewCallback() +{ + if (mpViewShell) + { + SfxLokHelper::setView(mnView); + mpViewShell->setLibreOfficeKitViewCallback(nullptr); + } +} + +void ScTestViewCallback::callback(int nType, const char* pPayload, void* pData) +{ + static_cast<ScTestViewCallback*>(pData)->callbackImpl(nType, pPayload); +} + +void ScTestViewCallback::callbackImpl(int nType, const char* pPayload) +{ + switch (nType) + { + case LOK_CALLBACK_VIEW_CURSOR_VISIBLE: + { + boost::property_tree::ptree aTree; + std::stringstream aStream(pPayload); + boost::property_tree::read_json(aStream, aTree); + m_textCursorVisible = aTree.get_child("visible").get_value<std::string>() == "true"; + } + break; + 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; + case LOK_CALLBACK_JSDIALOG: + { + std::stringstream aStream(pPayload); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + if (aTree.get_child("jsontype").get_value<std::string>() == "formulabar") + { + if (aTree.find("data") != aTree.not_found()) + { + if (aTree.get_child("data").find("separator") + != aTree.get_child("data").not_found()) + { + decimalSeparator = aTree.get_child("data") + .get_child("separator") + .get_value<std::string>(); + } + } + } + } + break; + } +} + +void ScTestViewCallback::ClearAllInvalids() +{ + m_bInvalidateTiles = false; + m_aInvalidations.clear(); + m_aInvalidationsParts.clear(); + m_aInvalidationsMode.clear(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/helper/sctestviewcallback.hxx b/sc/qa/unit/helper/sctestviewcallback.hxx new file mode 100644 index 000000000000..a5452a1f8f3e --- /dev/null +++ b/sc/qa/unit/helper/sctestviewcallback.hxx @@ -0,0 +1,94 @@ +/* -*- 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 <map> + +#include <boost/property_tree/ptree.hpp> + +#include <tools/gen.hxx> +#include <rtl/string.hxx> +#include <test/lokcallback.hxx> + +#include "scqahelperdllapi.h" + +class SfxViewShell; + +struct SCQAHELPER_DLLPUBLIC ScTestEditCursorMessage final +{ + tools::Rectangle m_aRelRect; + Point m_aRefPoint; + + void clear(); + + bool empty(); + + void parseMessage(const char* pMessage); + + tools::Rectangle getBounds(); +}; + +struct SCQAHELPER_DLLPUBLIC ScTestTextSelectionMessage +{ + std::vector<tools::Rectangle> m_aRelRects; + Point m_aRefPoint; + + void clear(); + + bool empty(); + + void parseMessage(const char* pMessage); + + tools::Rectangle getBounds(size_t nIndex); +}; +/// A view callback tracks callbacks invoked on one specific view. +class SCQAHELPER_DLLPUBLIC ScTestViewCallback final +{ + SfxViewShell* mpViewShell; + int mnView; + +public: + bool m_bOwnCursorInvalidated; + bool m_bViewCursorInvalidated; + bool m_textCursorVisible; + 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; + ScTestEditCursorMessage m_aInvalidateCursorResult; + ScTestTextSelectionMessage m_aTextSelectionResult; + OString m_sInvalidateHeader; + OString m_sInvalidateSheetGeometry; + OString m_aHyperlinkClicked; + OString m_ShapeSelection; + std::map<std::string, boost::property_tree::ptree> m_aStateChanges; + std::string decimalSeparator; + TestLokCallbackWrapper m_callbackWrapper; + + ScTestViewCallback(bool bDeleteListenerOnDestruct = true); + + ~ScTestViewCallback(); + + static void callback(int nType, const char* pPayload, void* pData); + + void callbackImpl(int nType, const char* pPayload); + + void ClearAllInvalids(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/helper/sctiledrenderingtest.cxx b/sc/qa/unit/helper/sctiledrenderingtest.cxx new file mode 100644 index 000000000000..7d835209dd9b --- /dev/null +++ b/sc/qa/unit/helper/sctiledrenderingtest.cxx @@ -0,0 +1,171 @@ +/* -*- 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 "sctiledrenderingtest.hxx" + +#include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <comphelper/lok.hxx> +#include <comphelper/servicehelper.hxx> +#include <sfx2/lokhelper.hxx> +#include <vcl/scheduler.hxx> + +#include <docuno.hxx> +#include <tabvwsh.hxx> + +#include "sctestviewcallback.hxx" + +using namespace com::sun::star; + +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; + } +} + +void ScTiledRenderingTest::checkSampleInvalidation(const ScTestViewCallback& rView, bool bFullRow) +{ + // we expect invalidations, but that isn't really important + CPPUNIT_ASSERT(rView.m_bInvalidateTiles); + tools::Rectangle aInvalidation; + for (const auto& rRect : rView.m_aInvalidations) + aInvalidation.Union(rRect); + if (!bFullRow) + { + // What matters is that we expect that the invalidation does not extend all the + // way to the max right of the sheet. + // Here we originally got 32212306 and now ~5056 for a single cell case + CPPUNIT_ASSERT_LESSEQUAL(tools::Long(8000), aInvalidation.GetWidth()); + } + else + { + // We expect RTL to continue to invalidate the entire row + // from 0 to end of sheet (see ScDocShell::PostPaint, 'Extend to whole rows'), + // which is different to the adjusted LTR case which + // invalidated the row from left of edited cell to right of end + // of sheet. + CPPUNIT_ASSERT_LESSEQUAL(tools::Long(0), aInvalidation.Left()); + CPPUNIT_ASSERT_EQUAL(tools::Long(32212230), aInvalidation.Right()); + } +} + +void ScTiledRenderingTest::cellInvalidationHelper(ScModelObj* pModelObj, ScTabViewShell* pView, + const ScAddress& rAdr, bool bAddText, + bool bFullRow) +{ + // view + ScTestViewCallback aView; + + if (bAddText) + { + // Type "Hello World" in D8, process events to idle and don't commit yet + typeCharsInCell("Hello World", rAdr.Col(), rAdr.Row(), pView, pModelObj, false, false); + + aView.m_bInvalidateTiles = false; + aView.m_aInvalidations.clear(); + + // commit text and process events to idle + typeCharsInCell("", rAdr.Col(), rAdr.Row(), pView, pModelObj, true, true); + } + else // DeleteText + { + pView->SetCursor(rAdr.Col(), rAdr.Row()); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::DELETE); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::DELETE); + Scheduler::ProcessEventsToIdle(); + } + + checkSampleInvalidation(aView, bFullRow); +} + +void ScTiledRenderingTest::typeCharsInCell(const std::string& aStr, SCCOL nCol, SCROW nRow, + ScTabViewShell* pView, ScModelObj* pModelObj, + bool bInEdit, bool bCommit) +{ + if (!bInEdit) + pView->SetCursor(nCol, nRow); + + for (const char& cChar : aStr) + { + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, cChar, 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, cChar, 0); + Scheduler::ProcessEventsToIdle(); + } + + if (bCommit) + { + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::RETURN); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::RETURN); + Scheduler::ProcessEventsToIdle(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/helper/sctiledrenderingtest.hxx b/sc/qa/unit/helper/sctiledrenderingtest.hxx new file mode 100644 index 000000000000..4bd7769e57a8 --- /dev/null +++ b/sc/qa/unit/helper/sctiledrenderingtest.hxx @@ -0,0 +1,53 @@ +/* -*- 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 <test/unoapixml_test.hxx> + +#include <osl/conditn.hxx> +#include <test/lokcallback.hxx> + +#include <types.hxx> + +#include "scqahelperdllapi.h" + +class ScTestViewCallback; +class ScModelObj; +class ScTabViewShell; +class ScAddress; +class SfxViewShell; + +class SCQAHELPER_DLLPUBLIC ScTiledRenderingTest : public UnoApiXmlTest +{ +public: + ScTiledRenderingTest(); + virtual void setUp() override; + virtual void tearDown() override; + + void checkSampleInvalidation(const ScTestViewCallback& 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); + + void typeCharsInCell(const std::string& aStr, SCCOL nCol, SCROW nRow, ScTabViewShell* pView, + ScModelObj* pModelObj, bool bInEdit = false, bool bCommit = true); + + /// document size changed callback. + osl::Condition m_aDocSizeCondition; + Size m_aDocumentSize; + + TestLokCallbackWrapper m_callbackWrapper; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index be54455154dd..e4966adc2f4a 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -7,11 +7,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "tiledrenderingmodeltestbase.cxx" -#include <test/helper/transferable.hxx> +#include <sctiledrenderingtest.hxx> + +#include <boost/property_tree/json_parser.hpp> #include <com/sun/star/datatransfer/clipboard/LokClipboard.hpp> #include <com/sun/star/util/URLTransformer.hpp> + +#include <test/helper/transferable.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/propertysequence.hxx> #include <comphelper/servicehelper.hxx> @@ -20,7 +23,8 @@ #include <svl/stritem.hxx> #include <svl/numformat.hxx> #include <svl/zformat.hxx> - +#include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <vcl/scheduler.hxx> #include <comphelper/lok.hxx> #include <comphelper/propertyvalue.hxx> #include <comphelper/dispatchcommand.hxx> @@ -30,11 +34,11 @@ #include <svx/svdpage.hxx> #include <vcl/vclevent.hxx> #include <vcl/virdev.hxx> -#include <sc.hrc> #include <tools/json_writer.hxx> -#include <postit.hxx> #include <unotools/syslocaleoptions.hxx> +#include <sc.hrc> +#include <postit.hxx> #include <attrib.hxx> #include <scitems.hxx> #include <document.hxx> @@ -42,6 +46,11 @@ #include <drwlayer.hxx> #include <editutil.hxx> #include <undomanager.hxx> +#include <docsh.hxx> +#include <tabvwsh.hxx> +#include <sctestviewcallback.hxx> + +using namespace com::sun::star; static std::ostream& operator<<(std::ostream& os, ViewShellId const & id) { @@ -207,10 +216,10 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testEmptyColumnSelection) CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testViewCursors) { ScModelObj* pModelObj = createDoc("select-row-cols.ods"); - ViewCallback aView1; + ScTestViewCallback aView1; SfxLokHelper::createView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2(/*bDeleteListenerOnDestruct*/false); + ScTestViewCallback aView2(/*bDeleteListenerOnDestruct*/false); // This was false, the new view did not get the view (cell) cursor of the old view. CPPUNIT_ASSERT(aView2.m_bViewCursorInvalidated); CPPUNIT_ASSERT(aView2.m_bOwnCursorInvalidated); @@ -243,10 +252,10 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testTextViewSelection) { // Create two views, and leave the second one current. ScModelObj* pModelObj = createDoc("select-row-cols.ods"); - ViewCallback aView1; + ScTestViewCallback aView1; SfxLokHelper::createView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2; + ScTestViewCallback aView2; // Create a selection on two cells in the second view, that's a text selection in LOK terms. aView1.m_bTextViewSelectionInvalidated = false; @@ -276,10 +285,10 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testViewLock) { // Load a document that has a shape and create two views. ScModelObj* pModelObj = createDoc("shape.ods"); - ViewCallback aView1; + ScTestViewCallback aView1; SfxLokHelper::createView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2; + ScTestViewCallback aView2; // Begin text edit in the second view and assert that the first gets a lock // notification. @@ -325,7 +334,7 @@ void lcl_extractHandleParameters(std::string_view selection, sal_uInt32& id, sal CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testMoveShapeHandle) { ScModelObj* pModelObj = createDoc("shape.ods"); - ViewCallback aView1; + ScTestViewCallback aView1; pModelObj->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, /*x=*/ 1,/*y=*/ 1,/*count=*/ 1, /*buttons=*/ 1, /*modifier=*/0); pModelObj->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP, /*x=*/ 1, /*y=*/ 1, /*count=*/ 1, /*buttons=*/ 1, /*modifier=*/0); Scheduler::ProcessEventsToIdle(); @@ -423,7 +432,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testTextEditViews) CPPUNIT_ASSERT(pViewData); // view #1 - ViewCallback aView1; + ScTestViewCallback aView1; CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); // text edit a cell in view #1 @@ -435,7 +444,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testTextEditViews) // view #2 SfxLokHelper::createView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2; + ScTestViewCallback aView2; // move cell cursor i view #2 pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::DOWN); @@ -455,13 +464,13 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testTextEditViewInvalidations) // view #1 int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); // view #2 SfxLokHelper::createView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2; + ScTestViewCallback aView2; // text edit a cell in view #1 SfxLokHelper::setView(nView1); @@ -492,7 +501,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testTextEditViewInvalidations) // view #3 SfxLokHelper::createView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView3; + ScTestViewCallback aView3; // text edit a cell in view #1 SfxLokHelper::setView(nView1); @@ -507,7 +516,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCreateViewGraphicSelection) { // Load a document that has a shape and create two views. ScModelObj* pModelObj = createDoc("shape.ods"); - ViewCallback aView1; + ScTestViewCallback aView1; // Mark the graphic in the first view. const ScViewData* pViewData = ScDocShell::GetViewData(); @@ -527,7 +536,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCreateViewGraphicSelection) int nView1 = SfxLokHelper::getView(); SfxLokHelper::createView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2; + ScTestViewCallback aView2; CPPUNIT_ASSERT(aView2.m_bGraphicViewSelection); CPPUNIT_ASSERT(aView1.m_bGraphicViewSelection); @@ -539,7 +548,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testGraphicInvalidate) { // Load a document that has a shape and create two views. ScModelObj* pModelObj = createDoc("shape.ods"); - ViewCallback aView; + ScTestViewCallback aView; // Click to select graphic aView.m_bGraphicSelection = false; @@ -565,7 +574,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testAutoSum) { createDoc("small.ods"); - ViewCallback aView; + ScTestViewCallback aView; uno::Sequence<beans::PropertyValue> aArgs; dispatchCommand(mxComponent, u".uno:AutoSum"_ustr, aArgs); @@ -635,7 +644,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testInvalidateOnCopyPasteCells) CPPUNIT_ASSERT(pModelObj); // view - ViewCallback aView; + ScTestViewCallback aView; uno::Sequence<beans::PropertyValue> aArgs; // select and copy cells @@ -669,7 +678,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testInvalidateOnInserRowCol) CPPUNIT_ASSERT(pModelObj); // view - ViewCallback aView; + ScTestViewCallback aView; uno::Sequence<beans::PropertyValue> aArgs; // move downward @@ -715,13 +724,13 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCommentCallback) { ScModelObj* pModelObj = createDoc("small.ods"); - ViewCallback aView1; + ScTestViewCallback aView1; int nView1 = SfxLokHelper::getView(); // Create a 2nd view SfxLokHelper::createView(); pModelObj->initializeForTiledRendering({}); - ViewCallback aView2; + ScTestViewCallback aView2; SfxLokHelper::setView(nView1); @@ -825,13 +834,13 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testUndoLimiting) // view #1 int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; // view #2 SfxLokHelper::createView(); int nView2 = SfxLokHelper::getView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2; + ScTestViewCallback aView2; // text edit a cell in view #1 SfxLokHelper::setView(nView1); @@ -883,13 +892,13 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testUndoRepairDispatch) // view #1 int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; // view #2 SfxLokHelper::createView(); int nView2 = SfxLokHelper::getView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2; + ScTestViewCallback aView2; // text edit a cell in view #1 SfxLokHelper::setView(nView1); @@ -927,7 +936,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testInsertGraphicInvalidations) CPPUNIT_ASSERT(pViewData); // view - ViewCallback aView; + ScTestViewCallback aView; // we need to paint a tile in the view for triggering the tile invalidation solution int nCanvasWidth = 256; @@ -1377,7 +1386,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testPageDownInvalidation) CPPUNIT_ASSERT(pViewData); int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); SfxLokHelper::setView(nView1); @@ -1422,7 +1431,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testSheetChangeNoInvalidation) CPPUNIT_ASSERT(pView); int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); SfxLokHelper::setView(nView1); @@ -1454,7 +1463,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testSheetChangeNoInvalidation) // we change B1 there should be an invalidation in the second sheet for the // range that depends on it. Because this is a single user document with no // active view on the 2nd sheet this will happen on switching back to sheet 2 - lcl_typeCharsInCell("101", 1, 0, pView, pModelObj); // Type '101' in B1 + typeCharsInCell("101", 1, 0, pView, pModelObj); // Type '101' in B1 aView1.ClearAllInvalids(); pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::PAGEDOWN | KEY_MOD1); @@ -1490,7 +1499,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testInsertDeletePageInvalidation) CPPUNIT_ASSERT(pViewData); int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); SfxLokHelper::setView(nView1); @@ -1531,7 +1540,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testGetRowColumnHeadersInvalidation) CPPUNIT_ASSERT(pViewData); int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); SfxLokHelper::setView(nView1); @@ -1575,7 +1584,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testJumpHorizontallyInvalidation) CPPUNIT_ASSERT(pViewData); int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); SfxLokHelper::setView(nView1); @@ -1599,7 +1608,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testJumpToLastRowInvalidation) CPPUNIT_ASSERT(pViewData); int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); SfxLokHelper::setView(nView1); @@ -1622,14 +1631,14 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testRowColumnHeaders) CPPUNIT_ASSERT(pViewData); // view #1 - ViewCallback aView1; + ScTestViewCallback aView1; int nView1 = SfxLokHelper::getView(); CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); // view #2 SfxLokHelper::createView(); int nView2 = SfxLokHelper::getView(); - ViewCallback aView2; + ScTestViewCallback aView2; pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); // ViewRowColumnHeaders test @@ -1863,13 +1872,13 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testSheetGeometryDataInvariance) CPPUNIT_ASSERT(pViewData); // view #1 - ViewCallback aView1; + ScTestViewCallback aView1; int nView1 = SfxLokHelper::getView(); // view #2 SfxLokHelper::createView(); int nView2 = SfxLokHelper::getView(); - ViewCallback aView2; + ScTestViewCallback aView2; pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); // Try with the default empty document once (nIdx = 0) and then with sheet geometry settings (nIdx = 1) @@ -1987,7 +1996,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testSheetGeometryDataCorrectness) CPPUNIT_ASSERT(pViewData); // view #1 - ViewCallback aView1; + ScTestViewCallback aView1; // with the default empty sheet and test the JSON encoding. OString aGeomDefaultStr = pModelObj->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true, @@ -2013,7 +2022,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testDeleteCellMultilineContent) CPPUNIT_ASSERT(pDocSh); // view #1 - ViewCallback aView1; + ScTestViewCallback aView1; CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); aView1.m_sInvalidateHeader = ""_ostr; @@ -2051,7 +2060,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testPasteIntoWrapTextCell) ScViewData* pViewData = ScDocShell::GetViewData(); CPPUNIT_ASSERT(pViewData); - ViewCallback aView; + ScTestViewCallback aView; CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); ScTabViewShell* pView = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); @@ -2128,7 +2137,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testSortAscendingDescending) ScModelObj* pModelObj = createDoc("sort-range.ods"); ScDocument* pDoc = pModelObj->GetDocument(); - ViewCallback aView; + ScTestViewCallback aView; // select the values in the first column pModelObj->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, 551, 129, 1, MOUSE_LEFT, 0); @@ -2186,19 +2195,19 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testAutoInputStringBlock) pDoc->SetString(ScAddress(0, 7, 0), u"ZZZ"_ustr); // A8 ScAddress aA1(0, 0, 0); - lcl_typeCharsInCell("X", aA1.Col(), aA1.Row(), pView, pModelObj); // Type 'X' in A1 + typeCharsInCell("X", aA1.Col(), aA1.Row(), pView, pModelObj); // Type 'X' in A1 CPPUNIT_ASSERT_EQUAL_MESSAGE("A1 should autocomplete", u"XYZ"_ustr, pDoc->GetString(aA1)); ScAddress aA3(0, 2, 0); // Adjacent to the string "superblock" A4:A8 - lcl_typeCharsInCell("X", aA3.Col(), aA3.Row(), pView, pModelObj); // Type 'X' in A3 + typeCharsInCell("X", aA3.Col(), aA3.Row(), pView, pModelObj); // Type 'X' in A3 CPPUNIT_ASSERT_EQUAL_MESSAGE("A3 should autocomplete", u"XYZ"_ustr, pDoc->GetString(aA3)); ScAddress aA9(0, 8, 0); // Adjacent to the string "superblock" A4:A8 - lcl_typeCharsInCell("X", aA9.Col(), aA9.Row(), pView, pModelObj); // Type 'X' in A9 + typeCharsInCell("X", aA9.Col(), aA9.Row(), pView, pModelObj); // Type 'X' in A9 CPPUNIT_ASSERT_EQUAL_MESSAGE("A9 should autocomplete", u"XYZ"_ustr, pDoc->GetString(aA9)); ScAddress aA11(0, 10, 0); - lcl_typeCharsInCell("X", aA11.Col(), aA11.Row(), pView, pModelObj); // Type 'X' in A11 + typeCharsInCell("X", aA11.Col(), aA11.Row(), pView, pModelObj); // Type 'X' in A11 CPPUNIT_ASSERT_EQUAL_MESSAGE("A11 should autocomplete", u"XYZ"_ustr, pDoc->GetString(aA11)); } @@ -2220,31 +2229,31 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testAutoInputExactMatch) pDoc->SetString(ScAddress(0, 6, 0), u"Castle"_ustr); // A7 ScAddress aA8(0, 7, 0); - lcl_typeCharsInCell("S", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "S" in A8 + typeCharsInCell("S", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "S" in A8 // Should show the partial completion "i". CPPUNIT_ASSERT_EQUAL_MESSAGE("1: A8 should have partial completion Si", u"Si"_ustr, pDoc->GetString(aA8)); - lcl_typeCharsInCell("Si", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "Si" in A8 + typeCharsInCell("Si", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "Si" in A8 // Should not show any suggestions. CPPUNIT_ASSERT_EQUAL_MESSAGE("2: A8 should not show suggestions", u"Si"_ustr, pDoc->GetString(aA8)); - lcl_typeCharsInCell("Sim", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "Sim" in A8 + typeCharsInCell("Sim", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "Sim" in A8 // Should autocomplete to "Simple" which is the only match. CPPUNIT_ASSERT_EQUAL_MESSAGE("3: A8 should autocomplete", u"Simple"_ustr, pDoc->GetString(aA8)); - lcl_typeCharsInCell("Sin", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "Sin" in A8 + typeCharsInCell("Sin", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "Sin" in A8 // Should autocomplete to "Sing" which is the only match. CPPUNIT_ASSERT_EQUAL_MESSAGE("4: A8 should autocomplete", u"Sing"_ustr, pDoc->GetString(aA8)); - lcl_typeCharsInCell("C", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "C" in A8 + typeCharsInCell("C", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "C" in A8 // Should show the partial completion "as". CPPUNIT_ASSERT_EQUAL_MESSAGE("5: A8 should have partial completion Cas", u"Cas"_ustr, pDoc->GetString(aA8)); - lcl_typeCharsInCell("Cast", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "Cast" in A8 + typeCharsInCell("Cast", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "Cast" in A8 // Should autocomplete to "Castle" which is the only match. CPPUNIT_ASSERT_EQUAL_MESSAGE("6: A8 should autocomplete", u"Castle"_ustr, pDoc->GetString(aA8)); - lcl_typeCharsInCell("T", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "T" in A8 + typeCharsInCell("T", aA8.Col(), aA8.Row(), pView, pModelObj); // Type "T" in A8 // Should autocomplete to "Time" which is the only match. CPPUNIT_ASSERT_EQUAL_MESSAGE("7: A8 should autocomplete", u"Time"_ustr, pDoc->GetString(aA8)); } @@ -2256,7 +2265,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testEditCursorBounds) ScModelObj* pModelObj = createDoc("empty.ods"); ScDocument* pDoc = pModelObj->GetDocument(); - ViewCallback aView; + ScTestViewCallback aView; ScTabViewShell* pView = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); CPPUNIT_ASSERT(pView); comphelper::LibreOfficeKit::setViewIdForVisCursorInvalidation(true); @@ -2299,7 +2308,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testTextSelectionBounds) ScModelObj* pModelObj = createDoc("empty.ods"); ScDocument* pDoc = pModelObj->GetDocument(); - ViewCallback aView; + ScTestViewCallback aView; ScTabViewShell* pView = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); CPPUNIT_ASSERT(pView); comphelper::LibreOfficeKit::setViewIdForVisCursorInvalidation(true); @@ -2381,7 +2390,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testSheetViewDataCrash) CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testTextBoxInsert) { createDoc("empty.ods"); - ViewCallback aView1; + ScTestViewCallback aView1; // insert textbox uno::Sequence<beans::PropertyValue> aArgs( @@ -2407,7 +2416,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCommentCellCopyPaste) { ScModelObj* pModelObj = createDoc("empty.ods"); - ViewCallback aView; + ScTestViewCallback aView; int nView = SfxLokHelper::getView(); SfxLokHelper::setView(nView); @@ -2415,7 +2424,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCommentCellCopyPaste) ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); CPPUNIT_ASSERT(pTabViewShell); - lcl_typeCharsInCell("ABC", 0, 0, pTabViewShell, pModelObj); // Type "ABC" in A1 + typeCharsInCell("ABC", 0, 0, pTabViewShell, pModelObj); // Type "ABC" in A1 pTabViewShell->SetCursor(1, 1); @@ -2499,7 +2508,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testInvalidEntrySave) CPPUNIT_ASSERT(pModelObj); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); const ScDocument* pDoc = pModelObj->GetDocument(); - ViewCallback aView; + ScTestViewCallback aView; int nView = SfxLokHelper::getView(); SfxLokHelper::setView(nView); @@ -2510,7 +2519,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testInvalidEntrySave) // Type partial date "7/8" of "7/8/2013" that // the validation cell at A8 can accept - lcl_typeCharsInCell("7/8", 0, 7, pTabViewShell, pModelObj, + typeCharsInCell("7/8", 0, 7, pTabViewShell, pModelObj, false /* bInEdit */, false /* bCommit */); // Type "7/8" in A8 uno::Sequence<beans::PropertyValue> aArgs; @@ -2519,7 +2528,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testInvalidEntrySave) CPPUNIT_ASSERT_MESSAGE("Should not be marked modified after save", !pDocSh->IsModified()); // Complete the date in A8 by appending "/2013" and commit. - lcl_typeCharsInCell("/2013", 0, 7, pTabViewShell, pModelObj, + typeCharsInCell("/2013", 0, 7, pTabViewShell, pModelObj, true /* bInEdit */, true /* bCommit */); // This would hang if the date entered "7/8/2013" is not acceptable. @@ -2540,13 +2549,13 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testUndoReordering) // view #1 int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; // view #2 SfxLokHelper::createView(); int nView2 = SfxLokHelper::getView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2; + ScTestViewCallback aView2; // text edit a cell in view #1 SfxLokHelper::setView(nView1); @@ -2601,14 +2610,14 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testUndoReorderingRedo) // view #1 int nView1 = SfxLokHelper::getView(); SfxViewShell* pView1 = SfxViewShell::Current(); - ViewCallback aView1; + ScTestViewCallback aView1; // view #2 SfxLokHelper::createView(); int nView2 = SfxLokHelper::getView(); SfxViewShell* pView2 = SfxViewShell::Current(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2; + ScTestViewCallback aView2; // text edit a cell in view #1 SfxLokHelper::setView(nView1); @@ -2690,13 +2699,13 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testUndoReorderingMulti) // view #1 int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; // view #2 SfxLokHelper::createView(); int nView2 = SfxLokHelper::getView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2; + ScTestViewCallback aView2; // text edit a cell in view #1 SfxLokHelper::setView(nView1); @@ -2756,12 +2765,12 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testGetViewRenderState) ScModelObj* pModelObj = createDoc("empty.ods"); int nFirstViewId = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; CPPUNIT_ASSERT_EQUAL("S;Default"_ostr, pModelObj->getViewRenderState()); // Create a second view SfxLokHelper::createView(); - ViewCallback aView2; + ScTestViewCallback aView2; CPPUNIT_ASSERT_EQUAL("S;Default"_ostr, pModelObj->getViewRenderState()); // Set second view to dark scheme { @@ -2823,7 +2832,7 @@ void testInvalidateOnTextEditWithDifferentZoomLevels::TestBody(const ColRowZoom& sZoomUnoCmd = ".uno:ZoomMinus"; } // view #1 - ViewCallback aView1; + ScTestViewCallback aView1; // set zoom level for (int i = 0; i < nZoomLevel; ++i) dispatchCommand(mxComponent, sZoomUnoCmd, {}); @@ -2849,7 +2858,7 @@ void testInvalidateOnTextEditWithDifferentZoomLevels::TestBody(const ColRowZoom& // view #2 SfxLokHelper::createView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); - ViewCallback aView2; + ScTestViewCallback aView2; Scheduler::ProcessEventsToIdle(); auto* pTabViewShell2 = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); CPPUNIT_ASSERT(pTabViewShell2); @@ -2872,9 +2881,9 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testOpenURL) // Given a document that has 2 views: createDoc("empty.ods"); int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; SfxLokHelper::createView(); - ViewCallback aView2; + ScTestViewCallback aView2; // When clicking on a link in view 2, but switching to view 1 before processing async events: ScGlobal::OpenURL(/*aUrl=*/u"http://www.example.com/"_ustr, /*aTarget=*/u""_ustr, @@ -2900,7 +2909,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testInvalidateForSplitPanes) CPPUNIT_ASSERT(pView); // view - ViewCallback aView; + ScTestViewCallback aView; // move way over to the right where BP:20 exists, enough so that rows A and B // would scroll off the page and not be visible, if they were not frozen @@ -2915,7 +2924,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testInvalidateForSplitPanes) aView.m_bInvalidateTiles = false; aView.m_aInvalidations.clear(); - lcl_typeCharsInCell("X", aBP20.Col(), aBP20.Row(), pView, pModelObj); // Type 'X' in A1 + typeCharsInCell("X", aBP20.Col(), aBP20.Row(), pView, pModelObj); // Type 'X' in A1 CPPUNIT_ASSERT(aView.m_bInvalidateTiles); @@ -2952,7 +2961,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testNoInvalidateOnSave) Scheduler::ProcessEventsToIdle(); // track invalidations - ViewCallback aView; + ScTestViewCallback aView; uno::Sequence<beans::PropertyValue> aArgs; dispatchCommand(mxComponent, u".uno:Save"_ustr, aArgs); @@ -2962,60 +2971,6 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testNoInvalidateOnSave) CPPUNIT_ASSERT(!aView.m_bInvalidateTiles); } -void ScTiledRenderingTest::checkSampleInvalidation(const ViewCallback& rView, bool bFullRow) -{ - // we expect invalidations, but that isn't really important - CPPUNIT_ASSERT(rView.m_bInvalidateTiles); - tools::Rectangle aInvalidation; - for (const auto& rRect : rView.m_aInvalidations) - aInvalidation.Union(rRect); - if (!bFullRow) - { - // What matters is that we expect that the invalidation does not extend all the - // way to the max right of the sheet. - // Here we originally got 32212306 and now ~5056 for a single cell case - CPPUNIT_ASSERT_LESSEQUAL(tools::Long(8000), aInvalidation.GetWidth()); - } - else - { - // We expect RTL to continue to invalidate the entire row - // from 0 to end of sheet (see ScDocShell::PostPaint, 'Extend to whole rows'), - // which is different to the adjusted LTR case which - // invalidated the row from left of edited cell to right of end - // of sheet. - CPPUNIT_ASSERT_LESSEQUAL(tools::Long(0), aInvalidation.Left()); - CPPUNIT_ASSERT_EQUAL(tools::Long(32212230), aInvalidation.Right()); - } -} - -void ScTiledRenderingTest::cellInvalidationHelper(ScModelObj* pModelObj, ScTabViewShell* pView, const ScAddress& rAdr, - bool bAddText, bool bFullRow) -{ - // view - ViewCallback aView; - - if (bAddText) - { - // Type "Hello World" in D8, process events to idle and don't commit yet - lcl_typeCharsInCell("Hello World", rAdr.Col(), rAdr.Row(), pView, pModelObj, false, false); - - aView.m_bInvalidateTiles = false; - aView.m_aInvalidations.clear(); - - // commit text and process events to idle - lcl_typeCharsInCell("", rAdr.Col(), rAdr.Row(), pView, pModelObj, true, true); - } - else // DeleteText - { - pView->SetCursor(rAdr.Col(), rAdr.Row()); - pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::DELETE); - pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::DELETE); - Scheduler::ProcessEventsToIdle(); - } - - checkSampleInvalidation(aView, bFullRow); -} - CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCellMinimalInvalidations) { ScAddress aA8(0, 7, 0); @@ -3045,7 +3000,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCellMinimalInvalidations) pView->SetCursor(aA8.Col(), aA8.Row()); Scheduler::ProcessEventsToIdle(); - ViewCallback aView; + ScTestViewCallback aView; dispatchCommand(mxComponent, u".uno:Paste"_ustr, aArgs); Scheduler::ProcessEventsToIdle(); @@ -3089,14 +3044,14 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCellInvalidationDocWithExistingZo int nView1 = SfxLokHelper::getView(); // register to track View #1 invalidations - ViewCallback aView1; + ScTestViewCallback aView1; // Create a View #2 SfxLokHelper::createView(); int nView2 = SfxLokHelper::getView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); // register to track View #1 invalidations - ViewCallback aView2; + ScTestViewCallback aView2; // Set View #2 to initial 100% and generate a paint pModelObj->setClientVisibleArea(tools::Rectangle(0, 0, 19845, 6405)); @@ -3224,9 +3179,9 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testStatusBarLocale) // Given 2 views, the second's locale is set to German: createDoc("empty.ods"); int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; SfxLokHelper::createView(); - ViewCallback aView2; + ScTestViewCallback aView2; SfxViewShell* pView2 = SfxViewShell::Current(); pView2->SetLOKLocale(u"de-DE"_ustr); { @@ -3295,7 +3250,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testLongFirstColumnMouseClick) int y = 1 / nPPTY; // Setup view #1 - ViewCallback aView1; + ScTestViewCallback aView1; // Set client rect to 2000 x 2000 pixels pModelObj->setClientVisibleArea(tools::Rectangle(0, 0, 2000 / nPPTX, 2000 / nPPTY)); Scheduler::ProcessEventsToIdle(); @@ -3323,7 +3278,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testLongFirstColumnMouseClick) // Setup view #2 SfxLokHelper::createView(); int nView2 = SfxLokHelper::getView(); - ViewCallback aView2; + ScTestViewCallback aView2; // Set client rect to 2000 x 2000 pixels pModelObj->setClientVisibleArea(tools::Rectangle(0, 0, 2000 / nPPTX, 2000 / nPPTY)); @@ -3369,7 +3324,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testExtendedAreasDontOverlap) Scheduler::ProcessEventsToIdle(); // register to track View #1 invalidations - ViewCallback aView1; + ScTestViewCallback aView1; // extend to the right and bottom pModelObj->setClientVisibleArea(tools::Rectangle(0, 0, 39750, 12780)); @@ -3421,7 +3376,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testEditShapeText) Bitmap aBitmapBefore = getTile(pModelObj, 4096, 3584, 15360, 7680); // reuse this to type into the active shape edit - lcl_typeCharsInCell("MMMMMMM", 0, 0, pView, pModelObj, true, false); + typeCharsInCell("MMMMMMM", 0, 0, pView, pModelObj, true, false); // Grab a new snapshot of the center of the shape Bitmap aBitmapAfter = getTile(pModelObj, 4096, 3584, 15360, 7680); @@ -3449,7 +3404,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testNumberFormatLocaleMultiUser) ScDocument* pDoc = pModelObj->GetDocument(); int nViewFR = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; SfxViewShell* pViewFR = SfxViewShell::Current(); pViewFR->SetLOKLocale(u"fr-FR"_ustr); @@ -3505,7 +3460,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testLeftOverflowEdit) { comphelper::LibreOfficeKit::setCompatFlag(comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs); ScModelObj* pModelObj = createDoc("right-aligned-with-overflow.ods"); - ViewCallback aView; + ScTestViewCallback aView; // Go to Cell B5000 uno::Sequence<beans::PropertyValue> aPropertyValues = { @@ -3532,7 +3487,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testLeftOverflowEdit) CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testFreezeRowOrColumn) { createDoc("empty.ods"); - ViewCallback aView; + ScTestViewCallback aView; SfxViewShell* pView = SfxViewShell::Current(); // Freeze panes on a column and receive the proper state back @@ -3572,7 +3527,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testFreezeRowOrColumn) CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCursorVisibilityAfterPaste) { ScModelObj* pModelObj = createDoc("empty.ods"); - ViewCallback aView; + ScTestViewCallback aView; SfxLokHelper::createView(); pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); diff --git a/sc/qa/unit/tiledrendering/tiledrendering2.cxx b/sc/qa/unit/tiledrendering/tiledrendering2.cxx index ccf2acd92e51..b3625d3128e6 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering2.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering2.cxx @@ -7,12 +7,19 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "tiledrenderingmodeltestbase.cxx" +#include <sctiledrenderingtest.hxx> #include <com/sun/star/datatransfer/XTransferable2.hpp> #include <comphelper/propertyvalue.hxx> #include <comphelper/propertysequence.hxx> +#include <sfx2/lokhelper.hxx> +#include <vcl/scheduler.hxx> +#include <LibreOfficeKit/LibreOfficeKitEnums.h> + +#include <sctestviewcallback.hxx> +#include <docuno.hxx> +#include <tabvwsh.hxx> using namespace com::sun::star; @@ -20,11 +27,11 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testSidebarLocale) { ScModelObj* pModelObj = createDoc("chart.ods"); int nView1 = SfxLokHelper::getView(); - ViewCallback aView1; + ScTestViewCallback aView1; SfxViewShell* pView1 = SfxViewShell::Current(); pView1->SetLOKLocale(u"en-US"_ustr); SfxLokHelper::createView(); - ViewCallback aView2; + ScTestViewCallback aView2; SfxViewShell* pView2 = SfxViewShell::Current(); pView2->SetLOKLocale(u"de-DE"_ustr); TestLokCallbackWrapper::InitializeSidebar(); @@ -48,7 +55,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCopyMultiSelection) { // Given a document with A1 and A3 as selected cells: ScModelObj* pModelObj = createDoc("multi-selection.ods"); - ViewCallback aView1; + ScTestViewCallback aView1; // Get the center of A3: uno::Sequence<beans::PropertyValue> aPropertyValues = { comphelper::makePropertyValue(u"ToPoint"_ustr, u"$A$3"_ustr), @@ -81,7 +88,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCopyMultiSelection) CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCursorJumpOnFailedSearch) { createDoc("empty.ods"); - ViewCallback aView; + ScTestViewCallback aView; // Go to lower cell uno::Sequence<beans::PropertyValue> aPropertyValues = { @@ -112,7 +119,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testLocaleFormulaSeparator) ScDocument* pDoc = pModelObj->GetDocument(); ScAddress addr(2, 0, 0); - lcl_typeCharsInCell("=subtotal(9,A1:A8", addr.Col(), addr.Row(), pView, pModelObj, false, true); + typeCharsInCell("=subtotal(9,A1:A8", addr.Col(), addr.Row(), pView, pModelObj, false, true); // Without the fix it would fail with // - Expected: 0 // - Actual : Err:508 @@ -123,7 +130,7 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testDecimalSeparatorInfo) { createDoc("decimal-separator.ods"); - ViewCallback aView1; + ScTestViewCallback aView1; // Go to cell A1. uno::Sequence<beans::PropertyValue> aPropertyValues diff --git a/sc/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx b/sc/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx deleted file mode 100644 index 99917ea72ca2..000000000000 --- a/sc/qa/unit/tiledrendering/tiledrenderingmodeltestbase.cxx +++ /dev/null @@ -1,521 +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/. - */ - -#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> -#include <vcl/scheduler.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_textCursorVisible; - 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; - std::string decimalSeparator; - TestLokCallbackWrapper m_callbackWrapper; - - ViewCallback(bool bDeleteListenerOnDestruct = true) - : m_bOwnCursorInvalidated(false) - , m_bViewCursorInvalidated(false) - , m_textCursorVisible(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_VIEW_CURSOR_VISIBLE: - { - boost::property_tree::ptree aTree; - std::stringstream aStream(pPayload); - boost::property_tree::read_json(aStream, aTree); - m_textCursorVisible = aTree.get_child("visible").get_value<std::string>() == "true"; - } - break; - 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; - case LOK_CALLBACK_JSDIALOG: - { - std::stringstream aStream(pPayload); - boost::property_tree::ptree aTree; - boost::property_tree::read_json(aStream, aTree); - if (aTree.get_child("jsontype").get_value<std::string>() == "formulabar") - { - if (aTree.find("data") != aTree.not_found()) - { - if (aTree.get_child("data").find("separator") - != aTree.get_child("data").not_found()) - { - decimalSeparator = aTree.get_child("data") - .get_child("separator") - .get_value<std::string>(); - } - } - } - } - break; - } - } - - void ClearAllInvalids() - { - m_bInvalidateTiles = false; - m_aInvalidations.clear(); - m_aInvalidationsParts.clear(); - m_aInvalidationsMode.clear(); - } -}; - -namespace -{ -void lcl_typeCharsInCell(const std::string& aStr, SCCOL nCol, SCROW nRow, ScTabViewShell* pView, - ScModelObj* pModelObj, bool bInEdit = false, bool bCommit = true) -{ - if (!bInEdit) - pView->SetCursor(nCol, nRow); - - for (const char& cChar : aStr) - { - pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, cChar, 0); - pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, cChar, 0); - Scheduler::ProcessEventsToIdle(); - } - - if (bCommit) - { - pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::RETURN); - pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::RETURN); - Scheduler::ProcessEventsToIdle(); - } -} -} //namespace - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */