docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / sw / source / uibase / uno / loktxdoc.cxx
blob6a2431b2dec3e2e3bf86a9c8574cac9cc1987821
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <map>
23 #include <utility>
24 #include <vector>
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>
36 #include <doc.hxx>
37 #include <docsh.hxx>
38 #include <fmtrfmrk.hxx>
39 #include <wrtsh.hxx>
40 #include <txtrfmrk.hxx>
41 #include <ndtxt.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;
62 namespace
64 /// Implements getCommandValues(".uno:TextFormFields").
65 ///
66 /// Parameters:
67 ///
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)
73 OUString aType;
74 OUString aCommandPrefix;
76 auto it = rArguments.find(u"type"_ustr);
77 if (it != rArguments.end())
79 aType = it->second;
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;
95 assert(pFieldmark);
96 if (pFieldmark->GetFieldname() != aType)
98 continue;
101 auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
102 if (itParam == pFieldmark->GetParameters()->end())
104 continue;
107 OUString aCommand;
108 itParam->second >>= aCommand;
109 if (!aCommand.startsWith(aCommandPrefix))
111 continue;
114 auto aField = rJsonWriter.startStruct();
115 rJsonWriter.put("type", aType);
116 rJsonWriter.put("command", aCommand);
120 /// Implements getCommandValues(".uno:TextFormField").
122 /// Parameters:
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)
129 OUString aType;
130 OUString aCommandPrefix;
131 auto it = rArguments.find(u"type"_ustr);
132 if (it != rArguments.end())
134 aType = it->second;
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");
148 if (!pFieldmark)
150 return;
153 if (pFieldmark->GetFieldname() != aType)
155 return;
158 auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
159 if (itParam == pFieldmark->GetParameters()->end())
161 return;
164 OUString aCommand;
165 itParam->second >>= aCommand;
166 if (!aCommand.startsWith(aCommandPrefix))
168 return;
171 rJsonWriter.put("type", aType);
172 rJsonWriter.put("command", aCommand);
175 /// Implements getCommandValues(".uno:SetDocumentProperties").
177 /// Parameters:
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(),
191 uno::UNO_QUERY);
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))
201 continue;
204 if (rUDP.Value.getValueTypeClass() != uno::TypeClass_STRING)
206 continue;
209 OUString aValue;
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").
221 /// Parameters:
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))
243 continue;
246 auto aProperty = rJsonWriter.startStruct();
247 rJsonWriter.put("name", pMark->GetName());
251 /// Implements getCommandValues(".uno:Bookmark").
253 /// Parameters:
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");
273 if (!pBookmark)
275 return;
278 if (!pBookmark->GetName().startsWith(aNamePrefix))
280 return;
283 rJsonWriter.put("name", pBookmark->GetName());
286 /// Implements getCommandValues(".uno:Fields").
288 /// Parameters:
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)
295 OUString aTypeName;
297 auto it = rArguments.find(u"typeName"_ustr);
298 if (it != rArguments.end())
300 aTypeName = it->second;
303 // See SwFieldTypeFromString().
304 if (aTypeName != "SetRef")
306 return;
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))
339 continue;
342 auto aProperty = rJsonWriter.startStruct();
343 rJsonWriter.put("name", pRefMark->GetRefName());
347 /// Implements getCommandValues(".uno:Field").
349 /// Parameters:
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)
356 OUString aTypeName;
358 auto it = rArguments.find(u"typeName"_ustr);
359 if (it != rArguments.end())
361 aTypeName = it->second;
364 // See SwFieldTypeFromString().
365 if (aTypeName != "SetRef")
367 return;
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");
385 if (aAttrs.empty())
387 return;
390 const SwFormatRefMark& rRefmark = aAttrs[0]->GetRefMark();
391 if (!rRefmark.GetRefName().startsWith(aNamePrefix))
393 return;
396 rJsonWriter.put("name", rRefmark.GetRefName());
399 /// Implements getCommandValues(".uno:ExtractDocumentStructures").
401 /// Parameters:
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))
414 return;
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);
431 sal_Int32 iID = -1;
432 xContentControlProps->getPropertyValue(UNO_NAME_ID) >>= iID;
433 rJsonWriter.put("id", iID);
435 OUString aTag;
436 xContentControlProps->getPropertyValue(UNO_NAME_TAG) >>= aTag;
437 rJsonWriter.put("tag", aTag);
439 OUString aAlias;
440 xContentControlProps->getPropertyValue(UNO_NAME_ALIAS) >>= aAlias;
441 rJsonWriter.put("alias", aAlias);
443 sal_Int32 iType(0);
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;
450 OUString aContent;
451 if (!bShowingPlaceHolder)
453 aContent = xContentControlText->getString();
455 rJsonWriter.put("content", aContent);
457 switch (aType)
459 case SwContentControlType::RICH_TEXT:
461 rJsonWriter.put("type", "rich-text");
463 break;
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));
471 break;
472 case SwContentControlType::DROP_DOWN_LIST:
474 rJsonWriter.put("type", "drop-down-list");
475 // we could list its elements if we want
477 break;
478 case SwContentControlType::PICTURE:
480 rJsonWriter.put("type", "picture");
482 break;
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);
496 break;
497 case SwContentControlType::PLAIN_TEXT:
499 rJsonWriter.put("type", "plain-text");
501 break;
502 case SwContentControlType::COMBO_BOX:
504 rJsonWriter.put("type", "combo-box");
505 // we could list its elements if we want
507 break;
508 default:
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))
524 return;
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())
533 continue;
535 uno::Reference<frame::XModel> xDocModel;
536 xShapeProps->getPropertyValue(u"Model"_ustr) >>= xDocModel;
537 if (!xDocModel.is())
538 continue;
540 uno::Reference<chart2::XChartDocument> xChartDoc(xDocModel, uno::UNO_QUERY);
541 if (!xChartDoc.is())
542 continue;
544 uno::Reference<chart2::data::XDataProvider> xDataProvider(xChartDoc->getDataProvider());
545 if (!xDataProvider.is())
546 continue;
548 uno::Reference<chart::XChartDataArray> xDataArray(xChartDoc->getDataProvider(),
549 uno::UNO_QUERY);
550 if (!xDataArray.is())
551 continue;
553 uno::Reference<chart2::XDiagram> xDiagram = xChartDoc->getFirstDiagram();
554 if (!xDiagram.is())
555 continue;
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())
565 OUString aName;
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);
572 if (xTitled.is())
574 uno::Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
575 if (xTitle.is())
577 OUString aTitle;
578 const uno::Sequence<uno::Reference<chart2::XFormattedString>> aFSSeq
579 = xTitle->getText();
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);
588 if (xSubTitled.is())
590 uno::Reference<chart2::XTitle> xSubTitle = xSubTitled->getTitleObject();
591 if (xSubTitle.is())
593 OUString aSubTitle;
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))
642 return;
645 uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropsSupplier(
646 pDocShell->GetModel(), uno::UNO_QUERY);
647 if (!xDocumentPropsSupplier.is())
648 return;
650 //uno::Reference<document::XDocumentProperties> xDocProps();
651 uno::Reference<document::XDocumentProperties2> xDocProps(
652 xDocumentPropsSupplier->getDocumentProperties(), uno::UNO_QUERY);
653 if (!xDocProps.is())
654 return;
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,
793 uno::UNO_QUERY);
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>());
822 else
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").
838 /// Parameters:
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))
859 continue;
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);
930 if (xEmbeddeds.is())
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: */