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