summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2023-02-21 13:19:42 +0200
committerTor Lillqvist <tml@collabora.com>2023-02-24 07:52:53 +0000
commitac1de680ae7f7d3ac71b73d3ebf2311a7f9e5451 (patch)
treea206e215f4e67d7622be0edd43f393356479a878 /desktop
parentc1bc0e666588050b793738c7f19fd3e1322c44e6 (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.cxx16
-rw-r--r--desktop/source/lib/init.cxx175
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,