sw lok: expose field type & command of fieldmark under cursor

It was possible to get the properties of all fieldmarks, but you could
not get the properties of the fieldmark under the current cursor.

Getting the properties of the current fieldmark is useful for Zotero: if
we already have a citation and want to insert one more, then we should
turn the current citation into a citation cluster.

Fix the problem by adding API similar to what commit
24219cc1e9 (sw lok, .uno:TextFormFields:
expose field code of fieldmarks, 2022-11-25), did: but here we return
properties of the innermost fieldmark, not all fieldmarks.

Also introduce a ITiledRenderable::supportsCommandValues(), this way
next time a command value getter is added in sw/sc/sd, no need to touch
desktop/ anymore.

Change-Id: I7f1a7064307034a18527ab5e985d2eac56807cb7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145062
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
This commit is contained in:
Miklos Vajna
2023-01-05 08:33:16 +00:00
parent ed259e5efe
commit bb20dee2ef
5 changed files with 122 additions and 37 deletions
+8 -36
View File
@@ -5714,12 +5714,13 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
static constexpr OStringLiteral aSheetGeometryData(".uno:SheetGeometryData");
static constexpr OStringLiteral aCellCursor(".uno:CellCursor");
static constexpr OStringLiteral aFontSubset(".uno:FontSubset&name=");
static const std::initializer_list<std::u16string_view> vForward = {
u"TextFormFields",
u"SetDocumentProperties",
u"Bookmarks",
u"Fields"
};
ITiledRenderable* pDoc = getTiledRenderable(pThis);
if (!pDoc)
{
SetLastExceptionMsg("Document doesn't support tiled rendering");
return nullptr;
}
if (!strcmp(pCommand, ".uno:LanguageStatus"))
{
@@ -5763,13 +5764,6 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
}
else if (o3tl::starts_with(aCommand, aViewRowColumnHeaders))
{
ITiledRenderable* pDoc = getTiledRenderable(pThis);
if (!pDoc)
{
SetLastExceptionMsg("Document doesn't support tiled rendering");
return nullptr;
}
tools::Rectangle aRectangle;
if (aCommand.size() > o3tl::make_unsigned(aViewRowColumnHeaders.getLength()))
{
@@ -5815,13 +5809,6 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
}
else if (o3tl::starts_with(aCommand, aSheetGeometryData))
{
ITiledRenderable* pDoc = getTiledRenderable(pThis);
if (!pDoc)
{
SetLastExceptionMsg("Document doesn't support tiled rendering");
return nullptr;
}
bool bColumns = true;
bool bRows = true;
bool bSizes = true;
@@ -5881,12 +5868,6 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
}
else if (o3tl::starts_with(aCommand, aCellCursor))
{
ITiledRenderable* pDoc = getTiledRenderable(pThis);
if (!pDoc)
{
SetLastExceptionMsg("Document doesn't support tiled rendering");
return nullptr;
}
// Ignore command's deprecated parameters.
tools::JsonWriter aJsonWriter;
pDoc->getCellCursor(aJsonWriter);
@@ -5896,17 +5877,8 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
{
return getFontSubset(aCommand.substr(aFontSubset.getLength()));
}
else if (std::find(vForward.begin(), vForward.end(),
INetURLObject(OUString::fromUtf8(aCommand)).GetURLPath())
!= vForward.end())
else if (pDoc->supportsCommandValues(INetURLObject(OUString::fromUtf8(aCommand)).GetURLPath()))
{
ITiledRenderable* pDoc = getTiledRenderable(pThis);
if (!pDoc)
{
SetLastExceptionMsg("Document doesn't support tiled rendering");
return nullptr;
}
tools::JsonWriter aJsonWriter;
pDoc->getCommandValues(aJsonWriter, aCommand);
return aJsonWriter.extractData();
+3
View File
@@ -369,6 +369,9 @@ public:
*/
virtual void setPaintTextEdit(bool) {}
/// Decides if it's OK to call getCommandValues(rCommand).
virtual bool supportsCommandValues(std::u16string_view /*rCommand*/) { return false; }
/// Returns a json mapping of the possible values for the given command.
virtual void getCommandValues(tools::JsonWriter& /*rJsonWriter*/, std::string_view /*rCommand*/)
{
+3
View File
@@ -462,6 +462,9 @@ public:
/// @see vcl::ITiledRenderable::getCommandValues().
void getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand) override;
/// @see vcl::ITiledRenderable::supportsCommandValues().
bool supportsCommandValues(std::u16string_view rCommand) override;
void Invalidate();
void Reactivate(SwDocShell* pNewDocShell);
SwXDocumentPropertyHelper * GetPropertyHelper ();
+38
View File
@@ -347,6 +347,44 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetFields)
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aTree.get_child("setRefs").count(""));
}
CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetTextFormField)
{
// Given a document with a fieldmark:
createSwDoc();
uno::Sequence<css::beans::PropertyValue> aArgs = {
comphelper::makePropertyValue("FieldType", uno::Any(OUString(ODF_UNHANDLED))),
comphelper::makePropertyValue("FieldCommand",
uno::Any(OUString("ADDIN ZOTERO_ITEM foo bar"))),
comphelper::makePropertyValue("FieldResult", uno::Any(OUString("result"))),
};
dispatchCommand(mxComponent, ".uno:TextFormField", aArgs);
// When stepping into the fieldmark with the cursor and getting the command value for
// uno:TextFormField:
SwDoc* pDoc = getSwDoc();
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
pWrtShell->SttEndDoc(/*bStt=*/false);
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
tools::JsonWriter aJsonWriter;
std::string_view aCommand(".uno:TextFormField?type=vnd.oasis.opendocument.field.UNHANDLED&"
"commandPrefix=ADDIN%20ZOTERO_ITEM");
auto pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
pXTextDocument->getCommandValues(aJsonWriter, aCommand);
// Then make sure we find the inserted fieldmark:
std::unique_ptr<char[], o3tl::free_delete> pJSON(aJsonWriter.extractData());
std::stringstream aStream(pJSON.get());
boost::property_tree::ptree aTree;
boost::property_tree::read_json(aStream, aTree);
// Without the accompanying fix in place, this test would have failed with:
// - No such node (type)
// i.e. the returned JSON was just an empty object.
CPPUNIT_ASSERT_EQUAL(std::string("vnd.oasis.opendocument.field.UNHANDLED"),
aTree.get<std::string>("type"));
CPPUNIT_ASSERT_EQUAL(std::string("ADDIN ZOTERO_ITEM foo bar"),
aTree.get<std::string>("command"));
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+70 -1
View File
@@ -35,6 +35,7 @@
#include <doc.hxx>
#include <docsh.hxx>
#include <fmtrfmrk.hxx>
#include <wrtsh.hxx>
using namespace ::com::sun::star;
@@ -45,7 +46,7 @@ namespace
/// Parameters:
///
/// - type: e.g. ODF_UNHANDLED
/// - commandPrefix: field comment prefix not not return all fieldmarks
/// - commandPrefix: field command prefix to not return all fieldmarks
void GetTextFormFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
const std::map<OUString, OUString>& rArguments)
{
@@ -96,6 +97,60 @@ void GetTextFormFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
}
}
/// Implements getCommandValues(".uno:TextFormField").
///
/// Parameters:
///
/// - type: e.g. ODF_UNHANDLED
/// - commandPrefix: field command prefix to not return all fieldmarks
void GetTextFormField(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
const std::map<OUString, OUString>& rArguments)
{
OUString aType;
OUString aCommandPrefix;
auto it = rArguments.find("type");
if (it != rArguments.end())
{
aType = it->second;
}
it = rArguments.find("commandPrefix");
if (it != rArguments.end())
{
aCommandPrefix = it->second;
}
IDocumentMarkAccess& rIDMA = *pDocShell->GetDoc()->getIDocumentMarkAccess();
SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
SwPosition& rCursor = *pWrtShell->GetCursor()->GetPoint();
sw::mark::IFieldmark* pFieldmark = rIDMA.getFieldmarkFor(rCursor);
if (!pFieldmark)
{
return;
}
if (pFieldmark->GetFieldname() != aType)
{
return;
}
auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
if (itParam == pFieldmark->GetParameters()->end())
{
return;
}
OUString aCommand;
itParam->second >>= aCommand;
if (!aCommand.startsWith(aCommandPrefix))
{
return;
}
rJsonWriter.put("type", aType);
rJsonWriter.put("command", aCommand);
}
/// Implements getCommandValues(".uno:SetDocumentProperties").
///
/// Parameters:
@@ -220,11 +275,21 @@ void GetFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
}
}
bool SwXTextDocument::supportsCommandValues(std::u16string_view rCommand)
{
static const std::initializer_list<std::u16string_view> vForward
= { u"TextFormFields", u"TextFormField", u"SetDocumentProperties", u"Bookmarks",
u"Fields" };
return std::find(vForward.begin(), vForward.end(), rCommand) != vForward.end();
}
void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand)
{
std::map<OUString, OUString> aMap;
static constexpr OStringLiteral aTextFormFields(".uno:TextFormFields");
static constexpr OStringLiteral aTextFormField(".uno:TextFormField");
static constexpr OStringLiteral aSetDocumentProperties(".uno:SetDocumentProperties");
static constexpr OStringLiteral aBookmarks(".uno:Bookmarks");
static constexpr OStringLiteral aFields(".uno:Fields");
@@ -255,6 +320,10 @@ void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::stri
{
GetTextFormFields(rJsonWriter, m_pDocShell, aMap);
}
if (o3tl::starts_with(rCommand, aTextFormField))
{
GetTextFormField(rJsonWriter, m_pDocShell, aMap);
}
else if (o3tl::starts_with(rCommand, aSetDocumentProperties))
{
GetDocumentProperties(rJsonWriter, m_pDocShell, aMap);