diff options
Diffstat (limited to 'desktop/qa/desktop_lib/test_desktop_lib.cxx')
-rw-r--r-- | desktop/qa/desktop_lib/test_desktop_lib.cxx | 1109 |
1 files changed, 791 insertions, 318 deletions
diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index 2a26b04dcfa0..4310e64f25dd 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -11,7 +11,6 @@ #include <memory> #include <string_view> -#include <com/sun/star/frame/Desktop.hpp> #include <com/sun/star/lang/XComponent.hpp> #include <com/sun/star/text/XTextDocument.hpp> #include <com/sun/star/awt/Key.hpp> @@ -21,6 +20,7 @@ #include <com/sun/star/text/TextContentAnchorType.hpp> #include <boost/property_tree/json_parser.hpp> #include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/util/XCloseable.hpp> #include <vcl/scheduler.hxx> #include <vcl/svapp.hxx> @@ -30,16 +30,12 @@ #include <vcl/uitest/uiobject.hxx> #include <comphelper/processfactory.hxx> #include <rtl/math.hxx> -#include <rtl/uri.hxx> -#include <sfx2/app.hxx> #include <sfx2/childwin.hxx> #include <sfx2/lokhelper.hxx> #include <test/unoapi_test.hxx> #include <comphelper/lok.hxx> -#include <comphelper/dispatchcommand.hxx> #include <comphelper/propertysequence.hxx> #include <osl/conditn.hxx> -#include <osl/thread.hxx> #include <svl/srchitem.hxx> #include <LibreOfficeKit/LibreOfficeKitEnums.h> #include <unotools/tempfile.hxx> @@ -51,14 +47,22 @@ #include <comphelper/string.hxx> #include <comphelper/scopeguard.hxx> #include <cairo.h> -#include <config_features.h> +#include <config_fonts.h> #include <config_mpl.h> #include <tools/json_writer.hxx> +#include <o3tl/unit_conversion.hxx> +#include <o3tl/string_view.hxx> #include <lib/init.hxx> #include <svx/svxids.hrc> #include <cppunit/TestAssert.h> +#include <vcl/BitmapTools.hxx> +#include <vcl/filter/PngImageWriter.hxx> +#include <vcl/filter/PDFiumLibrary.hxx> +#include <svtools/colorcfg.hxx> +#include <sal/types.h> +#include <test/lokcallback.hxx> #if USE_TLS_NSS #include <nss.h> @@ -110,28 +114,27 @@ public: comphelper::LibreOfficeKit::setActive(true); UnoApiTest::setUp(); - mxDesktop.set(frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory()))); - SfxApplication::GetOrCreate(); } virtual void tearDown() override { closeDoc(); - UnoApiTest::tearDown(); + // documents are already closed, no need to call UnoApiTest::tearDown + test::BootstrapFixture::tearDown(); comphelper::LibreOfficeKit::setActive(false); } - std::pair<std::unique_ptr<LibLODocument_Impl>, uno::Reference<lang::XComponent>> + std::unique_ptr<LibLODocument_Impl> loadDocImpl(const char* pName, LibreOfficeKitDocumentType eType); private: - std::pair<std::unique_ptr<LibLODocument_Impl>, uno::Reference<lang::XComponent>> + std::unique_ptr<LibLODocument_Impl> loadDocImpl(const char* pName); public: - std::pair<std::unique_ptr<LibLODocument_Impl>, uno::Reference<lang::XComponent>> + std::unique_ptr<LibLODocument_Impl> loadDocUrlImpl(const OUString& rFileURL, LibreOfficeKitDocumentType eType); LibLODocument_Impl* loadDocUrl(const OUString& rFileURL, LibreOfficeKitDocumentType eType); @@ -141,9 +144,8 @@ public: return loadDoc(pName, getDocumentTypeFromName(pName)); } - void closeDoc(std::unique_ptr<LibLODocument_Impl>& loDocument, - uno::Reference<lang::XComponent>& xComponent); - void closeDoc() { closeDoc(m_pDocument, mxComponent); } + void closeDoc(std::unique_ptr<LibLODocument_Impl>& loDocument); + void closeDoc() { closeDoc(m_pDocument); } static void callback(int nType, const char* pPayload, void* pData); void callbackImpl(int nType, const char* pPayload); @@ -156,6 +158,7 @@ public: void testSearchAllNotificationsCalc(); void testPaintTile(); void testSaveAs(); + void testSaveAsJsonOptions(); void testSaveAsCalc(); void testPasteWriter(); void testPasteWriterJPEG(); @@ -167,17 +170,20 @@ public: void testWriterComments(); void testSheetOperations(); void testSheetSelections(); + void testSheetDragDrop(); void testContextMenuCalc(); void testContextMenuWriter(); void testContextMenuImpress(); void testNotificationCompression(); void testTileInvalidationCompression(); void testPartInInvalidation(); + void testBinaryCallback(); void testInput(); void testRedlineWriter(); void testTrackChanges(); void testRedlineCalc(); void testPaintPartTile(); + void testPaintPartTileDifferentSchemes(); #if HAVE_MORE_FONTS void testGetFontSubset(); #endif @@ -190,21 +196,26 @@ public: void testExtractParameter(); void testGetSignatureState_NonSigned(); void testGetSignatureState_Signed(); +#if 0 // broken with system nss on RHEL 7 void testInsertCertificate_DER_ODT(); void testInsertCertificate_PEM_ODT(); void testInsertCertificate_PEM_DOCX(); +#endif void testSignDocument_PEM_PDF(); void testTextSelectionHandles(); void testComplexSelection(); void testSpellcheckerMultiView(); void testDialogPaste(); - void testShowHideDialog(); - void testDialogInput(); void testCalcSaveAs(); void testControlState(); void testMetricField(); void testMultiDocuments(); void testJumpCursor(); + void testRenderSearchResult_WriterNode(); + void testRenderSearchResult_CommonNode(); + void testNoDuplicateTableSelection(); + void testMultiViewTableSelection(); + void testColorPaletteCallback(); void testABI(); CPPUNIT_TEST_SUITE(DesktopLOKTest); @@ -217,6 +228,7 @@ public: CPPUNIT_TEST(testSearchAllNotificationsCalc); CPPUNIT_TEST(testPaintTile); CPPUNIT_TEST(testSaveAs); + CPPUNIT_TEST(testSaveAsJsonOptions); CPPUNIT_TEST(testSaveAsCalc); CPPUNIT_TEST(testPasteWriter); CPPUNIT_TEST(testPasteWriterJPEG); @@ -228,17 +240,20 @@ public: CPPUNIT_TEST(testWriterComments); CPPUNIT_TEST(testSheetOperations); CPPUNIT_TEST(testSheetSelections); + CPPUNIT_TEST(testSheetDragDrop); CPPUNIT_TEST(testContextMenuCalc); CPPUNIT_TEST(testContextMenuWriter); CPPUNIT_TEST(testContextMenuImpress); CPPUNIT_TEST(testNotificationCompression); CPPUNIT_TEST(testTileInvalidationCompression); CPPUNIT_TEST(testPartInInvalidation); + CPPUNIT_TEST(testBinaryCallback); CPPUNIT_TEST(testInput); CPPUNIT_TEST(testRedlineWriter); CPPUNIT_TEST(testTrackChanges); CPPUNIT_TEST(testRedlineCalc); CPPUNIT_TEST(testPaintPartTile); + CPPUNIT_TEST(testPaintPartTileDifferentSchemes); #if HAVE_MORE_FONTS CPPUNIT_TEST(testGetFontSubset); #endif @@ -252,26 +267,30 @@ public: CPPUNIT_TEST(testGetSignatureState_Signed); CPPUNIT_TEST(testGetSignatureState_NonSigned); #if !MPL_HAVE_SUBSET +#if 0 // broken with system nss on RHEL 7 CPPUNIT_TEST(testInsertCertificate_DER_ODT); CPPUNIT_TEST(testInsertCertificate_PEM_ODT); CPPUNIT_TEST(testInsertCertificate_PEM_DOCX); +#endif CPPUNIT_TEST(testSignDocument_PEM_PDF); #endif CPPUNIT_TEST(testTextSelectionHandles); CPPUNIT_TEST(testComplexSelection); CPPUNIT_TEST(testSpellcheckerMultiView); CPPUNIT_TEST(testDialogPaste); - CPPUNIT_TEST(testShowHideDialog); - CPPUNIT_TEST(testDialogInput); CPPUNIT_TEST(testCalcSaveAs); CPPUNIT_TEST(testControlState); CPPUNIT_TEST(testMetricField); CPPUNIT_TEST(testMultiDocuments); CPPUNIT_TEST(testJumpCursor); + CPPUNIT_TEST(testRenderSearchResult_WriterNode); + CPPUNIT_TEST(testRenderSearchResult_CommonNode); + CPPUNIT_TEST(testNoDuplicateTableSelection); + CPPUNIT_TEST(testMultiViewTableSelection); + CPPUNIT_TEST(testColorPaletteCallback); CPPUNIT_TEST(testABI); CPPUNIT_TEST_SUITE_END(); - uno::Reference<lang::XComponent> mxComponent; OString m_aTextSelection; OString m_aTextSelectionStart; OString m_aTextSelectionEnd; @@ -320,7 +339,7 @@ static Control* GetFocusControl(vcl::Window const * pParent) return nullptr; } -std::pair<std::unique_ptr<LibLODocument_Impl>, uno::Reference<lang::XComponent>> +std::unique_ptr<LibLODocument_Impl> DesktopLOKTest::loadDocUrlImpl(const OUString& rFileURL, LibreOfficeKitDocumentType eType) { OUString aService; @@ -342,23 +361,22 @@ DesktopLOKTest::loadDocUrlImpl(const OUString& rFileURL, LibreOfficeKitDocumentT static int nDocumentIdCounter = 0; SfxViewShell::SetCurrentDocId(ViewShellDocId(nDocumentIdCounter)); - uno::Reference<lang::XComponent> xComponent = loadFromDesktop(rFileURL, aService); + mxComponent = loadFromDesktop(rFileURL, aService); - std::unique_ptr<LibLODocument_Impl> pDocument(new LibLODocument_Impl(xComponent, nDocumentIdCounter)); + std::unique_ptr<LibLODocument_Impl> pDocument(new LibLODocument_Impl(mxComponent, nDocumentIdCounter)); ++nDocumentIdCounter; - return std::make_pair(std::move(pDocument), xComponent); + return pDocument; } -std::pair<std::unique_ptr<LibLODocument_Impl>, uno::Reference<lang::XComponent>> +std::unique_ptr<LibLODocument_Impl> DesktopLOKTest::loadDocImpl(const char* pName, LibreOfficeKitDocumentType eType) { - OUString aFileURL; - createFileURL(OUString::createFromAscii(pName), aFileURL); + OUString aFileURL = createFileURL(OUString::createFromAscii(pName)); return loadDocUrlImpl(aFileURL, eType); } -std::pair<std::unique_ptr<LibLODocument_Impl>, uno::Reference<lang::XComponent>> +std::unique_ptr<LibLODocument_Impl> DesktopLOKTest::loadDocImpl(const char* pName) { return loadDocImpl(pName, getDocumentTypeFromName(pName)); @@ -366,18 +384,17 @@ DesktopLOKTest::loadDocImpl(const char* pName) LibLODocument_Impl* DesktopLOKTest::loadDocUrl(const OUString& rFileURL, LibreOfficeKitDocumentType eType) { - std::tie(m_pDocument, mxComponent) = loadDocUrlImpl(rFileURL, eType); + m_pDocument = loadDocUrlImpl(rFileURL, eType); return m_pDocument.get(); } LibLODocument_Impl* DesktopLOKTest::loadDoc(const char* pName, LibreOfficeKitDocumentType eType) { - std::tie(m_pDocument, mxComponent) = loadDocImpl(pName, eType); + m_pDocument = loadDocImpl(pName, eType); return m_pDocument.get(); } -void DesktopLOKTest::closeDoc(std::unique_ptr<LibLODocument_Impl>& pDocument, - uno::Reference<lang::XComponent>& xComponent) +void DesktopLOKTest::closeDoc(std::unique_ptr<LibLODocument_Impl>& pDocument) { if (pDocument) { @@ -385,10 +402,11 @@ void DesktopLOKTest::closeDoc(std::unique_ptr<LibLODocument_Impl>& pDocument, pDocument.reset(); } - if (xComponent.is()) + if (mxComponent.is()) { - closeDocument(xComponent); - xComponent.clear(); + css::uno::Reference<util::XCloseable> xCloseable(mxComponent, css::uno::UNO_QUERY_THROW); + xCloseable->close(false); + mxComponent.clear(); } } @@ -438,7 +456,7 @@ void DesktopLOKTest::callbackImpl(int nType, const char* pPayload) case LOK_CALLBACK_STATE_CHANGED: { OString aPayload(pPayload); - OString aPrefix(".uno:ModifiedStatus="); + OString aPrefix(".uno:ModifiedStatus="_ostr); if (aPayload.startsWith(aPrefix)) { m_bModified = aPayload.copy(aPrefix.getLength()).toBoolean(); @@ -584,12 +602,11 @@ void DesktopLOKTest::testSearchCalc() uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( { - {"SearchItem.SearchString", uno::makeAny(OUString("foo"))}, - {"SearchItem.Backward", uno::makeAny(false)}, - {"SearchItem.Command", uno::makeAny(static_cast<sal_uInt16>(SvxSearchCmd::FIND_ALL))}, + {"SearchItem.SearchString", uno::Any(OUString("foo"))}, + {"SearchItem.Backward", uno::Any(false)}, + {"SearchItem.Command", uno::Any(static_cast<sal_uInt16>(SvxSearchCmd::FIND_ALL))}, })); - comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues); - Scheduler::ProcessEventsToIdle(); + dispatchCommand(mxComponent, ".uno:ExecuteSearch", aPropertyValues); std::vector<OString> aSelections; sal_Int32 nIndex = 0; @@ -615,12 +632,11 @@ void DesktopLOKTest::testSearchAllNotificationsCalc() uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( { - {"SearchItem.SearchString", uno::makeAny(OUString("foo"))}, - {"SearchItem.Backward", uno::makeAny(false)}, - {"SearchItem.Command", uno::makeAny(static_cast<sal_uInt16>(SvxSearchCmd::FIND_ALL))}, + {"SearchItem.SearchString", uno::Any(OUString("foo"))}, + {"SearchItem.Backward", uno::Any(false)}, + {"SearchItem.Command", uno::Any(static_cast<sal_uInt16>(SvxSearchCmd::FIND_ALL))}, })); - comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues); - Scheduler::ProcessEventsToIdle(); + dispatchCommand(mxComponent, ".uno:ExecuteSearch", aPropertyValues); // This was 1, make sure that we get no notifications about selection changes during search. CPPUNIT_ASSERT_EQUAL(0, m_nSelectionBeforeSearchResult); @@ -657,30 +673,49 @@ void DesktopLOKTest::testPaintTile() void DesktopLOKTest::testSaveAs() { LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); - utl::TempFile aTempFile; - aTempFile.EnableKillingFile(); - CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, aTempFile.GetURL().toUtf8().getStr(), "png", nullptr)); + CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, maTempFile.GetURL().toUtf8().getStr(), "png", nullptr)); +} + +void DesktopLOKTest::testSaveAsJsonOptions() +{ + // Given a document with 3 pages: + LibLODocument_Impl* pDocument = loadDoc("3page.odg"); + + // When exporting that document to PDF, skipping the first page: + OString aOptions("{\"PageRange\":{\"type\":\"string\",\"value\":\"2-\"}}"_ostr); + CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, maTempFile.GetURL().toUtf8().getStr(), "pdf", aOptions.getStr())); + + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + return; + + // Then make sure the resulting PDF has 2 pages: + std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument + = parsePDFExport(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 + // - Actual : 3 + // i.e. FilterOptions was ignored. + CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount()); } void DesktopLOKTest::testSaveAsCalc() { LibLODocument_Impl* pDocument = loadDoc("search.ods"); - utl::TempFile aTempFile; - aTempFile.EnableKillingFile(); - CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, aTempFile.GetURL().toUtf8().getStr(), "png", nullptr)); + CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, maTempFile.GetURL().toUtf8().getStr(), "png", nullptr)); } void DesktopLOKTest::testPasteWriter() { LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); - OString aText("hello"); + OString aText("hello"_ostr); CPPUNIT_ASSERT(pDocument->pClass->paste(pDocument, "text/plain;charset=utf-8", aText.getStr(), aText.getLength())); pDocument->pClass->postUnoCommand(pDocument, ".uno:SelectAll", nullptr, false); Scheduler::ProcessEventsToIdle(); char* pText = pDocument->pClass->getTextSelection(pDocument, "text/plain;charset=utf-8", nullptr); - CPPUNIT_ASSERT_EQUAL(OString("hello"), OString(pText)); + CPPUNIT_ASSERT_EQUAL("hello"_ostr, OString(pText)); free(pText); // textt/plain should be rejected. @@ -691,7 +726,7 @@ void DesktopLOKTest::testPasteWriter() // Overwrite doc contents with a HTML paste. pDocument->pClass->postUnoCommand(pDocument, ".uno:SelectAll", nullptr, false); Scheduler::ProcessEventsToIdle(); - OString aComment("foo <!-- bar --> baz"); + OString aComment("foo <!-- bar --> baz"_ostr); CPPUNIT_ASSERT(pDocument->pClass->paste(pDocument, "text/html", aComment.getStr(), aComment.getLength())); // Check if we have a comment. @@ -711,8 +746,7 @@ void DesktopLOKTest::testPasteWriterJPEG() { LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); - OUString aFileURL; - createFileURL(u"paste.jpg", aFileURL); + OUString aFileURL = createFileURL(u"paste.jpg"); std::ifstream aImageStream(aFileURL.toUtf8().copy(strlen("file://")).getStr()); std::vector<char> aImageContents((std::istreambuf_iterator<char>(aImageStream)), std::istreambuf_iterator<char>()); @@ -731,9 +765,9 @@ void DesktopLOKTest::testPasteWriterJPEG() uno::Reference<lang::XComponent>(xShape, uno::UNO_QUERY_THROW)->dispose(); uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( { - {"AnchorType", uno::makeAny(static_cast<sal_uInt16>(text::TextContentAnchorType_AT_CHARACTER))}, + {"AnchorType", uno::Any(static_cast<sal_uInt16>(text::TextContentAnchorType_AT_CHARACTER))}, })); - comphelper::dispatchCommand(".uno:Paste", aPropertyValues); + dispatchCommand(mxComponent, ".uno:Paste", aPropertyValues); xShape.set(xDrawPage->getByIndex(0), uno::UNO_QUERY); // This was text::TextContentAnchorType_AS_CHARACTER, AnchorType argument was ignored. CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER, xShape->getPropertyValue("AnchorType").get<text::TextContentAnchorType>()); @@ -816,14 +850,14 @@ void DesktopLOKTest::testRowColumnHeaders() bool bNotEnoughHeaders = true; for (const boost::property_tree::ptree::value_type& rValue : aTree.get_child("rows")) { - sal_Int32 nSize = OString(rValue.second.get<std::string>("size").c_str()).toInt32(); - nSize *= 15; /* TWIPS_PER_PIXEL */ - OString aText(rValue.second.get<std::string>("text").c_str()); + sal_Int32 nSize = o3tl::toInt32(rValue.second.get<std::string>("size")); + nSize = o3tl::convert(nSize, o3tl::Length::px, o3tl::Length::twip); + OString aText(rValue.second.get<std::string>("text")); if (bFirstHeader) { CPPUNIT_ASSERT(nSize <= nY); - CPPUNIT_ASSERT_EQUAL(OString("10"), aText); + CPPUNIT_ASSERT_EQUAL("10"_ostr, aText); bFirstHeader = false; } else @@ -845,13 +879,13 @@ void DesktopLOKTest::testRowColumnHeaders() bNotEnoughHeaders = true; for (const boost::property_tree::ptree::value_type& rValue : aTree.get_child("columns")) { - sal_Int32 nSize = OString(rValue.second.get<std::string>("size").c_str()).toInt32(); - nSize *= 15; /* TWIPS_PER_PIXEL */ - OString aText(rValue.second.get<std::string>("text").c_str()); + sal_Int32 nSize = o3tl::toInt32(rValue.second.get<std::string>("size")); + nSize = o3tl::convert(nSize, o3tl::Length::px, o3tl::Length::twip); + OString aText(rValue.second.get<std::string>("text")); if (bFirstHeader) { CPPUNIT_ASSERT(nSize <= nX); - CPPUNIT_ASSERT_EQUAL(OString("3"), aText); + CPPUNIT_ASSERT_EQUAL("3"_ostr, aText); bFirstHeader = false; } else @@ -895,7 +929,7 @@ void DesktopLOKTest::testHiddenRowHeaders() sal_Int32 nIndex = 0; for (const boost::property_tree::ptree::value_type& rValue : aTree.get_child("rows")) { - sal_Int32 nSize = OString(rValue.second.get<std::string>("size").c_str()).toInt32(); + sal_Int32 nSize = o3tl::toInt32(rValue.second.get<std::string>("size")); if (nIndex++ == 2) { @@ -921,9 +955,9 @@ void DesktopLOKTest::testCellCursor() boost::property_tree::read_json(aStream, aTree); - OString aRectangle(aTree.get<std::string>("commandValues").c_str()); + OString aRectangle(aTree.get<std::string>("commandValues")); // cell cursor geometry + col + row - CPPUNIT_ASSERT_EQUAL(OString("0, 0, 1274, 254, 0, 0"), aRectangle); + CPPUNIT_ASSERT_EQUAL("0, 0, 1274, 254, 0, 0"_ostr, aRectangle); } void DesktopLOKTest::testCommandResult() @@ -953,7 +987,7 @@ void DesktopLOKTest::testCommandResult() m_aCommandResultCondition.wait(aTimeValue); boost::property_tree::ptree aTree; - std::stringstream aStream(m_aCommandResult.getStr()); + std::stringstream aStream((std::string(m_aCommandResult))); boost::property_tree::read_json(aStream, aTree); CPPUNIT_ASSERT_EQUAL(std::string(".uno:Bold"), aTree.get_child("commandName").get_value<std::string>()); @@ -1042,7 +1076,7 @@ void DesktopLOKTest::testSheetOperations() Scheduler::ProcessEventsToIdle(); CPPUNIT_ASSERT_EQUAL(6, pDocument->pClass->getParts(pDocument)); - std::vector<OString> aExpected = { "FirstSheet", "Renamed", "Sheet3", "Sheet4", "Sheet5", "LastSheet" }; + std::vector<OString> aExpected = { "FirstSheet"_ostr, "Renamed"_ostr, "Sheet3"_ostr, "Sheet4"_ostr, "Sheet5"_ostr, "LastSheet"_ostr }; for (int i = 0; i < 6; ++i) { char* pPartName = pDocument->pClass->getPartName(pDocument, i); @@ -1101,11 +1135,11 @@ void DesktopLOKTest::testSheetSelections() char* pCopiedContent = pDocument->pClass->getTextSelection(pDocument, nullptr, &pUsedMimeType); std::vector<long> aExpected = {5, 6, 7, 8, 9}; std::istringstream iss(pCopiedContent); - for (size_t i = 0; i < aExpected.size(); i++) + for (const long nIndex : aExpected) { std::string token; iss >> token; - CPPUNIT_ASSERT_EQUAL(aExpected[i], strtol(token.c_str(), nullptr, 10)); + CPPUNIT_ASSERT_EQUAL(nIndex, strtol(token.c_str(), nullptr, 10)); } free(pUsedMimeType); @@ -1115,20 +1149,6 @@ void DesktopLOKTest::testSheetSelections() /* * Check if clicking inside the selection deselects the whole selection */ - int const row10 = 2400; - // Select starting from row5, col1 to row10, col5 - pDocument->pClass->postMouseEvent(pDocument, - LOK_MOUSEEVENT_MOUSEBUTTONDOWN, - col1, row5, - 1, 1, 0); - pDocument->pClass->postMouseEvent(pDocument, - LOK_MOUSEEVENT_MOUSEMOVE, - col5, row5, - 1, 1, 0); - pDocument->pClass->postMouseEvent(pDocument, - LOK_MOUSEEVENT_MOUSEBUTTONUP, - col5, row10, - 1, 1, 0); // Click at row5, col4 pDocument->pClass->postMouseEvent(pDocument, @@ -1148,11 +1168,11 @@ void DesktopLOKTest::testSheetSelections() char* pCopiedContent = pDocument->pClass->getTextSelection(pDocument, nullptr, &pUsedMimeType); std::vector<long> aExpected = { 8 }; std::istringstream iss(pCopiedContent); - for (size_t i = 0; i < aExpected.size(); i++) + for (const long nIndex : aExpected) { std::string token; iss >> token; - CPPUNIT_ASSERT_EQUAL(aExpected[i], strtol(token.c_str(), nullptr, 10)); + CPPUNIT_ASSERT_EQUAL(nIndex, strtol(token.c_str(), nullptr, 10)); } free(pUsedMimeType); @@ -1160,6 +1180,132 @@ void DesktopLOKTest::testSheetSelections() } } +void DesktopLOKTest::testSheetDragDrop() +{ + LibLODocument_Impl* pDocument = loadDoc("sheets.ods", LOK_DOCTYPE_SPREADSHEET); + pDocument->pClass->initializeForRendering(pDocument, nullptr); + pDocument->pClass->registerCallback(pDocument, &DesktopLOKTest::callback, this); + + int row01 = 100; + int col01 = 1100; + int col02 = 2200; + int col03 = 3300; + int col05 = 5500; + int col07 = 5700; + + // Select row 01 from column 01 through column 05 + pDocument->pClass->postMouseEvent(pDocument, + LOK_MOUSEEVENT_MOUSEBUTTONDOWN, + col01, row01, + 1, 1, 0); + pDocument->pClass->postMouseEvent(pDocument, + LOK_MOUSEEVENT_MOUSEMOVE, + col02, row01, + 1, 1, 0); + pDocument->pClass->postMouseEvent(pDocument, + LOK_MOUSEEVENT_MOUSEMOVE, + col05, row01, + 1, 1, 0); + pDocument->pClass->postMouseEvent(pDocument, + LOK_MOUSEEVENT_MOUSEBUTTONUP, + col05, row01, + 1, 1, 0); + + Scheduler::ProcessEventsToIdle(); + { + SfxViewShell* pViewShell = SfxViewShell::Current(); + SfxViewFrame& rViewFrame = pViewShell->GetViewFrame(); + + OUString sValue; + css::uno::Any aValue; + css::util::URL aURL; + std::unique_ptr<SfxPoolItem> pState; + + aURL.Protocol = ".uno:"; + aURL.Complete = ".uno:Address"; + aURL.Path = "Address"; + aURL.Main = ".uno:Address"; + + rViewFrame.GetBindings().QueryState(rViewFrame.GetBindings().QuerySlotId(aURL), pState); + pState->QueryValue(aValue); + aValue >>= sValue; + CPPUNIT_ASSERT_EQUAL(OUString("Sheet5.A1:E1"), sValue); + } + + // Check selection content + { + char* pMimeType = nullptr; + char* pContent = pDocument->pClass->getTextSelection(pDocument, nullptr, &pMimeType); + std::vector<long> aExpected = {1, 2, 3, 4, 5}; + std::istringstream aContent(pContent); + std::string token; + for (const long nIndex : aExpected) + { + aContent >> token; + CPPUNIT_ASSERT_EQUAL(nIndex, strtol(token.c_str(), nullptr, 10)); + } + + free(pMimeType); + free(pContent); + } + + // drag and drop + pDocument->pClass->postMouseEvent(pDocument, + LOK_MOUSEEVENT_MOUSEBUTTONDOWN, + col01, row01, + 1, 1, 0); + pDocument->pClass->postMouseEvent(pDocument, + LOK_MOUSEEVENT_MOUSEMOVE, + col02, row01, + 1, 1, 0); + pDocument->pClass->postMouseEvent(pDocument, + LOK_MOUSEEVENT_MOUSEMOVE, + col03, row01, + 1, 1, 0); + pDocument->pClass->postMouseEvent(pDocument, + LOK_MOUSEEVENT_MOUSEBUTTONUP, + col07, row01, + 1, 1, 0); + + Scheduler::ProcessEventsToIdle(); + { + SfxViewShell* pViewShell = SfxViewShell::Current(); + SfxViewFrame& rViewFrame = pViewShell->GetViewFrame(); + + OUString sValue; + css::uno::Any aValue; + css::util::URL aURL; + std::unique_ptr<SfxPoolItem> pState; + + aURL.Protocol = ".uno:"; + aURL.Complete = ".uno:Address"; + aURL.Path = "Address"; + aURL.Main = ".uno:Address"; + + rViewFrame.GetBindings().QueryState(rViewFrame.GetBindings().QuerySlotId(aURL), pState); + pState->QueryValue(aValue); + aValue >>= sValue; + CPPUNIT_ASSERT_EQUAL(OUString("Sheet5.D1:H1"), sValue); + } + + // Check selection content + { + char* pMimeType = nullptr; + char* pContent = pDocument->pClass->getTextSelection(pDocument, nullptr, &pMimeType); + std::vector<long> aExpected = {1, 2, 3, 4, 5}; + std::istringstream aContent(pContent); + std::string token; + for (const long nIndex : aExpected) + { + aContent >> token; + CPPUNIT_ASSERT_EQUAL(nIndex, strtol(token.c_str(), nullptr, 10)); + } + + free(pMimeType); + free(pContent); + } +} + namespace { void verifyContextMenuStructure(boost::property_tree::ptree& aRoot) @@ -1292,7 +1438,7 @@ void DesktopLOKTest::testContextMenuCalc() // Remove hyperlink is disabled { - boost::optional<boost::property_tree::ptree> aMenuItem = getContextMenuItem(aMenu.get(), ".uno:DeleteShapeHyperlink"); + boost::optional<boost::property_tree::ptree> aMenuItem = getContextMenuItem(aMenu.get(), ".uno:RemoveHyperlink"); CPPUNIT_ASSERT(aMenuItem); boost::optional<boost::property_tree::ptree&> aEnabled = aMenuItem.get().get_child_optional("enabled"); @@ -1533,38 +1679,39 @@ void DesktopLOKTest::testNotificationCompression() LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); - - handler->queue(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, ""); // 0 - handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15, 25, 15, 10"); // Superseded. - handler->queue(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, ""); // Should be dropped. - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15, 25, 15, 10"); // 1 - handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15, 25, 15, 10"); // Should be dropped. - handler->queue(LOK_CALLBACK_TEXT_SELECTION, ""); // Superseded. - handler->queue(LOK_CALLBACK_STATE_CHANGED, ""); // 2 - handler->queue(LOK_CALLBACK_STATE_CHANGED, ".uno:Bold"); // 3 - handler->queue(LOK_CALLBACK_STATE_CHANGED, ""); // 4 - handler->queue(LOK_CALLBACK_MOUSE_POINTER, "text"); // 5 - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15, 25, 15, 10"); // Should be dropped. - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15, 25, 15, 10"); // Should be dropped. - handler->queue(LOK_CALLBACK_MOUSE_POINTER, "text"); // Should be dropped. - handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15, 25, 15, 10"); // Superseded. - handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15, 25, 15, 10"); // Superseded. - handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15, 25, 15, 10"); // Superseded. - handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15, 25, 15, 10"); // Should be dropped. - handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15, 25, 15, 10"); // Should be dropped. - handler->queue(LOK_CALLBACK_TEXT_SELECTION, ""); // 7 - handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15, 25, 15, 10"); // 8 - handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15, 25, 15, 10"); // 9 - handler->queue(LOK_CALLBACK_CELL_CURSOR, "15, 25, 15, 10"); // 10 - handler->queue(LOK_CALLBACK_CURSOR_VISIBLE, ""); // 11 - handler->queue(LOK_CALLBACK_CELL_CURSOR, "15, 25, 15, 10"); // Should be dropped. - handler->queue(LOK_CALLBACK_CELL_FORMULA, "blah"); // 12 - handler->queue(LOK_CALLBACK_SET_PART, "1"); // 13 - handler->queue(LOK_CALLBACK_STATE_CHANGED, ".uno:AssignLayout=20"); // Superseded - handler->queue(LOK_CALLBACK_CURSOR_VISIBLE, ""); // Should be dropped. - handler->queue(LOK_CALLBACK_CELL_FORMULA, "blah"); // Should be dropped. - handler->queue(LOK_CALLBACK_SET_PART, "1"); // Should be dropped. - handler->queue(LOK_CALLBACK_STATE_CHANGED, ".uno:AssignLayout=1"); // 14 + handler->setViewId(SfxLokHelper::getView()); + + handler->queue(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, ""_ostr); // 0 + handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15, 25, 15, 10"_ostr); // Superseded. + handler->queue(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, ""_ostr); // Should be dropped. + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15, 25, 15, 10"_ostr); // 1 + handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15, 25, 15, 10"_ostr); // Should be dropped. + handler->queue(LOK_CALLBACK_TEXT_SELECTION, ""_ostr); // Superseded. + handler->queue(LOK_CALLBACK_STATE_CHANGED, ""_ostr); // 2 + handler->queue(LOK_CALLBACK_STATE_CHANGED, ".uno:Bold"_ostr); // 3 + handler->queue(LOK_CALLBACK_STATE_CHANGED, ""_ostr); // 4 + handler->queue(LOK_CALLBACK_MOUSE_POINTER, "text"_ostr); // 5 + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15, 25, 15, 10"_ostr); // Should be dropped. + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15, 25, 15, 10"_ostr); // Should be dropped. + handler->queue(LOK_CALLBACK_MOUSE_POINTER, "text"_ostr); // Should be dropped. + handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15, 25, 15, 10"_ostr); // Superseded. + handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15, 25, 15, 10"_ostr); // Superseded. + handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15, 25, 15, 10"_ostr); // Superseded. + handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15, 25, 15, 10"_ostr); // Should be dropped. + handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15, 25, 15, 10"_ostr); // Should be dropped. + handler->queue(LOK_CALLBACK_TEXT_SELECTION, ""_ostr); // 7 + handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15, 25, 15, 10"_ostr); // 8 + handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15, 25, 15, 10"_ostr); // 9 + handler->queue(LOK_CALLBACK_CELL_CURSOR, "15, 25, 15, 10"_ostr); // 10 + handler->queue(LOK_CALLBACK_CURSOR_VISIBLE, ""_ostr); // 11 + handler->queue(LOK_CALLBACK_CELL_CURSOR, "15, 25, 15, 10"_ostr); // Should be dropped. + handler->queue(LOK_CALLBACK_CELL_FORMULA, "blah"_ostr); // 12 + handler->queue(LOK_CALLBACK_SET_PART, "1"_ostr); // 13 + handler->queue(LOK_CALLBACK_STATE_CHANGED, ".uno:AssignLayout=20"_ostr); // Superseded + handler->queue(LOK_CALLBACK_CURSOR_VISIBLE, ""_ostr); // Should be dropped. + handler->queue(LOK_CALLBACK_CELL_FORMULA, "blah"_ostr); // Should be dropped. + handler->queue(LOK_CALLBACK_SET_PART, "1"_ostr); // Should be dropped. + handler->queue(LOK_CALLBACK_STATE_CHANGED, ".uno:AssignLayout=1"_ostr); // 14 Scheduler::ProcessEventsToIdle(); @@ -1628,12 +1775,13 @@ void DesktopLOKTest::testTileInvalidationCompression() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-100, -50, 500, 650, 0"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, 0"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "100, 100, 200, 200, 0"); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0, 0"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0, 0"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-100, -50, 500, 650, 0, 0"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, 0, 0"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "100, 100, 200, 200, 0, 0"_ostr); Scheduler::ProcessEventsToIdle(); @@ -1641,19 +1789,20 @@ void DesktopLOKTest::testTileInvalidationCompression() size_t i = 0; CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[i])); - CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 400, 600, 0"), std::get<1>(notifs[i++])); + CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 400, 600, 0, 0"), std::get<1>(notifs[i++])); } // Part Number { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 1"); // Different part - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 0, 0, 2"); // Invalid - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-121, -121, 200, 200, 0"); // Inside first - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, 1"); // Invalid + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0, 0"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 1, 0"_ostr); // Different part + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 0, 0, 2, 0"_ostr); // Invalid + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-121, -121, 200, 200, 0, 0"_ostr); // Inside first + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, 1, 0"_ostr); // Invalid Scheduler::ProcessEventsToIdle(); @@ -1661,25 +1810,26 @@ void DesktopLOKTest::testTileInvalidationCompression() size_t i = 0; CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[i])); - CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 200, 200, 1"), std::get<1>(notifs[i++])); + CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 200, 200, 1, 0"), std::get<1>(notifs[i++])); CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[i])); - CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 239, 239, 0"), std::get<1>(notifs[i++])); + CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 239, 239, 0, 0"), std::get<1>(notifs[i++])); } // All Parts { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0"); // 0 - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 1"); // 1: Different part - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 0, 0, -1"); // Invalid - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-121, -121, 200, 200, -1"); // 0: All parts - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, -1"); // Invalid - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-100, -100, 1200, 1200, -1"); // 0: All parts - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 3"); // Overlapped - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "1000, 1000, 1239, 1239, 2"); // 1: Unique region + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0, 0"_ostr); // 0 + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 1, 0"_ostr); // 1: Different part + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 0, 0, -1, 0"_ostr); // Invalid + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-121, -121, 200, 200, -1, 0"_ostr); // 0: All parts + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, -1, 0"_ostr); // Invalid + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-100, -100, 1200, 1200, -1, 0"_ostr); // 0: All parts + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 3, 0"_ostr); // Overlapped + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "1000, 1000, 1239, 1239, 2, 0"_ostr); // 1: Unique region Scheduler::ProcessEventsToIdle(); @@ -1687,25 +1837,26 @@ void DesktopLOKTest::testTileInvalidationCompression() size_t i = 0; CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[i])); - CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 1100, 1100, -1"), std::get<1>(notifs[i++])); + CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 1100, 1100, -1, 0"), std::get<1>(notifs[i++])); CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[i])); - CPPUNIT_ASSERT_EQUAL(std::string("1000, 1000, 1239, 1239, 2"), std::get<1>(notifs[i++])); + CPPUNIT_ASSERT_EQUAL(std::string("1000, 1000, 1239, 1239, 2, 0"), std::get<1>(notifs[i++])); } // All Parts (partial) { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 0"); // 0 - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 100, 100, 1"); // 1: Different part - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 0, 0, -1"); // Invalid - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "150, 150, 50, 50, -1"); // 2: All-parts - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, -1"); // Invalid - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "150, 150, 40, 40, 3"); // Overlapped w/ 2 - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 4"); // 3: Unique - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "1000, 1000, 1239, 1239, 1"); // 4: Unique + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 0, 0"_ostr); // 0 + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 100, 100, 1, 0"_ostr); // 1: Different part + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 0, 0, -1, 0"_ostr); // Invalid + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "150, 150, 50, 50, -1, 0"_ostr); // 2: All-parts + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, -1, 0"_ostr); // Invalid + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "150, 150, 40, 40, 3, 0"_ostr); // Overlapped w/ 2 + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 4, 0"_ostr); // 3: Unique + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "1000, 1000, 1239, 1239, 1, 0"_ostr); // 4: Unique Scheduler::ProcessEventsToIdle(); @@ -1713,31 +1864,32 @@ void DesktopLOKTest::testTileInvalidationCompression() size_t i = 0; CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[i])); - CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 200, 200, 0"), std::get<1>(notifs[i++])); + CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 200, 200, 0, 0"), std::get<1>(notifs[i++])); CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[i])); - CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 100, 100, 1"), std::get<1>(notifs[i++])); + CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 100, 100, 1, 0"), std::get<1>(notifs[i++])); CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[i])); - CPPUNIT_ASSERT_EQUAL(std::string("150, 150, 50, 50, -1"), std::get<1>(notifs[i++])); + CPPUNIT_ASSERT_EQUAL(std::string("150, 150, 50, 50, -1, 0"), std::get<1>(notifs[i++])); CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[i])); - CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 200, 200, 4"), std::get<1>(notifs[i++])); + CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 200, 200, 4, 0"), std::get<1>(notifs[i++])); CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[i])); - CPPUNIT_ASSERT_EQUAL(std::string("1000, 1000, 1239, 1239, 1"), std::get<1>(notifs[i++])); + CPPUNIT_ASSERT_EQUAL(std::string("1000, 1000, 1239, 1239, 1, 0"), std::get<1>(notifs[i++])); } // Merge with "EMPTY" { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "EMPTY, 0"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 240, 0"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-121, -121, 300, 300, 0"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, 0"); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0, 0"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "EMPTY, 0, 0"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 240, 0, 0"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-121, -121, 300, 300, 0, 0"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, 0, 0"_ostr); Scheduler::ProcessEventsToIdle(); @@ -1745,7 +1897,7 @@ void DesktopLOKTest::testTileInvalidationCompression() size_t i = 0; CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[i])); - CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 1000000000, 1000000000, 0"), std::get<1>(notifs[i++])); + CPPUNIT_ASSERT_EQUAL(std::string("EMPTY, 0, 0"), std::get<1>(notifs[i++])); } } @@ -1756,9 +1908,10 @@ void DesktopLOKTest::testPartInInvalidation() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "20, 10, 20, 10"); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "20, 10, 20, 10"_ostr); Scheduler::ProcessEventsToIdle(); @@ -1771,9 +1924,10 @@ void DesktopLOKTest::testPartInInvalidation() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "40, 10, 20, 10"); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "40, 10, 20, 10"_ostr); Scheduler::ProcessEventsToIdle(); @@ -1790,9 +1944,10 @@ void DesktopLOKTest::testPartInInvalidation() std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10, 0"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "20, 10, 20, 10, 0"); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10, 0, 0"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "20, 10, 20, 10, 0, 0"_ostr); Scheduler::ProcessEventsToIdle(); @@ -1808,9 +1963,10 @@ void DesktopLOKTest::testPartInInvalidation() std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10, 0"); - handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "20, 10, 20, 10, 1"); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10, 0, 0"_ostr); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "20, 10, 20, 10, 1, 0"_ostr); Scheduler::ProcessEventsToIdle(); @@ -1820,40 +1976,65 @@ void DesktopLOKTest::testPartInInvalidation() } } -void DesktopLOKTest::testDialogInput() +static void callbackBinaryCallbackTest(const int type, const char* payload, void* data) +{ + std::vector<std::tuple<int, std::string>>* notifs = static_cast<std::vector<std::tuple<int, std::string>>*>(data); + notifs->emplace_back(type, std::string(payload ? payload : "(nil)")); +} + +void DesktopLOKTest::testBinaryCallback() { - comphelper::LibreOfficeKit::setActive(); LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); - pDocument->pClass->postUnoCommand(pDocument, ".uno:HyperlinkDialog", nullptr, false); - Scheduler::ProcessEventsToIdle(); - SfxViewShell* pViewShell = SfxViewShell::Current(); - pViewShell->GetViewFrame()->GetBindings().Update(); + const tools::Rectangle rect1(Point(10,15),Size(20,25)); + const std::string rect1String(rect1.toString()); + // Verify that using queue() and libreOfficeKitViewInvalidateTilesCallback() has the same result. + { + std::vector<std::tuple<int, std::string>> notifs; + std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackBinaryCallbackTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); - VclPtr<vcl::Window> pWindow(Application::GetActiveTopWindow()); - CPPUNIT_ASSERT(pWindow); + handler->queue(LOK_CALLBACK_INVALIDATE_TILES, OString(rect1String)); - Control* pCtrlFocused = GetFocusControl(pWindow.get()); - CPPUNIT_ASSERT(pCtrlFocused); - CPPUNIT_ASSERT_EQUAL(WindowType::COMBOBOX, pCtrlFocused->GetType()); - CPPUNIT_ASSERT_EQUAL(OUString(""), pCtrlFocused->GetText()); + Scheduler::ProcessEventsToIdle(); - vcl::LOKWindowId nDialogId = pWindow->GetLOKWindowId(); - pDocument->pClass->postWindowExtTextInputEvent(pDocument, nDialogId, LOK_EXT_TEXTINPUT, "wiki."); - pDocument->pClass->postWindowExtTextInputEvent(pDocument, nDialogId, LOK_EXT_TEXTINPUT_END, "wiki."); - pDocument->pClass->removeTextContext(pDocument, nDialogId, 1, 0); - Scheduler::ProcessEventsToIdle(); - CPPUNIT_ASSERT_EQUAL(OUString("wiki"), pCtrlFocused->GetText()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), notifs.size()); + CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[0])); + CPPUNIT_ASSERT_EQUAL(rect1String, std::get<1>(notifs[0])); + } + { + std::vector<std::tuple<int, std::string>> notifs; + std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackBinaryCallbackTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); - static_cast<SystemWindow*>(pWindow.get())->Close(); - Scheduler::ProcessEventsToIdle(); + handler->libreOfficeKitViewInvalidateTilesCallback(&rect1, INT_MIN, 0); + + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), notifs.size()); + CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[0])); + CPPUNIT_ASSERT_EQUAL(rect1String, std::get<1>(notifs[0])); + } + // Verify that the "EMPTY" invalidation gets converted properly. + { + std::vector<std::tuple<int, std::string>> notifs; + std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackBinaryCallbackTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); + + handler->libreOfficeKitViewInvalidateTilesCallback(nullptr, INT_MIN, 0); + + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), notifs.size()); + CPPUNIT_ASSERT_EQUAL(int(LOK_CALLBACK_INVALIDATE_TILES), std::get<0>(notifs[0])); + CPPUNIT_ASSERT_EQUAL(std::string("EMPTY"), std::get<1>(notifs[0])); + } } void DesktopLOKTest::testInput() { // Load a Writer document, enable change recording and press a key. LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); - uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY); Scheduler::ProcessEventsToIdle(); // Get focus & other bits setup. @@ -1881,7 +2062,7 @@ void DesktopLOKTest::testInput() Scheduler::ProcessEventsToIdle(); char* pText = pDocument->pClass->getTextSelection(pDocument, "text/plain;charset=utf-8", nullptr); CPPUNIT_ASSERT(pText != nullptr); - CPPUNIT_ASSERT_EQUAL(OString("far beyond lovely "), OString(pText)); + CPPUNIT_ASSERT_EQUAL("far beyond lovely "_ostr, OString(pText)); free(pText); } @@ -1890,7 +2071,7 @@ void DesktopLOKTest::testRedlineWriter() // Load a Writer document, enable change recording and press a key. LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY); - xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true)); + xPropertySet->setPropertyValue("RecordChanges", uno::Any(true)); pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYINPUT, 't', 0); pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYUP, 't', 0); Scheduler::ProcessEventsToIdle(); @@ -1917,7 +2098,7 @@ void DesktopLOKTest::testRedlineCalc() // Load a Writer document, enable change recording and press a key. LibLODocument_Impl* pDocument = loadDoc("sheets.ods"); uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY); - xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true)); + xPropertySet->setPropertyValue("RecordChanges", uno::Any(true)); pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYINPUT, 't', 0); pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYUP, 't', 0); pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYINPUT, 0, KEY_RETURN); @@ -1947,15 +2128,19 @@ class ViewCallback int mnView; public: OString m_aCellFormula; + int m_nTableSelectionCount; + int m_nColorPaletteCallbackCount = 0; + bool m_bEmptyTableSelection; bool m_bTilesInvalidated; bool m_bZeroCursor; tools::Rectangle m_aOwnCursor; boost::property_tree::ptree m_aCommentCallbackResult; - boost::property_tree::ptree m_aCallbackWindowResult; - bool m_bWindowHidden; + boost::property_tree::ptree m_aColorPaletteCallbackResult; ViewCallback(LibLODocument_Impl* pDocument) : mpDocument(pDocument), + m_nTableSelectionCount(0), + m_bEmptyTableSelection(false), m_bTilesInvalidated(false), m_bZeroCursor(false) { @@ -1990,12 +2175,12 @@ public: if (std::string_view("EMPTY") == pPayload) return; CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), aSeq.getLength()); - m_aOwnCursor.setX(aSeq[0].toInt32()); - m_aOwnCursor.setY(aSeq[1].toInt32()); + m_aOwnCursor.SetLeft(aSeq[0].toInt32()); + m_aOwnCursor.SetTop(aSeq[1].toInt32()); m_aOwnCursor.setWidth(aSeq[2].toInt32()); m_aOwnCursor.setHeight(aSeq[3].toInt32()); - if (m_aOwnCursor.getX() == 0 && m_aOwnCursor.getY() == 0) + if (m_aOwnCursor.Left() == 0 && m_aOwnCursor.Top() == 0) m_bZeroCursor = true; } break; @@ -2007,22 +2192,26 @@ public: m_aCommentCallbackResult = m_aCommentCallbackResult.get_child("comment"); } break; - case LOK_CALLBACK_WINDOW: - { - m_aCallbackWindowResult.clear(); - std::stringstream aStream(pPayload); - boost::property_tree::read_json(aStream, m_aCallbackWindowResult); - - std::string sAction = m_aCallbackWindowResult.get<std::string>("action"); - if (sAction == "hide") - m_bWindowHidden = true; - } break; case LOK_CALLBACK_CELL_FORMULA: { m_aCellFormula = aPayload; } break; + case LOK_CALLBACK_TABLE_SELECTED: + { + m_bEmptyTableSelection = (std::string(pPayload).compare("{ }") == 0); + ++m_nTableSelectionCount; + } + break; + case LOK_CALLBACK_COLOR_PALETTES: + { + m_aColorPaletteCallbackResult.clear(); + std::stringstream aStream(pPayload); + boost::property_tree::read_json(aStream, m_aColorPaletteCallbackResult); + ++m_nColorPaletteCallbackCount; + } + break; } } }; @@ -2057,7 +2246,7 @@ void DesktopLOKTest::testPaintPartTile() // Call paintPartTile() to paint the second part (in whichever view it finds suitable for this). unsigned char pPixels[256 * 256 * 4]; - pDocument->m_pDocumentClass->paintPartTile(pDocument, pPixels, 1, 256, 256, 0, 0, 256, 256); + pDocument->m_pDocumentClass->paintPartTile(pDocument, pPixels, 1, 0, 256, 256, 0, 0, 256, 256); // Type again. Scheduler::ProcessEventsToIdle(); @@ -2070,7 +2259,85 @@ void DesktopLOKTest::testPaintPartTile() //CPPUNIT_ASSERT(aView1.m_bTilesInvalidated); } +void DesktopLOKTest::testPaintPartTileDifferentSchemes() +{ + Color aDarkColor(0x1c, 0x1c, 0x1c); + + // Add a minimal dark scheme + { + svtools::EditableColorConfig aColorConfig; + svtools::ColorConfigValue aValue; + aValue.bIsVisible = true; + aValue.nColor = aDarkColor; + aColorConfig.SetColorValue(svtools::DOCCOLOR, aValue); + aColorConfig.AddScheme(u"Dark"_ustr); + } + + // Add a minimal light scheme + { + svtools::EditableColorConfig aColorConfig; + svtools::ColorConfigValue aValue; + aValue.bIsVisible = true; + aValue.nColor = COL_WHITE; + aColorConfig.SetColorValue(svtools::DOCCOLOR, aValue); + aColorConfig.AddScheme(u"Light"_ustr); + } + + // This view will default to light scheme + LibLODocument_Impl* pDocument = loadDoc("2slides.odp"); + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + int nView1 = pDocument->m_pDocumentClass->getView(pDocument); + + // Create a second view + pDocument->m_pDocumentClass->createView(pDocument); + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + + // Go to the second slide in the second view + pDocument->m_pDocumentClass->setPart(pDocument, 1); + + // Set to dark scheme + { + uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence( + { + { "NewTheme", uno::Any(OUString("Dark")) }, + } + ); + dispatchCommand(mxComponent, ".uno:ChangeTheme", aPropertyValues); + } + + constexpr int nCanvasWidth = 256; + constexpr int nCanvasHeight = 256; + + // Just a random pixel in the middle of the canvas + constexpr int nPixelX = 128; + constexpr int nPixelY = 128 * nCanvasWidth; + + std::array<sal_uInt8, nCanvasWidth * nCanvasHeight * 4> aPixels; + + // Both parts should be painted with dark scheme + pDocument->m_pDocumentClass->paintPartTile(pDocument, aPixels.data(), 0, 0, nCanvasWidth, nCanvasHeight, 0, 0, nCanvasWidth, nCanvasHeight); + Color aPixel(aPixels[nPixelX + nPixelY + 0], aPixels[nPixelX + nPixelY + 1], aPixels[nPixelX + nPixelY + 2]); + CPPUNIT_ASSERT_EQUAL(aDarkColor, aPixel); + + pDocument->m_pDocumentClass->paintPartTile(pDocument, aPixels.data(), 0, 0, nCanvasWidth, nCanvasHeight, 0, 0, nCanvasWidth, nCanvasHeight); + aPixel = Color(aPixels[nPixelX + nPixelY + 0], aPixels[nPixelX + nPixelY + 1], aPixels[nPixelX + nPixelY + 2]); + CPPUNIT_ASSERT_EQUAL(aDarkColor, aPixel); + + // Switch back to first view + pDocument->m_pDocumentClass->setView(pDocument, nView1); + + // Both parts should be painted with light scheme + pDocument->m_pDocumentClass->paintPartTile(pDocument, aPixels.data(), 0, 0, nCanvasWidth, nCanvasHeight, 0, 0, nCanvasWidth, nCanvasHeight); + aPixel = Color(aPixels[nPixelX + nPixelY + 0], aPixels[nPixelX + nPixelY + 1], aPixels[nPixelX + nPixelY + 2]); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, aPixel); + + pDocument->m_pDocumentClass->paintPartTile(pDocument, aPixels.data(), 0, 0, nCanvasWidth, nCanvasHeight, 0, 0, nCanvasWidth, nCanvasHeight); + aPixel = Color(aPixels[nPixelX + nPixelY + 0], aPixels[nPixelX + nPixelY + 1], aPixels[nPixelX + nPixelY + 2]); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, aPixel); +} + #if HAVE_MORE_FONTS +#include <rtl/uri.hxx> void DesktopLOKTest::testGetFontSubset() { LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); @@ -2125,7 +2392,7 @@ void DesktopLOKTest::testCommentsWriter() CPPUNIT_ASSERT(!rComment.second.get<std::string>("text").empty()); // Has a valid iso 8601 date time string css::util::DateTime aDateTime; - OUString aDateTimeString = OUString::createFromAscii(rComment.second.get<std::string>("dateTime").c_str()); + OUString aDateTimeString = OUString::createFromAscii(rComment.second.get<std::string>("dateTime")); CPPUNIT_ASSERT(utl::ISO8601parseDateTime(aDateTimeString, aDateTime)); // This comment has a marked text range @@ -2137,7 +2404,7 @@ void DesktopLOKTest::testCommentsWriter() // This is a reply comment else if (rComment.second.get<std::string>("text") == "Reply to Comment 2") { - CPPUNIT_ASSERT_EQUAL(nComment2Id, rComment.second.get<int>("parent")); + CPPUNIT_ASSERT_EQUAL(nComment2Id, rComment.second.get<int>("parentId")); } } @@ -2173,14 +2440,14 @@ void DesktopLOKTest::testCommentsCalc() { CPPUNIT_ASSERT_EQUAL(std::string("4"), rComment.second.get<std::string>("tab")); CPPUNIT_ASSERT_EQUAL(std::string("Comment1"), rComment.second.get<std::string>("text")); - CPPUNIT_ASSERT_EQUAL(std::string("7650, 3570, 1274, 254"), rComment.second.get<std::string>("cellPos")); + CPPUNIT_ASSERT_EQUAL(std::string("6 14 6 14"), rComment.second.get<std::string>("cellRange")); } break; case 1: { CPPUNIT_ASSERT_EQUAL(std::string("4"), rComment.second.get<std::string>("tab")); CPPUNIT_ASSERT_EQUAL(std::string("Comment2"), rComment.second.get<std::string>("text")); - CPPUNIT_ASSERT_EQUAL(std::string("8925, 4335, 1274, 254"), rComment.second.get<std::string>("cellPos")); + CPPUNIT_ASSERT_EQUAL(std::string("7 17 7 17"), rComment.second.get<std::string>("cellRange")); } break; } @@ -2225,7 +2492,7 @@ void DesktopLOKTest::testCommentsImpress() CPPUNIT_ASSERT_EQUAL(std::string("This is comment1"), rComment.second.get<std::string>("text")); CPPUNIT_ASSERT_EQUAL(std::string("LOK User1"), rComment.second.get<std::string>("author")); css::util::DateTime aDateTime; - OUString aDateTimeString = OUString::createFromAscii(rComment.second.get<std::string>("dateTime").c_str()); + OUString aDateTimeString = OUString::createFromAscii(rComment.second.get<std::string>("dateTime")); CPPUNIT_ASSERT(utl::ISO8601parseDateTime(aDateTimeString, aDateTime)); } break; @@ -2235,7 +2502,7 @@ void DesktopLOKTest::testCommentsImpress() CPPUNIT_ASSERT_EQUAL(std::string("This is comment2"), rComment.second.get<std::string>("text")); CPPUNIT_ASSERT_EQUAL(std::string("LOK User2"), rComment.second.get<std::string>("author")); css::util::DateTime aDateTime; - OUString aDateTimeString = OUString::createFromAscii(rComment.second.get<std::string>("dateTime").c_str()); + OUString aDateTimeString = OUString::createFromAscii(rComment.second.get<std::string>("dateTime")); CPPUNIT_ASSERT(utl::ISO8601parseDateTime(aDateTimeString, aDateTime)); } break; @@ -2262,7 +2529,7 @@ void DesktopLOKTest::testCommentsCallbacksWriter() ViewCallback aView2(pDocument); // Add a new comment - OString aCommandArgs("{ \"Text\": { \"type\": \"string\", \"value\": \"Additional comment\" }, \"Author\": { \"type\": \"string\", \"value\": \"LOK User1\" } }"); + OString aCommandArgs("{ \"Text\": { \"type\": \"string\", \"value\": \"Additional comment\" }, \"Author\": { \"type\": \"string\", \"value\": \"LOK User1\" } }"_ostr); pDocument->pClass->postUnoCommand(pDocument, ".uno:InsertAnnotation", aCommandArgs.getStr(), false); Scheduler::ProcessEventsToIdle(); @@ -2279,8 +2546,8 @@ void DesktopLOKTest::testCommentsCallbacksWriter() // We received a LOK_CALLBACK_COMMENT callback with comment 'Add' action and linked to its parent comment CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView1.m_aCommentCallbackResult.get<std::string>("action")); CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView2.m_aCommentCallbackResult.get<std::string>("action")); - CPPUNIT_ASSERT_EQUAL(nCommentId1, aView1.m_aCommentCallbackResult.get<int>("parent")); - CPPUNIT_ASSERT_EQUAL(nCommentId1, aView2.m_aCommentCallbackResult.get<int>("parent")); + CPPUNIT_ASSERT_EQUAL(nCommentId1, aView1.m_aCommentCallbackResult.get<int>("parentId")); + CPPUNIT_ASSERT_EQUAL(nCommentId1, aView2.m_aCommentCallbackResult.get<int>("parentId")); CPPUNIT_ASSERT_EQUAL(std::string("Reply comment"), aView1.m_aCommentCallbackResult.get<std::string>("text")); CPPUNIT_ASSERT_EQUAL(std::string("Reply comment"), aView2.m_aCommentCallbackResult.get<std::string>("text")); int nCommentId2 = aView1.m_aCommentCallbackResult.get<int>("id"); @@ -2294,8 +2561,8 @@ void DesktopLOKTest::testCommentsCallbacksWriter() CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1.m_aCommentCallbackResult.get<std::string>("action")); CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView2.m_aCommentCallbackResult.get<std::string>("action")); // parent is unchanged still - CPPUNIT_ASSERT_EQUAL(nCommentId1, aView1.m_aCommentCallbackResult.get<int>("parent")); - CPPUNIT_ASSERT_EQUAL(nCommentId1, aView2.m_aCommentCallbackResult.get<int>("parent")); + CPPUNIT_ASSERT_EQUAL(nCommentId1, aView1.m_aCommentCallbackResult.get<int>("parentId")); + CPPUNIT_ASSERT_EQUAL(nCommentId1, aView2.m_aCommentCallbackResult.get<int>("parentId")); CPPUNIT_ASSERT_EQUAL(std::string("Edited comment"), aView1.m_aCommentCallbackResult.get<std::string>("text")); CPPUNIT_ASSERT_EQUAL(std::string("Edited comment"), aView2.m_aCommentCallbackResult.get<std::string>("text")); @@ -2318,8 +2585,8 @@ void DesktopLOKTest::testCommentsCallbacksWriter() // We received a LOK_CALLBACK_COMMENT callback with comment 'Add' action and linked to its parent comment CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView1.m_aCommentCallbackResult.get<std::string>("action")); CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView2.m_aCommentCallbackResult.get<std::string>("action")); - CPPUNIT_ASSERT_EQUAL(nCommentId1, aView1.m_aCommentCallbackResult.get<int>("parent")); - CPPUNIT_ASSERT_EQUAL(nCommentId1, aView2.m_aCommentCallbackResult.get<int>("parent")); + CPPUNIT_ASSERT_EQUAL(nCommentId1, aView1.m_aCommentCallbackResult.get<int>("parentId")); + CPPUNIT_ASSERT_EQUAL(nCommentId1, aView2.m_aCommentCallbackResult.get<int>("parentId")); CPPUNIT_ASSERT_EQUAL(std::string("Reply comment again"), aView1.m_aCommentCallbackResult.get<std::string>("text")); CPPUNIT_ASSERT_EQUAL(std::string("Reply comment again"), aView2.m_aCommentCallbackResult.get<std::string>("text")); @@ -2336,7 +2603,7 @@ void DesktopLOKTest::testCommentsCallbacksWriter() namespace { -void addParameter(tools::JsonWriter& rJson, const char* sName, OString const & type, OString const & value) +void addParameter(tools::JsonWriter& rJson, const char* sName, std::string_view type, std::string_view value) { auto testNode = rJson.startNode(sName); rJson.put("type", type); @@ -2359,7 +2626,7 @@ void DesktopLOKTest::testCommentsAddEditDeleteDraw() tools::JsonWriter aJson; addParameter(aJson, "Text", "string", "Comment"); addParameter(aJson, "Author", "string", "LOK User1"); - aCommandArgs = aJson.extractAsOString(); + aCommandArgs = aJson.finishAndGetAsOString(); } pDocument->pClass->postUnoCommand(pDocument, ".uno:InsertAnnotation", aCommandArgs.getStr(), false); @@ -2374,7 +2641,7 @@ void DesktopLOKTest::testCommentsAddEditDeleteDraw() tools::JsonWriter aJson; addParameter(aJson, "Id", "string", OString::number(nCommentId1)); addParameter(aJson, "Text", "string", "Edited comment"); - aCommandArgs = aJson.extractAsOString(); + aCommandArgs = aJson.finishAndGetAsOString(); } pDocument->pClass->postUnoCommand(pDocument, ".uno:EditAnnotation", aCommandArgs.getStr(), false); @@ -2388,7 +2655,7 @@ void DesktopLOKTest::testCommentsAddEditDeleteDraw() { tools::JsonWriter aJson; addParameter(aJson, "Id", "string", OString::number(nCommentId1)); - aCommandArgs = aJson.extractAsOString(); + aCommandArgs = aJson.finishAndGetAsOString(); } pDocument->pClass->postUnoCommand(pDocument, ".uno:DeleteAnnotation", aCommandArgs.getStr(), false); Scheduler::ProcessEventsToIdle(); @@ -2404,10 +2671,10 @@ void DesktopLOKTest::testRunMacro() bool bGoodMacro, bNonExistentMacro; // Tools macros come pre-installed in system share/basic folder, - bGoodMacro = aOffice.m_pOfficeClass->runMacro(&aOffice, OString("macro:///Tools.Debug.ActivateReadOnlyFlag()").getStr()); + bGoodMacro = aOffice.m_pOfficeClass->runMacro(&aOffice, "macro:///Tools.Debug.ActivateReadOnlyFlag()"); CPPUNIT_ASSERT(bGoodMacro); - bNonExistentMacro = aOffice.m_pOfficeClass->runMacro(&aOffice, OString("macro:///I.Am.Not(There)").getStr()); + bNonExistentMacro = aOffice.m_pOfficeClass->runMacro(&aOffice, "macro:///I.Am.Not(There)"); CPPUNIT_ASSERT(!bNonExistentMacro); } @@ -2442,8 +2709,7 @@ void DesktopLOKTest::testExtractParameter() void DesktopLOKTest::readFileIntoByteVector(std::u16string_view sFilename, std::vector<unsigned char> & rByteVector) { rByteVector.clear(); - OUString aURL; - createFileURL(sFilename, aURL); + OUString aURL = createFileURL(sFilename); SvFileStream aStream(aURL, StreamMode::READ); rByteVector.resize(aStream.remainingSize()); aStream.ReadBytes(rByteVector.data(), aStream.remainingSize()); @@ -2491,16 +2757,15 @@ void DesktopLOKTest::testGetSignatureState_NonSigned() CPPUNIT_ASSERT_EQUAL(int(0), nState); } +#if 0 // broken with system nss on RHEL 7 void DesktopLOKTest::testInsertCertificate_DER_ODT() { // Load the document, save it into a temp file and load that file again LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); - utl::TempFile aTempFile; - aTempFile.EnableKillingFile(); - CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, aTempFile.GetURL().toUtf8().getStr(), "odt", nullptr)); + CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, maTempFile.GetURL().toUtf8().getStr(), "odt", nullptr)); closeDoc(); - pDocument = loadDocUrl(aTempFile.GetURL(), LOK_DOCTYPE_TEXT); + pDocument = loadDocUrl(maTempFile.GetURL(), LOK_DOCTYPE_TEXT); Scheduler::ProcessEventsToIdle(); CPPUNIT_ASSERT(mxComponent.is()); @@ -2545,12 +2810,10 @@ void DesktopLOKTest::testInsertCertificate_PEM_ODT() { // Load the document, save it into a temp file and load that file again LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); - utl::TempFile aTempFile; - aTempFile.EnableKillingFile(); - CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, aTempFile.GetURL().toUtf8().getStr(), "odt", nullptr)); + CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, maTempFile.GetURL().toUtf8().getStr(), "odt", nullptr)); closeDoc(); - pDocument = loadDocUrl(aTempFile.GetURL(), LOK_DOCTYPE_TEXT); + pDocument = loadDocUrl(maTempFile.GetURL(), LOK_DOCTYPE_TEXT); Scheduler::ProcessEventsToIdle(); CPPUNIT_ASSERT(mxComponent.is()); @@ -2602,12 +2865,10 @@ void DesktopLOKTest::testInsertCertificate_PEM_DOCX() { // Load the document, save it into a temp file and load that file again LibLODocument_Impl* pDocument = loadDoc("blank_text.docx"); - utl::TempFile aTempFile; - aTempFile.EnableKillingFile(); - CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, aTempFile.GetURL().toUtf8().getStr(), "docx", nullptr)); + CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, maTempFile.GetURL().toUtf8().getStr(), "docx", nullptr)); closeDoc(); - pDocument = loadDocUrl(aTempFile.GetURL(), LOK_DOCTYPE_TEXT); + pDocument = loadDocUrl(maTempFile.GetURL(), LOK_DOCTYPE_TEXT); Scheduler::ProcessEventsToIdle(); CPPUNIT_ASSERT(mxComponent.is()); @@ -2654,13 +2915,12 @@ void DesktopLOKTest::testInsertCertificate_PEM_DOCX() int nState = pDocument->m_pDocumentClass->getSignatureState(pDocument); CPPUNIT_ASSERT_EQUAL(int(5), nState); } +#endif void DesktopLOKTest::testSignDocument_PEM_PDF() { // Load the document, save it into a temp file and load that file again LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); - utl::TempFile aTempFile; - aTempFile.EnableKillingFile(); Scheduler::ProcessEventsToIdle(); CPPUNIT_ASSERT(mxComponent.is()); @@ -2694,7 +2954,7 @@ void DesktopLOKTest::testSignDocument_PEM_PDF() CPPUNIT_ASSERT(bResult); } - CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, aTempFile.GetURL().toUtf8().getStr(), "pdf", nullptr)); + CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, maTempFile.GetURL().toUtf8().getStr(), "pdf", nullptr)); closeDoc(); @@ -2704,7 +2964,7 @@ void DesktopLOKTest::testSignDocument_PEM_PDF() readFileIntoByteVector(u"test-PK-signing.pem", aPrivateKey); LibLibreOffice_Impl aOffice; - bool bResult = aOffice.m_pOfficeClass->signDocument(&aOffice, aTempFile.GetURL().toUtf8().getStr(), + bool bResult = aOffice.m_pOfficeClass->signDocument(&aOffice, maTempFile.GetURL().toUtf8().getStr(), aCertificate.data(), int(aCertificate.size()), aPrivateKey.data(), int(aPrivateKey.size())); @@ -2716,7 +2976,7 @@ void DesktopLOKTest::testTextSelectionHandles() LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); pDocument->pClass->registerCallback(pDocument, &DesktopLOKTest::callback, this); - OString aText("hello"); + OString aText("hello"_ostr); CPPUNIT_ASSERT(pDocument->pClass->paste(pDocument, "text/plain;charset=utf-8", aText.getStr(), aText.getLength())); // select the inserted text @@ -2725,12 +2985,12 @@ void DesktopLOKTest::testTextSelectionHandles() char* pText = pDocument->pClass->getTextSelection(pDocument, "text/plain;charset=utf-8", nullptr); CPPUNIT_ASSERT_EQUAL(aText, OString(pText)); free(pText); - CPPUNIT_ASSERT_EQUAL(OString("1418, 1418, 0, 275"), m_aTextSelectionStart); - CPPUNIT_ASSERT_EQUAL(OString("1898, 1418, 0, 275"), m_aTextSelectionEnd); + CPPUNIT_ASSERT_EQUAL("1418, 1418, 0, 275"_ostr, m_aTextSelectionStart); + CPPUNIT_ASSERT_EQUAL("1898, 1418, 0, 275"_ostr, m_aTextSelectionEnd); // deselect & check - m_aTextSelectionStart = ""; - m_aTextSelectionEnd = ""; + m_aTextSelectionStart = ""_ostr; + m_aTextSelectionEnd = ""_ostr; pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYINPUT, 0, com::sun::star::awt::Key::ESCAPE); Scheduler::ProcessEventsToIdle(); pText = pDocument->pClass->getTextSelection(pDocument, "text/plain;charset=utf-8", nullptr); @@ -2746,8 +3006,8 @@ void DesktopLOKTest::testTextSelectionHandles() pText = pDocument->pClass->getTextSelection(pDocument, "text/plain;charset=utf-8", nullptr); CPPUNIT_ASSERT_EQUAL(aText, OString(pText)); free(pText); - CPPUNIT_ASSERT_EQUAL(OString("1418, 1418, 0, 275"), m_aTextSelectionStart); - CPPUNIT_ASSERT_EQUAL(OString("1898, 1418, 0, 275"), m_aTextSelectionEnd); + CPPUNIT_ASSERT_EQUAL("1418, 1418, 0, 275"_ostr, m_aTextSelectionStart); + CPPUNIT_ASSERT_EQUAL("1898, 1418, 0, 275"_ostr, m_aTextSelectionEnd); } void DesktopLOKTest::testDialogPaste() @@ -2757,7 +3017,7 @@ void DesktopLOKTest::testDialogPaste() Scheduler::ProcessEventsToIdle(); SfxViewShell* pViewShell = SfxViewShell::Current(); - pViewShell->GetViewFrame()->GetBindings().Update(); + pViewShell->GetViewFrame().GetBindings().Update(); VclPtr<vcl::Window> pWindow(Application::GetActiveTopWindow()); CPPUNIT_ASSERT(pWindow); @@ -2775,49 +3035,27 @@ void DesktopLOKTest::testDialogPaste() Scheduler::ProcessEventsToIdle(); } -void DesktopLOKTest::testShowHideDialog() -{ - - LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); - - pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); - ViewCallback aView(pDocument); - - pDocument->pClass->postUnoCommand(pDocument, ".uno:HyperlinkDialog", nullptr, false); - Scheduler::ProcessEventsToIdle(); - - VclPtr<vcl::Window> pWindow(Application::GetActiveTopWindow()); - CPPUNIT_ASSERT(pWindow); - - aView.m_bWindowHidden = false; - - pWindow->Hide(); - Scheduler::ProcessEventsToIdle(); - - CPPUNIT_ASSERT_EQUAL(true, aView.m_bWindowHidden); - - static_cast<SystemWindow*>(pWindow.get())->Close(); - Scheduler::ProcessEventsToIdle(); -} - void DesktopLOKTest::testComplexSelection() { // Start with a blank text file and add contents. LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); - static constexpr OStringLiteral aText("hello world"); + static constexpr OString aText("hello world"_ostr); // Certainly not complex. CPPUNIT_ASSERT_EQUAL(static_cast<int>(LOK_SELTYPE_NONE), pDocument->pClass->getSelectionType(pDocument)); + CPPUNIT_ASSERT_EQUAL(static_cast<int>(LOK_SELTYPE_NONE), pDocument->pClass->getSelectionTypeAndText(pDocument, + "", nullptr, nullptr)); // Paste text. CPPUNIT_ASSERT(pDocument->pClass->paste(pDocument, "text/plain;charset=utf-8", aText.getStr(), aText.getLength())); // No selection. CPPUNIT_ASSERT_EQUAL(static_cast<int>(LOK_SELTYPE_NONE), pDocument->pClass->getSelectionType(pDocument)); + CPPUNIT_ASSERT_EQUAL(static_cast<int>(LOK_SELTYPE_NONE), pDocument->pClass->getSelectionTypeAndText(pDocument, + "", nullptr, nullptr)); // Paste an image. - OUString aFileURL; - createFileURL(u"paste.jpg", aFileURL); + OUString aFileURL = createFileURL(u"paste.jpg"); std::ifstream aImageStream(aFileURL.toUtf8().copy(strlen("file://")).getStr()); std::vector<char> aImageContents((std::istreambuf_iterator<char>(aImageStream)), std::istreambuf_iterator<char>()); CPPUNIT_ASSERT(pDocument->pClass->paste(pDocument, "image/jpeg", aImageContents.data(), aImageContents.size())); @@ -2829,7 +3067,7 @@ void DesktopLOKTest::testComplexSelection() // Export as plain text, we should get only the text part "hello". char* pText = pDocument->pClass->getTextSelection(pDocument, "text/plain;charset=utf-8", nullptr); CPPUNIT_ASSERT(pText != nullptr); - CPPUNIT_ASSERT_EQUAL(OString(aText), OString(pText)); + CPPUNIT_ASSERT_EQUAL(aText, OString(pText)); free(pText); // Export as rtf, we should also get the image. @@ -2848,12 +3086,12 @@ void DesktopLOKTest::testComplexSelection() // We expect this to be complex. CPPUNIT_ASSERT_EQUAL(static_cast<int>(LOK_SELTYPE_COMPLEX), pDocument->pClass->getSelectionType(pDocument)); + CPPUNIT_ASSERT_EQUAL(static_cast<int>(LOK_SELTYPE_COMPLEX), pDocument->pClass->getSelectionTypeAndText(pDocument, + "", nullptr, nullptr)); } void DesktopLOKTest::testCalcSaveAs() { - comphelper::LibreOfficeKit::setActive(); - LibLODocument_Impl* pDocument = loadDoc("sheets.ods"); CPPUNIT_ASSERT(pDocument); @@ -2863,13 +3101,11 @@ void DesktopLOKTest::testCalcSaveAs() Scheduler::ProcessEventsToIdle(); // Save as a new file. - utl::TempFile aTempFile; - aTempFile.EnableKillingFile(); - pDocument->pClass->saveAs(pDocument, aTempFile.GetURL().toUtf8().getStr(), "ods", nullptr); + pDocument->pClass->saveAs(pDocument, maTempFile.GetURL().toUtf8().getStr(), "ods", nullptr); closeDoc(); // Load the new document and verify that the in-flight changes are saved. - pDocument = loadDocUrl(aTempFile.GetURL(), LOK_DOCTYPE_SPREADSHEET); + pDocument = loadDocUrl(maTempFile.GetURL(), LOK_DOCTYPE_SPREADSHEET); CPPUNIT_ASSERT(pDocument); ViewCallback aView(pDocument); @@ -2882,12 +3118,12 @@ void DesktopLOKTest::testCalcSaveAs() pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYUP, 0, KEY_LEFT); Scheduler::ProcessEventsToIdle(); - CPPUNIT_ASSERT_EQUAL(OString("X"), aView.m_aCellFormula); + CPPUNIT_ASSERT_EQUAL("X"_ostr, aView.m_aCellFormula); } void DesktopLOKTest::testSpellcheckerMultiView() { - static constexpr OUStringLiteral aLangISO(u"en-US"); + static constexpr OUString aLangISO(u"en-US"_ustr); SvtSysLocaleOptions aSysLocaleOptions; aSysLocaleOptions.SetLocaleConfigString(aLangISO); aSysLocaleOptions.SetUILocaleConfigString(aLangISO); @@ -2939,9 +3175,7 @@ void DesktopLOKTest::testMultiDocuments() for (int i = 0; i < 3; i++) { // Load a document. - uno::Reference<lang::XComponent> xComponent1; - std::unique_ptr<LibLODocument_Impl> document1; - std::tie(document1, xComponent1) = loadDocImpl("blank_text.odt"); + std::unique_ptr<LibLODocument_Impl> document1 = loadDocImpl("blank_text.odt"); LibLODocument_Impl* pDocument1 = document1.get(); CPPUNIT_ASSERT_EQUAL(1, pDocument1->m_pDocumentClass->getViewsCount(pDocument1)); const int nDocId1 = pDocument1->mnDocumentId; @@ -2970,9 +3204,7 @@ void DesktopLOKTest::testMultiDocuments() CPPUNIT_ASSERT_EQUAL(2, pDocument1->m_pDocumentClass->getViewsCount(pDocument1)); // Load another document. - uno::Reference<lang::XComponent> xComponent2; - std::unique_ptr<LibLODocument_Impl> document2; - std::tie(document2, xComponent2) = loadDocImpl("blank_presentation.odp"); + std::unique_ptr<LibLODocument_Impl> document2 = loadDocImpl("blank_presentation.odp"); LibLODocument_Impl* pDocument2 = document2.get(); CPPUNIT_ASSERT_EQUAL(1, pDocument2->m_pDocumentClass->getViewsCount(pDocument2)); const int nDocId2 = pDocument2->mnDocumentId; @@ -3024,9 +3256,9 @@ void DesktopLOKTest::testMultiDocuments() pDocument2->m_pDocumentClass->destroyView(pDocument2, nDoc2View1); CPPUNIT_ASSERT_EQUAL(1, pDocument2->m_pDocumentClass->getViewsCount(pDocument2)); - closeDoc(document2, xComponent2); + closeDoc(document2); - closeDoc(document1, xComponent1); + closeDoc(document1); } } @@ -3034,12 +3266,13 @@ void DesktopLOKTest::testControlState() { LibLODocument_Impl* pDocument = loadDoc("search.ods"); pDocument->pClass->postUnoCommand(pDocument, ".uno:StarShapes", nullptr, false); + TestLokCallbackWrapper::InitializeSidebar(); Scheduler::ProcessEventsToIdle(); boost::property_tree::ptree aState; SfxViewShell* pViewShell = SfxViewShell::Current(); - pViewShell->GetViewFrame()->GetBindings().Update(); - pViewShell->GetViewFrame()->GetBindings().QueryControlState(SID_ATTR_TRANSFORM_WIDTH, aState); + pViewShell->GetViewFrame().GetBindings().Update(); + pViewShell->GetViewFrame().GetBindings().QueryControlState(SID_ATTR_TRANSFORM_WIDTH, aState); CPPUNIT_ASSERT(!aState.empty()); } @@ -3047,17 +3280,9 @@ void DesktopLOKTest::testMetricField() { LibLODocument_Impl* pDocument = loadDoc("search.ods"); pDocument->pClass->postUnoCommand(pDocument, ".uno:StarShapes", nullptr, false); + SfxChildWindow* pSideBar = TestLokCallbackWrapper::InitializeSidebar(); Scheduler::ProcessEventsToIdle(); - SfxViewShell* pViewShell = SfxViewShell::Current(); - CPPUNIT_ASSERT(pViewShell); - - SfxViewFrame* pViewFrame = pViewShell->GetViewFrame(); - CPPUNIT_ASSERT(pViewFrame); - - SfxChildWindow* pSideBar = pViewFrame->GetChildWindow(SID_SIDEBAR); - CPPUNIT_ASSERT(pSideBar); - vcl::Window* pWin = pSideBar->GetWindow(); CPPUNIT_ASSERT(pWin); @@ -3103,6 +3328,229 @@ void DesktopLOKTest::testJumpCursor() comphelper::LibreOfficeKit::setTiledAnnotations(true); } +void DesktopLOKTest::testRenderSearchResult_WriterNode() +{ + constexpr const bool bDumpBitmap = false; + + LibLODocument_Impl* pDocument = loadDoc("SearchIndexResultTest.odt"); + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + + Scheduler::ProcessEventsToIdle(); + + unsigned char* pBuffer = nullptr; + OString aPayload = + "<indexing>" + "<paragraph node_type=\"writer\" index=\"19\">ABC</paragraph>" + "</indexing>"_ostr; + + int nWidth = 0; + int nHeight = 0; + size_t nByteSize = 0; + + bool bResult = pDocument->m_pDocumentClass->renderSearchResult(pDocument, aPayload.getStr(), &pBuffer, &nWidth, &nHeight, &nByteSize); + + CPPUNIT_ASSERT(bResult); + CPPUNIT_ASSERT(pBuffer); + + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_EQUAL(642, nWidth); + CPPUNIT_ASSERT_EQUAL(561, nHeight); + CPPUNIT_ASSERT_EQUAL(size_t(1440648), nByteSize); + + const sal_uInt8* pD = reinterpret_cast<const sal_uInt8*>(pBuffer); + BitmapEx aBitmap = vcl::bitmap::CreateFromData(pD, nWidth, nHeight, nWidth * 4, /*nBitsPerPixel*/32, true, true); + + if (bDumpBitmap) + { + SvFileStream aStream("~/SearchResultBitmap.png", StreamMode::WRITE | StreamMode::TRUNC); + vcl::PngImageWriter aPNGWriter(aStream); + aPNGWriter.write(aBitmap); + } + CPPUNIT_ASSERT_EQUAL(tools::Long(642), aBitmap.GetSizePixel().Width()); + CPPUNIT_ASSERT_EQUAL(tools::Long(561), aBitmap.GetSizePixel().Height()); + + std::free(pBuffer); +} + +void DesktopLOKTest::testRenderSearchResult_CommonNode() +{ + constexpr const bool bDumpBitmap = false; + + LibLODocument_Impl* pDocument = loadDoc("SearchIndexResultShapeTest.odt"); + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + + Scheduler::ProcessEventsToIdle(); + + unsigned char* pBuffer = nullptr; + OString aPayload = + "<indexing>" + "<paragraph node_type=\"common\" index=\"0\" object_name=\"Shape 1\" />" + "</indexing>"_ostr; + + int nWidth = 0; + int nHeight = 0; + size_t nByteSize = 0; + + bool bResult = pDocument->m_pDocumentClass->renderSearchResult(pDocument, aPayload.getStr(), &pBuffer, &nWidth, &nHeight, &nByteSize); + + CPPUNIT_ASSERT(bResult); + CPPUNIT_ASSERT(pBuffer); + + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_EQUAL(192, nWidth); + CPPUNIT_ASSERT_EQUAL(96, nHeight); + CPPUNIT_ASSERT_EQUAL(size_t(73728), nByteSize); + + const sal_uInt8* pD = reinterpret_cast<const sal_uInt8*>(pBuffer); + BitmapEx aBitmap = vcl::bitmap::CreateFromData(pD, nWidth, nHeight, nWidth * 4, /*nBitsPerPixel*/32, true, true); + + if (bDumpBitmap) + { + SvFileStream aStream("~/SearchResultBitmap.png", StreamMode::WRITE | StreamMode::TRUNC); + vcl::PngImageWriter aPNGWriter(aStream); + aPNGWriter.write(aBitmap); + } + CPPUNIT_ASSERT_EQUAL(tools::Long(192), aBitmap.GetSizePixel().Width()); + CPPUNIT_ASSERT_EQUAL(tools::Long(96), aBitmap.GetSizePixel().Height()); + + std::free(pBuffer); +} + +static void lcl_repeatKeyStroke(LibLODocument_Impl *pDocument, int nCharCode, int nKeyCode, size_t nCount) +{ + for (size_t nCtr = 0; nCtr < nCount; ++nCtr) + { + pDocument->m_pDocumentClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYINPUT, nCharCode, nKeyCode); + pDocument->m_pDocumentClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYUP, nCharCode, nKeyCode); + } +} + +void DesktopLOKTest::testNoDuplicateTableSelection() +{ + LibLODocument_Impl* pDocument = loadDoc("table-selection.odt"); + + // Create view 1. + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + ViewCallback aView1(pDocument); + + lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(1, aView1.m_nTableSelectionCount); + CPPUNIT_ASSERT(aView1.m_bEmptyTableSelection); + + aView1.m_nTableSelectionCount = 0; + // Go to Table1. + lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(1, aView1.m_nTableSelectionCount); + CPPUNIT_ASSERT(!aView1.m_bEmptyTableSelection); + + aView1.m_nTableSelectionCount = 0; + // Move to the last row in Table1. + lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 2); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(0, aView1.m_nTableSelectionCount); + + // Go outside Table1. + lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(1, aView1.m_nTableSelectionCount); + CPPUNIT_ASSERT(aView1.m_bEmptyTableSelection); +} + +void DesktopLOKTest::testMultiViewTableSelection() +{ + LibLODocument_Impl* pDocument = loadDoc("table-selection.odt"); + + // Create view 1. + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + ViewCallback aView1(pDocument); + int nView1 = pDocument->m_pDocumentClass->getView(pDocument); + + // Create view 2. + pDocument->m_pDocumentClass->createView(pDocument); + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + ViewCallback aView2(pDocument); + int nView2 = pDocument->m_pDocumentClass->getView(pDocument); + + // switch to view 1. + pDocument->m_pDocumentClass->setView(pDocument, nView1); + lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(1, aView1.m_nTableSelectionCount); + CPPUNIT_ASSERT_EQUAL(1, aView2.m_nTableSelectionCount); + CPPUNIT_ASSERT(aView1.m_bEmptyTableSelection); + CPPUNIT_ASSERT(aView2.m_bEmptyTableSelection); + + aView1.m_nTableSelectionCount = 0; + aView2.m_nTableSelectionCount = 0; + + pDocument->m_pDocumentClass->setView(pDocument, nView1); + // Go to Table1. + lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(1, aView1.m_nTableSelectionCount); + CPPUNIT_ASSERT_EQUAL(0, aView2.m_nTableSelectionCount); + + aView1.m_nTableSelectionCount = 0; + // Switch to view 2 + pDocument->m_pDocumentClass->setView(pDocument, nView2); + // Go to Table2 in view 2. + lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 7); + Scheduler::ProcessEventsToIdle(); + // View1 should not get any table selection messages. + CPPUNIT_ASSERT_EQUAL(0, aView1.m_nTableSelectionCount); + // View2 will first get table selection of Table1, then empty selection, and finally on 7th down arrow keypress, + // it will get table-selection of Table2. So in total it should get 3 table selections. + CPPUNIT_ASSERT_EQUAL(3, aView2.m_nTableSelectionCount); + CPPUNIT_ASSERT(!aView2.m_bEmptyTableSelection); + + aView1.m_nTableSelectionCount = 0; + aView2.m_nTableSelectionCount = 0; + + // Switch to view 1 + pDocument->m_pDocumentClass->setView(pDocument, nView1); + // Go out of Table1 and re-enter.. + lcl_repeatKeyStroke(pDocument, 0, KEY_UP, 1); + lcl_repeatKeyStroke(pDocument, 0, KEY_DOWN, 1); + Scheduler::ProcessEventsToIdle(); + // View1 should get one empty table selection, then get Table1 selection. + CPPUNIT_ASSERT_EQUAL(2, aView1.m_nTableSelectionCount); + // View2 should not get any table selection. + CPPUNIT_ASSERT_EQUAL(0, aView2.m_nTableSelectionCount); + CPPUNIT_ASSERT(!aView1.m_bEmptyTableSelection); +} + +void DesktopLOKTest::testColorPaletteCallback() +{ + LibLODocument_Impl* pDocument = loadDoc("ThemeDocument.docx"); + + // Create view 1. + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + ViewCallback aView1(pDocument); + Scheduler::ProcessEventsToIdle(); + { + CPPUNIT_ASSERT_EQUAL(1, aView1.m_nColorPaletteCallbackCount); + boost::property_tree::ptree aValues = aView1.m_aColorPaletteCallbackResult.get_child("ThemeColors"); + CPPUNIT_ASSERT(!aValues.empty()); + CPPUNIT_ASSERT_EQUAL(size_t(6), aValues.size()); + } + + // Create view 2. + pDocument->m_pDocumentClass->createView(pDocument); + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + ViewCallback aView2(pDocument); + Scheduler::ProcessEventsToIdle(); + { + CPPUNIT_ASSERT_EQUAL(1, aView2.m_nColorPaletteCallbackCount); + boost::property_tree::ptree aValues = aView1.m_aColorPaletteCallbackResult.get_child("ThemeColors"); + CPPUNIT_ASSERT(!aValues.empty()); + CPPUNIT_ASSERT_EQUAL(size_t(6), aValues.size()); + } +} + namespace { constexpr size_t classOffset(int i) @@ -3132,6 +3580,20 @@ void DesktopLOKTest::testABI() CPPUNIT_ASSERT_EQUAL(classOffset(9), offsetof(struct _LibreOfficeKitClass, getVersionInfo)); CPPUNIT_ASSERT_EQUAL(classOffset(10), offsetof(struct _LibreOfficeKitClass, runMacro)); CPPUNIT_ASSERT_EQUAL(classOffset(11), offsetof(struct _LibreOfficeKitClass, signDocument)); + CPPUNIT_ASSERT_EQUAL(classOffset(12), offsetof(struct _LibreOfficeKitClass, runLoop)); + CPPUNIT_ASSERT_EQUAL(classOffset(13), offsetof(struct _LibreOfficeKitClass, sendDialogEvent)); + CPPUNIT_ASSERT_EQUAL(classOffset(14), offsetof(struct _LibreOfficeKitClass, setOption)); + CPPUNIT_ASSERT_EQUAL(classOffset(15), offsetof(struct _LibreOfficeKitClass, dumpState)); + CPPUNIT_ASSERT_EQUAL(classOffset(16), offsetof(struct _LibreOfficeKitClass, extractRequest)); + CPPUNIT_ASSERT_EQUAL(classOffset(17), offsetof(struct _LibreOfficeKitClass, trimMemory)); + CPPUNIT_ASSERT_EQUAL(classOffset(18), offsetof(struct _LibreOfficeKitClass, startURP)); + CPPUNIT_ASSERT_EQUAL(classOffset(19), offsetof(struct _LibreOfficeKitClass, stopURP)); + CPPUNIT_ASSERT_EQUAL(classOffset(20), offsetof(struct _LibreOfficeKitClass, joinThreads)); + CPPUNIT_ASSERT_EQUAL(classOffset(21), offsetof(struct _LibreOfficeKitClass, setForkedChild)); + + // When extending LibreOfficeKit with a new function pointer, add new assert for the offsetof the + // new function pointer and bump this assert for the size of the class. + CPPUNIT_ASSERT_EQUAL(classOffset(22), sizeof(struct _LibreOfficeKitClass)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(0), offsetof(struct _LibreOfficeKitDocumentClass, destroy)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(1), offsetof(struct _LibreOfficeKitDocumentClass, saveAs)); @@ -3200,10 +3662,21 @@ void DesktopLOKTest::testABI() CPPUNIT_ASSERT_EQUAL(documentClassOffset(59), offsetof(struct _LibreOfficeKitDocumentClass, completeFunction)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(60), offsetof(struct _LibreOfficeKitDocumentClass, setWindowTextSelection)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(61), offsetof(struct _LibreOfficeKitDocumentClass, sendFormFieldEvent)); - - // Extending is fine, update this, and add new assert for the offsetof the - // new method - CPPUNIT_ASSERT_EQUAL(documentClassOffset(62), sizeof(struct _LibreOfficeKitDocumentClass)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(62), offsetof(struct _LibreOfficeKitDocumentClass, setBlockedCommandList)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(63), offsetof(struct _LibreOfficeKitDocumentClass, renderSearchResult)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(64), offsetof(struct _LibreOfficeKitDocumentClass, sendContentControlEvent)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(65), offsetof(struct _LibreOfficeKitDocumentClass, getSelectionTypeAndText)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(66), offsetof(struct _LibreOfficeKitDocumentClass, getDataArea)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(67), offsetof(struct _LibreOfficeKitDocumentClass, getEditMode)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(68), offsetof(struct _LibreOfficeKitDocumentClass, setViewTimezone)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(69), offsetof(struct _LibreOfficeKitDocumentClass, setAccessibilityState)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(70), offsetof(struct _LibreOfficeKitDocumentClass, getA11yFocusedParagraph)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(71), offsetof(struct _LibreOfficeKitDocumentClass, getA11yCaretPosition)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(72), offsetof(struct _LibreOfficeKitDocumentClass, setViewReadOnly)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(73), offsetof(struct _LibreOfficeKitDocumentClass, setAllowChangeComments)); + + // As above + CPPUNIT_ASSERT_EQUAL(documentClassOffset(74), sizeof(struct _LibreOfficeKitDocumentClass)); } CPPUNIT_TEST_SUITE_REGISTRATION(DesktopLOKTest); |