officecfg/registry/data/org/openoffice/Office/UI/ImpressWindowState.xcu | 10 +++ sd/UIConfig_simpress.mk | 2 sd/inc/drawdoc.hxx | 2 sd/inc/sdpage.hxx | 4 + sd/source/core/drawdoc2.cxx | 17 ++++++ sd/source/core/sdpage.cxx | 2 sd/source/ui/slidesorter/controller/SlideSorterController.cxx | 14 ++++- sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx | 27 +++++++++- sd/source/ui/view/ViewClipboard.cxx | 5 + sd/source/ui/view/drviews7.cxx | 11 ++++ sd/source/ui/view/viewshe3.cxx | 2 sd/uiconfig/simpress/popupmenu/pagepanecanvas.xml | 13 ++++ sd/uiconfig/simpress/popupmenu/pagepanecanvasmaster.xml | 13 ++++ 13 files changed, 118 insertions(+), 4 deletions(-)
New commits: commit b058526f16724d72f87810c438ac0cccb2ca16ff Author: Mohit Marathe <[email protected]> AuthorDate: Tue Oct 21 10:55:32 2025 +0530 Commit: Michael Stahl <[email protected]> CommitDate: Thu Nov 6 18:57:58 2025 +0100 sd: make sure that canvas page remains as the last page This commit restricts the following operations: - duplicating canvas page - moving canvas page up - inserting a page after the canvas page - including canvas page in the slideshow Also, prevent deleting the only non-canvas page. Signed-off-by: Mohit Marathe <[email protected]> Change-Id: I8050dfc9836719f345e0f5349f25b62cd164344d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192769 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Michael Stahl <[email protected]> diff --git a/officecfg/registry/data/org/openoffice/Office/UI/ImpressWindowState.xcu b/officecfg/registry/data/org/openoffice/Office/UI/ImpressWindowState.xcu index 8475ac8c9847..2532a49ea2e8 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/ImpressWindowState.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/ImpressWindowState.xcu @@ -125,6 +125,11 @@ <value xml:lang="en-US">Slide Sorter/Pane</value> </prop> </node> + <node oor:name="private:resource/popupmenu/pagepanecanvas" oor:op="replace"> + <prop oor:name="UIName" oor:type="xs:string"> + <value xml:lang="en-US">Slide Sorter/Pane (Canvas)</value> + </prop> + </node> <node oor:name="private:resource/popupmenu/pagepanenosel" oor:op="replace"> <prop oor:name="UIName" oor:type="xs:string"> <value xml:lang="en-US">Slide Sorter/Pane (no selection)</value> @@ -135,6 +140,11 @@ <value xml:lang="en-US">Master Slide Sorter/Pane</value> </prop> </node> + <node oor:name="private:resource/popupmenu/pagepanecanvasmaster" oor:op="replace"> + <prop oor:name="UIName" oor:type="xs:string"> + <value xml:lang="en-US">Master Slide Sorter/Pane (Canvas)</value> + </prop> + </node> <node oor:name="private:resource/popupmenu/pagepanenoselmaster" oor:op="replace"> <prop oor:name="UIName" oor:type="xs:string"> <value xml:lang="en-US">Master Slide Sorter/Pane (no selection)</value> diff --git a/sd/UIConfig_simpress.mk b/sd/UIConfig_simpress.mk index c70fc3bc9cb3..ad21ed0e48fb 100644 --- a/sd/UIConfig_simpress.mk +++ b/sd/UIConfig_simpress.mk @@ -37,9 +37,11 @@ $(eval $(call gb_UIConfig_add_popupmenufiles,modules/simpress,\ sd/uiconfig/simpress/popupmenu/oleobject \ sd/uiconfig/simpress/popupmenu/outline \ sd/uiconfig/simpress/popupmenu/pagepanemaster \ + sd/uiconfig/simpress/popupmenu/pagepanecanvasmaster \ sd/uiconfig/simpress/popupmenu/pagepanenoselmaster \ sd/uiconfig/simpress/popupmenu/pagepanenosel \ sd/uiconfig/simpress/popupmenu/pagepane \ + sd/uiconfig/simpress/popupmenu/pagepanecanvas \ sd/uiconfig/simpress/popupmenu/pagetab \ sd/uiconfig/simpress/popupmenu/page \ sd/uiconfig/simpress/popupmenu/table \ diff --git a/sd/inc/drawdoc.hxx b/sd/inc/drawdoc.hxx index b13749c6fe6d..f08c9cdcabbe 100644 --- a/sd/inc/drawdoc.hxx +++ b/sd/inc/drawdoc.hxx @@ -1032,7 +1032,7 @@ public: bool bIsPageObj, const sal_Int32 nInsertPosition); - SAL_DLLPRIVATE bool HasCanvasPage() const { return mpCanvasPage != nullptr; } + SAL_DLLPRIVATE bool HasCanvasPage() const { return mpCanvasPage.is(); } SAL_DLLPRIVATE sal_uInt16 GetOrInsertCanvasPage (); diff --git a/sd/inc/sdpage.hxx b/sd/inc/sdpage.hxx index f873efc819e8..a338a880ad2b 100644 --- a/sd/inc/sdpage.hxx +++ b/sd/inc/sdpage.hxx @@ -123,6 +123,7 @@ friend class sd::UndoAttrObject; sal_uInt16 mnPaperBin; ///< PaperBin SdPageLink* mpPageLink; ///< Page link (at left sides only) bool mbIsCanvasPage; ///< whether the page is a canvas page + bool mbIsCanvasMasterPage; ///< whether it is the master page of canvas page // PDF link annotations for read-only pdfium std::vector<std::pair<basegfx::B2DRectangle, OUString>> maLinkAnnotations; @@ -405,6 +406,9 @@ public: bool IsCanvasPage() const { return mbIsCanvasPage; } void SetCanvasPage() { mbIsCanvasPage = true; } + bool IsCanvasMasterPage() const { return mbIsCanvasMasterPage; } + void SetCanvasMasterPage() { mbIsCanvasMasterPage = true; } + private: bool mbIsPrecious; diff --git a/sd/source/core/drawdoc2.cxx b/sd/source/core/drawdoc2.cxx index a59e651094c3..a32499255b55 100644 --- a/sd/source/core/drawdoc2.cxx +++ b/sd/source/core/drawdoc2.cxx @@ -486,11 +486,16 @@ void SdDrawDocument::DeletePage(sal_uInt16 nPgNum) // Remove page rtl::Reference<SdrPage> SdDrawDocument::RemovePage(sal_uInt16 nPgNum) { + // Do not remove the only non-canvas page + if (HasCanvasPage() && GetSdPageCount(PageKind::Standard) == 2) + return nullptr; rtl::Reference<SdrPage> pPage = FmFormModel::RemovePage(nPgNum); bool bLast = ((nPgNum+1)/2 == (GetPageCount()+1)/2); auto pSdPage = static_cast<SdPage*>(pPage.get()); + if (pSdPage->IsCanvasPage()) + mpCanvasPage = nullptr; pSdPage->DisconnectLink(); ReplacePageInCustomShows( pSdPage, nullptr ); UpdatePageObjectsInNotes(nPgNum); @@ -1221,6 +1226,8 @@ sal_uInt16 SdDrawDocument::CreatePage ( bool bIsPageObj, const sal_Int32 nInsertPosition) { + if (pActualPage->IsCanvasPage()) + return 0xffff; SdPage* pPreviousStandardPage; SdPage* pPreviousNotesPage; rtl::Reference<SdPage> pStandardPage; @@ -1304,6 +1311,9 @@ sal_uInt16 SdDrawDocument::DuplicatePage (sal_uInt16 nPageNum) // Get current page SdPage* pActualPage = GetSdPage(nPageNum, ePageKind); + if (pActualPage->IsCanvasPage()) + return 0xffff; + // Get background flags SdrLayerAdmin& rLayerAdmin = GetLayerAdmin(); SdrLayerID aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background); @@ -1327,6 +1337,8 @@ sal_uInt16 SdDrawDocument::DuplicatePage ( bool bIsPageObj, const sal_Int32 nInsertPosition) { + if (pActualPage->IsCanvasPage()) + return 0xffff; SdPage* pPreviousStandardPage; SdPage* pPreviousNotesPage; rtl::Reference<SdPage> pStandardPage; @@ -1470,6 +1482,8 @@ sal_uInt16 SdDrawDocument::GetOrInsertCanvasPage() sal_uInt16 nCanvasPageNum = CreatePage(pLastStandardPage, PageKind::Standard, u"Canvas Page"_ustr, u"Canvas notes page"_ustr, AutoLayout::AUTOLAYOUT_NONE, AutoLayout::AUTOLAYOUT_NONE, false, true, pLastStandardPage->GetPageNum() + 2); SdPage* pCanvasPage = GetSdPage(nCanvasPageNum, PageKind::Standard); + if (!pCanvasPage) + return 0xffff; const Size aCanvasSize(500000, 500000); @@ -1477,6 +1491,9 @@ sal_uInt16 SdDrawDocument::GetOrInsertCanvasPage() pCanvasPage->SetCanvasPage(); mpCanvasPage = pCanvasPage; + SdPage* pMasterCanvas = static_cast<SdPage*>(&pCanvasPage->TRG_GetMasterPage()); + pMasterCanvas->SetCanvasMasterPage(); + populatePagePreviewsGrid(); return pCanvasPage->GetPageNum() / 2; diff --git a/sd/source/core/sdpage.cxx b/sd/source/core/sdpage.cxx index 386fc9bf930d..9df568ffb7fe 100644 --- a/sd/source/core/sdpage.cxx +++ b/sd/source/core/sdpage.cxx @@ -121,6 +121,8 @@ SdPage::SdPage(SdDrawDocument& rNewDoc, bool bMasterPage) , meCharSet(osl_getThreadTextEncoding()) , mnPaperBin(PAPERBIN_PRINTER_SETTINGS) , mpPageLink(nullptr) +, mbIsCanvasPage(false) +, mbIsCanvasMasterPage(false) , mnTransitionType(0) , mnTransitionSubtype(0) , mbTransitionDirection(true) diff --git a/sd/source/ui/slidesorter/controller/SlideSorterController.cxx b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx index 1589488dd6f8..9675ed1077ba 100644 --- a/sd/source/ui/slidesorter/controller/SlideSorterController.cxx +++ b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx @@ -302,12 +302,22 @@ bool SlideSorterController::Command ( if (mrModel.GetEditMode() == EditMode::Page) { if (pPage != nullptr) - aPopupId = "pagepane"; + { + if (pPage->IsCanvasPage()) + aPopupId = "pagepanecanvas"; + else + aPopupId = "pagepane"; + } else aPopupId = "pagepanenosel"; } else if (pPage != nullptr) - aPopupId = "pagepanemaster"; + { + if (pPage->IsCanvasMasterPage()) + aPopupId = "pagepanecanvasmaster"; + else + aPopupId = "pagepanemaster"; + } else aPopupId = "pagepanenoselmaster"; diff --git a/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx b/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx index e4f7a34fd05d..ef62841fd98e 100644 --- a/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx +++ b/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx @@ -797,6 +797,13 @@ void SlideSorterViewShell::GetStateMovePageFirst (SfxItemSet& rSet) rSet.DisableItem( SID_MOVE_PAGE_FIRST ); rSet.DisableItem( SID_MOVE_PAGE_UP ); } + + if (GetDoc()->HasCanvasPage()) + if (firstSelectedPageNo == GetDoc()->GetSdPageCount(PageKind::Standard) - 1) + { + rSet.DisableItem( SID_MOVE_PAGE_FIRST ); + rSet.DisableItem( SID_MOVE_PAGE_UP ); + } } void SlideSorterViewShell::ExecMovePageUp (SfxRequest& /*rReq*/) @@ -819,6 +826,10 @@ void SlideSorterViewShell::ExecMovePageUp (SfxRequest& /*rReq*/) if (firstSelectedPageNo == 0) return; + if (GetDoc()->HasCanvasPage()) + if (firstSelectedPageNo == GetDoc()->GetSdPageCount(PageKind::Standard) - 1) + return; + // Move pages before firstSelectedPageNo - 1 (so after firstSelectedPageNo - 2), // remembering that -1 means at first, which is good. GetDoc()->MoveSelectedPages( firstSelectedPageNo - 2 ); @@ -848,6 +859,9 @@ void SlideSorterViewShell::ExecMovePageDown (SfxRequest& /*rReq*/) lastSelectedPageNo = (lastSelectedPageNo - 1) / 2; if (lastSelectedPageNo == nNoOfPages - 1) return; + if (GetDoc()->HasCanvasPage()) + if (lastSelectedPageNo == nNoOfPages - 2) + return; // Move to position after lastSelectedPageNo GetDoc()->MoveSelectedPages( lastSelectedPageNo + 1 ); @@ -874,7 +888,10 @@ void SlideSorterViewShell::ExecMovePageLast (SfxRequest& /*rReq*/) sal_uInt16 nNoOfPages = GetDoc()->GetSdPageCount(PageKind::Standard); // Move to position after last page No (=Number of pages - 1) - GetDoc()->MoveSelectedPages( nNoOfPages - 1 ); + if (!GetDoc()->HasCanvasPage()) + GetDoc()->MoveSelectedPages( nNoOfPages - 1 ); + else + GetDoc()->MoveSelectedPages( nNoOfPages - 2 ); PostMoveSlidesActions(xSelection); } @@ -906,6 +923,14 @@ void SlideSorterViewShell::GetStateMovePageLast (SfxItemSet& rSet) rSet.DisableItem( SID_MOVE_PAGE_LAST ); rSet.DisableItem( SID_MOVE_PAGE_DOWN ); } + if (GetDoc()->HasCanvasPage()) + { + if (lastSelectedPageNo == nNoOfPages - 2) + { + rSet.DisableItem( SID_MOVE_PAGE_LAST ); + rSet.DisableItem( SID_MOVE_PAGE_DOWN ); + } + } } void SlideSorterViewShell::PostMoveSlidesActions(const std::shared_ptr<SlideSorterViewShell::PageSelection> &rpSelection) diff --git a/sd/source/ui/view/ViewClipboard.cxx b/sd/source/ui/view/ViewClipboard.cxx index 66af08ba2bb8..14adb70ca32e 100644 --- a/sd/source/ui/view/ViewClipboard.cxx +++ b/sd/source/ui/view/ViewClipboard.cxx @@ -172,6 +172,11 @@ sal_uInt16 ViewClipboard::DetermineInsertPosition () if( pPage->IsSelected() ) nInsertPos = nPage * 2 + 3; } + if (rDoc.HasCanvasPage()) + { + if (nInsertPos == rDoc.GetPageCount()) + nInsertPos = rDoc.GetPageCount() - 2; + } return nInsertPos; } diff --git a/sd/source/ui/view/drviews7.cxx b/sd/source/ui/view/drviews7.cxx index 8857bab914b2..be89ec0e5c5e 100644 --- a/sd/source/ui/view/drviews7.cxx +++ b/sd/source/ui/view/drviews7.cxx @@ -850,6 +850,17 @@ void DrawViewShell::GetMenuState( SfxItemSet &rSet ) rSet.DisableItem (SID_DELETE_MASTER_PAGE); rSet.DisableItem (SID_RENAME_MASTER_PAGE); rSet.DisableItem (SID_CLOSE_MASTER_VIEW); + + if (mpActualPage->IsCanvasPage()) + { + rSet.DisableItem(SID_INSERTPAGE); + rSet.DisableItem(SID_INSERTPAGE_QUICK); + rSet.DisableItem(SID_INSERTFILE); + rSet.DisableItem(SID_DUPLICATE_PAGE); + rSet.DisableItem(SID_PRESENTATION_LAYOUT); + rSet.DisableItem(SID_HIDE_SLIDE); + rSet.DisableItem(SID_SHOW_SLIDE); + } } else { diff --git a/sd/source/ui/view/viewshe3.cxx b/sd/source/ui/view/viewshe3.cxx index a722aef10fe3..c60a894b25e0 100644 --- a/sd/source/ui/view/viewshe3.cxx +++ b/sd/source/ui/view/viewshe3.cxx @@ -164,6 +164,8 @@ SdPage* ViewShell::CreateOrDuplicatePage ( SdPage* pPage, const sal_Int32 nInsertPosition) { + if (pPage->IsCanvasPage()) + return nullptr; sal_uInt16 nSId = rRequest.GetSlot(); SdDrawDocument* pDocument = GetDoc(); SdrLayerAdmin& rLayerAdmin = pDocument->GetLayerAdmin(); diff --git a/sd/uiconfig/simpress/popupmenu/pagepanecanvas.xml b/sd/uiconfig/simpress/popupmenu/pagepanecanvas.xml new file mode 100644 index 000000000000..0cff10845b42 --- /dev/null +++ b/sd/uiconfig/simpress/popupmenu/pagepanecanvas.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * +--> +<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu"> + <menu:menuitem menu:id=".uno:RenameSlide"/> + <menu:menuitem menu:id=".uno:DeleteSlide"/> +</menu:menupopup> diff --git a/sd/uiconfig/simpress/popupmenu/pagepanecanvasmaster.xml b/sd/uiconfig/simpress/popupmenu/pagepanecanvasmaster.xml new file mode 100644 index 000000000000..c6d0366c333f --- /dev/null +++ b/sd/uiconfig/simpress/popupmenu/pagepanecanvasmaster.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * +--> +<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu"> + <menu:menuitem menu:id=".uno:DeleteMasterPage"/> + <menu:menuitem menu:id=".uno:RenameMasterPage"/> +</menu:menupopup>
