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