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
50namespace sw::sidebar
51{
52static void UpdateTree(SwDocShell& rDocSh, SwEditShell& rEditSh,
53 std::vector<svx::sidebar::TreeNode>& aStore, sal_Int32& rParIdx);
54
55std::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 = dynamic_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 // 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);
77 }
78
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);
85}
86
88{
89 if (rHint.GetId() == SfxHintId::SwLegacyModify)
90 {
91 const sw::LegacyModifyHint& rLegacy = static_cast<const sw::LegacyModifyHint&>(rHint);
92 if (rLegacy.GetWhich() == RES_OBJECTDYING)
93 m_pShell = nullptr;
94 }
95 SwClient::SwClientNotify(rModify, rHint);
96}
97
99{
100 if (m_pShell)
101 {
103 m_pShell->Remove(this);
104 }
105}
106
107static OUString PropertyNametoRID(const OUString& rName)
108{
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 },
337 };
338
339 auto itr = aNameToRID.find(rName);
340 if (itr != aNameToRID.end())
341 return SwResId(itr->second);
342 return rName;
343}
344
345static svx::sidebar::TreeNode SimplePropToTreeNode(const OUString& rName, const css::uno::Any& rVal)
346{
347 svx::sidebar::TreeNode aCurNode;
348 aCurNode.sNodeName = PropertyNametoRID(rName);
349 aCurNode.aValue = rVal;
350
351 return aCurNode;
352}
353
354static svx::sidebar::TreeNode BorderToTreeNode(const OUString& rName, const css::uno::Any& rVal)
355{
356 table::BorderLine2 aBorder;
357 rVal >>= aBorder;
358 svx::sidebar::TreeNode aCurNode;
359 aCurNode.sNodeName = PropertyNametoRID(rName);
361
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;
370}
371
372static svx::sidebar::TreeNode LocaleToTreeNode(const OUString& rName, const css::uno::Any& rVal)
373{
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;
382
383 return aCurNode;
384}
385
386// Collect text of the current level of the annotated text
387// ranges (InContentMetadata) and metadata fields (MetadataField)
388static OUString NestedTextContentToText(const css::uno::Any& rVal)
389{
390 uno::Reference<container::XEnumerationAccess> xMeta;
391 if (rVal >>= xMeta)
392 {
393 uno::Reference<container::XEnumeration> xMetaPortions = xMeta->createEnumeration();
394
395 OUStringBuffer aBuf;
396 while (xMetaPortions->hasMoreElements())
397 {
398 uno::Reference<css::text::XTextRange> xRng(xMetaPortions->nextElement(),
399 uno::UNO_QUERY);
400 aBuf.append(xRng->getString());
401 }
402 return aBuf.makeStringAndClear();
403 }
404
405 return OUString();
406}
407
408// List metadata associated to the paragraph or character range
409static void MetadataToTreeNode(const css::uno::Reference<css::uno::XInterface>& rSource,
411{
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;
416
417 // add metadata of parents for nested annotated text ranges
418 uno::Reference<container::XChild> xChild(rSource, uno::UNO_QUERY);
419 if (xChild.is())
420 {
421 uno::Reference<container::XEnumerationAccess> xParentMeta(xChild->getParent(),
422 uno::UNO_QUERY);
423 if (xParentMeta.is())
424 MetadataToTreeNode(xParentMeta, rNode);
425 }
426
427 svx::sidebar::TreeNode aCurNode;
428 aCurNode.sNodeName = PropertyNametoRID("MetadataReference");
430
431 aCurNode.children.push_back(
432 SimplePropToTreeNode("xml:id", uno::Any(xMeta->getMetadataReference().Second)));
433
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()))
437 {
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)));
446 }
447
448 rNode.children.push_back(aCurNode);
449}
450
452PropertyToTreeNode(const css::beans::Property& rProperty,
453 const uno::Reference<beans::XPropertySet>& xPropertiesSet, const bool rIsGrey)
454{
455 const OUString& rPropName = rProperty.Name;
456 svx::sidebar::TreeNode aCurNode;
457 const uno::Any aAny = xPropertiesSet->getPropertyValue(rPropName);
458 aCurNode.sNodeName = PropertyNametoRID(rPropName);
459
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")
465 {
466 aCurNode = BorderToTreeNode(rPropName, aAny);
467 }
468 else if (rPropName == "CharLocale")
469 {
470 aCurNode = LocaleToTreeNode(rPropName, aAny);
471 }
472 else
473 aCurNode = SimplePropToTreeNode(rPropName, aAny);
474
475 if (rIsGrey)
476 {
477 aCurNode.isGrey = true;
478 for (svx::sidebar::TreeNode& rChildNode : aCurNode.children)
479 rChildNode.isGrey = true; // grey out all the children nodes
480 }
481
482 return aCurNode;
483}
484
485static 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)
490{
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();
495
496 for (const beans::Property& rProperty : aProperties)
497 {
498 const OUString& rPropName = rProperty.Name;
499 if (std::find(rHiddenProperty.begin(), rHiddenProperty.end(), rPropName)
500 != rHiddenProperty.end())
501 continue;
502
503 if (isRoot
504 || xPropertiesState->getPropertyState(rPropName) == beans::PropertyState_DIRECT_VALUE)
505 {
507 = PropertyToTreeNode(rProperty, xPropertiesSet, rIsDefined[rPropName]);
508 rIsDefined[rPropName] = true;
509
510 // process NestedTextContent and show associated metadata
511 // under the tree node "Metadata Reference", if they exist
512 if (rPropName == "NestedTextContent")
513 {
514 uno::Reference<container::XEnumerationAccess> xMeta;
515 if (aCurNode.aValue >>= xMeta)
516 MetadataToTreeNode(xMeta, rFieldsNode);
517 aCurNode.aValue <<= NestedTextContentToText(aCurNode.aValue);
518 }
519
520 rNode.children.push_back(aCurNode);
521 }
522 }
523
526 Application::GetSettings().GetUILanguageTag().getLocale());
527
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;
532 });
533}
534
535static void UpdateTree(SwDocShell& rDocSh, SwEditShell& rEditSh,
536 std::vector<svx::sidebar::TreeNode>& aStore, sal_Int32& rParIdx)
537{
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;
547
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);
561 aTextSectionsNode.NodeType = svx::sidebar::TreeNode::Category;
562
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;
567
568 const std::vector<OUString> aHiddenProperties{ UNO_NAME_RSID,
582
583 const std::vector<OUString> aHiddenCharacterProperties{ UNO_NAME_CHAR_COLOR_THEME,
585
586 InsertValues(xRange, aIsDefined, aCharDFNode, false, aHiddenProperties, aFieldsNode);
587
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;
593
594 uno::Reference<container::XNameAccess> xStyleFamily(
595 xStyleFamilies->getByName("CharacterStyles"), uno::UNO_QUERY_THROW);
596 xPropertiesSet->getPropertyValue("CharStyleName") >>= sCurrentCharStyle;
597 xPropertiesSet->getPropertyValue("ParaStyleName") >>= sCurrentParaStyle;
598
599 if (!sCurrentCharStyle.isEmpty())
600 {
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;
606
607 InsertValues(xPropertiesSet, aIsDefined, aCurrentChild, false, aHiddenCharacterProperties,
608 aFieldsNode);
609
610 aCharNode.children.push_back(aCurrentChild);
611 }
612
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())
618 {
619 // Collect metadata of the current paragraph
620 MetadataToTreeNode(xThisParagraphRange, aParaDFNode);
621 InsertValues(xThisParagraphRange, aIsDefined, aParaDFNode, false, aHiddenProperties,
622 aFieldsNode);
623 }
624
625 xStyleFamily.set(xStyleFamilies->getByName("ParagraphStyles"), uno::UNO_QUERY_THROW);
626
627 while (!sCurrentParaStyle.isEmpty())
628 {
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;
637
638 InsertValues(xPropertiesSet, aIsDefined, aCurrentChild, aParentParaStyle.isEmpty(),
639 aHiddenCharacterProperties, aFieldsNode);
640
641 aParaNode.children.push_back(aCurrentChild);
642 sCurrentParaStyle = aParentParaStyle;
643 }
644
645 std::reverse(aParaNode.children.begin(),
646 aParaNode.children.end()); // Parent style should be first then children
647
648 // Collect bookmarks at character position
649 uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(rDocSh.GetBaseModel(),
650 uno::UNO_QUERY);
651
652 uno::Reference<container::XIndexAccess> xBookmarks(xBookmarksSupplier->getBookmarks(),
653 uno::UNO_QUERY);
654 for (sal_Int32 i = 0; i < xBookmarks->getCount(); ++i)
655 {
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);
660
661 try
662 {
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)
669 {
670 aCurNode.sNodeName = xBookmark->getName();
672
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);
677 }
678 }
679 catch (const lang::IllegalArgumentException&)
680 {
681 }
682 }
683
684 // Collect sections at character position
685 uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(rDocSh.GetBaseModel(),
686 uno::UNO_QUERY);
687
688 uno::Reference<container::XIndexAccess> xTextSections(xTextSectionsSupplier->getTextSections(),
689 uno::UNO_QUERY);
690 for (sal_Int32 i = 0; i < xTextSections->getCount(); ++i)
691 {
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);
696
697 try
698 {
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)
705 {
706 aCurNode.sNodeName = xTextSection->getName();
708
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);
713 }
714 }
715 catch (const lang::IllegalArgumentException&)
716 {
717 }
718 }
719
720 /*
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
729 */
730 rParIdx = 0;
731 // show sections, bookmarks and fields only if they have RDF metadata
732 if (aTextSectionsNode.children.size() > 0)
733 {
734 aStore.push_back(aTextSectionsNode);
735 rParIdx++;
736 }
737 if (aBookmarksNode.children.size() > 0)
738 {
739 aStore.push_back(aBookmarksNode);
740 rParIdx++;
741 }
742 if (aFieldsNode.children.size() > 0)
743 {
744 aStore.push_back(aFieldsNode);
745 rParIdx++;
746 }
747 aStore.push_back(aParaNode);
748 aStore.push_back(aParaDFNode);
749 aStore.push_back(aCharNode);
750 aStore.push_back(aCharDFNode);
751}
752
753IMPL_LINK(WriterInspectorTextPanel, AttrChangedNotify, LinkParamNone*, pLink, void)
754{
755 if (m_oldLink.IsSet())
756 m_oldLink.Call(pLink);
757
758 SwDocShell* pDocSh = m_pShell->GetDoc()->GetDocShell();
759 std::vector<svx::sidebar::TreeNode> aStore;
760
761 SwEditShell* pEditSh = pDocSh ? pDocSh->GetDoc()->GetEditShell() : nullptr;
762 if (pEditSh && pEditSh->GetCursor()->GetPointNode().GetTextNode())
763 UpdateTree(*pDocSh, *pEditSh, aStore, m_nParIdx);
764
765 updateEntries(aStore, m_nParIdx);
766}
767
768} // end of namespace svx::sidebar
769
770/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
static const AllSettings & GetSettings()
SfxHintId GetId() const
css::uno::Reference< css::frame::XModel3 > GetBaseModel() const
static SAL_WARN_UNUSED_RESULT SfxObjectShell * Current()
virtual void SwClientNotify(const SwModify &, const SfxHint &rHint) override
Definition: calbck.cxx:120
const Link< LinkParamNone *, void > & GetChgLnk() const
Definition: crsrsh.hxx:504
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:194
void SetChgLnk(const Link< LinkParamNone *, void > &rLnk)
Definition: crsrsh.hxx:503
SwWrtShell * GetWrtShell()
Access to the SwWrtShell belonging to SwView.
Definition: docsh.hxx:225
SwDoc * GetDoc()
returns Doc. But be careful!
Definition: docsh.hxx:204
Definition: doc.hxx:197
SwEditShell const * GetEditShell() const
Definition: doccorr.cxx:330
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
SwNode & GetPointNode() const
Definition: pam.hxx:275
const SwPosition * GetPoint() const
Definition: pam.hxx:253
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 rtl::Reference< SwXTextRange > CreateXTextRange(SwDoc &rDoc, const SwPosition &rPos, const SwPosition *const pMark)
Definition: unoobj2.cxx:1221
void updateEntries(const std::vector< TreeNode > &rStore, const sal_Int32 nParIdx)
virtual void SwClientNotify(const SwModify &, const SfxHint &rHint) override
static std::unique_ptr< PanelLayout > Create(weld::Widget *pParent)
OUString sDisplayName
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_OBJECTDYING(RES_FORMAT_MSG_BEGIN)
Shell * m_pShell
SvBaseLink * pLink
aBuf
const LanguageTag & getLocale()
Reference< XComponentContext > getProcessComponentContext()
int i
static void MetadataToTreeNode(const css::uno::Reference< css::uno::XInterface > &rSource, svx::sidebar::TreeNode &rNode)
static OUString PropertyNametoRID(const OUString &rName)
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)
IMPL_LINK(PageColumnControl, ColumnButtonClickHdl_Impl, weld::Button &, rButton, void)
static svx::sidebar::TreeNode SimplePropToTreeNode(const OUString &rName, const css::uno::Any &rVal)
static void UpdateTree(SwDocShell &rDocSh, SwEditShell &rEditSh, std::vector< svx::sidebar::TreeNode > &aStore, sal_Int32 &rParIdx)
static OUString NestedTextContentToText(const css::uno::Any &rVal)
static svx::sidebar::TreeNode BorderToTreeNode(const OUString &rName, const css::uno::Any &rVal)
static svx::sidebar::TreeNode PropertyToTreeNode(const css::beans::Property &rProperty, const uno::Reference< beans::XPropertySet > &xPropertiesSet, const bool rIsGrey)
static svx::sidebar::TreeNode LocaleToTreeNode(const OUString &rName, const css::uno::Any &rVal)
std::vector< TreeNode > children
css::uno::Any aValue
enum svx::sidebar::TreeNode::@4 NodeType
sal_uInt16 GetWhich() const
Definition: calbck.hxx:75
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:168
constexpr OUStringLiteral UNO_NAME_SORTED_TEXT_ID
Definition: unoprnms.hxx:424
constexpr OUStringLiteral UNO_NAME_PARA_IS_NUMBERING_RESTART
Definition: unoprnms.hxx:527
constexpr OUStringLiteral UNO_NAME_CHAR_COLOR_THEME
constexpr OUStringLiteral UNO_NAME_NUMBERING_IS_NUMBER
Definition: unoprnms.hxx:169
constexpr OUStringLiteral UNO_NAME_PARA_CONDITIONAL_STYLE_NAME
Definition: unoprnms.hxx:498
constexpr OUStringLiteral UNO_NAME_PARA_STYLE_NAME
Definition: unoprnms.hxx:193
constexpr OUStringLiteral UNO_NAME_CHAR_COLOR_TINT_OR_SHADE
constexpr OUStringLiteral UNO_NAME_RSID
Definition: unoprnms.hxx:857
constexpr OUStringLiteral UNO_NAME_NUMBERING_LEVEL
constexpr OUStringLiteral UNO_NAME_PAGE_STYLE_NAME
Definition: unoprnms.hxx:189
constexpr OUStringLiteral UNO_NAME_NUMBERING_START_VALUE
Definition: unoprnms.hxx:168
constexpr OUStringLiteral UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE
Definition: unoprnms.hxx:840
constexpr OUStringLiteral UNO_NAME_PARRSID
Definition: unoprnms.hxx:858
constexpr OUStringLiteral UNO_NAME_CHAR_STYLE_NAME