sd/inc/drawdoc.hxx | 8 - sd/inc/pres.hxx | 1 sd/inc/sdpage.hxx | 2 sd/source/core/drawdoc2.cxx | 124 ++++++++++++++++- sd/source/core/sdpage.cxx | 20 ++ sd/source/ui/slidesorter/controller/SlsSlotManager.cxx | 2 sd/source/ui/unoidl/unopage.cxx | 3 sd/source/ui/view/drviews2.cxx | 2 8 files changed, 152 insertions(+), 10 deletions(-)
New commits: commit be59f89eecfdb82faa572f80e53ca7ad53521b52 Author: Mohit Marathe <[email protected]> AuthorDate: Tue Oct 21 10:48:17 2025 +0530 Commit: Michael Stahl <[email protected]> CommitDate: Mon Jan 12 19:14:09 2026 +0100 sd: insert or remove the page preview from canvas page when the corresponding page has been inserted or removed Signed-off-by: Mohit Marathe <[email protected]> Change-Id: I4f9309a77a960814a85f8a015e3719ee7a0623b4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192768 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Michael Stahl <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196795 Tested-by: Jenkins diff --git a/sd/inc/drawdoc.hxx b/sd/inc/drawdoc.hxx index fdb41267ab66..bb485147e9fb 100644 --- a/sd/inc/drawdoc.hxx +++ b/sd/inc/drawdoc.hxx @@ -1001,6 +1001,8 @@ public: bool bIsPageObj, const sal_Int32 nInsertPosition); + SAL_DLLPRIVATE bool HasCanvasPage() const { return mpCanvasPage != nullptr; } + SAL_DLLPRIVATE sal_uInt16 GetOrInsertCanvasPage (); /** return the document fonts for latin, cjk and ctl according to the current @@ -1139,10 +1141,8 @@ private: bool bIsPageBack, bool bIsPageObj); - SAL_DLLPRIVATE bool hasCanvasPage() const { return mpCanvasPage != nullptr; } - SAL_DLLPRIVATE void populatePagePreviewsGrid(); - SAL_DLLPRIVATE void updateCanvasPreviewsGrid(); + SAL_DLLPRIVATE void updatePagePreviewsGrid(SdPage* pPage); SAL_DLLPRIVATE virtual void PageListChanged() override; SAL_DLLPRIVATE virtual void MasterPageListChanged() override; diff --git a/sd/source/core/drawdoc2.cxx b/sd/source/core/drawdoc2.cxx index 19ae5cf93bcd..03f1ceab22f6 100644 --- a/sd/source/core/drawdoc2.cxx +++ b/sd/source/core/drawdoc2.cxx @@ -445,21 +445,22 @@ void SdDrawDocument::InsertPage(SdrPage* pPage, sal_uInt16 nPos) FmFormModel::InsertPage(pPage, nPos); - static_cast<SdPage*>(pPage)->ConnectLink(); + SdPage* pSdPage = static_cast<SdPage*>(pPage); + pSdPage->ConnectLink(); UpdatePageObjectsInNotes(nPos); if (!bLast) - UpdatePageRelativeURLs(static_cast<SdPage*>( pPage ), nPos, 1); + UpdatePageRelativeURLs(pSdPage, nPos, 1); - if (comphelper::LibreOfficeKit::isActive() && static_cast<SdPage*>(pPage)->GetPageKind() == PageKind::Standard) + if (comphelper::LibreOfficeKit::isActive() && pSdPage->GetPageKind() == PageKind::Standard) { SdXImpressDocument* pDoc = getUnoModel(); SfxLokHelper::notifyDocumentSizeChangedAllViews(pDoc); } - if (hasCanvasPage()) - updateCanvasPreviewsGrid(); + if (HasCanvasPage()) + updatePagePreviewsGrid(pSdPage); } // Override SfxBaseModel::getUnoModel and return a more concrete type @@ -475,8 +476,11 @@ void SdDrawDocument::DeletePage(sal_uInt16 nPgNum) UpdatePageObjectsInNotes(nPgNum); - if (hasCanvasPage()) - updateCanvasPreviewsGrid(); + // if (HasCanvasPage()) + // { + // SdPage* pPage = static_cast<SdPage*>(GetPage(nPgNum)); + // updatePagePreviewsGrid(pPage); + // } } // Remove page @@ -500,8 +504,8 @@ rtl::Reference<SdrPage> SdDrawDocument::RemovePage(sal_uInt16 nPgNum) SfxLokHelper::notifyDocumentSizeChangedAllViews(pDoc); } - if (hasCanvasPage()) - updateCanvasPreviewsGrid(); + if (HasCanvasPage()) + updatePagePreviewsGrid(pSdPage); return pPage; } @@ -1456,7 +1460,7 @@ void SdDrawDocument::SetupNewPage ( sal_uInt16 SdDrawDocument::GetOrInsertCanvasPage() { - if (hasCanvasPage()) + if (HasCanvasPage()) return mpCanvasPage->GetPageNum() / 2; sal_uInt16 nLastPageNum = GetSdPageCount(PageKind::Standard); @@ -1543,10 +1547,39 @@ void SdDrawDocument::populatePagePreviewsGrid() } } -void SdDrawDocument::updateCanvasPreviewsGrid() +void SdDrawDocument::updatePagePreviewsGrid(SdPage* pPage) { - SdrPage* pPage = mpCanvasPage.get(); - pPage->ClearSdrObjList(); - populatePagePreviewsGrid(); + SdrObjList* pObjList = mpCanvasPage.get(); + sal_uInt16 nTotalPreviews = 0; + sal_uInt16 nPageCnt = GetSdPageCount(PageKind::Standard) - 1; // do not count canvas page + + std::vector<SdrObject*> aToRemove; + SdrObjListIter aIter(pObjList, SdrIterMode::Flat); + for (SdrObject* pObj = aIter.Next(); pObj; pObj = aIter.Next()) + { + if (pObj->GetObjIdentifier() == SdrObjKind::Page) + { + nTotalPreviews++; + SdrPageObj* pPageObj = static_cast<SdrPageObj*>(pObj); + if (pPage == pPageObj->GetReferencedPage()) + { + aToRemove.push_back(pObj); + } + } + } + for (SdrObject* pObject : aToRemove) + pObjList->RemoveObject(pObject->GetOrdNum()); + + // page inserted + if (nTotalPreviews < nPageCnt) + { + const sal_uInt16 nPageNum = pPage->GetPageNum(); + const ::tools::Long nPreviewWidth = pPage->GetWidth() / 5; + const ::tools::Long nPreviewHeight = pPage->GetHeight() / 5; + const ::tools::Long nX = (mpCanvasPage->GetWidth() - nPreviewWidth) / 2; + const ::tools::Long nY = (mpCanvasPage->GetHeight() - nPreviewHeight) / 2; + + mpCanvasPage->CreatePresObj(PresObjKind::PagePreview, true, ::tools::Rectangle(Point(nX,nY), Size(nPreviewWidth, nPreviewHeight)), OUString(), nPageNum); + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 81910d315dcda70d62a9b1043a5717e974092415 Author: Mohit Marathe <[email protected]> AuthorDate: Mon Oct 13 20:36:55 2025 +0530 Commit: Michael Stahl <[email protected]> CommitDate: Mon Jan 12 19:14:00 2026 +0100 sd: populate page previews grid in canvas page Signed-off-by: Mohit Marathe <[email protected]> Change-Id: I9058a857cad403b78c20e3f771e1531d7f641a38 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192767 Reviewed-by: Michael Stahl <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196794 Tested-by: Jenkins diff --git a/sd/inc/drawdoc.hxx b/sd/inc/drawdoc.hxx index db7656d450b1..fdb41267ab66 100644 --- a/sd/inc/drawdoc.hxx +++ b/sd/inc/drawdoc.hxx @@ -413,6 +413,8 @@ private: sal_Int32 mnImagePreferredDPI; + rtl::Reference<SdPage> mpCanvasPage; + SAL_DLLPRIVATE virtual css::uno::Reference< css::frame::XModel > createUnoModel() override; public: @@ -999,8 +1001,7 @@ public: bool bIsPageObj, const sal_Int32 nInsertPosition); - - SAL_DLLPRIVATE sal_uInt16 InsertCanvasPage (); + SAL_DLLPRIVATE sal_uInt16 GetOrInsertCanvasPage (); /** return the document fonts for latin, cjk and ctl according to the current languages set at this document */ @@ -1138,6 +1139,11 @@ private: bool bIsPageBack, bool bIsPageObj); + SAL_DLLPRIVATE bool hasCanvasPage() const { return mpCanvasPage != nullptr; } + + SAL_DLLPRIVATE void populatePagePreviewsGrid(); + SAL_DLLPRIVATE void updateCanvasPreviewsGrid(); + SAL_DLLPRIVATE virtual void PageListChanged() override; SAL_DLLPRIVATE virtual void MasterPageListChanged() override; }; diff --git a/sd/inc/pres.hxx b/sd/inc/pres.hxx index ab2b44adf6c5..b0780b9dd47d 100644 --- a/sd/inc/pres.hxx +++ b/sd/inc/pres.hxx @@ -32,6 +32,7 @@ enum class PresObjKind Page, Handout, Notes, + PagePreview, Header, Footer, DateTime, diff --git a/sd/inc/sdpage.hxx b/sd/inc/sdpage.hxx index a63a362373f3..013fecbccb56 100644 --- a/sd/inc/sdpage.hxx +++ b/sd/inc/sdpage.hxx @@ -168,7 +168,7 @@ public: sd::ShapeList& GetPresentationShapeList() { return maPresentationShapeList; } void EnsureMasterPageDefaultBackground(); - SD_DLLPUBLIC SdrObject* CreatePresObj(PresObjKind eObjKind, bool bVertical, const ::tools::Rectangle& rRect, const OUString& rCustomPrompt = OUString()); + SD_DLLPUBLIC SdrObject* CreatePresObj(PresObjKind eObjKind, bool bVertical, const ::tools::Rectangle& rRect, const OUString& rCustomPrompt = OUString(), const sal_uInt16 nPagePreviewNum = 0xffff); SD_DLLPUBLIC rtl::Reference<SdrObject> CreateDefaultPresObj(PresObjKind eObjKind); SD_DLLPUBLIC void DestroyDefaultPresObj(PresObjKind eObjKind); SD_DLLPUBLIC SdrObject* GetPresObj(PresObjKind eObjKind, int nIndex = 1, bool bFuzzySearch = false ); diff --git a/sd/source/core/drawdoc2.cxx b/sd/source/core/drawdoc2.cxx index 65efc70f84f9..19ae5cf93bcd 100644 --- a/sd/source/core/drawdoc2.cxx +++ b/sd/source/core/drawdoc2.cxx @@ -457,6 +457,9 @@ void SdDrawDocument::InsertPage(SdrPage* pPage, sal_uInt16 nPos) SdXImpressDocument* pDoc = getUnoModel(); SfxLokHelper::notifyDocumentSizeChangedAllViews(pDoc); } + + if (hasCanvasPage()) + updateCanvasPreviewsGrid(); } // Override SfxBaseModel::getUnoModel and return a more concrete type @@ -471,6 +474,9 @@ void SdDrawDocument::DeletePage(sal_uInt16 nPgNum) FmFormModel::DeletePage(nPgNum); UpdatePageObjectsInNotes(nPgNum); + + if (hasCanvasPage()) + updateCanvasPreviewsGrid(); } // Remove page @@ -494,6 +500,9 @@ rtl::Reference<SdrPage> SdDrawDocument::RemovePage(sal_uInt16 nPgNum) SfxLokHelper::notifyDocumentSizeChangedAllViews(pDoc); } + if (hasCanvasPage()) + updateCanvasPreviewsGrid(); + return pPage; } @@ -1445,8 +1454,11 @@ void SdDrawDocument::SetupNewPage ( } } -sal_uInt16 SdDrawDocument::InsertCanvasPage() +sal_uInt16 SdDrawDocument::GetOrInsertCanvasPage() { + if (hasCanvasPage()) + return mpCanvasPage->GetPageNum() / 2; + sal_uInt16 nLastPageNum = GetSdPageCount(PageKind::Standard); SdPage* pLastStandardPage = GetSdPage(nLastPageNum - 1, PageKind::Standard); @@ -1457,6 +1469,10 @@ sal_uInt16 SdDrawDocument::InsertCanvasPage() const Size aCanvasSize(500000, 500000); ResizeCurrentPage(pCanvasPage, aCanvasSize, PageKind::Standard); + pCanvasPage->SetCanvasPage(); + mpCanvasPage = pCanvasPage; + + populatePagePreviewsGrid(); return pCanvasPage->GetPageNum() / 2; } @@ -1466,4 +1482,71 @@ sd::UndoManager* SdDrawDocument::GetUndoManager() const return mpDocSh ? dynamic_cast< sd::UndoManager* >(mpDocSh->GetUndoManager()) : nullptr; } +static int calculateGridColumns(const sal_uInt16 nCnt) +{ + int n = static_cast<int>(nCnt); + int srqtN = std::round(std::sqrt(n)); + + return (n % srqtN) ? srqtN + 1 : srqtN; +} + +void SdDrawDocument::populatePagePreviewsGrid() +{ + sal_uInt16 nPageCnt = GetSdPageCount(PageKind::Standard) - 1; // don't count the canvas page + sal_uInt16 nTotalCol = static_cast<sal_uInt16>(calculateGridColumns(nPageCnt)); + sal_uInt16 nTotalRow = nPageCnt / nTotalCol + (nPageCnt % nTotalCol ? 1 : 0); + + // width and height of a standard 16:9 page + sal_uInt16 nWidth = 28000; + sal_uInt16 nHeight = 15750; + + // the factor by which width & height will be divided + sal_uInt8 nFactor = 3; + + // TODO: this should also vary based on the available space + sal_uInt16 nGapWidth = 500; + sal_uInt16 nGapHeight = 500; + + ::tools::Long nPreviewWidth; + ::tools::Long nPreviewHeight; + ::tools::Long nTotalGridWidth; + ::tools::Long nTotalGridHeight; + do + { + nTotalGridWidth = (nTotalCol - 1) * nGapWidth; + nTotalGridHeight = (nTotalRow - 1) * nGapHeight; + nPreviewWidth = (nWidth / nFactor); + nPreviewHeight = (nHeight / nFactor); + nTotalGridWidth += nPreviewWidth * nTotalCol; + nTotalGridHeight += nPreviewHeight * nTotalRow; + nFactor++; + } + while (nTotalGridWidth >= mpCanvasPage->GetWidth() || + nTotalGridHeight >= mpCanvasPage->GetHeight()); + + ::tools::Long nY = (mpCanvasPage->GetHeight() - nTotalGridHeight) / 2; + for (sal_uInt16 nRow = 0; nRow < nTotalRow; nRow++) + { + ::tools::Long nX = (mpCanvasPage->GetWidth() - nTotalGridWidth) / 2; + for (sal_uInt16 nCol = 0; nCol < nTotalCol; nCol++) + { + sal_uInt16 nCurrentPageIndex = nTotalCol * nRow + nCol; + if (nCurrentPageIndex == nPageCnt) + return; + SdPage* pPage = GetSdPage(nCurrentPageIndex, PageKind::Standard); + if (pPage->IsCanvasPage()) break; + const sal_uInt16 nPageNum = pPage->GetPageNum(); + mpCanvasPage->CreatePresObj(PresObjKind::PagePreview, true, ::tools::Rectangle(Point(nX, nY), Size(nPreviewWidth, nPreviewHeight)), OUString(), nPageNum); + nX += nPreviewWidth + nGapWidth; + } + nY += nPreviewHeight + nGapHeight; + } +} + +void SdDrawDocument::updateCanvasPreviewsGrid() +{ + SdrPage* pPage = mpCanvasPage.get(); + pPage->ClearSdrObjList(); + populatePagePreviewsGrid(); +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/sdpage.cxx b/sd/source/core/sdpage.cxx index 812b909cab72..4e8a56233405 100644 --- a/sd/source/core/sdpage.cxx +++ b/sd/source/core/sdpage.cxx @@ -286,7 +286,7 @@ void SdPage::EnsureMasterPageDefaultBackground() /** creates a presentation object with the given PresObjKind on this page. A user call will be set */ -SdrObject* SdPage::CreatePresObj(PresObjKind eObjKind, bool bVertical, const ::tools::Rectangle& rRect, const OUString& rCustomPrompt) +SdrObject* SdPage::CreatePresObj(PresObjKind eObjKind, bool bVertical, const ::tools::Rectangle& rRect, const OUString& rCustomPrompt, const sal_uInt16 nPagePreviewNum) { SfxUndoManager* pUndoManager(static_cast< SdDrawDocument& >(getSdrModelFromSdrPage()).GetUndoManager()); const bool bUndo = pUndoManager && pUndoManager->IsInListAction() && IsInserted(); @@ -429,6 +429,22 @@ SdrObject* SdPage::CreatePresObj(PresObjKind eObjKind, bool bVertical, const ::t } break; + case PresObjKind::PagePreview: + { + if (nPagePreviewNum < getSdrModelFromSdrPage().GetPageCount()) + { + pSdrObj = new SdrPageObj(getSdrModelFromSdrPage(), getSdrModelFromSdrPage().GetPage(nPagePreviewNum)); + } + else + { + pSdrObj = new SdrPageObj(getSdrModelFromSdrPage()); + } + pSdrObj->SetMarkProtect(false); + pSdrObj->SetResizeProtect(false); + pSdrObj->SetMoveProtect(false); + } + break; + case PresObjKind::Header: case PresObjKind::Footer: case PresObjKind::DateTime: @@ -917,7 +933,7 @@ const o3tl::enumarray<PresObjKind, const char*> PresObjKindVector = { "PRESOBJ_TEXT" ,"PRESOBJ_GRAPHIC" , "PRESOBJ_OBJECT", "PRESOBJ_CHART", "PRESOBJ_ORGCHART", "PRESOBJ_TABLE", "PRESOBJ_PAGE", "PRESOBJ_HANDOUT", - "PRESOBJ_NOTES","PRESOBJ_HEADER", "PRESOBJ_FOOTER", + "PRESOBJ_NOTES", "PRESOBJ_PAGEPREVIEW", "PRESOBJ_HEADER", "PRESOBJ_FOOTER", "PRESOBJ_DATETIME", "PRESOBJ_SLIDENUMBER", "PRESOBJ_CALC", "PRESOBJ_MEDIA" }; diff --git a/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx b/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx index 04f6f57ea3ce..00976414946b 100644 --- a/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx +++ b/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx @@ -251,7 +251,7 @@ void SlotManager::FuTemporary (SfxRequest& rRequest) case SID_INSERT_CANVAS_SLIDE: { SdDrawDocument* pDoc = pShell->GetDoc(); - sal_uInt16 nCanvasPageIndex = pDoc->InsertCanvasPage(); + sal_uInt16 nCanvasPageIndex = pDoc->GetOrInsertCanvasPage(); SdPage* pCanvasPage = static_cast<SdPage*>(pDoc->GetPage(nCanvasPageIndex)); view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter); diff --git a/sd/source/ui/unoidl/unopage.cxx b/sd/source/ui/unoidl/unopage.cxx index c5e5ef2dc2c2..f9bf3a7ddd41 100644 --- a/sd/source/ui/unoidl/unopage.cxx +++ b/sd/source/ui/unoidl/unopage.cxx @@ -1494,6 +1494,9 @@ Reference< drawing::XShape > SdGenericDrawPage::CreateShape(SdrObject *pObj) co case PresObjKind::Handout: aShapeType += "HandoutShape"; break; + case PresObjKind::PagePreview: + aShapeType += "PageShape"; + break; case PresObjKind::Notes: aShapeType += "NotesShape"; break; diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx index c10804ca3e62..956c92eb2180 100644 --- a/sd/source/ui/view/drviews2.cxx +++ b/sd/source/ui/view/drviews2.cxx @@ -1401,7 +1401,7 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) break; case SID_INSERT_CANVAS_SLIDE: { - sal_uInt16 nCanvasPageIndex = GetDoc()->InsertCanvasPage(); + sal_uInt16 nCanvasPageIndex = GetDoc()->GetOrInsertCanvasPage(); Cancel(); // Don't know what this does SwitchPage(nCanvasPageIndex); rReq.Done();
