1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <unotxdoc.hxx>
26 #include <com/sun/star/beans/XPropertyAccess.hpp>
28 #include <comphelper/sequence.hxx>
29 #include <o3tl/string_view.hxx>
30 #include <tools/json_writer.hxx>
31 #include <tools/urlobj.hxx>
32 #include <xmloff/odffields.hxx>
33 #include <sfx2/lokhelper.hxx>
35 #include <IDocumentMarkAccess.hxx>
38 #include <fmtrfmrk.hxx>
40 #include <txtrfmrk.hxx>
43 #include <unoport.hxx>
44 #include <unoprnms.hxx>
45 #include <unocontentcontrol.hxx>
46 #include <com/sun/star/text/XTextContent.hpp>
48 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
49 #include <com/sun/star/chart2/XInternalDataProvider.hpp>
50 #include <com/sun/star/chart2/XChartDocument.hpp>
51 #include <com/sun/star/chart/XChartDocument.hpp>
52 #include <com/sun/star/chart/XChartDataArray.hpp>
53 #include <com/sun/star/chart2/XTitle.hpp>
54 #include <com/sun/star/chart2/XTitled.hpp>
55 #include <com/sun/star/document/XDocumentProperties2.hpp>
56 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
58 #include <sax/tools/converter.hxx>
60 using namespace ::com::sun::star
;
64 /// Implements getCommandValues(".uno:TextFormFields").
68 /// - type: e.g. ODF_UNHANDLED
69 /// - commandPrefix: field command prefix to not return all fieldmarks
70 void GetTextFormFields(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
71 const std::map
<OUString
, OUString
>& rArguments
)
74 OUString aCommandPrefix
;
76 auto it
= rArguments
.find(u
"type"_ustr
);
77 if (it
!= rArguments
.end())
82 it
= rArguments
.find(u
"commandPrefix"_ustr
);
83 if (it
!= rArguments
.end())
85 aCommandPrefix
= it
->second
;
89 SwDoc
* pDoc
= pDocShell
->GetDoc();
90 IDocumentMarkAccess
* pMarkAccess
= pDoc
->getIDocumentMarkAccess();
91 auto aFields
= rJsonWriter
.startArray("fields");
92 for (auto it
= pMarkAccess
->getFieldmarksBegin(); it
!= pMarkAccess
->getFieldmarksEnd(); ++it
)
94 sw::mark::Fieldmark
* pFieldmark
= *it
;
96 if (pFieldmark
->GetFieldname() != aType
)
101 auto itParam
= pFieldmark
->GetParameters()->find(ODF_CODE_PARAM
);
102 if (itParam
== pFieldmark
->GetParameters()->end())
108 itParam
->second
>>= aCommand
;
109 if (!aCommand
.startsWith(aCommandPrefix
))
114 auto aField
= rJsonWriter
.startStruct();
115 rJsonWriter
.put("type", aType
);
116 rJsonWriter
.put("command", aCommand
);
120 /// Implements getCommandValues(".uno:TextFormField").
124 /// - type: e.g. ODF_UNHANDLED
125 /// - commandPrefix: field command prefix to not return all fieldmarks
126 void GetTextFormField(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
127 const std::map
<OUString
, OUString
>& rArguments
)
130 OUString aCommandPrefix
;
131 auto it
= rArguments
.find(u
"type"_ustr
);
132 if (it
!= rArguments
.end())
137 it
= rArguments
.find(u
"commandPrefix"_ustr
);
138 if (it
!= rArguments
.end())
140 aCommandPrefix
= it
->second
;
143 IDocumentMarkAccess
& rIDMA
= *pDocShell
->GetDoc()->getIDocumentMarkAccess();
144 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
145 SwPosition
& rCursor
= *pWrtShell
->GetCursor()->GetPoint();
146 sw::mark::Fieldmark
* pFieldmark
= rIDMA
.getInnerFieldmarkFor(rCursor
);
147 auto typeNode
= rJsonWriter
.startNode("field");
153 if (pFieldmark
->GetFieldname() != aType
)
158 auto itParam
= pFieldmark
->GetParameters()->find(ODF_CODE_PARAM
);
159 if (itParam
== pFieldmark
->GetParameters()->end())
165 itParam
->second
>>= aCommand
;
166 if (!aCommand
.startsWith(aCommandPrefix
))
171 rJsonWriter
.put("type", aType
);
172 rJsonWriter
.put("command", aCommand
);
175 /// Implements getCommandValues(".uno:SetDocumentProperties").
179 /// - namePrefix: field name prefix to not return all user-defined properties
180 void GetDocumentProperties(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
181 const std::map
<OUString
, OUString
>& rArguments
)
183 OUString aNamePrefix
;
184 auto it
= rArguments
.find(u
"namePrefix"_ustr
);
185 if (it
!= rArguments
.end())
187 aNamePrefix
= it
->second
;
190 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(pDocShell
->GetModel(),
192 uno::Reference
<document::XDocumentProperties
> xDP
= xDPS
->getDocumentProperties();
193 uno::Reference
<beans::XPropertyAccess
> xUDP(xDP
->getUserDefinedProperties(), uno::UNO_QUERY
);
194 auto aUDPs
= comphelper::sequenceToContainer
<std::vector
<beans::PropertyValue
>>(
195 xUDP
->getPropertyValues());
196 auto aProperties
= rJsonWriter
.startArray("userDefinedProperties");
197 for (const auto& rUDP
: aUDPs
)
199 if (!rUDP
.Name
.startsWith(aNamePrefix
))
204 if (rUDP
.Value
.getValueTypeClass() != uno::TypeClass_STRING
)
210 rUDP
.Value
>>= aValue
;
212 auto aProperty
= rJsonWriter
.startStruct();
213 rJsonWriter
.put("name", rUDP
.Name
);
214 rJsonWriter
.put("type", "string");
215 rJsonWriter
.put("value", aValue
);
219 /// Implements getCommandValues(".uno:Bookmarks").
223 /// - namePrefix: bookmark name prefix to not return all bookmarks
224 void GetBookmarks(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
225 const std::map
<OUString
, OUString
>& rArguments
)
227 OUString aNamePrefix
;
229 auto it
= rArguments
.find(u
"namePrefix"_ustr
);
230 if (it
!= rArguments
.end())
232 aNamePrefix
= it
->second
;
236 IDocumentMarkAccess
& rIDMA
= *pDocShell
->GetDoc()->getIDocumentMarkAccess();
237 auto aBookmarks
= rJsonWriter
.startArray("bookmarks");
238 for (auto it
= rIDMA
.getBookmarksBegin(); it
!= rIDMA
.getBookmarksEnd(); ++it
)
240 sw::mark::MarkBase
* pMark
= *it
;
241 if (!pMark
->GetName().startsWith(aNamePrefix
))
246 auto aProperty
= rJsonWriter
.startStruct();
247 rJsonWriter
.put("name", pMark
->GetName());
251 /// Implements getCommandValues(".uno:Bookmark").
255 /// - namePrefix: bookmark name prefix to not return all bookmarks
256 void GetBookmark(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
257 const std::map
<OUString
, OUString
>& rArguments
)
259 OUString aNamePrefix
;
261 auto it
= rArguments
.find(u
"namePrefix"_ustr
);
262 if (it
!= rArguments
.end())
264 aNamePrefix
= it
->second
;
268 IDocumentMarkAccess
& rIDMA
= *pDocShell
->GetDoc()->getIDocumentMarkAccess();
269 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
270 SwPosition
& rCursor
= *pWrtShell
->GetCursor()->GetPoint();
271 sw::mark::MarkBase
* pBookmark
= rIDMA
.getOneInnermostBookmarkFor(rCursor
);
272 auto aBookmark
= rJsonWriter
.startNode("bookmark");
278 if (!pBookmark
->GetName().startsWith(aNamePrefix
))
283 rJsonWriter
.put("name", pBookmark
->GetName());
286 /// Implements getCommandValues(".uno:Fields").
290 /// - typeName: field type condition to not return all fields
291 /// - namePrefix: field name prefix to not return all fields
292 void GetFields(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
293 const std::map
<OUString
, OUString
>& rArguments
)
297 auto it
= rArguments
.find(u
"typeName"_ustr
);
298 if (it
!= rArguments
.end())
300 aTypeName
= it
->second
;
303 // See SwFieldTypeFromString().
304 if (aTypeName
!= "SetRef")
309 OUString aNamePrefix
;
311 auto it
= rArguments
.find(u
"namePrefix"_ustr
);
312 if (it
!= rArguments
.end())
314 aNamePrefix
= it
->second
;
318 SwDoc
* pDoc
= pDocShell
->GetDoc();
319 auto aBookmarks
= rJsonWriter
.startArray("setRefs");
320 std::vector
<const SwFormatRefMark
*> aRefMarks
;
321 for (sal_uInt16 i
= 0; i
< pDoc
->GetRefMarks(); ++i
)
323 aRefMarks
.push_back(pDoc
->GetRefMark(i
));
325 // Sort the refmarks based on their start position.
326 std::sort(aRefMarks
.begin(), aRefMarks
.end(),
327 [](const SwFormatRefMark
* pMark1
, const SwFormatRefMark
* pMark2
) -> bool {
328 const SwTextRefMark
* pTextRefMark1
= pMark1
->GetTextRefMark();
329 const SwTextRefMark
* pTextRefMark2
= pMark2
->GetTextRefMark();
330 SwPosition
aPos1(pTextRefMark1
->GetTextNode(), pTextRefMark1
->GetStart());
331 SwPosition
aPos2(pTextRefMark2
->GetTextNode(), pTextRefMark2
->GetStart());
332 return aPos1
< aPos2
;
335 for (const auto& pRefMark
: aRefMarks
)
337 if (!pRefMark
->GetRefName().startsWith(aNamePrefix
))
342 auto aProperty
= rJsonWriter
.startStruct();
343 rJsonWriter
.put("name", pRefMark
->GetRefName());
347 /// Implements getCommandValues(".uno:Field").
351 /// - typeName: field type condition to not return all fields
352 /// - namePrefix: field name prefix to not return all fields
353 void GetField(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
354 const std::map
<OUString
, OUString
>& rArguments
)
358 auto it
= rArguments
.find(u
"typeName"_ustr
);
359 if (it
!= rArguments
.end())
361 aTypeName
= it
->second
;
364 // See SwFieldTypeFromString().
365 if (aTypeName
!= "SetRef")
370 OUString aNamePrefix
;
372 auto it
= rArguments
.find(u
"namePrefix"_ustr
);
373 if (it
!= rArguments
.end())
375 aNamePrefix
= it
->second
;
379 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
380 SwPosition
& rCursor
= *pWrtShell
->GetCursor()->GetPoint();
381 SwTextNode
* pTextNode
= rCursor
.GetNode().GetTextNode();
382 std::vector
<SwTextAttr
*> aAttrs
383 = pTextNode
->GetTextAttrsAt(rCursor
.GetContentIndex(), RES_TXTATR_REFMARK
);
384 auto aRefmark
= rJsonWriter
.startNode("setRef");
390 const SwFormatRefMark
& rRefmark
= aAttrs
[0]->GetRefMark();
391 if (!rRefmark
.GetRefName().startsWith(aNamePrefix
))
396 rJsonWriter
.put("name", rRefmark
.GetRefName());
399 /// Implements getCommandValues(".uno:ExtractDocumentStructures").
403 /// - filter: To filter what document structure types to extract
404 /// now, only contentcontrol is supported.
405 void GetDocStructure(tools::JsonWriter
& rJsonWriter
, SwDocShell
* /*pDocShell*/,
406 const std::map
<OUString
, OUString
>& rArguments
,
407 uno::Reference
<container::XIndexAccess
>& xContentControls
)
409 auto it
= rArguments
.find(u
"filter"_ustr
);
410 if (it
!= rArguments
.end())
412 // If filter is present but we are filtering not to contentcontrols
413 if (!it
->second
.equals(u
"contentcontrol"_ustr
))
417 int iCCcount
= xContentControls
->getCount();
419 for (int i
= 0; i
< iCCcount
; ++i
)
421 OString
aNodeName("ContentControls.ByIndex."_ostr
+ OString::number(i
));
422 auto ContentControlNode
= rJsonWriter
.startNode(aNodeName
);
424 uno::Reference
<text::XTextContent
> xContentControl
;
426 xContentControls
->getByIndex(i
) >>= xContentControl
;
428 uno::Reference
<text::XText
> xContentControlText(xContentControl
, uno::UNO_QUERY
);
429 uno::Reference
<beans::XPropertySet
> xContentControlProps(xContentControl
, uno::UNO_QUERY
);
432 xContentControlProps
->getPropertyValue(UNO_NAME_ID
) >>= iID
;
433 rJsonWriter
.put("id", iID
);
436 xContentControlProps
->getPropertyValue(UNO_NAME_TAG
) >>= aTag
;
437 rJsonWriter
.put("tag", aTag
);
440 xContentControlProps
->getPropertyValue(UNO_NAME_ALIAS
) >>= aAlias
;
441 rJsonWriter
.put("alias", aAlias
);
444 xContentControlProps
->getPropertyValue(UNO_NAME_CONTENT_CONTROL_TYPE
) >>= iType
;
445 SwContentControlType aType
= static_cast<SwContentControlType
>(iType
);
447 bool bShowingPlaceHolder
= false;
448 xContentControlProps
->getPropertyValue(UNO_NAME_SHOWING_PLACE_HOLDER
)
449 >>= bShowingPlaceHolder
;
451 if (!bShowingPlaceHolder
)
453 aContent
= xContentControlText
->getString();
455 rJsonWriter
.put("content", aContent
);
459 case SwContentControlType::RICH_TEXT
:
461 rJsonWriter
.put("type", "rich-text");
464 case SwContentControlType::CHECKBOX
:
466 rJsonWriter
.put("type", "checkbox");
467 bool bchecked
= false;
468 xContentControlProps
->getPropertyValue(UNO_NAME_CHECKED
) >>= bchecked
;
469 rJsonWriter
.put(UNO_NAME_CHECKED
, OUString::boolean(bchecked
));
472 case SwContentControlType::DROP_DOWN_LIST
:
474 rJsonWriter
.put("type", "drop-down-list");
475 // we could list its elements if we want
478 case SwContentControlType::PICTURE
:
480 rJsonWriter
.put("type", "picture");
483 case SwContentControlType::DATE
:
485 rJsonWriter
.put("type", "date");
486 OUString aDateFormat
;
487 xContentControlProps
->getPropertyValue(UNO_NAME_DATE_FORMAT
) >>= aDateFormat
;
488 rJsonWriter
.put(UNO_NAME_DATE_FORMAT
, aDateFormat
);
489 OUString aDateLanguage
;
490 xContentControlProps
->getPropertyValue(UNO_NAME_DATE_LANGUAGE
) >>= aDateLanguage
;
491 rJsonWriter
.put(UNO_NAME_DATE_LANGUAGE
, aDateLanguage
);
492 OUString aCurrentDate
;
493 xContentControlProps
->getPropertyValue(UNO_NAME_CURRENT_DATE
) >>= aCurrentDate
;
494 rJsonWriter
.put(UNO_NAME_CURRENT_DATE
, aCurrentDate
);
497 case SwContentControlType::PLAIN_TEXT
:
499 rJsonWriter
.put("type", "plain-text");
502 case SwContentControlType::COMBO_BOX
:
504 rJsonWriter
.put("type", "combo-box");
505 // we could list its elements if we want
509 //it should never happen
510 rJsonWriter
.put("type", "no type?");
515 void GetDocStructureCharts(tools::JsonWriter
& rJsonWriter
, SwDocShell
* /*pDocShell*/,
516 const std::map
<OUString
, OUString
>& rArguments
,
517 uno::Reference
<container::XIndexAccess
>& xEmbeddeds
)
519 auto it
= rArguments
.find(u
"filter"_ustr
);
520 if (it
!= rArguments
.end())
522 // If filter is present but we are filtering not to charts
523 if (!it
->second
.equals(u
"charts"_ustr
))
527 sal_Int32 nEOcount
= xEmbeddeds
->getCount();
529 for (int i
= 0; i
< nEOcount
; ++i
)
531 uno::Reference
<beans::XPropertySet
> xShapeProps(xEmbeddeds
->getByIndex(i
), uno::UNO_QUERY
);
532 if (!xShapeProps
.is())
535 uno::Reference
<frame::XModel
> xDocModel
;
536 xShapeProps
->getPropertyValue(u
"Model"_ustr
) >>= xDocModel
;
540 uno::Reference
<chart2::XChartDocument
> xChartDoc(xDocModel
, uno::UNO_QUERY
);
544 uno::Reference
<chart2::data::XDataProvider
> xDataProvider(xChartDoc
->getDataProvider());
545 if (!xDataProvider
.is())
548 uno::Reference
<chart::XChartDataArray
> xDataArray(xChartDoc
->getDataProvider(),
550 if (!xDataArray
.is())
553 uno::Reference
<chart2::XDiagram
> xDiagram
= xChartDoc
->getFirstDiagram();
557 //we have the chart Data now, we can start to extract it
558 OString
aNodeName("Charts.ByEmbedIndex."_ostr
+ OString::number(i
));
559 auto aChartNode
= rJsonWriter
.startNode(aNodeName
);
561 //get the object name
562 uno::Reference
<container::XNamed
> xNamedShape(xEmbeddeds
->getByIndex(i
), uno::UNO_QUERY
);
563 if (xNamedShape
.is())
566 aName
= xNamedShape
->getName();
567 rJsonWriter
.put("name", aName
);
570 //get the chart title, if there is one
571 uno::Reference
<chart2::XTitled
> xTitled(xChartDoc
, uno::UNO_QUERY_THROW
);
574 uno::Reference
<chart2::XTitle
> xTitle
= xTitled
->getTitleObject();
578 const uno::Sequence
<uno::Reference
<chart2::XFormattedString
>> aFSSeq
580 for (auto const& fs
: aFSSeq
)
581 aTitle
+= fs
->getString();
582 rJsonWriter
.put("title", aTitle
);
586 //get the chart subtitle, if there is one
587 uno::Reference
<chart2::XTitled
> xSubTitled(xDiagram
, uno::UNO_QUERY_THROW
);
590 uno::Reference
<chart2::XTitle
> xSubTitle
= xSubTitled
->getTitleObject();
594 const uno::Sequence
<uno::Reference
<chart2::XFormattedString
>> aFSSeq
595 = xSubTitle
->getText();
596 for (auto const& fs
: aFSSeq
)
597 aSubTitle
+= fs
->getString();
598 rJsonWriter
.put("subtitle", aSubTitle
);
603 uno::Sequence
<OUString
> aRowDesc
= xDataArray
->getRowDescriptions();
604 auto aRowDescNode
= rJsonWriter
.startArray("RowDescriptions");
605 for (int j
= 0; j
< aRowDesc
.getLength(); j
++)
607 rJsonWriter
.putSimpleValue(aRowDesc
[j
]);
611 uno::Sequence
<OUString
> aColDesc
= xDataArray
->getColumnDescriptions();
612 auto aColDescNode
= rJsonWriter
.startArray("ColumnDescriptions");
613 for (int j
= 0; j
< aColDesc
.getLength(); j
++)
615 rJsonWriter
.putSimpleValue(aColDesc
[j
]);
619 uno::Sequence
<uno::Sequence
<double>> aData
= xDataArray
->getData();
620 auto aDataValuesNode
= rJsonWriter
.startArray("DataValues");
621 for (int j
= 0; j
< aData
.getLength(); j
++)
623 OString
aRowNodeName("Row."_ostr
+ OString::number(j
));
624 auto aRowNode
= rJsonWriter
.startArray(aRowNodeName
);
625 for (int k
= 0; k
< aData
[j
].getLength(); k
++)
627 rJsonWriter
.putSimpleValue(OUString::number(aData
[j
][k
]));
634 void GetDocStructureDocProps(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
635 const std::map
<OUString
, OUString
>& rArguments
)
637 auto it
= rArguments
.find(u
"filter"_ustr
);
638 if (it
!= rArguments
.end())
640 // If filter is present but we are filtering not to document properties
641 if (!it
->second
.equals(u
"docprops"_ustr
))
645 uno::Reference
<document::XDocumentPropertiesSupplier
> xDocumentPropsSupplier(
646 pDocShell
->GetModel(), uno::UNO_QUERY
);
647 if (!xDocumentPropsSupplier
.is())
650 //uno::Reference<document::XDocumentProperties> xDocProps();
651 uno::Reference
<document::XDocumentProperties2
> xDocProps(
652 xDocumentPropsSupplier
->getDocumentProperties(), uno::UNO_QUERY
);
656 auto aDocPropsNode
= rJsonWriter
.startNode("DocumentProperties");
658 // StringBuffer for converting DateTimes to String
659 OUStringBuffer
aDateBuf(32);
661 //Properties from XDocumentProperties
662 OUString aAuthor
= xDocProps
->getAuthor();
663 rJsonWriter
.put("Author", aAuthor
);
665 OUString aGenerator
= xDocProps
->getGenerator();
666 rJsonWriter
.put("Generator", aGenerator
);
668 util::DateTime aCreationDate
= xDocProps
->getCreationDate();
669 sax::Converter::convertDateTime(aDateBuf
, aCreationDate
, nullptr, true);
670 rJsonWriter
.put("CreationDate", aDateBuf
.makeStringAndClear());
672 OUString aTitle
= xDocProps
->getTitle();
673 rJsonWriter
.put("Title", aTitle
);
675 OUString aSubject
= xDocProps
->getSubject();
676 rJsonWriter
.put("Subject", aSubject
);
678 OUString aDescription
= xDocProps
->getDescription();
679 rJsonWriter
.put("Description", aDescription
);
681 uno::Sequence
<OUString
> aKeywords
= xDocProps
->getKeywords();
683 auto aKeywordsNode
= rJsonWriter
.startArray("Keywords");
684 for (int i
= 0; i
< aKeywords
.getLength(); i
++)
686 rJsonWriter
.putSimpleValue(aKeywords
[i
]);
690 lang::Locale aLanguage
= xDocProps
->getLanguage();
691 OUString
aLanguageStr(LanguageTag::convertToBcp47(aLanguage
, false));
692 rJsonWriter
.put("Language", aLanguageStr
);
694 OUString aModifiedBy
= xDocProps
->getModifiedBy();
695 rJsonWriter
.put("ModifiedBy", aModifiedBy
);
697 util::DateTime aModificationDate
= xDocProps
->getModificationDate();
698 sax::Converter::convertDateTime(aDateBuf
, aModificationDate
, nullptr, true);
699 rJsonWriter
.put("ModificationDate", aDateBuf
.makeStringAndClear());
701 OUString aPrintedBy
= xDocProps
->getPrintedBy();
702 rJsonWriter
.put("PrintedBy", aPrintedBy
);
704 util::DateTime aPrintDate
= xDocProps
->getPrintDate();
705 sax::Converter::convertDateTime(aDateBuf
, aPrintDate
, nullptr, true);
706 rJsonWriter
.put("PrintDate", aDateBuf
.makeStringAndClear());
708 OUString aTemplateName
= xDocProps
->getTemplateName();
709 rJsonWriter
.put("TemplateName", aTemplateName
);
711 OUString aTemplateURL
= xDocProps
->getTemplateURL();
712 rJsonWriter
.put("TemplateURL", aTemplateURL
);
714 util::DateTime aTemplateDate
= xDocProps
->getTemplateDate();
715 sax::Converter::convertDateTime(aDateBuf
, aTemplateDate
, nullptr, true);
716 rJsonWriter
.put("TemplateDate", aDateBuf
.makeStringAndClear());
718 OUString aAutoloadURL
= xDocProps
->getAutoloadURL();
719 rJsonWriter
.put("AutoloadURL", aAutoloadURL
);
721 sal_Int32 aAutoloadSecs
= xDocProps
->getAutoloadSecs();
722 rJsonWriter
.put("AutoloadSecs", aAutoloadSecs
);
724 OUString aDefaultTarget
= xDocProps
->getDefaultTarget();
725 rJsonWriter
.put("DefaultTarget", aDefaultTarget
);
727 uno::Sequence
<beans::NamedValue
> aDocumentStatistics
= xDocProps
->getDocumentStatistics();
729 auto aDocumentStatisticsNode
= rJsonWriter
.startNode("DocumentStatistics");
730 for (int i
= 0; i
< aDocumentStatistics
.getLength(); i
++)
732 // Todo check: do all stats are integer numbers?
733 sal_Int32 nValue
= 0;
734 aDocumentStatistics
[i
].Value
>>= nValue
;
735 std::string
aStr(OUStringToOString(aDocumentStatistics
[i
].Name
, RTL_TEXTENCODING_UTF8
));
736 rJsonWriter
.put(aStr
, nValue
);
740 sal_Int16 aEditingCycles
= xDocProps
->getEditingCycles();
741 rJsonWriter
.put("EditingCycles", aEditingCycles
);
743 sal_Int32 aEditingDuration
= xDocProps
->getEditingDuration();
744 rJsonWriter
.put("EditingDuration", aEditingDuration
);
746 //Properties from XDocumentProperties2
747 uno::Sequence
<OUString
> aContributor
= xDocProps
->getContributor();
749 auto aContributorNode
= rJsonWriter
.startArray("Contributor");
750 for (int i
= 0; i
< aContributor
.getLength(); i
++)
752 rJsonWriter
.putSimpleValue(aContributor
[i
]);
756 OUString aCoverage
= xDocProps
->getCoverage();
757 rJsonWriter
.put("Coverage", aCoverage
);
759 OUString aIdentifier
= xDocProps
->getIdentifier();
760 rJsonWriter
.put("Identifier", aIdentifier
);
762 uno::Sequence
<OUString
> aPublisher
= xDocProps
->getPublisher();
764 auto aPublisherNode
= rJsonWriter
.startArray("Publisher");
765 for (int i
= 0; i
< aPublisher
.getLength(); i
++)
767 rJsonWriter
.putSimpleValue(aPublisher
[i
]);
771 uno::Sequence
<OUString
> aRelation
= xDocProps
->getRelation();
773 auto aRelationNode
= rJsonWriter
.startArray("Relation");
774 for (int i
= 0; i
< aRelation
.getLength(); i
++)
776 rJsonWriter
.putSimpleValue(aRelation
[i
]);
780 OUString aRights
= xDocProps
->getRights();
781 rJsonWriter
.put("Rights", aRights
);
783 OUString aSource
= xDocProps
->getSource();
784 rJsonWriter
.put("Source", aSource
);
786 OUString aType
= xDocProps
->getType();
787 rJsonWriter
.put("Type", aType
);
789 // PropertySet -> JSON
790 css::uno::Reference
<css::beans::XPropertyContainer
> aUserDefinedProperties
791 = xDocProps
->getUserDefinedProperties();
792 uno::Reference
<beans::XPropertySet
> aUserDefinedPropertySet(aUserDefinedProperties
,
794 if (aUserDefinedPropertySet
.is())
796 auto aRelationNode
= rJsonWriter
.startNode("UserDefinedProperties");
797 const uno::Sequence
<beans::Property
> aProperties
798 = aUserDefinedPropertySet
->getPropertySetInfo()->getProperties();
799 for (const beans::Property
& rProperty
: aProperties
)
801 const OUString
& rKey
= rProperty
.Name
;
802 auto aNode
= rJsonWriter
.startNode(OUStringToOString(rKey
, RTL_TEXTENCODING_UTF8
));
803 uno::Any aValue
= aUserDefinedPropertySet
->getPropertyValue(rKey
);
805 OUString aAnyType
= aValue
.getValueTypeName();
806 rJsonWriter
.put("type", aAnyType
);
808 if (aAnyType
== "boolean")
809 rJsonWriter
.put("value", aValue
.get
<bool>());
810 else if (aAnyType
== "double")
811 rJsonWriter
.put("value", aValue
.get
<double>());
812 else if (aAnyType
== "float")
813 rJsonWriter
.put("value", aValue
.get
<float>());
814 else if (aAnyType
== "long")
815 rJsonWriter
.put("value", aValue
.get
<sal_Int32
>());
816 else if (aAnyType
== "short")
817 rJsonWriter
.put("value", aValue
.get
<sal_Int16
>());
818 else if (aValue
.has
<OUString
>())
819 rJsonWriter
.put("value", aValue
.get
<OUString
>());
820 else if (aValue
.has
<sal_uInt64
>())
821 rJsonWriter
.put("value", aValue
.get
<sal_Int64
>());
824 // Todo: some more types should be supported..
825 // AddProperty allow these 13 types:
826 // "com.sun.star.util.Date", "DateTime", "DateTimeWithTimezone",
827 // "DateWithTimezone", "Duration", "Time"
828 // typelib_TypeClass_BOOLEAN, typelib_TypeClass_DOUBLE, typelib_TypeClass_FLOAT
829 // typelib_TypeClass_HYPER, typelib_TypeClass_LONG, typelib_TypeClass_SHORT,
830 // typelib_TypeClass_STRING
836 /// Implements getCommandValues(".uno:Sections").
840 /// - namePrefix: field name prefix to not return all sections
841 void GetSections(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
842 const std::map
<OUString
, OUString
>& rArguments
)
844 OUString aNamePrefix
;
846 auto it
= rArguments
.find(u
"namePrefix"_ustr
);
847 if (it
!= rArguments
.end())
849 aNamePrefix
= it
->second
;
853 SwDoc
* pDoc
= pDocShell
->GetDoc();
854 auto aBookmarks
= rJsonWriter
.startArray("sections");
855 for (const auto& pSection
: pDoc
->GetSections())
857 if (!pSection
->GetName().startsWith(aNamePrefix
))
862 auto aProperty
= rJsonWriter
.startStruct();
863 rJsonWriter
.put("name", pSection
->GetName());
868 bool SwXTextDocument::supportsCommand(std::u16string_view rCommand
)
870 static const std::initializer_list
<std::u16string_view
> vForward
871 = { u
"TextFormFields", u
"TextFormField", u
"SetDocumentProperties",
872 u
"Bookmarks", u
"Fields", u
"Sections",
873 u
"Bookmark", u
"Field" };
875 return std::find(vForward
.begin(), vForward
.end(), rCommand
) != vForward
.end();
878 void SwXTextDocument::getCommandValues(tools::JsonWriter
& rJsonWriter
, std::string_view rCommand
)
880 static constexpr OStringLiteral
aTextFormFields(".uno:TextFormFields");
881 static constexpr OStringLiteral
aTextFormField(".uno:TextFormField");
882 static constexpr OStringLiteral
aSetDocumentProperties(".uno:SetDocumentProperties");
883 static constexpr OStringLiteral
aBookmarks(".uno:Bookmarks");
884 static constexpr OStringLiteral
aFields(".uno:Fields");
885 static constexpr OStringLiteral
aSections(".uno:Sections");
886 static constexpr OStringLiteral
aBookmark(".uno:Bookmark");
887 static constexpr OStringLiteral
aField(".uno:Field");
888 static constexpr OStringLiteral
aExtractDocStructure(".uno:ExtractDocumentStructure");
890 std::map
<OUString
, OUString
> aMap
891 = SfxLokHelper::parseCommandParameters(OUString::fromUtf8(rCommand
));
893 if (o3tl::starts_with(rCommand
, aTextFormFields
))
895 GetTextFormFields(rJsonWriter
, m_pDocShell
, aMap
);
897 if (o3tl::starts_with(rCommand
, aTextFormField
))
899 GetTextFormField(rJsonWriter
, m_pDocShell
, aMap
);
901 else if (o3tl::starts_with(rCommand
, aSetDocumentProperties
))
903 GetDocumentProperties(rJsonWriter
, m_pDocShell
, aMap
);
905 else if (o3tl::starts_with(rCommand
, aBookmarks
))
907 GetBookmarks(rJsonWriter
, m_pDocShell
, aMap
);
909 else if (o3tl::starts_with(rCommand
, aFields
))
911 GetFields(rJsonWriter
, m_pDocShell
, aMap
);
913 else if (o3tl::starts_with(rCommand
, aSections
))
915 GetSections(rJsonWriter
, m_pDocShell
, aMap
);
917 else if (o3tl::starts_with(rCommand
, aBookmark
))
919 GetBookmark(rJsonWriter
, m_pDocShell
, aMap
);
921 else if (o3tl::starts_with(rCommand
, aField
))
923 GetField(rJsonWriter
, m_pDocShell
, aMap
);
925 else if (o3tl::starts_with(rCommand
, aExtractDocStructure
))
927 auto commentsNode
= rJsonWriter
.startNode("DocStructure");
929 uno::Reference
<container::XIndexAccess
> xEmbeddeds(getEmbeddedObjects(), uno::UNO_QUERY
);
932 GetDocStructureCharts(rJsonWriter
, m_pDocShell
, aMap
, xEmbeddeds
);
935 uno::Reference
<container::XIndexAccess
> xContentControls
= getContentControls();
936 GetDocStructure(rJsonWriter
, m_pDocShell
, aMap
, xContentControls
);
937 GetDocStructureDocProps(rJsonWriter
, m_pDocShell
, aMap
);
941 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */