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 <controller/SlsSlotManager.hxx>
21 #include <SlideSorter.hxx>
22 #include <SlideSorterViewShell.hxx>
23 #include <controller/SlideSorterController.hxx>
24 #include <controller/SlsClipboard.hxx>
25 #include <controller/SlsCurrentSlideManager.hxx>
26 #include <controller/SlsInsertionIndicatorHandler.hxx>
27 #include <controller/SlsPageSelector.hxx>
28 #include <controller/SlsSelectionFunction.hxx>
29 #include <controller/SlsSelectionManager.hxx>
30 #include <model/SlideSorterModel.hxx>
31 #include <model/SlsPageEnumerationProvider.hxx>
32 #include <model/SlsPageDescriptor.hxx>
33 #include <view/SlideSorterView.hxx>
34 #include <view/SlsLayouter.hxx>
35 #include <framework/FrameworkHelper.hxx>
38 #include <fucushow.hxx>
39 #include <fusldlg.hxx>
40 #include <fuexpand.hxx>
41 #include <fusumry.hxx>
42 #include <slideshow.hxx>
44 #include <strings.hrc>
45 #include <sdresid.hxx>
46 #include <unokywds.hxx>
47 #include <drawdoc.hxx>
48 #include <DrawDocShell.hxx>
49 #include <ViewShellBase.hxx>
50 #include <ViewShellImplementation.hxx>
54 #include <unmodpg.hxx>
55 #include <DrawViewShell.hxx>
56 #include <sdabstdlg.hxx>
58 #include <unomodel.hxx>
60 #include <vcl/uitest/logger.hxx>
61 #include <vcl/uitest/eventdescription.hxx>
63 #include <sfx2/request.hxx>
64 #include <sfx2/viewfrm.hxx>
65 #include <sfx2/bindings.hxx>
66 #include <sfx2/sidebar/Sidebar.hxx>
67 #include <svx/svxids.hrc>
68 #include <svx/svxdlg.hxx>
69 #include <svl/intitem.hxx>
70 #include <svl/stritem.hxx>
71 #include <svl/whiter.hxx>
72 #include <svl/itempool.hxx>
73 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
74 #include <com/sun/star/drawing/XDrawPages.hpp>
75 #include <osl/diagnose.h>
79 using namespace ::com::sun::star
;
80 using namespace ::com::sun::star::uno
;
82 namespace sd::slidesorter::controller
{
86 /** The state of a set of slides with respect to being excluded from the
89 enum SlideExclusionState
{UNDEFINED
, EXCLUDED
, INCLUDED
, MIXED
};
91 /** Return for the given set of slides whether they included are
92 excluded from the slide show.
94 SlideExclusionState
GetSlideExclusionState (model::PageEnumeration
& rPageSet
);
96 } // end of anonymous namespace
101 void collectUIInformation(std::map
<OUString
, OUString
>&& aParameters
, const OUString
& rAction
)
103 EventDescription aDescription
;
104 aDescription
.aID
= "impress_win_or_draw_win";
105 aDescription
.aParameters
= std::move(aParameters
);
106 aDescription
.aAction
= rAction
;
107 aDescription
.aKeyWord
= "ImpressWindowUIObject";
108 aDescription
.aParent
= "MainWindow";
110 UITestLogger::getInstance().logEvent(aDescription
);
115 SlotManager::SlotManager (SlideSorter
& rSlideSorter
)
116 : mrSlideSorter(rSlideSorter
)
120 void SlotManager::FuTemporary (SfxRequest
& rRequest
)
122 SdDrawDocument
* pDocument
= mrSlideSorter
.GetModel().GetDocument();
124 SlideSorterViewShell
* pShell
125 = dynamic_cast<SlideSorterViewShell
*>(mrSlideSorter
.GetViewShell());
126 if (pShell
== nullptr)
129 switch (rRequest
.GetSlot())
131 case SID_PRESENTATION
:
132 case SID_PRESENTATION_CURRENT_SLIDE
:
133 case SID_REHEARSE_TIMINGS
:
134 slideshowhelp::ShowSlideShow(rRequest
, *mrSlideSorter
.GetModel().GetDocument());
140 ChangeSlideExclusionState(model::SharedPageDescriptor(), true);
144 ChangeSlideExclusionState(model::SharedPageDescriptor(), false);
147 case SID_PAGES_PER_ROW
:
148 if (rRequest
.GetArgs() != nullptr)
150 const SfxUInt16Item
* pPagesPerRow
= rRequest
.GetArg
<SfxUInt16Item
>(SID_PAGES_PER_ROW
);
151 if (pPagesPerRow
!= nullptr)
153 sal_Int32 nColumnCount
= pPagesPerRow
->GetValue();
154 // Force the given number of columns by setting
155 // the minimal and maximal number of columns to
157 mrSlideSorter
.GetView().GetLayouter().SetColumnCount (
158 nColumnCount
, nColumnCount
);
159 // Force a repaint and re-layout.
160 pShell
->ArrangeGUIElements ();
161 // Rearrange the UI-elements controlled by the
162 // controller and force a rearrangement of the
164 mrSlideSorter
.GetController().Rearrange(true);
171 mrSlideSorter
.GetController().GetPageSelector().SelectAllPages();
175 case SID_SLIDE_TRANSITIONS_PANEL
:
177 // First make sure that the sidebar is visible
178 if (SfxViewFrame
* pFrame
= pShell
->GetViewFrame())
180 pFrame
->ShowChildWindow(SID_SIDEBAR
);
181 ::sfx2::sidebar::Sidebar::ShowPanel(
182 u
"SdSlideTransitionPanel",
183 pFrame
->GetFrame().GetFrameInterface());
189 case SID_MASTER_SLIDES_PANEL
:
191 // First make sure that the sidebar is visible
192 if (SfxViewFrame
* pFrame
= pShell
->GetViewFrame())
194 pFrame
->ShowChildWindow(SID_SIDEBAR
);
195 ::sfx2::sidebar::Sidebar::ShowPanel(
196 u
"SdAllMasterPagesPanel",
197 pFrame
->GetFrame().GetFrameInterface());
203 case SID_PRESENTATION_DLG
:
204 FuSlideShowDlg::Create (
206 mrSlideSorter
.GetContentWindow(),
207 &mrSlideSorter
.GetView(),
212 case SID_CUSTOMSHOW_DLG
:
213 FuCustomShowDlg::Create (
215 mrSlideSorter
.GetContentWindow(),
216 &mrSlideSorter
.GetView(),
221 case SID_EXPAND_PAGE
:
222 FuExpandPage::Create (
224 mrSlideSorter
.GetContentWindow(),
225 &mrSlideSorter
.GetView(),
230 case SID_SUMMARY_PAGE
:
231 FuSummaryPage::Create (
233 mrSlideSorter
.GetContentWindow(),
234 &mrSlideSorter
.GetView(),
240 case SID_INSERT_MASTER_PAGE
:
241 InsertSlide(rRequest
);
245 case SID_DUPLICATE_PAGE
:
246 DuplicateSelectedSlides(rRequest
);
250 case SID_DELETE_PAGE
:
251 case SID_DELETE_MASTER_PAGE
:
252 case SID_DELETE
: // we need SID_CUT to handle the delete key
253 // (DEL -> accelerator -> SID_CUT).
254 if (mrSlideSorter
.GetModel().GetPageCount() > 1)
256 mrSlideSorter
.GetView().EndTextEditAllViews();
257 mrSlideSorter
.GetController().GetSelectionManager()->DeleteSelectedPages();
264 case SID_RENAME_MASTER_PAGE
:
265 RenameSlide (rRequest
);
269 case SID_ASSIGN_LAYOUT
:
271 pShell
->mpImpl
->AssignLayout( rRequest
, PageKind::Standard
);
278 SdAbstractDialogFactory
* pFact
= SdAbstractDialogFactory::Create();
279 vcl::Window
* pWin
= mrSlideSorter
.GetContentWindow();
280 ScopedVclPtr
<VclAbstractDialog
> pDlg(pFact
->CreateSdPhotoAlbumDialog(
281 pWin
? pWin
->GetFrameWeld() : nullptr,
290 #ifdef ENABLE_SDREMOTE
291 SdAbstractDialogFactory
* pFact
= SdAbstractDialogFactory::Create();
292 vcl::Window
* pWin
= mrSlideSorter
.GetContentWindow();
293 ScopedVclPtr
<VclAbstractDialog
> pDlg(pFact
->CreateRemoteDialog(pWin
? pWin
->GetFrameWeld() : nullptr));
304 void SlotManager::FuPermanent (SfxRequest
& rRequest
)
306 ViewShell
* pShell
= mrSlideSorter
.GetViewShell();
307 if (pShell
== nullptr)
310 if(pShell
->GetCurrentFunction().is())
312 rtl::Reference
<FuPoor
> xEmpty
;
313 if (pShell
->GetOldFunction() == pShell
->GetCurrentFunction())
314 pShell
->SetOldFunction(xEmpty
);
316 pShell
->GetCurrentFunction()->Deactivate();
317 pShell
->SetCurrentFunction(xEmpty
);
320 switch(rRequest
.GetSlot())
322 case SID_OBJECT_SELECT
:
323 pShell
->SetCurrentFunction( SelectionFunction::Create(mrSlideSorter
, rRequest
) );
331 if(pShell
->GetOldFunction().is())
333 pShell
->GetOldFunction()->Deactivate();
334 rtl::Reference
<FuPoor
> xEmpty
;
335 pShell
->SetOldFunction(xEmpty
);
338 if(pShell
->GetCurrentFunction().is())
340 pShell
->GetCurrentFunction()->Activate();
341 pShell
->SetOldFunction(pShell
->GetCurrentFunction());
344 //! that's only until ENUM-Slots ?are
345 // Invalidate( SID_OBJECT_SELECT );
348 void SlotManager::FuSupport (SfxRequest
& rRequest
)
350 switch (rRequest
.GetSlot())
352 case SID_STYLE_FAMILY
:
353 if (rRequest
.GetArgs() != nullptr)
355 SdDrawDocument
* pDocument
356 = mrSlideSorter
.GetModel().GetDocument();
357 if (pDocument
!= nullptr)
359 const SfxPoolItem
& rItem (
360 rRequest
.GetArgs()->Get(SID_STYLE_FAMILY
));
361 pDocument
->GetDocSh()->SetStyleFamily(
362 static_cast<SfxStyleFamily
>(static_cast<const SfxUInt16Item
&>(rItem
).GetValue()));
369 SdTransferable
* pTransferClip
= SdModule::get()->pTransferClip
;
372 SfxObjectShell
* pTransferDocShell
= pTransferClip
->GetDocShell().get();
374 DrawDocShell
* pDocShell
= dynamic_cast<DrawDocShell
*>(pTransferDocShell
);
375 if (pDocShell
&& pDocShell
->GetDoc()->GetPageCount() > 1)
377 mrSlideSorter
.GetController().GetClipboard().HandleSlotCall(rRequest
);
381 ViewShellBase
* pBase
= mrSlideSorter
.GetViewShellBase();
382 if (pBase
!= nullptr)
384 std::shared_ptr
<DrawViewShell
> pDrawViewShell (
385 std::dynamic_pointer_cast
<DrawViewShell
>(pBase
->GetMainViewShell()));
386 if (pDrawViewShell
!= nullptr)
387 pDrawViewShell
->FuSupport(rRequest
);
395 mrSlideSorter
.GetView().EndTextEditAllViews();
396 mrSlideSorter
.GetController().GetClipboard().HandleSlotCall(rRequest
);
399 case SID_DRAWINGMODE
:
401 case SID_HANDOUT_MASTER_MODE
:
402 case SID_SLIDE_SORTER_MODE
:
403 case SID_OUTLINE_MODE
:
405 ViewShellBase
* pBase
= mrSlideSorter
.GetViewShellBase();
406 if (pBase
!= nullptr)
408 framework::FrameworkHelper::Instance(*pBase
)->HandleModeChangeSlot(
409 rRequest
.GetSlot(), rRequest
);
417 SlideSorterViewShell
* pViewShell
418 = dynamic_cast<SlideSorterViewShell
*>(mrSlideSorter
.GetViewShell());
419 if (pViewShell
!= nullptr)
421 pViewShell
->ImpSidUndo (rRequest
);
428 SlideSorterViewShell
* pViewShell
429 = dynamic_cast<SlideSorterViewShell
*>(mrSlideSorter
.GetViewShell());
430 if (pViewShell
!= nullptr)
432 pViewShell
->ImpSidRedo (rRequest
);
442 void SlotManager::ExecCtrl (SfxRequest
& rRequest
)
444 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
445 sal_uInt16 nSlot
= rRequest
.GetSlot();
450 // empty Undo-Manager
451 mrSlideSorter
.GetModel().GetDocument()->GetDocSh()->ClearUndoBuffer();
453 // normal forwarding to ViewFrame for execution
454 if (pViewShell
!= nullptr)
455 pViewShell
->GetViewFrame()->ExecuteSlot(rRequest
);
457 // has to be finished right away
461 case SID_OUTPUT_QUALITY_COLOR
:
462 case SID_OUTPUT_QUALITY_GRAYSCALE
:
463 case SID_OUTPUT_QUALITY_BLACKWHITE
:
464 case SID_OUTPUT_QUALITY_CONTRAST
:
467 if (pViewShell
!= nullptr)
468 pViewShell
->ExecReq (rRequest
);
472 case SID_MAIL_SCROLLBODY_PAGEDOWN
:
474 if (pViewShell
!= nullptr)
475 pViewShell
->ExecReq (rRequest
);
479 case SID_OPT_LOCALE_CHANGED
:
481 mrSlideSorter
.GetController().UpdateAllPages();
482 if (pViewShell
!= nullptr)
483 pViewShell
->UpdatePreview (pViewShell
->GetActualPage());
489 // We have to handle the SID_SEARCH_DLG slot explicitly because
490 // in some cases (when the slide sorter is displayed in the
491 // center pane) we want to disable the search dialog. Therefore
492 // we have to handle the execution of that slot as well.
493 // We try to do that by forwarding the request to the view frame
494 // of the view shell.
495 if (pViewShell
!= nullptr)
496 pViewShell
->GetViewFrame()->ExecuteSlot(rRequest
);
504 void SlotManager::GetAttrState (SfxItemSet
& rSet
)
506 // Iterate over all items.
507 SfxWhichIter
aIter (rSet
);
508 sal_uInt16 nWhich
= aIter
.FirstWhich();
511 sal_uInt16
nSlotId (nWhich
);
512 if (SfxItemPool::IsWhich(nWhich
) && mrSlideSorter
.GetViewShell()!=nullptr)
513 nSlotId
= mrSlideSorter
.GetViewShell()->GetPool().GetSlotId(nWhich
);
516 case SID_PAGES_PER_ROW
:
520 static_cast<sal_uInt16
>(mrSlideSorter
.GetView().GetLayouter().GetColumnCount())
525 nWhich
= aIter
.NextWhich();
529 void SlotManager::GetMenuState (SfxItemSet
& rSet
)
531 EditMode eEditMode
= mrSlideSorter
.GetModel().GetEditMode();
532 ViewShell
* pShell
= mrSlideSorter
.GetViewShell();
533 DrawDocShell
* pDocShell
= mrSlideSorter
.GetModel().GetDocument()->GetDocSh();
535 if (pShell
!=nullptr && pShell
->GetCurrentFunction().is())
537 sal_uInt16 nSId
= pShell
->GetCurrentFunction()->GetSlotID();
539 rSet
.Put( SfxBoolItem( nSId
, true ) );
541 rSet
.Put( SfxBoolItem( SID_DRAWINGMODE
, false ) );
542 rSet
.Put( SfxBoolItem( SID_SLIDE_SORTER_MODE
, true ) );
543 rSet
.Put( SfxBoolItem( SID_OUTLINE_MODE
, false ) );
544 rSet
.Put( SfxBoolItem( SID_NOTES_MODE
, false ) );
545 rSet
.Put( SfxBoolItem( SID_HANDOUT_MASTER_MODE
, false ) );
547 if (pShell
!=nullptr && pShell
->IsMainViewShell())
549 rSet
.DisableItem(SID_SPELL_DIALOG
);
550 rSet
.DisableItem(SID_SEARCH_DLG
);
553 if (SfxItemState::DEFAULT
== rSet
.GetItemState(SID_EXPAND_PAGE
))
555 bool bDisable
= true;
556 if (eEditMode
== EditMode::Page
)
558 // At least one of the selected pages has to contain an outline
559 // presentation objects in order to enable the expand page menu
561 model::PageEnumeration
aSelectedPages (
562 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
563 mrSlideSorter
.GetModel()));
564 while (aSelectedPages
.HasMoreElements())
566 SdPage
* pPage
= aSelectedPages
.GetNextElement()->GetPage();
567 SdrObject
* pObj
= pPage
->GetPresObj(PresObjKind::Outline
);
570 if( !pObj
->IsEmptyPresObj() )
576 // check if the object is in edit, then if it's temporarily not empty
577 SdrTextObj
* pTextObj
= DynCastSdrTextObj( pObj
);
580 if( pTextObj
->CanCreateEditOutlinerParaObject() )
591 rSet
.DisableItem (SID_EXPAND_PAGE
);
594 if (SfxItemState::DEFAULT
== rSet
.GetItemState(SID_SUMMARY_PAGE
))
596 bool bDisable
= true;
597 if (eEditMode
== EditMode::Page
)
599 // At least one of the selected pages has to contain a title
600 // presentation objects in order to enable the summary page menu
602 model::PageEnumeration
aSelectedPages (
603 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
604 mrSlideSorter
.GetModel()));
605 while (aSelectedPages
.HasMoreElements())
607 SdPage
* pPage
= aSelectedPages
.GetNextElement()->GetPage();
608 SdrObject
* pObj
= pPage
->GetPresObj(PresObjKind::Title
);
610 if (pObj
!=nullptr && !pObj
->IsEmptyPresObj())
615 rSet
.DisableItem (SID_SUMMARY_PAGE
);
618 // starting of presentation possible?
619 if( SfxItemState::DEFAULT
== rSet
.GetItemState( SID_PRESENTATION
) ||
620 SfxItemState::DEFAULT
== rSet
.GetItemState( SID_REHEARSE_TIMINGS
) )
622 bool bDisable
= true;
623 model::PageEnumeration
aAllPages (
624 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrSlideSorter
.GetModel()));
625 while (aAllPages
.HasMoreElements())
627 SdPage
* pPage
= aAllPages
.GetNextElement()->GetPage();
629 if( !pPage
->IsExcluded() )
632 if( bDisable
|| pDocShell
->IsPreview())
634 rSet
.DisableItem( SID_PRESENTATION
);
635 rSet
.DisableItem( SID_REHEARSE_TIMINGS
);
639 // Disable the rename slots when there are no or more than one slides/master
640 // pages selected; disable the duplicate slot when there are no slides
642 if (rSet
.GetItemState(SID_RENAMEPAGE
) == SfxItemState::DEFAULT
643 || rSet
.GetItemState(SID_RENAME_MASTER_PAGE
) == SfxItemState::DEFAULT
644 || rSet
.GetItemState(SID_DUPLICATE_PAGE
) == SfxItemState::DEFAULT
)
646 int n
= mrSlideSorter
.GetController().GetPageSelector()
647 .GetSelectedPageCount();
650 rSet
.DisableItem(SID_RENAMEPAGE
);
651 rSet
.DisableItem(SID_RENAME_MASTER_PAGE
);
655 rSet
.DisableItem(SID_DUPLICATE_PAGE
);
659 if (rSet
.GetItemState(SID_HIDE_SLIDE
) == SfxItemState::DEFAULT
660 || rSet
.GetItemState(SID_SHOW_SLIDE
) == SfxItemState::DEFAULT
)
662 model::PageEnumeration
aSelectedPages (
663 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
664 mrSlideSorter
.GetModel()));
665 const SlideExclusionState
eState (GetSlideExclusionState(aSelectedPages
));
669 // Show both entries.
673 rSet
.DisableItem(SID_HIDE_SLIDE
);
677 rSet
.DisableItem(SID_SHOW_SLIDE
);
681 rSet
.DisableItem(SID_HIDE_SLIDE
);
682 rSet
.DisableItem(SID_SHOW_SLIDE
);
687 if (eEditMode
== EditMode::MasterPage
)
689 // Disable some slots when in master page mode.
690 rSet
.DisableItem(SID_ASSIGN_LAYOUT
);
691 rSet
.DisableItem(SID_INSERTPAGE
);
693 if (rSet
.GetItemState(SID_DUPLICATE_PAGE
) == SfxItemState::DEFAULT
)
694 rSet
.DisableItem(SID_DUPLICATE_PAGE
);
698 void SlotManager::GetClipboardState ( SfxItemSet
& rSet
)
700 SdTransferable
* pTransferClip
= SdModule::get()->pTransferClip
;
702 if (rSet
.GetItemState(SID_PASTE
) == SfxItemState::DEFAULT
703 || rSet
.GetItemState(SID_PASTE_SPECIAL
) == SfxItemState::DEFAULT
)
705 // no own clipboard data?
706 if ( !pTransferClip
|| !pTransferClip
->GetDocShell().is() )
708 rSet
.DisableItem(SID_PASTE
);
709 rSet
.DisableItem(SID_PASTE_SPECIAL
);
713 SfxObjectShell
* pTransferDocShell
= pTransferClip
->GetDocShell().get();
715 if( !pTransferDocShell
|| static_cast<DrawDocShell
*>(pTransferDocShell
)->GetDoc()->GetPageCount() <= 1 )
717 bool bIsPastingSupported (false);
719 // No or just one page. Check if there is anything that can be
720 // pasted via a DrawViewShell.
721 ViewShellBase
* pBase
= mrSlideSorter
.GetViewShellBase();
722 if (pBase
!= nullptr)
724 std::shared_ptr
<DrawViewShell
> pDrawViewShell (
725 std::dynamic_pointer_cast
<DrawViewShell
>(pBase
->GetMainViewShell()));
726 if (pDrawViewShell
!= nullptr)
728 TransferableDataHelper
aDataHelper (
729 TransferableDataHelper::CreateFromSystemClipboard(
730 pDrawViewShell
->GetActiveWindow()));
731 if (aDataHelper
.GetFormatCount() > 0)
732 bIsPastingSupported
= true;
736 if ( ! bIsPastingSupported
)
738 rSet
.DisableItem(SID_PASTE
);
739 rSet
.DisableItem(SID_PASTE_SPECIAL
);
745 // Cut, copy and paste of master pages is not yet implemented properly
746 if (rSet
.GetItemState(SID_COPY
) == SfxItemState::DEFAULT
747 || rSet
.GetItemState(SID_PASTE
) == SfxItemState::DEFAULT
748 || rSet
.GetItemState(SID_PASTE_SPECIAL
) == SfxItemState::DEFAULT
749 || rSet
.GetItemState(SID_CUT
) == SfxItemState::DEFAULT
)
751 if (mrSlideSorter
.GetModel().GetEditMode() == EditMode::MasterPage
)
753 if (rSet
.GetItemState(SID_CUT
) == SfxItemState::DEFAULT
)
754 rSet
.DisableItem(SID_CUT
);
755 if (rSet
.GetItemState(SID_COPY
) == SfxItemState::DEFAULT
)
756 rSet
.DisableItem(SID_COPY
);
757 if (rSet
.GetItemState(SID_PASTE
) == SfxItemState::DEFAULT
)
758 rSet
.DisableItem(SID_PASTE
);
759 if (rSet
.GetItemState(SID_PASTE_SPECIAL
) == SfxItemState::DEFAULT
)
760 rSet
.DisableItem(SID_PASTE_SPECIAL
);
764 ViewShellBase
* pBase
= mrSlideSorter
.GetViewShellBase();
765 if (pBase
&& pBase
->GetObjectShell()->isContentExtractionLocked())
767 rSet
.DisableItem(SID_COPY
);
768 rSet
.DisableItem(SID_CUT
);
771 // Cut, copy, and delete page are disabled when there is no selection.
772 if (!(rSet
.GetItemState(SID_CUT
) == SfxItemState::DEFAULT
773 || rSet
.GetItemState(SID_COPY
) == SfxItemState::DEFAULT
774 || rSet
.GetItemState(SID_DELETE
) == SfxItemState::DEFAULT
775 || rSet
.GetItemState(SID_DELETE_PAGE
) == SfxItemState::DEFAULT
776 || rSet
.GetItemState(SID_DELETE_MASTER_PAGE
) == SfxItemState::DEFAULT
))
779 model::PageEnumeration
aSelectedPages (
780 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
781 mrSlideSorter
.GetModel()));
783 // For copy to work we have to have at least one selected page.
784 if ( ! aSelectedPages
.HasMoreElements())
785 rSet
.DisableItem(SID_COPY
);
787 bool bDisable
= false;
788 // The operations that lead to the deletion of a page are valid if
789 // a) there is at least one selected page
790 // b) deleting the selected pages leaves at least one page in the
792 // c) selected master pages must not be used by slides.
795 if ( ! aSelectedPages
.HasMoreElements())
797 // Test b): Count the number of selected pages. It has to be less
798 // than the number of all pages.
799 else if (mrSlideSorter
.GetController().GetPageSelector().GetSelectedPageCount()
800 >= mrSlideSorter
.GetController().GetPageSelector().GetPageCount())
802 // Test c): Iterate over the selected pages and look for a master
803 // page that is used by at least one page.
804 else while (aSelectedPages
.HasMoreElements())
806 SdPage
* pPage
= aSelectedPages
.GetNextElement()->GetPage();
807 int nUseCount (mrSlideSorter
.GetModel().GetDocument()
808 ->GetMasterPageUserCount(pPage
));
818 rSet
.DisableItem(SID_CUT
);
819 rSet
.DisableItem(SID_DELETE_PAGE
);
820 rSet
.DisableItem(SID_DELETE_MASTER_PAGE
);
824 void SlotManager::GetStatusBarState (SfxItemSet
& rSet
)
826 // page view and layout
827 SdPage
* pPage
= nullptr;
828 sal_uInt16 nSelectedPages
= mrSlideSorter
.GetController().GetPageSelector().GetSelectedPageCount();
829 View
* pDrView
= &mrSlideSorter
.GetView();
831 //Set number of slides
832 if (nSelectedPages
> 0)
834 model::PageEnumeration
aSelectedPages (
835 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
836 mrSlideSorter
.GetModel()));
837 model::SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
841 pPage
= pDescriptor
->GetPage();
842 sal_uInt16 nFirstPage
= (pPage
->GetPageNum()/2) + 1;
843 sal_Int32 nPageCount
= mrSlideSorter
.GetModel().GetPageCount();
844 sal_Int32 nActivePageCount
= static_cast<sal_Int32
>(mrSlideSorter
.GetModel().GetDocument()->GetActiveSdPageCount());
846 if (pDrView
->GetDoc().GetDocumentType() == DocumentType::Draw
)
847 aPageStr
= (nPageCount
== nActivePageCount
) ? SdResId(STR_SD_PAGE_COUNT_DRAW
) : SdResId(STR_SD_PAGE_COUNT_CUSTOM_DRAW
);
849 aPageStr
= (nPageCount
== nActivePageCount
) ? SdResId(STR_SD_PAGE_COUNT
) : SdResId(STR_SD_PAGE_COUNT_CUSTOM
);
851 aPageStr
= aPageStr
.replaceFirst("%1", OUString::number(nFirstPage
));
852 aPageStr
= aPageStr
.replaceFirst("%2", OUString::number(nPageCount
));
853 if(nPageCount
!= nActivePageCount
)
854 aPageStr
= aPageStr
.replaceFirst("%3", OUString::number(nActivePageCount
));
856 rSet
.Put( SfxStringItem( SID_STATUS_PAGE
, aPageStr
) );
859 if (nSelectedPages
== 1 && pPage
!= nullptr)
861 SdPage
* pFirstPage
= pPage
;
862 OUString aLayoutStr
= pFirstPage
->GetLayoutName();
863 sal_Int32 nIndex
= aLayoutStr
.indexOf( SD_LT_SEPARATOR
);
865 aLayoutStr
= aLayoutStr
.copy(0, nIndex
);
866 rSet
.Put( SfxStringItem( SID_STATUS_LAYOUT
, aLayoutStr
) );
869 const Fraction
& aUIScale
= mrSlideSorter
.GetModel().GetDocument()->GetUIScale();
870 OUString aString
= OUString::number(aUIScale
.GetNumerator()) +
871 ":" + OUString::number(aUIScale
.GetDenominator());
872 rSet
.Put( SfxStringItem( SID_SCALE
, aString
) );
875 void SlotManager::RenameSlide(const SfxRequest
& rRequest
)
877 View
* pDrView
= &mrSlideSorter
.GetView();
879 if ( pDrView
->IsTextEdit() )
881 pDrView
->SdrEndTextEdit();
884 SdPage
* pSelectedPage
= nullptr;
885 model::PageEnumeration
aSelectedPages (
886 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
887 mrSlideSorter
.GetModel()));
888 if (aSelectedPages
.HasMoreElements())
889 pSelectedPage
= aSelectedPages
.GetNextElement()->GetPage();
890 if (pSelectedPage
== nullptr)
893 // tdf#107183 Set different dialog titles when renaming
894 // master slides or normal ones
896 if( rRequest
.GetSlot() == SID_RENAME_MASTER_PAGE
)
898 if (pDrView
->GetDoc().GetDocumentType() == DocumentType::Draw
)
899 aTitle
= SdResId( STR_TITLE_RENAMEMASTERPAGE
);
901 aTitle
= SdResId( STR_TITLE_RENAMEMASTERSLIDE
);
905 if (pDrView
->GetDoc().GetDocumentType() == DocumentType::Draw
)
906 aTitle
= SdResId( STR_TITLE_RENAMEPAGE
);
908 aTitle
= SdResId( STR_TITLE_RENAMESLIDE
);
911 OUString
aDescr( SdResId( STR_DESC_RENAMESLIDE
) );
912 OUString aPageName
= pSelectedPage
->GetName();
914 if(rRequest
.GetArgs())
916 OUString aName
= rRequest
.GetArgs()->GetItem
<const SfxStringItem
>(SID_RENAMEPAGE
)->GetValue();
918 bool bResult
= RenameSlideFromDrawViewShell(pSelectedPage
->GetPageNum()/2, aName
);
919 DBG_ASSERT( bResult
, "Couldn't rename slide or page" );
923 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
924 vcl::Window
* pWin
= mrSlideSorter
.GetContentWindow();
925 ScopedVclPtr
<AbstractSvxNameDialog
> aNameDlg(pFact
->CreateSvxNameDialog(
926 pWin
? pWin
->GetFrameWeld() : nullptr,
928 OUString aOldName
= aNameDlg
->GetName();
929 aNameDlg
->SetText( aTitle
);
930 aNameDlg
->SetCheckNameHdl( LINK( this, SlotManager
, RenameSlideHdl
) );
931 aNameDlg
->SetCheckNameTooltipHdl( LINK( this, SlotManager
, RenameSlideTooltipHdl
) );
932 aNameDlg
->SetEditHelpId( HID_SD_NAMEDIALOG_PAGE
);
934 if( aNameDlg
->Execute() == RET_OK
)
936 OUString aNewName
= aNameDlg
->GetName();
937 if (aNewName
!= aPageName
)
940 RenameSlideFromDrawViewShell(
941 pSelectedPage
->GetPageNum()/2, aNewName
);
942 DBG_ASSERT( bResult
, "Couldn't rename slide or page" );
945 OUString aNewName
= aNameDlg
->GetName();
946 collectUIInformation({{"OldName", aOldName
}, {"NewName", aNewName
}}, u
"RENAME"_ustr
);
947 aNameDlg
.disposeAndClear();
949 // Tell the slide sorter about the name change (necessary for
951 mrSlideSorter
.GetController().PageNameHasChanged(
952 (pSelectedPage
->GetPageNum()-1)/2, aPageName
);
955 IMPL_LINK(SlotManager
, RenameSlideHdl
, AbstractSvxNameDialog
&, rDialog
, bool)
957 OUString aNewName
= rDialog
.GetName();
959 model::SharedPageDescriptor
pDescriptor (
960 mrSlideSorter
.GetController().GetCurrentSlideManager()->GetCurrentSlide());
961 SdPage
* pCurrentPage
= nullptr;
963 pCurrentPage
= pDescriptor
->GetPage();
965 return (pCurrentPage
!=nullptr && aNewName
== pCurrentPage
->GetName())
966 || (mrSlideSorter
.GetViewShell()
967 && mrSlideSorter
.GetViewShell()->GetDocSh()->IsNewPageNameValid( aNewName
) );
970 IMPL_STATIC_LINK_NOARG(SlotManager
, RenameSlideTooltipHdl
, AbstractSvxNameDialog
&, OUString
)
972 return SdResId(STR_TOOLTIP_RENAME
);
975 bool SlotManager::RenameSlideFromDrawViewShell( sal_uInt16 nPageId
, const OUString
& rName
)
978 SdDrawDocument
* pDocument
= mrSlideSorter
.GetModel().GetDocument();
979 if( pDocument
->GetPageByName( rName
, bOutDummy
) != SDRPAGE_NOTFOUND
)
982 SdPage
* pPageToRename
= nullptr;
984 SfxUndoManager
* pManager
= pDocument
->GetDocSh()->GetUndoManager();
986 if( mrSlideSorter
.GetModel().GetEditMode() == EditMode::Page
)
988 model::SharedPageDescriptor
pDescriptor (
989 mrSlideSorter
.GetController().GetCurrentSlideManager()->GetCurrentSlide());
991 pPageToRename
= pDescriptor
->GetPage();
993 if (pPageToRename
!= nullptr)
996 SdPage
* pUndoPage
= pPageToRename
;
997 SdrLayerAdmin
& rLayerAdmin
= pDocument
->GetLayerAdmin();
998 SdrLayerID nBackground
= rLayerAdmin
.GetLayerID(sUNO_LayerName_background
);
999 SdrLayerID nBgObj
= rLayerAdmin
.GetLayerID(sUNO_LayerName_background_objects
);
1000 SdrLayerIDSet aVisibleLayers
= pPageToRename
->TRG_GetMasterPageVisibleLayers();
1003 pManager
->AddUndoAction(
1004 std::make_unique
<ModifyPageUndoAction
>(
1005 pDocument
, pUndoPage
, rName
, pUndoPage
->GetAutoLayout(),
1006 aVisibleLayers
.IsSet( nBackground
),
1007 aVisibleLayers
.IsSet( nBgObj
)));
1010 pPageToRename
->SetName( rName
);
1012 // also rename notes-page
1013 SdPage
* pNotesPage
= pDocument
->GetSdPage( nPageId
, PageKind::Notes
);
1014 if (pNotesPage
!= nullptr)
1015 pNotesPage
->SetName (rName
);
1020 // rename MasterPage -> rename LayoutTemplate
1021 pPageToRename
= pDocument
->GetMasterSdPage( nPageId
, PageKind::Standard
);
1022 if (pPageToRename
!= nullptr)
1024 const OUString
aOldLayoutName( pPageToRename
->GetLayoutName() );
1025 pManager
->AddUndoAction( std::make_unique
<RenameLayoutTemplateUndoAction
>( pDocument
, aOldLayoutName
, rName
) );
1026 pDocument
->RenameLayoutTemplate( aOldLayoutName
, rName
);
1030 bool bSuccess
= pPageToRename
!=nullptr && ( rName
== pPageToRename
->GetName() );
1034 // user edited page names may be changed by the page so update control
1035 // aTabControl.SetPageText( nPageId, rName );
1037 // set document to modified state
1038 pDocument
->SetChanged();
1040 // inform navigator about change
1041 if (mrSlideSorter
.GetViewShell() && mrSlideSorter
.GetViewShell()->GetViewFrame())
1042 mrSlideSorter
.GetViewShell()->GetViewFrame()->GetBindings().Invalidate(
1043 SID_NAVIGATOR_STATE
, true);
1049 /** Insert a slide. The insertion position depends on a) the selection and
1050 b) the mouse position when there is no selection.
1052 When there is a selection then insertion takes place after the last
1053 slide of the selection. For this to work all but the last selected
1054 slide are deselected first.
1056 Otherwise, when there is no selection but the insertion marker is visible
1057 the slide is inserted at that position. The slide before that marker is
1060 When both the selection and the insertion marker are not visible--can
1061 that happen?--the new slide is inserted after the last slide.
1063 void SlotManager::InsertSlide (SfxRequest
& rRequest
)
1065 const sal_Int32
nInsertionIndex (GetInsertionPosition());
1067 PageSelector::BroadcastLock
aBroadcastLock (mrSlideSorter
);
1069 SdPage
* pNewPage
= nullptr;
1070 if (mrSlideSorter
.GetModel().GetEditMode() == EditMode::Page
)
1072 SlideSorterViewShell
* pShell
= dynamic_cast<SlideSorterViewShell
*>(
1073 mrSlideSorter
.GetViewShell());
1074 if (pShell
!= nullptr)
1076 pNewPage
= pShell
->CreateOrDuplicatePage (
1080 ? mrSlideSorter
.GetModel().GetPageDescriptor(nInsertionIndex
)->GetPage()
1086 // Use the API to create a new page.
1087 SdDrawDocument
* pDocument
= mrSlideSorter
.GetModel().GetDocument();
1088 rtl::Reference
<SdXImpressDocument
> xMasterPagesSupplier (
1089 pDocument
->getUnoModel());
1090 if (xMasterPagesSupplier
.is())
1092 Reference
<drawing::XDrawPages
> xMasterPages (
1093 xMasterPagesSupplier
->getMasterPages());
1094 if (xMasterPages
.is())
1096 xMasterPages
->insertNewByIndex (nInsertionIndex
+1);
1098 // Create shapes for the default layout.
1099 pNewPage
= pDocument
->GetMasterSdPage(
1100 static_cast<sal_uInt16
>(nInsertionIndex
+1), PageKind::Standard
);
1101 pNewPage
->CreateTitleAndLayout (true,true);
1105 if (pNewPage
== nullptr)
1108 // When a new page has been inserted then select it, make it the
1109 // current page, and focus it.
1110 view::SlideSorterView::DrawLock
aDrawLock (mrSlideSorter
);
1111 PageSelector::UpdateLock
aUpdateLock (mrSlideSorter
);
1112 mrSlideSorter
.GetController().GetPageSelector().DeselectAllPages();
1113 mrSlideSorter
.GetController().GetPageSelector().SelectPage(pNewPage
);
1114 collectUIInformation({{"POS", OUString::number(nInsertionIndex
+ 2)}}, u
"Insert_New_Page_or_Slide"_ustr
);
1117 void SlotManager::DuplicateSelectedSlides (SfxRequest
& rRequest
)
1119 // Create a list of the pages that are to be duplicated. The process of
1120 // duplication alters the selection.
1121 sal_Int32
nInsertPosition (0);
1122 ::std::vector
<SdPage
*> aPagesToDuplicate
;
1123 model::PageEnumeration
aSelectedPages (
1124 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter
.GetModel()));
1125 while (aSelectedPages
.HasMoreElements())
1127 model::SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
1128 if (pDescriptor
&& pDescriptor
->GetPage())
1130 aPagesToDuplicate
.push_back(pDescriptor
->GetPage());
1131 nInsertPosition
= pDescriptor
->GetPage()->GetPageNum()+2;
1135 // Duplicate the pages in aPagesToDuplicate and collect the newly
1136 // created pages in aPagesToSelect.
1137 const bool bUndo (aPagesToDuplicate
.size()>1 && mrSlideSorter
.GetView().IsUndoEnabled());
1139 mrSlideSorter
.GetView().BegUndo(SdResId(STR_INSERTPAGE
));
1141 ::std::vector
<SdPage
*> aPagesToSelect
;
1142 for(const auto& rpPage
: aPagesToDuplicate
)
1144 aPagesToSelect
.push_back(
1145 mrSlideSorter
.GetViewShell()->CreateOrDuplicatePage(
1146 rRequest
, PageKind::Standard
, rpPage
, nInsertPosition
));
1147 nInsertPosition
+= 2;
1149 aPagesToDuplicate
.clear();
1152 mrSlideSorter
.GetView().EndUndo();
1154 // Set the selection to the pages in aPagesToSelect.
1155 PageSelector
& rSelector (mrSlideSorter
.GetController().GetPageSelector());
1156 rSelector
.DeselectAllPages();
1157 for (auto const& it
: aPagesToSelect
)
1159 rSelector
.SelectPage(it
);
1162 collectUIInformation({{"POS", OUString::number(nInsertPosition
+ 2)}}, u
"Duplicate"_ustr
);
1165 void SlotManager::ChangeSlideExclusionState (
1166 const model::SharedPageDescriptor
& rpDescriptor
,
1167 const bool bExcludeSlide
)
1169 SdDrawDocument
* pDocument
= mrSlideSorter
.GetModel().GetDocument();
1170 SfxUndoManager
* pManager
= pDocument
->GetDocSh()->GetUndoManager();
1173 mrSlideSorter
.GetView().SetState(
1175 model::PageDescriptor::ST_Excluded
,
1177 pManager
->AddUndoAction(std::make_unique
<ChangeSlideExclusionStateUndoAction
>(
1178 pDocument
, rpDescriptor
, model::PageDescriptor::ST_Excluded
, !bExcludeSlide
));
1182 model::PageEnumeration
aSelectedPages (
1183 model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
1184 mrSlideSorter
.GetModel()));
1185 std::unique_ptr
<ChangeSlideExclusionStateUndoAction
> pChangeSlideExclusionStateUndoAction(
1186 new ChangeSlideExclusionStateUndoAction(pDocument
, model::PageDescriptor::ST_Excluded
,
1188 while (aSelectedPages
.HasMoreElements())
1190 model::SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
1191 mrSlideSorter
.GetView().SetState(
1193 model::PageDescriptor::ST_Excluded
,
1195 pChangeSlideExclusionStateUndoAction
->AddPageDescriptor(pDescriptor
);
1197 pManager
->AddUndoAction(std::move(pChangeSlideExclusionStateUndoAction
));
1200 SfxBindings
& rBindings (mrSlideSorter
.GetViewShell()->GetViewFrame()->GetBindings());
1201 rBindings
.Invalidate(SID_PRESENTATION
);
1202 rBindings
.Invalidate(SID_REHEARSE_TIMINGS
);
1203 rBindings
.Invalidate(SID_HIDE_SLIDE
);
1204 rBindings
.Invalidate(SID_SHOW_SLIDE
);
1205 mrSlideSorter
.GetModel().GetDocument()->SetChanged();
1208 sal_Int32
SlotManager::GetInsertionPosition() const
1210 PageSelector
& rSelector (mrSlideSorter
.GetController().GetPageSelector());
1212 // The insertion indicator is preferred. After all the user explicitly
1213 // used it to define the insertion position.
1214 if (mrSlideSorter
.GetController().GetInsertionIndicatorHandler()->IsActive())
1216 // Select the page before the insertion indicator.
1217 return mrSlideSorter
.GetController().GetInsertionIndicatorHandler()->GetInsertionPageIndex()
1221 // Is there a stored insertion position?
1222 else if (mrSlideSorter
.GetController().GetSelectionManager()->GetInsertionPosition() >= 0)
1224 return mrSlideSorter
.GetController().GetSelectionManager()->GetInsertionPosition() - 1;
1227 // Use the index of the last selected slide.
1228 else if (rSelector
.GetSelectedPageCount() > 0)
1230 for (int nIndex
=rSelector
.GetPageCount()-1; nIndex
>=0; --nIndex
)
1231 if (rSelector
.IsPageSelected(nIndex
))
1234 // We should never get here.
1236 return rSelector
.GetPageCount() - 1;
1239 // Select the last page when there is at least one page.
1240 else if (rSelector
.GetPageCount() > 0)
1242 return rSelector
.GetPageCount() - 1;
1245 // Hope for the best that CreateOrDuplicatePage() can cope with an empty
1249 // We should never get here because there has to be at least one page.
1255 void SlotManager::NotifyEditModeChange()
1257 SfxBindings
& rBindings (mrSlideSorter
.GetViewShell()->GetViewFrame()->GetBindings());
1258 rBindings
.Invalidate(SID_PRESENTATION
);
1259 rBindings
.Invalidate(SID_INSERTPAGE
);
1260 rBindings
.Invalidate(SID_DUPLICATE_PAGE
);
1265 SlideExclusionState
GetSlideExclusionState (model::PageEnumeration
& rPageSet
)
1267 SlideExclusionState
eState (UNDEFINED
);
1269 // Get toggle state of the selected pages.
1270 while (rPageSet
.HasMoreElements() && eState
!=MIXED
)
1272 const bool bState
= rPageSet
.GetNextElement()->GetPage()->IsExcluded();
1276 // Use the first selected page to set the initial value.
1277 eState
= bState
? EXCLUDED
: INCLUDED
;
1281 // The pages before where all not part of the show,
1288 // The pages before where all part of the show,
1295 // No need to change anything.
1303 } // end of anonymous namespace
1305 } // end of namespace ::sd::slidesorter::controller
1307 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */