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();

Reply via email to