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-22 08:14:30 +0000
commit1aa37ca99112c0760552600d7774ba7224581c5b (patch)
tree90fe0a1eee3280c6c7d1f8ccb85fa7e3d874022e /desktop
parentbdc4dc93a9edd5f46bdede12514ac5f66bf43167 (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/+/147396 Tested-by: Jenkins 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 3d2fc3c0d2fb..c143662d7dd4 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -3549,6 +3549,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));
@@ -3626,10 +3635,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 ed601003d042..1a077ce19500 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -67,6 +67,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>
@@ -179,6 +180,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>
@@ -399,6 +401,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);
@@ -1022,6 +1115,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,
@@ -1295,6 +1389,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
@@ -2428,6 +2523,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,
@@ -2468,6 +2566,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;
}
@@ -2983,6 +3082,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)
@@ -3849,6 +4011,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,