From bde6437f72a6721810983f13829a62424de705f7 Mon Sep 17 00:00:00 2001 From: Mohit Marathe Date: Mon, 25 May 2026 11:50:15 +0000 Subject: [PATCH] sd: add .uno:RemoveSlideSectionsAndSlides Executing this command would iteratively delete all the slides in the section in reverse order via XDrawPages::remove. The deletion of slide is handled by SlideSectionManager::OnSlideRemoved, which deletes the section when all of its slides are removed. Signed-off-by: Mohit Marathe Change-Id: Idacb703f67695751ace2837bd03ce9deb8abd238 Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/3256 Reviewed-by: Pranam Lashkari Tested-by: Pranam Lashkari (cherry picked from commit 6bc6c67557fe4c2a09d0260c97b6d4c561f55c9f) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/206632 Reviewed-by: Xisco Fauli Tested-by: Jenkins --- .../Office/UI/DrawImpressCommands.xcu | 5 ++ sd/inc/SlideSectionManager.hxx | 8 ++++ sd/inc/app.hrc | 1 + sd/inc/strings.hrc | 1 + sd/sdi/SlideSorterController.sdi | 5 ++ sd/sdi/_drvwsh.sdi | 5 ++ sd/sdi/sdraw.sdi | 17 +++++++ sd/source/core/SlideSectionManager.cxx | 46 +++++++++++++++++++ .../slidesorter/controller/SlsSlotManager.cxx | 32 +++++++++++++ .../inc/controller/SlsSlotManager.hxx | 1 + sd/source/ui/view/drviews2.cxx | 26 +++++++++++ sd/source/ui/view/drviews7.cxx | 20 ++++++++ 12 files changed, 167 insertions(+) diff --git a/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu index 04f757d6e49c..a3f8703744d3 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu @@ -1244,6 +1244,11 @@ Remove Section + + + Remove Section & Slides + + Rename Section... diff --git a/sd/inc/SlideSectionManager.hxx b/sd/inc/SlideSectionManager.hxx index 605ea03ecee9..c25809a9e899 100644 --- a/sd/inc/SlideSectionManager.hxx +++ b/sd/inc/SlideSectionManager.hxx @@ -65,6 +65,14 @@ public: /// Remove a section; its slides merge into the previous section. void RemoveSection(sal_Int32 nSectionIndex); + /// Delete every slide belonging to nSectionIndex via the document's + /// XDrawPages, iterating in reverse so that the indices of the slides + /// still to be deleted stay valid. Never deletes the last remaining + /// slide in the document. The caller owns undo grouping and view + /// refresh; the now-empty section metadata is auto-erased by + /// OnSlideRemoved as the slides are removed. + void RemoveSectionSlides(sal_Int32 nSectionIndex); + /// Rename a section. void RenameSection(sal_Int32 nSectionIndex, const OUString& rNewName); diff --git a/sd/inc/app.hrc b/sd/inc/app.hrc index 83358c3d08b6..5c56ea3b3fe8 100644 --- a/sd/inc/app.hrc +++ b/sd/inc/app.hrc @@ -434,5 +434,6 @@ #define SID_RENAME_SLIDE_SECTION (SID_SD_START+455) #define SID_MOVE_SLIDE_SECTION_UP (SID_SD_START+456) #define SID_MOVE_SLIDE_SECTION_DOWN (SID_SD_START+457) +#define SID_REMOVE_SLIDE_SECTION_AND_SLIDES (SID_SD_START+458) /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/inc/strings.hrc b/sd/inc/strings.hrc index d03bceaa2e9f..7d5b99da8dd9 100644 --- a/sd/inc/strings.hrc +++ b/sd/inc/strings.hrc @@ -499,5 +499,6 @@ #define STR_UNDO_REMOVE_SLIDE_SECTION NC_("STR_UNDO_REMOVE_SLIDE_SECTION", "Remove section") #define STR_UNDO_RENAME_SLIDE_SECTION NC_("STR_UNDO_RENAME_SLIDE_SECTION", "Rename section") #define STR_UNDO_MOVE_SLIDE_SECTION NC_("STR_UNDO_MOVE_SLIDE_SECTION", "Move section") +#define STR_UNDO_REMOVE_SLIDE_SECTION_AND_SLIDES NC_("STR_UNDO_REMOVE_SLIDE_SECTION_AND_SLIDES", "Remove section and slides") /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/sdi/SlideSorterController.sdi b/sd/sdi/SlideSorterController.sdi index d05ef39ce39a..dba06f524eab 100644 --- a/sd/sdi/SlideSorterController.sdi +++ b/sd/sdi/SlideSorterController.sdi @@ -111,6 +111,11 @@ interface SlideSorterView ExecMethod = FuTemporary ; StateMethod = GetMenuState ; ] + SID_REMOVE_SLIDE_SECTION_AND_SLIDES + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] SID_RENAME_SLIDE_SECTION [ ExecMethod = FuTemporary ; diff --git a/sd/sdi/_drvwsh.sdi b/sd/sdi/_drvwsh.sdi index 1e9df3ef07aa..73dbc6e02b54 100644 --- a/sd/sdi/_drvwsh.sdi +++ b/sd/sdi/_drvwsh.sdi @@ -202,6 +202,11 @@ interface DrawView ExecMethod = FuTemporary ; StateMethod = GetMenuState ; ] + SID_REMOVE_SLIDE_SECTION_AND_SLIDES + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] SID_RENAME_SLIDE_SECTION [ ExecMethod = FuTemporary ; diff --git a/sd/sdi/sdraw.sdi b/sd/sdi/sdraw.sdi index 0573b283b5e3..3e35df6eb7fd 100644 --- a/sd/sdi/sdraw.sdi +++ b/sd/sdi/sdraw.sdi @@ -4300,6 +4300,23 @@ SfxVoidItem RemoveSlideSection SID_REMOVE_SLIDE_SECTION GroupId = SfxGroupId::Format; ] +SfxVoidItem RemoveSlideSectionAndSlides SID_REMOVE_SLIDE_SECTION_AND_SLIDES +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = TRUE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Format; +] + SfxVoidItem RenameSlideSection SID_RENAME_SLIDE_SECTION (SfxInt32Item SectionIndex SID_RENAME_SLIDE_SECTION, SfxStringItem Name SID_RENAMEPAGE) [ diff --git a/sd/source/core/SlideSectionManager.cxx b/sd/source/core/SlideSectionManager.cxx index 64c9c9b4e24f..6a1dc1488a99 100644 --- a/sd/source/core/SlideSectionManager.cxx +++ b/sd/source/core/SlideSectionManager.cxx @@ -10,9 +10,12 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -195,6 +198,49 @@ void SlideSectionManager::RemoveSection(sal_Int32 nSectionIndex) maSections.erase(maSections.begin() + nSectionIndex); } +void SlideSectionManager::RemoveSectionSlides(sal_Int32 nSectionIndex) +{ + if (nSectionIndex < 0 || nSectionIndex >= static_cast(maSections.size())) + return; + + // Compute the [nStart, nEnd) range of slides in this section. The + // section list is sorted by start index, so the next section's start + // (or the document's slide count) marks the end of this section. + const sal_Int32 nStart = maSections[nSectionIndex].mnStartIndex; + const sal_Int32 nEnd = (nSectionIndex + 1 < static_cast(maSections.size())) + ? maSections[nSectionIndex + 1].mnStartIndex + : static_cast(mrDoc.GetSdPageCount(PageKind::Standard)); + + try + { + rtl::Reference xModel(mrDoc.getUnoModel()); + if (!xModel.is()) + return; + + css::uno::Reference xPages(xModel->getDrawPages(), + css::uno::UNO_SET_THROW); + + // Iterate in reverse so that each remove() does not shift the + // indices of the slides we still have to delete. OnSlideRemoved + // fires per page delete and auto-erases the now-empty section + // metadata, so we deliberately do not call RemoveSection() here. + for (sal_Int32 i = nEnd - 1; i >= nStart; --i) + { + // Do not delete the last slide in the document. + if (xPages->getCount() <= 1) + break; + + css::uno::Reference xPage(xPages->getByIndex(i), + css::uno::UNO_QUERY_THROW); + xPages->remove(xPage); + } + } + catch (const css::uno::Exception&) + { + TOOLS_WARN_EXCEPTION("sd", "SlideSectionManager::RemoveSectionSlides()"); + } +} + void SlideSectionManager::RenameSection(sal_Int32 nSectionIndex, const OUString& rNewName) { if (nSectionIndex < 0 || nSectionIndex >= static_cast(maSections.size())) diff --git a/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx b/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx index c75272214e87..7c2204f19087 100644 --- a/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx +++ b/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx @@ -294,6 +294,11 @@ void SlotManager::FuTemporary (SfxRequest& rRequest) rRequest.Done(); break; + case SID_REMOVE_SLIDE_SECTION_AND_SLIDES: + RemoveSectionAndSlides(); + rRequest.Done(); + break; + case SID_RENAME_SLIDE_SECTION: RenameSection(); rRequest.Done(); @@ -701,6 +706,7 @@ void SlotManager::GetMenuState (SfxItemSet& rSet) if (rSet.GetItemState(SID_ADD_SLIDE_SECTION) == SfxItemState::DEFAULT || rSet.GetItemState(SID_REMOVE_SLIDE_SECTION) == SfxItemState::DEFAULT + || rSet.GetItemState(SID_REMOVE_SLIDE_SECTION_AND_SLIDES) == SfxItemState::DEFAULT || rSet.GetItemState(SID_RENAME_SLIDE_SECTION) == SfxItemState::DEFAULT || rSet.GetItemState(SID_MOVE_SLIDE_SECTION_UP) == SfxItemState::DEFAULT || rSet.GetItemState(SID_MOVE_SLIDE_SECTION_DOWN) == SfxItemState::DEFAULT) @@ -710,6 +716,7 @@ void SlotManager::GetMenuState (SfxItemSet& rSet) { rSet.DisableItem(SID_ADD_SLIDE_SECTION); rSet.DisableItem(SID_REMOVE_SLIDE_SECTION); + rSet.DisableItem(SID_REMOVE_SLIDE_SECTION_AND_SLIDES); rSet.DisableItem(SID_RENAME_SLIDE_SECTION); rSet.DisableItem(SID_MOVE_SLIDE_SECTION_UP); rSet.DisableItem(SID_MOVE_SLIDE_SECTION_DOWN); @@ -736,6 +743,7 @@ void SlotManager::GetMenuState (SfxItemSet& rSet) if (!rMgr.IsSectionStart(nPageIndex)) { rSet.DisableItem(SID_REMOVE_SLIDE_SECTION); + rSet.DisableItem(SID_REMOVE_SLIDE_SECTION_AND_SLIDES); rSet.DisableItem(SID_RENAME_SLIDE_SECTION); rSet.DisableItem(SID_MOVE_SLIDE_SECTION_UP); rSet.DisableItem(SID_MOVE_SLIDE_SECTION_DOWN); @@ -1208,6 +1216,30 @@ void SlotManager::RemoveSection() } } +void SlotManager::RemoveSectionAndSlides() +{ + auto oCtx = GetSelectedSectionContext(mrSlideSorter); + if (!oCtx) + return; + if (oCtx->nSectionIndex < 0 || !oCtx->pMgr->IsSectionStart(oCtx->nPageIndex)) + return; + + SdDrawDocument* pDoc = mrSlideSorter.GetModel().GetDocument(); + if (!pDoc) + return; + + const bool bUndo = pDoc->IsUndoEnabled(); + if (bUndo) + pDoc->BegUndo(SdResId(STR_UNDO_REMOVE_SLIDE_SECTION_AND_SLIDES)); + + oCtx->pMgr->RemoveSectionSlides(oCtx->nSectionIndex); + + if (bUndo) + pDoc->EndUndo(); + + mrSlideSorter.GetController().HandleModelChange(); +} + void SlotManager::RenameSection() { auto oCtx = GetSelectedSectionContext(mrSlideSorter); diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx index 04b8d62695a2..82e7e92ad638 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx @@ -89,6 +89,7 @@ private: void AddSection(); void RemoveSection(); + void RemoveSectionAndSlides(); void RenameSection(); void MoveSectionUp(); void MoveSectionDown(); diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx index 03650a6d187d..ed8f5b1cea9a 100644 --- a/sd/source/ui/view/drviews2.cxx +++ b/sd/source/ui/view/drviews2.cxx @@ -1613,6 +1613,32 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) } break; + case SID_REMOVE_SLIDE_SECTION_AND_SLIDES: + { + SdPage* pPage = GetActualPage(); + if (pPage) + { + sal_uInt16 nPage = (pPage->GetPageNum() - 1) / 2; + sd::SlideSectionManager& rMgr = GetDoc()->GetSectionManager(); + sal_Int32 nSectionIdx = rMgr.GetSectionIndexForSlide(nPage); + if (nSectionIdx >= 0 && rMgr.IsSectionStart(nPage)) + { + const bool bUndo = GetDoc()->IsUndoEnabled(); + if (bUndo) + GetView()->BegUndo( + SdResId(STR_UNDO_REMOVE_SLIDE_SECTION_AND_SLIDES)); + + rMgr.RemoveSectionSlides(nSectionIdx); + + if (bUndo) + GetView()->EndUndo(); + GetDocSh()->SetModified(); + ResetActualPage(); + } + } + } + break; + case SID_RENAME_SLIDE_SECTION: { sd::SlideSectionManager& rMgr = GetDoc()->GetSectionManager(); diff --git a/sd/source/ui/view/drviews7.cxx b/sd/source/ui/view/drviews7.cxx index d6c8dd0dacfd..e7d87e5a2949 100644 --- a/sd/source/ui/view/drviews7.cxx +++ b/sd/source/ui/view/drviews7.cxx @@ -88,6 +88,7 @@ #include #include #include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -1649,6 +1650,25 @@ void DrawViewShell::GetMenuState( SfxItemSet &rSet ) if (!SdModule::get()->pTransferClip) rSet.DisableItem(SID_PASTE_SLIDE); + if (rSet.GetItemState(SID_REMOVE_SLIDE_SECTION) == SfxItemState::DEFAULT + || rSet.GetItemState(SID_REMOVE_SLIDE_SECTION_AND_SLIDES) == SfxItemState::DEFAULT) + { + bool bDisable = true; + SdPage* pPage = GetActualPage(); + if (pPage && GetDoc()) + { + sal_uInt16 nPageIdx = (pPage->GetPageNum() - 1) / 2; + sd::SlideSectionManager& rMgr = GetDoc()->GetSectionManager(); + if (rMgr.IsSectionStart(nPageIdx)) + bDisable = false; + } + if (bDisable) + { + rSet.DisableItem(SID_REMOVE_SLIDE_SECTION); + rSet.DisableItem(SID_REMOVE_SLIDE_SECTION_AND_SLIDES); + } + } + GetModeSwitchingMenuState (rSet); }