LibreOffice Module sw (master)  1
WriterInspectorTextPanel.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
21 
22 #include <doc.hxx>
23 #include <ndtxt.hxx>
24 #include <docsh.hxx>
25 #include <wrtsh.hxx>
26 #include <unoprnms.hxx>
27 #include <editeng/unoprnms.hxx>
28 #include <com/sun/star/text/XBookmarksSupplier.hpp>
29 #include <com/sun/star/text/XTextSectionsSupplier.hpp>
30 #include <com/sun/star/text/XTextRange.hpp>
31 #include <com/sun/star/text/XTextRangeCompare.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/beans/XPropertyState.hpp>
34 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
35 #include <com/sun/star/table/BorderLine2.hpp>
36 #include <com/sun/star/lang/IllegalArgumentException.hpp>
37 #include <com/sun/star/rdf/XMetadatable.hpp>
38 #include <com/sun/star/rdf/XDocumentMetadataAccess.hpp>
39 #include <com/sun/star/container/XChild.hpp>
40 
41 #include <unotextrange.hxx>
42 #include <comphelper/string.hxx>
45 #include <vcl/settings.hxx>
46 #include <inspectorproperties.hrc>
47 #include <strings.hrc>
48 #include <rdfhelper.hxx>
49 
50 namespace sw::sidebar
51 {
52 static void UpdateTree(SwDocShell* pDocSh, std::vector<svx::sidebar::TreeNode>& aStore,
53  sal_Int32& rParIdx);
54 
55 std::unique_ptr<PanelLayout> WriterInspectorTextPanel::Create(weld::Widget* pParent)
56 {
57  if (pParent == nullptr)
58  throw lang::IllegalArgumentException(
59  "no parent Window given to WriterInspectorTextPanel::Create", nullptr, 0);
60  return std::make_unique<WriterInspectorTextPanel>(pParent);
61 }
62 
64  : InspectorTextPanel(pParent)
65  , m_nParIdx(0)
66 {
67  SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current());
68  m_pShell = pDocSh ? pDocSh->GetWrtShell() : nullptr;
69  if (m_pShell)
70  {
72  m_pShell->SetChgLnk(LINK(this, WriterInspectorTextPanel, AttrChangedNotify));
73  }
74 
75  // Update panel on start
76  std::vector<svx::sidebar::TreeNode> aStore;
77  if (pDocSh && pDocSh->GetDoc()->GetEditShell()->GetCursor()->GetNode().GetTextNode())
78  UpdateTree(pDocSh, aStore, m_nParIdx);
79  updateEntries(aStore, m_nParIdx);
80 }
81 
83 
84 static OUString PropertyNametoRID(const OUString& rName)
85 {
86  static const std::map<OUString, TranslateId> aNameToRID = {
87  { "BorderDistance", RID_BORDER_DISTANCE },
88  { "BottomBorder", RID_BOTTOM_BORDER },
89  { "BottomBorderDistance", RID_BOTTOM_BORDER_DISTANCE },
90  { "BreakType", RID_BREAK_TYPE },
91  { "Category", RID_CATEGORY },
92  { "Cell", RID_CELL },
93  { "CharAutoEscapement", RID_CHAR_AUTO_ESCAPEMENT },
94  { "CharAutoKerning", RID_CHAR_AUTO_KERNING },
95  { "CharAutoStyleName", RID_CHAR_AUTO_STYLE_NAME },
96  { "CharBackColor", RID_CHAR_BACK_COLOR },
97  { "CharBackTransparent", RID_CHAR_BACK_TRANSPARENT },
98  { "CharBorderDistance", RID_CHAR_BORDER_DISTANCE },
99  { "CharBottomBorder", RID_CHAR_BOTTOM_BORDER },
100  { "CharBottomBorderDistance", RID_CHAR_BOTTOM_BORDER_DISTANCE },
101  { "CharCaseMap", RID_CHAR_CASE_MAP },
102  { "CharColor", RID_CHAR_COLOR },
103  { "CharCombineIsOn", RID_CHAR_COMBINE_IS_ON },
104  { "CharCombinePrefix", RID_CHAR_COMBINE_PREFIX },
105  { "CharCombineSuffix", RID_CHAR_COMBINE_SUFFIX },
106  { "CharContoured", RID_CHAR_CONTOURED },
107  { "CharCrossedOut", RID_CHAR_CROSSED_OUT },
108  { "CharDiffHeight", RID_CHAR_DIFF_HEIGHT },
109  { "CharDiffHeightAsian", RID_CHAR_DIFF_HEIGHT_ASIAN },
110  { "CharDiffHeightComplex", RID_CHAR_DIFF_HEIGHT_COMPLEX },
111  { "CharEmphasis", RID_CHAR_EMPHASIS },
112  { "CharEscapement", RID_CHAR_ESCAPEMENT },
113  { "CharEscapementHeight", RID_CHAR_ESCAPEMENT_HEIGHT },
114  { "CharFlash", RID_CHAR_FLASH },
115  { "CharFontCharSet", RID_CHAR_FONT_CHAR_SET },
116  { "CharFontCharSetAsian", RID_CHAR_FONT_CHAR_SET_ASIAN },
117  { "CharFontCharSetComplex", RID_CHAR_FONT_CHAR_SET_COMPLEX },
118  { "CharFontFamily", RID_CHAR_FONT_FAMILY },
119  { "CharFontFamilyAsian", RID_CHAR_FONT_FAMILY_ASIAN },
120  { "CharFontFamilyComplex", RID_CHAR_FONT_FAMILY_COMPLEX },
121  { "CharFontName", RID_CHAR_FONT_NAME },
122  { "CharFontNameAsian", RID_CHAR_FONT_NAME_ASIAN },
123  { "CharFontNameComplex", RID_CHAR_FONT_NAME_COMPLEX },
124  { "CharFontPitch", RID_CHAR_FONT_PITCH },
125  { "CharFontPitchAsian", RID_CHAR_FONT_PITCH_ASIAN },
126  { "CharFontPitchComplex", RID_CHAR_FONT_PITCH_COMPLEX },
127  { "CharFontStyleName", RID_CHAR_FONT_STYLE_NAME },
128  { "CharFontStyleNameAsian", RID_CHAR_FONT_STYLE_NAME_ASIAN },
129  { "CharFontStyleNameComplex", RID_CHAR_FONT_STYLE_NAME_COMPLEX },
130  { "CharHeight", RID_CHAR_HEIGHT },
131  { "CharHeightAsian", RID_CHAR_HEIGHT_ASIAN },
132  { "CharHeightComplex", RID_CHAR_HEIGHT_COMPLEX },
133  { "CharHidden", RID_CHAR_HIDDEN },
134  { "CharHighlight", RID_CHAR_HIGHLIGHT },
135  { "CharInteropGrabBag", RID_CHAR_INTEROP_GRAB_BAG },
136  { "CharKerning", RID_CHAR_KERNING },
137  { "CharLeftBorder", RID_CHAR_LEFT_BORDER },
138  { "CharLeftBorderDistance", RID_CHAR_LEFT_BORDER_DISTANCE },
139  { "CharLocale", RID_CHAR_LOCALE },
140  { "CharLocaleAsian", RID_CHAR_LOCALE_ASIAN },
141  { "CharLocaleComplex", RID_CHAR_LOCALE_COMPLEX },
142  { "CharNoHyphenation", RID_CHAR_NO_HYPHENATION },
143  { "CharOverline", RID_CHAR_OVERLINE },
144  { "CharOverlineColor", RID_CHAR_OVERLINE_COLOR },
145  { "CharOverlineHasColor", RID_CHAR_OVERLINE_HAS_COLOR },
146  { "CharPosture", RID_CHAR_POSTURE },
147  { "CharPostureAsian", RID_CHAR_POSTURE_ASIAN },
148  { "CharPostureComplex", RID_CHAR_POSTURE_COMPLEX },
149  { "CharPropHeight", RID_CHAR_PROP_HEIGHT },
150  { "CharPropHeightAsian", RID_CHAR_PROP_HEIGHT_ASIAN },
151  { "CharPropHeightComplex", RID_CHAR_PROP_HEIGHT_COMPLEX },
152  { "CharRelief", RID_CHAR_RELIEF },
153  { "CharRightBorder", RID_CHAR_RIGHT_BORDER },
154  { "CharRightBorderDistance", RID_CHAR_RIGHT_BORDER_DISTANCE },
155  { "CharRotation", RID_CHAR_ROTATION },
156  { "CharRotationIsFitToLine", RID_CHAR_ROTATION_IS_FIT_TO_LINE },
157  { "CharScaleWidth", RID_CHAR_SCALE_WIDTH },
158  { "CharShadingValue", RID_CHAR_SHADING_VALUE },
159  { "CharShadowFormat", RID_CHAR_SHADOW_FORMAT },
160  { "CharShadowed", RID_CHAR_SHADOWED },
161  { "CharStrikeout", RID_CHAR_STRIKEOUT },
162  { "CharStyleName", RID_CHAR_STYLE_NAME },
163  { "CharStyleNames", RID_CHAR_STYLE_NAMES },
164  { "CharTopBorder", RID_CHAR_TOP_BORDER },
165  { "CharTopBorderDistance", RID_CHAR_TOP_BORDER_DISTANCE },
166  { "CharTransparence", RID_CHAR_TRANSPARENCE },
167  { "CharUnderline", RID_CHAR_UNDERLINE },
168  { "CharUnderlineColor", RID_CHAR_UNDERLINE_COLOR },
169  { "CharUnderlineHasColor", RID_CHAR_UNDERLINE_HAS_COLOR },
170  { "CharWeight", RID_CHAR_WEIGHT },
171  { "CharWeightAsian", RID_CHAR_WEIGHT_ASIAN },
172  { "CharWeightComplex", RID_CHAR_WEIGHT_COMPLEX },
173  { "CharWordMode", RID_CHAR_WORD_MODE },
174  { "ContinueingPreviousSubTree", RID_CONTINUING_PREVIOUS_SUB_TREE },
175  { "DisplayName", RID_DISPLAY_NAME },
176  { "DocumentIndex", RID_DOCUMENT_INDEX },
177  { "DocumentIndexMark", RID_DOCUMENT_INDEX_MARK },
178  { "DropCapCharStyleName", RID_DROP_CAP_CHAR_STYLE_NAME },
179  { "DropCapFormat", RID_DROP_CAP_FORMAT },
180  { "DropCapWholeWord", RID_DROP_CAP_WHOLE_WORD },
181  { "Endnote", RID_ENDNOTE },
182  { "FillBackground", RID_FILL_BACKGROUND },
183  { "FillBitmap", RID_FILL_BITMAP },
184  { "FillBitmapLogicalSize", RID_FILL_BITMAP_LOGICAL_SIZE },
185  { "FillBitmapMode", RID_FILL_BITMAP_MODE },
186  { "FillBitmapName", RID_FILL_BITMAP_NAME },
187  { "FillBitmapOffsetX", RID_FILL_BITMAP_OFFSET_X },
188  { "FillBitmapOffsetY", RID_FILL_BITMAP_OFFSET_Y },
189  { "FillBitmapPositionOffsetX", RID_FILL_BITMAP_POSITION_OFFSET_X },
190  { "FillBitmapPositionOffsetY", RID_FILL_BITMAP_POSITION_OFFSET_Y },
191  { "FillBitmapRectanglePoint", RID_FILL_BITMAP_RECTANGLE_POINT },
192  { "FillBitmapSizeX", RID_FILL_BITMAP_SIZE_X },
193  { "FillBitmapSizeY", RID_FILL_BITMAP_SIZE_Y },
194  { "FillBitmapStretch", RID_FILL_BITMAP_STRETCH },
195  { "FillBitmapTile", RID_FILL_BITMAP_TILE },
196  { "FillBitmapURL", RID_FILL_BITMAP_URL },
197  { "FillColor", RID_FILL_COLOR },
198  { "FillColor2", RID_FILL_COLOR2 },
199  { "FillGradient", RID_FILL_GRADIENT },
200  { "FillGradientName", RID_FILL_GRADIENT_NAME },
201  { "FillGradientStepCount", RID_FILL_GRADIENT_STEP_COUNT },
202  { "FillHatch", RID_FILL_HATCH },
203  { "FillHatchName", RID_FILL_HATCH_NAME },
204  { "FillStyle", RID_FILL_STYLE },
205  { "FillTransparence", RID_FILL_TRANSPARENCE },
206  { "FillTransparenceGradient", RID_FILL_TRANSPARENCE_GRADIENT },
207  { "FillTransparenceGradientName", RID_FILL_TRANSPARENCE_GRADIENT_NAME },
208  { "FollowStyle", RID_FOLLOW_STYLE },
209  { "Footnote", RID_FOOTNOTE },
210  { "Hidden", RID_HIDDEN },
211  { "HyperLinkEvents", RID_HYPERLINK_EVENTS },
212  { "HyperLinkName", RID_HYPERLINK_NAME },
213  { "HyperLinkTarget", RID_HYPERLINK_TARGET },
214  { "HyperLinkURL", RID_HYPERLINK_URL },
215  { "IsAutoUpdate", RID_IS_AUTO_UPDATE },
216  { "IsPhysical", RID_IS_PHYSICAL },
217  { "LeftBorder", RID_LEFT_BORDER },
218  { "LeftBorderDistance", RID_LEFT_BORDER_DISTANCE },
219  { "ListAutoFormat", RID_LIST_AUTO_FORMAT },
220  { "ListId", RID_LIST_ID },
221  { "ListLabelString", RID_LIST_LABEL_STRING },
222  { "MetadataReference", RID_METADATA_REFERENCE },
223  { "NestedTextContent", RID_NESTED_TEXT_CONTENT },
224  { "NumberingIsNumber", RID_NUMBERING_IS_NUMBER },
225  { "NumberingLevel", RID_NUMBERING_LEVEL },
226  { "NumberingRules", RID_NUMBERING_RULES },
227  { "NumberingStartValue", RID_NUMBERING_START_VALUE },
228  { "NumberingStyleName", RID_NUMBERING_STYLE_NAME },
229  { "OutlineContentVisible", RID_OUTLINE_CONTENT_VISIBLE },
230  { "OutlineLevel", RID_OUTLINE_LEVEL },
231  { "PageDescName", RID_PAGE_DESC_NAME },
232  { "PageNumberOffset", RID_PAGE_NUMBER_OFFSET },
233  { "PageStyleName", RID_PAGE_STYLE_NAME },
234  { "ParRsid", RID_PAR_RSID },
235  { "ParaAdjust", RID_PARA_ADJUST },
236  { "ParaAutoStyleName", RID_PARA_AUTO_STYLE_NAME },
237  { "ParaBackColor", RID_PARA_BACK_COLOR },
238  { "ParaBackGraphic", RID_PARA_BACK_GRAPHIC },
239  { "ParaBackGraphicFilter", RID_PARA_BACK_GRAPHIC_FILTER },
240  { "ParaBackGraphicLocation", RID_PARA_BACK_GRAPHIC_LOCATION },
241  { "ParaBackGraphicURL", RID_PARA_BACK_GRAPHIC_URL },
242  { "ParaBackTransparent", RID_PARA_BACK_TRANSPARENT },
243  { "ParaBottomMargin", RID_PARA_BOTTOM_MARGIN },
244  { "ParaBottomMarginRelative", RID_PARA_BOTTOM_MARGIN_RELATIVE },
245  { "ParaChapterNumberingLevel", RID_PARA_CHAPTER_NUMBERING_LEVEL },
246  { "ParaConditionalStyleName", RID_PARA_CONDITIONAL_STYLE_NAME },
247  { "ParaContextMargin", RID_PARA_CONTEXT_MARGIN },
248  { "ParaExpandSingleWord", RID_PARA_EXPAND_SINGLE_WORD },
249  { "ParaFirstLineIndent", RID_PARA_FIRST_LINE_INDENT },
250  { "ParaFirstLineIndentRelative", RID_PARA_FIRST_LINE_INDENT_RELATIVE },
251  { "ParaHyphenationMaxHyphens", RID_PARA_HYPHENATION_MAX_HYPHENS },
252  { "ParaHyphenationMaxLeadingChars", RID_PARA_HYPHENATION_MAX_LEADING_CHARS },
253  { "ParaHyphenationMaxTrailingChars", RID_PARA_HYPHENATION_MAX_TRAILING_CHARS },
254  { "ParaHyphenationNoCaps", RID_PARA_HYPHENATION_NO_CAPS },
255  { "ParaInteropGrabBag", RID_PARA_INTEROP_GRAB_BAG },
256  { "ParaIsAutoFirstLineIndent", RID_PARA_IS_AUTO_FIRST_LINE_INDENT },
257  { "ParaIsCharacterDistance", RID_PARA_IS_CHARACTER_DISTANCE },
258  { "ParaIsConnectBorder", RID_PARA_IS_CONNECT_BORDER },
259  { "ParaIsForbiddenRules", RID_PARA_IS_FORBIDDEN_RULES },
260  { "ParaIsHangingPunctuation", RID_PARA_IS_HANGING_PUNCTUATION },
261  { "ParaIsHyphenation", RID_PARA_IS_HYPHENATION },
262  { "ParaIsNumberingRestart", RID_PARA_IS_NUMBERING_RESTART },
263  { "ParaKeepTogether", RID_PARA_KEEP_TOGETHER },
264  { "ParaLastLineAdjust", RID_PARA_LAST_LINE_ADJUST },
265  { "ParaLeftMargin", RID_PARA_LEFT_MARGIN },
266  { "ParaLeftMarginRelative", RID_PARA_LEFT_MARGIN_RELATIVE },
267  { "ParaLineNumberCount", RID_PARA_LINE_NUMBER_COUNT },
268  { "ParaLineNumberStartValue", RID_PARA_LINE_NUMBER_START_VALUE },
269  { "ParaLineSpacing", RID_PARA_LINE_SPACING },
270  { "ParaOrphans", RID_PARA_ORPHANS },
271  { "ParaRegisterModeActive", RID_PARA_REGISTER_MODE_ACTIVE },
272  { "ParaRightMargin", RID_PARA_RIGHT_MARGIN },
273  { "ParaRightMarginRelative", RID_PARA_RIGHT_MARGIN_RELATIVE },
274  { "ParaShadowFormat", RID_PARA_SHADOW_FORMAT },
275  { "ParaSplit", RID_PARA_SPLIT },
276  { "ParaStyleName", RID_PARA_STYLE_NAME },
277  { "ParaTabStops", RID_PARA_TAB_STOPS },
278  { "ParaTopMargin", RID_PARA_TOP_MARGIN },
279  { "ParaTopMarginRelative", RID_PARA_TOP_MARGIN_RELATIVE },
280  { "ParaUserDefinedAttributes", RID_PARA_USER_DEFINED_ATTRIBUTES },
281  { "ParaVertAlignment", RID_PARA_VERT_ALIGNMENT },
282  { "ParaWidows", RID_PARA_WIDOWS },
283  { "ReferenceMark", RID_REFERENCE_MARK },
284  { "RightBorder", RID_RIGHT_BORDER },
285  { "RightBorderDistance", RID_RIGHT_BORDER_DISTANCE },
286  { "Rsid", RID_RSID },
287  { "RubyAdjust", RID_RUBY_ADJUST },
288  { "RubyCharStyleName", RID_RUBY_CHAR_STYLE_NAME },
289  { "RubyIsAbove", RID_RUBY_IS_ABOVE },
290  { "RubyPosition", RID_RUBY_POSITION },
291  { "RubyText", RID_RUBY_TEXT },
292  { "SnapToGrid", RID_SNAP_TO_GRID },
293  { "StyleInteropGrabBag", RID_STYLE_INTEROP_GRAB_BAG },
294  { "TextField", RID_TEXT_FIELD },
295  { "TextFrame", RID_TEXT_FRAME },
296  { "TextParagraph", RID_TEXT_PARAGRAPH },
297  { "TextSection", RID_TEXT_SECTION },
298  { "TextTable", RID_TEXT_TABLE },
299  { "TextUserDefinedAttributes", RID_TEXT_USER_DEFINED_ATTRIBUTES },
300  { "TopBorder", RID_TOP_BORDER },
301  { "TopBorderDistance", RID_TOP_BORDER_DISTANCE },
302  { "UnvisitedCharStyleName", RID_UNVISITED_CHAR_STYLE_NAME },
303  { "VisitedCharStyleName", RID_VISITED_CHAR_STYLE_NAME },
304  { "WritingMode", RID_WRITING_MODE },
305  { "BorderColor", RID_BORDER_COLOR },
306  { "BorderInnerLineWidth", RID_BORDER_INNER_LINE_WIDTH },
307  { "BorderLineDistance", RID_BORDER_LINE_DISTANCE },
308  { "BorderLineStyle", RID_BORDER_LINE_STYLE },
309  { "BorderLineWidth", RID_BORDER_LINE_WIDTH },
310  { "BorderOuterLineWidth", RID_BORDER_OUTER_LINE_WIDTH },
311  };
312 
313  auto itr = aNameToRID.find(rName);
314  if (itr != aNameToRID.end())
315  return SwResId(itr->second);
316  return rName;
317 }
318 
319 static svx::sidebar::TreeNode SimplePropToTreeNode(const OUString& rName, const css::uno::Any& rVal)
320 {
321  svx::sidebar::TreeNode aCurNode;
322  aCurNode.sNodeName = PropertyNametoRID(rName);
323  aCurNode.aValue = rVal;
324 
325  return aCurNode;
326 }
327 
328 static svx::sidebar::TreeNode BorderToTreeNode(const OUString& rName, const css::uno::Any& rVal)
329 {
330  table::BorderLine2 aBorder;
331  rVal >>= aBorder;
332  svx::sidebar::TreeNode aCurNode;
333  aCurNode.sNodeName = PropertyNametoRID(rName);
335 
336  aCurNode.children.push_back(SimplePropToTreeNode("BorderColor", css::uno::Any(aBorder.Color)));
337  aCurNode.children.push_back(
338  SimplePropToTreeNode("BorderLineWidth", css::uno::Any(aBorder.LineWidth)));
339  aCurNode.children.push_back(
340  SimplePropToTreeNode("BorderLineStyle", css::uno::Any(aBorder.LineStyle)));
341  aCurNode.children.push_back(
342  SimplePropToTreeNode("BorderLineDistance", css::uno::Any(aBorder.LineDistance)));
343  aCurNode.children.push_back(
344  SimplePropToTreeNode("BorderInnerLineWidth", css::uno::Any(aBorder.InnerLineWidth)));
345  aCurNode.children.push_back(
346  SimplePropToTreeNode("BorderOuterLineWidth", css::uno::Any(aBorder.OuterLineWidth)));
347 
348  return aCurNode;
349 }
350 
351 static svx::sidebar::TreeNode LocaleToTreeNode(const OUString& rName, const css::uno::Any& rVal)
352 {
353  svx::sidebar::TreeNode aCurNode;
354  aCurNode.sNodeName = PropertyNametoRID(rName);
355  lang::Locale aLocale;
356  rVal >>= aLocale;
357  OUString aLocaleText(aLocale.Language + "-" + aLocale.Country);
358  if (!aLocale.Variant.isEmpty())
359  aLocaleText += " (" + aLocale.Variant + ")";
360  aCurNode.aValue <<= aLocaleText;
361 
362  return aCurNode;
363 }
364 
365 // Collect text of the current level of the annotated text
366 // ranges (InContentMetadata) and metadata fields (MetadataField)
367 static OUString NestedTextContentToText(const css::uno::Any& rVal)
368 {
369  uno::Reference<container::XEnumerationAccess> xMeta;
370  if (rVal >>= xMeta)
371  {
372  uno::Reference<container::XEnumeration> xMetaPortions = xMeta->createEnumeration();
373 
374  OUStringBuffer aBuf;
375  while (xMetaPortions->hasMoreElements())
376  {
377  uno::Reference<css::text::XTextRange> xRng(xMetaPortions->nextElement(),
378  uno::UNO_QUERY);
379  aBuf.append(xRng->getString());
380  }
381  return aBuf.makeStringAndClear();
382  }
383 
384  return OUString();
385 }
386 
387 // List metadata associated to the paragraph or character range
388 static void MetadataToTreeNode(const css::uno::Reference<css::uno::XInterface>& rSource,
389  svx::sidebar::TreeNode& rNode)
390 {
391  uno::Reference<rdf::XMetadatable> xMeta(rSource, uno::UNO_QUERY_THROW);
392  // don't add tree node "Metadata Reference", if there is no xml:id
393  if (!xMeta.is() || xMeta->getMetadataReference().Second.isEmpty())
394  return;
395 
396  // add metadata of parents for nested annotated text ranges
397  uno::Reference<container::XChild> xChild(rSource, uno::UNO_QUERY);
398  if (xChild.is())
399  {
400  uno::Reference<container::XEnumerationAccess> xParentMeta(xChild->getParent(),
401  uno::UNO_QUERY);
402  if (xParentMeta.is())
403  MetadataToTreeNode(xParentMeta, rNode);
404  }
405 
406  svx::sidebar::TreeNode aCurNode;
407  aCurNode.sNodeName = PropertyNametoRID("MetadataReference");
409 
410  aCurNode.children.push_back(
411  SimplePropToTreeNode("xml:id", uno::Any(xMeta->getMetadataReference().Second)));
412 
413  // list associated (predicate, object) pairs of the actual subject
414  // under the tree node "Metadata Reference"
415  SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current());
416  uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(pDocSh->GetBaseModel(),
417  uno::UNO_QUERY);
418  const uno::Reference<rdf::XRepository>& xRepo = xDocumentMetadataAccess->getRDFRepository();
419  const css::uno::Reference<css::rdf::XResource> xSubject(rSource, uno::UNO_QUERY);
420  std::map<OUString, OUString> xStatements
421  = SwRDFHelper::getStatements(pDocSh->GetBaseModel(), xRepo->getGraphNames(), xSubject);
422  for (const auto& pair : xStatements)
423  aCurNode.children.push_back(SimplePropToTreeNode(pair.first, uno::Any(pair.second)));
424 
425  rNode.children.push_back(aCurNode);
426 }
427 
429 PropertyToTreeNode(const css::beans::Property& rProperty,
430  const uno::Reference<beans::XPropertySet>& xPropertiesSet, const bool rIsGrey)
431 {
432  const OUString& rPropName = rProperty.Name;
433  svx::sidebar::TreeNode aCurNode;
434  const uno::Any aAny = xPropertiesSet->getPropertyValue(rPropName);
435  aCurNode.sNodeName = PropertyNametoRID(rPropName);
436 
437  // These properties are handled separately as they are stored in STRUCT and not in single data members
438  if (rPropName == "CharTopBorder" || rPropName == "CharBottomBorder"
439  || rPropName == "CharLeftBorder" || rPropName == "CharRightBorder"
440  || rPropName == "TopBorder" || rPropName == "BottomBorder" || rPropName == "LeftBorder"
441  || rPropName == "RightBorder")
442  {
443  aCurNode = BorderToTreeNode(rPropName, aAny);
444  }
445  else if (rPropName == "CharLocale")
446  {
447  aCurNode = LocaleToTreeNode(rPropName, aAny);
448  }
449  else
450  aCurNode = SimplePropToTreeNode(rPropName, aAny);
451 
452  if (rIsGrey)
453  {
454  aCurNode.isGrey = true;
455  for (svx::sidebar::TreeNode& rChildNode : aCurNode.children)
456  rChildNode.isGrey = true; // grey out all the children nodes
457  }
458 
459  return aCurNode;
460 }
461 
462 static void InsertValues(const css::uno::Reference<css::uno::XInterface>& rSource,
463  std::unordered_map<OUString, bool>& rIsDefined,
464  svx::sidebar::TreeNode& rNode, const bool isRoot,
465  const std::vector<OUString>& rHiddenProperty,
466  svx::sidebar::TreeNode& rFieldsNode)
467 {
468  uno::Reference<beans::XPropertySet> xPropertiesSet(rSource, uno::UNO_QUERY_THROW);
469  uno::Reference<beans::XPropertyState> xPropertiesState(rSource, uno::UNO_QUERY_THROW);
470  const uno::Sequence<beans::Property> aProperties
471  = xPropertiesSet->getPropertySetInfo()->getProperties();
472 
473  for (const beans::Property& rProperty : aProperties)
474  {
475  const OUString& rPropName = rProperty.Name;
476  if (std::find(rHiddenProperty.begin(), rHiddenProperty.end(), rPropName)
477  != rHiddenProperty.end())
478  continue;
479 
480  if (isRoot
481  || xPropertiesState->getPropertyState(rPropName) == beans::PropertyState_DIRECT_VALUE)
482  {
483  svx::sidebar::TreeNode aCurNode
484  = PropertyToTreeNode(rProperty, xPropertiesSet, rIsDefined[rPropName]);
485  rIsDefined[rPropName] = true;
486 
487  // process NestedTextContent and show associated metadata
488  // under the tree node "Metadata Reference", if they exist
489  if (rPropName == "NestedTextContent")
490  {
491  uno::Reference<container::XEnumerationAccess> xMeta;
492  if (aCurNode.aValue >>= xMeta)
493  MetadataToTreeNode(xMeta, rFieldsNode);
494  aCurNode.aValue <<= NestedTextContentToText(aCurNode.aValue);
495  }
496 
497  rNode.children.push_back(aCurNode);
498  }
499  }
500 
503  Application::GetSettings().GetUILanguageTag().getLocale());
504 
505  std::sort(
506  rNode.children.begin(), rNode.children.end(),
507  [&aSorter](svx::sidebar::TreeNode const& rEntry1, svx::sidebar::TreeNode const& rEntry2) {
508  return aSorter.compare(rEntry1.sNodeName, rEntry2.sNodeName) < 0;
509  });
510 }
511 
512 static void UpdateTree(SwDocShell* pDocSh, std::vector<svx::sidebar::TreeNode>& aStore,
513  sal_Int32& rParIdx)
514 {
515  SwDoc* pDoc = pDocSh->GetDoc();
516  SwPaM* pCursor = pDoc->GetEditShell()->GetCursor();
517  svx::sidebar::TreeNode aCharDFNode;
518  svx::sidebar::TreeNode aCharNode;
519  svx::sidebar::TreeNode aParaNode;
520  svx::sidebar::TreeNode aParaDFNode;
521  svx::sidebar::TreeNode aBookmarksNode;
522  svx::sidebar::TreeNode aFieldsNode;
523  svx::sidebar::TreeNode aTextSectionsNode;
524 
525  aCharNode.sNodeName = SwResId(STR_CHARACTERSTYLEFAMILY);
526  aParaNode.sNodeName = SwResId(STR_PARAGRAPHSTYLEFAMILY);
527  aCharDFNode.sNodeName = SwResId(RID_CHAR_DIRECTFORMAT);
528  aParaDFNode.sNodeName = SwResId(RID_PARA_DIRECTFORMAT);
529  aBookmarksNode.sNodeName = SwResId(STR_CONTENT_TYPE_BOOKMARK);
530  aFieldsNode.sNodeName = SwResId(STR_CONTENT_TYPE_TEXTFIELD);
531  aTextSectionsNode.sNodeName = SwResId(STR_CONTENT_TYPE_REGION);
538  aTextSectionsNode.NodeType = svx::sidebar::TreeNode::Category;
539 
540  uno::Reference<text::XTextRange> xRange(
541  SwXTextRange::CreateXTextRange(*pDoc, *pCursor->GetPoint(), nullptr));
542  uno::Reference<beans::XPropertySet> xPropertiesSet(xRange, uno::UNO_QUERY_THROW);
543  std::unordered_map<OUString, bool> aIsDefined;
544 
545  const std::vector<OUString> aHiddenProperties{ UNO_NAME_RSID,
556 
557  InsertValues(xRange, aIsDefined, aCharDFNode, false, aHiddenProperties, aFieldsNode);
558 
559  uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(pDocSh->GetBaseModel(),
560  uno::UNO_QUERY);
561  uno::Reference<container::XNameAccess> xStyleFamilies
562  = xStyleFamiliesSupplier->getStyleFamilies();
563  OUString sCurrentCharStyle, sCurrentParaStyle, sDisplayName;
564 
565  uno::Reference<container::XNameAccess> xStyleFamily(
566  xStyleFamilies->getByName("CharacterStyles"), uno::UNO_QUERY_THROW);
567  xPropertiesSet->getPropertyValue("CharStyleName") >>= sCurrentCharStyle;
568  xPropertiesSet->getPropertyValue("ParaStyleName") >>= sCurrentParaStyle;
569 
570  if (!sCurrentCharStyle.isEmpty())
571  {
572  xPropertiesSet.set(xStyleFamily->getByName(sCurrentCharStyle), css::uno::UNO_QUERY_THROW);
573  xPropertiesSet->getPropertyValue("DisplayName") >>= sDisplayName;
574  svx::sidebar::TreeNode aCurrentChild;
575  aCurrentChild.sNodeName = sDisplayName;
577 
578  InsertValues(xPropertiesSet, aIsDefined, aCurrentChild, false, {}, aFieldsNode);
579 
580  aCharNode.children.push_back(aCurrentChild);
581  }
582 
583  // Collect paragraph direct formatting
584  uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xRange, uno::UNO_QUERY_THROW);
585  uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
586  uno::Reference<text::XTextRange> xThisParagraphRange(xParaEnum->nextElement(), uno::UNO_QUERY);
587  if (xThisParagraphRange.is())
588  {
589  // Collect metadata of the current paragraph
590  MetadataToTreeNode(xThisParagraphRange, aParaDFNode);
591  InsertValues(xThisParagraphRange, aIsDefined, aParaDFNode, false, aHiddenProperties,
592  aFieldsNode);
593  }
594 
595  xStyleFamily.set(xStyleFamilies->getByName("ParagraphStyles"), uno::UNO_QUERY_THROW);
596 
597  while (!sCurrentParaStyle.isEmpty())
598  {
599  uno::Reference<style::XStyle> xPropertiesStyle(xStyleFamily->getByName(sCurrentParaStyle),
600  uno::UNO_QUERY_THROW);
601  xPropertiesSet.set(xPropertiesStyle, css::uno::UNO_QUERY_THROW);
602  xPropertiesSet->getPropertyValue("DisplayName") >>= sDisplayName;
603  OUString aParentParaStyle = xPropertiesStyle->getParentStyle();
604  svx::sidebar::TreeNode aCurrentChild;
605  aCurrentChild.sNodeName = sDisplayName;
607 
608  InsertValues(xPropertiesSet, aIsDefined, aCurrentChild, aParentParaStyle.isEmpty(), {},
609  aFieldsNode);
610 
611  aParaNode.children.push_back(aCurrentChild);
612  sCurrentParaStyle = aParentParaStyle;
613  }
614 
615  std::reverse(aParaNode.children.begin(),
616  aParaNode.children.end()); // Parent style should be first then children
617 
618  // Collect bookmarks at character position
619  uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(pDocSh->GetBaseModel(),
620  uno::UNO_QUERY);
621 
622  uno::Reference<container::XIndexAccess> xBookmarks(xBookmarksSupplier->getBookmarks(),
623  uno::UNO_QUERY);
624  for (sal_Int32 i = 0; i < xBookmarks->getCount(); ++i)
625  {
626  svx::sidebar::TreeNode aCurNode;
627  uno::Reference<text::XTextContent> bookmark;
628  xBookmarks->getByIndex(i) >>= bookmark;
629  uno::Reference<container::XNamed> xBookmark(bookmark, uno::UNO_QUERY);
630 
631  try
632  {
633  uno::Reference<text::XTextRange> bookmarkRange = bookmark->getAnchor();
634  uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xRange->getText(),
635  uno::UNO_QUERY);
636  if (xTextRangeCompare.is()
637  && xTextRangeCompare->compareRegionStarts(bookmarkRange, xRange) != -1
638  && xTextRangeCompare->compareRegionEnds(xRange, bookmarkRange) != -1)
639  {
640  aCurNode.sNodeName = xBookmark->getName();
642 
643  MetadataToTreeNode(xBookmark, aCurNode);
644  // show bookmark only if it has RDF metadata
645  if (aCurNode.children.size() > 0)
646  aBookmarksNode.children.push_back(aCurNode);
647  }
648  }
649  catch (const lang::IllegalArgumentException&)
650  {
651  }
652  }
653 
654  // Collect sections at character position
655  uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(pDocSh->GetBaseModel(),
656  uno::UNO_QUERY);
657 
658  uno::Reference<container::XIndexAccess> xTextSections(xTextSectionsSupplier->getTextSections(),
659  uno::UNO_QUERY);
660  for (sal_Int32 i = 0; i < xTextSections->getCount(); ++i)
661  {
662  svx::sidebar::TreeNode aCurNode;
663  uno::Reference<text::XTextContent> section;
664  xTextSections->getByIndex(i) >>= section;
665  uno::Reference<container::XNamed> xTextSection(section, uno::UNO_QUERY);
666 
667  try
668  {
669  uno::Reference<text::XTextRange> sectionRange = section->getAnchor();
670  uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xRange->getText(),
671  uno::UNO_QUERY);
672  if (xTextRangeCompare.is()
673  && xTextRangeCompare->compareRegionStarts(sectionRange, xRange) != -1
674  && xTextRangeCompare->compareRegionEnds(xRange, sectionRange) != -1)
675  {
676  aCurNode.sNodeName = xTextSection->getName();
678 
679  MetadataToTreeNode(xTextSection, aCurNode);
680  // show section only if it has RDF metadata
681  if (aCurNode.children.size() > 0)
682  aTextSectionsNode.children.push_back(aCurNode);
683  }
684  }
685  catch (const lang::IllegalArgumentException&)
686  {
687  }
688  }
689 
690  /*
691  Display Order :-
692  SECTIONS with RDF metadata (optional)
693  BOOKMARKS with RDF metadata (optional)
694  FIELDS with RDF metadata (optional)
695  PARAGRAPH STYLE
696  PARAGRAPH DIRECT FORMATTING
697  CHARACTER STYLE
698  DIRECT FORMATTING
699  */
700  rParIdx = 0;
701  // show sections, bookmarks and fields only if they have RDF metadata
702  if (aTextSectionsNode.children.size() > 0)
703  {
704  aStore.push_back(aTextSectionsNode);
705  rParIdx++;
706  }
707  if (aBookmarksNode.children.size() > 0)
708  {
709  aStore.push_back(aBookmarksNode);
710  rParIdx++;
711  }
712  if (aFieldsNode.children.size() > 0)
713  {
714  aStore.push_back(aFieldsNode);
715  rParIdx++;
716  }
717  aStore.push_back(aParaNode);
718  aStore.push_back(aParaDFNode);
719  aStore.push_back(aCharNode);
720  aStore.push_back(aCharDFNode);
721 }
722 
723 IMPL_LINK(WriterInspectorTextPanel, AttrChangedNotify, LinkParamNone*, pLink, void)
724 {
725  if (m_oldLink.IsSet())
726  m_oldLink.Call(pLink);
727 
728  SwDocShell* pDocSh = m_pShell->GetDoc()->GetDocShell();
729  std::vector<svx::sidebar::TreeNode> aStore;
730 
731  if (pDocSh && pDocSh->GetDoc()->GetEditShell()->GetCursor()->GetNode().GetTextNode())
732  UpdateTree(pDocSh, aStore, m_nParIdx);
733 
734  updateEntries(aStore, m_nParIdx);
735 }
736 
737 } // end of namespace svx::sidebar
738 
739 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:224
#define UNO_NAME_RSID
Definition: unoprnms.hxx:822
enum svx::sidebar::TreeNode::@4 NodeType
static const AllSettings & GetSettings()
#define UNO_NAME_PARA_STYLE_NAME
Definition: unoprnms.hxx:175
constexpr OUStringLiteral UNO_NAME_CHAR_STYLE_NAME
Definition: doc.hxx:187
aBuf
static void InsertValues(const css::uno::Reference< css::uno::XInterface > &rSource, std::unordered_map< OUString, bool > &rIsDefined, svx::sidebar::TreeNode &rNode, const bool isRoot, const std::vector< OUString > &rHiddenProperty, svx::sidebar::TreeNode &rFieldsNode)
static svx::sidebar::TreeNode PropertyToTreeNode(const css::beans::Property &rProperty, const uno::Reference< beans::XPropertySet > &xPropertiesSet, const bool rIsGrey)
IMPL_LINK(PageColumnControl, ColumnButtonClickHdl_Impl, weld::Button &, rButton, void)
static SfxObjectShell * Current()
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:164
#define UNO_NAME_PARA_CONDITIONAL_STYLE_NAME
Definition: unoprnms.hxx:466
void updateEntries(const std::vector< TreeNode > &rStore, const sal_Int32 nParIdx)
PropertiesInfo aProperties
static std::map< OUString, OUString > getStatements(const css::uno::Reference< css::frame::XModel > &xModel, const css::uno::Sequence< css::uno::Reference< css::rdf::XURI >> &rGraphNames, const css::uno::Reference< css::rdf::XResource > &xSubject)
Gets all (XResource, key, value) statements in RDF graphs given the graph-names.
static svx::sidebar::TreeNode BorderToTreeNode(const OUString &rName, const css::uno::Any &rVal)
constexpr OUStringLiteral UNO_NAME_NUMBERING_LEVEL
static svx::sidebar::TreeNode LocaleToTreeNode(const OUString &rName, const css::uno::Any &rVal)
void SetChgLnk(const Link< LinkParamNone *, void > &rLnk)
Definition: crsrsh.hxx:488
SwDoc * GetDoc()
returns Doc. But be careful!
Definition: docsh.hxx:204
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:137
static void MetadataToTreeNode(const css::uno::Reference< css::uno::XInterface > &rSource, svx::sidebar::TreeNode &rNode)
css::uno::Any aValue
int i
static OUString NestedTextContentToText(const css::uno::Any &rVal)
const SwPosition * GetPoint() const
Definition: pam.hxx:208
SwEditShell const * GetEditShell() const
Definition: doccorr.cxx:328
static std::unique_ptr< PanelLayout > Create(weld::Widget *pParent)
css::uno::Reference< css::frame::XModel3 > GetBaseModel() const
SwWrtShell * GetWrtShell()
Access to the SwWrtShell belonging to SwView.
Definition: docsh.hxx:225
static svx::sidebar::TreeNode SimplePropToTreeNode(const OUString &rName, const css::uno::Any &rVal)
Shell * m_pShell
#define UNO_NAME_NUMBERING_START_VALUE
Definition: unoprnms.hxx:150
std::vector< TreeNode > children
const Link< LinkParamNone *, void > & GetChgLnk() const
Definition: crsrsh.hxx:489
#define UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE
Definition: unoprnms.hxx:806
#define UNO_NAME_PARRSID
Definition: unoprnms.hxx:823
const LanguageTag & getLocale()
#define UNO_NAME_NUMBERING_IS_NUMBER
Definition: unoprnms.hxx:151
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:195
SvBaseLink * pLink
static OUString PropertyNametoRID(const OUString &rName)
#define UNO_NAME_PARA_IS_NUMBERING_RESTART
Definition: unoprnms.hxx:491
Reference< XComponentContext > getProcessComponentContext()
static void UpdateTree(SwDocShell *pDocSh, std::vector< svx::sidebar::TreeNode > &aStore, sal_Int32 &rParIdx)
sal_Int32 compare(const OUString &rLHS, const OUString &rRHS) const
static css::uno::Reference< css::text::XTextRange > CreateXTextRange(SwDoc &rDoc, const SwPosition &rPos, const SwPosition *const pMark)
Definition: unoobj2.cxx:1214
#define UNO_NAME_PAGE_STYLE_NAME
Definition: unoprnms.hxx:171
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:864
OUString sDisplayName