Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sw/source/uibase/utlui/glbltree.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
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <o3tl/safeint.hxx>
21
#include <svl/stritem.hxx>
22
#include <sfx2/fcontnr.hxx>
23
#include <sfx2/linkmgr.hxx>
24
#include <sfx2/dispatch.hxx>
25
#include <sfx2/viewfrm.hxx>
26
#include <sfx2/docfile.hxx>
27
#include <sfx2/docfilt.hxx>
28
#include <vcl/commandevent.hxx>
29
#include <vcl/event.hxx>
30
#include <sot/filelist.hxx>
31
#include <svl/eitem.hxx>
32
#include <vcl/graphicfilter.hxx>
33
#include <osl/diagnose.h>
34
35
#include <sfx2/docinsert.hxx>
36
#include <sfx2/filedlghelper.hxx>
37
38
#include <wrtsh.hxx>
39
#include <view.hxx>
40
#include <docsh.hxx>
41
#include <edglbldc.hxx>
42
#include <section.hxx>
43
#include <tox.hxx>
44
#include <navipi.hxx>
45
#include <edtwin.hxx>
46
#include <toxmgr.hxx>
47
48
#include <cmdid.h>
49
#include <helpids.h>
50
#include <strings.hrc>
51
#include <bitmaps.hlst>
52
#include <swabstdlg.hxx>
53
#include <memory>
54
55
#include <sfx2/event.hxx>
56
#include <unotxvw.hxx>
57
58
using namespace ::com::sun::star::uno;
59
60
0
#define GLOBAL_UPDATE_TIMEOUT 2000
61
62
const SfxObjectShell* SwGlobalTree::s_pShowShell = nullptr;
63
64
namespace {
65
66
class SwGlobalFrameListener_Impl : public SfxListener
67
{
68
    bool m_bValid;
69
public:
70
    explicit SwGlobalFrameListener_Impl(SfxViewFrame& rFrame)
71
0
        : m_bValid(true)
72
0
    {
73
0
        StartListening(rFrame);
74
0
    }
75
76
    virtual void        Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
77
78
0
    bool                IsValid() const {return m_bValid;}
79
};
80
81
}
82
83
void SwGlobalFrameListener_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
84
0
{
85
0
    if( rHint.GetId() == SfxHintId::Dying)
86
0
        m_bValid = false;
87
0
}
88
89
namespace {
90
91
enum GLOBAL_CONTEXT_IDX
92
{
93
    IDX_STR_UPDATE = 0,
94
    IDX_STR_EDIT_CONTENT = 1,
95
    IDX_STR_EDIT_INSERT = 2,
96
    IDX_STR_INDEX = 3,
97
    IDX_STR_FILE = 4,
98
    IDX_STR_NEW_FILE = 5,
99
    IDX_STR_INSERT_TEXT = 6,
100
    IDX_STR_DELETE = 7,
101
    IDX_STR_UPDATE_SEL = 8,
102
    IDX_STR_UPDATE_INDEX = 9,
103
    IDX_STR_UPDATE_LINK = 10,
104
    IDX_STR_UPDATE_ALL = 11,
105
    IDX_STR_BROKEN_LINK = 12,
106
    IDX_STR_EDIT_LINK = 13
107
};
108
109
}
110
111
const TranslateId GLOBAL_CONTEXT_ARY[] =
112
{
113
    STR_UPDATE,
114
    STR_EDIT_CONTENT,
115
    STR_EDIT_INSERT,
116
    STR_INDEX,
117
    STR_FILE,
118
    STR_NEW_FILE,
119
    STR_INSERT_TEXT,
120
    STR_DELETE,
121
    STR_UPDATE_SEL,
122
    STR_UPDATE_INDEX,
123
    STR_UPDATE_LINK,
124
    STR_UPDATE_ALL,
125
    STR_BROKEN_LINK,
126
    STR_EDIT_LINK
127
};
128
129
SwGlobalTree::SwGlobalTree(std::unique_ptr<weld::TreeView> xTreeView, SwNavigationPI* pDialog)
130
0
    : m_xTreeView(std::move(xTreeView))
131
0
    , m_aDropTargetHelper(*this)
132
0
    , m_pDialog(pDialog)
133
0
    , m_aUpdateTimer("SwGlobalTree m_aUpdateTimer")
134
0
    , m_pActiveShell(nullptr)
135
0
{
136
0
    m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 30,
137
0
                                  m_xTreeView->get_text_height() * 14);
138
139
0
    m_aUpdateTimer.SetTimeout(GLOBAL_UPDATE_TIMEOUT);
140
0
    m_aUpdateTimer.SetInvokeHandler(LINK(this, SwGlobalTree, Timeout));
141
0
    m_aUpdateTimer.Start();
142
0
    for (sal_uInt16 i = 0; i < GLOBAL_CONTEXT_COUNT; i++)
143
0
    {
144
0
        m_aContextStrings[i] = SwResId(GLOBAL_CONTEXT_ARY[i]);
145
0
    }
146
0
    m_xTreeView->set_help_id(HID_NAVIGATOR_GLOB_TREELIST);
147
0
    Select();
148
0
    m_xTreeView->connect_row_activated(LINK(this, SwGlobalTree, DoubleClickHdl));
149
0
    m_xTreeView->connect_selection_changed(LINK(this, SwGlobalTree, SelectHdl));
150
0
    m_xTreeView->connect_focus_in(LINK(this, SwGlobalTree, FocusInHdl));
151
0
    m_xTreeView->connect_key_press(LINK(this, SwGlobalTree, KeyInputHdl));
152
0
    m_xTreeView->connect_popup_menu(LINK(this, SwGlobalTree, CommandHdl));
153
0
    m_xTreeView->connect_query_tooltip(LINK(this, SwGlobalTree, QueryTooltipHdl));
154
0
}
155
156
SwGlobalTree::~SwGlobalTree()
157
0
{
158
0
    m_pSwGlblDocContents.reset();
159
0
    m_pDocInserter.reset();
160
0
    m_aUpdateTimer.Stop();
161
0
}
162
163
SwGlobalTreeDropTarget::SwGlobalTreeDropTarget(SwGlobalTree& rTreeView)
164
0
    : DropTargetHelper(rTreeView.get_widget().get_drop_target())
165
0
    , m_rTreeView(rTreeView)
166
0
{
167
0
}
168
169
sal_Int8 SwGlobalTreeDropTarget::ExecuteDrop( const ExecuteDropEvent& rEvt )
170
0
{
171
0
    sal_Int8 nRet = DND_ACTION_NONE;
172
173
0
    weld::TreeView& rWidget = m_rTreeView.get_widget();
174
0
    std::unique_ptr<weld::TreeIter> xDropEntry(rWidget.make_iterator());
175
0
    if (!rWidget.get_dest_row_at_pos(rEvt.maPosPixel, xDropEntry.get(), true))
176
0
        xDropEntry.reset();
177
178
0
    if (rWidget.get_drag_source() == &rWidget)  // internal drag
179
0
        m_rTreeView.MoveSelectionTo(xDropEntry.get());
180
0
    else
181
0
    {
182
0
        TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
183
184
0
        OUString sFileName;
185
0
        const SwGlblDocContent* pCnt = xDropEntry ?
186
0
                    weld::fromId<const SwGlblDocContent*>(rWidget.get_id(*xDropEntry)) :
187
0
                            nullptr;
188
0
        if( aData.HasFormat( SotClipboardFormatId::FILE_LIST ))
189
0
        {
190
0
            nRet = rEvt.mnAction;
191
0
            SwGlblDocContents aTempContents;
192
0
            int nAbsContPos = xDropEntry ?
193
0
                                rWidget.get_iter_index_in_parent(*xDropEntry):
194
0
                                    - 1;
195
0
            size_t nEntryCount = rWidget.n_children();
196
197
            // Get data
198
0
            FileList aFileList;
199
0
            aData.GetFileList( SotClipboardFormatId::FILE_LIST, aFileList );
200
0
            size_t n = aFileList.Count();
201
0
            while (n)
202
0
            {
203
0
                --n;
204
0
                sFileName = aFileList.GetFile(n);
205
0
                m_rTreeView.InsertRegion(pCnt, &sFileName);
206
                // The list of contents must be newly fetched after inserting,
207
                // to not work on an old content.
208
0
                if(n)
209
0
                {
210
0
                    if (const SwWrtShell* pSh = m_rTreeView.GetActiveWrtShell())
211
0
                    {
212
0
                        pSh->GetGlobalDocContent(aTempContents);
213
                        // If the file was successfully inserted,
214
                        // then the next content must also be fetched.
215
0
                        if(nEntryCount < aTempContents.size())
216
0
                        {
217
0
                            nEntryCount++;
218
0
                            nAbsContPos++;
219
0
                            pCnt = aTempContents[ nAbsContPos ].get();
220
0
                        }
221
0
                    }
222
0
                }
223
0
            }
224
0
        }
225
0
        else if( !(sFileName =
226
0
                        SwNavigationPI::CreateDropFileName( aData )).isEmpty())
227
0
        {
228
0
            INetURLObject aTemp(sFileName);
229
0
            GraphicDescriptor aDesc(aTemp);
230
0
            if( !aDesc.Detect() )   // accept no graphics
231
0
            {
232
0
                nRet = rEvt.mnAction;
233
0
                m_rTreeView.InsertRegion(pCnt, &sFileName);
234
0
            }
235
0
        }
236
0
    }
237
0
    return nRet;
238
0
}
239
240
sal_Int8 SwGlobalTreeDropTarget::AcceptDrop( const AcceptDropEvent& rEvt )
241
0
{
242
    // to enable the autoscroll when we're close to the edges
243
0
    weld::TreeView& rWidget = m_rTreeView.get_widget();
244
0
    rWidget.get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true);
245
246
0
    sal_Int8 nRet = rEvt.mnAction;
247
248
0
    if (rWidget.get_drag_source() == &rWidget)  // internal drag
249
0
        return nRet;
250
251
0
    if (IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE) ||
252
0
        IsDropFormatSupported( SotClipboardFormatId::STRING) ||
253
0
        IsDropFormatSupported( SotClipboardFormatId::FILE_LIST) ||
254
0
        IsDropFormatSupported( SotClipboardFormatId::SOLK) ||
255
0
        IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK )||
256
0
        IsDropFormatSupported( SotClipboardFormatId::FILECONTENT) ||
257
0
        IsDropFormatSupported( SotClipboardFormatId::FILEGRPDESCRIPTOR) ||
258
0
        IsDropFormatSupported( SotClipboardFormatId::UNIFORMRESOURCELOCATOR) ||
259
0
        IsDropFormatSupported( SotClipboardFormatId::FILENAME))
260
0
    {
261
0
        nRet = DND_ACTION_LINK;
262
0
    }
263
264
0
    return nRet;
265
0
}
266
267
IMPL_LINK(SwGlobalTree, CommandHdl, const CommandEvent&, rCEvt, bool)
268
0
{
269
0
    if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
270
0
        return false;
271
272
0
    bool bPop = false;
273
0
    if (m_pActiveShell && !m_pActiveShell->GetView().GetDocShell()->IsReadOnly())
274
0
    {
275
0
        std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xTreeView.get(), u"modules/swriter/ui/mastercontextmenu.ui"_ustr));
276
0
        std::unique_ptr<weld::Menu> xPopup = xBuilder->weld_menu(u"navmenu"_ustr);
277
0
        std::unique_ptr<weld::Menu> xSubPopup = xBuilder->weld_menu(u"insertmenu"_ustr);
278
279
0
        const MenuEnableFlags nEnableFlags = GetEnableFlags();
280
281
0
        xPopup->set_sensitive(u"updatesel"_ustr, bool(nEnableFlags & MenuEnableFlags::UpdateSel));
282
283
0
        xPopup->set_sensitive(u"editlink"_ustr, bool(nEnableFlags & MenuEnableFlags::EditLink));
284
285
        //disabling if applicable
286
0
        xSubPopup->set_sensitive(u"insertindex"_ustr, bool(nEnableFlags & MenuEnableFlags::InsertIdx ));
287
0
        xSubPopup->set_sensitive(u"insertfile"_ustr, bool(nEnableFlags & MenuEnableFlags::InsertFile));
288
0
        xSubPopup->set_sensitive(u"insertnewfile"_ustr, bool(nEnableFlags & MenuEnableFlags::InsertFile));
289
0
        xSubPopup->set_sensitive(u"inserttext"_ustr, bool(nEnableFlags & MenuEnableFlags::InsertText));
290
291
0
        xPopup->set_sensitive(u"update"_ustr, bool(nEnableFlags & MenuEnableFlags::Update));
292
0
        xPopup->set_sensitive(u"insert"_ustr, bool(nEnableFlags & MenuEnableFlags::InsertIdx));
293
0
        xPopup->set_sensitive(u"editcontent"_ustr, bool(nEnableFlags & MenuEnableFlags::Edit));
294
0
        xPopup->set_sensitive(u"deleteentry"_ustr, bool(nEnableFlags & MenuEnableFlags::Delete));
295
296
0
        OUString sCommand = xPopup->popup_at_rect(m_xTreeView.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
297
0
        if (!sCommand.isEmpty())
298
0
            ExecuteContextMenuAction(sCommand);
299
300
0
        bPop = true;
301
0
    }
302
0
    return bPop;
303
0
}
304
305
void SwGlobalTree::TbxMenuHdl(std::u16string_view rCommand, weld::Menu& rMenu)
306
0
{
307
0
    const MenuEnableFlags nEnableFlags = GetEnableFlags();
308
0
    if (rCommand == u"insert")
309
0
    {
310
0
        rMenu.set_sensitive(u"insertindex"_ustr, bool(nEnableFlags & MenuEnableFlags::InsertIdx));
311
0
        rMenu.set_sensitive(u"insertfile"_ustr, bool(nEnableFlags & MenuEnableFlags::InsertFile));
312
0
        rMenu.set_sensitive(u"insertnewfile"_ustr, bool(nEnableFlags & MenuEnableFlags::InsertFile));
313
0
        rMenu.set_sensitive(u"inserttext"_ustr, bool(nEnableFlags & MenuEnableFlags::InsertText));
314
0
    }
315
0
    else if (rCommand == u"update")
316
0
    {
317
0
        rMenu.set_sensitive(u"updatesel"_ustr, bool(nEnableFlags & MenuEnableFlags::UpdateSel));
318
0
    }
319
0
}
320
321
MenuEnableFlags SwGlobalTree::GetEnableFlags() const
322
0
{
323
0
    std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
324
0
    bool bEntry = m_xTreeView->get_selected(xEntry.get());
325
326
0
    int nSelCount = m_xTreeView->count_selected_rows();
327
0
    size_t nEntryCount = m_xTreeView->n_children();
328
0
    std::unique_ptr<weld::TreeIter> xPrevEntry;
329
0
    bool bPrevEntry = false;
330
0
    if (bEntry)
331
0
    {
332
0
        xPrevEntry = m_xTreeView->make_iterator(xEntry.get());
333
0
        bPrevEntry = m_xTreeView->iter_previous(*xPrevEntry);
334
0
    }
335
336
0
    MenuEnableFlags nRet = MenuEnableFlags::NONE;
337
0
    if(nSelCount == 1 || !nEntryCount)
338
0
        nRet |= MenuEnableFlags::InsertIdx|MenuEnableFlags::InsertFile;
339
0
    if(nSelCount == 1)
340
0
    {
341
0
        nRet |= MenuEnableFlags::Edit;
342
0
        if (bEntry && weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(*xEntry))->GetType() != GLBLDOC_UNKNOWN &&
343
0
                    (!bPrevEntry || weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(*xPrevEntry))->GetType() != GLBLDOC_UNKNOWN))
344
0
            nRet |= MenuEnableFlags::InsertText;
345
0
        if (bEntry && GLBLDOC_SECTION == weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(*xEntry))->GetType())
346
0
            nRet |= MenuEnableFlags::EditLink;
347
0
    }
348
0
    else if(!nEntryCount)
349
0
    {
350
0
        nRet |= MenuEnableFlags::InsertText;
351
0
    }
352
0
    if(nEntryCount)
353
0
        nRet |= MenuEnableFlags::Update|MenuEnableFlags::Delete;
354
0
    if(nSelCount)
355
0
        nRet |= MenuEnableFlags::UpdateSel;
356
0
    return nRet;
357
0
}
358
359
IMPL_LINK(SwGlobalTree, QueryTooltipHdl, const weld::TreeIter&, rIter, OUString)
360
0
{
361
0
    OUString sEntry;
362
363
0
    const SwGlblDocContent* pCont = weld::fromId<const SwGlblDocContent*>(m_xTreeView->get_id(rIter));
364
0
    if (pCont && GLBLDOC_SECTION == pCont->GetType())
365
0
    {
366
0
        const SwSection* pSect = pCont->GetSection();
367
0
        sEntry = pSect->GetLinkFileName().getToken(0, sfx2::cTokenSeparator);
368
0
        if (!pSect->IsConnectFlag())
369
0
            sEntry = m_aContextStrings[IDX_STR_BROKEN_LINK] + sEntry;
370
0
    }
371
372
0
    return sEntry;
373
0
}
374
375
IMPL_LINK_NOARG(SwGlobalTree, SelectHdl, weld::TreeView&, void)
376
0
{
377
0
    Select();
378
0
}
379
380
void SwGlobalTree::Select()
381
0
{
382
0
    int nSelCount = m_xTreeView->count_selected_rows();
383
0
    int nSel = m_xTreeView->get_selected_index();
384
0
    int nAbsPos = nSel != -1 ? nSel : 0;
385
0
    SwNavigationPI* pNavi = GetParentWindow();
386
0
    bool bReadonly = !m_pActiveShell ||
387
0
                m_pActiveShell->GetView().GetDocShell()->IsReadOnly();
388
0
    pNavi->m_xGlobalToolBox->set_item_sensitive(u"edit"_ustr,  nSelCount == 1 && !bReadonly);
389
0
    pNavi->m_xGlobalToolBox->set_item_sensitive(u"insert"_ustr,  nSelCount <= 1 && !bReadonly);
390
0
    pNavi->m_xGlobalToolBox->set_item_sensitive(u"update"_ustr,  m_xTreeView->n_children() > 0 && !bReadonly);
391
0
    pNavi->m_xGlobalToolBox->set_item_sensitive(u"moveup"_ustr,
392
0
                    nSelCount == 1 && nAbsPos && !bReadonly);
393
0
    pNavi->m_xGlobalToolBox->set_item_sensitive(u"movedown"_ustr,
394
0
                    nSelCount == 1 && nAbsPos < m_xTreeView->n_children() - 1 && !bReadonly);
395
396
0
}
397
398
void SwGlobalTree::MoveSelectionTo(const weld::TreeIter* pDropEntry)
399
0
{
400
0
    int nSource = m_xTreeView->get_selected_index();
401
402
0
    int nDest = pDropEntry ? m_xTreeView->get_iter_index_in_parent(*pDropEntry)
403
0
                           : m_pSwGlblDocContents->size();
404
405
0
    if (m_pActiveShell->MoveGlobalDocContent(
406
0
            *m_pSwGlblDocContents, nSource, nSource + 1, nDest ) &&
407
0
            Update( false ))
408
0
        Display();
409
0
}
410
411
IMPL_LINK_NOARG(SwGlobalTree, FocusInHdl, weld::Widget&, void)
412
0
{
413
0
    if (Update(false))
414
0
        Display();
415
0
}
416
417
IMPL_LINK(SwGlobalTree, KeyInputHdl, const KeyEvent&, rKEvt, bool)
418
0
{
419
0
    bool bHandled = false;
420
0
    const vcl::KeyCode aCode = rKEvt.GetKeyCode();
421
0
    if (aCode.GetCode() == KEY_RETURN)
422
0
    {
423
0
        switch (aCode.GetModifier())
424
0
        {
425
0
            case KEY_MOD2:
426
                // Switch boxes
427
0
                GetParentWindow()->ToggleTree();
428
0
                bHandled = true;
429
0
            break;
430
0
        }
431
0
    }
432
0
    return bHandled;
433
0
}
434
435
void SwGlobalTree::Display(bool bOnlyUpdateUserData)
436
0
{
437
0
    size_t nCount = m_pSwGlblDocContents->size();
438
0
    size_t nChildren = m_xTreeView->n_children();
439
0
    if (bOnlyUpdateUserData && nChildren == m_pSwGlblDocContents->size())
440
0
    {
441
0
        std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
442
0
        bool bEntry = m_xTreeView->get_iter_first(*xEntry);
443
0
        for (size_t i = 0; i < nCount && bEntry; i++)
444
0
        {
445
0
            const SwGlblDocContent* pCont = (*m_pSwGlblDocContents)[i].get();
446
0
            OUString sId(weld::toId(pCont));
447
0
            m_xTreeView->set_id(*xEntry, sId);
448
0
            if (pCont->GetType() == GLBLDOC_SECTION && !pCont->GetSection()->IsConnectFlag())
449
0
                m_xTreeView->set_font_color(*xEntry, COL_LIGHTRED);
450
0
            else
451
0
                m_xTreeView->set_font_color(*xEntry, COL_AUTO);
452
0
            bEntry = m_xTreeView->iter_next(*xEntry);
453
0
            assert(bEntry || i == nCount - 1);
454
0
        }
455
0
    }
456
0
    else
457
0
    {
458
0
        int nOldSelEntry = m_xTreeView->get_selected_index();
459
0
        OUString sEntryName;  // Name of the entry
460
0
        int nSelPos = -1;
461
0
        if (nOldSelEntry != -1)
462
0
        {
463
0
            sEntryName = m_xTreeView->get_text(nOldSelEntry);
464
0
            nSelPos = nOldSelEntry;
465
0
        }
466
0
        m_xTreeView->freeze();
467
0
        m_xTreeView->clear();
468
469
0
        int nSelEntry = -1;
470
0
        for (size_t i = 0; i < nCount; ++i)
471
0
        {
472
0
            const SwGlblDocContent* pCont = (*m_pSwGlblDocContents)[i].get();
473
474
0
            OUString sId(weld::toId(pCont));
475
0
            OUString sEntry;
476
0
            OUString aImage;
477
0
            switch (pCont->GetType())
478
0
            {
479
0
                case GLBLDOC_UNKNOWN:
480
0
                    sEntry = m_aContextStrings[IDX_STR_INSERT_TEXT];
481
0
                break;
482
0
                case GLBLDOC_TOXBASE:
483
0
                {
484
0
                    const SwTOXBase* pBase = pCont->GetTOX();
485
0
                    sEntry = pBase->GetTitle();
486
0
                    aImage = RID_BMP_NAVI_INDEX;
487
0
                }
488
0
                break;
489
0
                case GLBLDOC_SECTION:
490
0
                {
491
0
                    const SwSection* pSect = pCont->GetSection();
492
0
                    sEntry = pSect->GetSectionName().toString();
493
0
                    aImage = RID_BMP_DROP_REGION;
494
0
                }
495
0
                break;
496
0
            }
497
498
0
            m_xTreeView->append(sId, sEntry);
499
0
            if (!aImage.isEmpty())
500
0
                m_xTreeView->set_image(i, aImage);
501
502
0
            if (pCont->GetType() == GLBLDOC_SECTION && !pCont->GetSection()->IsConnectFlag())
503
0
                m_xTreeView->set_font_color(i, COL_LIGHTRED);
504
505
0
            if (sEntry == sEntryName)
506
0
                nSelEntry = i;
507
0
        }
508
0
        m_xTreeView->thaw();
509
0
        if (nSelEntry != -1)
510
0
            m_xTreeView->select(nSelEntry);
511
0
        else if (nSelPos != -1 && o3tl::make_unsigned(nSelPos) < nCount)
512
0
            m_xTreeView->select(nSelPos);
513
0
        else if (nCount)
514
0
            m_xTreeView->select(0);
515
0
        Select();
516
0
    }
517
0
}
518
519
void SwGlobalTree::InsertRegion( const SwGlblDocContent* pCont, const OUString* pFileName )
520
0
{
521
0
    Sequence< OUString > aFileNames;
522
0
    if ( !pFileName )
523
0
    {
524
0
        SwNavigationPI* pNavi = GetParentWindow();
525
0
        m_pDocInserter.reset(new ::sfx2::DocumentInserter(pNavi->GetFrameWeld(), u"swriter"_ustr, sfx2::DocumentInserter::Mode::InsertMulti));
526
0
        m_pDocInserter->StartExecuteModal( LINK( this, SwGlobalTree, DialogClosedHdl ) );
527
0
    }
528
0
    else if ( !pFileName->isEmpty() )
529
0
    {
530
0
        aFileNames.realloc(1);
531
0
        INetURLObject aFileName;
532
0
        aFileName.SetSmartURL( *pFileName );
533
        // tdf#127978 - don't URL encode filename for navigator's tooltip
534
0
        aFileNames.getArray()[0]
535
0
            = aFileName.GetMainURL(INetURLObject::DecodeMechanism::WithCharset);
536
0
        InsertRegion( pCont, aFileNames );
537
0
    }
538
0
}
539
540
void SwGlobalTree::EditContent(const SwGlblDocContent* pCont )
541
0
{
542
0
    sal_uInt16 nSlot = 0;
543
0
    switch( pCont->GetType() )
544
0
    {
545
0
        case GLBLDOC_UNKNOWN:
546
0
            m_pActiveShell->GetView().GetEditWin().GrabFocus();
547
0
        break;
548
0
        case GLBLDOC_TOXBASE:
549
0
        {
550
0
            const SwTOXBase* pBase = pCont->GetTOX();
551
0
            if(pBase)
552
0
                nSlot = FN_INSERT_MULTI_TOX;
553
0
        }
554
0
        break;
555
0
        case GLBLDOC_SECTION:
556
0
        {
557
0
            OpenDoc(pCont);
558
559
0
            nSlot = 0;
560
0
            pCont = nullptr;
561
0
        }
562
0
        break;
563
0
    }
564
0
    if(pCont)
565
0
        GotoContent(pCont);
566
0
    if(nSlot)
567
0
    {
568
0
        m_pActiveShell->GetView().GetViewFrame().GetDispatcher()->Execute(nSlot);
569
0
        if(Update( false ))
570
0
            Display();
571
0
    }
572
0
}
573
574
void SwGlobalTree::ExecuteContextMenuAction(std::u16string_view rSelectedPopupEntry)
575
0
{
576
0
    bool bUpdateHard = false;
577
578
0
    int nEntry = m_xTreeView->get_selected_index();
579
0
    SwGlblDocContent* pCont = nEntry != -1 ? weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(nEntry)) : nullptr;
580
    // If a RequestHelp is called during the dialogue,
581
    // then the content gets lost. Because of that a copy
582
    // is created in which only the DocPos is set correctly.
583
0
    std::optional<SwGlblDocContent> oContCopy;
584
0
    if(pCont)
585
0
        oContCopy.emplace(pCont->GetDocPos());
586
0
    SfxDispatcher& rDispatch = *m_pActiveShell->GetView().GetViewFrame().GetDispatcher();
587
0
    sal_uInt16 nSlot = 0;
588
0
    if (rSelectedPopupEntry == u"updatesel")
589
0
    {
590
        // Two passes: first update the areas, then the directories.
591
0
        m_xTreeView->selected_foreach([this](weld::TreeIter& rSelEntry){
592
0
            SwGlblDocContent* pContent = weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(rSelEntry));
593
0
            if (GLBLDOC_SECTION == pContent->GetType() &&
594
0
                pContent->GetSection()->IsConnected())
595
0
            {
596
0
                const_cast<SwSection*>(pContent->GetSection())->UpdateNow();
597
0
            }
598
0
            return false;
599
0
        });
600
0
        m_xTreeView->selected_foreach([this](weld::TreeIter& rSelEntry){
601
0
            SwGlblDocContent* pContent = weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(rSelEntry));
602
0
            if (GLBLDOC_TOXBASE == pContent->GetType())
603
0
                m_pActiveShell->UpdateTableOf(*pContent->GetTOX());
604
0
            return false;
605
0
        });
606
607
0
        bUpdateHard = true;
608
0
    }
609
0
    else if (rSelectedPopupEntry == u"updateindex")
610
0
    {
611
0
        nSlot = FN_UPDATE_TOX;
612
0
        bUpdateHard = true;
613
0
    }
614
0
    else if (rSelectedPopupEntry == u"updatelinks" || rSelectedPopupEntry == u"updateall")
615
0
    {
616
0
        m_pActiveShell->GetLinkManager().UpdateAllLinks(true, false, nullptr, u""_ustr);
617
0
        if (rSelectedPopupEntry == u"updateall")
618
0
            nSlot = FN_UPDATE_TOX;
619
0
        pCont = nullptr;
620
0
        bUpdateHard = true;
621
0
    }
622
0
    else if (rSelectedPopupEntry == u"editcontent")
623
0
    {
624
0
        OSL_ENSURE(pCont, "edit without entry ? " );
625
0
        if (pCont)
626
0
        {
627
0
            EditContent(pCont);
628
0
        }
629
0
    }
630
0
    else if (rSelectedPopupEntry == u"editlink")
631
0
    {
632
0
        OSL_ENSURE(pCont, "edit without entry ? " );
633
0
        if (pCont)
634
0
        {
635
0
            SfxStringItem aName(FN_EDIT_REGION,
636
0
                    pCont->GetSection()->GetSectionName().toString());
637
0
            rDispatch.ExecuteList(FN_EDIT_REGION, SfxCallMode::ASYNCHRON,
638
0
                    { &aName });
639
0
        }
640
0
    }
641
0
    else if (rSelectedPopupEntry == u"deleteentry")
642
0
    {
643
        // If several entries selected, then after each delete the array
644
        // must be refilled. So you do not have to remember anything,
645
        // deleting begins at the end.
646
0
        std::vector<int> aRows = m_xTreeView->get_selected_rows();
647
0
        std::sort(aRows.begin(), aRows.end());
648
649
0
        std::unique_ptr<SwGlblDocContents> pTempContents;
650
0
        m_pActiveShell->StartAction();
651
0
        for (auto iter = aRows.rbegin(); iter != aRows.rend(); ++iter)
652
0
        {
653
0
            m_pActiveShell->DeleteGlobalDocContent(
654
0
                pTempContents ? *pTempContents : *m_pSwGlblDocContents,
655
0
                                 *iter);
656
0
            pTempContents.reset(new SwGlblDocContents);
657
0
            m_pActiveShell->GetGlobalDocContent(*pTempContents);
658
0
        }
659
0
        pTempContents.reset();
660
0
        m_pActiveShell->EndAction();
661
0
        pCont = nullptr;
662
0
    }
663
0
    else if (rSelectedPopupEntry == u"insertindex")
664
0
    {
665
0
        if(oContCopy)
666
0
        {
667
0
            SfxItemSetFixed<
668
0
                    RES_FRM_SIZE, RES_FRM_SIZE,
669
0
                    RES_LR_SPACE, RES_LR_SPACE,
670
0
                    RES_BACKGROUND, RES_BACKGROUND,
671
0
                    RES_COL, RES_COL,
672
0
                    SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE,
673
0
                    FN_PARAM_TOX_TYPE, FN_PARAM_TOX_TYPE>
674
0
                aSet( m_pActiveShell->GetView().GetPool() );
675
676
0
            SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
677
0
            ScopedVclPtr<AbstractMultiTOXTabDialog> pDlg(pFact->CreateMultiTOXTabDialog(
678
0
                                                    m_xTreeView.get(), aSet,
679
0
                                                    *m_pActiveShell,
680
0
                                                    nullptr,
681
0
                                                    true));
682
0
            if(RET_OK == pDlg->Execute())
683
0
            {
684
0
                SwTOXDescription&  rDesc = pDlg->GetTOXDescription(
685
0
                                            pDlg->GetCurrentTOXType());
686
0
                SwTOXMgr aMgr(m_pActiveShell);
687
0
                SwTOXBase* pToInsert = nullptr;
688
0
                if(aMgr.UpdateOrInsertTOX(rDesc, &pToInsert, pDlg->GetOutputItemSet()))
689
0
                    m_pActiveShell->InsertGlobalDocContent( *oContCopy, *pToInsert );
690
0
            }
691
0
            pCont = nullptr;
692
0
        }
693
0
    }
694
0
    else if (rSelectedPopupEntry == u"insertfile")
695
0
    {
696
0
        m_oDocContent = std::move(oContCopy);
697
0
        InsertRegion( &*m_oDocContent );
698
0
        pCont = nullptr;
699
0
    }
700
0
    else if (rSelectedPopupEntry == u"insertnewfile")
701
0
    {
702
0
        SfxViewFrame& rGlobFrame = m_pActiveShell->GetView().GetViewFrame();
703
0
        SwGlobalFrameListener_Impl aFrameListener(rGlobFrame);
704
705
        // Creating a new doc
706
0
        SfxStringItem aFactory(SID_NEWDOCDIRECT,
707
0
                        SwDocShell::Factory().GetFilterContainer()->GetName());
708
709
0
        SfxPoolItemHolder aResult(
710
0
            rDispatch.ExecuteList(SID_NEWDOCDIRECT,
711
0
            SfxCallMode::SYNCHRON, { &aFactory }));
712
0
        const SfxFrameItem* pItem(static_cast<const SfxFrameItem*>(aResult.getItem()));
713
714
        // save at
715
0
        SfxFrame* pFrame = pItem ? pItem->GetFrame() : nullptr;
716
0
        SfxViewFrame* pViewFrame = pFrame ? pFrame->GetCurrentViewFrame() : nullptr;
717
0
        if (pViewFrame)
718
0
        {
719
0
            aResult = pViewFrame->GetDispatcher()->Execute(
720
0
                    SID_SAVEASDOC, SfxCallMode::SYNCHRON );
721
0
            const SfxBoolItem* pBool(static_cast<const SfxBoolItem*>(aResult.getItem()));
722
0
            SfxObjectShell& rObj = *pViewFrame->GetObjectShell();
723
0
            const SfxMedium* pMedium = rObj.GetMedium();
724
0
            OUString sNewFile(pMedium->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri));
725
            // Insert the area with the Doc-Name
726
            // Bring the own Doc in the foreground
727
0
            if(aFrameListener.IsValid() && !sNewFile.isEmpty())
728
0
            {
729
0
                rGlobFrame.ToTop();
730
                // Due to the update the entries are invalid
731
0
                if (nEntry != -1)
732
0
                {
733
0
                    Update( false );
734
0
                    Display();
735
0
                    m_xTreeView->select(nEntry);
736
0
                    Select();
737
0
                    nEntry = m_xTreeView->get_selected_index();
738
0
                    pCont = nEntry != -1 ? weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(nEntry)) : nullptr;
739
0
                }
740
0
                else
741
0
                {
742
0
                    nEntry = -1;
743
0
                    pCont = nullptr;
744
0
                }
745
0
                if(pBool->GetValue())
746
0
                {
747
0
                    InsertRegion(pCont, &sNewFile);
748
0
                    pViewFrame->ToTop();
749
0
                }
750
0
                else
751
0
                    pViewFrame->GetDispatcher()->Execute(SID_CLOSEWIN, SfxCallMode::SYNCHRON);
752
0
            }
753
0
            else
754
0
            {
755
0
                pViewFrame->ToTop();
756
0
                return;
757
0
            }
758
0
        }
759
0
    }
760
0
    else if (rSelectedPopupEntry == u"inserttext")
761
0
    {
762
0
        if (pCont)
763
0
            m_pActiveShell->InsertGlobalDocContent(*pCont);
764
0
        else
765
0
        {
766
0
            m_pActiveShell->SplitNode(); // Empty document
767
0
            m_pActiveShell->Up( false );
768
0
        }
769
0
        m_pActiveShell->GetView().GetEditWin().GrabFocus();
770
0
    }
771
0
    else if (rSelectedPopupEntry == u"update")
772
0
        pCont = nullptr;
773
774
0
    if (pCont)
775
0
        GotoContent(pCont);
776
0
    if (nSlot)
777
0
        rDispatch.Execute(nSlot);
778
0
    if (Update(bUpdateHard))
779
0
        Display();
780
0
}
781
782
IMPL_LINK_NOARG(SwGlobalTree, Timeout, Timer *, void)
783
0
{
784
0
    SwView* pView = GetParentWindow()->GetCreateView();
785
0
    if (pView && pView->GetEditWin().HasFocus())
786
0
    {
787
0
        if (Update(false))
788
0
            Display();
789
0
        UpdateTracking();
790
0
    }
791
0
}
792
793
// track GlobalDocContentType at the cursor position in the document
794
void SwGlobalTree::UpdateTracking()
795
0
{
796
0
    if (!m_pActiveShell)
797
0
        return;
798
799
0
    m_xTreeView->unselect_all();
800
801
0
    const SwSection* pActiveShellCurrSection = m_pActiveShell->GetCurrSection();
802
0
    if (pActiveShellCurrSection)
803
0
    {
804
0
        const SwSection* pSection = pActiveShellCurrSection;
805
0
        while (SwSection* pParent = pSection->GetParent())
806
0
            pSection = pParent;
807
0
        for (const std::unique_ptr<SwGlblDocContent>& rGlblDocContent : *m_pSwGlblDocContents)
808
0
        {
809
0
            if (rGlblDocContent->GetType() == GlobalDocContentType::GLBLDOC_UNKNOWN)
810
0
                continue;
811
0
            if ((pSection->GetType() == SectionType::ToxContent
812
0
                 && rGlblDocContent->GetTOX() == pSection->GetTOXBase())
813
0
                    || (pSection->GetType() != SectionType::ToxContent
814
0
                        && rGlblDocContent->GetSection() == pSection))
815
0
            {
816
0
                const OUString aId(weld::toId(rGlblDocContent.get()));
817
0
                m_xTreeView->select(m_xTreeView->find_id(aId));
818
0
                break;
819
0
            }
820
0
        }
821
0
    }
822
0
    else
823
0
    {
824
0
        const SwCursor* pCursor = m_pActiveShell->GetCursor();
825
0
        const SwNode& rNode = pCursor->GetPoint()->GetNode();
826
0
        if (rNode.IsTextNode())
827
0
        {
828
            // only the first text node in each series of text nodes is stored in the
829
            // SwGlblDocContents array
830
0
            SwNodeIndex aIdx(rNode);
831
0
            do
832
0
            {
833
0
                --aIdx;
834
0
            } while (aIdx.GetNode().IsTextNode());
835
0
            ++aIdx;
836
0
            SwNodeOffset aTextNodeIndex(aIdx.GetNode().GetIndex());
837
0
            for (const std::unique_ptr<SwGlblDocContent>& rGlblDocContent : *m_pSwGlblDocContents)
838
0
            {
839
0
                if (rGlblDocContent->GetType() == GlobalDocContentType::GLBLDOC_UNKNOWN
840
0
                        && rGlblDocContent->GetDocPos() == aTextNodeIndex)
841
0
                {
842
0
                    const OUString aId(weld::toId(rGlblDocContent.get()));
843
0
                    m_xTreeView->select(m_xTreeView->find_id(aId));
844
0
                }
845
0
            }
846
0
        }
847
0
    }
848
849
0
    Select();
850
0
}
851
852
void SwGlobalTree::GotoContent(const SwGlblDocContent* pCont)
853
0
{
854
0
    m_pActiveShell->EnterStdMode();
855
856
0
    switch( pCont->GetType()  )
857
0
    {
858
0
        case GLBLDOC_UNKNOWN:
859
0
            m_pActiveShell->GotoGlobalDocContent(*pCont);
860
0
        break;
861
0
        case GLBLDOC_TOXBASE:
862
0
        {
863
0
            const UIName sName = pCont->GetTOX()->GetTOXName();
864
0
            if (!m_pActiveShell->GotoNextTOXBase(&sName))
865
0
                m_pActiveShell->GotoPrevTOXBase(&sName);
866
0
        }
867
0
        break;
868
0
        case GLBLDOC_SECTION:
869
0
        break;
870
0
    }
871
872
0
}
873
874
void SwGlobalTree::ShowTree()
875
0
{
876
0
    m_aUpdateTimer.Start();
877
0
    m_xTreeView->show();
878
0
    UpdateTracking();
879
0
}
880
881
void SwGlobalTree::HideTree()
882
0
{
883
0
    m_aUpdateTimer.Stop();
884
0
    m_xTreeView->hide();
885
0
}
886
887
void SwGlobalTree::ExecCommand(std::u16string_view rCmd)
888
0
{
889
0
    int nEntry = m_xTreeView->get_selected_index();
890
0
    if (nEntry == -1)
891
0
        return;
892
0
    if (rCmd == u"edit")
893
0
    {
894
0
        const SwGlblDocContent* pCont = weld::fromId<const SwGlblDocContent*>(
895
0
                                                m_xTreeView->get_id(nEntry));
896
0
        EditContent(pCont);
897
0
    }
898
0
    else
899
0
    {
900
0
        if (m_xTreeView->count_selected_rows() == 1)
901
0
        {
902
0
            bool bMove = false;
903
0
            int nSource = nEntry;
904
0
            int nDest = nSource;
905
0
            if (rCmd == u"movedown")
906
0
            {
907
0
                int nEntryCount = m_xTreeView->n_children();
908
0
                bMove = nEntryCount > nSource + 1;
909
0
                nDest+= 2;
910
0
            }
911
0
            else if (rCmd == u"moveup")
912
0
            {
913
0
                bMove = 0 != nSource;
914
0
                nDest--;
915
0
            }
916
0
            if( bMove && m_pActiveShell->MoveGlobalDocContent(
917
0
                *m_pSwGlblDocContents, nSource, nSource + 1, nDest ) &&
918
0
                    Update( false ))
919
0
                Display();
920
0
        }
921
0
    }
922
0
}
923
924
bool SwGlobalTree::Update(bool bHard)
925
0
{
926
0
    SwView* pActView = GetParentWindow()->GetCreateView();
927
0
    bool bRet = false;
928
0
    if (pActView && pActView->GetWrtShellPtr())
929
0
    {
930
0
        const SwWrtShell* pOldShell = m_pActiveShell;
931
0
        m_pActiveShell = pActView->GetWrtShellPtr();
932
0
        if(m_pActiveShell != pOldShell)
933
0
        {
934
0
            m_pSwGlblDocContents.reset();
935
0
            if (!IsListening(*m_pActiveShell->GetView().GetDocShell()))
936
0
                StartListening(*m_pActiveShell->GetView().GetDocShell());
937
0
        }
938
0
        if(!m_pSwGlblDocContents)
939
0
        {
940
0
            m_pSwGlblDocContents.reset(new SwGlblDocContents);
941
0
            bRet = true;
942
0
            m_pActiveShell->GetGlobalDocContent(*m_pSwGlblDocContents);
943
0
        }
944
0
        else
945
0
        {
946
0
            bool bCopy = false;
947
0
            SwGlblDocContents aTempContents;
948
0
            m_pActiveShell->GetGlobalDocContent(aTempContents);
949
0
            size_t nChildren = m_xTreeView->n_children();
950
0
            if (aTempContents.size() != m_pSwGlblDocContents->size() ||
951
0
                    aTempContents.size() != nChildren)
952
0
            {
953
0
                bRet = true;
954
0
                bCopy = true;
955
0
            }
956
0
            else
957
0
            {
958
0
                for(size_t i = 0; i < aTempContents.size() && !bCopy; i++)
959
0
                {
960
0
                    SwGlblDocContent* pLeft = aTempContents[i].get();
961
0
                    SwGlblDocContent* pRight = (*m_pSwGlblDocContents)[i].get();
962
0
                    GlobalDocContentType eType = pLeft->GetType();
963
0
                    OUString sTemp = m_xTreeView->get_text(i);
964
0
                    if (
965
0
                         eType != pRight->GetType() ||
966
0
                         (
967
0
                           eType == GLBLDOC_SECTION &&
968
0
                           pLeft->GetSection()->GetSectionName() != sTemp
969
0
                         ) ||
970
0
                         (
971
0
                           eType == GLBLDOC_TOXBASE &&
972
0
                           pLeft->GetTOX()->GetTitle() != sTemp
973
0
                         )
974
0
                       )
975
0
                    {
976
0
                        bCopy = true;
977
0
                    }
978
0
                }
979
0
            }
980
0
            if (bCopy || bHard)
981
0
            {
982
0
                *m_pSwGlblDocContents = std::move( aTempContents );
983
0
                bRet = true;
984
0
            }
985
0
        }
986
0
    }
987
0
    else
988
0
    {
989
0
        m_xTreeView->clear();
990
0
        if(m_pSwGlblDocContents)
991
0
            m_pSwGlblDocContents->clear();
992
0
    }
993
    // FIXME: Implement a test for changes!
994
0
    return bRet;
995
0
}
996
997
void SwGlobalTree::OpenDoc(const SwGlblDocContent* pCont)
998
0
{
999
0
    const OUString sFileName(pCont->GetSection()->GetLinkFileName().getToken(0,
1000
0
            sfx2::cTokenSeparator));
1001
0
    bool bFound = false;
1002
0
    const SfxObjectShell* pCurr = SfxObjectShell::GetFirst();
1003
0
    while( !bFound && pCurr )
1004
0
    {
1005
0
        if(pCurr->GetMedium() &&
1006
0
           pCurr->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri) == sFileName)
1007
0
        {
1008
0
            bFound = true;
1009
0
            SwGlobalTree::SetShowShell(pCurr);
1010
0
            Application::PostUserEvent(LINK(this, SwGlobalTree, ShowFrameHdl));
1011
0
            pCurr = nullptr;
1012
0
        }
1013
0
        else
1014
0
            pCurr = SfxObjectShell::GetNext(*pCurr);
1015
0
    }
1016
0
    if(!bFound)
1017
0
    {
1018
0
        SfxStringItem aURL(SID_FILE_NAME, sFileName);
1019
0
        SfxBoolItem aReadOnly(SID_DOC_READONLY, false);
1020
0
        SfxStringItem aTargetFrameName( SID_TARGETNAME, u"_blank"_ustr );
1021
0
        SfxStringItem aReferer(SID_REFERER, m_pActiveShell->GetView().GetDocShell()->GetTitle());
1022
0
        m_pActiveShell->GetView().GetViewFrame().GetDispatcher()->
1023
0
                ExecuteList(SID_OPENDOC, SfxCallMode::ASYNCHRON,
1024
0
                        { &aURL, &aReadOnly, &aReferer, &aTargetFrameName });
1025
0
    }
1026
0
}
1027
1028
IMPL_LINK_NOARG( SwGlobalTree, DoubleClickHdl, weld::TreeView&, bool)
1029
0
{
1030
0
    int nEntry = m_xTreeView->get_cursor_index();
1031
0
    SwGlblDocContent* pCont = weld::fromId<SwGlblDocContent*>(m_xTreeView->get_id(nEntry));
1032
0
    if (pCont->GetType() == GLBLDOC_SECTION)
1033
0
        OpenDoc(pCont);
1034
0
    else
1035
0
    {
1036
0
        GotoContent(pCont);
1037
0
        m_pActiveShell->GetView().GetEditWin().GrabFocus();
1038
0
    }
1039
0
    return false;
1040
0
}
1041
1042
SwNavigationPI* SwGlobalTree::GetParentWindow()
1043
0
{
1044
0
    return m_pDialog;
1045
0
}
1046
1047
IMPL_STATIC_LINK_NOARG(SwGlobalTree, ShowFrameHdl, void*, void)
1048
0
{
1049
0
    SfxViewFrame* pFirst = s_pShowShell ? SfxViewFrame::GetFirst(s_pShowShell) : nullptr;
1050
0
    if (pFirst)
1051
0
        pFirst->ToTop();
1052
0
    SwGlobalTree::SetShowShell(nullptr);
1053
0
}
1054
1055
void SwGlobalTree::InsertRegion( const SwGlblDocContent* _pContent, const Sequence< OUString >& _rFiles )
1056
0
{
1057
0
    sal_Int32 nFiles = _rFiles.getLength();
1058
0
    if (!nFiles)
1059
0
        return;
1060
1061
0
    size_t nEntryCount = m_xTreeView->n_children();
1062
1063
0
    bool bMove = _pContent == nullptr;
1064
0
    const OUString* pFileNames = _rFiles.getConstArray();
1065
0
    SwWrtShell& rSh = GetParentWindow()->GetCreateView()->GetWrtShell();
1066
0
    rSh.StartAction();
1067
    // after insertion of the first new content the 'pCont' parameter becomes invalid
1068
    // find the index of the 'anchor' content to always use a current anchor content
1069
0
    size_t nAnchorContent = m_pSwGlblDocContents->size() - 1;
1070
0
    if (!bMove)
1071
0
    {
1072
0
        for (size_t nContent = 0; nContent < m_pSwGlblDocContents->size();
1073
0
                ++nContent)
1074
0
        {
1075
0
            if( *_pContent == *(*m_pSwGlblDocContents)[ nContent ] )
1076
0
            {
1077
0
                nAnchorContent = nContent;
1078
0
                break;
1079
0
            }
1080
0
        }
1081
0
    }
1082
0
    SwGlblDocContents aTempContents;
1083
0
    for ( sal_Int32 nFile = 0; nFile < nFiles; ++nFile )
1084
0
    {
1085
        //update the global document content after each inserted document
1086
0
        rSh.GetGlobalDocContent(aTempContents);
1087
0
        SwGlblDocContent* pAnchorContent = nullptr;
1088
0
        OSL_ENSURE(aTempContents.size() > (nAnchorContent + nFile), "invalid anchor content -> last insertion failed");
1089
0
        if ( aTempContents.size() > (nAnchorContent + nFile) )
1090
0
            pAnchorContent = aTempContents[nAnchorContent + nFile].get();
1091
0
        else
1092
0
            pAnchorContent = aTempContents.back().get();
1093
0
        OUString sFileName(pFileNames[nFile]);
1094
0
        INetURLObject aFileUrl;
1095
0
        aFileUrl.SetSmartURL( sFileName );
1096
0
        OUString sSectionName(aFileUrl.GetLastName(
1097
0
            INetURLObject::DecodeMechanism::Unambiguous).getToken(0, sfx2::cTokenSeparator));
1098
0
        sal_uInt16 nSectCount = rSh.GetSectionFormatCount();
1099
0
        OUString sTempSectionName(sSectionName);
1100
0
        sal_uInt16 nAddNumber = 0;
1101
0
        sal_uInt16 nCount = 0;
1102
        // if applicable: add index if the range name is already in use.
1103
0
        while ( nCount < nSectCount )
1104
0
        {
1105
0
            const SwSectionFormat& rFormat = rSh.GetSectionFormat(nCount);
1106
0
            if ((rFormat.GetSection()->GetSectionName() == sTempSectionName)
1107
0
                && rFormat.IsInNodesArr())
1108
0
            {
1109
0
                nCount = 0;
1110
0
                nAddNumber++;
1111
0
                sTempSectionName = sSectionName + ":" + OUString::number( nAddNumber );
1112
0
            }
1113
0
            else
1114
0
                nCount++;
1115
0
        }
1116
1117
0
        if ( nAddNumber )
1118
0
            sSectionName = sTempSectionName;
1119
1120
0
        SwSectionData aSectionData(SectionType::Content, UIName(sSectionName));
1121
0
        aSectionData.SetProtectFlag(true);
1122
0
        aSectionData.SetHidden(false);
1123
1124
0
        aSectionData.SetLinkFileName(sFileName);
1125
0
        aSectionData.SetType(SectionType::FileLink);
1126
0
        aSectionData.SetLinkFilePassword( OUString() );
1127
1128
0
        rSh.InsertGlobalDocContent( *pAnchorContent, aSectionData );
1129
0
    }
1130
0
    if (bMove)
1131
0
    {
1132
0
        Update( false );
1133
0
        rSh.MoveGlobalDocContent(
1134
0
            *m_pSwGlblDocContents, nEntryCount, nEntryCount + nFiles, nEntryCount - nFiles );
1135
0
    }
1136
0
    rSh.EndAction();
1137
0
    Update( false );
1138
0
    Display();
1139
1140
0
}
1141
1142
IMPL_LINK( SwGlobalTree, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
1143
0
{
1144
0
    if ( ERRCODE_NONE != _pFileDlg->GetError() )
1145
0
        return;
1146
1147
0
    SfxMediumList aMedList(m_pDocInserter->CreateMediumList());
1148
0
    if ( aMedList.empty() )
1149
0
        return;
1150
1151
0
    Sequence< OUString >aFileNames( aMedList.size() );
1152
0
    OUString* pFileNames = aFileNames.getArray();
1153
0
    sal_Int32 nPos = 0;
1154
0
    for (const std::unique_ptr<SfxMedium>& pMed : aMedList)
1155
0
    {
1156
        // tdf#127978 - don't URL encode filename for navigator's tooltip
1157
0
        pFileNames[nPos++]
1158
0
            = pMed->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::Unambiguous)
1159
0
            + OUStringChar(sfx2::cTokenSeparator)
1160
0
            + pMed->GetFilter()->GetFilterName()
1161
0
            + OUStringChar(sfx2::cTokenSeparator);
1162
0
    }
1163
0
    InsertRegion( &*m_oDocContent, aFileNames );
1164
0
    m_oDocContent.reset();
1165
0
}
1166
1167
void SwGlobalTree::Notify(SfxBroadcaster& rBC, SfxHint const& rHint)
1168
0
{
1169
0
    if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
1170
0
    {
1171
0
        const SfxEventHint* pEventHint = static_cast<const SfxEventHint*>(&rHint);
1172
0
        if (pEventHint->GetEventId() == SfxEventHintId::CloseView)
1173
0
        {
1174
0
            SfxViewEventHint const*const pVEHint(static_cast<SfxViewEventHint const*>(&rHint));
1175
0
            if (m_pActiveShell)
1176
0
            {
1177
0
                SwXTextView* pDyingShell = dynamic_cast<SwXTextView*>(pVEHint->GetController().get());
1178
0
                if (pDyingShell && pDyingShell->GetView() == &m_pActiveShell->GetView())
1179
0
                {
1180
0
                    EndListening(*m_pActiveShell->GetView().GetDocShell());
1181
0
                    m_pActiveShell = nullptr;
1182
0
                }
1183
0
            }
1184
0
            return;
1185
0
        }
1186
0
    }
1187
0
    SfxListener::Notify(rBC, rHint);
1188
0
    if (rHint.GetId() == SfxHintId::SwNavigatorUpdateTracking)
1189
0
        UpdateTracking();
1190
0
}
1191
1192
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */