Coverage Report

Created: 2026-05-16 09:25

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
#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: */