summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorLászló Németh <nemeth@numbertext.org>2021-03-22 11:39:48 +0100
committerLászló Németh <nemeth@numbertext.org>2021-03-28 22:02:38 +0200
commitdd45df62d217db59be3f515b6c7e1bfd17ec4350 (patch)
tree2d22aaaf268bf193fa13a870100167906fc0e898 /sw
parentecb3be65817c018800355310ba8a88c1227c86e4 (diff)
tdf#30709 sw: show RDF metadata in Style Inspector
Show associated metadata of the actual paragraph (text:p/text:h with xml:id) and annotated text range or metadata fields at the actual cursor position (text:meta and text:meta-field) under the tree node "Metadata Reference". Show text of the annotated text ranges and metadata fields in Character Direct Formatting/Nested Text Content (note: without the text of the children, e.g. helping the detection of unwanted annotations, e.g. annotating the already annotated text range again. In this case, positioning the cursor at the beginning of the outer text range, "Nested Text Content" will show empty text content in the Style Inspector). Change-Id: I2f5149f1f2584d0cf4a4fbbfc4f58f5802844e24 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113259 Tested-by: Jenkins Reviewed-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'sw')
-rw-r--r--sw/inc/inspectorproperties.hrc1
-rw-r--r--sw/qa/uitest/data/metadata.odtbin0 -> 10066 bytes
-rw-r--r--sw/qa/uitest/styleInspector/styleInspector.py58
-rw-r--r--sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx70
4 files changed, 129 insertions, 0 deletions
diff --git a/sw/inc/inspectorproperties.hrc b/sw/inc/inspectorproperties.hrc
index 1de4f7e25c4c..0def6ab41780 100644
--- a/sw/inc/inspectorproperties.hrc
+++ b/sw/inc/inspectorproperties.hrc
@@ -173,6 +173,7 @@
#define RID_LIST_AUTO_FORMAT NC_("RID_ATTRIBUTE_NAMES_MAP", "List Auto Format")
#define RID_LIST_ID NC_("RID_ATTRIBUTE_NAMES_MAP", "List Id")
#define RID_LIST_LABEL_STRING NC_("RID_ATTRIBUTE_NAMES_MAP", "List Label String")
+#define RID_METADATA_REFERENCE NC_("RID_ATTRIBUTE_NAMES_MAP", "Metadata Reference")
#define RID_NESTED_TEXT_CONTENT NC_("RID_ATTRIBUTE_NAMES_MAP", "Nested Text Content")
#define RID_NUMBERING_IS_NUMBER NC_("RID_ATTRIBUTE_NAMES_MAP", "Numbering is Number")
#define RID_NUMBERING_LEVEL NC_("RID_ATTRIBUTE_NAMES_MAP", "Numbering Level")
diff --git a/sw/qa/uitest/data/metadata.odt b/sw/qa/uitest/data/metadata.odt
new file mode 100644
index 000000000000..1566f4ae1d73
--- /dev/null
+++ b/sw/qa/uitest/data/metadata.odt
Binary files differ
diff --git a/sw/qa/uitest/styleInspector/styleInspector.py b/sw/qa/uitest/styleInspector/styleInspector.py
index 1b8cc0c68d90..bd23e8a461c4 100644
--- a/sw/qa/uitest/styleInspector/styleInspector.py
+++ b/sw/qa/uitest/styleInspector/styleInspector.py
@@ -129,4 +129,62 @@ class styleNavigator(UITestCase):
self.xUITest.executeCommand(".uno:Sidebar")
self.ui_test.close_doc()
+ def test_metadata(self):
+ self.ui_test.load_file(get_url_for_data_file("metadata.odt"))
+ xWriterDoc = self.xUITest.getTopFocusWindow()
+ xWriterEdit = xWriterDoc.getChild("writer_edit")
+
+ self.xUITest.executeCommand(".uno:Sidebar")
+ xWriterEdit.executeAction("SIDEBAR", mkPropertyValues({"PANEL": "InspectorTextPanel"}))
+
+ xListBox = xWriterEdit.getChild('listbox_fonts')
+
+ # The cursor is on text without metadata
+ self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
+ self.assertEqual("Default Paragraph Style", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
+ self.assertEqual(136, len(xListBox.getChild('0').getChild('0').getChildren()))
+ self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
+ self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
+ self.assertEqual(0, len(xListBox.getChild('3').getChildren()))
+
+ self.xUITest.executeCommand(".uno:GoDown")
+
+ # The cursor is on text with paragraph metadata showed under direct paragraph formatting
+ self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
+ self.assertEqual("Default Paragraph Style", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
+ self.assertEqual(136, len(xListBox.getChild('0').getChild('0').getChildren()))
+
+ xParDirFormatting = xListBox.getChild('1')
+ self.assertEqual(1, len(xParDirFormatting.getChildren()))
+ self.assertEqual("Metadata Reference", get_state_as_dict(xParDirFormatting.getChild('0'))['Text'])
+
+ xMetadata = xParDirFormatting.getChild('0')
+ self.assertEqual(3, len(xMetadata.getChildren()))
+ self.assertEqual("http://www.w3.org/1999/02/22-rdf-syntax-ns#type\tParagraph", get_state_as_dict(xMetadata.getChild('0'))['Text'])
+ self.assertEqual("http://www.w3.org/2000/01/rdf-schema#comment\tAbout this paragraph...", get_state_as_dict(xMetadata.getChild('1'))['Text'])
+ self.assertEqual("http://www.w3.org/2000/01/rdf-schema#label\tAnnotated paragraph", get_state_as_dict(xMetadata.getChild('2'))['Text'])
+
+ self.xUITest.executeCommand(".uno:GoDown")
+ # FIXME jump over the control character (not visible in getString(), but it affects
+ # cursor position and avabiality of NestedTextContent)
+ self.xUITest.executeCommand(".uno:GoRight")
+
+ # The cursor is on text with annotated text range
+ xDirFormatting = xListBox.getChild('3')
+ self.assertEqual(2, len(xDirFormatting.getChildren()))
+ self.assertEqual("Metadata Reference", get_state_as_dict(xDirFormatting.getChild('0'))['Text'])
+ self.assertEqual("Nested Text Content\tAnnotated text range", get_state_as_dict(xDirFormatting.getChild('1'))['Text'])
+
+ xMetadata = xDirFormatting.getChild('0')
+ self.assertEqual(3, len(xMetadata.getChildren()))
+ self.assertEqual("http://www.w3.org/1999/02/22-rdf-syntax-ns#type\tText span", get_state_as_dict(xMetadata.getChild('0'))['Text'])
+ self.assertEqual("http://www.w3.org/2000/01/rdf-schema#comment\tComment...", get_state_as_dict(xMetadata.getChild('1'))['Text'])
+ self.assertEqual("http://www.w3.org/2000/01/rdf-schema#label\tAnnotated paragraph portion", get_state_as_dict(xMetadata.getChild('2'))['Text'])
+
+ self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
+ self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
+
+ self.xUITest.executeCommand(".uno:Sidebar")
+ self.ui_test.close_doc()
+
# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
index 959c2bd48a25..f1d23ad05ad7 100644
--- a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
+++ b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx
@@ -32,6 +32,8 @@
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
#include <com/sun/star/table/BorderLine2.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/rdf/XMetadatable.hpp>
+#include <com/sun/star/rdf/XDocumentMetadataAccess.hpp>
#include <unotextrange.hxx>
#include <comphelper/string.hxx>
@@ -40,6 +42,7 @@
#include <vcl/settings.hxx>
#include <inspectorproperties.hrc>
#include <strings.hrc>
+#include <rdfhelper.hxx>
namespace sw::sidebar
{
@@ -211,6 +214,7 @@ static OUString PropertyNametoRID(const OUString& rName)
{ "ListAutoFormat", RID_LIST_AUTO_FORMAT },
{ "ListId", RID_LIST_ID },
{ "ListLabelString", RID_LIST_LABEL_STRING },
+ { "MetadataReference", RID_METADATA_REFERENCE },
{ "NestedTextContent", RID_NESTED_TEXT_CONTENT },
{ "NumberingIsNumber", RID_NUMBERING_IS_NUMBER },
{ "NumberingLevel", RID_NUMBERING_LEVEL },
@@ -353,6 +357,57 @@ static svx::sidebar::TreeNode LocaleToTreeNode(const OUString& rName, const css:
return aCurNode;
}
+// Collect text of the current level of the annotated text
+// ranges (InContentMetadata) and metadata fields (MetadataField)
+static OUString NestedTextContentToText(const css::uno::Any& rVal)
+{
+ uno::Reference<container::XEnumerationAccess> xMeta;
+ if (rVal >>= xMeta)
+ {
+ uno::Reference<container::XEnumeration> xMetaPortions = xMeta->createEnumeration();
+
+ OUStringBuffer aBuf;
+ while (xMetaPortions->hasMoreElements())
+ {
+ uno::Reference<css::text::XTextRange> xRng(xMetaPortions->nextElement(),
+ uno::UNO_QUERY);
+ aBuf.append(xRng->getString());
+ }
+ return aBuf.makeStringAndClear();
+ }
+
+ return OUString();
+}
+
+// List metadata associated to the paragraph or character range
+static void MetadataToTreeNode(const css::uno::Reference<css::uno::XInterface>& rSource,
+ svx::sidebar::TreeNode& rNode)
+{
+ uno::Reference<rdf::XMetadatable> xMeta(rSource, uno::UNO_QUERY_THROW);
+ // don't add tree node "Metadata Reference", if there is no xml:id
+ if (xMeta.is() && !xMeta->getMetadataReference().Second.isEmpty())
+ {
+ svx::sidebar::TreeNode aCurNode;
+ aCurNode.sNodeName = PropertyNametoRID("MetadataReference");
+ aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty;
+
+ // list associated (predicate, object) pairs of the actual subject
+ // under the tree node "Metadata Reference"
+ SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current());
+ uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(pDocSh->GetBaseModel(),
+ uno::UNO_QUERY);
+ const uno::Reference<rdf::XRepository>& xRepo = xDocumentMetadataAccess->getRDFRepository();
+ const css::uno::Reference<css::rdf::XResource> xSubject(rSource, uno::UNO_QUERY);
+ std::map<OUString, OUString> xStatements
+ = SwRDFHelper::getStatements(pDocSh->GetBaseModel(), xRepo->getGraphNames(), xSubject);
+ for (const auto& pair : xStatements)
+ aCurNode.children.push_back(
+ SimplePropToTreeNode(pair.first, uno::makeAny(pair.second)));
+
+ rNode.children.push_back(aCurNode);
+ }
+}
+
static svx::sidebar::TreeNode
PropertyToTreeNode(const css::beans::Property& rProperty,
const uno::Reference<beans::XPropertySet>& xPropertiesSet, const bool rIsGrey)
@@ -410,6 +465,17 @@ static void InsertValues(const css::uno::Reference<css::uno::XInterface>& rSourc
svx::sidebar::TreeNode aCurNode
= PropertyToTreeNode(rProperty, xPropertiesSet, rIsDefined[rPropName]);
rIsDefined[rPropName] = true;
+
+ // process NestedTextContent and show associated metadata
+ // under the tree node "Metadata Reference", if they exist
+ if (rPropName == "NestedTextContent")
+ {
+ uno::Reference<container::XEnumerationAccess> xMeta;
+ if (aCurNode.aValue >>= xMeta)
+ MetadataToTreeNode(xMeta, rNode);
+ aCurNode.aValue <<= NestedTextContentToText(aCurNode.aValue);
+ }
+
rNode.children.push_back(aCurNode);
}
}
@@ -491,7 +557,11 @@ static void UpdateTree(SwDocShell* pDocSh, std::vector<svx::sidebar::TreeNode>&
uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
uno::Reference<text::XTextRange> xThisParagraphRange(xParaEnum->nextElement(), uno::UNO_QUERY);
if (xThisParagraphRange.is())
+ {
+ // Collect metadata of the current paragraph
+ MetadataToTreeNode(xThisParagraphRange, aParaDFNode);
InsertValues(xThisParagraphRange, aIsDefined, aParaDFNode, false, aHiddenProperties);
+ }
xStyleFamily.set(xStyleFamilies->getByName("ParagraphStyles"), uno::UNO_QUERY_THROW);