Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/view/ViewShellImplementation.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 <config_features.h>
21
22
#include <ViewShellImplementation.hxx>
23
24
#include <sdpage.hxx>
25
#include <drawdoc.hxx>
26
#include <sdresid.hxx>
27
#include <unokywds.hxx>
28
#include <strings.hrc>
29
#include <app.hrc>
30
#include <unmodpg.hxx>
31
#include <DrawDocShell.hxx>
32
#include <FactoryIds.hxx>
33
#include <ViewShellBase.hxx>
34
35
#include <sfx2/bindings.hxx>
36
#include <sfx2/dispatch.hxx>
37
#include <sfx2/request.hxx>
38
#include <sfx2/sfxsids.hrc>
39
#include <sfx2/viewfrm.hxx>
40
#include <sfx2/sidebar/Sidebar.hxx>
41
#include <svl/intitem.hxx>
42
#include <svl/stritem.hxx>
43
#include <svx/imapdlg.hxx>
44
#include <basic/sbstar.hxx>
45
#include <basic/sberrors.hxx>
46
#include <xmloff/autolayout.hxx>
47
#include <vcl/svapp.hxx>
48
49
#include <undo/undoobjects.hxx>
50
51
namespace sd {
52
53
ViewShell::Implementation::Implementation (ViewShell& rViewShell)
54
0
    : mbIsMainViewShell(false),
55
0
      mbIsInitialized(false),
56
0
      mbArrangeActive(false),
57
0
      mrViewShell(rViewShell)
58
0
{
59
0
}
60
61
ViewShell::Implementation::~Implementation() COVERITY_NOEXCEPT_FALSE
62
0
{
63
0
    if ( ! mpUpdateLockForMouse.expired())
64
0
    {
65
0
        std::shared_ptr<ToolBarManagerLock> pLock(mpUpdateLockForMouse);
66
0
        if (pLock != nullptr)
67
0
        {
68
            // Force the ToolBarManagerLock to be released even when the
69
            // IsUICaptured() returns <TRUE/>.
70
0
            pLock->Release(true);
71
0
        }
72
0
    }
73
0
}
74
75
void ViewShell::Implementation::ProcessModifyPageSlot (
76
    SfxRequest& rRequest,
77
    SdPage* pCurrentPage,
78
    PageKind ePageKind)
79
0
{
80
0
    SdDrawDocument* pDocument = mrViewShell.GetDoc();
81
0
    SdrLayerAdmin& rLayerAdmin = pDocument->GetLayerAdmin();
82
0
    SdrLayerIDSet aVisibleLayers;
83
0
    bool bHandoutMode = false;
84
0
    SdPage* pHandoutMPage = nullptr;
85
0
    OUString aNewName;
86
87
0
    AutoLayout aNewAutoLayout;
88
89
0
    bool bBVisible;
90
0
    bool bBObjsVisible;
91
0
    const SfxItemSet* pArgs = rRequest.GetArgs();
92
93
0
    if (pCurrentPage != nullptr && pCurrentPage->TRG_HasMasterPage())
94
0
        aVisibleLayers = pCurrentPage->TRG_GetMasterPageVisibleLayers();
95
0
    else
96
0
        aVisibleLayers.SetAll();
97
98
0
    do
99
0
    {
100
0
        if (pCurrentPage == nullptr)
101
0
            break;
102
103
0
        if (!pArgs || pArgs->Count() == 1 || pArgs->Count() == 2 )
104
0
        {
105
            // First make sure that the sidebar is visible
106
0
            mrViewShell.GetDrawView()->SdrEndTextEdit();
107
0
            mrViewShell.GetDrawView()->UnmarkAll();
108
0
            if (SfxViewFrame* pViewFrame = mrViewShell.GetViewFrame())
109
0
            {
110
0
                pViewFrame->ShowChildWindow(SID_SIDEBAR);
111
0
                sfx2::sidebar::Sidebar::TogglePanel(
112
0
                    u"SdLayoutsPanel",
113
0
                    pViewFrame->GetFrame().GetFrameInterface());
114
0
            }
115
0
            break;
116
0
        }
117
0
        else if (pArgs->Count() == 4)
118
0
        {
119
0
            const SfxStringItem* pNewName = rRequest.GetArg(ID_VAL_PAGENAME);
120
0
            const SfxUInt32Item* pNewAutoLayout = rRequest.GetArg(ID_VAL_WHATLAYOUT);
121
0
            const SfxBoolItem* pBVisible = rRequest.GetArg<SfxBoolItem>(ID_VAL_ISPAGEBACK);
122
0
            const SfxBoolItem* pBObjsVisible = rRequest.GetArg<SfxBoolItem>(ID_VAL_ISPAGEOBJ);
123
0
            assert(pNewName && pNewAutoLayout && pBVisible && pBObjsVisible && "must be present");
124
0
            AutoLayout aLayout (static_cast<AutoLayout>(pNewAutoLayout->GetValue ()));
125
0
            if (aLayout >= AUTOLAYOUT_START
126
0
                && aLayout < AUTOLAYOUT_END)
127
0
            {
128
0
                aNewName        = pNewName->GetValue ();
129
0
                aNewAutoLayout = static_cast<AutoLayout>(pNewAutoLayout->GetValue ());
130
0
                bBVisible       = pBVisible->GetValue ();
131
0
                bBObjsVisible   = pBObjsVisible->GetValue ();
132
0
            }
133
0
            else
134
0
            {
135
#if HAVE_FEATURE_SCRIPTING
136
                StarBASIC::FatalError (ERRCODE_BASIC_BAD_PROP_VALUE);
137
#endif
138
0
                rRequest.Ignore ();
139
0
                break;
140
0
            }
141
0
            if (ePageKind == PageKind::Handout)
142
0
            {
143
0
                bHandoutMode = true;
144
0
                pHandoutMPage = pDocument->GetMasterSdPage(0, PageKind::Handout);
145
0
            }
146
0
        }
147
0
        else
148
0
        {
149
#if HAVE_FEATURE_SCRIPTING
150
            StarBASIC::FatalError (ERRCODE_BASIC_WRONG_ARGS);
151
#endif
152
0
            rRequest.Ignore ();
153
0
            break;
154
0
        }
155
156
0
        SdPage* pUndoPage =
157
0
            bHandoutMode ? pHandoutMPage : pCurrentPage;
158
159
0
        SfxUndoManager* pUndoManager = mrViewShell.GetDocSh()->GetUndoManager();
160
0
        DBG_ASSERT(pUndoManager, "No UNDO MANAGER ?!?");
161
162
0
        if( pUndoManager )
163
0
        {
164
0
            OUString aComment( SdResId(STR_UNDO_MODIFY_PAGE) );
165
0
            pUndoManager->EnterListAction(aComment, aComment, 0, mrViewShell.GetViewShellBase().GetViewShellId());
166
0
            pUndoManager->AddUndoAction(
167
0
                std::make_unique<ModifyPageUndoAction>(
168
0
                    *pDocument, pUndoPage, aNewName, aNewAutoLayout, bBVisible, bBObjsVisible));
169
170
            // Clear the selection because the selected object may be removed as
171
            // a result of the assignment of the layout.
172
0
            mrViewShell.GetDrawView()->UnmarkAll();
173
174
0
            if (!bHandoutMode)
175
0
            {
176
0
                if (pCurrentPage->GetName() != aNewName)
177
0
                {
178
0
                    pCurrentPage->SetName(aNewName);
179
180
0
                    if (ePageKind == PageKind::Standard)
181
0
                    {
182
0
                        sal_uInt16 nPage = (pCurrentPage->GetPageNum()-1) / 2;
183
0
                        SdPage* pNotesPage = pDocument->GetSdPage(nPage, PageKind::Notes);
184
0
                        if (pNotesPage != nullptr)
185
0
                            pNotesPage->SetName(aNewName);
186
0
                    }
187
0
                }
188
189
0
                pCurrentPage->SetAutoLayout(aNewAutoLayout, true);
190
191
0
                SdrLayerID aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background);
192
0
                SdrLayerID aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects);
193
0
                aVisibleLayers.Set(aBckgrnd, bBVisible);
194
0
                aVisibleLayers.Set(aBckgrndObj, bBObjsVisible);
195
0
                pCurrentPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers);
196
0
            }
197
0
            else
198
0
            {
199
0
                pHandoutMPage->SetAutoLayout(aNewAutoLayout, true);
200
0
            }
201
202
0
            mrViewShell.GetViewFrame()->GetDispatcher()->Execute(SID_SWITCHPAGE,
203
0
                SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
204
205
0
            bool bSetModified = true;
206
207
0
            if (pArgs->Count() == 1)
208
0
            {
209
0
                bSetModified = static_cast<const SfxBoolItem&>(pArgs->Get(SID_MODIFYPAGE)).GetValue();
210
0
            }
211
212
0
            pUndoManager->AddUndoAction( std::make_unique<UndoAutoLayoutPosAndSize>( *pUndoPage ) );
213
0
            pUndoManager->LeaveListAction();
214
215
0
            pDocument->SetChanged(bSetModified);
216
0
        }
217
0
    }
218
0
    while (false);
219
220
0
    mrViewShell.Cancel();
221
0
    rRequest.Done ();
222
0
}
223
224
void ViewShell::Implementation::AssignLayout ( SfxRequest const & rRequest, PageKind ePageKind )
225
0
{
226
0
    const SfxUInt32Item* pWhatPage = rRequest.GetArg(ID_VAL_WHATPAGE);
227
0
    const SfxUInt32Item* pWhatLayout = rRequest.GetArg(ID_VAL_WHATLAYOUT);
228
229
0
    SdDrawDocument* pDocument = mrViewShell.GetDoc();
230
0
    if( !pDocument )
231
0
        return;
232
233
0
    SdPage* pPage = nullptr;
234
0
    if( pWhatPage )
235
0
    {
236
0
        pPage = pDocument->GetSdPage(static_cast<sal_uInt16>(pWhatPage->GetValue()), ePageKind);
237
0
    }
238
239
0
    if( pPage == nullptr )
240
0
        pPage = mrViewShell.getCurrentPage();
241
242
0
    if( !pPage )
243
0
        return;
244
245
0
    AutoLayout eLayout = pPage->GetAutoLayout();
246
247
0
    if( pWhatLayout )
248
0
        eLayout = static_cast< AutoLayout >( pWhatLayout->GetValue() );
249
250
    // Transform the given request into the four argument form that is
251
    // understood by ProcessModifyPageSlot().
252
0
    SdrLayerAdmin& rLayerAdmin (mrViewShell.GetViewShellBase().GetDocument()->GetLayerAdmin());
253
0
    SdrLayerID aBackground (rLayerAdmin.GetLayerID(sUNO_LayerName_background));
254
0
    SdrLayerID aBackgroundObject (rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects));
255
256
0
    SdrLayerIDSet aVisibleLayers;
257
258
0
    if( pPage->GetPageKind() == PageKind::Handout )
259
0
        aVisibleLayers.SetAll();
260
0
    else
261
0
        aVisibleLayers = pPage->TRG_GetMasterPageVisibleLayers();
262
263
0
    SfxRequest aRequest(mrViewShell.GetViewShellBase().GetViewFrame(), SID_MODIFYPAGE);
264
0
    aRequest.AppendItem(SfxStringItem (ID_VAL_PAGENAME, pPage->GetName()));
265
0
    aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATLAYOUT, eLayout));
266
0
    aRequest.AppendItem(SfxBoolItem(ID_VAL_ISPAGEBACK, aVisibleLayers.IsSet(aBackground)));
267
0
    aRequest.AppendItem(SfxBoolItem(ID_VAL_ISPAGEOBJ, aVisibleLayers.IsSet(aBackgroundObject)));
268
269
    // Forward the call with the new arguments.
270
0
    ProcessModifyPageSlot( aRequest, pPage, pPage->GetPageKind());
271
0
}
272
273
SfxInterfaceId ViewShell::Implementation::GetViewId() const
274
0
{
275
0
    switch (mrViewShell.GetShellType())
276
0
    {
277
0
        case ViewShell::ST_IMPRESS:
278
0
        case ViewShell::ST_NOTES:
279
0
        case ViewShell::ST_HANDOUT:
280
0
            return IMPRESS_FACTORY_ID;
281
282
0
        case ViewShell::ST_DRAW:
283
0
            return DRAW_FACTORY_ID;
284
285
0
        case ViewShell::ST_OUTLINE:
286
0
            return OUTLINE_FACTORY_ID;
287
288
0
        case ViewShell::ST_SLIDE_SORTER:
289
0
            return SLIDE_SORTER_FACTORY_ID;
290
291
0
        case ViewShell::ST_PRESENTATION:
292
0
            return PRESENTATION_FACTORY_ID;
293
294
        // Since we have to return a view id for every possible shell type
295
        // and there is not (yet) a proper ViewShellBase sub class for the
296
        // remaining types we chose the Impress factory as a fall back.
297
0
        case ViewShell::ST_NOTESPANEL:
298
0
        case ViewShell::ST_SIDEBAR:
299
0
        case ViewShell::ST_NONE:
300
0
        default:
301
0
            return IMPRESS_FACTORY_ID;
302
0
    }
303
0
}
304
305
SvxIMapDlg* ViewShell::Implementation::GetImageMapDialog()
306
0
{
307
0
    SfxViewFrame* pViewFrm = SfxViewFrame::Current();
308
0
    if (!pViewFrm)
309
0
        return nullptr;
310
311
0
    SfxChildWindow* pChildWindow = pViewFrm->GetChildWindow(
312
0
        SvxIMapDlgChildWindow::GetChildWindowId());
313
0
    if (pChildWindow == nullptr)
314
0
        return nullptr;
315
316
0
    return dynamic_cast<SvxIMapDlg*>(pChildWindow->GetController().get());
317
0
}
318
319
//===== ToolBarManagerLock ====================================================
320
321
class ViewShell::Implementation::ToolBarManagerLock::Deleter { public:
322
0
    void operator() (ToolBarManagerLock* pObject) { delete pObject; }
323
};
324
325
std::shared_ptr<ViewShell::Implementation::ToolBarManagerLock>
326
    ViewShell::Implementation::ToolBarManagerLock::Create (
327
        const std::shared_ptr<ToolBarManager>& rpManager)
328
0
{
329
0
    std::shared_ptr<ToolBarManagerLock> pLock (
330
0
        new ViewShell::Implementation::ToolBarManagerLock(rpManager),
331
0
        ViewShell::Implementation::ToolBarManagerLock::Deleter());
332
0
    pLock->mpSelf = pLock;
333
0
    return pLock;
334
0
}
335
336
ViewShell::Implementation::ToolBarManagerLock::ToolBarManagerLock (
337
    const std::shared_ptr<ToolBarManager>& rpManager)
338
0
    : mpLock(new ToolBarManager::UpdateLock(rpManager)),
339
0
      maTimer("sd ToolBarManagerLock maTimer")
340
0
{
341
    // Start a timer that will unlock the ToolBarManager update lock when
342
    // that is not done explicitly by calling Release().
343
0
    maTimer.SetInvokeHandler(LINK(this,ToolBarManagerLock,TimeoutCallback));
344
0
    maTimer.SetTimeout(100);
345
0
    maTimer.Start();
346
0
}
347
348
IMPL_LINK_NOARG(ViewShell::Implementation::ToolBarManagerLock, TimeoutCallback, Timer *, void)
349
0
{
350
    // If possible then release the lock now.  Otherwise start the timer
351
    // and try again later.
352
0
    if (Application::IsUICaptured())
353
0
    {
354
0
        maTimer.Start();
355
0
    }
356
0
    else
357
0
    {
358
0
        mpSelf.reset();
359
0
    }
360
0
}
361
362
void ViewShell::Implementation::ToolBarManagerLock::Release (bool bForce)
363
0
{
364
    // If possible then release the lock now.  Otherwise try again when the
365
    // timer expires.
366
0
    if (bForce || ! Application::IsUICaptured())
367
0
    {
368
0
        mpSelf.reset();
369
0
    }
370
0
}
371
372
ViewShell::Implementation::ToolBarManagerLock::~ToolBarManagerLock()
373
0
{
374
0
    mpLock.reset();
375
0
}
376
377
} // end of namespace sd
378
379
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */