include/vcl/weld.hxx                                |    7 
 sd/Library_sd.mk                                    |    1 
 sd/source/ui/sidebar/AllMasterPagesSelector.cxx     |   11 
 sd/source/ui/sidebar/CurrentMasterPagesSelector.cxx |   21 -
 sd/source/ui/sidebar/MasterPagesSelector.cxx        |  271 +++++++++-----------
 sd/source/ui/sidebar/MasterPagesSelector.hxx        |   33 +-
 sd/source/ui/sidebar/PreviewValueSet.cxx            |  127 ---------
 sd/source/ui/sidebar/PreviewValueSet.hxx            |   59 ----
 sd/source/ui/sidebar/RecentMasterPagesSelector.cxx  |   27 -
 sd/source/ui/sidebar/RecentMasterPagesSelector.hxx  |   14 -
 sd/uiconfig/simpress/ui/masterpagepanel.ui          |   41 ++-
 sd/uiconfig/simpress/ui/masterpagepanelall.ui       |   41 ++-
 sd/uiconfig/simpress/ui/masterpagepanelrecent.ui    |   41 ++-
 solenv/clang-format/excludelist                     |    1 
 vcl/inc/salvtables.hxx                              |   16 +
 vcl/source/app/salvtables.cxx                       |   94 ++++++
 vcl/unx/gtk3/gtkinst.cxx                            |  101 +++++++
 17 files changed, 479 insertions(+), 427 deletions(-)

New commits:
commit aa2f2c1329c444aa4011c7447a03dbe71bbe3628
Author:     Rashesh <[email protected]>
AuthorDate: Mon Nov 25 17:07:59 2024 +0530
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Wed Dec 4 07:40:14 2024 +0100

    sd: convert sidebar masterpage panels from drawingview to iconview
    
    - also removes unused PreviewValueSet
    
    Change-Id: I5e7dacb4f472de526a61366295bc91edca12e9ac
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176768
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Tomaž Vajngerl <[email protected]>

diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 3e334f2cbbee..16d27fd6e399 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -1470,8 +1470,14 @@ public:
     virtual OUString get_selected_text() const = 0;
 
     //by index. Don't select when frozen, select after thaw. Note selection 
doesn't survive a freeze.
+    virtual OUString get_id(int pos) const = 0;
     virtual void select(int pos) = 0;
     virtual void unselect(int pos) = 0;
+    virtual void set_image(int pos, VirtualDevice* pDevice) = 0;
+    virtual void set_text(int pos, const OUString& rText) = 0;
+    virtual void set_id(int pos, const OUString& rId) = 0;
+    virtual void remove(int pos) = 0;
+    virtual tools::Rectangle get_rect(int pos) const = 0;
 
     //via iter
     virtual std::unique_ptr<TreeIter> make_iterator(const TreeIter* pOrig = 
nullptr) const = 0;
@@ -1481,6 +1487,7 @@ public:
     virtual bool get_iter_first(TreeIter& rIter) const = 0;
     virtual OUString get_id(const TreeIter& rIter) const = 0;
     virtual OUString get_text(const TreeIter& rIter) const = 0;
+    virtual bool iter_next_sibling(TreeIter& rIter) const = 0;
     virtual void scroll_to_item(const TreeIter& rIter) = 0;
 
     // call func on each selected element until func returns true or we run 
out of elements
diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk
index 099a8b49ce65..9f0a8db2aad1 100644
--- a/sd/Library_sd.mk
+++ b/sd/Library_sd.mk
@@ -361,7 +361,6 @@ $(eval $(call gb_Library_add_exception_objects,sd,\
        sd/source/ui/sidebar/MasterPagesSelector \
        sd/source/ui/sidebar/NavigatorWrapper \
        sd/source/ui/sidebar/PanelFactory \
-       sd/source/ui/sidebar/PreviewValueSet \
        sd/source/ui/sidebar/RecentlyUsedMasterPages \
        sd/source/ui/sidebar/RecentMasterPagesSelector \
        sd/source/ui/sidebar/SlideBackground \
diff --git a/sd/source/ui/sidebar/AllMasterPagesSelector.cxx 
b/sd/source/ui/sidebar/AllMasterPagesSelector.cxx
index 76e056120ec8..3e6091bf6a82 100644
--- a/sd/source/ui/sidebar/AllMasterPagesSelector.cxx
+++ b/sd/source/ui/sidebar/AllMasterPagesSelector.cxx
@@ -97,14 +97,13 @@ std::unique_ptr<PanelLayout> AllMasterPagesSelector::Create 
(
     return xSelector;
 }
 
-AllMasterPagesSelector::AllMasterPagesSelector (
-    weld::Widget* pParent,
-    SdDrawDocument& rDocument,
-    ViewShellBase& rBase,
+AllMasterPagesSelector::AllMasterPagesSelector(
+    weld::Widget* pParent, SdDrawDocument& rDocument, ViewShellBase& rBase,
     const std::shared_ptr<MasterPageContainer>& rpContainer,
     const css::uno::Reference<css::ui::XSidebar>& rxSidebar)
-    : MasterPagesSelector(pParent, rDocument, rBase, rpContainer, rxSidebar, 
"modules/simpress/ui/masterpagepanelall.ui", "allvalueset"),
-      mpSortedMasterPages(new SortedMasterPageDescriptorList())
+    : MasterPagesSelector(pParent, rDocument, rBase, rpContainer, rxSidebar,
+                          "modules/simpress/ui/masterpagepanelall.ui", 
"masterpageall_icons")
+    , mpSortedMasterPages(new SortedMasterPageDescriptorList())
 {
     MasterPagesSelector::Fill();
 }
diff --git a/sd/source/ui/sidebar/CurrentMasterPagesSelector.cxx 
b/sd/source/ui/sidebar/CurrentMasterPagesSelector.cxx
index e0e1c6a07cbe..ca06cf0e02e9 100644
--- a/sd/source/ui/sidebar/CurrentMasterPagesSelector.cxx
+++ b/sd/source/ui/sidebar/CurrentMasterPagesSelector.cxx
@@ -18,7 +18,6 @@
  */
 
 #include "CurrentMasterPagesSelector.hxx"
-#include "PreviewValueSet.hxx"
 #include <ViewShellBase.hxx>
 #include <DrawViewShell.hxx>
 #include <drawdoc.hxx>
@@ -61,13 +60,12 @@ std::unique_ptr<PanelLayout> 
CurrentMasterPagesSelector::Create (
     return xSelector;
 }
 
-CurrentMasterPagesSelector::CurrentMasterPagesSelector (
-    weld::Widget* pParent,
-    SdDrawDocument& rDocument,
-    ViewShellBase& rBase,
+CurrentMasterPagesSelector::CurrentMasterPagesSelector(
+    weld::Widget* pParent, SdDrawDocument& rDocument, ViewShellBase& rBase,
     const std::shared_ptr<MasterPageContainer>& rpContainer,
     const css::uno::Reference<css::ui::XSidebar>& rxSidebar)
-    : MasterPagesSelector (pParent, rDocument, rBase, rpContainer, rxSidebar, 
"modules/simpress/ui/masterpagepanel.ui", "usedvalueset")
+    : MasterPagesSelector(pParent, rDocument, rBase, rpContainer, rxSidebar,
+                          "modules/simpress/ui/masterpagepanel.ui", 
"masterpagecurrent_icons")
 {
     Link<sd::tools::EventMultiplexerEvent&,void> aLink 
(LINK(this,CurrentMasterPagesSelector,EventMultiplexerListener));
     rBase.GetEventMultiplexer()->AddEventListener(aLink);
@@ -176,17 +174,6 @@ void CurrentMasterPagesSelector::UpdateSelection()
             }
         }
     }
-
-    // Find the items for the master pages in the set.
-    sal_uInt16 nItemCount (mxPreviewValueSet->GetItemCount());
-    for (nIndex=1; nIndex<=nItemCount && bLoop; nIndex++)
-    {
-        OUString sName (mxPreviewValueSet->GetItemText (nIndex));
-        if (aNames.find(sName) != aNames.end())
-        {
-            mxPreviewValueSet->SelectItem (nIndex);
-        }
-    }
 }
 
 void CurrentMasterPagesSelector::ExecuteCommand(const OUString &rIdent)
diff --git a/sd/source/ui/sidebar/MasterPagesSelector.cxx 
b/sd/source/ui/sidebar/MasterPagesSelector.cxx
index 5be2e73cd091..85a1746eae45 100644
--- a/sd/source/ui/sidebar/MasterPagesSelector.cxx
+++ b/sd/source/ui/sidebar/MasterPagesSelector.cxx
@@ -32,7 +32,7 @@
 
 #include <DrawController.hxx>
 #include <SlideSorterViewShell.hxx>
-#include "PreviewValueSet.hxx"
+#include <vcl/vclptr.hxx>
 #include <ViewShellBase.hxx>
 #include <o3tl/safeint.hxx>
 #include <vcl/image.hxx>
@@ -40,6 +40,7 @@
 #include <sfx2/viewfrm.hxx>
 #include <sfx2/sidebar/Theme.hxx>
 #include <memory>
+#include <vcl/virdev.hxx>
 
 using namespace ::com::sun::star::text;
 
@@ -50,35 +51,22 @@ namespace sd::sidebar {
     */
 constexpr OUStringLiteral gsDefaultClickAction = u"applyselect";
 
-MasterPagesSelector::MasterPagesSelector (
-    weld::Widget* pParent,
-    SdDrawDocument& rDocument,
-    ViewShellBase& rBase,
-    std::shared_ptr<MasterPageContainer> pContainer,
-    css::uno::Reference<css::ui::XSidebar> xSidebar,
-    const OUString& rUIFileName,
-    const OUString& rValueSetName)
-    : PanelLayout( pParent, "MasterPagePanel", rUIFileName ),
-      mpContainer(std::move(pContainer)),
-      mxPreviewValueSet(new PreviewValueSet),
-      mxPreviewValueSetWin(new weld::CustomWeld(*m_xBuilder, rValueSetName, 
*mxPreviewValueSet)),
-      mrDocument(rDocument),
-      mrBase(rBase),
-      mxSidebar(std::move(xSidebar))
-{
-    mxPreviewValueSet->SetSelectHdl (
-        LINK(this, MasterPagesSelector, ClickHandler));
-    mxPreviewValueSet->SetContextMenuHandler (
-        LINK(this, MasterPagesSelector, ContextMenuHandler));
-    mxPreviewValueSet->SetStyle(mxPreviewValueSet->GetStyle() | 
WB_NO_DIRECTSELECT);
-
-    if 
(mxPreviewValueSet->GetDrawingArea()->get_ref_device().GetDPIScaleFactor() > 1)
-        mpContainer->SetPreviewSize(MasterPageContainer::LARGE);
-
-    mxPreviewValueSet->SetPreviewSize(mpContainer->GetPreviewSizePixel());
-    mxPreviewValueSet->Show();
-
-    
mxPreviewValueSet->SetColor(sfx2::sidebar::Theme::GetColor(sfx2::sidebar::Theme::Color_PanelBackground));
+MasterPagesSelector::MasterPagesSelector(weld::Widget* pParent, 
SdDrawDocument& rDocument,
+                                         ViewShellBase& rBase,
+                                         std::shared_ptr<MasterPageContainer> 
pContainer,
+                                         
css::uno::Reference<css::ui::XSidebar> xSidebar,
+                                         const OUString& rUIFileName, const 
OUString& rIconViewId)
+    : PanelLayout(pParent, "MasterPagePanel", rUIFileName)
+    , mpContainer(std::move(pContainer))
+    , mxPreviewIconView(m_xBuilder->weld_icon_view(rIconViewId))
+    , mrDocument(rDocument)
+    , mrBase(rBase)
+    , mxSidebar(std::move(xSidebar))
+    , maIconViewId(rIconViewId)
+{
+    mxPreviewIconView->connect_item_activated(LINK(this, MasterPagesSelector, 
MasterPageSelected));
+    mxPreviewIconView->connect_mouse_press(LINK(this, MasterPagesSelector, 
MousePressHdl));
+    mxPreviewIconView->connect_query_tooltip(LINK(this, MasterPagesSelector, 
QueryTooltipHdl));
 
     Link<MasterPageContainerChangeEvent&,void> aChangeListener 
(LINK(this,MasterPagesSelector,ContainerChangeListener));
     mpContainer->AddChangeListener(aChangeListener);
@@ -92,21 +80,13 @@ MasterPagesSelector::~MasterPagesSelector()
     Link<MasterPageContainerChangeEvent&,void> aChangeListener 
(LINK(this,MasterPagesSelector,ContainerChangeListener));
     mpContainer->RemoveChangeListener(aChangeListener);
     mpContainer.reset();
-    mxPreviewValueSetWin.reset();
-    mxPreviewValueSet.reset();
+    mxPreviewIconView.reset();
 }
 
 void MasterPagesSelector::LateInit()
 {
 }
 
-sal_Int32 MasterPagesSelector::GetPreferredHeight (sal_Int32 nWidth)
-{
-    const ::osl::MutexGuard aGuard (maMutex);
-
-    return mxPreviewValueSet->GetPreferredHeight (nWidth);
-}
-
 void MasterPagesSelector::UpdateLocks (const ItemList& rItemList)
 {
     ItemList aNewLockList;
@@ -146,61 +126,50 @@ OUString MasterPagesSelector::GetContextMenuUIFile() const
     return "modules/simpress/ui/mastermenu.ui";
 }
 
-IMPL_LINK_NOARG(MasterPagesSelector, ClickHandler, ValueSet*, void)
+IMPL_LINK_NOARG(MasterPagesSelector, MasterPageSelected, weld::IconView&, bool)
 {
-    // We use the framework to assign the clicked-on master page because we
-    // so use the same mechanism as the context menu does (where we do not
-    // have the option to call the assignment method directly.)
     ExecuteCommand(gsDefaultClickAction);
+    return true;
 }
 
-IMPL_LINK(MasterPagesSelector, ContextMenuHandler, const Point*, pPos, void)
+IMPL_LINK(MasterPagesSelector, MousePressHdl, const MouseEvent&, rMEvet, bool)
 {
-    if (pPos)
+    if (!rMEvet.IsRight())
+        return false;
+
+    const Point& pPos = rMEvet.GetPosPixel();
+    for (int i = 0; i < mxPreviewIconView->n_children(); i++)
     {
-        // Here we only prepare the display of the context menu: on right
-        // click the item under the mouse is selected.
-        mxPreviewValueSet->GrabFocus();
-        mxPreviewValueSet->ReleaseMouse();
-
-        sal_uInt16 nIndex = mxPreviewValueSet->GetItemId(*pPos);
-        if (nIndex > 0)
-            mxPreviewValueSet->SelectItem(nIndex);
+        const ::tools::Rectangle aRect = mxPreviewIconView->get_rect(i);
+        if (aRect.Contains(pPos))
+        {
+            mxPreviewIconView->select(i);
+            ShowContextMenu(pPos);
+            break;
+        }
     }
-
-    // Now do the actual display of the context menu
-    ShowContextMenu(pPos);
+    return false;
 }
 
-void MasterPagesSelector::ShowContextMenu(const Point* pPos)
+IMPL_LINK(MasterPagesSelector, QueryTooltipHdl, const weld::TreeIter&, iter, 
OUString)
 {
-    // Use the currently selected item and show the popup menu in its
-    // center.
-    const sal_uInt16 nIndex = mxPreviewValueSet->GetSelectedItemId();
-    if (nIndex <= 0)
-        return;
+    const OUString sId = mxPreviewIconView->get_id(iter);
+    if (!sId.isEmpty())
+        return mpContainer->GetPageNameForToken(sId.toUInt32());
 
-    // The position of the upper left corner of the context menu is
-    // taken either from the mouse position (when the command was sent
-    // as reaction to a right click) or in the center of the selected
-    // item (when the command was sent as reaction to Shift+F10.)
-    Point aPosition;
-    if (!pPos)
-    {
-        ::tools::Rectangle aBBox (mxPreviewValueSet->GetItemRect(nIndex));
-        aPosition = aBBox.Center();
-    }
-    else
-        aPosition = *pPos;
+    return OUString();
+}
 
+void MasterPagesSelector::ShowContextMenu(const Point& pPos)
+{
     // Setup the menu.
-    weld::Widget* pParent = mxPreviewValueSet->GetDrawingArea();
-    std::unique_ptr<weld::Builder> 
xBuilder(Application::CreateBuilder(pParent, GetContextMenuUIFile()));
+    ::tools::Rectangle aRect(pPos, Size(1, 1));
+    std::unique_ptr<weld::Builder> xBuilder(
+        Application::CreateBuilder(mxPreviewIconView.get(), 
GetContextMenuUIFile()));
     std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("menu"));
     ProcessPopupMenu(*xMenu);
-    ::tools::Rectangle aRect(aPosition, Size(1,1));
     // Show the menu.
-    ExecuteCommand(xMenu->popup_at_rect(pParent, aRect));
+    ExecuteCommand(xMenu->popup_at_rect(mxPreviewIconView.get(), aRect));
 }
 
 void MasterPagesSelector::ProcessPopupMenu(weld::Menu& rMenu)
@@ -256,13 +225,12 @@ void MasterPagesSelector::ExecuteCommand(const OUString 
&rIdent)
             SfxDispatcher* pDispatcher = rViewFrame.GetDispatcher();
             if (pDispatcher != nullptr)
             {
-                sal_uInt16 nIndex = mxPreviewValueSet->GetSelectedItemId();
                 pDispatcher->Execute(SID_MASTERPAGE, SfxCallMode::SYNCHRON);
-                mxPreviewValueSet->SelectItem (nIndex);
                 mrBase.GetDrawController()->setCurrentPage(xSelectedMaster);
             }
         }
     }
+    mxPreviewIconView->unselect_all();
 }
 
 IMPL_LINK(MasterPagesSelector, ContainerChangeListener, 
MasterPageContainerChangeEvent&, rEvent, void)
@@ -275,11 +243,13 @@ SdPage* MasterPagesSelector::GetSelectedMasterPage()
     const ::osl::MutexGuard aGuard (maMutex);
 
     SdPage* pMasterPage = nullptr;
-    sal_uInt16 nIndex = mxPreviewValueSet->GetSelectedItemId();
-    UserData* pData = GetUserData(nIndex);
-    if (pData != nullptr)
+    OUString sSelectedId = mxPreviewIconView->get_selected_id();
+
+    if (!sSelectedId.isEmpty())
     {
-        pMasterPage = mpContainer->GetPageObjectForToken(pData->second, true);
+        const MasterPageContainer::Token aToken
+            = static_cast<MasterPageContainer::Token>(sSelectedId.toInt32());
+        pMasterPage = mpContainer->GetPageObjectForToken(aToken, true);
     }
     return pMasterPage;
 }
@@ -356,7 +326,6 @@ void MasterPagesSelector::NotifyContainerChangeEvent (const 
MasterPageContainerC
     switch (rEvent.meEventType)
     {
         case MasterPageContainerChangeEvent::EventType::SIZE_CHANGED:
-            
mxPreviewValueSet->SetPreviewSize(mpContainer->GetPreviewSizePixel());
             UpdateAllPreviews();
             break;
 
@@ -365,10 +334,12 @@ void MasterPagesSelector::NotifyContainerChangeEvent 
(const MasterPageContainerC
             int nIndex (GetIndexForToken(rEvent.maChildToken));
             if (nIndex >= 0)
             {
-                mxPreviewValueSet->SetItemImage (
-                    static_cast<sal_uInt16>(nIndex),
-                    mpContainer->GetPreviewForToken(rEvent.maChildToken));
-                
mxPreviewValueSet->Invalidate(mxPreviewValueSet->GetItemRect(static_cast<sal_uInt16>(nIndex)));
+                Image 
aPreview(mpContainer->GetPreviewForToken(rEvent.maChildToken));
+                if (aPreview.GetSizePixel().Width() > 0)
+                {
+                    VclPtr<VirtualDevice> aDev = GetVirtualDevice(aPreview);
+                    mxPreviewIconView->set_image(nIndex, aDev);
+                }
             }
         }
         break;
@@ -392,58 +363,50 @@ void MasterPagesSelector::NotifyContainerChangeEvent 
(const MasterPageContainerC
    }
 }
 
-MasterPagesSelector::UserData* MasterPagesSelector::GetUserData (int nIndex) 
const
+std::unique_ptr<MasterPagesSelector::UserData> 
MasterPagesSelector::GetUserData(int nIndex) const
 {
-    const ::osl::MutexGuard aGuard (maMutex);
+    const ::osl::MutexGuard aGuard(maMutex);
 
-    if (nIndex>0 && 
o3tl::make_unsigned(nIndex)<=mxPreviewValueSet->GetItemCount())
-        return 
static_cast<UserData*>(mxPreviewValueSet->GetItemData(static_cast<sal_uInt16>(nIndex)));
+    if (nIndex >= 0 && nIndex < mxPreviewIconView->n_children())
+    {
+        const MasterPageContainer::Token aToken
+            = 
static_cast<MasterPageContainer::Token>(mxPreviewIconView->get_id(nIndex).toInt32());
+        return std::make_unique<UserData>(std::make_pair(nIndex, aToken));
+    }
     else
         return nullptr;
 }
 
-void MasterPagesSelector::SetUserData (int nIndex, std::unique_ptr<UserData> 
pData)
-{
-    const ::osl::MutexGuard aGuard (maMutex);
-
-    delete GetUserData(nIndex);
-    mxPreviewValueSet->SetItemData(static_cast<sal_uInt16>(nIndex), 
pData.release());
-}
-
 void MasterPagesSelector::SetItem (
     sal_uInt16 nIndex,
     MasterPageContainer::Token aToken)
 {
     const ::osl::MutexGuard aGuard (maMutex);
 
-    RemoveTokenToIndexEntry(nIndex,aToken);
+    RemoveTokenToIndexEntry(nIndex, aToken);
 
-    if (nIndex <= 0)
-        return;
+    mxPreviewIconView->freeze();
 
     if (aToken != MasterPageContainer::NIL_TOKEN)
     {
         Image aPreview (mpContainer->GetPreviewForToken(aToken));
         MasterPageContainer::PreviewState eState 
(mpContainer->GetPreviewState(aToken));
 
-        if (aPreview.GetSizePixel().Width()>0)
+        if (aPreview.GetSizePixel().Width() > 0)
         {
-            if (mxPreviewValueSet->GetItemPos(nIndex) != 
VALUESET_ITEM_NOTFOUND)
+            VclPtr<VirtualDevice> aVDev = GetVirtualDevice(aPreview);
+            if (!mxPreviewIconView->get_id(nIndex).isEmpty())
             {
-                mxPreviewValueSet->SetItemImage(nIndex,aPreview);
-                mxPreviewValueSet->SetItemText(nIndex, 
mpContainer->GetPageNameForToken(aToken));
+                mxPreviewIconView->set_image(nIndex, aVDev);
+                mxPreviewIconView->set_id(nIndex, OUString::number(aToken));
             }
             else
             {
-                mxPreviewValueSet->InsertItem (
-                    nIndex,
-                    aPreview,
-                    mpContainer->GetPageNameForToken(aToken),
-                    nIndex);
+                OUString sId = OUString::number(aToken);
+                mxPreviewIconView->insert(nIndex, nullptr, &sId, aVDev, 
nullptr);
             }
-            SetUserData(nIndex, std::make_unique<UserData>(nIndex,aToken));
 
-            AddTokenToIndexEntry(nIndex,aToken);
+            AddTokenToIndexEntry(nIndex, aToken);
         }
 
         if (eState == MasterPageContainer::PS_CREATABLE)
@@ -451,9 +414,9 @@ void MasterPagesSelector::SetItem (
     }
     else
     {
-        mxPreviewValueSet->RemoveItem(nIndex);
+        mxPreviewIconView->remove(nIndex);
     }
-
+    mxPreviewIconView->thaw();
 }
 
 void MasterPagesSelector::AddTokenToIndexEntry (
@@ -471,7 +434,7 @@ void MasterPagesSelector::RemoveTokenToIndexEntry (
 {
     const ::osl::MutexGuard aGuard (maMutex);
 
-    UserData* pData = GetUserData(nIndex);
+    std::unique_ptr<UserData> pData = GetUserData(nIndex);
     if (pData != nullptr)
     {
         // Get the token that the index pointed to previously.
@@ -480,7 +443,7 @@ void MasterPagesSelector::RemoveTokenToIndexEntry (
         if (aNewToken != aOldToken
             && nIndex == GetIndexForToken(aOldToken))
         {
-            maTokenToValueSetIndex[aOldToken] = 0;
+            maTokenToValueSetIndex[aOldToken] = -1;
         }
     }
 }
@@ -489,9 +452,9 @@ void MasterPagesSelector::InvalidatePreview (const SdPage* 
pPage)
 {
     const ::osl::MutexGuard aGuard (maMutex);
 
-    for (size_t nIndex=1; nIndex<=mxPreviewValueSet->GetItemCount(); nIndex++)
+    for (int nIndex = 0; nIndex < mxPreviewIconView->n_children(); nIndex++)
     {
-        UserData* pData = GetUserData(nIndex);
+        std::unique_ptr<UserData> pData = GetUserData(nIndex);
         if (pData != nullptr)
         {
             MasterPageContainer::Token aToken (pData->second);
@@ -505,43 +468,54 @@ void MasterPagesSelector::InvalidatePreview (const 
SdPage* pPage)
     }
 }
 
+VclPtr<VirtualDevice> MasterPagesSelector::GetVirtualDevice(Image pImage)
+{
+    BitmapEx aPreviewBitmap = pImage.GetBitmapEx();
+    VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create();
+    const Point aNull(0, 0);
+    if (pVDev->GetDPIScaleFactor() > 1)
+        aPreviewBitmap.Scale(pVDev->GetDPIScaleFactor(), 
pVDev->GetDPIScaleFactor());
+    const Size aSize(aPreviewBitmap.GetSizePixel());
+    pVDev->SetOutputSizePixel(aSize);
+    pVDev->DrawBitmapEx(aNull, aPreviewBitmap);
+
+    return pVDev;
+}
+
 void MasterPagesSelector::UpdateAllPreviews()
 {
     const ::osl::MutexGuard aGuard (maMutex);
 
-    for (size_t nIndex=1; nIndex<=mxPreviewValueSet->GetItemCount(); nIndex++)
+    mxPreviewIconView->freeze();
+    for (int aIndex = 0; aIndex < mxPreviewIconView->n_children(); aIndex++)
     {
-        UserData* pData = GetUserData(nIndex);
-        if (pData != nullptr)
+        const MasterPageContainer::Token aToken
+            = 
static_cast<MasterPageContainer::Token>(mxPreviewIconView->get_id(aIndex).toInt32());
+
+        Image aPreview(mpContainer->GetPreviewForToken(aToken));
+        if (aPreview.GetSizePixel().Width() > 0)
         {
-            MasterPageContainer::Token aToken (pData->second);
-            mxPreviewValueSet->SetItemImage(
-                nIndex,
-                mpContainer->GetPreviewForToken(aToken));
-            if (mpContainer->GetPreviewState(aToken) == 
MasterPageContainer::PS_CREATABLE)
-                mpContainer->RequestPreview(aToken);
+            VclPtr<VirtualDevice> pVDev = GetVirtualDevice(aPreview);
+            mxPreviewIconView->set_image(aIndex, pVDev);
+        }
+        else if (mpContainer->GetPreviewState(aToken) == 
MasterPageContainer::PS_CREATABLE)
+        {
+            mpContainer->RequestPreview(aToken);
         }
     }
-    mxPreviewValueSet->Rearrange();
+    mxPreviewIconView->thaw();
 }
 
 void MasterPagesSelector::ClearPageSet()
 {
     const ::osl::MutexGuard aGuard (maMutex);
-
-    for (size_t nIndex=1; nIndex<=mxPreviewValueSet->GetItemCount(); nIndex++)
-    {
-        UserData* pData = GetUserData(nIndex);
-        delete pData;
-    }
-    mxPreviewValueSet->Clear();
+    mxPreviewIconView->clear();
 }
 
 void MasterPagesSelector::SetHelpId( const OUString& aId )
 {
     const ::osl::MutexGuard aGuard (maMutex);
-
-    mxPreviewValueSet->SetHelpId( aId );
+    mxPreviewIconView->set_help_id(aId);
 }
 
 sal_Int32 MasterPagesSelector::GetIndexForToken (MasterPageContainer::Token 
aToken) const
@@ -579,7 +553,7 @@ void MasterPagesSelector::UpdateItemList 
(::std::unique_ptr<ItemList> && pNewIte
     ItemList::const_iterator iCurrentItem (maCurrentItemList.begin());
     ItemList::const_iterator iNewEnd (pNewItemList->end());
     ItemList::const_iterator iCurrentEnd (maCurrentItemList.end());
-    sal_uInt16 nIndex (1);
+    sal_uInt16 nIndex(0);
 
     // Update existing items.
     for ( ; iNewItem!=iNewEnd && iCurrentItem!=iCurrentEnd; ++iNewItem, 
++iCurrentItem,++nIndex)
@@ -604,15 +578,22 @@ void MasterPagesSelector::UpdateItemList 
(::std::unique_ptr<ItemList> && pNewIte
 
     maCurrentItemList.swap(*pNewItemList);
 
-    mxPreviewValueSet->Rearrange();
     if (mxSidebar.is())
         mxSidebar->requestLayout();
 }
 
-css::ui::LayoutSize MasterPagesSelector::GetHeightForWidth (const sal_Int32 
nWidth)
+css::ui::LayoutSize MasterPagesSelector::GetHeightForWidth(const sal_Int32 
nWidth)
 {
-    const sal_Int32 nHeight (GetPreferredHeight(nWidth));
-    return css::ui::LayoutSize(nHeight,nHeight,nHeight);
+    if (maIconViewId == "masterpageall_icons")
+        return css::ui::LayoutSize(-1, -1, -1);
+
+    const sal_uInt32 nItemWidth = mxPreviewIconView->get_item_width();
+    sal_Int32 nMinimumHeight = 
mxPreviewIconView->get_preferred_size().getHeight();
+    const sal_Int32 itemsInRows = floor(nWidth / nItemWidth);
+    sal_Int32 totalItems = mxPreviewIconView->n_children();
+    if (itemsInRows > 0)
+        nMinimumHeight = ((totalItems / itemsInRows) + 1) * nMinimumHeight;
+    return css::ui::LayoutSize(nMinimumHeight, nMinimumHeight, nMinimumHeight);
 }
 
 } // end of namespace sd::sidebar
diff --git a/sd/source/ui/sidebar/MasterPagesSelector.hxx 
b/sd/source/ui/sidebar/MasterPagesSelector.hxx
index f0a540bade1b..3eaf9851e317 100644
--- a/sd/source/ui/sidebar/MasterPagesSelector.hxx
+++ b/sd/source/ui/sidebar/MasterPagesSelector.hxx
@@ -22,7 +22,10 @@
 #include <map>
 #include <memory>
 #include "MasterPageContainer.hxx"
-#include "PreviewValueSet.hxx"
+#include <vcl/image.hxx>
+#include <vcl/vclptr.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/weld.hxx>
 #include <sfx2/sidebar/ILayoutableWindow.hxx>
 #include <sfx2/sidebar/PanelLayout.hxx>
 
@@ -46,14 +49,10 @@ class MasterPagesSelector : public PanelLayout
                           , public sfx2::sidebar::ILayoutableWindow
 {
 public:
-    MasterPagesSelector (
-        weld::Widget* pParent,
-        SdDrawDocument& rDocument,
-        ViewShellBase& rBase,
-        std::shared_ptr<MasterPageContainer> pContainer,
-        css::uno::Reference<css::ui::XSidebar> xSidebar,
-        const OUString& rUIFileName,
-        const OUString& rValueSetName);
+    MasterPagesSelector(weld::Widget* pParent, SdDrawDocument& rDocument, 
ViewShellBase& rBase,
+                        std::shared_ptr<MasterPageContainer> pContainer,
+                        css::uno::Reference<css::ui::XSidebar> xSidebar,
+                        const OUString& rUIFileName, const OUString& 
rIconViewId);
     virtual ~MasterPagesSelector() override;
 
     virtual void LateInit();
@@ -80,7 +79,7 @@ public:
 
     void UpdateAllPreviews();
 
-    void ShowContextMenu(const Point* pPos);
+    void ShowContextMenu(const Point& pPos);
 
     // ILayoutableWindow
     virtual css::ui::LayoutSize GetHeightForWidth (const sal_Int32 nWidth) 
override;
@@ -89,8 +88,7 @@ protected:
     mutable ::osl::Mutex maMutex;
     std::shared_ptr<MasterPageContainer> mpContainer;
 
-    std::unique_ptr<PreviewValueSet> mxPreviewValueSet;
-    std::unique_ptr<weld::CustomWeld> mxPreviewValueSetWin;
+    std::unique_ptr<weld::IconView> mxPreviewIconView;
 
     SdDrawDocument& mrDocument;
     ViewShellBase& mrBase;
@@ -117,8 +115,7 @@ protected:
     virtual void NotifyContainerChangeEvent (const 
MasterPageContainerChangeEvent& rEvent);
 
     typedef ::std::pair<int, MasterPageContainer::Token> UserData;
-    UserData* GetUserData (int nIndex) const;
-    void SetUserData (int nIndex, std::unique_ptr<UserData> pData);
+    std::unique_ptr<MasterPagesSelector::UserData> GetUserData(int nIndex) 
const;
 
     sal_Int32 GetIndexForToken (MasterPageContainer::Token aToken) const;
     typedef ::std::vector<MasterPageContainer::Token> ItemList;
@@ -155,14 +152,16 @@ protected:
 
 private:
     css::uno::Reference<css::ui::XSidebar> mxSidebar;
+    OUString maIconViewId;
 
     /** The offset between ValueSet index and MasterPageContainer::Token
         last seen.  This value is used heuristically to speed up the lookup
         of an index for a token.
     */
-    DECL_LINK(ClickHandler, ValueSet*, void);
-    DECL_LINK(ContextMenuHandler, const Point*, void);
+    DECL_LINK(MasterPageSelected, weld::IconView&, bool);
+    DECL_LINK(MousePressHdl, const MouseEvent&, bool);
     DECL_LINK(ContainerChangeListener, MasterPageContainerChangeEvent&, void);
+    DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString);
 
     void SetItem (
         sal_uInt16 nIndex,
@@ -173,6 +172,8 @@ private:
     void RemoveTokenToIndexEntry (
         sal_uInt16 nIndex,
         MasterPageContainer::Token aToken);
+
+    static VclPtr<VirtualDevice> GetVirtualDevice(Image pPreview);
 };
 
 } // end of namespace sd::sidebar
diff --git a/sd/source/ui/sidebar/PreviewValueSet.cxx 
b/sd/source/ui/sidebar/PreviewValueSet.cxx
deleted file mode 100644
index f752d60eb00d..000000000000
--- a/sd/source/ui/sidebar/PreviewValueSet.cxx
+++ /dev/null
@@ -1,127 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * 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/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#include "PreviewValueSet.hxx"
-#include <vcl/commandevent.hxx>
-
-namespace sd::sidebar {
-
-const int gnBorderWidth(3);
-const int gnBorderHeight(3);
-
-PreviewValueSet::PreviewValueSet()
-    : ValueSet(nullptr)
-    , maPreviewSize(10,10)
-{
-    SetStyle (
-        GetStyle()
-        & ~(WB_ITEMBORDER)// | WB_MENUSTYLEVALUESET)
-        //        | WB_FLATVALUESET);
-        );
-}
-
-void PreviewValueSet::SetDrawingArea(weld::DrawingArea* pDrawingArea)
-{
-    ValueSet::SetDrawingArea(pDrawingArea);
-
-    SetColCount(2);
-    SetExtraSpacing (2);
-}
-
-PreviewValueSet::~PreviewValueSet()
-{
-}
-
-void PreviewValueSet::SetPreviewSize (const Size& rSize)
-{
-    maPreviewSize = rSize;
-}
-
-void PreviewValueSet::SetContextMenuHandler(const Link<const Point*, void>& 
rLink)
-{
-    maContextMenuHandler = rLink;
-}
-
-bool PreviewValueSet::Command(const CommandEvent& rEvent)
-{
-    if (rEvent.GetCommand() != CommandEventId::ContextMenu)
-        return ValueSet::Command(rEvent);
-    maContextMenuHandler.Call(rEvent.IsMouseEvent() ? 
&rEvent.GetMousePosPixel() : nullptr);
-    return true;
-}
-
-void PreviewValueSet::Resize()
-{
-    ValueSet::Resize();
-
-    Size aWindowSize (GetOutputSizePixel());
-    if (!aWindowSize.IsEmpty())
-    {
-        Rearrange();
-    }
-}
-
-void PreviewValueSet::Rearrange()
-{
-    sal_uInt16 nNewColumnCount (CalculateColumnCount (
-        GetOutputSizePixel().Width()));
-    sal_uInt16 nNewRowCount (CalculateRowCount (nNewColumnCount));
-
-    SetFormat();
-    SetColCount(nNewColumnCount);
-    SetLineCount(nNewRowCount);
-}
-
-sal_uInt16 PreviewValueSet::CalculateColumnCount (int nWidth) const
-{
-    int nColumnCount = 0;
-    if (nWidth > 0)
-    {
-        nColumnCount = nWidth / (maPreviewSize.Width() + 2*gnBorderWidth);
-        if (nColumnCount < 1)
-            nColumnCount = 1;
-    }
-    return static_cast<sal_uInt16>(nColumnCount);
-}
-
-sal_uInt16 PreviewValueSet::CalculateRowCount (sal_uInt16 nColumnCount) const
-{
-    int nRowCount = 0;
-    int nItemCount = GetItemCount();
-    if (nColumnCount > 0)
-    {
-        nRowCount = (nItemCount+nColumnCount-1) / nColumnCount;
-        if (nRowCount < 1)
-            nRowCount = 1;
-    }
-
-    return static_cast<sal_uInt16>(nRowCount);
-}
-
-sal_Int32 PreviewValueSet::GetPreferredHeight (sal_Int32 nWidth)
-{
-    int nRowCount (CalculateRowCount(CalculateColumnCount(nWidth)));
-    int nItemHeight (maPreviewSize.Height());
-
-    return nRowCount * (nItemHeight + 2*gnBorderHeight);
-}
-
-} // end of namespace sd::sidebar
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/sidebar/PreviewValueSet.hxx 
b/sd/source/ui/sidebar/PreviewValueSet.hxx
deleted file mode 100644
index adab3c78ad4d..000000000000
--- a/sd/source/ui/sidebar/PreviewValueSet.hxx
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * 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/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#pragma once
-
-#include <svtools/valueset.hxx>
-
-namespace sd::sidebar
-{
-/** Adapt the svtools valueset to the needs of the master page controls.
-*/
-class PreviewValueSet : public ValueSet
-{
-public:
-    explicit PreviewValueSet();
-    virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
-    virtual ~PreviewValueSet() override;
-
-    void SetContextMenuHandler(const Link<const Point*, void>& rLink);
-
-    virtual void Resize() override;
-    virtual bool Command(const CommandEvent& rEvent) override;
-
-    void SetPreviewSize(const Size& rSize);
-
-    sal_Int32 GetPreferredHeight(sal_Int32 nWidth);
-
-    /** Set the number of rows and columns according to the current number
-        of items.  Call this method when new items have been inserted.
-    */
-    void Rearrange();
-
-private:
-    Link<const Point*, void> maContextMenuHandler;
-    Size maPreviewSize;
-
-    sal_uInt16 CalculateColumnCount(int nWidth) const;
-    sal_uInt16 CalculateRowCount(sal_uInt16 nColumnCount) const;
-};
-
-} // end of namespace sd::sidebar
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/sidebar/RecentMasterPagesSelector.cxx 
b/sd/source/ui/sidebar/RecentMasterPagesSelector.cxx
index 6e5a46c736a1..16605b1e43af 100644
--- a/sd/source/ui/sidebar/RecentMasterPagesSelector.cxx
+++ b/sd/source/ui/sidebar/RecentMasterPagesSelector.cxx
@@ -51,13 +51,12 @@ std::unique_ptr<PanelLayout> 
RecentMasterPagesSelector::Create (
     return xSelector;
 }
 
-RecentMasterPagesSelector::RecentMasterPagesSelector (
-    weld::Widget* pParent,
-    SdDrawDocument& rDocument,
-    ViewShellBase& rBase,
+RecentMasterPagesSelector::RecentMasterPagesSelector(
+    weld::Widget* pParent, SdDrawDocument& rDocument, ViewShellBase& rBase,
     const std::shared_ptr<MasterPageContainer>& rpContainer,
     const css::uno::Reference<css::ui::XSidebar>& rxSidebar)
-    : MasterPagesSelector (pParent, rDocument, rBase, rpContainer, rxSidebar, 
"modules/simpress/ui/masterpagepanelrecent.ui", "recentvalueset")
+    : MasterPagesSelector(pParent, rDocument, rBase, rpContainer, rxSidebar,
+                          "modules/simpress/ui/masterpagepanelrecent.ui", 
"masterpagerecent_icons")
 {
 }
 
@@ -115,24 +114,6 @@ void RecentMasterPagesSelector::Fill (ItemList& rItemList)
     }
 }
 
-void RecentMasterPagesSelector::AssignMasterPageToPageList (
-    SdPage* pMasterPage,
-    const std::shared_ptr<std::vector<SdPage*> >& rpPageList)
-{
-    sal_uInt16 nSelectedItemId = mxPreviewValueSet->GetSelectedItemId();
-
-    MasterPagesSelector::AssignMasterPageToPageList(pMasterPage, rpPageList);
-
-    // Restore the selection.
-    if (mxPreviewValueSet->GetItemCount() > 0)
-    {
-        if (mxPreviewValueSet->GetItemCount() >= nSelectedItemId)
-            mxPreviewValueSet->SelectItem(nSelectedItemId);
-        else
-            mxPreviewValueSet->SelectItem(mxPreviewValueSet->GetItemCount());
-    }
-}
-
 } // end of namespace sd::sidebar
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/sidebar/RecentMasterPagesSelector.hxx 
b/sd/source/ui/sidebar/RecentMasterPagesSelector.hxx
index 6dbc3a2aae07..bf35ca0adf3b 100644
--- a/sd/source/ui/sidebar/RecentMasterPagesSelector.hxx
+++ b/sd/source/ui/sidebar/RecentMasterPagesSelector.hxx
@@ -49,20 +49,6 @@ private:
 
     using sd::sidebar::MasterPagesSelector::Fill;
 
-    /** Forward this call to the base class but save and restore the
-        currently selected item.
-        Assign the given master page to the list of pages.
-        @param pMasterPage
-            This master page will usually be a member of the list of all
-            available master pages as provided by the MasterPageContainer.
-        @param rPageList
-            The pages to which to assign the master page.  These pages may
-            be slides or master pages themselves.
-    */
-    virtual void AssignMasterPageToPageList (
-        SdPage* pMasterPage,
-        const std::shared_ptr<std::vector<SdPage*> >& rpPageList) override;
-
     virtual void LateInit() override;
 };
 
diff --git a/sd/uiconfig/simpress/ui/masterpagepanel.ui 
b/sd/uiconfig/simpress/ui/masterpagepanel.ui
index 429032ed2148..666d30ffacb5 100644
--- a/sd/uiconfig/simpress/ui/masterpagepanel.ui
+++ b/sd/uiconfig/simpress/ui/masterpagepanel.ui
@@ -3,22 +3,51 @@
 <interface domain="sd">
   <requires lib="gtk+" version="3.20"/>
   <!-- n-columns=1 n-rows=1 -->
-  <object class="GtkGrid" id="MasterPagePanel">
+  <object class="GtkTreeStore" id="liststore1">
+    <columns>
+      <!-- column-name pixbuf -->
+      <column type="GdkPixbuf"/>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkBox" id="MasterPagePanel">
     <property name="visible">True</property>
     <property name="can-focus">False</property>
-    <property name="hexpand">True</property>
     <property name="vexpand">True</property>
+    <property name="orientation">vertical</property>
     <child>
-      <object class="GtkDrawingArea" id="usedvalueset">
+      <object class="GtkScrolledWindow" 
id="masterpagecurrent_icons_scrolled_window">
         <property name="visible">True</property>
         <property name="can-focus">True</property>
-        <property name="events">GDK_BUTTON_PRESS_MASK | 
GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | 
GDK_STRUCTURE_MASK</property>
         <property name="hexpand">True</property>
         <property name="vexpand">True</property>
+        <property name="hscrollbar-policy">never</property>
+        <property name="shadow-type">in</property>
+        <child>
+          <object class="GtkIconView" id="masterpagecurrent_icons">
+            <property name="visible">True</property>
+            <property name="item-padding">2</property>
+            <property name="can-focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="model">liststore1</property>
+            <property name="pixbuf-column">0</property>
+            <property name="item-width">55</property>
+            <property name="margin">6</property>
+            <property name="activate-on-single-click">True</property>
+            <child internal-child="accessible">
+              <object class="AtkObject" id="masterpagecurrent_icons-atkobject">
+                <property name="AtkObject::accessible-description" 
translatable="yes" 
context="masterpagecurrentpanel|extended_tip|masterpagecurrent_icons">Currently 
selected master slide.</property>
+              </object>
+            </child>
+          </object>
+        </child>
       </object>
       <packing>
-        <property name="left-attach">0</property>
-        <property name="top-attach">0</property>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
       </packing>
     </child>
   </object>
diff --git a/sd/uiconfig/simpress/ui/masterpagepanelall.ui 
b/sd/uiconfig/simpress/ui/masterpagepanelall.ui
index 979d06990e9e..078c4b7bec09 100644
--- a/sd/uiconfig/simpress/ui/masterpagepanelall.ui
+++ b/sd/uiconfig/simpress/ui/masterpagepanelall.ui
@@ -3,22 +3,51 @@
 <interface domain="sd">
   <requires lib="gtk+" version="3.20"/>
   <!-- n-columns=1 n-rows=1 -->
-  <object class="GtkGrid" id="MasterPagePanel">
+  <object class="GtkTreeStore" id="liststore1">
+    <columns>
+      <!-- column-name pixbuf -->
+      <column type="GdkPixbuf"/>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkBox" id="MasterPagePanel">
     <property name="visible">True</property>
     <property name="can-focus">False</property>
-    <property name="hexpand">True</property>
     <property name="vexpand">True</property>
+    <property name="orientation">vertical</property>
     <child>
-      <object class="GtkDrawingArea" id="allvalueset">
+      <object class="GtkScrolledWindow" 
id="masterpageall_icons_scrolled_window">
         <property name="visible">True</property>
         <property name="can-focus">True</property>
-        <property name="events">GDK_BUTTON_PRESS_MASK | 
GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | 
GDK_STRUCTURE_MASK</property>
         <property name="hexpand">True</property>
         <property name="vexpand">True</property>
+        <property name="hscrollbar-policy">never</property>
+        <property name="shadow-type">in</property>
+        <child>
+          <object class="GtkIconView" id="masterpageall_icons">
+            <property name="item-padding">2</property>
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="model">liststore1</property>
+            <property name="pixbuf-column">0</property>
+            <property name="activate-on-single-click">True</property>
+            <property name="item-width">55</property>
+            <property name="margin">6</property>
+            <child internal-child="accessible">
+              <object class="AtkObject" id="masterpageall_icons-atkobject">
+                <property name="AtkObject::accessible-description" 
translatable="yes" 
context="masterpageallpanel|extended_tip|masterpageall_icons">Select master 
slide from available.</property>
+              </object>
+            </child>
+          </object>
+        </child>
       </object>
       <packing>
-        <property name="left-attach">0</property>
-        <property name="top-attach">0</property>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
       </packing>
     </child>
   </object>
diff --git a/sd/uiconfig/simpress/ui/masterpagepanelrecent.ui 
b/sd/uiconfig/simpress/ui/masterpagepanelrecent.ui
index 4ec8487cfc5c..9be8d5a3ec9e 100644
--- a/sd/uiconfig/simpress/ui/masterpagepanelrecent.ui
+++ b/sd/uiconfig/simpress/ui/masterpagepanelrecent.ui
@@ -3,22 +3,51 @@
 <interface domain="sd">
   <requires lib="gtk+" version="3.20"/>
   <!-- n-columns=1 n-rows=1 -->
-  <object class="GtkGrid" id="MasterPagePanel">
+  <object class="GtkTreeStore" id="liststore1">
+    <columns>
+      <!-- column-name pixbuf -->
+      <column type="GdkPixbuf"/>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+    </columns>
+    </object>
+  <object class="GtkBox" id="MasterPagePanel">
     <property name="visible">True</property>
     <property name="can-focus">False</property>
-    <property name="hexpand">True</property>
     <property name="vexpand">True</property>
+    <property name="orientation">vertical</property>
     <child>
-      <object class="GtkDrawingArea" id="recentvalueset">
+      <object class="GtkScrolledWindow" 
id="masterpagerecent_icons_scrolled_window">
         <property name="visible">True</property>
         <property name="can-focus">True</property>
-        <property name="events">GDK_BUTTON_PRESS_MASK | 
GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | 
GDK_STRUCTURE_MASK</property>
         <property name="hexpand">True</property>
         <property name="vexpand">True</property>
+        <property name="hscrollbar-policy">never</property>
+        <property name="shadow-type">in</property>
+        <child>
+          <object class="GtkIconView" id="masterpagerecent_icons">
+            <property name="item-padding">2</property>
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="model">liststore1</property>
+            <property name="pixbuf-column">0</property>
+            <property name="item-width">55</property>
+            <property name="margin">6</property>
+            <property name="activate-on-single-click">True</property>
+            <child internal-child="accessible">
+              <object class="AtkObject" id="masterpagerecent_icons-atkobject">
+                <property name="AtkObject::accessible-description" 
translatable="yes" 
context="masterpagerecentpanel|extended_tip|masterpagerecent_icons">Select 
recenty used master slide.</property>
+              </object>
+            </child>
+        </object>
+        </child>
       </object>
       <packing>
-        <property name="left-attach">0</property>
-        <property name="top-attach">0</property>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
       </packing>
     </child>
   </object>
diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist
index 32eb3c84f21e..db7fd10875ab 100644
--- a/solenv/clang-format/excludelist
+++ b/solenv/clang-format/excludelist
@@ -9882,7 +9882,6 @@ sd/source/ui/sidebar/NavigatorWrapper.hxx
 sd/source/ui/sidebar/PageMarginUtils.hxx
 sd/source/ui/sidebar/PanelFactory.cxx
 sd/source/ui/sidebar/PanelFactory.hxx
-sd/source/ui/sidebar/PreviewValueSet.cxx
 sd/source/ui/sidebar/RecentMasterPagesSelector.cxx
 sd/source/ui/sidebar/RecentMasterPagesSelector.hxx
 sd/source/ui/sidebar/RecentlyUsedMasterPages.cxx
diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx
index 079d9b78af5e..7cc26c25d39e 100644
--- a/vcl/inc/salvtables.hxx
+++ b/vcl/inc/salvtables.hxx
@@ -1978,14 +1978,30 @@ public:
 
     virtual bool get_iter_first(weld::TreeIter& rIter) const override;
 
+    virtual bool iter_next_sibling(weld::TreeIter& rIter) const override;
+
     virtual void scroll_to_item(const weld::TreeIter& rIter) override;
 
     virtual void selected_foreach(const std::function<bool(weld::TreeIter&)>& 
func) override;
 
     virtual OUString get_id(const weld::TreeIter& rIter) const override;
 
+    virtual OUString get_id(int pos) const override;
+
+    virtual void remove(int pos) override;
+
+    const OUString* getEntryData(int index) const;
+
+    virtual void set_image(int pos, VirtualDevice* rImage) override;
+
+    virtual void set_text(int pos, const OUString& rText) override;
+
+    virtual void set_id(int pos, const OUString& rId) override;
+
     virtual OUString get_text(const weld::TreeIter& rIter) const override;
 
+    virtual tools::Rectangle get_rect(int pos) const override;
+
     virtual void clear() override;
 
     virtual ~SalInstanceIconView() override;
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index ddffe9d2bb79..2e4dfeb14016 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -5647,6 +5647,13 @@ bool SalInstanceIconView::get_iter_first(weld::TreeIter& 
rIter) const
     return rVclIter.iter != nullptr;
 }
 
+bool SalInstanceIconView::iter_next_sibling(weld::TreeIter& rIter) const
+{
+    SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
+    rVclIter.iter = rVclIter.iter->NextSibling();
+    return rVclIter.iter != nullptr;
+}
+
 void SalInstanceIconView::scroll_to_item(const weld::TreeIter& rIter)
 {
     assert(m_xIconView->IsUpdateMode()
@@ -5678,12 +5685,99 @@ OUString SalInstanceIconView::get_id(const 
weld::TreeIter& rIter) const
     return OUString();
 }
 
+OUString SalInstanceIconView::get_id(int pos) const
+{
+    const OUString* pRet = getEntryData(pos);
+    if (!pRet)
+        return OUString();
+    return *pRet;
+}
+
+void SalInstanceIconView::set_image(int pos, VirtualDevice* pIcon)
+{
+    SvTreeListEntry* aEntry = m_xIconView->GetEntry(nullptr, pos);
+    if (aEntry == nullptr)
+        return;
+    SvLBoxContextBmp* aItem
+        = 
static_cast<SvLBoxContextBmp*>(aEntry->GetFirstItem(SvLBoxItemType::ContextBmp));
+
+    Image aImage;
+    if (pIcon)
+    {
+        const Point aNull(0, 0);
+        const Size aSize = pIcon->GetOutputSize();
+        aImage = Image(pIcon->GetBitmapEx(aNull, aSize));
+    }
+    if (aItem == nullptr)
+    {
+        aEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aImage, aImage, 
false));
+    }
+    else
+    {
+        aItem->SetBitmap1(aImage);
+        aItem->SetBitmap2(aImage);
+    }
+
+    if (!m_xIconView->GetModel()->IsEnableInvalidate())
+        m_xIconView->ModelHasEntryInvalidated(aEntry);
+}
+
+void SalInstanceIconView::remove(int pos)
+{
+    disable_notify_events();
+    SvTreeListEntry* pEntry = m_xIconView->GetEntry(nullptr, pos);
+    m_xIconView->RemoveEntry(pEntry);
+    enable_notify_events();
+}
+
+const OUString* SalInstanceIconView::getEntryData(int index) const
+{
+    SvTreeListEntry* pEntry = m_xIconView->GetEntry(nullptr, index);
+    return pEntry ? static_cast<const OUString*>(pEntry->GetUserData()) : 
nullptr;
+}
+
 OUString SalInstanceIconView::get_text(const weld::TreeIter& rIter) const
 {
     const SalInstanceTreeIter& rVclIter = static_cast<const 
SalInstanceTreeIter&>(rIter);
     return SvTabListBox::GetEntryText(rVclIter.iter, 0);
 }
 
+void SalInstanceIconView::set_text(int pos, const OUString& rText)
+{
+    SvTreeListEntry* aEntry = m_xIconView->GetEntry(nullptr, pos);
+    if (aEntry == nullptr)
+        return;
+
+    SvLBoxString* aItem = 
static_cast<SvLBoxString*>(aEntry->GetFirstItem(SvLBoxItemType::String));
+    if (aItem == nullptr)
+    {
+        aEntry->AddItem(std::make_unique<SvLBoxString>(rText));
+    }
+    else
+    {
+        aItem->SetText(rText);
+    }
+
+    if (!m_xIconView->GetModel()->IsEnableInvalidate())
+        m_xIconView->ModelHasEntryInvalidated(aEntry);
+}
+
+void SalInstanceIconView::set_id(int pos, const OUString& rId)
+{
+    SvTreeListEntry* pEntry = m_xIconView->GetEntry(nullptr, pos);
+    m_aUserData.emplace_back(std::make_unique<OUString>(rId));
+    pEntry->SetUserData(m_aUserData.back().get());
+}
+
+tools::Rectangle SalInstanceIconView::get_rect(int pos) const
+{
+    SvTreeListEntry* aEntry = m_xIconView->GetEntry(nullptr, pos);
+    if (aEntry == nullptr)
+        return tools::Rectangle();
+
+    return m_xIconView->GetBoundingRect(aEntry);
+}
+
 void SalInstanceIconView::clear()
 {
     disable_notify_events();
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index 3b9ce8bc0de9..120f24c09b3e 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -2271,6 +2271,17 @@ namespace
         {
             rOutRect = GdkRectangle{static_cast<int>(rInRect.Left()), 
static_cast<int>(rInRect.Top()),
                                  static_cast<int>(rInRect.GetWidth()), 
static_cast<int>(rInRect.GetHeight())};
+
+            if (GTK_IS_ICON_VIEW(pWidget))
+            {
+                // GtkIconView is a little weird in its positioning with 
scrolling, so adjust here to match what
+                // it expects
+                gint nOffsetX(0), nOffsetY(0);
+                
gtk_icon_view_convert_widget_to_bin_window_coords(GTK_ICON_VIEW(pWidget), 0, 0, 
&nOffsetX, &nOffsetY);
+                rOutRect.x -= nOffsetX;
+                rOutRect.y -= nOffsetY;
+            }
+
             if (SwapForRTL(pWidget))
                 rOutRect.x = gtk_widget_get_allocated_width(pWidget) - 
rOutRect.width - 1 - rOutRect.x;
         }
@@ -17069,6 +17080,87 @@ private:
         return sRet;
     }
 
+    OUString get(int pos, int col) const
+    {
+        GtkTreeModel* pModel = GTK_TREE_MODEL(m_pTreeStore);
+        OUString sRet;
+        GtkTreeIter iter;
+        if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos))
+            sRet = get(iter, col);
+        return sRet;
+    }
+
+    tools::Rectangle get_rect(int pos) const override
+    {
+        GtkTreeModel* pModel = GTK_TREE_MODEL(m_pTreeStore);
+        GtkTreeIter rIter;
+        if (!gtk_tree_model_iter_nth_child(pModel, &rIter, nullptr, pos))
+            return tools::Rectangle();
+
+        const GtkInstanceTreeIter& rGtkIter = static_cast<const 
GtkInstanceTreeIter&>(rIter);
+        GtkTreePath* path
+            = gtk_tree_model_get_path(pModel, 
const_cast<GtkTreeIter*>(&rGtkIter.iter));
+
+        GdkRectangle aRect;
+        gtk_icon_view_get_cell_rect(m_pIconView, path, nullptr, &aRect);
+        gtk_tree_path_free(path);
+
+        // GtkIconView is a little weird in its positioning with scrolling
+        gtk_icon_view_convert_widget_to_bin_window_coords(m_pIconView, 
aRect.x, aRect.y, &aRect.x,
+                                                          &aRect.y);
+
+        return tools::Rectangle(aRect.x, aRect.y, aRect.x + aRect.width, 
aRect.y + aRect.height);
+    }
+
+    void set_image(int pos, VirtualDevice* pIcon) override
+    {
+        GtkTreeModel* pModel = GTK_TREE_MODEL(m_pTreeStore);
+        GtkTreeIter iter;
+        if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos))
+        {
+            if (pIcon)
+            {
+                GdkPixbuf* pixbuf = getPixbuf(*pIcon);
+                gtk_tree_store_set(m_pTreeStore, &iter, m_nImageCol, pixbuf, 
-1);
+                if (pixbuf)
+                    g_object_unref(pixbuf);
+            }
+        }
+    }
+
+    virtual void set_text(int pos, const OUString& rText) override
+    {
+        GtkTreeModel* pModel = GTK_TREE_MODEL(m_pTreeStore);
+        GtkTreeIter iter;
+        if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos))
+        {
+            OString aStr(OUStringToOString(rText, RTL_TEXTENCODING_UTF8));
+            gtk_tree_store_set(m_pTreeStore, &iter, m_nTextCol, aStr.getStr(), 
-1);
+        }
+    }
+
+    virtual void set_id(int pos, const OUString& rId) override
+    {
+        GtkTreeModel* pModel = GTK_TREE_MODEL(m_pTreeStore);
+        GtkTreeIter iter;
+
+        if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos))
+        {
+            OString aStr(OUStringToOString(rId, RTL_TEXTENCODING_UTF8));
+            gtk_tree_store_set(m_pTreeStore, &iter, m_nIdCol, aStr.getStr(), 
-1);
+        }
+    }
+
+    virtual void remove(int pos) override
+    {
+        disable_notify_events();
+        GtkTreeModel* pModel = GTK_TREE_MODEL(m_pTreeStore);
+        GtkTreeIter iter;
+        if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos))
+            tree_store_remove(pModel, &iter);
+        enable_notify_events();
+    }
+
     bool get_selected_iterator(GtkTreeIter* pIter) const
     {
         assert(gtk_icon_view_get_model(m_pIconView) && "don't request 
selection when frozen");
@@ -17334,6 +17426,13 @@ public:
         return gtk_tree_model_get_iter_first(pModel, &rGtkIter.iter);
     }
 
+    virtual bool iter_next_sibling(weld::TreeIter& rIter) const override
+    {
+        GtkInstanceTreeIter& rGtkIter = 
static_cast<GtkInstanceTreeIter&>(rIter);
+        GtkTreeModel* pModel = GTK_TREE_MODEL(m_pTreeStore);
+        return gtk_tree_model_iter_next(pModel, &rGtkIter.iter);
+    }
+
     virtual void scroll_to_item(const weld::TreeIter& rIter) override
     {
         assert(gtk_icon_view_get_model(m_pIconView) && "don't select when 
frozen, select after thaw. Note selection doesn't survive a freeze");
@@ -17378,6 +17477,8 @@ public:
         return get(rGtkIter.iter, m_nIdCol);
     }
 
+    virtual OUString get_id(int pos) const override { return get(pos, 
m_nIdCol); }
+
     virtual OUString get_text(const weld::TreeIter& rIter) const override
     {
         const GtkInstanceTreeIter& rGtkIter = static_cast<const 
GtkInstanceTreeIter&>(rIter);

Reply via email to