diff options
author | Tor Lillqvist <tml@collabora.com> | 2023-02-21 13:19:42 +0200 |
---|---|---|
committer | Tor Lillqvist <tml@collabora.com> | 2023-02-24 07:52:53 +0000 |
commit | ac1de680ae7f7d3ac71b73d3ebf2311a7f9e5451 (patch) | |
tree | a206e215f4e67d7622be0edd43f393356479a878 /desktop | |
parent | c1bc0e666588050b793738c7f19fd3e1322c44e6 (diff) |
Extend LOKit API with functionality to extract a request and paint thumbnails
Original author was Mert Tümer.
Change-Id: I181a9955bcce1d5ee4c81e2a52445ef318dc4823
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147432
Tested-by: Tor Lillqvist <tml@collabora.com>
Reviewed-by: Tor Lillqvist <tml@collabora.com>
Diffstat (limited to 'desktop')
-rw-r--r-- | desktop/qa/desktop_lib/test_desktop_lib.cxx | 16 | ||||
-rw-r--r-- | desktop/source/lib/init.cxx | 175 |
2 files changed, 188 insertions, 3 deletions
diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index 3908829f1918..4348da15a68b 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -3554,6 +3554,15 @@ 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)); + + // 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(17), sizeof(struct _LibreOfficeKitClass)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(0), offsetof(struct _LibreOfficeKitDocumentClass, destroy)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(1), offsetof(struct _LibreOfficeKitDocumentClass, saveAs)); @@ -3631,10 +3640,11 @@ void DesktopLOKTest::testABI() 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, paintThumbnail)); + - // Extending is fine, update this, and add new assert for the offsetof the - // new method - CPPUNIT_ASSERT_EQUAL(documentClassOffset(69), sizeof(struct _LibreOfficeKitDocumentClass)); + // As above + CPPUNIT_ASSERT_EQUAL(documentClassOffset(70), sizeof(struct _LibreOfficeKitDocumentClass)); } CPPUNIT_TEST_SUITE_REGISTRATION(DesktopLOKTest); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index d0e899b124f4..399a42159cc3 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -63,6 +63,7 @@ #include <cppuhelper/bootstrap.hxx> #include <comphelper/base64.hxx> #include <comphelper/dispatchcommand.hxx> +#include <comphelper/propertysequence.hxx> #include <comphelper/lok.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/string.hxx> @@ -175,6 +176,7 @@ // Needed for getUndoManager() #include <com/sun/star/document/XUndoManager.hpp> #include <com/sun/star/document/XUndoManagerSupplier.hpp> +#include <com/sun/star/document/XLinkTargetSupplier.hpp> #include <editeng/sizeitem.hxx> #include <svx/rulritem.hxx> #include <svx/pageitem.hxx> @@ -395,6 +397,97 @@ std::vector<beans::PropertyValue> desktop::jsonToPropertyValuesVector(const char return aArguments; } +static bool extractLinks(const uno::Reference< container::XNameAccess >& xLinks, bool subcontent, OUStringBuffer& jsonText) +{ + const uno::Sequence< OUString > aNames( xLinks->getElementNames() ); + + const sal_uLong nLinks = aNames.getLength(); + const OUString* pNames = aNames.getConstArray(); + const OUString aProp_LinkDisplayName( "LinkDisplayName" ); + const OUString aProp_LinkTarget( "com.sun.star.document.LinkTarget" ); + bool bIsTarget = false; + for( sal_uLong i = 0; i < nLinks; i++ ) + { + uno::Any aAny; + OUString aLink( *pNames++ ); + + bool bError = false; + try + { + aAny = xLinks->getByName( aLink ); + } + catch(const uno::Exception&) + { + // if the name of the target was invalid (like empty headings) + // no object can be provided + bError = true; + } + if(bError) + continue; + + uno::Reference< beans::XPropertySet > xTarget; + if( aAny >>= xTarget ) + { + try + { + // get name to display + aAny = xTarget->getPropertyValue( aProp_LinkDisplayName ); + OUString aDisplayName; + aAny >>= aDisplayName; + OUString aStrDisplayname ( aDisplayName ); + + if (subcontent) + { + jsonText.append("\""); + jsonText.append(aStrDisplayname); + jsonText.append("\": \""); + jsonText.append(aLink); + jsonText.append("\""); + if (i < nLinks-1) + { + jsonText.append(", "); + } + } + else + { + uno::Reference< lang::XServiceInfo > xSI( xTarget, uno::UNO_QUERY ); + bIsTarget = xSI->supportsService( aProp_LinkTarget ); + if (i != 0) + { + if (!bIsTarget) + jsonText.append("}"); + if (i < nLinks) + { + jsonText.append(", "); + } + } + jsonText.append("\""); + jsonText.append(aStrDisplayname); + jsonText.append("\": "); + + if (bIsTarget) + { + jsonText.append("true"); + continue; + } + jsonText.append("{"); + } + + uno::Reference< document::XLinkTargetSupplier > xLTS( xTarget, uno::UNO_QUERY ); + if( xLTS.is() ) + { + extractLinks(xLTS->getLinks(), true, jsonText); + } + } + catch(...) + { + SAL_WARN("lok", "extractLinks: Exception"); + } + } + } + return bIsTarget; +} + static void unoAnyToJson(tools::JsonWriter& rJson, const char * pNodeName, const uno::Any& anyItem) { auto aNode = rJson.startNode(pNodeName); @@ -1018,6 +1111,7 @@ static void doc_paintTile(LibreOfficeKitDocument* pThis, const int nCanvasWidth, const int nCanvasHeight, const int nTilePosX, const int nTilePosY, const int nTileWidth, const int nTileHeight); +static void doc_paintThumbnail(LibreOfficeKitDocument* pThis, unsigned char* pBuffer, int x, int y); #ifdef IOS static void doc_paintTileToCGContext(LibreOfficeKitDocument* pThis, void* rCGContext, @@ -1291,6 +1385,7 @@ LibLODocument_Impl::LibLODocument_Impl(uno::Reference <css::lang::XComponent> xC m_pDocumentClass->setPartMode = doc_setPartMode; m_pDocumentClass->getEditMode = doc_getEditMode; m_pDocumentClass->paintTile = doc_paintTile; + m_pDocumentClass->paintThumbnail = doc_paintThumbnail; #ifdef IOS m_pDocumentClass->paintTileToCGContext = doc_paintTileToCGContext; #endif @@ -2424,6 +2519,9 @@ static bool lo_signDocument(LibreOfficeKit* pThis, const unsigned char* pPrivateKeyBinary, const int nPrivateKeyBinarySize); +static char* lo_extractRequest(LibreOfficeKit* pThis, + const char* pFilePath); + static void lo_runLoop(LibreOfficeKit* pThis, LibreOfficeKitPollCallback pPollCallback, LibreOfficeKitWakeCallback pWakeCallback, @@ -2464,6 +2562,7 @@ LibLibreOffice_Impl::LibLibreOffice_Impl() m_pOfficeClass->sendDialogEvent = lo_sendDialogEvent; m_pOfficeClass->setOption = lo_setOption; m_pOfficeClass->dumpState = lo_dumpState; + m_pOfficeClass->extractRequest = lo_extractRequest; gOfficeClass = m_pOfficeClass; } @@ -2979,6 +3078,69 @@ static bool lo_signDocument(LibreOfficeKit* /*pThis*/, return true; } + +static char* lo_extractRequest(LibreOfficeKit* /*pThis*/, const char* pFilePath) +{ + uno::Reference<frame::XDesktop2> xComponentLoader = frame::Desktop::create(xContext); + uno::Reference< css::lang::XComponent > xComp; + OUString aURL(getAbsoluteURL(pFilePath)); + OUString result; + if (!aURL.isEmpty()) + { + if (xComponentLoader.is()) + { + try + { + uno::Sequence<css::beans::PropertyValue> aFilterOptions(comphelper::InitPropertySequence( + { + {"Hidden", css::uno::Any(true)}, + {"ReadOnly", css::uno::Any(true)} + })); + xComp = xComponentLoader->loadComponentFromURL( aURL, "_blank", 0, aFilterOptions ); + } + catch ( const lang::IllegalArgumentException& ex ) + { + SAL_WARN("lok", "lo_extractRequest: IllegalArgumentException: " << ex.Message); + result = "{ }"; + return convertOUString(result); + } + catch (...) + { + SAL_WARN("lok", "lo_extractRequest: Exception on loadComponentFromURL, url= " << aURL); + result = "{ }"; + return convertOUString(result); + } + + if (xComp.is()) + { + uno::Reference< document::XLinkTargetSupplier > xLTS( xComp, uno::UNO_QUERY ); + + if( xLTS.is() ) + { + OUStringBuffer jsonText; + jsonText.append("{ \"Targets\": { "); + bool lastParentheses = extractLinks(xLTS->getLinks(), false, jsonText); + jsonText.append("} }"); + if (!lastParentheses) + jsonText.append(" }"); + + OUString res(jsonText.makeStringAndClear()); + return convertOUString(res); + } + xComp->dispose(); + } + else + { + result = "{ }"; + return convertOUString(result); + } + + } + } + result = "{ }"; + return convertOUString(result); +} + static void lo_registerCallback (LibreOfficeKit* pThis, LibreOfficeKitCallback pCallback, void* pData) @@ -3845,6 +4007,19 @@ static void doc_paintTileToCGContext(LibreOfficeKitDocument* pThis, #endif +static void doc_paintThumbnail(LibreOfficeKitDocument* pThis, unsigned char* pBuffer, int x, int y) +{ + constexpr float zoom = 0.5f; + constexpr int pixelWidth = 120; + constexpr int pixelHeight = 120; + constexpr int pixelWidthTwips = pixelWidth * 15 / zoom; + constexpr int pixelHeightTwips = pixelHeight * 15 / zoom; + constexpr int offsetXTwips = 15 * 15; // start 15 px/twips before the target to get a clearer thumbnail + constexpr int offsetYTwips = 15 * 15; + + doc_paintTile(pThis, pBuffer, pixelWidth, pixelHeight, x-offsetXTwips, y-offsetYTwips, pixelWidthTwips, pixelHeightTwips); +} + static void doc_paintPartTile(LibreOfficeKitDocument* pThis, unsigned char* pBuffer, const int nPart, |