Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/view/ViewClipboard.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 <ViewClipboard.hxx>
21
22
#include <DrawDocShell.hxx>
23
#include <DrawViewShell.hxx>
24
#include <View.hxx>
25
#include <ViewShell.hxx>
26
#include <Window.hxx>
27
28
#include <drawdoc.hxx>
29
#include <sdmod.hxx>
30
#include <sdpage.hxx>
31
#include <sdxfer.hxx>
32
#include <strings.hxx>
33
34
#include <svx/svdpagv.hxx>
35
#include <vcl/svapp.hxx>
36
37
namespace sd {
38
39
ViewClipboard::ViewClipboard (::sd::View& rView)
40
0
    : mrView(rView)
41
0
{
42
0
}
43
44
ViewClipboard::~ViewClipboard()
45
0
{
46
0
}
47
48
void ViewClipboard::HandlePageDrop (const SdTransferable& rTransferable)
49
0
{
50
    // Determine whether to insert the given set of slides or to assign a
51
    // given master page.
52
    // tdf#113405 only assign master pages to normal pages, don't attempt to assign a master
53
    // page to a master page
54
0
    sd::DrawViewShell* pDrawViewShell = dynamic_cast<::sd::DrawViewShell*>(mrView.GetViewShell());
55
0
    SdPage* pMasterPage = (pDrawViewShell && pDrawViewShell->GetEditMode() == EditMode::Page) ? GetFirstMasterPage(rTransferable) : nullptr;
56
0
    if (pMasterPage)
57
0
        AssignMasterPage (rTransferable, pMasterPage);
58
0
    else
59
0
        InsertSlides (rTransferable, DetermineInsertPosition ());
60
0
}
61
62
SdPage* ViewClipboard::GetFirstMasterPage (const SdTransferable& rTransferable)
63
0
{
64
0
    SdPage* pFirstMasterPage = nullptr;
65
66
0
    if (rTransferable.HasPageBookmarks())
67
0
    {
68
0
        do
69
0
        {
70
0
            const std::vector<OUString> &rBookmarks = rTransferable.GetPageBookmarks();
71
72
0
            if (rBookmarks.empty())
73
0
                break;
74
75
0
            DrawDocShell* pDocShell = rTransferable.GetPageDocShell();
76
0
            if (pDocShell == nullptr)
77
0
                break;
78
79
0
            SdDrawDocument* pDocument = pDocShell->GetDoc();
80
0
            if (pDocument == nullptr)
81
0
                break;
82
83
0
            for (const OUString& sName : rBookmarks)
84
0
            {
85
0
                bool bIsMasterPage;
86
87
                // SdPage* GetMasterSdPage(sal_uInt16 nPgNum, PageKind ePgKind);
88
                // sal_uInt16 GetMasterSdPageCount(PageKind ePgKind) const;
89
90
0
                sal_uInt16 nBMPage = pDocument->GetPageByName (
91
0
                    sName, bIsMasterPage);
92
0
                if ( ! bIsMasterPage)
93
0
                {
94
                    // At least one regular slide: return NULL to indicate
95
                    // that not all bookmarks point to master pages.
96
0
                    pFirstMasterPage = nullptr;
97
0
                    break;
98
0
                }
99
0
                else if (pFirstMasterPage == nullptr)
100
0
                {
101
                    // Remember the first master page for later.
102
0
                    if (nBMPage != SDRPAGE_NOTFOUND)
103
0
                        pFirstMasterPage = static_cast<SdPage*>(
104
0
                            pDocument->GetMasterPage(nBMPage));
105
0
                }
106
0
            }
107
0
        }
108
0
        while (false);
109
0
    }
110
111
0
    return pFirstMasterPage;
112
0
}
113
114
void ViewClipboard::AssignMasterPage (
115
    const SdTransferable& rTransferable,
116
    SdPage const * pMasterPage)
117
0
{
118
0
    if (pMasterPage == nullptr)
119
0
        return;
120
121
    // Get the target page to which the master page is assigned.
122
0
    SdrPageView* pPageView = mrView.GetSdrPageView();
123
0
    if (pPageView == nullptr)
124
0
        return;
125
126
0
    SdPage* pPage = static_cast<SdPage*>(pPageView->GetPage());
127
0
    if (pPage == nullptr)
128
0
        return;
129
130
0
    SdDrawDocument& rDocument = mrView.GetDoc();
131
132
0
    if ( ! rTransferable.HasPageBookmarks())
133
0
        return;
134
135
0
    DrawDocShell* pDataDocShell = rTransferable.GetPageDocShell();
136
0
    if (pDataDocShell == nullptr)
137
0
        return;
138
139
0
    SdDrawDocument* pSourceDocument = pDataDocShell->GetDoc();
140
0
    if (pSourceDocument == nullptr)
141
0
        return;
142
143
    // We have to remove the layout suffix from the layout name which is
144
    // appended again by SetMasterPage() to the given name.  Don't ask.
145
0
    OUString sLayoutSuffix = SD_LT_SEPARATOR + STR_LAYOUT_OUTLINE;
146
0
    sal_Int32 nLength = sLayoutSuffix.getLength();
147
0
    OUString sLayoutName = pMasterPage->GetLayoutName();
148
0
    if (sLayoutName.endsWith(sLayoutSuffix))
149
0
        sLayoutName = sLayoutName.copy(0, sLayoutName.getLength() - nLength);
150
151
0
    rDocument.SetMasterPage (
152
0
        pPage->GetPageNum() / 2,
153
0
        sLayoutName,
154
0
        pSourceDocument,
155
0
        false, // Exchange the master page of only the target page.
156
0
        false // Keep unused master pages.
157
0
        );
158
0
}
159
160
sal_uInt16 ViewClipboard::DetermineInsertPosition  ()
161
0
{
162
0
    SdDrawDocument& rDoc = mrView.GetDoc();
163
0
    sal_uInt16 nPgCnt = rDoc.GetSdPageCount( PageKind::Standard );
164
165
    // Insert position is the behind the last selected page or behind the
166
    // last page when the selection is empty.
167
0
    sal_uInt16 nInsertPos = rDoc.GetSdPageCount( PageKind::Standard ) * 2 + 1;
168
0
    for( sal_uInt16 nPage = 0; nPage < nPgCnt; nPage++ )
169
0
    {
170
0
        SdPage* pPage = rDoc.GetSdPage( nPage, PageKind::Standard );
171
172
0
        if( pPage->IsSelected() )
173
0
            nInsertPos = nPage * 2 + 3;
174
0
    }
175
0
    if (rDoc.HasCanvasPage())
176
0
    {
177
0
        if (nInsertPos == 1)
178
0
            nInsertPos = 3;
179
0
    }
180
181
0
    return nInsertPos;
182
0
}
183
184
sal_uInt16 ViewClipboard::InsertSlides (
185
    const SdTransferable& rTransferable,
186
    sal_uInt16 nInsertPosition)
187
0
{
188
0
    SdDrawDocument& rDoc = mrView.GetDoc();
189
190
0
    sal_uInt16 nInsertPgCnt = 0;
191
0
    bool bMergeMasterPages = !rTransferable.HasSourceDoc( &rDoc );
192
193
    // Prepare the insertion.
194
0
    const std::vector<OUString> *pBookmarkList = nullptr;
195
0
    DrawDocShell* pDataDocSh;
196
0
    if (rTransferable.HasPageBookmarks())
197
0
    {
198
        // When the transferable contains page bookmarks then the referenced
199
        // pages are inserted.
200
0
        pBookmarkList = &rTransferable.GetPageBookmarks();
201
0
        pDataDocSh = rTransferable.GetPageDocShell();
202
0
        nInsertPgCnt = static_cast<sal_uInt16>(pBookmarkList->size());
203
0
    }
204
0
    else
205
0
    {
206
        // Otherwise all pages of the document of the transferable are
207
        // inserted.
208
0
        SfxObjectShell* pShell = rTransferable.GetDocShell().get();
209
0
        pDataDocSh = static_cast<DrawDocShell*>(pShell);
210
0
        SdDrawDocument* pDataDoc = pDataDocSh->GetDoc();
211
212
0
        if (pDataDoc!=nullptr && pDataDoc->GetSdPageCount(PageKind::Standard))
213
0
            nInsertPgCnt = pDataDoc->GetSdPageCount(PageKind::Standard);
214
0
    }
215
0
    if (nInsertPgCnt > 0)
216
0
    {
217
0
        const SolarMutexGuard aGuard;
218
0
        ::sd::Window* pWin = mrView.GetViewShell()->GetActiveWindow();
219
0
        const bool bWait = pWin && pWin->IsWait();
220
221
0
        if( bWait )
222
0
            pWin->LeaveWait();
223
224
0
        if (&rTransferable == SdModule::get()->pTransferDrag)
225
0
        {
226
            // This is a drag and drop operation
227
0
            rDoc.DropBookmarkAsPage(
228
0
                pBookmarkList ? *pBookmarkList : std::vector<OUString>(),
229
0
                nInsertPosition,
230
0
                pDataDocSh,
231
0
                bMergeMasterPages);
232
0
        }
233
0
        else
234
0
        {
235
            // This is a regular paste operation
236
0
            rDoc.PasteBookmarkAsPage(
237
0
                pBookmarkList ? *pBookmarkList : std::vector<OUString>(),
238
0
                nInsertPosition,
239
0
                pDataDocSh,
240
0
                bMergeMasterPages);
241
0
        }
242
243
0
        if( bWait )
244
0
            pWin->EnterWait();
245
0
    }
246
247
0
    return nInsertPgCnt;
248
0
}
249
250
} // end of namespace ::sd
251
252
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */