Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/func/fuprlout.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 <fuprlout.hxx>
21
#include <sfx2/dispatch.hxx>
22
23
#include <sfx2/viewfrm.hxx>
24
#include <sfx2/request.hxx>
25
#include <svl/stritem.hxx>
26
27
#include <sdattr.hrc>
28
#include <drawdoc.hxx>
29
#include <sdpage.hxx>
30
#include <pres.hxx>
31
#include <DrawViewShell.hxx>
32
#include <View.hxx>
33
#include <glob.hxx>
34
#include <app.hrc>
35
#include <DrawDocShell.hxx>
36
#include <SlideSorterViewShell.hxx>
37
#include <Window.hxx>
38
#include <drawview.hxx>
39
#include <sdabstdlg.hxx>
40
#include <memory>
41
#include <unordered_set>
42
43
namespace sd
44
{
45
46
47
0
#define DOCUMENT_TOKEN '#'
48
49
FuPresentationLayout::FuPresentationLayout (
50
    ViewShell& rViewSh,
51
    ::sd::Window* pWin,
52
    ::sd::View* pView,
53
    SdDrawDocument& rDoc,
54
    SfxRequest& rReq)
55
0
    : FuPoor(rViewSh, pWin, pView, rDoc, rReq)
56
0
{
57
0
}
58
59
rtl::Reference<FuPoor> FuPresentationLayout::Create( ViewShell& rViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument& rDoc, SfxRequest& rReq )
60
0
{
61
0
    rtl::Reference<FuPoor> xFunc( new FuPresentationLayout( rViewSh, pWin, pView, rDoc, rReq ) );
62
0
    xFunc->DoExecute(rReq);
63
0
    return xFunc;
64
0
}
65
66
void FuPresentationLayout::DoExecute( SfxRequest& rReq )
67
0
{
68
    // prevent selected objects or objects which are under editing from disappearing
69
0
    mpView->SdrEndTextEdit();
70
71
0
    if(mpView->GetSdrPageView())
72
0
    {
73
0
        mpView->UnmarkAll();
74
0
    }
75
76
0
    bool bError = false;
77
78
    /* if we are on a master page, the changes apply for all pages and notes-
79
       pages who are using the relevant layout */
80
0
    bool bOnMaster = false;
81
0
    if (DrawViewShell *pShell = dynamic_cast<DrawViewShell*>(&mrViewShell))
82
0
    {
83
0
        EditMode eEditMode = pShell->GetEditMode();
84
0
        if (eEditMode == EditMode::MasterPage)
85
0
            bOnMaster = true;
86
0
    }
87
88
0
    std::vector<SdPage*> aUnselect;
89
0
    if (!bOnMaster)
90
0
    {
91
        //We later rely on IsSelected, so transfer the selection here
92
        //into the document
93
0
        slidesorter::SlideSorterViewShell* pSlideSorterViewShell
94
0
            = slidesorter::SlideSorterViewShell::GetSlideSorter(mrViewShell.GetViewShellBase());
95
0
        if (pSlideSorterViewShell)
96
0
        {
97
0
            std::shared_ptr<slidesorter::SlideSorterViewShell::PageSelection> xSelection(
98
0
                pSlideSorterViewShell->GetPageSelection());
99
0
            if (xSelection)
100
0
            {
101
0
                for (SdPage *pPage : *xSelection)
102
0
                {
103
0
                    if (pPage->IsSelected() || pPage->GetPageKind() != PageKind::Standard)
104
0
                        continue;
105
0
                    mrDoc.SetSelected(pPage, true);
106
0
                    aUnselect.push_back(pPage);
107
0
                }
108
0
            }
109
0
        }
110
0
    }
111
112
0
    std::vector<SdPage*> aSelectedPages;
113
0
    std::vector<sal_uInt16> aSelectedPageNums;
114
    // determine the active pages
115
0
    for (sal_uInt16 nPage = 0; nPage < mrDoc.GetSdPageCount(PageKind::Standard); nPage++)
116
0
    {
117
0
        SdPage* pPage = mrDoc.GetSdPage(nPage, PageKind::Standard);
118
0
        if (pPage->IsSelected())
119
0
        {
120
0
            aSelectedPages.push_back(pPage);
121
0
            aSelectedPageNums.push_back(nPage);
122
0
        }
123
0
    }
124
125
0
    bool bMasterPage = bOnMaster;
126
0
    bool bCheckMasters = false;
127
128
    // call dialog
129
0
    bool   bLoad = false;           // appear the new master pages?
130
0
    OUString aFile;
131
132
0
    SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<ATTR_PRESLAYOUT_START, ATTR_PRESLAYOUT_END>(mrDoc.GetPool() ));
133
134
0
    aSet.Put( SfxBoolItem( ATTR_PRESLAYOUT_LOAD, bLoad));
135
0
    aSet.Put( SfxBoolItem( ATTR_PRESLAYOUT_MASTER_PAGE, bMasterPage ) );
136
0
    aSet.Put( SfxBoolItem( ATTR_PRESLAYOUT_CHECK_MASTERS, bCheckMasters ) );
137
138
0
    if (!aSelectedPages.empty())
139
0
    {
140
0
        OUString aOldLayoutName(aSelectedPages.back()->GetLayoutName());
141
0
        sal_Int32 nPos = aOldLayoutName.indexOf(SD_LT_SEPARATOR);
142
0
        if (nPos != -1)
143
0
            aOldLayoutName = aOldLayoutName.copy(0, nPos);
144
0
        aSet.Put(SfxStringItem(ATTR_PRESLAYOUT_NAME, aOldLayoutName));
145
0
    }
146
147
0
    const SfxItemSet *pArgs = rReq.GetArgs ();
148
149
0
    if (pArgs)
150
0
    {
151
0
        if (pArgs->GetItemState(ATTR_PRESLAYOUT_LOAD) == SfxItemState::SET)
152
0
            bLoad = static_cast<const SfxBoolItem&>(pArgs->Get(ATTR_PRESLAYOUT_LOAD)).GetValue();
153
0
        if( pArgs->GetItemState( ATTR_PRESLAYOUT_MASTER_PAGE ) == SfxItemState::SET )
154
0
            bMasterPage = pArgs->Get( ATTR_PRESLAYOUT_MASTER_PAGE ).GetValue();
155
0
        if( pArgs->GetItemState( ATTR_PRESLAYOUT_CHECK_MASTERS ) == SfxItemState::SET )
156
0
            bCheckMasters = static_cast<const SfxBoolItem&>( pArgs->Get( ATTR_PRESLAYOUT_CHECK_MASTERS ) ).GetValue();
157
0
        if (pArgs->GetItemState(ATTR_PRESLAYOUT_NAME) == SfxItemState::SET)
158
0
            aFile = pArgs->Get(ATTR_PRESLAYOUT_NAME).GetValue();
159
0
    }
160
0
    else
161
0
    {
162
0
        SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
163
0
        ScopedVclPtr<AbstractSdPresLayoutDlg> pDlg(pFact->CreateSdPresLayoutDlg(mpWindow ? mpWindow->GetFrameWeld() : nullptr, mpDocSh, aSet));
164
165
0
        sal_uInt16 nResult = pDlg->Execute();
166
167
0
        switch (nResult)
168
0
        {
169
0
            case RET_OK:
170
0
            {
171
0
                pDlg->GetAttr(aSet);
172
0
                if (aSet.GetItemState(ATTR_PRESLAYOUT_LOAD) == SfxItemState::SET)
173
0
                    bLoad = static_cast<const SfxBoolItem&>(aSet.Get(ATTR_PRESLAYOUT_LOAD)).GetValue();
174
0
                if( aSet.GetItemState( ATTR_PRESLAYOUT_MASTER_PAGE ) == SfxItemState::SET )
175
0
                    bMasterPage = aSet.Get( ATTR_PRESLAYOUT_MASTER_PAGE ).GetValue();
176
0
                if( aSet.GetItemState( ATTR_PRESLAYOUT_CHECK_MASTERS ) == SfxItemState::SET )
177
0
                    bCheckMasters = static_cast<const SfxBoolItem&>(aSet.Get( ATTR_PRESLAYOUT_CHECK_MASTERS ) ).GetValue();
178
0
                if (aSet.GetItemState(ATTR_PRESLAYOUT_NAME) == SfxItemState::SET)
179
0
                    aFile = aSet.Get(ATTR_PRESLAYOUT_NAME).GetValue();
180
0
            }
181
0
            break;
182
183
0
            default:
184
0
                bError = true;
185
0
        }
186
0
    }
187
188
0
    if (bError)
189
0
        return;
190
191
    // tdf#111085 - exchanging the master page already updates all slides using the same master,
192
    // so it is enough to update one selected slide per master
193
0
    std::vector<sal_uInt16> aPageNumsToChange;
194
0
    std::unordered_set<OUString> aHandledLayouts;
195
0
    for (size_t i = 0; i < aSelectedPages.size(); ++i)
196
0
    {
197
0
        if (!bMasterPage || aHandledLayouts.insert(aSelectedPages[i]->GetLayoutName()).second)
198
0
            aPageNumsToChange.push_back(aSelectedPageNums[i]);
199
0
    }
200
201
0
    mpDocSh->SetWaitCursor( true );
202
203
    /* Here, we only exchange masterpages, therefore the current page
204
       remains the current page. To prevent calling PageOrderChangedHint
205
       during insertion and extraction of the masterpages, we block. */
206
    /* That isn't quite right. If the masterpageview is active and you are
207
       removing a masterpage, it's possible that you are removing the
208
       current masterpage. So you have to call ResetActualPage ! */
209
0
    if( dynamic_cast< const DrawViewShell *>( &mrViewShell ) !=  nullptr && !bCheckMasters )
210
0
        static_cast<DrawView*>(mpView)->BlockPageOrderChangedHint(true);
211
212
0
    if (bLoad)
213
0
    {
214
0
        sal_Int32 nIdx{ 0 };
215
0
        OUString aFileName = aFile.getToken(0, DOCUMENT_TOKEN, nIdx);
216
0
        SdDrawDocument* pTempDoc = mrDoc.OpenBookmarkDoc( aFileName );
217
218
        // #69581: If I chose the standard-template I got no filename and so I get no
219
        //         SdDrawDocument-Pointer. But the method SetMasterPage is able to handle
220
        //         a NULL-pointer as a Standard-template ( look at SdDrawDocument::SetMasterPage )
221
0
        OUString aLayoutName;
222
0
        if( pTempDoc )
223
0
            aLayoutName = aFile.getToken(0, DOCUMENT_TOKEN, nIdx);
224
0
        for (auto nSelectedPage : aPageNumsToChange)
225
0
            mrDoc.SetMasterPage(nSelectedPage, aLayoutName, pTempDoc, bMasterPage, bCheckMasters);
226
0
        mrDoc.CloseBookmarkDoc();
227
0
    }
228
0
    else
229
0
    {
230
        // use master page with the layout name aFile from current Doc
231
0
        for (auto nSelectedPage : aPageNumsToChange)
232
0
            mrDoc.SetMasterPage(nSelectedPage, aFile, &mrDoc, bMasterPage, bCheckMasters);
233
0
    }
234
235
    // remove blocking
236
0
    if( dynamic_cast< const DrawViewShell *>( &mrViewShell ) !=  nullptr && !bCheckMasters )
237
0
        static_cast<DrawView*>(mpView)->BlockPageOrderChangedHint(false);
238
239
    // if the master page was visible, show it again
240
0
    if (!aSelectedPages.empty())
241
0
    {
242
0
        if (bOnMaster)
243
0
        {
244
0
            if( auto pDrawViewShell = dynamic_cast<DrawViewShell *>( &mrViewShell ))
245
0
            {
246
0
                ::sd::View* pView = pDrawViewShell->GetView();
247
0
                for (auto pSelectedPage : aSelectedPages)
248
0
                {
249
0
                    sal_uInt16 nPgNum = pSelectedPage->TRG_GetMasterPage().GetPageNum();
250
251
0
                    if (static_cast<DrawViewShell*>(&mrViewShell)->GetPageKind() == PageKind::Notes)
252
0
                        nPgNum++;
253
254
0
                    pView->HideSdrPage();
255
0
                    pView->ShowSdrPage(pView->GetModel().GetMasterPage(nPgNum));
256
0
                }
257
0
            }
258
259
            // force update of TabBar
260
0
            mrViewShell.GetViewFrame()->GetDispatcher()->Execute(SID_MASTERPAGE, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
261
0
        }
262
0
        else
263
0
        {
264
0
            for (auto pSelectedPage : aSelectedPages)
265
0
                pSelectedPage->SetAutoLayout(pSelectedPage->GetAutoLayout());
266
0
        }
267
0
    }
268
269
    //Undo transfer to document selection
270
0
    for (auto pPage : aUnselect)
271
0
        mrDoc.SetSelected(pPage, false);
272
273
274
    // fake a mode change to repaint the page tab bar
275
0
    if( auto pDrawViewSh = dynamic_cast<DrawViewShell *>( &mrViewShell ) )
276
0
    {
277
0
        EditMode eMode = pDrawViewSh->GetEditMode();
278
0
        bool bLayer = pDrawViewSh->IsLayerModeActive();
279
0
        pDrawViewSh->ChangeEditMode( eMode, !bLayer );
280
0
        pDrawViewSh->ChangeEditMode( eMode, bLayer );
281
0
    }
282
283
0
    mpDocSh->SetWaitCursor( false );
284
0
}
285
286
} // end of namespace sd
287
288
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */