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 <memory>
21 #include "MasterPageDescriptor.hxx"
22 #include "MasterPageContainerProviders.hxx"
23 
24 #include "DocumentHelper.hxx"
25 #include <PreviewRenderer.hxx>
26 #include <sdpage.hxx>
27 #include <tools/urlobj.hxx>
28 #include <sal/log.hxx>
29 
30 namespace sd::sidebar {
31 
32 //===== MasterPageDescriptor ==================================================
33 
34 MasterPageDescriptor::MasterPageDescriptor (
35     MasterPageContainer::Origin eOrigin,
36     const sal_Int32 nTemplateIndex,
37     const OUString& rsURL,
38     const OUString& rsPageName,
39     const OUString& rsStyleName,
40     const bool bIsPrecious,
41     const std::shared_ptr<PageObjectProvider>& rpPageObjectProvider,
42     const std::shared_ptr<PreviewProvider>& rpPreviewProvider)
43     : maToken(MasterPageContainer::NIL_TOKEN),
44       meOrigin(eOrigin),
45       msURL(INetURLObject(rsURL).GetMainURL(INetURLObject::DecodeMechanism::Unambiguous)),
46       msPageName(rsPageName),
47       msStyleName(rsStyleName),
48       mbIsPrecious(bIsPrecious),
49       mpMasterPage(nullptr),
50       mpSlide(nullptr),
51       maSmallPreview(),
52       maLargePreview(),
53       mpPreviewProvider(rpPreviewProvider),
54       mpPageObjectProvider(rpPageObjectProvider),
55       mnTemplateIndex(nTemplateIndex),
56       meURLClassification(URLCLASS_UNDETERMINED),
57       mnUseCount(0)
58 {
59 }
60 
61 void MasterPageDescriptor::SetToken (MasterPageContainer::Token aToken)
62 {
63     maToken = aToken;
64 }
65 
66 const Image& MasterPageDescriptor::GetPreview (MasterPageContainer::PreviewSize eSize) const
67 {
68     if (eSize == MasterPageContainer::SMALL)
69         return maSmallPreview;
70     else
71         return maLargePreview;
72 }
73 
74 ::std::unique_ptr<std::vector<MasterPageContainerChangeEvent::EventType> >
75     MasterPageDescriptor::Update (
76         const MasterPageDescriptor& rDescriptor)
77 {
78     bool bDataChanged (false);
79     bool bIndexChanged (false);
80     bool bPreviewChanged (false);
81 
82     if (meOrigin==MasterPageContainer::UNKNOWN
83         && rDescriptor.meOrigin!=MasterPageContainer::UNKNOWN)
84     {
85         meOrigin = rDescriptor.meOrigin;
86         bIndexChanged = true;
87     }
88 
89     if (msURL.isEmpty() && !rDescriptor.msURL.isEmpty())
90     {
91         msURL = rDescriptor.msURL;
92         bDataChanged = true;
93     }
94 
95     if (msPageName.isEmpty() && !rDescriptor.msPageName.isEmpty())
96     {
97         msPageName = rDescriptor.msPageName;
98         bDataChanged = true;
99     }
100 
101     if (msStyleName.isEmpty() && !rDescriptor.msStyleName.isEmpty())
102     {
103         msStyleName = rDescriptor.msStyleName;
104         bDataChanged = true;
105     }
106 
107     if (mpPageObjectProvider == nullptr && rDescriptor.mpPageObjectProvider != nullptr)
108     {
109         mpPageObjectProvider = rDescriptor.mpPageObjectProvider;
110         bDataChanged = true;
111     }
112 
113     if (mpPreviewProvider == nullptr && rDescriptor.mpPreviewProvider != nullptr)
114     {
115         mpPreviewProvider = rDescriptor.mpPreviewProvider;
116         bPreviewChanged = true;
117     }
118 
119     if (mnTemplateIndex<0 && rDescriptor.mnTemplateIndex>=0)
120     {
121          mnTemplateIndex = rDescriptor.mnTemplateIndex;
122          bIndexChanged = true;
123     }
124 
125      // Prepare the list of event types that will be returned.
126     ::std::unique_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pResult;
127     if (bDataChanged || bIndexChanged || bPreviewChanged)
128     {
129          pResult.reset(new std::vector<MasterPageContainerChangeEvent::EventType>);
130          if (bDataChanged)
131              pResult->push_back(MasterPageContainerChangeEvent::EventType::DATA_CHANGED);
132          if (bIndexChanged)
133              pResult->push_back(MasterPageContainerChangeEvent::EventType::INDEX_CHANGED);
134          if (bPreviewChanged)
135              pResult->push_back(MasterPageContainerChangeEvent::EventType::PREVIEW_CHANGED);
136     }
137 
138     return pResult;
139 }
140 
141 int MasterPageDescriptor::UpdatePageObject (
142     sal_Int32 nCostThreshold,
143     SdDrawDocument* pDocument)
144 {
145     int nModified = 0;
146 
147     // Update the page object when that is not yet known.
148     if (mpMasterPage == nullptr && mpPageObjectProvider != nullptr
149         && (nCostThreshold < 0 || mpPageObjectProvider->GetCostIndex() <= nCostThreshold))
150     {
151         // Note that pDocument may be NULL.
152 
153         SdPage* pPage = (*mpPageObjectProvider)(pDocument);
154         if (meOrigin == MasterPageContainer::MASTERPAGE)
155         {
156             mpMasterPage = pPage;
157             if (mpMasterPage != nullptr)
158                 mpMasterPage->SetPrecious(mbIsPrecious);
159         }
160         else
161         {
162             // Master pages from templates are copied into the local document.
163             if (pDocument != nullptr)
164                 mpMasterPage = DocumentHelper::CopyMasterPageToLocalDocument(*pDocument,pPage);
165             mpSlide = DocumentHelper::GetSlideForMasterPage(mpMasterPage);
166         }
167 
168         if (mpMasterPage != nullptr)
169         {
170             // Update page name and style name.
171             if (msPageName.isEmpty())
172                 msPageName = mpMasterPage->GetName();
173             msStyleName = mpMasterPage->GetName();
174 
175             // Delete an existing substitution. The next request for a preview
176             // will create the real one.
177             maSmallPreview = Image();
178             maLargePreview = Image();
179             mpPreviewProvider = std::make_shared<PagePreviewProvider>();
180         }
181         else
182         {
183             SAL_WARN( "sd", "UpdatePageObject: master page is NULL");
184             return -1;
185         }
186 
187         nModified = 1;
188     }
189 
190     return nModified;
191 }
192 
193 bool MasterPageDescriptor::UpdatePreview (
194     sal_Int32 nCostThreshold,
195     const Size& rSmallSize,
196     const Size& rLargeSize,
197     ::sd::PreviewRenderer& rRenderer)
198 {
199     bool bModified (false);
200 
201     // Update the preview when that is not yet known.
202     if (maLargePreview.GetSizePixel().Width() == 0 && mpPreviewProvider != nullptr
203         && (nCostThreshold < 0 || mpPreviewProvider->GetCostIndex() <= nCostThreshold))
204     {
205         SdPage* pPage = mpSlide;
206         if (pPage == nullptr)
207         {
208             pPage = mpMasterPage;
209         }
210         //TODO: Notify LOOL of preview updates.
211         maLargePreview = (*mpPreviewProvider)(
212             rLargeSize.Width(),
213             pPage,
214             rRenderer);
215         if (maLargePreview.GetSizePixel().Width() > 0)
216         {
217             // Create the small preview by scaling the large one down.
218             maSmallPreview = rRenderer.ScaleBitmap(
219                 maLargePreview.GetBitmapEx(),
220                 rSmallSize.Width());
221             // The large preview may not have the desired width.  Scale it
222             // accordingly.
223             if (maLargePreview.GetSizePixel().Width() != rLargeSize.Width())
224                 maLargePreview = rRenderer.ScaleBitmap(
225                     maLargePreview.GetBitmapEx(),
226                     rLargeSize.Width());
227             bModified = true;
228         }
229     }
230 
231     return bModified;
232 }
233 
234 MasterPageDescriptor::URLClassification MasterPageDescriptor::GetURLClassification()
235 {
236     if (meURLClassification == URLCLASS_UNDETERMINED)
237     {
238         if (msURL.isEmpty())
239             meURLClassification = URLCLASS_UNKNOWN;
240         else if (msURL.indexOf("presnt")>=0)
241         {
242             meURLClassification = URLCLASS_PRESENTATION;
243         }
244         else if (msURL.indexOf("layout")>=0)
245         {
246             meURLClassification = URLCLASS_LAYOUT;
247         }
248         else if (msURL.indexOf("educate")>=0)
249         {
250             meURLClassification = URLCLASS_OTHER;
251         }
252         else
253         {
254             meURLClassification = URLCLASS_USER;
255         }
256     }
257 
258     return meURLClassification;
259 }
260 
261 //===== URLComparator =========================================================
262 
263 MasterPageDescriptor::URLComparator::URLComparator (const OUString& sURL)
264     : msURL(sURL)
265 {
266 }
267 
268 bool MasterPageDescriptor::URLComparator::operator() (
269     const SharedMasterPageDescriptor& rDescriptor)
270 {
271     if (!rDescriptor)
272         return false;
273     else
274         return rDescriptor->msURL == msURL;
275 }
276 
277 // ===== StyleNameComparator ==================================================
278 
279 MasterPageDescriptor::StyleNameComparator::StyleNameComparator (const OUString& sStyleName)
280     : msStyleName(sStyleName)
281 {
282 }
283 
284 bool MasterPageDescriptor::StyleNameComparator::operator() (
285     const SharedMasterPageDescriptor& rDescriptor)
286 {
287     if (!rDescriptor)
288         return false;
289     else
290         return rDescriptor->msStyleName == msStyleName;
291 }
292 
293 //===== PageObjectComparator ==================================================
294 
295 MasterPageDescriptor::PageObjectComparator::PageObjectComparator (const SdPage* pPageObject)
296     : mpMasterPage(pPageObject)
297 {
298 }
299 
300 bool MasterPageDescriptor::PageObjectComparator::operator() (
301     const SharedMasterPageDescriptor& rDescriptor)
302 {
303     if (!rDescriptor)
304         return false;
305     else
306         return rDescriptor->mpMasterPage==mpMasterPage;
307 }
308 
309 //===== AllComparator =========================================================
310 
311 MasterPageDescriptor::AllComparator::AllComparator(const SharedMasterPageDescriptor& rDescriptor)
312     : mpDescriptor(rDescriptor)
313 {
314 }
315 
316 bool MasterPageDescriptor::AllComparator::operator() (const SharedMasterPageDescriptor&rDescriptor)
317 {
318     if (!rDescriptor)
319         return false;
320     else
321     {
322         // Take URL, page name, style name, and page object into account
323         // when comparing two descriptors.  When two descriptors are
324         // identical in any of these values then there are thought of as
325         // equivalent.  Only the Origin has to be the same in both
326         // descriptors.
327         return mpDescriptor->meOrigin == rDescriptor->meOrigin
328                && ((!mpDescriptor->msURL.isEmpty() && mpDescriptor->msURL == rDescriptor->msURL)
329                    || (!mpDescriptor->msPageName.isEmpty()
330                        && mpDescriptor->msPageName == rDescriptor->msPageName)
331                    || (!mpDescriptor->msStyleName.isEmpty()
332                        && mpDescriptor->msStyleName == rDescriptor->msStyleName)
333                    || (mpDescriptor->mpMasterPage != nullptr
334                        && mpDescriptor->mpMasterPage == rDescriptor->mpMasterPage)
335                    || (mpDescriptor->mpPageObjectProvider != nullptr
336                        && rDescriptor->mpPageObjectProvider != nullptr
337                        && mpDescriptor->mpPageObjectProvider == rDescriptor->mpPageObjectProvider));
338     }
339 }
340 
341 } // end of namespace sd::sidebar
342 
343 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
344