[Libreoffice-commits] core.git: sw/inc sw/qa sw/source

László Németh (via logerrit) logerrit at kemper.freedesktop.org
Sun Mar 28 20:03:20 UTC 2021


 sw/inc/inspectorproperties.hrc                        |    1 
 sw/qa/uitest/data/metadata.odt                        |binary
 sw/qa/uitest/styleInspector/styleInspector.py         |   58 ++++++++++++++
 sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx |   70 ++++++++++++++++++
 4 files changed, 129 insertions(+)

New commits:
commit dd45df62d217db59be3f515b6c7e1bfd17ec4350
Author:     László Németh <nemeth at numbertext.org>
AuthorDate: Mon Mar 22 11:39:48 2021 +0100
Commit:     László Németh <nemeth at numbertext.org>
CommitDate: Sun Mar 28 22:02:38 2021 +0200

    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 at numbertext.org>

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
Binary files /dev/null and b/sw/qa/uitest/data/metadata.odt 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);
 


More information about the Libreoffice-commits mailing list