/src/libreoffice/sfx2/source/devtools/DocumentModelTreeHandler.cxx
Line | Count | Source |
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 | | */ |
10 | | |
11 | | #include <memory> |
12 | | |
13 | | #include <sfx2/devtools/DocumentModelTreeHandler.hxx> |
14 | | |
15 | | #include <sfx2/sfxresid.hxx> |
16 | | #include "DevToolsStrings.hrc" |
17 | | #include <vcl/weld/TreeView.hxx> |
18 | | |
19 | | #include <com/sun/star/lang/XServiceInfo.hpp> |
20 | | #include <com/sun/star/container/XNamed.hpp> |
21 | | #include <com/sun/star/container/XEnumerationAccess.hpp> |
22 | | |
23 | | #include <com/sun/star/drawing/XDrawPage.hpp> |
24 | | #include <com/sun/star/drawing/XDrawPages.hpp> |
25 | | #include <com/sun/star/drawing/XDrawPagesSupplier.hpp> |
26 | | #include <com/sun/star/drawing/XDrawPageSupplier.hpp> |
27 | | #include <com/sun/star/drawing/XMasterPagesSupplier.hpp> |
28 | | #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> |
29 | | #include <com/sun/star/sheet/XSpreadsheet.hpp> |
30 | | #include <com/sun/star/sheet/XDataPilotTablesSupplier.hpp> |
31 | | #include <com/sun/star/sheet/XDataPilotTables.hpp> |
32 | | #include <com/sun/star/table/XTableChartsSupplier.hpp> |
33 | | #include <com/sun/star/table/XTableCharts.hpp> |
34 | | #include <com/sun/star/text/XTextDocument.hpp> |
35 | | #include <com/sun/star/text/XTextTablesSupplier.hpp> |
36 | | #include <com/sun/star/text/XTextFramesSupplier.hpp> |
37 | | #include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp> |
38 | | #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp> |
39 | | #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> |
40 | | #include <utility> |
41 | | |
42 | | using namespace css; |
43 | | |
44 | | namespace |
45 | | { |
46 | | // returns a name of the object, if available |
47 | | OUString lclGetNamed(uno::Reference<uno::XInterface> const& xObject) |
48 | 0 | { |
49 | 0 | uno::Reference<container::XNamed> xNamed(xObject, uno::UNO_QUERY); |
50 | 0 | if (!xNamed.is()) |
51 | 0 | return OUString(); |
52 | 0 | return xNamed->getName(); |
53 | 0 | } |
54 | | |
55 | | /** DocumentModelTreeEntry is an object "attached" to a tree node. |
56 | | * |
57 | | * It represents an object that is "attached" to the tree view an is |
58 | | * responsible to provide the UNO object associated with the current |
59 | | * node and on demand create and fill the children of the said node. |
60 | | */ |
61 | | class DocumentModelTreeEntry |
62 | | { |
63 | | protected: |
64 | | OUString maString; |
65 | | css::uno::Reference<css::uno::XInterface> mxObject; |
66 | | |
67 | | public: |
68 | | DocumentModelTreeEntry(OUString aString, css::uno::Reference<css::uno::XInterface> xObject) |
69 | 0 | : maString(std::move(aString)) |
70 | 0 | , mxObject(std::move(xObject)) |
71 | 0 | { |
72 | 0 | } |
73 | | |
74 | 0 | virtual ~DocumentModelTreeEntry() {} |
75 | | |
76 | | /// the node string shown in the tree view |
77 | 0 | OUString& getString() { return maString; } |
78 | | |
79 | | /// should show the expander for the tree view node |
80 | 0 | virtual bool shouldShowExpander() { return false; } |
81 | | |
82 | | /// The main UNO object for this entry |
83 | 0 | virtual css::uno::Reference<css::uno::XInterface> getMainObject() { return mxObject; } |
84 | | |
85 | | /// Create and fill the children to the parent tree view node. |
86 | | virtual void fill(std::unique_ptr<weld::TreeView>& /*pDocumentModelTree*/, |
87 | | weld::TreeIter const& /*rParent*/) |
88 | 0 | { |
89 | 0 | } |
90 | | }; |
91 | | |
92 | | // append an entry to a input TreeView to a parent |
93 | | void lclAppendToParentEntry(const std::unique_ptr<weld::TreeView>& rTree, |
94 | | weld::TreeIter const& rParent, DocumentModelTreeEntry* pEntry) |
95 | 0 | { |
96 | 0 | OUString sId(weld::toId(pEntry)); |
97 | 0 | OUString const& rString = pEntry->getString(); |
98 | 0 | rTree->insert(&rParent, -1, &rString, &sId, nullptr, nullptr, pEntry->shouldShowExpander(), |
99 | 0 | nullptr); |
100 | 0 | } |
101 | | |
102 | | // append a root entry to a input TreeView |
103 | | void lclAppend(const std::unique_ptr<weld::TreeView>& rTree, DocumentModelTreeEntry* pEntry) |
104 | 0 | { |
105 | 0 | OUString sId(weld::toId(pEntry)); |
106 | 0 | OUString const& rString = pEntry->getString(); |
107 | 0 | rTree->insert(nullptr, -1, &rString, &sId, nullptr, nullptr, pEntry->shouldShowExpander(), |
108 | 0 | nullptr); |
109 | 0 | } |
110 | | |
111 | | /** Entry that represents a object, which implements a XNameAccess */ |
112 | | class NameAccessTreeEntry : public DocumentModelTreeEntry |
113 | | { |
114 | | protected: |
115 | | NameAccessTreeEntry(OUString const& rString, uno::Reference<uno::XInterface> const& xObject) |
116 | 0 | : DocumentModelTreeEntry(rString, xObject) |
117 | 0 | { |
118 | 0 | } |
119 | | |
120 | | bool shouldShowExpander() override |
121 | 0 | { |
122 | 0 | uno::Reference<container::XNameAccess> xNameAccess(getMainObject(), uno::UNO_QUERY); |
123 | 0 | return xNameAccess.is() && xNameAccess->getElementNames().getLength() > 0; |
124 | 0 | } |
125 | | |
126 | | /// A generic fill when the UNO object implements XNameAccess interface |
127 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
128 | | weld::TreeIter const& rParent) override |
129 | 0 | { |
130 | 0 | uno::Reference<container::XNameAccess> xNameAccess(getMainObject(), uno::UNO_QUERY); |
131 | 0 | xNameAccess.set(getMainObject(), uno::UNO_QUERY); |
132 | 0 | if (!xNameAccess.is()) |
133 | 0 | return; |
134 | | |
135 | 0 | const uno::Sequence<OUString> aNames = xNameAccess->getElementNames(); |
136 | 0 | for (auto const& rName : aNames) |
137 | 0 | { |
138 | 0 | uno::Reference<uno::XInterface> xObject(xNameAccess->getByName(rName), uno::UNO_QUERY); |
139 | 0 | auto pEntry = std::make_unique<DocumentModelTreeEntry>(rName, xObject); |
140 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pEntry.release()); |
141 | 0 | } |
142 | 0 | } |
143 | | }; |
144 | | |
145 | | /** Entry that represents the document root object */ |
146 | | class DocumentRootEntry : public DocumentModelTreeEntry |
147 | | { |
148 | | public: |
149 | | DocumentRootEntry(OUString const& rString, uno::Reference<uno::XInterface> const& xObject) |
150 | 0 | : DocumentModelTreeEntry(rString, xObject) |
151 | 0 | { |
152 | 0 | } |
153 | | |
154 | 0 | bool shouldShowExpander() override { return false; } |
155 | | }; |
156 | | |
157 | | /** Represents a paragraph object (XParagraph) */ |
158 | | class ParagraphEntry : public DocumentModelTreeEntry |
159 | | { |
160 | | public: |
161 | | ParagraphEntry(OUString const& rString, |
162 | | css::uno::Reference<css::uno::XInterface> const& xObject) |
163 | 0 | : DocumentModelTreeEntry(rString, xObject) |
164 | 0 | { |
165 | 0 | } |
166 | | |
167 | | bool shouldShowExpander() override |
168 | 0 | { |
169 | 0 | uno::Reference<container::XEnumerationAccess> xEnumAccess(getMainObject(), uno::UNO_QUERY); |
170 | 0 | if (!xEnumAccess.is()) |
171 | 0 | return false; |
172 | 0 | auto xTextPortions = xEnumAccess->createEnumeration(); |
173 | 0 | if (!xTextPortions.is()) |
174 | 0 | return false; |
175 | 0 | return xTextPortions->hasMoreElements(); |
176 | 0 | } |
177 | | |
178 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
179 | | weld::TreeIter const& rParent) override |
180 | 0 | { |
181 | 0 | uno::Reference<container::XEnumerationAccess> xEnumAccess(getMainObject(), uno::UNO_QUERY); |
182 | 0 | if (!xEnumAccess.is()) |
183 | 0 | return; |
184 | | |
185 | 0 | uno::Reference<container::XEnumeration> xTextPortions = xEnumAccess->createEnumeration(); |
186 | 0 | if (!xTextPortions.is()) |
187 | 0 | return; |
188 | | |
189 | 0 | for (sal_Int32 i = 0; xTextPortions->hasMoreElements(); i++) |
190 | 0 | { |
191 | 0 | uno::Reference<text::XTextRange> const xTextPortion(xTextPortions->nextElement(), |
192 | 0 | uno::UNO_QUERY); |
193 | 0 | OUString aString = lclGetNamed(xTextPortion); |
194 | 0 | if (aString.isEmpty()) |
195 | 0 | { |
196 | 0 | OUString aNumber = OUString::number(i + 1); |
197 | 0 | aString = SfxResId(STR_TEXT_PORTION).replaceFirst("%1", aNumber); |
198 | 0 | } |
199 | |
|
200 | 0 | auto pEntry = std::make_unique<DocumentModelTreeEntry>(aString, xTextPortion); |
201 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pEntry.release()); |
202 | 0 | } |
203 | 0 | } |
204 | | }; |
205 | | |
206 | | /** Represents a list of paragraphs */ |
207 | | class ParagraphsEntry : public DocumentModelTreeEntry |
208 | | { |
209 | | public: |
210 | | ParagraphsEntry(OUString const& rString, |
211 | | css::uno::Reference<css::uno::XInterface> const& xObject) |
212 | 0 | : DocumentModelTreeEntry(rString, xObject) |
213 | 0 | { |
214 | 0 | } |
215 | | |
216 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
217 | 0 | { |
218 | 0 | uno::Reference<text::XTextDocument> xDocument(mxObject, uno::UNO_QUERY); |
219 | 0 | if (!xDocument.is()) |
220 | 0 | return mxObject; |
221 | | |
222 | 0 | return xDocument->getText()->getText(); |
223 | 0 | } |
224 | | |
225 | | bool shouldShowExpander() override |
226 | 0 | { |
227 | 0 | uno::Reference<container::XEnumerationAccess> xEnumAccess(getMainObject(), uno::UNO_QUERY); |
228 | 0 | if (!xEnumAccess.is()) |
229 | 0 | return false; |
230 | 0 | auto xParagraphEnum = xEnumAccess->createEnumeration(); |
231 | 0 | if (!xParagraphEnum.is()) |
232 | 0 | return false; |
233 | 0 | return xParagraphEnum->hasMoreElements(); |
234 | 0 | } |
235 | | |
236 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
237 | | weld::TreeIter const& rParent) override |
238 | 0 | { |
239 | 0 | uno::Reference<container::XEnumerationAccess> xEnumAccess(getMainObject(), uno::UNO_QUERY); |
240 | 0 | if (!xEnumAccess.is()) |
241 | 0 | return; |
242 | | |
243 | 0 | uno::Reference<container::XEnumeration> xParagraphEnum = xEnumAccess->createEnumeration(); |
244 | |
|
245 | 0 | if (!xParagraphEnum.is()) |
246 | 0 | return; |
247 | | |
248 | 0 | for (sal_Int32 i = 0; xParagraphEnum->hasMoreElements(); i++) |
249 | 0 | { |
250 | 0 | uno::Reference<text::XTextContent> const xParagraph(xParagraphEnum->nextElement(), |
251 | 0 | uno::UNO_QUERY); |
252 | 0 | OUString aString = lclGetNamed(xParagraph); |
253 | 0 | if (aString.isEmpty()) |
254 | 0 | { |
255 | 0 | aString = SfxResId(STR_PARAGRAPH).replaceFirst("%1", OUString::number(i + 1)); |
256 | 0 | } |
257 | |
|
258 | 0 | auto pEntry = std::make_unique<ParagraphEntry>(aString, xParagraph); |
259 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pEntry.release()); |
260 | 0 | } |
261 | 0 | } |
262 | | }; |
263 | | |
264 | | /** Represents a list of shapes */ |
265 | | class ShapesEntry : public DocumentModelTreeEntry |
266 | | { |
267 | | public: |
268 | | ShapesEntry(OUString const& rString, css::uno::Reference<css::uno::XInterface> const& xObject) |
269 | 0 | : DocumentModelTreeEntry(rString, xObject) |
270 | 0 | { |
271 | 0 | } |
272 | | |
273 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
274 | 0 | { |
275 | 0 | uno::Reference<drawing::XDrawPageSupplier> xSupplier(mxObject, uno::UNO_QUERY); |
276 | 0 | if (!xSupplier.is()) |
277 | 0 | return mxObject; |
278 | 0 | return xSupplier->getDrawPage(); |
279 | 0 | } |
280 | | |
281 | | bool shouldShowExpander() override |
282 | 0 | { |
283 | 0 | uno::Reference<container::XIndexAccess> xShapes(getMainObject(), uno::UNO_QUERY); |
284 | 0 | return xShapes.is() && xShapes->getCount() > 0; |
285 | 0 | } |
286 | | |
287 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
288 | | weld::TreeIter const& rParent) override |
289 | 0 | { |
290 | 0 | uno::Reference<container::XIndexAccess> xShapes(getMainObject(), uno::UNO_QUERY); |
291 | 0 | if (!xShapes.is()) |
292 | 0 | return; |
293 | 0 | for (sal_Int32 nIndexShapes = 0; nIndexShapes < xShapes->getCount(); ++nIndexShapes) |
294 | 0 | { |
295 | 0 | uno::Reference<uno::XInterface> xShape(xShapes->getByIndex(nIndexShapes), |
296 | 0 | uno::UNO_QUERY); |
297 | 0 | OUString aShapeName = lclGetNamed(xShape); |
298 | 0 | if (aShapeName.isEmpty()) |
299 | 0 | { |
300 | 0 | aShapeName |
301 | 0 | = SfxResId(STR_SHAPE).replaceFirst("%1", OUString::number(nIndexShapes + 1)); |
302 | 0 | } |
303 | |
|
304 | 0 | auto pEntry = std::make_unique<DocumentModelTreeEntry>(aShapeName, xShape); |
305 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pEntry.release()); |
306 | 0 | } |
307 | 0 | } |
308 | | }; |
309 | | |
310 | | /** Represents a list of tables */ |
311 | | class TablesEntry : public NameAccessTreeEntry |
312 | | { |
313 | | public: |
314 | | TablesEntry(OUString const& rString, css::uno::Reference<css::uno::XInterface> const& xObject) |
315 | 0 | : NameAccessTreeEntry(rString, xObject) |
316 | 0 | { |
317 | 0 | } |
318 | | |
319 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
320 | 0 | { |
321 | 0 | uno::Reference<text::XTextTablesSupplier> xSupplier(mxObject, uno::UNO_QUERY); |
322 | 0 | if (!xSupplier.is()) |
323 | 0 | return mxObject; |
324 | 0 | return xSupplier->getTextTables(); |
325 | 0 | } |
326 | | }; |
327 | | |
328 | | /** Represents a list of frames */ |
329 | | class FramesEntry : public NameAccessTreeEntry |
330 | | { |
331 | | public: |
332 | | FramesEntry(OUString const& rString, css::uno::Reference<css::uno::XInterface> const& xObject) |
333 | 0 | : NameAccessTreeEntry(rString, xObject) |
334 | 0 | { |
335 | 0 | } |
336 | | |
337 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
338 | 0 | { |
339 | 0 | uno::Reference<text::XTextFramesSupplier> xSupplier(mxObject, uno::UNO_QUERY); |
340 | 0 | if (!xSupplier.is()) |
341 | 0 | return mxObject; |
342 | 0 | return xSupplier->getTextFrames(); |
343 | 0 | } |
344 | | }; |
345 | | |
346 | | /** Represents a list of writer graphic objects */ |
347 | | class WriterGraphicObjectsEntry : public NameAccessTreeEntry |
348 | | { |
349 | | public: |
350 | | WriterGraphicObjectsEntry(OUString const& rString, |
351 | | css::uno::Reference<css::uno::XInterface> const& xObject) |
352 | 0 | : NameAccessTreeEntry(rString, xObject) |
353 | 0 | { |
354 | 0 | } |
355 | | |
356 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
357 | 0 | { |
358 | 0 | uno::Reference<text::XTextGraphicObjectsSupplier> xSupplier(mxObject, uno::UNO_QUERY); |
359 | 0 | if (!xSupplier.is()) |
360 | 0 | return mxObject; |
361 | 0 | return xSupplier->getGraphicObjects(); |
362 | 0 | } |
363 | | }; |
364 | | |
365 | | /** Represents a list of writer embedded (OLE) objects */ |
366 | | class EmbeddedObjectsEntry : public NameAccessTreeEntry |
367 | | { |
368 | | public: |
369 | | EmbeddedObjectsEntry(OUString const& rString, |
370 | | css::uno::Reference<css::uno::XInterface> const& xObject) |
371 | 0 | : NameAccessTreeEntry(rString, xObject) |
372 | 0 | { |
373 | 0 | } |
374 | | |
375 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
376 | 0 | { |
377 | 0 | uno::Reference<text::XTextEmbeddedObjectsSupplier> xSupplier(mxObject, uno::UNO_QUERY); |
378 | 0 | if (!xSupplier.is()) |
379 | 0 | return mxObject; |
380 | 0 | return xSupplier->getEmbeddedObjects(); |
381 | 0 | } |
382 | | }; |
383 | | |
384 | | /** Represents a style family, which contains a list of styles */ |
385 | | class StylesFamilyEntry : public NameAccessTreeEntry |
386 | | { |
387 | | public: |
388 | | StylesFamilyEntry(OUString const& rString, |
389 | | css::uno::Reference<css::uno::XInterface> const& xObject) |
390 | 0 | : NameAccessTreeEntry(rString, xObject) |
391 | 0 | { |
392 | 0 | } |
393 | | }; |
394 | | |
395 | | /** Represents a list of style families */ |
396 | | class StylesFamiliesEntry : public DocumentModelTreeEntry |
397 | | { |
398 | | public: |
399 | | StylesFamiliesEntry(OUString const& rString, |
400 | | css::uno::Reference<css::uno::XInterface> const& xObject) |
401 | 0 | : DocumentModelTreeEntry(rString, xObject) |
402 | 0 | { |
403 | 0 | } |
404 | | |
405 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
406 | 0 | { |
407 | 0 | uno::Reference<style::XStyleFamiliesSupplier> xSupplier(mxObject, uno::UNO_QUERY); |
408 | 0 | if (!xSupplier.is()) |
409 | 0 | return mxObject; |
410 | 0 | return xSupplier->getStyleFamilies(); |
411 | 0 | } |
412 | | |
413 | | bool shouldShowExpander() override |
414 | 0 | { |
415 | 0 | uno::Reference<container::XNameAccess> xStyleFamilies(getMainObject(), uno::UNO_QUERY); |
416 | 0 | return xStyleFamilies.is() && xStyleFamilies->getElementNames().getLength() > 0; |
417 | 0 | } |
418 | | |
419 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
420 | | weld::TreeIter const& rParent) override |
421 | 0 | { |
422 | 0 | uno::Reference<container::XNameAccess> xStyleFamilies(getMainObject(), uno::UNO_QUERY); |
423 | 0 | if (!xStyleFamilies.is()) |
424 | 0 | return; |
425 | | |
426 | 0 | const uno::Sequence<OUString> aNames = xStyleFamilies->getElementNames(); |
427 | 0 | for (auto const& rFamilyName : aNames) |
428 | 0 | { |
429 | 0 | uno::Reference<uno::XInterface> xStyleFamily(xStyleFamilies->getByName(rFamilyName), |
430 | 0 | uno::UNO_QUERY); |
431 | |
|
432 | 0 | auto pStylesFamilyEntry |
433 | 0 | = std::make_unique<StylesFamilyEntry>(rFamilyName, xStyleFamily); |
434 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pStylesFamilyEntry.release()); |
435 | 0 | } |
436 | 0 | } |
437 | | }; |
438 | | |
439 | | /** Represents a list of pages */ |
440 | | class PagesEntry : public DocumentModelTreeEntry |
441 | | { |
442 | | public: |
443 | | PagesEntry(OUString const& rString, css::uno::Reference<css::uno::XInterface> const& xObject) |
444 | 0 | : DocumentModelTreeEntry(rString, xObject) |
445 | 0 | { |
446 | 0 | } |
447 | | |
448 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
449 | 0 | { |
450 | 0 | uno::Reference<drawing::XDrawPagesSupplier> xSupplier(mxObject, uno::UNO_QUERY); |
451 | 0 | if (!xSupplier.is()) |
452 | 0 | return mxObject; |
453 | 0 | return xSupplier->getDrawPages(); |
454 | 0 | } |
455 | | |
456 | | bool shouldShowExpander() override |
457 | 0 | { |
458 | 0 | uno::Reference<drawing::XDrawPages> xDrawPages(getMainObject(), uno::UNO_QUERY); |
459 | 0 | return xDrawPages.is() && xDrawPages->getCount() > 0; |
460 | 0 | } |
461 | | |
462 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
463 | | weld::TreeIter const& rParent) override |
464 | 0 | { |
465 | 0 | uno::Reference<drawing::XDrawPages> xDrawPages(getMainObject(), uno::UNO_QUERY); |
466 | 0 | for (sal_Int32 i = 0; i < xDrawPages->getCount(); ++i) |
467 | 0 | { |
468 | 0 | uno::Reference<drawing::XDrawPage> xPage(xDrawPages->getByIndex(i), uno::UNO_QUERY); |
469 | 0 | if (!xPage.is()) |
470 | 0 | continue; |
471 | | |
472 | 0 | OUString aPageString = lclGetNamed(xPage); |
473 | 0 | if (aPageString.isEmpty()) |
474 | 0 | aPageString = SfxResId(STR_PAGE).replaceFirst("%1", OUString::number(i + 1)); |
475 | |
|
476 | 0 | auto pShapesEntry = std::make_unique<ShapesEntry>(aPageString, xPage); |
477 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pShapesEntry.release()); |
478 | 0 | } |
479 | 0 | } |
480 | | }; |
481 | | |
482 | | /** Represents a list of (Impress) slides */ |
483 | | class SlidesEntry : public DocumentModelTreeEntry |
484 | | { |
485 | | public: |
486 | | SlidesEntry(OUString const& rString, css::uno::Reference<css::uno::XInterface> const& xObject) |
487 | 0 | : DocumentModelTreeEntry(rString, xObject) |
488 | 0 | { |
489 | 0 | } |
490 | | |
491 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
492 | 0 | { |
493 | 0 | uno::Reference<drawing::XDrawPagesSupplier> xSupplier(mxObject, uno::UNO_QUERY); |
494 | 0 | if (!xSupplier.is()) |
495 | 0 | return mxObject; |
496 | 0 | return xSupplier->getDrawPages(); |
497 | 0 | } |
498 | | |
499 | | bool shouldShowExpander() override |
500 | 0 | { |
501 | 0 | uno::Reference<drawing::XDrawPages> xDrawPages(getMainObject(), uno::UNO_QUERY); |
502 | 0 | return xDrawPages.is() && xDrawPages->getCount() > 0; |
503 | 0 | } |
504 | | |
505 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
506 | | weld::TreeIter const& rParent) override |
507 | 0 | { |
508 | 0 | uno::Reference<drawing::XDrawPages> xDrawPages(getMainObject(), uno::UNO_QUERY); |
509 | 0 | for (sal_Int32 i = 0; i < xDrawPages->getCount(); ++i) |
510 | 0 | { |
511 | 0 | uno::Reference<drawing::XDrawPage> xPage(xDrawPages->getByIndex(i), uno::UNO_QUERY); |
512 | 0 | if (!xPage.is()) |
513 | 0 | continue; |
514 | | |
515 | 0 | OUString aPageString = lclGetNamed(xPage); |
516 | 0 | if (aPageString.isEmpty()) |
517 | 0 | aPageString = SfxResId(STR_SLIDE).replaceFirst("%1", OUString::number(i + 1)); |
518 | |
|
519 | 0 | auto pShapesEntry = std::make_unique<ShapesEntry>(aPageString, xPage); |
520 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pShapesEntry.release()); |
521 | 0 | } |
522 | 0 | } |
523 | | }; |
524 | | |
525 | | /** Represents a list of (Impress) master slides */ |
526 | | class MasterSlidesEntry : public DocumentModelTreeEntry |
527 | | { |
528 | | public: |
529 | | MasterSlidesEntry(OUString const& rString, |
530 | | css::uno::Reference<css::uno::XInterface> const& xObject) |
531 | 0 | : DocumentModelTreeEntry(rString, xObject) |
532 | 0 | { |
533 | 0 | } |
534 | | |
535 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
536 | 0 | { |
537 | 0 | uno::Reference<drawing::XMasterPagesSupplier> xSupplier(mxObject, uno::UNO_QUERY); |
538 | 0 | if (!xSupplier.is()) |
539 | 0 | return mxObject; |
540 | 0 | return xSupplier->getMasterPages(); |
541 | 0 | } |
542 | | |
543 | | bool shouldShowExpander() override |
544 | 0 | { |
545 | 0 | uno::Reference<drawing::XDrawPages> xDrawPages(getMainObject(), uno::UNO_QUERY); |
546 | 0 | return xDrawPages.is() && xDrawPages->getCount() > 0; |
547 | 0 | } |
548 | | |
549 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
550 | | weld::TreeIter const& rParent) override |
551 | 0 | { |
552 | 0 | uno::Reference<drawing::XDrawPages> xDrawPages(getMainObject(), uno::UNO_QUERY); |
553 | 0 | for (sal_Int32 i = 0; i < xDrawPages->getCount(); ++i) |
554 | 0 | { |
555 | 0 | uno::Reference<drawing::XDrawPage> xPage(xDrawPages->getByIndex(i), uno::UNO_QUERY); |
556 | 0 | if (!xPage.is()) |
557 | 0 | continue; |
558 | | |
559 | 0 | OUString aPageString = lclGetNamed(xPage); |
560 | 0 | if (aPageString.isEmpty()) |
561 | 0 | { |
562 | 0 | aPageString |
563 | 0 | = SfxResId(STR_MASTER_SLIDE).replaceFirst("%1", OUString::number(i + 1)); |
564 | 0 | } |
565 | |
|
566 | 0 | auto pShapesEntry = std::make_unique<ShapesEntry>(aPageString, xPage); |
567 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pShapesEntry.release()); |
568 | 0 | } |
569 | 0 | } |
570 | | }; |
571 | | |
572 | | /** Represents a list of charts */ |
573 | | class ChartsEntry : public NameAccessTreeEntry |
574 | | { |
575 | | public: |
576 | | ChartsEntry(OUString const& rString, css::uno::Reference<css::uno::XInterface> const& xObject) |
577 | 0 | : NameAccessTreeEntry(rString, xObject) |
578 | 0 | { |
579 | 0 | } |
580 | | |
581 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
582 | 0 | { |
583 | 0 | uno::Reference<table::XTableChartsSupplier> xSupplier(mxObject, uno::UNO_QUERY); |
584 | 0 | if (!xSupplier.is()) |
585 | 0 | return mxObject; |
586 | 0 | return xSupplier->getCharts(); |
587 | 0 | } |
588 | | |
589 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
590 | | weld::TreeIter const& rParent) override |
591 | 0 | { |
592 | 0 | uno::Reference<table::XTableCharts> xCharts(getMainObject(), uno::UNO_QUERY); |
593 | 0 | if (!xCharts.is()) |
594 | 0 | return; |
595 | 0 | NameAccessTreeEntry::fill(pDocumentModelTree, rParent); |
596 | 0 | } |
597 | | }; |
598 | | |
599 | | /** Represents a list of pivot tables */ |
600 | | class PivotTablesEntry : public NameAccessTreeEntry |
601 | | { |
602 | | public: |
603 | | PivotTablesEntry(OUString const& rString, |
604 | | css::uno::Reference<css::uno::XInterface> const& xObject) |
605 | 0 | : NameAccessTreeEntry(rString, xObject) |
606 | 0 | { |
607 | 0 | } |
608 | | |
609 | 0 | bool shouldShowExpander() override { return true; } |
610 | | |
611 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
612 | 0 | { |
613 | 0 | uno::Reference<sheet::XDataPilotTablesSupplier> xSupplier(mxObject, uno::UNO_QUERY); |
614 | 0 | if (!xSupplier.is()) |
615 | 0 | return mxObject; |
616 | 0 | return xSupplier->getDataPilotTables(); |
617 | 0 | } |
618 | | |
619 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
620 | | weld::TreeIter const& rParent) override |
621 | 0 | { |
622 | 0 | uno::Reference<sheet::XDataPilotTables> xPivotTables(getMainObject(), uno::UNO_QUERY); |
623 | 0 | if (!xPivotTables.is()) |
624 | 0 | return; |
625 | 0 | NameAccessTreeEntry::fill(pDocumentModelTree, rParent); |
626 | 0 | } |
627 | | }; |
628 | | |
629 | | /** Represents a (Calc) sheet */ |
630 | | class SheetEntry : public DocumentModelTreeEntry |
631 | | { |
632 | | public: |
633 | | SheetEntry(OUString const& rString, css::uno::Reference<css::uno::XInterface> const& xObject) |
634 | 0 | : DocumentModelTreeEntry(rString, xObject) |
635 | 0 | { |
636 | 0 | } |
637 | | |
638 | 0 | bool shouldShowExpander() override { return true; } |
639 | | |
640 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
641 | | weld::TreeIter const& rParent) override |
642 | 0 | { |
643 | 0 | auto pShapesEntry |
644 | 0 | = std::make_unique<ShapesEntry>(SfxResId(STR_SHAPES_ENTRY), getMainObject()); |
645 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pShapesEntry.release()); |
646 | |
|
647 | 0 | auto pChartsEntry |
648 | 0 | = std::make_unique<ChartsEntry>(SfxResId(STR_CHARTS_ENTRY), getMainObject()); |
649 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pChartsEntry.release()); |
650 | |
|
651 | 0 | auto pPivotTablesEntry |
652 | 0 | = std::make_unique<PivotTablesEntry>(SfxResId(STR_PIVOT_TABLES_ENTRY), getMainObject()); |
653 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pPivotTablesEntry.release()); |
654 | 0 | } |
655 | | }; |
656 | | |
657 | | /** Represents a list of (Calc) sheet */ |
658 | | class SheetsEntry : public DocumentModelTreeEntry |
659 | | { |
660 | | public: |
661 | | SheetsEntry(OUString const& rString, css::uno::Reference<css::uno::XInterface> const& xObject) |
662 | 0 | : DocumentModelTreeEntry(rString, xObject) |
663 | 0 | { |
664 | 0 | } |
665 | | |
666 | | css::uno::Reference<css::uno::XInterface> getMainObject() override |
667 | 0 | { |
668 | 0 | uno::Reference<sheet::XSpreadsheetDocument> xSheetDocument(mxObject, uno::UNO_QUERY); |
669 | 0 | if (!xSheetDocument.is()) |
670 | 0 | return mxObject; |
671 | 0 | return xSheetDocument->getSheets(); |
672 | 0 | } |
673 | | |
674 | | bool shouldShowExpander() override |
675 | 0 | { |
676 | 0 | uno::Reference<container::XIndexAccess> xIndexAccess(getMainObject(), uno::UNO_QUERY); |
677 | 0 | return xIndexAccess.is() && xIndexAccess->getCount() > 0; |
678 | 0 | } |
679 | | |
680 | | void fill(std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
681 | | weld::TreeIter const& rParent) override |
682 | 0 | { |
683 | 0 | uno::Reference<container::XIndexAccess> xIndexAccesss(getMainObject(), uno::UNO_QUERY); |
684 | 0 | if (!xIndexAccesss.is()) |
685 | 0 | return; |
686 | | |
687 | 0 | for (sal_Int32 i = 0; i < xIndexAccesss->getCount(); ++i) |
688 | 0 | { |
689 | 0 | uno::Reference<sheet::XSpreadsheet> xSheet(xIndexAccesss->getByIndex(i), |
690 | 0 | uno::UNO_QUERY); |
691 | 0 | OUString aString = lclGetNamed(xSheet); |
692 | 0 | if (aString.isEmpty()) |
693 | 0 | aString = SfxResId(STR_SHEET).replaceFirst("%1", OUString::number(i + 1)); |
694 | 0 | auto pEntry = std::make_unique<SheetEntry>(aString, xSheet); |
695 | 0 | lclAppendToParentEntry(pDocumentModelTree, rParent, pEntry.release()); |
696 | 0 | } |
697 | 0 | } |
698 | | }; |
699 | | |
700 | | } // end anonymous namespace |
701 | | |
702 | | DocumentModelTreeHandler::DocumentModelTreeHandler( |
703 | | std::unique_ptr<weld::TreeView>& pDocumentModelTree, |
704 | | css::uno::Reference<css::uno::XInterface> xDocument) |
705 | 0 | : mpDocumentModelTree(pDocumentModelTree) |
706 | 0 | , mxDocument(std::move(xDocument)) |
707 | 0 | { |
708 | 0 | mpDocumentModelTree->connect_expanding(LINK(this, DocumentModelTreeHandler, ExpandingHandler)); |
709 | 0 | } |
710 | | |
711 | | uno::Reference<uno::XInterface> DocumentModelTreeHandler::getObjectByID(OUString const& rID) |
712 | 0 | { |
713 | 0 | uno::Reference<uno::XInterface> xObject; |
714 | 0 | if (rID.isEmpty()) |
715 | 0 | return xObject; |
716 | 0 | auto* pEntry = weld::fromId<DocumentModelTreeEntry*>(rID); |
717 | 0 | return pEntry->getMainObject(); |
718 | 0 | } |
719 | | |
720 | | void DocumentModelTreeHandler::clearAll() |
721 | 0 | { |
722 | | // destroy all DocumentModelTreeEntries from the tree |
723 | 0 | mpDocumentModelTree->all_foreach([this](weld::TreeIter& rEntry) { |
724 | 0 | OUString sID = mpDocumentModelTree->get_id(rEntry); |
725 | 0 | auto* pEntry = weld::fromId<DocumentModelTreeEntry*>(sID); |
726 | 0 | delete pEntry; |
727 | 0 | return false; |
728 | 0 | }); |
729 | 0 | mpDocumentModelTree->clear(); |
730 | 0 | } |
731 | | |
732 | | void DocumentModelTreeHandler::clearChildren(weld::TreeIter const& rParent) |
733 | 0 | { |
734 | 0 | bool bChild = false; |
735 | 0 | do |
736 | 0 | { |
737 | 0 | bChild = mpDocumentModelTree->iter_has_child(rParent); |
738 | 0 | if (bChild) |
739 | 0 | { |
740 | 0 | std::unique_ptr<weld::TreeIter> pChild = mpDocumentModelTree->make_iterator(&rParent); |
741 | 0 | bChild = mpDocumentModelTree->iter_children(*pChild); |
742 | 0 | if (bChild) |
743 | 0 | { |
744 | 0 | clearChildren(*pChild); |
745 | 0 | OUString sID = mpDocumentModelTree->get_id(*pChild); |
746 | 0 | auto* pEntry = weld::fromId<DocumentModelTreeEntry*>(sID); |
747 | 0 | delete pEntry; |
748 | 0 | mpDocumentModelTree->remove(*pChild); |
749 | 0 | } |
750 | 0 | } |
751 | 0 | } while (bChild); |
752 | 0 | } |
753 | | |
754 | | void DocumentModelTreeHandler::dispose() |
755 | 0 | { |
756 | 0 | mpDocumentModelTree->all_foreach([this](weld::TreeIter& rEntry) { |
757 | 0 | OUString sID = mpDocumentModelTree->get_id(rEntry); |
758 | 0 | auto* pEntry = weld::fromId<DocumentModelTreeEntry*>(sID); |
759 | 0 | delete pEntry; |
760 | 0 | return false; |
761 | 0 | }); |
762 | 0 | } |
763 | | |
764 | | IMPL_LINK(DocumentModelTreeHandler, ExpandingHandler, weld::TreeIter const&, rParent, bool) |
765 | 0 | { |
766 | 0 | OUString sID = mpDocumentModelTree->get_id(rParent); |
767 | 0 | if (sID.isEmpty()) |
768 | 0 | return true; |
769 | | |
770 | 0 | clearChildren(rParent); |
771 | 0 | auto* pEntry = weld::fromId<DocumentModelTreeEntry*>(sID); |
772 | 0 | pEntry->fill(mpDocumentModelTree, rParent); |
773 | |
|
774 | 0 | return true; |
775 | 0 | } |
776 | | |
777 | | void DocumentModelTreeHandler::selectObject( |
778 | | css::uno::Reference<css::uno::XInterface> const& xInterface) |
779 | 0 | { |
780 | 0 | mpDocumentModelTree->unselect_all(); |
781 | |
|
782 | 0 | mpDocumentModelTree->all_foreach([this, xInterface](weld::TreeIter& rEntry) { |
783 | 0 | OUString sID = mpDocumentModelTree->get_id(rEntry); |
784 | 0 | auto* pEntry = weld::fromId<DocumentModelTreeEntry*>(sID); |
785 | 0 | if (xInterface == pEntry->getMainObject()) |
786 | 0 | { |
787 | 0 | mpDocumentModelTree->select(rEntry); |
788 | 0 | return true; |
789 | 0 | } |
790 | 0 | return false; |
791 | 0 | }); |
792 | 0 | } |
793 | | |
794 | | void DocumentModelTreeHandler::inspectDocument() |
795 | 0 | { |
796 | 0 | clearAll(); |
797 | |
|
798 | 0 | uno::Reference<lang::XServiceInfo> xDocumentServiceInfo(mxDocument, uno::UNO_QUERY_THROW); |
799 | |
|
800 | 0 | lclAppend(mpDocumentModelTree, new DocumentRootEntry(SfxResId(STR_DOCUMENT_ENTRY), mxDocument)); |
801 | |
|
802 | 0 | if (xDocumentServiceInfo->supportsService(u"com.sun.star.sheet.SpreadsheetDocument"_ustr)) |
803 | 0 | { |
804 | 0 | lclAppend(mpDocumentModelTree, new SheetsEntry(SfxResId(STR_SHEETS_ENTRY), mxDocument)); |
805 | 0 | lclAppend(mpDocumentModelTree, |
806 | 0 | new StylesFamiliesEntry(SfxResId(STR_STYLES_ENTRY), mxDocument)); |
807 | 0 | } |
808 | 0 | else if (xDocumentServiceInfo->supportsService( |
809 | 0 | u"com.sun.star.presentation.PresentationDocument"_ustr)) |
810 | 0 | { |
811 | 0 | lclAppend(mpDocumentModelTree, new SlidesEntry(SfxResId(STR_SLIDES_ENTRY), mxDocument)); |
812 | 0 | lclAppend(mpDocumentModelTree, |
813 | 0 | new MasterSlidesEntry(SfxResId(STR_MASTER_SLIDES_ENTRY), mxDocument)); |
814 | 0 | lclAppend(mpDocumentModelTree, |
815 | 0 | new StylesFamiliesEntry(SfxResId(STR_STYLES_ENTRY), mxDocument)); |
816 | 0 | } |
817 | 0 | else if (xDocumentServiceInfo->supportsService(u"com.sun.star.drawing.DrawingDocument"_ustr)) |
818 | 0 | { |
819 | 0 | lclAppend(mpDocumentModelTree, new PagesEntry(SfxResId(STR_PAGES_ENTRY), mxDocument)); |
820 | 0 | lclAppend(mpDocumentModelTree, |
821 | 0 | new StylesFamiliesEntry(SfxResId(STR_STYLES_ENTRY), mxDocument)); |
822 | 0 | } |
823 | 0 | else if (xDocumentServiceInfo->supportsService(u"com.sun.star.text.TextDocument"_ustr) |
824 | 0 | || xDocumentServiceInfo->supportsService(u"com.sun.star.text.WebDocument"_ustr)) |
825 | 0 | { |
826 | 0 | lclAppend(mpDocumentModelTree, |
827 | 0 | new ParagraphsEntry(SfxResId(STR_PARAGRAPHS_ENTRY), mxDocument)); |
828 | 0 | lclAppend(mpDocumentModelTree, new ShapesEntry(SfxResId(STR_SHAPES_ENTRY), mxDocument)); |
829 | 0 | lclAppend(mpDocumentModelTree, new TablesEntry(SfxResId(STR_TABLES_ENTRY), mxDocument)); |
830 | 0 | lclAppend(mpDocumentModelTree, new FramesEntry(SfxResId(STR_FRAMES_ENTRY), mxDocument)); |
831 | 0 | lclAppend(mpDocumentModelTree, |
832 | 0 | new WriterGraphicObjectsEntry(SfxResId(STR_GRAPHIC_OBJECTS_ENTRY), mxDocument)); |
833 | 0 | lclAppend(mpDocumentModelTree, |
834 | 0 | new EmbeddedObjectsEntry(SfxResId(STR_EMBEDDED_OBJECTS_ENTRY), mxDocument)); |
835 | 0 | lclAppend(mpDocumentModelTree, |
836 | 0 | new StylesFamiliesEntry(SfxResId(STR_STYLES_ENTRY), mxDocument)); |
837 | 0 | } |
838 | 0 | } |
839 | | |
840 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |