1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "model/SlideSorterModel.hxx"
22 #include "SlideSorter.hxx"
23 #include "model/SlsPageDescriptor.hxx"
24 #include "model/SlsPageEnumerationProvider.hxx"
25 #include "controller/SlideSorterController.hxx"
26 #include "controller/SlsProperties.hxx"
27 #include "controller/SlsPageSelector.hxx"
28 #include "controller/SlsCurrentSlideManager.hxx"
29 #include "controller/SlsSlotManager.hxx"
30 #include "view/SlideSorterView.hxx"
31 #include "taskpane/SlideSorterCacheDisplay.hxx"
32 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
33 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/beans/UnknownPropertyException.hpp>
37 #include "ViewShellBase.hxx"
38 #include "DrawViewShell.hxx"
39 #include "DrawDocShell.hxx"
40 #include "drawdoc.hxx"
42 #include "FrameView.hxx"
44 #include <tools/diagnose_ex.h>
46 using namespace ::com::sun::star
;
47 using namespace ::com::sun::star::uno
;
49 namespace sd
{ namespace slidesorter
{ namespace model
{
52 bool PrintModel (const SlideSorterModel
& rModel
)
54 for (sal_Int32 nIndex
=0,nCount
=rModel
.GetPageCount(); nIndex
<nCount
; ++nIndex
)
56 SharedPageDescriptor
pDescriptor (rModel
.GetPageDescriptor(nIndex
));
61 nIndex
<< " " << pDescriptor
->GetPageIndex() << " "
62 << pDescriptor
->GetVisualState().mnPageId
<< " "
63 << FromCoreIndex(pDescriptor
->GetPage()->GetPageNum())
64 << " " << pDescriptor
->GetPage());
68 SAL_INFO("sd.sls", nIndex
);
74 bool CheckModel (const SlideSorterModel
& rModel
)
76 for (sal_Int32 nIndex
=0,nCount
=rModel
.GetPageCount(); nIndex
<nCount
; ++nIndex
)
78 SharedPageDescriptor
pDescriptor (rModel
.GetPageDescriptor(nIndex
));
82 OSL_ASSERT(pDescriptor
);
85 if (nIndex
!= pDescriptor
->GetPageIndex())
88 OSL_ASSERT(nIndex
== pDescriptor
->GetPageIndex());
91 if (nIndex
!= pDescriptor
->GetVisualState().mnPageId
)
94 OSL_ASSERT(nIndex
== pDescriptor
->GetVisualState().mnPageId
);
103 SlideSorterModel::SlideSorterModel (SlideSorter
& rSlideSorter
)
105 mrSlideSorter(rSlideSorter
),
107 mePageKind(PK_STANDARD
),
113 SlideSorterModel::~SlideSorterModel()
115 ClearDescriptorList ();
118 void SlideSorterModel::Dispose()
120 ClearDescriptorList ();
123 SdDrawDocument
* SlideSorterModel::GetDocument()
125 if (mrSlideSorter
.GetViewShellBase() != NULL
)
126 return mrSlideSorter
.GetViewShellBase()->GetDocument();
131 bool SlideSorterModel::SetEditMode (EditMode eEditMode
)
133 bool bEditModeChanged
= false;
134 if (meEditMode
!= eEditMode
)
136 meEditMode
= eEditMode
;
138 bEditModeChanged
= true;
140 return bEditModeChanged
;
143 sal_Int32
SlideSorterModel::GetPageCount() const
145 return maPageDescriptors
.size();
148 SharedPageDescriptor
SlideSorterModel::GetPageDescriptor (
149 const sal_Int32 nPageIndex
,
150 const bool bCreate
) const
152 ::osl::MutexGuard
aGuard (maMutex
);
154 SharedPageDescriptor pDescriptor
;
156 if (nPageIndex
>=0 && nPageIndex
<GetPageCount())
158 pDescriptor
= maPageDescriptors
[nPageIndex
];
159 if (pDescriptor
== 0 && bCreate
&& mxSlides
.is())
161 SdPage
* pPage
= GetPage(nPageIndex
);
162 pDescriptor
.reset(new PageDescriptor (
163 Reference
<drawing::XDrawPage
>(mxSlides
->getByIndex(nPageIndex
),UNO_QUERY
),
166 maPageDescriptors
[nPageIndex
] = pDescriptor
;
173 sal_Int32
SlideSorterModel::GetIndex (const Reference
<drawing::XDrawPage
>& rxSlide
) const
175 ::osl::MutexGuard
aGuard (maMutex
);
177 // First try to guess the right index.
178 Reference
<beans::XPropertySet
> xSet (rxSlide
, UNO_QUERY
);
183 const Any
aNumber (xSet
->getPropertyValue("Number"));
184 sal_Int16
nNumber (-1);
187 SharedPageDescriptor
pDescriptor (GetPageDescriptor(nNumber
, false));
188 if (pDescriptor
.get() != NULL
189 && pDescriptor
->GetXDrawPage() == rxSlide
)
194 catch (uno::Exception
&)
196 DBG_UNHANDLED_EXCEPTION();
200 // Guess was wrong, iterate over all slides and search for the right
202 const sal_Int32
nCount (maPageDescriptors
.size());
203 for (sal_Int32 nIndex
=0; nIndex
<nCount
; ++nIndex
)
205 SharedPageDescriptor
pDescriptor (maPageDescriptors
[nIndex
]);
207 // Make sure that the descriptor exists. Without it the given slide
209 if (pDescriptor
.get() == NULL
)
211 // Call GetPageDescriptor() to create the missing descriptor.
212 pDescriptor
= GetPageDescriptor(nIndex
,true);
215 if (pDescriptor
->GetXDrawPage() == rxSlide
)
222 sal_Int32
SlideSorterModel::GetIndex (const SdrPage
* pPage
) const
227 ::osl::MutexGuard
aGuard (maMutex
);
229 // First try to guess the right index.
230 sal_Int16
nNumber ((pPage
->GetPageNum()-1)/2);
231 SharedPageDescriptor
pDescriptor (GetPageDescriptor(nNumber
, false));
232 if (pDescriptor
.get() != NULL
233 && pDescriptor
->GetPage() == pPage
)
238 // Guess was wrong, iterate over all slides and search for the right
240 const sal_Int32
nCount (maPageDescriptors
.size());
241 for (sal_Int32 nIndex
=0; nIndex
<nCount
; ++nIndex
)
243 pDescriptor
= maPageDescriptors
[nIndex
];
245 // Make sure that the descriptor exists. Without it the given slide
247 if (pDescriptor
.get() == NULL
)
249 // Call GetPageDescriptor() to create the missing descriptor.
250 pDescriptor
= GetPageDescriptor(nIndex
, true);
253 if (pDescriptor
->GetPage() == pPage
)
260 sal_uInt16
SlideSorterModel::GetCoreIndex (const sal_Int32 nIndex
) const
262 SharedPageDescriptor
pDescriptor (GetPageDescriptor(nIndex
));
264 return pDescriptor
->GetPage()->GetPageNum();
266 return mxSlides
->getCount()*2+1;
269 /** For now this method uses a trivial algorithm: throw away all descriptors
270 and create them anew (on demand). The main problem that we are facing
271 when designing a better algorithm is that we can not compare pointers to
272 pages stored in the PageDescriptor objects and those obtained from the
273 document: pages may have been deleted and others may have been created
274 at the exact same memory locations.
276 void SlideSorterModel::Resync()
278 ::osl::MutexGuard
aGuard (maMutex
);
280 // Check if document and this model really differ.
281 bool bIsUpToDate (true);
282 SdDrawDocument
* pDocument
= GetDocument();
283 if (pDocument
!=NULL
&& maPageDescriptors
.size()==pDocument
->GetSdPageCount(mePageKind
))
285 for (sal_Int32 nIndex
=0,nCount
=maPageDescriptors
.size(); nIndex
<nCount
; ++nIndex
)
287 if (maPageDescriptors
[nIndex
]
288 && maPageDescriptors
[nIndex
]->GetPage()
291 SAL_INFO("sd.sls", "page " << nIndex
<< " differs");
300 OSL_TRACE("models differ");
305 SynchronizeDocumentSelection(); // Try to make the current selection persistent.
306 ClearDescriptorList ();
308 SynchronizeModelSelection();
309 mrSlideSorter
.GetController().GetPageSelector().CountSelectedPages();
314 void SlideSorterModel::ClearDescriptorList()
316 DescriptorContainer aDescriptors
;
319 ::osl::MutexGuard
aGuard (maMutex
);
320 aDescriptors
.swap(maPageDescriptors
);
323 for (DescriptorContainer::iterator iDescriptor
=aDescriptors
.begin(), iEnd
=aDescriptors
.end();
327 if (iDescriptor
->get() != NULL
)
329 if ( ! iDescriptor
->unique())
333 "trying to delete page descriptor that is still used with"
334 " count " << iDescriptor
->use_count());
335 // No assertion here because that can hang the office when
336 // opening a dialog from here.
338 iDescriptor
->reset();
343 void SlideSorterModel::SynchronizeDocumentSelection()
345 ::osl::MutexGuard
aGuard (maMutex
);
347 PageEnumeration
aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
348 while (aAllPages
.HasMoreElements())
350 SharedPageDescriptor
pDescriptor (aAllPages
.GetNextElement());
351 const bool bIsSelected (pDescriptor
->HasState(PageDescriptor::ST_Selected
));
352 pDescriptor
->GetPage()->SetSelected(bIsSelected
);
356 void SlideSorterModel::SynchronizeModelSelection()
358 ::osl::MutexGuard
aGuard (maMutex
);
360 PageEnumeration
aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
361 while (aAllPages
.HasMoreElements())
363 SharedPageDescriptor
pDescriptor (aAllPages
.GetNextElement());
364 const bool bIsSelected (pDescriptor
->GetPage()->IsSelected());
365 pDescriptor
->SetState(PageDescriptor::ST_Selected
, bIsSelected
);
369 void SlideSorterModel::SetDocumentSlides (
370 const Reference
<container::XIndexAccess
>& rxSlides
)
372 ::osl::MutexGuard
aGuard (maMutex
);
374 // Make the current selection persistent and then release the
375 // current set of pages.
376 SynchronizeDocumentSelection();
378 ClearDescriptorList ();
380 // Reset the current page to cause everbody to release references to it.
381 mrSlideSorter
.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(-1);
383 // Set the new set of pages.
386 SynchronizeModelSelection();
387 mrSlideSorter
.GetController().GetPageSelector().CountSelectedPages();
389 model::PageEnumeration
aSelectedPages (
390 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(*this));
391 if (aSelectedPages
.HasMoreElements())
393 SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
394 mrSlideSorter
.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(
395 pDescriptor
->GetPage());
398 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
399 if (pViewShell
!= NULL
)
401 SdPage
* pPage
= pViewShell
->getCurrentPage();
403 mrSlideSorter
.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(
407 // No current page. This can only be when the slide sorter is
408 // the main view shell. Get current slide form frame view.
409 const FrameView
* pFrameView
= pViewShell
->GetFrameView();
410 if (pFrameView
!= NULL
)
411 mrSlideSorter
.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(
412 pFrameView
->GetSelectedPage());
415 // No frame view. As a last resort use the first slide as
417 mrSlideSorter
.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(
423 mrSlideSorter
.GetController().GetSlotManager()->NotifyEditModeChange();
426 Reference
<container::XIndexAccess
> SlideSorterModel::GetDocumentSlides() const
428 ::osl::MutexGuard
aGuard (maMutex
);
432 void SlideSorterModel::UpdatePageList()
434 ::osl::MutexGuard
aGuard (maMutex
);
436 Reference
<container::XIndexAccess
> xPages
;
438 // Get the list of pages according to the edit mode.
439 Reference
<frame::XController
> xController (mrSlideSorter
.GetXController());
440 if (xController
.is())
446 Reference
<drawing::XMasterPagesSupplier
> xSupplier (
447 xController
->getModel(), UNO_QUERY
);
450 xPages
= Reference
<container::XIndexAccess
>(
451 xSupplier
->getMasterPages(), UNO_QUERY
);
458 Reference
<drawing::XDrawPagesSupplier
> xSupplier (
459 xController
->getModel(), UNO_QUERY
);
462 xPages
= Reference
<container::XIndexAccess
>(
463 xSupplier
->getDrawPages(), UNO_QUERY
);
469 // We should never get here.
475 mrSlideSorter
.GetController().SetDocumentSlides(xPages
);
478 void SlideSorterModel::AdaptSize()
481 maPageDescriptors
.resize(mxSlides
->getCount());
483 maPageDescriptors
.resize(0);
486 bool SlideSorterModel::IsReadOnly() const
488 if (mrSlideSorter
.GetViewShellBase() != NULL
489 && mrSlideSorter
.GetViewShellBase()->GetDocShell())
490 return mrSlideSorter
.GetViewShellBase()->GetDocShell()->IsReadOnly();
495 void SlideSorterModel::SaveCurrentSelection()
497 PageEnumeration
aPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
498 while (aPages
.HasMoreElements())
500 SharedPageDescriptor
pDescriptor (aPages
.GetNextElement());
501 pDescriptor
->SetState(
502 PageDescriptor::ST_WasSelected
,
503 pDescriptor
->HasState(PageDescriptor::ST_Selected
));
507 vcl::Region
SlideSorterModel::RestoreSelection()
509 vcl::Region aRepaintRegion
;
510 PageEnumeration
aPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
511 while (aPages
.HasMoreElements())
513 SharedPageDescriptor
pDescriptor (aPages
.GetNextElement());
514 if (pDescriptor
->SetState(
515 PageDescriptor::ST_Selected
,
516 pDescriptor
->HasState(PageDescriptor::ST_WasSelected
)))
518 aRepaintRegion
.Union(pDescriptor
->GetBoundingBox());
521 return aRepaintRegion
;
524 bool SlideSorterModel::NotifyPageEvent (const SdrPage
* pSdrPage
)
526 ::osl::MutexGuard
aGuard (maMutex
);
528 SdPage
* pPage
= const_cast<SdPage
*>(dynamic_cast<const SdPage
*>(pSdrPage
));
532 // We are only interested in pages that are currently served by this
534 if (pPage
->GetPageKind() != mePageKind
)
536 if (pPage
->IsMasterPage() != (meEditMode
==EM_MASTERPAGE
))
539 if (pPage
->IsInserted())
548 void SlideSorterModel::InsertSlide (SdPage
* pPage
)
550 // Find the index at which to insert the given page.
551 sal_uInt16
nCoreIndex (pPage
->GetPageNum());
552 sal_Int32
nIndex (FromCoreIndex(nCoreIndex
));
553 if (pPage
!= GetPage(nIndex
))
556 // Check that the pages in the document before and after the given page
557 // are present in this model.
559 if (GetPage(nIndex
-1) != GetPageDescriptor(nIndex
-1)->GetPage())
561 if (size_t(nIndex
)<maPageDescriptors
.size()-1)
562 if (GetPage(nIndex
+1) != GetPageDescriptor(nIndex
)->GetPage())
565 // Insert the given page at index nIndex
566 maPageDescriptors
.insert(
567 maPageDescriptors
.begin()+nIndex
,
568 SharedPageDescriptor(
570 Reference
<drawing::XDrawPage
>(mxSlides
->getByIndex(nIndex
),UNO_QUERY
),
574 // Update page indices.
575 UpdateIndices(nIndex
+1);
578 void SlideSorterModel::DeleteSlide (const SdPage
* pPage
)
582 // Caution, GetIndex() may be negative since it uses GetPageNumber()-1
583 // for calculation, so do this only when page is inserted, else the
584 // GetPageNumber() will be zero and thus GetIndex() == -1
585 if(pPage
->IsInserted())
587 nIndex
= GetIndex(pPage
);
591 // if not inserted, search for page
592 for(; nIndex
< static_cast<sal_Int32
>(maPageDescriptors
.size()); nIndex
++)
594 if(maPageDescriptors
[nIndex
]->GetPage() == pPage
)
601 if(nIndex
>= 0 && nIndex
< static_cast<sal_Int32
>(maPageDescriptors
.size()))
603 if (maPageDescriptors
[nIndex
])
604 if (maPageDescriptors
[nIndex
]->GetPage() != pPage
)
607 maPageDescriptors
.erase(maPageDescriptors
.begin()+nIndex
);
608 UpdateIndices(nIndex
);
612 void SlideSorterModel::UpdateIndices (const sal_Int32 nFirstIndex
)
614 for (sal_Int32 nDescriptorIndex
=0,nCount
=maPageDescriptors
.size();
615 nDescriptorIndex
<nCount
;
618 SharedPageDescriptor
& rpDescriptor (maPageDescriptors
[nDescriptorIndex
]);
621 if (nDescriptorIndex
< nFirstIndex
)
623 if (rpDescriptor
->GetPageIndex()!=nDescriptorIndex
)
625 OSL_ASSERT(rpDescriptor
->GetPageIndex()==nDescriptorIndex
);
630 rpDescriptor
->SetPageIndex(nDescriptorIndex
);
636 SdPage
* SlideSorterModel::GetPage (const sal_Int32 nSdIndex
) const
638 SdDrawDocument
* pModel
= const_cast<SlideSorterModel
*>(this)->GetDocument();
641 if (meEditMode
== EM_PAGE
)
642 return pModel
->GetSdPage ((sal_uInt16
)nSdIndex
, mePageKind
);
644 return pModel
->GetMasterSdPage ((sal_uInt16
)nSdIndex
, mePageKind
);
650 } } } // end of namespace ::sd::slidesorter::model
652 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */