Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / uibase / sidebar / WriterInspectorTextPanel.cxx
blob63b952f0fa861024793211b85470506ae8519d59
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 "WriterInspectorTextPanel.hxx"
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>
41 #include <unotextrange.hxx>
42 #include <comphelper/string.hxx>
43 #include <comphelper/processfactory.hxx>
44 #include <i18nlangtag/languagetag.hxx>
45 #include <vcl/settings.hxx>
46 #include <inspectorproperties.hrc>
47 #include <strings.hrc>
48 #include <rdfhelper.hxx>
50 namespace sw::sidebar
52 static void UpdateTree(SwDocShell& rDocSh, SwEditShell& rEditSh,
53 std::vector<svx::sidebar::TreeNode>& aStore, sal_Int32& rParIdx);
55 std::unique_ptr<PanelLayout> WriterInspectorTextPanel::Create(weld::Widget* pParent)
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);
63 WriterInspectorTextPanel::WriterInspectorTextPanel(weld::Widget* pParent)
64 : InspectorTextPanel(pParent)
65 , m_nParIdx(0)
67 SwDocShell* pDocSh = dynamic_cast<SwDocShell*>(SfxObjectShell::Current());
68 m_pShell = pDocSh ? pDocSh->GetWrtShell() : nullptr;
69 if (m_pShell)
71 m_oldLink = m_pShell->GetChgLnk();
72 m_pShell->SetChgLnk(LINK(this, WriterInspectorTextPanel, AttrChangedNotify));
74 // tdf#154629 listen to know if the shell destructs before this panel does,
75 // which can happen on entering print preview
76 m_pShell->Add(this);
79 // Update panel on start
80 std::vector<svx::sidebar::TreeNode> aStore;
81 SwEditShell* pEditSh = pDocSh ? pDocSh->GetDoc()->GetEditShell() : nullptr;
82 if (pEditSh && pEditSh->GetCursor()->GetPointNode().GetTextNode())
83 UpdateTree(*pDocSh, *pEditSh, aStore, m_nParIdx);
84 updateEntries(aStore, m_nParIdx);
87 void WriterInspectorTextPanel::SwClientNotify(const SwModify& rModify, const SfxHint& rHint)
89 if (rHint.GetId() == SfxHintId::SwLegacyModify)
91 const sw::LegacyModifyHint& rLegacy = static_cast<const sw::LegacyModifyHint&>(rHint);
92 if (rLegacy.GetWhich() == RES_OBJECTDYING)
93 m_pShell = nullptr;
95 SwClient::SwClientNotify(rModify, rHint);
98 WriterInspectorTextPanel::~WriterInspectorTextPanel()
100 if (m_pShell)
102 m_pShell->SetChgLnk(m_oldLink);
103 m_pShell->Remove(this);
107 static OUString PropertyNametoRID(const OUString& rName)
109 static const std::map<OUString, TranslateId> aNameToRID = {
110 { "BorderDistance", RID_BORDER_DISTANCE },
111 { "BottomBorder", RID_BOTTOM_BORDER },
112 { "BottomBorderDistance", RID_BOTTOM_BORDER_DISTANCE },
113 { "BreakType", RID_BREAK_TYPE },
114 { "Category", RID_CATEGORY },
115 { "Cell", RID_CELL },
116 { "CharAutoEscapement", RID_CHAR_AUTO_ESCAPEMENT },
117 { "CharAutoKerning", RID_CHAR_AUTO_KERNING },
118 { "CharAutoStyleName", RID_CHAR_AUTO_STYLE_NAME },
119 { "CharBackColor", RID_CHAR_BACK_COLOR },
120 { "CharBackTransparent", RID_CHAR_BACK_TRANSPARENT },
121 { "CharBorderDistance", RID_CHAR_BORDER_DISTANCE },
122 { "CharBottomBorder", RID_CHAR_BOTTOM_BORDER },
123 { "CharBottomBorderDistance", RID_CHAR_BOTTOM_BORDER_DISTANCE },
124 { "CharCaseMap", RID_CHAR_CASE_MAP },
125 { "CharColor", RID_CHAR_COLOR },
126 { "CharCombineIsOn", RID_CHAR_COMBINE_IS_ON },
127 { "CharCombinePrefix", RID_CHAR_COMBINE_PREFIX },
128 { "CharCombineSuffix", RID_CHAR_COMBINE_SUFFIX },
129 { "CharContoured", RID_CHAR_CONTOURED },
130 { "CharCrossedOut", RID_CHAR_CROSSED_OUT },
131 { "CharDiffHeight", RID_CHAR_DIFF_HEIGHT },
132 { "CharDiffHeightAsian", RID_CHAR_DIFF_HEIGHT_ASIAN },
133 { "CharDiffHeightComplex", RID_CHAR_DIFF_HEIGHT_COMPLEX },
134 { "CharEmphasis", RID_CHAR_EMPHASIS },
135 { "CharEscapement", RID_CHAR_ESCAPEMENT },
136 { "CharEscapementHeight", RID_CHAR_ESCAPEMENT_HEIGHT },
137 { "CharFlash", RID_CHAR_FLASH },
138 { "CharFontCharSet", RID_CHAR_FONT_CHAR_SET },
139 { "CharFontCharSetAsian", RID_CHAR_FONT_CHAR_SET_ASIAN },
140 { "CharFontCharSetComplex", RID_CHAR_FONT_CHAR_SET_COMPLEX },
141 { "CharFontFamily", RID_CHAR_FONT_FAMILY },
142 { "CharFontFamilyAsian", RID_CHAR_FONT_FAMILY_ASIAN },
143 { "CharFontFamilyComplex", RID_CHAR_FONT_FAMILY_COMPLEX },
144 { "CharFontName", RID_CHAR_FONT_NAME },
145 { "CharFontNameAsian", RID_CHAR_FONT_NAME_ASIAN },
146 { "CharFontNameComplex", RID_CHAR_FONT_NAME_COMPLEX },
147 { "CharFontPitch", RID_CHAR_FONT_PITCH },
148 { "CharFontPitchAsian", RID_CHAR_FONT_PITCH_ASIAN },
149 { "CharFontPitchComplex", RID_CHAR_FONT_PITCH_COMPLEX },
150 { "CharFontStyleName", RID_CHAR_FONT_STYLE_NAME },
151 { "CharFontStyleNameAsian", RID_CHAR_FONT_STYLE_NAME_ASIAN },
152 { "CharFontStyleNameComplex", RID_CHAR_FONT_STYLE_NAME_COMPLEX },
153 { "CharHeight", RID_CHAR_HEIGHT },
154 { "CharHeightAsian", RID_CHAR_HEIGHT_ASIAN },
155 { "CharHeightComplex", RID_CHAR_HEIGHT_COMPLEX },
156 { "CharHidden", RID_CHAR_HIDDEN },
157 { "CharHighlight", RID_CHAR_HIGHLIGHT },
158 { "CharInteropGrabBag", RID_CHAR_INTEROP_GRAB_BAG },
159 { "CharKerning", RID_CHAR_KERNING },
160 { "CharLeftBorder", RID_CHAR_LEFT_BORDER },
161 { "CharLeftBorderDistance", RID_CHAR_LEFT_BORDER_DISTANCE },
162 { "CharLocale", RID_CHAR_LOCALE },
163 { "CharLocaleAsian", RID_CHAR_LOCALE_ASIAN },
164 { "CharLocaleComplex", RID_CHAR_LOCALE_COMPLEX },
165 { "CharNoHyphenation", RID_CHAR_NO_HYPHENATION },
166 { "CharOverline", RID_CHAR_OVERLINE },
167 { "CharOverlineColor", RID_CHAR_OVERLINE_COLOR },
168 { "CharOverlineHasColor", RID_CHAR_OVERLINE_HAS_COLOR },
169 { "CharPosture", RID_CHAR_POSTURE },
170 { "CharPostureAsian", RID_CHAR_POSTURE_ASIAN },
171 { "CharPostureComplex", RID_CHAR_POSTURE_COMPLEX },
172 { "CharPropHeight", RID_CHAR_PROP_HEIGHT },
173 { "CharPropHeightAsian", RID_CHAR_PROP_HEIGHT_ASIAN },
174 { "CharPropHeightComplex", RID_CHAR_PROP_HEIGHT_COMPLEX },
175 { "CharRelief", RID_CHAR_RELIEF },
176 { "CharRightBorder", RID_CHAR_RIGHT_BORDER },
177 { "CharRightBorderDistance", RID_CHAR_RIGHT_BORDER_DISTANCE },
178 { "CharRotation", RID_CHAR_ROTATION },
179 { "CharRotationIsFitToLine", RID_CHAR_ROTATION_IS_FIT_TO_LINE },
180 { "CharScaleWidth", RID_CHAR_SCALE_WIDTH },
181 { "CharShadingValue", RID_CHAR_SHADING_VALUE },
182 { "CharShadowFormat", RID_CHAR_SHADOW_FORMAT },
183 { "CharShadowed", RID_CHAR_SHADOWED },
184 { "CharStrikeout", RID_CHAR_STRIKEOUT },
185 { "CharStyleName", RID_CHAR_STYLE_NAME },
186 { "CharStyleNames", RID_CHAR_STYLE_NAMES },
187 { "CharTopBorder", RID_CHAR_TOP_BORDER },
188 { "CharTopBorderDistance", RID_CHAR_TOP_BORDER_DISTANCE },
189 { "CharTransparence", RID_CHAR_TRANSPARENCE },
190 { "CharUnderline", RID_CHAR_UNDERLINE },
191 { "CharUnderlineColor", RID_CHAR_UNDERLINE_COLOR },
192 { "CharUnderlineHasColor", RID_CHAR_UNDERLINE_HAS_COLOR },
193 { "CharWeight", RID_CHAR_WEIGHT },
194 { "CharWeightAsian", RID_CHAR_WEIGHT_ASIAN },
195 { "CharWeightComplex", RID_CHAR_WEIGHT_COMPLEX },
196 { "CharWordMode", RID_CHAR_WORD_MODE },
197 { "ContinueingPreviousSubTree", RID_CONTINUING_PREVIOUS_SUB_TREE },
198 { "DisplayName", RID_DISPLAY_NAME },
199 { "DocumentIndex", RID_DOCUMENT_INDEX },
200 { "DocumentIndexMark", RID_DOCUMENT_INDEX_MARK },
201 { "DropCapCharStyleName", RID_DROP_CAP_CHAR_STYLE_NAME },
202 { "DropCapFormat", RID_DROP_CAP_FORMAT },
203 { "DropCapWholeWord", RID_DROP_CAP_WHOLE_WORD },
204 { "Endnote", RID_ENDNOTE },
205 { "FillBackground", RID_FILL_BACKGROUND },
206 { "FillBitmap", RID_FILL_BITMAP },
207 { "FillBitmapLogicalSize", RID_FILL_BITMAP_LOGICAL_SIZE },
208 { "FillBitmapMode", RID_FILL_BITMAP_MODE },
209 { "FillBitmapName", RID_FILL_BITMAP_NAME },
210 { "FillBitmapOffsetX", RID_FILL_BITMAP_OFFSET_X },
211 { "FillBitmapOffsetY", RID_FILL_BITMAP_OFFSET_Y },
212 { "FillBitmapPositionOffsetX", RID_FILL_BITMAP_POSITION_OFFSET_X },
213 { "FillBitmapPositionOffsetY", RID_FILL_BITMAP_POSITION_OFFSET_Y },
214 { "FillBitmapRectanglePoint", RID_FILL_BITMAP_RECTANGLE_POINT },
215 { "FillBitmapSizeX", RID_FILL_BITMAP_SIZE_X },
216 { "FillBitmapSizeY", RID_FILL_BITMAP_SIZE_Y },
217 { "FillBitmapStretch", RID_FILL_BITMAP_STRETCH },
218 { "FillBitmapTile", RID_FILL_BITMAP_TILE },
219 { "FillBitmapURL", RID_FILL_BITMAP_URL },
220 { "FillColor", RID_FILL_COLOR },
221 { "FillColor2", RID_FILL_COLOR2 },
222 { "FillGradient", RID_FILL_GRADIENT },
223 { "FillGradientName", RID_FILL_GRADIENT_NAME },
224 { "FillGradientStepCount", RID_FILL_GRADIENT_STEP_COUNT },
225 { "FillHatch", RID_FILL_HATCH },
226 { "FillHatchName", RID_FILL_HATCH_NAME },
227 { "FillStyle", RID_FILL_STYLE },
228 { "FillTransparence", RID_FILL_TRANSPARENCE },
229 { "FillTransparenceGradient", RID_FILL_TRANSPARENCE_GRADIENT },
230 { "FillTransparenceGradientName", RID_FILL_TRANSPARENCE_GRADIENT_NAME },
231 { "FollowStyle", RID_FOLLOW_STYLE },
232 { "Footnote", RID_FOOTNOTE },
233 { "Hidden", RID_HIDDEN },
234 { "HyperLinkEvents", RID_HYPERLINK_EVENTS },
235 { "HyperLinkName", RID_HYPERLINK_NAME },
236 { "HyperLinkTarget", RID_HYPERLINK_TARGET },
237 { "HyperLinkURL", RID_HYPERLINK_URL },
238 { "IsAutoUpdate", RID_IS_AUTO_UPDATE },
239 { "IsPhysical", RID_IS_PHYSICAL },
240 { "LeftBorder", RID_LEFT_BORDER },
241 { "LeftBorderDistance", RID_LEFT_BORDER_DISTANCE },
242 { "ListAutoFormat", RID_LIST_AUTO_FORMAT },
243 { "ListId", RID_LIST_ID },
244 { "ListLabelString", RID_LIST_LABEL_STRING },
245 { "MetadataReference", RID_METADATA_REFERENCE },
246 { "NestedTextContent", RID_NESTED_TEXT_CONTENT },
247 { "NumberingIsNumber", RID_NUMBERING_IS_NUMBER },
248 { "NumberingLevel", RID_NUMBERING_LEVEL },
249 { "NumberingRules", RID_NUMBERING_RULES },
250 { "NumberingStartValue", RID_NUMBERING_START_VALUE },
251 { "NumberingStyleName", RID_NUMBERING_STYLE_NAME },
252 { "OutlineContentVisible", RID_OUTLINE_CONTENT_VISIBLE },
253 { "OutlineLevel", RID_OUTLINE_LEVEL },
254 { "PageDescName", RID_PAGE_DESC_NAME },
255 { "PageNumberOffset", RID_PAGE_NUMBER_OFFSET },
256 { "PageStyleName", RID_PAGE_STYLE_NAME },
257 { "ParRsid", RID_PAR_RSID },
258 { "ParaAdjust", RID_PARA_ADJUST },
259 { "ParaAutoStyleName", RID_PARA_AUTO_STYLE_NAME },
260 { "ParaBackColor", RID_PARA_BACK_COLOR },
261 { "ParaBackGraphic", RID_PARA_BACK_GRAPHIC },
262 { "ParaBackGraphicFilter", RID_PARA_BACK_GRAPHIC_FILTER },
263 { "ParaBackGraphicLocation", RID_PARA_BACK_GRAPHIC_LOCATION },
264 { "ParaBackGraphicURL", RID_PARA_BACK_GRAPHIC_URL },
265 { "ParaBackTransparent", RID_PARA_BACK_TRANSPARENT },
266 { "ParaBottomMargin", RID_PARA_BOTTOM_MARGIN },
267 { "ParaBottomMarginRelative", RID_PARA_BOTTOM_MARGIN_RELATIVE },
268 { "ParaChapterNumberingLevel", RID_PARA_CHAPTER_NUMBERING_LEVEL },
269 { "ParaConditionalStyleName", RID_PARA_CONDITIONAL_STYLE_NAME },
270 { "ParaContextMargin", RID_PARA_CONTEXT_MARGIN },
271 { "ParaExpandSingleWord", RID_PARA_EXPAND_SINGLE_WORD },
272 { "ParaFirstLineIndent", RID_PARA_FIRST_LINE_INDENT },
273 { "ParaFirstLineIndentRelative", RID_PARA_FIRST_LINE_INDENT_RELATIVE },
274 { "ParaHyphenationMaxHyphens", RID_PARA_HYPHENATION_MAX_HYPHENS },
275 { "ParaHyphenationMaxLeadingChars", RID_PARA_HYPHENATION_MAX_LEADING_CHARS },
276 { "ParaHyphenationMaxTrailingChars", RID_PARA_HYPHENATION_MAX_TRAILING_CHARS },
277 { "ParaHyphenationNoCaps", RID_PARA_HYPHENATION_NO_CAPS },
278 { "ParaHyphenationNoLastWord", RID_PARA_HYPHENATION_NO_LAST_WORD },
279 { "ParaHyphenationMinWordLength", RID_PARA_HYPHENATION_MIN_WORD_LENGTH },
280 { "ParaHyphenationZone", RID_PARA_HYPHENATION_ZONE },
281 { "ParaInteropGrabBag", RID_PARA_INTEROP_GRAB_BAG },
282 { "ParaIsAutoFirstLineIndent", RID_PARA_IS_AUTO_FIRST_LINE_INDENT },
283 { "ParaIsCharacterDistance", RID_PARA_IS_CHARACTER_DISTANCE },
284 { "ParaIsConnectBorder", RID_PARA_IS_CONNECT_BORDER },
285 { "ParaIsForbiddenRules", RID_PARA_IS_FORBIDDEN_RULES },
286 { "ParaIsHangingPunctuation", RID_PARA_IS_HANGING_PUNCTUATION },
287 { "ParaIsHyphenation", RID_PARA_IS_HYPHENATION },
288 { "ParaIsNumberingRestart", RID_PARA_IS_NUMBERING_RESTART },
289 { "ParaKeepTogether", RID_PARA_KEEP_TOGETHER },
290 { "ParaLastLineAdjust", RID_PARA_LAST_LINE_ADJUST },
291 { "ParaLeftMargin", RID_PARA_LEFT_MARGIN },
292 { "ParaLeftMarginRelative", RID_PARA_LEFT_MARGIN_RELATIVE },
293 { "ParaLineNumberCount", RID_PARA_LINE_NUMBER_COUNT },
294 { "ParaLineNumberStartValue", RID_PARA_LINE_NUMBER_START_VALUE },
295 { "ParaLineSpacing", RID_PARA_LINE_SPACING },
296 { "ParaOrphans", RID_PARA_ORPHANS },
297 { "ParaRegisterModeActive", RID_PARA_REGISTER_MODE_ACTIVE },
298 { "ParaRightMargin", RID_PARA_RIGHT_MARGIN },
299 { "ParaRightMarginRelative", RID_PARA_RIGHT_MARGIN_RELATIVE },
300 { "ParaShadowFormat", RID_PARA_SHADOW_FORMAT },
301 { "ParaSplit", RID_PARA_SPLIT },
302 { "ParaStyleName", RID_PARA_STYLE_NAME },
303 { "ParaTabStops", RID_PARA_TAB_STOPS },
304 { "ParaTopMargin", RID_PARA_TOP_MARGIN },
305 { "ParaTopMarginRelative", RID_PARA_TOP_MARGIN_RELATIVE },
306 { "ParaUserDefinedAttributes", RID_PARA_USER_DEFINED_ATTRIBUTES },
307 { "ParaVertAlignment", RID_PARA_VERT_ALIGNMENT },
308 { "ParaWidows", RID_PARA_WIDOWS },
309 { "ReferenceMark", RID_REFERENCE_MARK },
310 { "RightBorder", RID_RIGHT_BORDER },
311 { "RightBorderDistance", RID_RIGHT_BORDER_DISTANCE },
312 { "Rsid", RID_RSID },
313 { "RubyAdjust", RID_RUBY_ADJUST },
314 { "RubyCharStyleName", RID_RUBY_CHAR_STYLE_NAME },
315 { "RubyIsAbove", RID_RUBY_IS_ABOVE },
316 { "RubyPosition", RID_RUBY_POSITION },
317 { "RubyText", RID_RUBY_TEXT },
318 { "SnapToGrid", RID_SNAP_TO_GRID },
319 { "StyleInteropGrabBag", RID_STYLE_INTEROP_GRAB_BAG },
320 { "TextField", RID_TEXT_FIELD },
321 { "TextFrame", RID_TEXT_FRAME },
322 { "TextParagraph", RID_TEXT_PARAGRAPH },
323 { "TextSection", RID_TEXT_SECTION },
324 { "TextTable", RID_TEXT_TABLE },
325 { "TextUserDefinedAttributes", RID_TEXT_USER_DEFINED_ATTRIBUTES },
326 { "TopBorder", RID_TOP_BORDER },
327 { "TopBorderDistance", RID_TOP_BORDER_DISTANCE },
328 { "UnvisitedCharStyleName", RID_UNVISITED_CHAR_STYLE_NAME },
329 { "VisitedCharStyleName", RID_VISITED_CHAR_STYLE_NAME },
330 { "WritingMode", RID_WRITING_MODE },
331 { "BorderColor", RID_BORDER_COLOR },
332 { "BorderInnerLineWidth", RID_BORDER_INNER_LINE_WIDTH },
333 { "BorderLineDistance", RID_BORDER_LINE_DISTANCE },
334 { "BorderLineStyle", RID_BORDER_LINE_STYLE },
335 { "BorderLineWidth", RID_BORDER_LINE_WIDTH },
336 { "BorderOuterLineWidth", RID_BORDER_OUTER_LINE_WIDTH },
339 auto itr = aNameToRID.find(rName);
340 if (itr != aNameToRID.end())
341 return SwResId(itr->second);
342 return rName;
345 static svx::sidebar::TreeNode SimplePropToTreeNode(const OUString& rName, const css::uno::Any& rVal)
347 svx::sidebar::TreeNode aCurNode;
348 aCurNode.sNodeName = PropertyNametoRID(rName);
349 aCurNode.aValue = rVal;
351 return aCurNode;
354 static svx::sidebar::TreeNode BorderToTreeNode(const OUString& rName, const css::uno::Any& rVal)
356 table::BorderLine2 aBorder;
357 rVal >>= aBorder;
358 svx::sidebar::TreeNode aCurNode;
359 aCurNode.sNodeName = PropertyNametoRID(rName);
360 aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty;
362 aCurNode.children
363 = { SimplePropToTreeNode("BorderColor", css::uno::Any(aBorder.Color)),
364 SimplePropToTreeNode("BorderLineWidth", css::uno::Any(aBorder.LineWidth)),
365 SimplePropToTreeNode("BorderLineStyle", css::uno::Any(aBorder.LineStyle)),
366 SimplePropToTreeNode("BorderLineDistance", css::uno::Any(aBorder.LineDistance)),
367 SimplePropToTreeNode("BorderInnerLineWidth", css::uno::Any(aBorder.InnerLineWidth)),
368 SimplePropToTreeNode("BorderOuterLineWidth", css::uno::Any(aBorder.OuterLineWidth)) };
369 return aCurNode;
372 static svx::sidebar::TreeNode LocaleToTreeNode(const OUString& rName, const css::uno::Any& rVal)
374 svx::sidebar::TreeNode aCurNode;
375 aCurNode.sNodeName = PropertyNametoRID(rName);
376 lang::Locale aLocale;
377 rVal >>= aLocale;
378 OUString aLocaleText(aLocale.Language + "-" + aLocale.Country);
379 if (!aLocale.Variant.isEmpty())
380 aLocaleText += " (" + aLocale.Variant + ")";
381 aCurNode.aValue <<= aLocaleText;
383 return aCurNode;
386 // Collect text of the current level of the annotated text
387 // ranges (InContentMetadata) and metadata fields (MetadataField)
388 static OUString NestedTextContentToText(const css::uno::Any& rVal)
390 uno::Reference<container::XEnumerationAccess> xMeta;
391 if (rVal >>= xMeta)
393 uno::Reference<container::XEnumeration> xMetaPortions = xMeta->createEnumeration();
395 OUStringBuffer aBuf;
396 while (xMetaPortions->hasMoreElements())
398 uno::Reference<css::text::XTextRange> xRng(xMetaPortions->nextElement(),
399 uno::UNO_QUERY);
400 aBuf.append(xRng->getString());
402 return aBuf.makeStringAndClear();
405 return OUString();
408 // List metadata associated to the paragraph or character range
409 static void MetadataToTreeNode(const css::uno::Reference<css::uno::XInterface>& rSource,
410 svx::sidebar::TreeNode& rNode)
412 uno::Reference<rdf::XMetadatable> xMeta(rSource, uno::UNO_QUERY_THROW);
413 // don't add tree node "Metadata Reference", if there is no xml:id
414 if (!xMeta.is() || xMeta->getMetadataReference().Second.isEmpty())
415 return;
417 // add metadata of parents for nested annotated text ranges
418 uno::Reference<container::XChild> xChild(rSource, uno::UNO_QUERY);
419 if (xChild.is())
421 uno::Reference<container::XEnumerationAccess> xParentMeta(xChild->getParent(),
422 uno::UNO_QUERY);
423 if (xParentMeta.is())
424 MetadataToTreeNode(xParentMeta, rNode);
427 svx::sidebar::TreeNode aCurNode;
428 aCurNode.sNodeName = PropertyNametoRID("MetadataReference");
429 aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty;
431 aCurNode.children.push_back(
432 SimplePropToTreeNode("xml:id", uno::Any(xMeta->getMetadataReference().Second)));
434 // list associated (predicate, object) pairs of the actual subject
435 // under the tree node "Metadata Reference"
436 if (SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current()))
438 uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(pDocSh->GetBaseModel(),
439 uno::UNO_QUERY);
440 const uno::Reference<rdf::XRepository>& xRepo = xDocumentMetadataAccess->getRDFRepository();
441 const css::uno::Reference<css::rdf::XResource> xSubject(rSource, uno::UNO_QUERY);
442 std::map<OUString, OUString> xStatements
443 = SwRDFHelper::getStatements(pDocSh->GetBaseModel(), xRepo->getGraphNames(), xSubject);
444 for (const auto& pair : xStatements)
445 aCurNode.children.push_back(SimplePropToTreeNode(pair.first, uno::Any(pair.second)));
448 rNode.children.push_back(aCurNode);
451 static svx::sidebar::TreeNode
452 PropertyToTreeNode(const css::beans::Property& rProperty,
453 const uno::Reference<beans::XPropertySet>& xPropertiesSet, const bool rIsGrey)
455 const OUString& rPropName = rProperty.Name;
456 svx::sidebar::TreeNode aCurNode;
457 const uno::Any aAny = xPropertiesSet->getPropertyValue(rPropName);
458 aCurNode.sNodeName = PropertyNametoRID(rPropName);
460 // These properties are handled separately as they are stored in STRUCT and not in single data members
461 if (rPropName == "CharTopBorder" || rPropName == "CharBottomBorder"
462 || rPropName == "CharLeftBorder" || rPropName == "CharRightBorder"
463 || rPropName == "TopBorder" || rPropName == "BottomBorder" || rPropName == "LeftBorder"
464 || rPropName == "RightBorder")
466 aCurNode = BorderToTreeNode(rPropName, aAny);
468 else if (rPropName == "CharLocale")
470 aCurNode = LocaleToTreeNode(rPropName, aAny);
472 else
473 aCurNode = SimplePropToTreeNode(rPropName, aAny);
475 if (rIsGrey)
477 aCurNode.isGrey = true;
478 for (svx::sidebar::TreeNode& rChildNode : aCurNode.children)
479 rChildNode.isGrey = true; // grey out all the children nodes
482 return aCurNode;
485 static void InsertValues(const css::uno::Reference<css::uno::XInterface>& rSource,
486 std::unordered_map<OUString, bool>& rIsDefined,
487 svx::sidebar::TreeNode& rNode, const bool isRoot,
488 const std::vector<OUString>& rHiddenProperty,
489 svx::sidebar::TreeNode& rFieldsNode)
491 uno::Reference<beans::XPropertySet> xPropertiesSet(rSource, uno::UNO_QUERY_THROW);
492 uno::Reference<beans::XPropertyState> xPropertiesState(rSource, uno::UNO_QUERY_THROW);
493 const uno::Sequence<beans::Property> aProperties
494 = xPropertiesSet->getPropertySetInfo()->getProperties();
496 for (const beans::Property& rProperty : aProperties)
498 const OUString& rPropName = rProperty.Name;
499 if (std::find(rHiddenProperty.begin(), rHiddenProperty.end(), rPropName)
500 != rHiddenProperty.end())
501 continue;
503 if (isRoot
504 || xPropertiesState->getPropertyState(rPropName) == beans::PropertyState_DIRECT_VALUE)
506 svx::sidebar::TreeNode aCurNode
507 = PropertyToTreeNode(rProperty, xPropertiesSet, rIsDefined[rPropName]);
508 rIsDefined[rPropName] = true;
510 // process NestedTextContent and show associated metadata
511 // under the tree node "Metadata Reference", if they exist
512 if (rPropName == "NestedTextContent")
514 uno::Reference<container::XEnumerationAccess> xMeta;
515 if (aCurNode.aValue >>= xMeta)
516 MetadataToTreeNode(xMeta, rFieldsNode);
517 aCurNode.aValue <<= NestedTextContentToText(aCurNode.aValue);
520 rNode.children.push_back(aCurNode);
524 const comphelper::string::NaturalStringSorter aSorter(
525 comphelper::getProcessComponentContext(),
526 Application::GetSettings().GetUILanguageTag().getLocale());
528 std::sort(
529 rNode.children.begin(), rNode.children.end(),
530 [&aSorter](svx::sidebar::TreeNode const& rEntry1, svx::sidebar::TreeNode const& rEntry2) {
531 return aSorter.compare(rEntry1.sNodeName, rEntry2.sNodeName) < 0;
535 static void UpdateTree(SwDocShell& rDocSh, SwEditShell& rEditSh,
536 std::vector<svx::sidebar::TreeNode>& aStore, sal_Int32& rParIdx)
538 SwDoc* pDoc = rDocSh.GetDoc();
539 SwPaM* pCursor = rEditSh.GetCursor();
540 svx::sidebar::TreeNode aCharDFNode;
541 svx::sidebar::TreeNode aCharNode;
542 svx::sidebar::TreeNode aParaNode;
543 svx::sidebar::TreeNode aParaDFNode;
544 svx::sidebar::TreeNode aBookmarksNode;
545 svx::sidebar::TreeNode aFieldsNode;
546 svx::sidebar::TreeNode aTextSectionsNode;
548 aCharNode.sNodeName = SwResId(STR_CHARACTERSTYLEFAMILY);
549 aParaNode.sNodeName = SwResId(STR_PARAGRAPHSTYLEFAMILY);
550 aCharDFNode.sNodeName = SwResId(RID_CHAR_DIRECTFORMAT);
551 aParaDFNode.sNodeName = SwResId(RID_PARA_DIRECTFORMAT);
552 aBookmarksNode.sNodeName = SwResId(STR_CONTENT_TYPE_BOOKMARK);
553 aFieldsNode.sNodeName = SwResId(STR_CONTENT_TYPE_TEXTFIELD);
554 aTextSectionsNode.sNodeName = SwResId(STR_CONTENT_TYPE_REGION);
555 aCharDFNode.NodeType = svx::sidebar::TreeNode::Category;
556 aCharNode.NodeType = svx::sidebar::TreeNode::Category;
557 aParaNode.NodeType = svx::sidebar::TreeNode::Category;
558 aParaDFNode.NodeType = svx::sidebar::TreeNode::Category;
559 aBookmarksNode.NodeType = svx::sidebar::TreeNode::Category;
560 aFieldsNode.NodeType = svx::sidebar::TreeNode::Category;
561 aTextSectionsNode.NodeType = svx::sidebar::TreeNode::Category;
563 uno::Reference<text::XTextRange> xRange(
564 SwXTextRange::CreateXTextRange(*pDoc, *pCursor->GetPoint(), nullptr));
565 uno::Reference<beans::XPropertySet> xPropertiesSet(xRange, uno::UNO_QUERY_THROW);
566 std::unordered_map<OUString, bool> aIsDefined;
568 const std::vector<OUString> aHiddenProperties{ UNO_NAME_RSID,
569 UNO_NAME_PARA_IS_NUMBERING_RESTART,
570 UNO_NAME_PARA_STYLE_NAME,
571 UNO_NAME_PARA_CONDITIONAL_STYLE_NAME,
572 UNO_NAME_PAGE_STYLE_NAME,
573 UNO_NAME_NUMBERING_START_VALUE,
574 UNO_NAME_NUMBERING_IS_NUMBER,
575 UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE,
576 UNO_NAME_CHAR_STYLE_NAME,
577 UNO_NAME_NUMBERING_LEVEL,
578 UNO_NAME_SORTED_TEXT_ID,
579 UNO_NAME_PARRSID,
580 UNO_NAME_CHAR_COLOR_THEME,
581 UNO_NAME_CHAR_COLOR_TINT_OR_SHADE };
583 const std::vector<OUString> aHiddenCharacterProperties{ UNO_NAME_CHAR_COLOR_THEME,
584 UNO_NAME_CHAR_COLOR_TINT_OR_SHADE };
586 InsertValues(xRange, aIsDefined, aCharDFNode, false, aHiddenProperties, aFieldsNode);
588 uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(rDocSh.GetBaseModel(),
589 uno::UNO_QUERY);
590 uno::Reference<container::XNameAccess> xStyleFamilies
591 = xStyleFamiliesSupplier->getStyleFamilies();
592 OUString sCurrentCharStyle, sCurrentParaStyle, sDisplayName;
594 uno::Reference<container::XNameAccess> xStyleFamily(
595 xStyleFamilies->getByName("CharacterStyles"), uno::UNO_QUERY_THROW);
596 xPropertiesSet->getPropertyValue("CharStyleName") >>= sCurrentCharStyle;
597 xPropertiesSet->getPropertyValue("ParaStyleName") >>= sCurrentParaStyle;
599 if (!sCurrentCharStyle.isEmpty())
601 xPropertiesSet.set(xStyleFamily->getByName(sCurrentCharStyle), css::uno::UNO_QUERY_THROW);
602 xPropertiesSet->getPropertyValue("DisplayName") >>= sDisplayName;
603 svx::sidebar::TreeNode aCurrentChild;
604 aCurrentChild.sNodeName = sDisplayName;
605 aCurrentChild.NodeType = svx::sidebar::TreeNode::ComplexProperty;
607 InsertValues(xPropertiesSet, aIsDefined, aCurrentChild, false, aHiddenCharacterProperties,
608 aFieldsNode);
610 aCharNode.children.push_back(aCurrentChild);
613 // Collect paragraph direct formatting
614 uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xRange, uno::UNO_QUERY_THROW);
615 uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
616 uno::Reference<text::XTextRange> xThisParagraphRange(xParaEnum->nextElement(), uno::UNO_QUERY);
617 if (xThisParagraphRange.is())
619 // Collect metadata of the current paragraph
620 MetadataToTreeNode(xThisParagraphRange, aParaDFNode);
621 InsertValues(xThisParagraphRange, aIsDefined, aParaDFNode, false, aHiddenProperties,
622 aFieldsNode);
625 xStyleFamily.set(xStyleFamilies->getByName("ParagraphStyles"), uno::UNO_QUERY_THROW);
627 while (!sCurrentParaStyle.isEmpty())
629 uno::Reference<style::XStyle> xPropertiesStyle(xStyleFamily->getByName(sCurrentParaStyle),
630 uno::UNO_QUERY_THROW);
631 xPropertiesSet.set(xPropertiesStyle, css::uno::UNO_QUERY_THROW);
632 xPropertiesSet->getPropertyValue("DisplayName") >>= sDisplayName;
633 OUString aParentParaStyle = xPropertiesStyle->getParentStyle();
634 svx::sidebar::TreeNode aCurrentChild;
635 aCurrentChild.sNodeName = sDisplayName;
636 aCurrentChild.NodeType = svx::sidebar::TreeNode::ComplexProperty;
638 InsertValues(xPropertiesSet, aIsDefined, aCurrentChild, aParentParaStyle.isEmpty(),
639 aHiddenCharacterProperties, aFieldsNode);
641 aParaNode.children.push_back(aCurrentChild);
642 sCurrentParaStyle = aParentParaStyle;
645 std::reverse(aParaNode.children.begin(),
646 aParaNode.children.end()); // Parent style should be first then children
648 // Collect bookmarks at character position
649 uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(rDocSh.GetBaseModel(),
650 uno::UNO_QUERY);
652 uno::Reference<container::XIndexAccess> xBookmarks(xBookmarksSupplier->getBookmarks(),
653 uno::UNO_QUERY);
654 for (sal_Int32 i = 0; i < xBookmarks->getCount(); ++i)
656 svx::sidebar::TreeNode aCurNode;
657 uno::Reference<text::XTextContent> bookmark;
658 xBookmarks->getByIndex(i) >>= bookmark;
659 uno::Reference<container::XNamed> xBookmark(bookmark, uno::UNO_QUERY);
663 uno::Reference<text::XTextRange> bookmarkRange = bookmark->getAnchor();
664 uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xRange->getText(),
665 uno::UNO_QUERY);
666 if (xTextRangeCompare.is()
667 && xTextRangeCompare->compareRegionStarts(bookmarkRange, xRange) != -1
668 && xTextRangeCompare->compareRegionEnds(xRange, bookmarkRange) != -1)
670 aCurNode.sNodeName = xBookmark->getName();
671 aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty;
673 MetadataToTreeNode(xBookmark, aCurNode);
674 // show bookmark only if it has RDF metadata
675 if (aCurNode.children.size() > 0)
676 aBookmarksNode.children.push_back(aCurNode);
679 catch (const lang::IllegalArgumentException&)
684 // Collect sections at character position
685 uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(rDocSh.GetBaseModel(),
686 uno::UNO_QUERY);
688 uno::Reference<container::XIndexAccess> xTextSections(xTextSectionsSupplier->getTextSections(),
689 uno::UNO_QUERY);
690 for (sal_Int32 i = 0; i < xTextSections->getCount(); ++i)
692 svx::sidebar::TreeNode aCurNode;
693 uno::Reference<text::XTextContent> section;
694 xTextSections->getByIndex(i) >>= section;
695 uno::Reference<container::XNamed> xTextSection(section, uno::UNO_QUERY);
699 uno::Reference<text::XTextRange> sectionRange = section->getAnchor();
700 uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xRange->getText(),
701 uno::UNO_QUERY);
702 if (xTextRangeCompare.is()
703 && xTextRangeCompare->compareRegionStarts(sectionRange, xRange) != -1
704 && xTextRangeCompare->compareRegionEnds(xRange, sectionRange) != -1)
706 aCurNode.sNodeName = xTextSection->getName();
707 aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty;
709 MetadataToTreeNode(xTextSection, aCurNode);
710 // show section only if it has RDF metadata
711 if (aCurNode.children.size() > 0)
712 aTextSectionsNode.children.push_back(aCurNode);
715 catch (const lang::IllegalArgumentException&)
721 Display Order :-
722 SECTIONS with RDF metadata (optional)
723 BOOKMARKS with RDF metadata (optional)
724 FIELDS with RDF metadata (optional)
725 PARAGRAPH STYLE
726 PARAGRAPH DIRECT FORMATTING
727 CHARACTER STYLE
728 DIRECT FORMATTING
730 rParIdx = 0;
731 // show sections, bookmarks and fields only if they have RDF metadata
732 if (aTextSectionsNode.children.size() > 0)
734 aStore.push_back(aTextSectionsNode);
735 rParIdx++;
737 if (aBookmarksNode.children.size() > 0)
739 aStore.push_back(aBookmarksNode);
740 rParIdx++;
742 if (aFieldsNode.children.size() > 0)
744 aStore.push_back(aFieldsNode);
745 rParIdx++;
747 aStore.push_back(aParaNode);
748 aStore.push_back(aParaDFNode);
749 aStore.push_back(aCharNode);
750 aStore.push_back(aCharDFNode);
753 IMPL_LINK(WriterInspectorTextPanel, AttrChangedNotify, LinkParamNone*, pLink, void)
755 if (m_oldLink.IsSet())
756 m_oldLink.Call(pLink);
758 SwDocShell* pDocSh = m_pShell->GetDoc()->GetDocShell();
759 std::vector<svx::sidebar::TreeNode> aStore;
761 SwEditShell* pEditSh = pDocSh ? pDocSh->GetDoc()->GetEditShell() : nullptr;
762 if (pEditSh && pEditSh->GetCursor()->GetPointNode().GetTextNode())
763 UpdateTree(*pDocSh, *pEditSh, aStore, m_nParIdx);
765 updateEntries(aStore, m_nParIdx);
768 } // end of namespace svx::sidebar
770 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */