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 <com/sun/star/beans/PropertyValue.hpp>
22 #include <editeng/outlobj.hxx>
24 #include <controller/SlsSlotManager.hxx>
25 #include <SlideSorter.hxx>
26 #include <SlideSorterViewShell.hxx>
27 #include <controller/SlideSorterController.hxx>
28 #include <controller/SlsClipboard.hxx>
29 #include <controller/SlsCurrentSlideManager.hxx>
30 #include <controller/SlsFocusManager.hxx>
31 #include <controller/SlsInsertionIndicatorHandler.hxx>
32 #include <controller/SlsPageSelector.hxx>
33 #include <controller/SlsSelectionFunction.hxx>
34 #include <controller/SlsSelectionManager.hxx>
35 #include <controller/SlsSelectionObserver.hxx>
36 #include <model/SlideSorterModel.hxx>
37 #include <model/SlsPageEnumerationProvider.hxx>
38 #include <model/SlsPageDescriptor.hxx>
39 #include <view/SlideSorterView.hxx>
40 #include <view/SlsLayouter.hxx>
41 #include <framework/FrameworkHelper.hxx>
45 #include <fucushow.hxx>
46 #include <fusldlg.hxx>
47 #include <fuexpand.hxx>
48 #include <fusumry.hxx>
49 #include <fuscale.hxx>
50 #include <slideshow.hxx>
52 #include <strings.hrc>
53 #include <sdresid.hxx>
54 #include <unokywds.hxx>
55 #include <drawdoc.hxx>
56 #include <DrawDocShell.hxx>
57 #include <ViewShellBase.hxx>
58 #include <ViewShellImplementation.hxx>
60 #include <FrameView.hxx>
61 #include <zoomlist.hxx>
65 #include <unmodpg.hxx>
66 #include <DrawViewShell.hxx>
67 #include <sdabstdlg.hxx>
70 #include <sfx2/request.hxx>
71 #include <sfx2/viewfrm.hxx>
72 #include <sfx2/bindings.hxx>
73 #include <sfx2/dispatch.hxx>
74 #include <sfx2/sidebar/Sidebar.hxx>
75 #include <svx/svxids.hrc>
76 #include <sfx2/zoomitem.hxx>
77 #include <svx/svxdlg.hxx>
78 #include <svx/dialogs.hrc>
79 #include <svl/intitem.hxx>
80 #include <svl/whiter.hxx>
81 #include <svl/itempool.hxx>
82 #include <svl/aeitem.hxx>
83 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
84 #include <com/sun/star/drawing/XDrawPages.hpp>
85 #include <vcl/svapp.hxx>
89 using namespace ::com::sun::star
;
90 using namespace ::com::sun::star::uno
;
91 using namespace ::com::sun::star::beans
;
93 namespace sd
{ namespace slidesorter
{ namespace controller
{
97 /** The state of a set of slides with respect to being excluded from the
100 enum SlideExclusionState
{UNDEFINED
, EXCLUDED
, INCLUDED
, MIXED
};
102 /** Return for the given set of slides whether they included are
103 excluded from the slide show.
105 SlideExclusionState
GetSlideExclusionState (model::PageEnumeration
& rPageSet
);
107 } // end of anonymous namespace
109 SlotManager::SlotManager (SlideSorter
& rSlideSorter
)
110 : mrSlideSorter(rSlideSorter
)
114 SlotManager::~SlotManager()
118 void SlotManager::FuTemporary (SfxRequest
& rRequest
)
120 SdDrawDocument
* pDocument
= mrSlideSorter
.GetModel().GetDocument();
122 SlideSorterViewShell
* pShell
123 = dynamic_cast<SlideSorterViewShell
*>(mrSlideSorter
.GetViewShell());
124 if (pShell
== nullptr)
127 switch (rRequest
.GetSlot())
129 case SID_PRESENTATION
:
130 case SID_PRESENTATION_CURRENT_SLIDE
:
131 case SID_REHEARSE_TIMINGS
:
132 slideshowhelp::ShowSlideShow(rRequest
, *mrSlideSorter
.GetModel().GetDocument());
138 ChangeSlideExclusionState(model::SharedPageDescriptor(), true);
142 ChangeSlideExclusionState(model::SharedPageDescriptor(), false);
145 case SID_PAGES_PER_ROW
:
146 if (rRequest
.GetArgs() != nullptr)
148 const SfxUInt16Item
* pPagesPerRow
= rRequest
.GetArg
<SfxUInt16Item
>(SID_PAGES_PER_ROW
);
149 if (pPagesPerRow
!= nullptr)
151 sal_Int32 nColumnCount
= pPagesPerRow
->GetValue();
152 // Force the given number of columns by setting
153 // the minimal and maximal number of columns to
155 mrSlideSorter
.GetView().GetLayouter().SetColumnCount (
156 nColumnCount
, nColumnCount
);
157 // Force a repaint and re-layout.
158 pShell
->ArrangeGUIElements ();
159 // Rearrange the UI-elements controlled by the
160 // controller and force a rearrangement of the
162 mrSlideSorter
.GetController().Rearrange(true);
169 mrSlideSorter
.GetController().GetPageSelector().SelectAllPages();
173 case SID_SLIDE_TRANSITIONS_PANEL
:
175 // First make sure that the sidebar is visible
176 pShell
->GetViewFrame()->ShowChildWindow(SID_SIDEBAR
);
177 ::sfx2::sidebar::Sidebar::ShowPanel(
178 "SdSlideTransitionPanel",
179 pShell
->GetViewFrame()->GetFrame().GetFrameInterface());
184 case SID_PRESENTATION_DLG
:
185 FuSlideShowDlg::Create (
187 mrSlideSorter
.GetContentWindow(),
188 &mrSlideSorter
.GetView(),
193 case SID_CUSTOMSHOW_DLG
:
194 FuCustomShowDlg::Create (
196 mrSlideSorter
.GetContentWindow(),
197 &mrSlideSorter
.GetView(),
202 case SID_EXPAND_PAGE
:
203 FuExpandPage::Create (
205 mrSlideSorter
.GetContentWindow(),
206 &mrSlideSorter
.GetView(),
211 case SID_SUMMARY_PAGE
:
212 FuSummaryPage::Create (
214 mrSlideSorter
.GetContentWindow(),
215 &mrSlideSorter
.GetView(),
221 case SID_INSERT_MASTER_PAGE
:
222 InsertSlide(rRequest
);
226 case SID_DUPLICATE_PAGE
:
227 DuplicateSelectedSlides(rRequest
);
231 case SID_DELETE_PAGE
:
232 case SID_DELETE_MASTER_PAGE
:
233 case SID_DELETE
: // we need SID_CUT to handle the delete key
234 // (DEL -> accelerator -> SID_CUT).
235 if (mrSlideSorter
.GetModel().GetPageCount() > 1)
237 mrSlideSorter
.GetController().GetSelectionManager()->DeleteSelectedPages();
244 case SID_RENAME_MASTER_PAGE
:
245 RenameSlide (rRequest
);
249 case SID_ASSIGN_LAYOUT
:
251 pShell
->mpImpl
->AssignLayout( rRequest
, PageKind::Standard
);
258 SdAbstractDialogFactory
* pFact
= SdAbstractDialogFactory::Create();
259 vcl::Window
* pWin
= mrSlideSorter
.GetContentWindow();
260 ScopedVclPtr
<VclAbstractDialog
> pDlg(pFact
->CreateSdPhotoAlbumDialog(
261 pWin
? pWin
->GetFrameWeld() : nullptr,
270 #ifdef ENABLE_SDREMOTE
271 SdAbstractDialogFactory
* pFact
= SdAbstractDialogFactory::Create();
272 ScopedVclPtr
<VclAbstractDialog
> pDlg( pFact
->CreateRemoteDialog( mrSlideSorter
.GetContentWindow() ) );
283 void SlotManager::FuPermanent (SfxRequest
& rRequest
)
285 ViewShell
* pShell
= mrSlideSorter
.GetViewShell();
286 if (pShell
== nullptr)
289 if(pShell
->GetCurrentFunction().is())
291 rtl::Reference
<FuPoor
> xEmpty
;
292 if (pShell
->GetOldFunction() == pShell
->GetCurrentFunction())
293 pShell
->SetOldFunction(xEmpty
);
295 pShell
->GetCurrentFunction()->Deactivate();
296 pShell
->SetCurrentFunction(xEmpty
);
299 switch(rRequest
.GetSlot())
301 case SID_OBJECT_SELECT
:
302 pShell
->SetCurrentFunction( SelectionFunction::Create(mrSlideSorter
, rRequest
) );
310 if(pShell
->GetOldFunction().is())
312 pShell
->GetOldFunction()->Deactivate();
313 rtl::Reference
<FuPoor
> xEmpty
;
314 pShell
->SetOldFunction(xEmpty
);
317 if(pShell
->GetCurrentFunction().is())
319 pShell
->GetCurrentFunction()->Activate();
320 pShell
->SetOldFunction(pShell
->GetCurrentFunction());
323 //! that's only until ENUM-Slots ?are
324 // Invalidate( SID_OBJECT_SELECT );
327 void SlotManager::FuSupport (SfxRequest
& rRequest
)
329 switch (rRequest
.GetSlot())
331 case SID_STYLE_FAMILY
:
332 if (rRequest
.GetArgs() != nullptr)
334 SdDrawDocument
* pDocument
335 = mrSlideSorter
.GetModel().GetDocument();
336 if (pDocument
!= nullptr)
338 const SfxPoolItem
& rItem (
339 rRequest
.GetArgs()->Get(SID_STYLE_FAMILY
));
340 pDocument
->GetDocSh()->SetStyleFamily(
341 static_cast<SfxStyleFamily
>(static_cast<const SfxUInt16Item
&>(rItem
).GetValue()));
348 SdTransferable
* pTransferClip
= SD_MOD()->pTransferClip
;
351 SfxObjectShell
* pTransferDocShell
= pTransferClip
->GetDocShell().get();
353 DrawDocShell
* pDocShell
= dynamic_cast<DrawDocShell
*>(pTransferDocShell
);
354 if (pDocShell
&& pDocShell
->GetDoc()->GetPageCount() > 1)
356 mrSlideSorter
.GetController().GetClipboard().HandleSlotCall(rRequest
);
360 ViewShellBase
* pBase
= mrSlideSorter
.GetViewShellBase();
361 if (pBase
!= nullptr)
363 std::shared_ptr
<DrawViewShell
> pDrawViewShell (
364 std::dynamic_pointer_cast
<DrawViewShell
>(pBase
->GetMainViewShell()));
365 if (pDrawViewShell
!= nullptr)
366 pDrawViewShell
->FuSupport(rRequest
);
374 mrSlideSorter
.GetController().GetClipboard().HandleSlotCall(rRequest
);
377 case SID_DRAWINGMODE
:
379 case SID_HANDOUT_MASTER_MODE
:
380 case SID_SLIDE_SORTER_MODE
:
381 case SID_OUTLINE_MODE
:
383 ViewShellBase
* pBase
= mrSlideSorter
.GetViewShellBase();
384 if (pBase
!= nullptr)
386 framework::FrameworkHelper::Instance(*pBase
)->HandleModeChangeSlot(
387 rRequest
.GetSlot(), rRequest
);
395 SlideSorterViewShell
* pViewShell
396 = dynamic_cast<SlideSorterViewShell
*>(mrSlideSorter
.GetViewShell());
397 if (pViewShell
!= nullptr)
399 pViewShell
->ImpSidUndo (rRequest
);
406 SlideSorterViewShell
* pViewShell
407 = dynamic_cast<SlideSorterViewShell
*>(mrSlideSorter
.GetViewShell());
408 if (pViewShell
!= nullptr)
410 pViewShell
->ImpSidRedo (rRequest
);
420 void SlotManager::ExecCtrl (SfxRequest
& rRequest
)
422 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
423 sal_uInt16 nSlot
= rRequest
.GetSlot();
428 // empty Undo-Manager
429 mrSlideSorter
.GetModel().GetDocument()->GetDocSh()->ClearUndoBuffer();
431 // normal forwarding to ViewFrame for execution
432 if (pViewShell
!= nullptr)
433 pViewShell
->GetViewFrame()->ExecuteSlot(rRequest
);
435 // has to be finished right away
439 case SID_OUTPUT_QUALITY_COLOR
:
440 case SID_OUTPUT_QUALITY_GRAYSCALE
:
441 case SID_OUTPUT_QUALITY_BLACKWHITE
:
442 case SID_OUTPUT_QUALITY_CONTRAST
:
445 if (pViewShell
!= nullptr)
446 pViewShell
->ExecReq (rRequest
);
450 case SID_MAIL_SCROLLBODY_PAGEDOWN
:
452 if (pViewShell
!= nullptr)
453 pViewShell
->ExecReq (rRequest
);
457 case SID_OPT_LOCALE_CHANGED
:
459 mrSlideSorter
.GetController().UpdateAllPages();
460 if (pViewShell
!= nullptr)
461 pViewShell
->UpdatePreview (pViewShell
->GetActualPage());
467 // We have to handle the SID_SEARCH_DLG slot explicitly because
468 // in some cases (when the slide sorter is displayed in the
469 // center pane) we want to disable the search dialog. Therefore
470 // we have to handle the execution of that slot as well.
471 // We try to do that by forwarding the request to the view frame
472 // of the view shell.
473 if (pViewShell
!= nullptr)
474 pViewShell
->GetViewFrame()->ExecuteSlot(rRequest
);
482 void SlotManager::GetAttrState (SfxItemSet
& rSet
)
484 // Iterate over all items.
485 SfxWhichIter
aIter (rSet
);
486 sal_uInt16 nWhich
= aIter
.FirstWhich();
489 sal_uInt16
nSlotId (nWhich
);
490 if (SfxItemPool::IsWhich(nWhich
) && mrSlideSorter
.GetViewShell()!=nullptr)
491 nSlotId
= mrSlideSorter
.GetViewShell()->GetPool().GetSlotId(nWhich
);
494 case SID_PAGES_PER_ROW
:
498 static_cast<sal_uInt16
>(mrSlideSorter
.GetView().GetLayouter().GetColumnCount())
503 nWhich
= aIter
.NextWhich();
507 void SlotManager::GetMenuState (SfxItemSet
& rSet
)
509 EditMode eEditMode
= mrSlideSorter
.GetModel().GetEditMode();
510 ViewShell
* pShell
= mrSlideSorter
.GetViewShell();
511 DrawDocShell
* pDocShell
= mrSlideSorter
.GetModel().GetDocument()->GetDocSh();
513 if (pShell
!=nullptr && pShell
->GetCurrentFunction().is())
515 sal_uInt16 nSId
= pShell
->GetCurrentFunction()->GetSlotID();
517 rSet
.Put( SfxBoolItem( nSId
, true ) );
519 rSet
.Put( SfxBoolItem( SID_DRAWINGMODE
, false ) );
520 rSet
.Put( SfxBoolItem( SID_SLIDE_SORTER_MODE
, true ) );
521 rSet
.Put( SfxBoolItem( SID_OUTLINE_MODE
, false ) );
522 rSet
.Put( SfxBoolItem( SID_NOTES_MODE
, false ) );
523 rSet
.Put( SfxBoolItem( SID_HANDOUT_MASTER_MODE
, false ) );
525 if (pShell
!=nullptr && pShell
->IsMainViewShell())
527 rSet
.DisableItem(SID_SPELL_DIALOG
);
528 rSet
.DisableItem(SID_SEARCH_DLG
);
531 if (SfxItemState::DEFAULT
== rSet
.GetItemState(SID_EXPAND_PAGE
))
533 bool bDisable
= true;
534 if (eEditMode
== EditMode::Page
)
536 // At least one of the selected pages has to contain an outline
537 // presentation objects in order to enable the expand page menu
539 model::PageEnumeration
aSelectedPages (
540 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
541 mrSlideSorter
.GetModel()));
542 while (aSelectedPages
.HasMoreElements())
544 SdPage
* pPage
= aSelectedPages
.GetNextElement()->GetPage();
545 SdrObject
* pObj
= pPage
->GetPresObj(PRESOBJ_OUTLINE
);
548 if( !pObj
->IsEmptyPresObj() )
554 // check if the object is in edit, than its temporarily not empty
555 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >( pObj
);
558 std::unique_ptr
<OutlinerParaObject
> pParaObj
= pTextObj
->GetEditOutlinerParaObject();
570 rSet
.DisableItem (SID_EXPAND_PAGE
);
573 if (SfxItemState::DEFAULT
== rSet
.GetItemState(SID_SUMMARY_PAGE
))
575 bool bDisable
= true;
576 if (eEditMode
== EditMode::Page
)
578 // At least one of the selected pages has to contain a title
579 // presentation objects in order to enable the summary page menu
581 model::PageEnumeration
aSelectedPages (
582 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
583 mrSlideSorter
.GetModel()));
584 while (aSelectedPages
.HasMoreElements())
586 SdPage
* pPage
= aSelectedPages
.GetNextElement()->GetPage();
587 SdrObject
* pObj
= pPage
->GetPresObj(PRESOBJ_TITLE
);
589 if (pObj
!=nullptr && !pObj
->IsEmptyPresObj())
594 rSet
.DisableItem (SID_SUMMARY_PAGE
);
597 // starting of presentation possible?
598 if( SfxItemState::DEFAULT
== rSet
.GetItemState( SID_PRESENTATION
) ||
599 SfxItemState::DEFAULT
== rSet
.GetItemState( SID_REHEARSE_TIMINGS
) )
601 bool bDisable
= true;
602 model::PageEnumeration
aAllPages (
603 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrSlideSorter
.GetModel()));
604 while (aAllPages
.HasMoreElements())
606 SdPage
* pPage
= aAllPages
.GetNextElement()->GetPage();
608 if( !pPage
->IsExcluded() )
611 if( bDisable
|| pDocShell
->IsPreview())
613 rSet
.DisableItem( SID_PRESENTATION
);
614 rSet
.DisableItem( SID_REHEARSE_TIMINGS
);
618 // Disable the rename slots when there are no or more than one slides/master
619 // pages selected; disable the duplicate slot when there are no slides
621 if (rSet
.GetItemState(SID_RENAMEPAGE
) == SfxItemState::DEFAULT
622 || rSet
.GetItemState(SID_RENAME_MASTER_PAGE
) == SfxItemState::DEFAULT
623 || rSet
.GetItemState(SID_DUPLICATE_PAGE
) == SfxItemState::DEFAULT
)
625 int n
= mrSlideSorter
.GetController().GetPageSelector()
626 .GetSelectedPageCount();
629 rSet
.DisableItem(SID_RENAMEPAGE
);
630 rSet
.DisableItem(SID_RENAME_MASTER_PAGE
);
634 rSet
.DisableItem(SID_DUPLICATE_PAGE
);
638 if (rSet
.GetItemState(SID_HIDE_SLIDE
) == SfxItemState::DEFAULT
639 || rSet
.GetItemState(SID_SHOW_SLIDE
) == SfxItemState::DEFAULT
)
641 model::PageEnumeration
aSelectedPages (
642 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
643 mrSlideSorter
.GetModel()));
644 const SlideExclusionState
eState (GetSlideExclusionState(aSelectedPages
));
648 // Show both entries.
652 rSet
.DisableItem(SID_HIDE_SLIDE
);
656 rSet
.DisableItem(SID_SHOW_SLIDE
);
660 rSet
.DisableItem(SID_HIDE_SLIDE
);
661 rSet
.DisableItem(SID_SHOW_SLIDE
);
666 if (eEditMode
== EditMode::MasterPage
)
668 // Disable some slots when in master page mode.
669 rSet
.DisableItem(SID_ASSIGN_LAYOUT
);
670 rSet
.DisableItem(SID_INSERTPAGE
);
672 if (rSet
.GetItemState(SID_DUPLICATE_PAGE
) == SfxItemState::DEFAULT
)
673 rSet
.DisableItem(SID_DUPLICATE_PAGE
);
677 void SlotManager::GetClipboardState ( SfxItemSet
& rSet
)
679 SdTransferable
* pTransferClip
= SD_MOD()->pTransferClip
;
681 if (rSet
.GetItemState(SID_PASTE
) == SfxItemState::DEFAULT
682 || rSet
.GetItemState(SID_PASTE_SPECIAL
) == SfxItemState::DEFAULT
)
684 // no own clipboard data?
685 if ( !pTransferClip
|| !pTransferClip
->GetDocShell().is() )
687 rSet
.DisableItem(SID_PASTE
);
688 rSet
.DisableItem(SID_PASTE_SPECIAL
);
692 SfxObjectShell
* pTransferDocShell
= pTransferClip
->GetDocShell().get();
694 if( !pTransferDocShell
|| static_cast<DrawDocShell
*>(pTransferDocShell
)->GetDoc()->GetPageCount() <= 1 )
696 bool bIsPastingSupported (false);
698 // No or just one page. Check if there is anything that can be
699 // pasted via a DrawViewShell.
700 ViewShellBase
* pBase
= mrSlideSorter
.GetViewShellBase();
701 if (pBase
!= nullptr)
703 std::shared_ptr
<DrawViewShell
> pDrawViewShell (
704 std::dynamic_pointer_cast
<DrawViewShell
>(pBase
->GetMainViewShell()));
705 if (pDrawViewShell
!= nullptr)
707 TransferableDataHelper
aDataHelper (
708 TransferableDataHelper::CreateFromSystemClipboard(
709 pDrawViewShell
->GetActiveWindow()));
710 if (aDataHelper
.GetFormatCount() > 0)
711 bIsPastingSupported
= true;
715 if ( ! bIsPastingSupported
)
717 rSet
.DisableItem(SID_PASTE
);
718 rSet
.DisableItem(SID_PASTE_SPECIAL
);
724 // Cut, copy and paste of master pages is not yet implemented properly
725 if (rSet
.GetItemState(SID_COPY
) == SfxItemState::DEFAULT
726 || rSet
.GetItemState(SID_PASTE
) == SfxItemState::DEFAULT
727 || rSet
.GetItemState(SID_PASTE_SPECIAL
) == SfxItemState::DEFAULT
728 || rSet
.GetItemState(SID_CUT
) == SfxItemState::DEFAULT
)
730 if (mrSlideSorter
.GetModel().GetEditMode() == EditMode::MasterPage
)
732 if (rSet
.GetItemState(SID_CUT
) == SfxItemState::DEFAULT
)
733 rSet
.DisableItem(SID_CUT
);
734 if (rSet
.GetItemState(SID_COPY
) == SfxItemState::DEFAULT
)
735 rSet
.DisableItem(SID_COPY
);
736 if (rSet
.GetItemState(SID_PASTE
) == SfxItemState::DEFAULT
)
737 rSet
.DisableItem(SID_PASTE
);
738 if (rSet
.GetItemState(SID_PASTE_SPECIAL
) == SfxItemState::DEFAULT
)
739 rSet
.DisableItem(SID_PASTE_SPECIAL
);
743 // Cut, copy, and delete page are disabled when there is no selection.
744 if (!(rSet
.GetItemState(SID_CUT
) == SfxItemState::DEFAULT
745 || rSet
.GetItemState(SID_COPY
) == SfxItemState::DEFAULT
746 || rSet
.GetItemState(SID_DELETE
) == SfxItemState::DEFAULT
747 || rSet
.GetItemState(SID_DELETE_PAGE
) == SfxItemState::DEFAULT
748 || rSet
.GetItemState(SID_DELETE_MASTER_PAGE
) == SfxItemState::DEFAULT
))
751 model::PageEnumeration
aSelectedPages (
752 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
753 mrSlideSorter
.GetModel()));
755 // For copy to work we have to have at least one selected page.
756 if ( ! aSelectedPages
.HasMoreElements())
757 rSet
.DisableItem(SID_COPY
);
759 bool bDisable
= false;
760 // The operations that lead to the deletion of a page are valid if
761 // a) there is at least one selected page
762 // b) deleting the selected pages leaves at least one page in the
764 // c) selected master pages must not be used by slides.
767 if ( ! aSelectedPages
.HasMoreElements())
769 // Test b): Count the number of selected pages. It has to be less
770 // than the number of all pages.
771 else if (mrSlideSorter
.GetController().GetPageSelector().GetSelectedPageCount()
772 >= mrSlideSorter
.GetController().GetPageSelector().GetPageCount())
774 // Test c): Iterate over the selected pages and look for a master
775 // page that is used by at least one page.
776 else while (aSelectedPages
.HasMoreElements())
778 SdPage
* pPage
= aSelectedPages
.GetNextElement()->GetPage();
779 int nUseCount (mrSlideSorter
.GetModel().GetDocument()
780 ->GetMasterPageUserCount(pPage
));
790 rSet
.DisableItem(SID_CUT
);
791 rSet
.DisableItem(SID_DELETE_PAGE
);
792 rSet
.DisableItem(SID_DELETE_MASTER_PAGE
);
796 void SlotManager::GetStatusBarState (SfxItemSet
& rSet
)
798 // page view and layout
799 SdPage
* pPage
= nullptr;
800 SdPage
* pFirstPage
= nullptr;
801 sal_uInt16 nFirstPage
;
802 sal_Int32 nPageCount
;
803 sal_Int32 nActivePageCount
;
804 sal_uInt16 nSelectedPages
= mrSlideSorter
.GetController().GetPageSelector().GetSelectedPageCount();
808 //Set number of slides
809 if (nSelectedPages
> 0)
811 model::PageEnumeration
aSelectedPages (
812 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
813 mrSlideSorter
.GetModel()));
814 model::SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
817 pPage
= pDescriptor
->GetPage();
818 nFirstPage
= (pPage
->GetPageNum()/2) + 1;
819 nPageCount
= mrSlideSorter
.GetModel().GetPageCount();
820 nActivePageCount
= static_cast<sal_Int32
>(mrSlideSorter
.GetModel().GetDocument()->GetActiveSdPageCount());
822 aPageStr
= (nPageCount
== nActivePageCount
) ? SdResId(STR_SD_PAGE_COUNT
) : SdResId(STR_SD_PAGE_COUNT_CUSTOM
);
824 aPageStr
= aPageStr
.replaceFirst("%1", OUString::number(nFirstPage
));
825 aPageStr
= aPageStr
.replaceFirst("%2", OUString::number(nPageCount
));
826 if(nPageCount
!= nActivePageCount
)
827 aPageStr
= aPageStr
.replaceFirst("%3", OUString::number(nActivePageCount
));
829 rSet
.Put( SfxStringItem( SID_STATUS_PAGE
, aPageStr
) );
832 if (nSelectedPages
== 1 && pPage
!= nullptr)
835 aLayoutStr
= pFirstPage
->GetLayoutName();
836 sal_Int32 nIndex
= aLayoutStr
.indexOf( SD_LT_SEPARATOR
);
838 aLayoutStr
= aLayoutStr
.copy(0, nIndex
);
839 rSet
.Put( SfxStringItem( SID_STATUS_LAYOUT
, aLayoutStr
) );
843 void SlotManager::RenameSlide(const SfxRequest
& rRequest
)
845 View
* pDrView
= &mrSlideSorter
.GetView();
847 if ( pDrView
->IsTextEdit() )
849 pDrView
->SdrEndTextEdit();
852 SdPage
* pSelectedPage
= nullptr;
853 model::PageEnumeration
aSelectedPages (
854 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
855 mrSlideSorter
.GetModel()));
856 if (aSelectedPages
.HasMoreElements())
857 pSelectedPage
= aSelectedPages
.GetNextElement()->GetPage();
858 if (pSelectedPage
== nullptr)
861 // tdf#107183 Set different dialog titles when renaming
862 // master slides or normal ones
864 if( rRequest
.GetSlot() == SID_RENAME_MASTER_PAGE
)
865 aTitle
= SdResId( STR_TITLE_RENAMEMASTER
);
867 aTitle
= SdResId( STR_TITLE_RENAMESLIDE
);
869 OUString
aDescr( SdResId( STR_DESC_RENAMESLIDE
) );
870 OUString aPageName
= pSelectedPage
->GetName();
872 if(rRequest
.GetArgs())
874 OUString aName
= rRequest
.GetArgs()->GetItem
<const SfxStringItem
>(SID_RENAMEPAGE
)->GetValue();
876 bool bResult
= RenameSlideFromDrawViewShell(pSelectedPage
->GetPageNum()/2, aName
);
877 DBG_ASSERT( bResult
, "Couldn't rename slide" );
881 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
882 vcl::Window
* pWin
= mrSlideSorter
.GetContentWindow();
883 ScopedVclPtr
<AbstractSvxNameDialog
> aNameDlg(pFact
->CreateSvxNameDialog(
884 pWin
? pWin
->GetFrameWeld() : nullptr,
886 aNameDlg
->SetText( aTitle
);
887 aNameDlg
->SetCheckNameHdl( LINK( this, SlotManager
, RenameSlideHdl
), true );
888 aNameDlg
->SetEditHelpId( HID_SD_NAMEDIALOG_PAGE
);
890 if( aNameDlg
->Execute() == RET_OK
)
893 aNameDlg
->GetName( aNewName
);
894 if (aNewName
!= aPageName
)
897 RenameSlideFromDrawViewShell(
898 pSelectedPage
->GetPageNum()/2, aNewName
);
899 DBG_ASSERT( bResult
, "Couldn't rename slide" );
902 aNameDlg
.disposeAndClear();
904 // Tell the slide sorter about the name change (necessary for
906 mrSlideSorter
.GetController().PageNameHasChanged(
907 (pSelectedPage
->GetPageNum()-1)/2, aPageName
);
910 IMPL_LINK(SlotManager
, RenameSlideHdl
, AbstractSvxNameDialog
&, rDialog
, bool)
913 rDialog
.GetName( aNewName
);
915 model::SharedPageDescriptor
pDescriptor (
916 mrSlideSorter
.GetController().GetCurrentSlideManager()->GetCurrentSlide());
917 SdPage
* pCurrentPage
= nullptr;
918 if (pDescriptor
.get() != nullptr)
919 pCurrentPage
= pDescriptor
->GetPage();
921 return (pCurrentPage
!=nullptr && aNewName
== pCurrentPage
->GetName())
922 || (mrSlideSorter
.GetViewShell()
923 && mrSlideSorter
.GetViewShell()->GetDocSh()->IsNewPageNameValid( aNewName
) );
926 bool SlotManager::RenameSlideFromDrawViewShell( sal_uInt16 nPageId
, const OUString
& rName
)
929 SdDrawDocument
* pDocument
= mrSlideSorter
.GetModel().GetDocument();
930 if( pDocument
->GetPageByName( rName
, bOutDummy
) != SDRPAGE_NOTFOUND
)
933 SdPage
* pPageToRename
= nullptr;
935 SfxUndoManager
* pManager
= pDocument
->GetDocSh()->GetUndoManager();
937 if( mrSlideSorter
.GetModel().GetEditMode() == EditMode::Page
)
939 model::SharedPageDescriptor
pDescriptor (
940 mrSlideSorter
.GetController().GetCurrentSlideManager()->GetCurrentSlide());
941 if (pDescriptor
.get() != nullptr)
942 pPageToRename
= pDescriptor
->GetPage();
944 if (pPageToRename
!= nullptr)
947 SdPage
* pUndoPage
= pPageToRename
;
948 SdrLayerAdmin
& rLayerAdmin
= pDocument
->GetLayerAdmin();
949 SdrLayerID nBackground
= rLayerAdmin
.GetLayerID(sUNO_LayerName_background
);
950 SdrLayerID nBgObj
= rLayerAdmin
.GetLayerID(sUNO_LayerName_background_objects
);
951 SdrLayerIDSet aVisibleLayers
= pPageToRename
->TRG_GetMasterPageVisibleLayers();
954 pManager
->AddUndoAction(
955 std::make_unique
<ModifyPageUndoAction
>(
956 pDocument
, pUndoPage
, rName
, pUndoPage
->GetAutoLayout(),
957 aVisibleLayers
.IsSet( nBackground
),
958 aVisibleLayers
.IsSet( nBgObj
)));
961 pPageToRename
->SetName( rName
);
963 // also rename notes-page
964 SdPage
* pNotesPage
= pDocument
->GetSdPage( nPageId
, PageKind::Notes
);
965 if (pNotesPage
!= nullptr)
966 pNotesPage
->SetName (rName
);
971 // rename MasterPage -> rename LayoutTemplate
972 pPageToRename
= pDocument
->GetMasterSdPage( nPageId
, PageKind::Standard
);
973 if (pPageToRename
!= nullptr)
975 const OUString
aOldLayoutName( pPageToRename
->GetLayoutName() );
976 pManager
->AddUndoAction( std::make_unique
<RenameLayoutTemplateUndoAction
>( pDocument
, aOldLayoutName
, rName
) );
977 pDocument
->RenameLayoutTemplate( aOldLayoutName
, rName
);
981 bool bSuccess
= pPageToRename
!=nullptr && ( rName
== pPageToRename
->GetName() );
985 // user edited page names may be changed by the page so update control
986 // aTabControl.SetPageText( nPageId, rName );
988 // set document to modified state
989 pDocument
->SetChanged();
991 // inform navigator about change
992 SfxBoolItem
aItem( SID_NAVIGATOR_INIT
, true );
993 if (mrSlideSorter
.GetViewShell() != nullptr)
994 mrSlideSorter
.GetViewShell()->GetDispatcher()->ExecuteList(
996 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
1003 /** Insert a slide. The insertion position depends on a) the selection and
1004 b) the mouse position when there is no selection.
1006 When there is a selection then insertion takes place after the last
1007 slide of the selection. For this to work all but the last selected
1008 slide are deselected first.
1010 Otherwise, when there is no selection but the insertion marker is visible
1011 the slide is inserted at that position. The slide before that marker is
1014 When both the selection and the insertion marker are not visible--can
1015 that happen?--the new slide is inserted after the last slide.
1017 void SlotManager::InsertSlide (SfxRequest
& rRequest
)
1019 const sal_Int32
nInsertionIndex (GetInsertionPosition());
1021 PageSelector::BroadcastLock
aBroadcastLock (mrSlideSorter
);
1023 SdPage
* pNewPage
= nullptr;
1024 if (mrSlideSorter
.GetModel().GetEditMode() == EditMode::Page
)
1026 SlideSorterViewShell
* pShell
= dynamic_cast<SlideSorterViewShell
*>(
1027 mrSlideSorter
.GetViewShell());
1028 if (pShell
!= nullptr)
1030 pNewPage
= pShell
->CreateOrDuplicatePage (
1034 ? mrSlideSorter
.GetModel().GetPageDescriptor(nInsertionIndex
)->GetPage()
1040 // Use the API to create a new page.
1041 SdDrawDocument
* pDocument
= mrSlideSorter
.GetModel().GetDocument();
1042 Reference
<drawing::XMasterPagesSupplier
> xMasterPagesSupplier (
1043 pDocument
->getUnoModel(), UNO_QUERY
);
1044 if (xMasterPagesSupplier
.is())
1046 Reference
<drawing::XDrawPages
> xMasterPages (
1047 xMasterPagesSupplier
->getMasterPages());
1048 if (xMasterPages
.is())
1050 xMasterPages
->insertNewByIndex (nInsertionIndex
+1);
1052 // Create shapes for the default layout.
1053 pNewPage
= pDocument
->GetMasterSdPage(
1054 static_cast<sal_uInt16
>(nInsertionIndex
+1), PageKind::Standard
);
1055 pNewPage
->CreateTitleAndLayout (true,true);
1059 if (pNewPage
== nullptr)
1062 // When a new page has been inserted then select it, make it the
1063 // current page, and focus it.
1064 view::SlideSorterView::DrawLock
aDrawLock (mrSlideSorter
);
1065 PageSelector::UpdateLock
aUpdateLock (mrSlideSorter
);
1066 mrSlideSorter
.GetController().GetPageSelector().DeselectAllPages();
1067 mrSlideSorter
.GetController().GetPageSelector().SelectPage(pNewPage
);
1070 void SlotManager::DuplicateSelectedSlides (SfxRequest
& rRequest
)
1072 // Create a list of the pages that are to be duplicated. The process of
1073 // duplication alters the selection.
1074 sal_Int32
nInsertPosition (0);
1075 ::std::vector
<SdPage
*> aPagesToDuplicate
;
1076 model::PageEnumeration
aSelectedPages (
1077 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter
.GetModel()));
1078 while (aSelectedPages
.HasMoreElements())
1080 model::SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
1081 if (pDescriptor
&& pDescriptor
->GetPage())
1083 aPagesToDuplicate
.push_back(pDescriptor
->GetPage());
1084 nInsertPosition
= pDescriptor
->GetPage()->GetPageNum()+2;
1088 // Duplicate the pages in aPagesToDuplicate and collect the newly
1089 // created pages in aPagesToSelect.
1090 const bool bUndo (aPagesToDuplicate
.size()>1 && mrSlideSorter
.GetView().IsUndoEnabled());
1092 mrSlideSorter
.GetView().BegUndo(SdResId(STR_INSERTPAGE
));
1094 ::std::vector
<SdPage
*> aPagesToSelect
;
1095 for(const auto& rpPage
: aPagesToDuplicate
)
1097 aPagesToSelect
.push_back(
1098 mrSlideSorter
.GetViewShell()->CreateOrDuplicatePage(
1099 rRequest
, PageKind::Standard
, rpPage
, nInsertPosition
));
1100 nInsertPosition
+= 2;
1102 aPagesToDuplicate
.clear();
1105 mrSlideSorter
.GetView().EndUndo();
1107 // Set the selection to the pages in aPagesToSelect.
1108 PageSelector
& rSelector (mrSlideSorter
.GetController().GetPageSelector());
1109 rSelector
.DeselectAllPages();
1110 for (auto const& it
: aPagesToSelect
)
1112 rSelector
.SelectPage(it
);
1116 void SlotManager::ChangeSlideExclusionState (
1117 const model::SharedPageDescriptor
& rpDescriptor
,
1118 const bool bExcludeSlide
)
1122 mrSlideSorter
.GetView().SetState(
1124 model::PageDescriptor::ST_Excluded
,
1129 model::PageEnumeration
aSelectedPages (
1130 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
1131 mrSlideSorter
.GetModel()));
1132 while (aSelectedPages
.HasMoreElements())
1134 model::SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
1135 mrSlideSorter
.GetView().SetState(
1137 model::PageDescriptor::ST_Excluded
,
1142 SfxBindings
& rBindings (mrSlideSorter
.GetViewShell()->GetViewFrame()->GetBindings());
1143 rBindings
.Invalidate(SID_PRESENTATION
);
1144 rBindings
.Invalidate(SID_REHEARSE_TIMINGS
);
1145 rBindings
.Invalidate(SID_HIDE_SLIDE
);
1146 rBindings
.Invalidate(SID_SHOW_SLIDE
);
1147 mrSlideSorter
.GetModel().GetDocument()->SetChanged();
1150 sal_Int32
SlotManager::GetInsertionPosition()
1152 PageSelector
& rSelector (mrSlideSorter
.GetController().GetPageSelector());
1154 // The insertion indicator is preferred. After all the user explicitly
1155 // used it to define the insertion position.
1156 if (mrSlideSorter
.GetController().GetInsertionIndicatorHandler()->IsActive())
1158 // Select the page before the insertion indicator.
1159 return mrSlideSorter
.GetController().GetInsertionIndicatorHandler()->GetInsertionPageIndex()
1163 // Is there a stored insertion position?
1164 else if (mrSlideSorter
.GetController().GetSelectionManager()->GetInsertionPosition() >= 0)
1166 return mrSlideSorter
.GetController().GetSelectionManager()->GetInsertionPosition() - 1;
1169 // Use the index of the last selected slide.
1170 else if (rSelector
.GetSelectedPageCount() > 0)
1172 for (int nIndex
=rSelector
.GetPageCount()-1; nIndex
>=0; --nIndex
)
1173 if (rSelector
.IsPageSelected(nIndex
))
1176 // We should never get here.
1178 return rSelector
.GetPageCount() - 1;
1181 // Select the last page when there is at least one page.
1182 else if (rSelector
.GetPageCount() > 0)
1184 return rSelector
.GetPageCount() - 1;
1187 // Hope for the best that CreateOrDuplicatePage() can cope with an empty
1191 // We should never get here because there has to be at least one page.
1197 void SlotManager::NotifyEditModeChange()
1199 SfxBindings
& rBindings (mrSlideSorter
.GetViewShell()->GetViewFrame()->GetBindings());
1200 rBindings
.Invalidate(SID_PRESENTATION
);
1201 rBindings
.Invalidate(SID_INSERTPAGE
);
1202 rBindings
.Invalidate(SID_DUPLICATE_PAGE
);
1207 SlideExclusionState
GetSlideExclusionState (model::PageEnumeration
& rPageSet
)
1209 SlideExclusionState
eState (UNDEFINED
);
1211 // Get toggle state of the selected pages.
1212 while (rPageSet
.HasMoreElements() && eState
!=MIXED
)
1214 const bool bState
= rPageSet
.GetNextElement()->GetPage()->IsExcluded();
1218 // Use the first selected page to set the initial value.
1219 eState
= bState
? EXCLUDED
: INCLUDED
;
1223 // The pages before where all not part of the show,
1230 // The pages before where all part of the show,
1237 // No need to change anything.
1245 } // end of anonymous namespace
1247 } } } // end of namespace ::sd::slidesorter::controller
1249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */