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