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