Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */