[Libreoffice-commits] core.git: desktop/inc desktop/source desktop/uiconfig include/vcl vcl/source vcl/unx

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Wed Feb 27 21:20:02 UTC 2019


 desktop/inc/bitmaps.hlst                                   |    1 
 desktop/inc/strings.hrc                                    |    3 
 desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx |   14 
 desktop/source/deployment/gui/dp_gui_updatedialog.cxx      |  420 ++++---------
 desktop/source/deployment/gui/dp_gui_updatedialog.hxx      |   86 --
 desktop/uiconfig/ui/updatedialog.ui                        |  106 ++-
 include/vcl/weld.hxx                                       |    9 
 vcl/source/app/salvtables.cxx                              |   30 
 vcl/unx/gtk3/gtk3gtkinst.cxx                               |   32 
 9 files changed, 342 insertions(+), 359 deletions(-)

New commits:
commit 4c3e0b2400c6b101a89f21e2268d5b696770fb9c
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue Feb 26 14:51:34 2019 +0000
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Wed Feb 27 22:19:31 2019 +0100

    weld UpdateDialog
    
    Change-Id: Ieca75774925a8766162481713f6e8a6ba0e9feb0
    Reviewed-on: https://gerrit.libreoffice.org/68396
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/desktop/inc/bitmaps.hlst b/desktop/inc/bitmaps.hlst
index d9dbc0cb47be..7a166d5e0807 100644
--- a/desktop/inc/bitmaps.hlst
+++ b/desktop/inc/bitmaps.hlst
@@ -14,7 +14,6 @@
 #define RID_BMP_LOCKED              "desktop/res/lock_16.png"
 #define RID_BMP_SHARED              "desktop/res/shared_16.png"
 #define RID_BMP_EXTENSION           "desktop/res/extension_32.png"
-#define RID_DLG_UPDATE_NORMALALERT  "desktop/res/caution_12.png"
 
 #endif
 
diff --git a/desktop/inc/strings.hrc b/desktop/inc/strings.hrc
index 6d70648d069a..975a0221eaa1 100644
--- a/desktop/inc/strings.hrc
+++ b/desktop/inc/strings.hrc
@@ -150,9 +150,6 @@
 #define RID_DLG_UPDATE_NODEPENDENCY_CUR_VER                 NC_("RID_DLG_UPDATE_NODEPENDENCY_CUR_VER", "You have %PRODUCTNAME %VERSION")
 #define RID_DLG_UPDATE_BROWSERBASED                         NC_("RID_DLG_UPDATE_BROWSERBASED", "browser based update")
 #define RID_DLG_UPDATE_VERSION                              NC_("RID_DLG_UPDATE_VERSION", "Version")
-#define RID_DLG_UPDATE_IGNORE                               NC_("RID_DLG_UPDATE_IGNORE", "Ignore this Update")
-#define RID_DLG_UPDATE_IGNORE_ALL                           NC_("RID_DLG_UPDATE_IGNORE_ALL", "Ignore all Updates")
-#define RID_DLG_UPDATE_ENABLE                               NC_("RID_DLG_UPDATE_ENABLE", "Enable Updates")
 #define RID_DLG_UPDATE_IGNORED_UPDATE                       NC_("RID_DLG_UPDATE_IGNORED_UPDATE", "This update will be ignored.\n")
 
 #define STR_BOOTSTRAP_ERR_CANNOT_START                      NC_("STR_BOOTSTRAP_ERR_CANNOT_START", "The application cannot be started. ")
diff --git a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx
index e0dc0b36e92b..9d60a0a607db 100644
--- a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx
+++ b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx
@@ -896,11 +896,11 @@ void ExtensionCmdQueue::Thread::_checkForUpdates(
     const SolarMutexGuard guard;
 
     std::vector< UpdateData > vData;
-    ScopedVclPtrInstance<UpdateDialog> pUpdateDialog( m_xContext, m_pDialogHelper? m_pDialogHelper->getWindow() : nullptr, vExtensionList, &vData );
+    UpdateDialog aUpdateDialog(m_xContext, m_pDialogHelper? m_pDialogHelper->getFrameWeld() : nullptr, vExtensionList, &vData);
 
-    pUpdateDialog->notifyMenubar( true, false ); // prepare the checking, if there updates to be notified via menu bar icon
+    aUpdateDialog.notifyMenubar( true, false ); // prepare the checking, if there updates to be notified via menu bar icon
 
-    if ( ( pUpdateDialog->Execute() == RET_OK ) && !vData.empty() )
+    if (aUpdateDialog.run() == RET_OK && !vData.empty())
     {
         // If there is at least one directly downloadable extension then we
         // open the install dialog.
@@ -917,10 +917,10 @@ void ExtensionCmdQueue::Thread::_checkForUpdates(
         {
             UpdateInstallDialog aDlg(m_pDialogHelper? m_pDialogHelper->getFrameWeld() : nullptr, dataDownload, m_xContext);
             nDialogResult = aDlg.run();
-            pUpdateDialog->notifyMenubar( false, true ); // Check, if there are still pending updates to be notified via menu bar icon
+            aUpdateDialog.notifyMenubar( false, true ); // Check, if there are still pending updates to be notified via menu bar icon
         }
         else
-            pUpdateDialog->notifyMenubar( false, false ); // Check, if there are pending updates to be notified via menu bar icon
+            aUpdateDialog.notifyMenubar( false, false ); // Check, if there are pending updates to be notified via menu bar icon
 
         //Now start the webbrowser and navigate to the websites where we get the updates
         if ( RET_OK == nDialogResult )
@@ -933,9 +933,7 @@ void ExtensionCmdQueue::Thread::_checkForUpdates(
         }
     }
     else
-        pUpdateDialog->notifyMenubar( false, false ); // check if there updates to be notified via menu bar icon
-
-    pUpdateDialog.disposeAndClear();
+        aUpdateDialog.notifyMenubar( false, false ); // check if there updates to be notified via menu bar icon
 }
 
 
diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.cxx b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx
index 243ed17fb4f3..47ebe701cd6b 100644
--- a/desktop/source/deployment/gui/dp_gui_updatedialog.cxx
+++ b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx
@@ -127,9 +127,6 @@ namespace {
 
 static sal_Unicode const LF = 0x000A;
 static sal_Unicode const CR = 0x000D;
-static const sal_uInt16 CMD_ENABLE_UPDATE = 1;
-static const sal_uInt16 CMD_IGNORE_UPDATE = 2;
-static const sal_uInt16 CMD_IGNORE_ALL_UPDATES = 3;
 
 #define IGNORED_UPDATES     OUString("/org.openoffice.Office.ExtensionManager/ExtensionUpdateData/IgnoredUpdates")
 #define PROPERTY_VERSION    "Version"
@@ -244,7 +241,7 @@ UpdateDialog::Thread::Thread(
     if( m_context.is() )
     {
         m_xInteractionHdl.set(
-            task::InteractionHandler::createWithParent(m_context, nullptr),
+            task::InteractionHandler::createWithParent(m_context, dialog.getDialog()->GetXWindow()),
             uno::UNO_QUERY );
         m_updateInformation->setInteractionHandler( m_xInteractionHdl );
     }
@@ -463,57 +460,51 @@ bool UpdateDialog::Thread::update(
     return ret;
 }
 
-
 // UpdateDialog ----------------------------------------------------------
 UpdateDialog::UpdateDialog(
     uno::Reference< uno::XComponentContext > const & context,
-    vcl::Window * parent,
-                           const std::vector<uno::Reference< deployment::XPackage > > &vExtensionList,
-    std::vector< dp_gui::UpdateData > * updateData):
-    ModalDialog(parent, "UpdateDialog", "desktop/ui/updatedialog.ui"),
-    m_context(context),
-    m_none(DpResId(RID_DLG_UPDATE_NONE)),
-    m_noInstallable(DpResId(RID_DLG_UPDATE_NOINSTALLABLE)),
-    m_failure(DpResId(RID_DLG_UPDATE_FAILURE)),
-    m_unknownError(DpResId(RID_DLG_UPDATE_UNKNOWNERROR)),
-    m_noDescription(DpResId(RID_DLG_UPDATE_NODESCRIPTION)),
-    m_noInstall(DpResId(RID_DLG_UPDATE_NOINSTALL)),
-    m_noDependency(DpResId(RID_DLG_UPDATE_NODEPENDENCY)),
-    m_noDependencyCurVer(DpResId(RID_DLG_UPDATE_NODEPENDENCY_CUR_VER)),
-    m_browserbased(DpResId(RID_DLG_UPDATE_BROWSERBASED)),
-    m_version(DpResId(RID_DLG_UPDATE_VERSION)),
-    m_ignoredUpdate(DpResId(RID_DLG_UPDATE_IGNORED_UPDATE)),
-    m_updateData(*updateData),
-    m_thread(
-        new UpdateDialog::Thread(
-            context, *this, vExtensionList)),
-    m_bModified( false )
-    // TODO: check!
-//    ,
-//    m_extensionManagerDialog(extensionManagerDialog)
+    weld::Window * parent, const std::vector<uno::Reference< deployment::XPackage > > &vExtensionList,
+    std::vector< dp_gui::UpdateData > * updateData)
+    : GenericDialogController(parent, "desktop/ui/updatedialog.ui", "UpdateDialog")
+    , m_context(context)
+    , m_none(DpResId(RID_DLG_UPDATE_NONE))
+    , m_noInstallable(DpResId(RID_DLG_UPDATE_NOINSTALLABLE))
+    , m_failure(DpResId(RID_DLG_UPDATE_FAILURE))
+    , m_unknownError(DpResId(RID_DLG_UPDATE_UNKNOWNERROR))
+    , m_noDescription(DpResId(RID_DLG_UPDATE_NODESCRIPTION))
+    , m_noInstall(DpResId(RID_DLG_UPDATE_NOINSTALL))
+    , m_noDependency(DpResId(RID_DLG_UPDATE_NODEPENDENCY))
+    , m_noDependencyCurVer(DpResId(RID_DLG_UPDATE_NODEPENDENCY_CUR_VER))
+    , m_browserbased(DpResId(RID_DLG_UPDATE_BROWSERBASED))
+    , m_version(DpResId(RID_DLG_UPDATE_VERSION))
+    , m_ignoredUpdate(DpResId(RID_DLG_UPDATE_IGNORED_UPDATE))
+    , m_updateData(*updateData)
+    , m_thread(new UpdateDialog::Thread(context, *this, vExtensionList))
+    , m_bModified( false )
+    , m_xChecking(m_xBuilder->weld_label("UPDATE_CHECKING"))
+    , m_xThrobber(m_xBuilder->weld_spinner("THROBBER"))
+    , m_xUpdate(m_xBuilder->weld_label("UPDATE_LABEL"))
+    , m_xUpdates(m_xBuilder->weld_tree_view("checklist"))
+    , m_xAll(m_xBuilder->weld_check_button("UPDATE_ALL"))
+    , m_xDescription(m_xBuilder->weld_label("DESCRIPTION_LABEL"))
+    , m_xPublisherLabel(m_xBuilder->weld_label("PUBLISHER_LABEL"))
+    , m_xPublisherLink(m_xBuilder->weld_link_button("PUBLISHER_LINK"))
+    , m_xReleaseNotesLabel(m_xBuilder->weld_label("RELEASE_NOTES_LABEL"))
+    , m_xReleaseNotesLink(m_xBuilder->weld_link_button("RELEASE_NOTES_LINK"))
+    , m_xDescriptions(m_xBuilder->weld_text_view("DESCRIPTIONS"))
+    , m_xOk(m_xBuilder->weld_button("ok"))
+    , m_xClose(m_xBuilder->weld_button("close"))
+    , m_xHelp(m_xBuilder->weld_button("help"))
 {
-    get(m_pchecking, "UPDATE_CHECKING");
-    get(m_pthrobber, "THROBBER");
-    get(m_pUpdate, "UPDATE_LABEL");
-    get(m_pContainer, "UPDATES_CONTAINER");
-    m_pUpdates = VclPtr<UpdateDialog::CheckListBox>::Create(m_pContainer, *this);
-    Size aSize(LogicToPixel(Size(240, 51), MapMode(MapUnit::MapAppFont)));
-    m_pUpdates->set_width_request(aSize.Width());
-    m_pUpdates->set_height_request(aSize.Height());
-    m_pUpdates->Show();
-    get(m_pAll, "UPDATE_ALL");
-    get(m_pDescription, "DESCRIPTION_LABEL");
-    get(m_pPublisherLabel, "PUBLISHER_LABEL");
-    get(m_pPublisherLink, "PUBLISHER_LINK");
-    get(m_pReleaseNotesLabel, "RELEASE_NOTES_LABEL");
-    get(m_pReleaseNotesLink, "RELEASE_NOTES_LINK");
-    get(m_pDescriptions, "DESCRIPTIONS");
-    aSize = LogicToPixel(Size(240, 59), MapMode(MapUnit::MapAppFont));
-    m_pDescriptions->set_width_request(aSize.Width());
-    m_pDescriptions->set_height_request(aSize.Height());
-    get(m_pOk, "INSTALL");
-    get(m_pClose, "close");
-    get(m_pHelp, "help");
+    auto nWidth = m_xDescriptions->get_approximate_digit_width() * 62;
+    auto nHeight = m_xDescriptions->get_height_rows(8);
+    m_xDescriptions->set_size_request(nWidth, nHeight);
+    m_xUpdates->set_size_request(nWidth, nHeight);
+
+    std::vector<int> aWidths;
+    aWidths.push_back(m_xUpdates->get_checkbox_column_width());
+    m_xUpdates->set_column_fixed_widths(aWidths);
+
     OSL_ASSERT(updateData != nullptr);
 
     m_xExtensionManager = deployment::ExtensionManager::get( context );
@@ -528,163 +519,55 @@ UpdateDialog::UpdateDialog(
         throw css::lang::WrappedTargetRuntimeException( e.Message,
                         e.Context, anyEx );
     }
-    m_pUpdates->SetSelectHdl(LINK(this, UpdateDialog, selectionHandler));
-    m_pAll->SetToggleHdl(LINK(this, UpdateDialog, allHandler));
-    m_pOk->SetClickHdl(LINK(this, UpdateDialog, okHandler));
-    m_pClose->SetClickHdl(LINK(this, UpdateDialog, closeHandler));
-    if ( ! dp_misc::office_is_running())
-        m_pHelp->Disable();
+    m_xUpdates->connect_changed(LINK(this, UpdateDialog, selectionHandler));
+    m_xUpdates->connect_toggled(LINK(this, UpdateDialog, entryToggled));
+    m_xAll->connect_toggled(LINK(this, UpdateDialog, allHandler));
+    m_xOk->connect_clicked(LINK(this, UpdateDialog, okHandler));
+    m_xClose->connect_clicked(LINK(this, UpdateDialog, closeHandler));
+    if (!dp_misc::office_is_running())
+        m_xHelp->set_sensitive(false);
 
     initDescription();
     getIgnoredUpdates();
 }
 
-
 UpdateDialog::~UpdateDialog()
 {
-    disposeOnce();
-}
-
-void UpdateDialog::dispose()
-{
     storeIgnoredUpdates();
-
-    m_ListboxEntries.clear();
-    m_ignoredUpdates.clear();
-    m_pUpdates.disposeAndClear();
-    m_pchecking.clear();
-    m_pthrobber.clear();
-    m_pUpdate.clear();
-    m_pContainer.clear();
-    m_pAll.clear();
-    m_pDescription.clear();
-    m_pPublisherLabel.clear();
-    m_pPublisherLink.clear();
-    m_pReleaseNotesLabel.clear();
-    m_pReleaseNotesLink.clear();
-    m_pDescriptions.clear();
-    m_pHelp.clear();
-    m_pOk.clear();
-    m_pClose.clear();
-    ModalDialog::dispose();
 }
 
-
-bool UpdateDialog::Close() {
-    m_thread->stop();
-    return ModalDialog::Close();
-}
-
-short UpdateDialog::Execute() {
-    m_pthrobber->start();
+short UpdateDialog::run() {
+    m_xThrobber->start();
     m_thread->launch();
-    return ModalDialog::Execute();
-}
-
-UpdateDialog::CheckListBox::CheckListBox( vcl::Window* pParent, UpdateDialog & dialog):
-    SvxCheckListBox( pParent, WinBits(WB_BORDER) ),
-    m_ignoreUpdate( DpResId( RID_DLG_UPDATE_IGNORE ) ),
-    m_ignoreAllUpdates( DpResId( RID_DLG_UPDATE_IGNORE_ALL ) ),
-    m_enableUpdate( DpResId( RID_DLG_UPDATE_ENABLE ) ),
-    m_dialog(dialog)
-{
-    SetNormalStaticImage(Image(StockImage::Yes, RID_DLG_UPDATE_NORMALALERT));
-}
-
-sal_uInt16 UpdateDialog::CheckListBox::getItemCount() const {
-    sal_uLong i = GetEntryCount();
-    OSL_ASSERT(i <= std::numeric_limits< sal_uInt16 >::max());
-    return sal::static_int_cast< sal_uInt16 >(i);
-}
-
-
-void UpdateDialog::CheckListBox::MouseButtonDown( MouseEvent const & event )
-{
-    // When clicking on a selected entry in an SvxCheckListBox, the entry's
-    // checkbox is toggled on mouse button down:
-    SvxCheckListBox::MouseButtonDown( event );
-
-    if ( event.IsRight() )
-    {
-        handlePopupMenu( event.GetPosPixel() );
-    }
-
-    m_dialog.enableOk();
-}
-
-
-void UpdateDialog::CheckListBox::MouseButtonUp(MouseEvent const & event) {
-    // When clicking on an entry's checkbox in an SvxCheckListBox, the entry's
-    // checkbox is toggled on mouse button up:
-    SvxCheckListBox::MouseButtonUp(event);
-    m_dialog.enableOk();
-}
-
-void UpdateDialog::CheckListBox::KeyInput(KeyEvent const & event) {
-    SvxCheckListBox::KeyInput(event);
-    m_dialog.enableOk();
+    short nRet = GenericDialogController::run();
+    m_thread->stop();
+    return nRet;
 }
 
-
-void UpdateDialog::CheckListBox::handlePopupMenu( const Point &rPos )
+IMPL_LINK(UpdateDialog, entryToggled, const row_col&, rRowCol, void)
 {
-    SvTreeListEntry *pData = GetEntry( rPos );
-
-    if ( pData )
-    {
-        sal_uLong nEntryPos = GetSelectedEntryPos();
-        UpdateDialog::Index * p = static_cast< UpdateDialog::Index * >( GetEntryData( nEntryPos ) );
+    int nRow = rRowCol.first;
 
-        if ( ( p->m_eKind == ENABLED_UPDATE ) || ( p->m_eKind == DISABLED_UPDATE ) )
-        {
-            ScopedVclPtrInstance<PopupMenu> aPopup;
+    // error's can't be enabled
+    const UpdateDialog::Index* p = reinterpret_cast<UpdateDialog::Index const *>(m_xUpdates->get_id(rRowCol.first).toInt64());
+    if (p->m_eKind == SPECIFIC_ERROR)
+        m_xUpdates->set_toggle(nRow, false, 0);
 
-            if ( p->m_bIgnored )
-                aPopup->InsertItem( CMD_ENABLE_UPDATE, m_enableUpdate );
-            else
-            {
-                aPopup->InsertItem( CMD_IGNORE_UPDATE, m_ignoreUpdate );
-                aPopup->InsertItem( CMD_IGNORE_ALL_UPDATES, m_ignoreAllUpdates );
-            }
-
-            sal_uInt16 aCmd = aPopup->Execute( this, rPos );
-            if ( ( aCmd == CMD_IGNORE_UPDATE ) || ( aCmd == CMD_IGNORE_ALL_UPDATES ) )
-            {
-                p->m_bIgnored = true;
-                if ( p->m_eKind == ENABLED_UPDATE )
-                {
-                    RemoveEntry( nEntryPos );
-                    m_dialog.addAdditional( p, SvLBoxButtonKind::DisabledCheckbox );
-                }
-                if ( aCmd == CMD_IGNORE_UPDATE )
-                    m_dialog.setIgnoredUpdate( p, true, false );
-                else
-                    m_dialog.setIgnoredUpdate( p, true, true );
-                // TODO: reselect entry to display new description!
-            }
-            else if ( aCmd == CMD_ENABLE_UPDATE )
-            {
-                p->m_bIgnored = false;
-                if ( p->m_eKind == ENABLED_UPDATE )
-                {
-                    RemoveEntry( nEntryPos );
-                    m_dialog.insertItem( p, SvLBoxButtonKind::EnabledCheckbox );
-                }
-                m_dialog.setIgnoredUpdate( p, false, false );
-            }
-        }
-    }
+    enableOk();
 }
 
-
-sal_uInt16 UpdateDialog::insertItem( UpdateDialog::Index *pEntry, SvLBoxButtonKind kind )
+sal_uInt16 UpdateDialog::insertItem(UpdateDialog::Index *pEntry, bool bEnabledCheckBox)
 {
-    m_pUpdates->InsertEntry( pEntry->m_aName, TREELIST_APPEND, static_cast< void * >( pEntry ), kind );
+    int nEntry = m_xUpdates->n_children();
+    m_xUpdates->append();
+    m_xUpdates->set_toggle(nEntry, bEnabledCheckBox, 0);
+    m_xUpdates->set_text(nEntry, pEntry->m_aName, 1);
+    m_xUpdates->set_id(nEntry, OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
 
-    for ( sal_uInt16 i = m_pUpdates->getItemCount(); i != 0 ; )
+    for (sal_uInt16 i = nEntry; i != 0 ;)
     {
         i -= 1;
-        UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( m_pUpdates->GetEntryData( i ) );
+        UpdateDialog::Index const * p = reinterpret_cast< UpdateDialog::Index const * >(m_xUpdates->get_id(i).toInt64());
         if ( p == pEntry )
             return i;
     }
@@ -692,21 +575,19 @@ sal_uInt16 UpdateDialog::insertItem( UpdateDialog::Index *pEntry, SvLBoxButtonKi
     return 0;
 }
 
-
-void UpdateDialog::addAdditional( UpdateDialog::Index * index, SvLBoxButtonKind kind )
+void UpdateDialog::addAdditional(UpdateDialog::Index * index, bool bEnabledCheckBox)
 {
-    m_pAll->Enable();
-    if (m_pAll->IsChecked())
+    m_xAll->set_sensitive(true);
+    if (m_xAll->get_active())
     {
-        insertItem( index, kind );
-        m_pUpdate->Enable();
-        m_pUpdates->Enable();
-        m_pDescription->Enable();
-        m_pDescriptions->Enable();
+        insertItem(index, bEnabledCheckBox);
+        m_xUpdate->set_sensitive(true);
+        m_xUpdates->set_sensitive(true);
+        m_xDescription->set_sensitive(true);
+        m_xDescriptions->set_sensitive(true);
     }
 }
 
-
 void UpdateDialog::addEnabledUpdate( OUString const & name,
                                      dp_gui::UpdateData const & data )
 {
@@ -716,21 +597,19 @@ void UpdateDialog::addEnabledUpdate( OUString const & name,
     m_enabledUpdates.push_back( data );
     m_ListboxEntries.emplace_back( pEntry );
 
-    if ( ! isIgnoredUpdate( pEntry ) )
+    if (!isIgnoredUpdate(pEntry))
     {
-        sal_uInt16 nPos = insertItem( pEntry, SvLBoxButtonKind::EnabledCheckbox );
-        m_pUpdates->CheckEntryPos( nPos );
+        insertItem(pEntry, true);
     }
     else
-        addAdditional( pEntry, SvLBoxButtonKind::DisabledCheckbox );
+        addAdditional(pEntry, false);
 
-    m_pUpdate->Enable();
-    m_pUpdates->Enable();
-    m_pDescription->Enable();
-    m_pDescriptions->Enable();
+    m_xUpdate->set_sensitive(true);
+    m_xUpdates->set_sensitive(true);
+    m_xDescription->set_sensitive(true);
+    m_xDescriptions->set_sensitive(true);
 }
 
-
 void UpdateDialog::addDisabledUpdate( UpdateDialog::DisabledUpdate const & data )
 {
     sal_uInt16 nIndex = sal::static_int_cast< sal_uInt16 >( m_disabledUpdates.size() );
@@ -740,10 +619,9 @@ void UpdateDialog::addDisabledUpdate( UpdateDialog::DisabledUpdate const & data
     m_ListboxEntries.emplace_back( pEntry );
 
     isIgnoredUpdate( pEntry );
-    addAdditional( pEntry, SvLBoxButtonKind::DisabledCheckbox );
+    addAdditional(pEntry, false);
 }
 
-
 void UpdateDialog::addSpecificError( UpdateDialog::SpecificError const & data )
 {
     sal_uInt16 nIndex = sal::static_int_cast< sal_uInt16 >( m_specificErrors.size() );
@@ -752,18 +630,18 @@ void UpdateDialog::addSpecificError( UpdateDialog::SpecificError const & data )
     m_specificErrors.push_back( data );
     m_ListboxEntries.emplace_back( pEntry );
 
-    addAdditional( pEntry, SvLBoxButtonKind::StaticImage);
+    addAdditional(pEntry, false);
 }
 
 void UpdateDialog::checkingDone() {
-    m_pchecking->Hide();
-    m_pthrobber->stop();
-    m_pthrobber->Hide();
-    if (m_pUpdates->getItemCount() == 0)
+    m_xChecking->hide();
+    m_xThrobber->stop();
+    m_xThrobber->hide();
+    if (m_xUpdates->n_children() == 0)
     {
         clearDescription();
-        m_pDescription->Enable();
-        m_pDescriptions->Enable();
+        m_xDescription->set_sensitive(true);
+        m_xDescriptions->set_sensitive(true);
 
         if ( m_disabledUpdates.empty() && m_specificErrors.empty() && m_ignoredUpdates.empty() )
             showDescription( m_none );
@@ -775,8 +653,13 @@ void UpdateDialog::checkingDone() {
 }
 
 void UpdateDialog::enableOk() {
-    if (!m_pchecking->IsVisible()) {
-        m_pOk->Enable(m_pUpdates->GetCheckedEntryCount() != 0);
+    if (!m_xChecking->get_visible()) {
+        int nChecked = 0;
+        for (int i = 0, nCount = m_xUpdates->n_children(); i < nCount; ++i) {
+            if (m_xUpdates->get_toggle(i, 0))
+                ++nChecked;
+        }
+        m_xOk->set_sensitive(nChecked != 0);
     }
 }
 
@@ -850,11 +733,11 @@ void UpdateDialog::notifyMenubar( bool bPrepareOnly, bool bRecheckOnly )
     if ( ! bRecheckOnly )
     {
         sal_Int32 nCount = 0;
-        for ( sal_uInt16 i = 0; i < m_pUpdates->getItemCount(); ++i )
+        for (sal_uInt16 i = 0, nItemCount = m_xUpdates->n_children(); i < nItemCount; ++i)
         {
             uno::Sequence< OUString > aItem(2);
 
-            UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >(m_pUpdates->GetEntryData(i));
+            UpdateDialog::Index const * p = reinterpret_cast< UpdateDialog::Index const * >(m_xUpdates->get_id(i).toInt64());
 
             if ( p->m_eKind == ENABLED_UPDATE )
             {
@@ -881,22 +764,22 @@ void UpdateDialog::notifyMenubar( bool bPrepareOnly, bool bRecheckOnly )
 
 void UpdateDialog::initDescription()
 {
-    m_pPublisherLabel->Hide();
-    m_pPublisherLink->Hide();
-    m_pReleaseNotesLabel->Hide();
-    m_pReleaseNotesLink->Hide();
+    m_xPublisherLabel->hide();
+    m_xPublisherLink->hide();
+    m_xReleaseNotesLabel->hide();
+    m_xReleaseNotesLink->hide();
 }
 
 void UpdateDialog::clearDescription()
 {
-    m_pPublisherLabel->Hide();
-    m_pPublisherLink->Hide();
-    m_pPublisherLink->SetText( "" );
-    m_pPublisherLink->SetURL( "" );
-    m_pReleaseNotesLabel->Hide();
-    m_pReleaseNotesLink->Hide();
-    m_pReleaseNotesLink->SetURL( "" );
-    m_pDescriptions->SetText("");
+    m_xPublisherLabel->hide();
+    m_xPublisherLink->hide();
+    m_xPublisherLink->set_label("");
+    m_xPublisherLink->set_uri("");
+    m_xReleaseNotesLabel->hide();
+    m_xReleaseNotesLink->hide();
+    m_xReleaseNotesLink->set_uri( "" );
+    m_xDescriptions->set_text("");
 }
 
 bool UpdateDialog::showDescription(uno::Reference< xml::dom::XNode > const & aUpdateInfo)
@@ -926,17 +809,17 @@ bool UpdateDialog::showDescription(std::pair< OUString, OUString > const & pairP
 
     if ( !sPub.isEmpty() )
     {
-        m_pPublisherLabel->Show();
-        m_pPublisherLink->Show();
-        m_pPublisherLink->SetText( sPub );
-        m_pPublisherLink->SetURL( sURL );
+        m_xPublisherLabel->show();
+        m_xPublisherLink->show();
+        m_xPublisherLink->set_label(sPub);
+        m_xPublisherLink->set_uri(sURL);
     }
 
     if ( !sReleaseNotes.isEmpty() )
     {
-        m_pReleaseNotesLabel->Show();
-        m_pReleaseNotesLink->Show();
-        m_pReleaseNotesLink->SetURL( sReleaseNotes );
+        m_xReleaseNotesLabel->show();
+        m_xReleaseNotesLink->show();
+        m_xReleaseNotesLink->set_uri( sReleaseNotes );
     }
     return true;
 }
@@ -947,11 +830,10 @@ bool UpdateDialog::showDescription( const OUString& rDescription)
         // nothing to show
         return false;
 
-    m_pDescriptions->SetText( rDescription );
+    m_xDescriptions->set_text(rDescription);
     return true;
 }
 
-
 void UpdateDialog::getIgnoredUpdates()
 {
     uno::Reference< lang::XMultiServiceFactory > xConfig(
@@ -1107,14 +989,16 @@ void UpdateDialog::setIgnoredUpdate( UpdateDialog::Index const *pIndex, bool bIg
 }
 
 
-IMPL_LINK_NOARG(UpdateDialog, selectionHandler, SvTreeListBox*, void)
+IMPL_LINK_NOARG(UpdateDialog, selectionHandler, weld::TreeView&, void)
 {
     OUStringBuffer b;
-    UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >(
-        m_pUpdates->GetSelectedEntryData());
+    int nSelectedPos = m_xUpdates->get_selected_index();
     clearDescription();
 
-    if ( p != nullptr )
+    const UpdateDialog::Index* p = nullptr;
+    if (nSelectedPos != -1)
+        p = reinterpret_cast<UpdateDialog::Index const *>(m_xUpdates->get_id(nSelectedPos).toInt64());
+    if (p != nullptr)
     {
         sal_uInt16 pos = p->m_nIndex;
 
@@ -1205,48 +1089,47 @@ IMPL_LINK_NOARG(UpdateDialog, selectionHandler, SvTreeListBox*, void)
     showDescription( b.makeStringAndClear() );
 }
 
-IMPL_LINK_NOARG(UpdateDialog, allHandler, CheckBox&, void)
+IMPL_LINK_NOARG(UpdateDialog, allHandler, weld::ToggleButton&, void)
 {
-    if (m_pAll->IsChecked())
+    if (m_xAll->get_active())
     {
-        m_pUpdate->Enable();
-        m_pUpdates->Enable();
-        m_pDescription->Enable();
-        m_pDescriptions->Enable();
+        m_xUpdate->set_sensitive(true);
+        m_xUpdates->set_sensitive(true);
+        m_xDescription->set_sensitive(true);
+        m_xDescriptions->set_sensitive(true);
 
         for (auto const& listboxEntry : m_ListboxEntries)
         {
             if ( listboxEntry->m_bIgnored || ( listboxEntry->m_eKind != ENABLED_UPDATE ) )
-                insertItem( listboxEntry.get(), SvLBoxButtonKind::DisabledCheckbox );
+                insertItem(listboxEntry.get(), false);
         }
     }
     else
     {
-        for ( sal_uInt16 i = 0; i < m_pUpdates->getItemCount(); )
+        for (sal_uInt16 i = m_xUpdates->n_children(); i != 0 ;)
         {
-            UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( m_pUpdates->GetEntryData(i) );
+            i -= 1;
+            UpdateDialog::Index const * p = reinterpret_cast< UpdateDialog::Index const * >( m_xUpdates->get_id(i).toInt64() );
             if ( p->m_bIgnored || ( p->m_eKind != ENABLED_UPDATE ) )
             {
-                m_pUpdates->RemoveEntry(i);
-            } else {
-                ++i;
+                m_xUpdates->remove(i);
             }
         }
 
-        if (m_pUpdates->getItemCount() == 0)
+        if (m_xUpdates->n_children() == 0)
         {
             clearDescription();
-            m_pUpdate->Disable();
-            m_pUpdates->Disable();
-            if (m_pchecking->IsVisible())
-                m_pDescription->Disable();
+            m_xUpdate->set_sensitive(false);
+            m_xUpdates->set_sensitive(false);
+            if (m_xChecking->get_visible())
+                m_xDescription->set_sensitive(false);
             else
                 showDescription(m_noInstallable);
         }
     }
 }
 
-IMPL_LINK_NOARG(UpdateDialog, okHandler, Button*, void)
+IMPL_LINK_NOARG(UpdateDialog, okHandler, weld::Button&, void)
 {
     //If users are going to update a shared extension then we need
     //to warn them
@@ -1258,22 +1141,23 @@ IMPL_LINK_NOARG(UpdateDialog, okHandler, Button*, void)
     }
 
 
-    for (sal_uInt16 i = 0; i < m_pUpdates->getItemCount(); ++i) {
+    for (sal_uInt16 i = 0, nCount = m_xUpdates->n_children(); i < nCount; ++i)
+    {
         UpdateDialog::Index const * p =
-            static_cast< UpdateDialog::Index const * >(
-                m_pUpdates->GetEntryData(i));
-        if (p->m_eKind == ENABLED_UPDATE && m_pUpdates->IsChecked(i)) {
+            reinterpret_cast< UpdateDialog::Index const * >(
+                m_xUpdates->get_id(i).toInt64());
+        if (p->m_eKind == ENABLED_UPDATE && m_xUpdates->get_toggle(i, 0)) {
             m_updateData.push_back( m_enabledUpdates[ p->m_nIndex ] );
         }
     }
 
-    EndDialog(RET_OK);
+    m_xDialog->response(RET_OK);
 }
 
-IMPL_LINK_NOARG(UpdateDialog, closeHandler, Button*, void)
+IMPL_LINK_NOARG(UpdateDialog, closeHandler, weld::Button&, void)
 {
     m_thread->stop();
-    EndDialog();
+    m_xDialog->response(RET_CANCEL);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.hxx b/desktop/source/deployment/gui/dp_gui_updatedialog.hxx
index 1b0812a6fc0a..b32797ee158a 100644
--- a/desktop/source/deployment/gui/dp_gui_updatedialog.hxx
+++ b/desktop/source/deployment/gui/dp_gui_updatedialog.hxx
@@ -27,15 +27,8 @@
 #include <com/sun/star/uno/Sequence.hxx>
 #include <rtl/ref.hxx>
 #include <rtl/ustring.hxx>
-#include <vcl/svlbitm.hxx>
-#include <svx/checklbx.hxx>
 #include <tools/link.hxx>
-#include <vcl/layout.hxx>
-#include <vcl/button.hxx>
-#include <vcl/dialog.hxx>
-#include <vcl/fixed.hxx>
-#include <vcl/fixedhyper.hxx>
-#include <vcl/throbber.hxx>
+#include <vcl/weld.hxx>
 
 #include "dp_gui_updatedata.hxx"
 
@@ -57,7 +50,7 @@ namespace dp_gui {
 /**
    The modal “Check for Updates” dialog.
 */
-class UpdateDialog: public ModalDialog {
+class UpdateDialog: public weld::GenericDialogController {
 public:
     /**
        Create an instance.
@@ -79,17 +72,14 @@ public:
     */
     UpdateDialog(
         css::uno::Reference< css::uno::XComponentContext > const & context,
-        vcl::Window * parent,
+        weld::Window * parent,
         const std::vector< css::uno::Reference<
         css::deployment::XPackage > > & vExtensionList,
         std::vector< dp_gui::UpdateData > * updateData);
 
     virtual ~UpdateDialog() override;
-    virtual void dispose() override;
 
-    virtual bool Close() override;
-
-    virtual short Execute() override;
+    virtual short run() override;
 
     void notifyMenubar( bool bPrepareOnly, bool bRecheckOnly );
     static void createNotifyJob( bool bPrepareOnly,
@@ -107,34 +97,10 @@ private:
     class Thread;
     friend class Thread;
 
-    class CheckListBox: public SvxCheckListBox {
-    public:
-        CheckListBox(
-            vcl::Window* pParent, UpdateDialog & dialog);
-
-        sal_uInt16 getItemCount() const;
-
-    private:
-        explicit CheckListBox(UpdateDialog::CheckListBox const &) = delete;
-        void operator =(UpdateDialog::CheckListBox const &) = delete;
-
-        virtual void MouseButtonDown(MouseEvent const & event) override;
-        virtual void MouseButtonUp(MouseEvent const & event) override;
-        virtual void KeyInput(KeyEvent const & event) override;
-
-        void handlePopupMenu( const Point &rPos );
-
-        OUString m_ignoreUpdate;
-        OUString m_ignoreAllUpdates;
-        OUString m_enableUpdate;
-        UpdateDialog & m_dialog;
-    };
-
-
     friend class CheckListBox;
 
-    sal_uInt16 insertItem( UpdateDialog::Index *pIndex, SvLBoxButtonKind kind );
-    void addAdditional( UpdateDialog::Index *pIndex, SvLBoxButtonKind kind );
+    sal_uInt16 insertItem(UpdateDialog::Index *pIndex, bool bEnableCheckBox);
+    void addAdditional(UpdateDialog::Index *pIndex, bool bEnableCheckBox);
     bool isIgnoredUpdate( UpdateDialog::Index *pIndex );
     void setIgnoredUpdate( UpdateDialog::Index const *pIndex, bool bIgnore, bool bIgnoreAll );
 
@@ -159,27 +125,14 @@ private:
         css::xml::dom::XNode > const & aUpdateInfo);
     bool showDescription( const OUString& rDescription);
 
-    DECL_LINK(selectionHandler, SvTreeListBox*, void);
-    DECL_LINK(allHandler, CheckBox&, void);
-    DECL_LINK(okHandler, Button*, void);
-    DECL_LINK(closeHandler, Button*, void);
+    DECL_LINK(selectionHandler, weld::TreeView&, void);
+    DECL_LINK(allHandler, weld::ToggleButton&, void);
+    DECL_LINK(okHandler, weld::Button&, void);
+    DECL_LINK(closeHandler, weld::Button&, void);
+    typedef std::pair<int, int> row_col;
+    DECL_LINK(entryToggled, const row_col&, void);
 
     css::uno::Reference< css::uno::XComponentContext >  m_context;
-    VclPtr<FixedText> m_pchecking;
-    VclPtr<Throbber> m_pthrobber;
-    VclPtr<FixedText> m_pUpdate;
-    VclPtr<VclViewport> m_pContainer;
-    VclPtr<UpdateDialog::CheckListBox> m_pUpdates;
-    VclPtr<CheckBox> m_pAll;
-    VclPtr<FixedText> m_pDescription;
-    VclPtr<FixedText> m_pPublisherLabel;
-    VclPtr<FixedHyperlink> m_pPublisherLink;
-    VclPtr<FixedText> m_pReleaseNotesLabel;
-    VclPtr<FixedHyperlink> m_pReleaseNotesLink;
-    VclPtr<VclMultiLineEdit> m_pDescriptions;
-    VclPtr<HelpButton> m_pHelp;
-    VclPtr<PushButton> m_pOk;
-    VclPtr<PushButton> m_pClose;
     OUString m_none;
     OUString m_noInstallable;
     OUString m_failure;
@@ -201,6 +154,21 @@ private:
     css::uno::Reference< css::deployment::XExtensionManager > m_xExtensionManager;
 
     bool    m_bModified;
+
+    std::unique_ptr<weld::Label> m_xChecking;
+    std::unique_ptr<weld::Spinner> m_xThrobber;
+    std::unique_ptr<weld::Label> m_xUpdate;
+    std::unique_ptr<weld::TreeView> m_xUpdates;
+    std::unique_ptr<weld::CheckButton> m_xAll;
+    std::unique_ptr<weld::Label> m_xDescription;
+    std::unique_ptr<weld::Label> m_xPublisherLabel;
+    std::unique_ptr<weld::LinkButton> m_xPublisherLink;
+    std::unique_ptr<weld::Label> m_xReleaseNotesLabel;
+    std::unique_ptr<weld::LinkButton> m_xReleaseNotesLink;
+    std::unique_ptr<weld::TextView> m_xDescriptions;
+    std::unique_ptr<weld::Button> m_xOk;
+    std::unique_ptr<weld::Button> m_xClose;
+    std::unique_ptr<weld::Button> m_xHelp;
 };
 
 }
diff --git a/desktop/uiconfig/ui/updatedialog.ui b/desktop/uiconfig/ui/updatedialog.ui
index 9efe2d6cce38..683f052965f1 100644
--- a/desktop/uiconfig/ui/updatedialog.ui
+++ b/desktop/uiconfig/ui/updatedialog.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
+<!-- Generated with glade 3.22.1 -->
 <interface domain="dkt">
   <requires lib="gtk+" version="3.18"/>
   <object class="GtkDialog" id="UpdateDialog">
@@ -8,7 +8,13 @@
     <property name="vexpand">True</property>
     <property name="border_width">6</property>
     <property name="title" translatable="yes" context="updatedialog|UpdateDialog">Extension Update</property>
+    <property name="modal">True</property>
+    <property name="default_width">0</property>
+    <property name="default_height">0</property>
     <property name="type_hint">dialog</property>
+    <child>
+      <placeholder/>
+    </child>
     <child internal-child="vbox">
       <object class="GtkBox" id="dialog-vbox1">
         <property name="can_focus">False</property>
@@ -34,7 +40,7 @@
               </packing>
             </child>
             <child>
-              <object class="GtkButton" id="INSTALL">
+              <object class="GtkButton" id="ok">
                 <property name="label" translatable="yes" context="updatedialog|INSTALL">_Install</property>
                 <property name="visible">True</property>
                 <property name="sensitive">False</property>
@@ -73,13 +79,12 @@
           </packing>
         </child>
         <child>
-          <object class="GtkBox" id="box1">
+          <object class="GtkGrid">
             <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>
-            <property name="spacing">6</property>
+            <property name="row_spacing">12</property>
             <child>
               <object class="GtkBox" id="box2">
                 <property name="visible">True</property>
@@ -139,13 +144,54 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow1">
+                  <object class="GtkScrolledWindow" id="checklistwin">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="vscrollbar_policy">never</property>
                     <property name="shadow_type">in</property>
                     <child>
-                      <object class="GtkViewport" id="UPDATES_CONTAINER">
+                      <object class="GtkTreeView" id="checklist">
                         <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="hexpand">True</property>
+                        <property name="vexpand">True</property>
+                        <property name="model">liststore1</property>
+                        <property name="headers_visible">False</property>
+                        <property name="search_column">0</property>
+                        <property name="show_expanders">False</property>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection"/>
+                        </child>
+                        <child>
+                          <object class="GtkTreeViewColumn" id="treeviewcolumn4">
+                            <property name="resizable">True</property>
+                            <property name="spacing">6</property>
+                            <property name="alignment">0.5</property>
+                            <child>
+                              <object class="GtkCellRendererToggle" id="cellrenderer5"/>
+                              <attributes>
+                                <attribute name="visible">3</attribute>
+                                <attribute name="active">0</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkTreeViewColumn" id="treeviewcolumn5">
+                            <property name="resizable">True</property>
+                            <property name="spacing">6</property>
+                            <child>
+                              <object class="GtkCellRendererText" id="cellrenderer4"/>
+                              <attributes>
+                                <attribute name="text">1</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                        </child>
                       </object>
                     </child>
                   </object>
@@ -174,9 +220,8 @@
                 </child>
               </object>
               <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
               </packing>
             </child>
             <child>
@@ -269,15 +314,25 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkTextView" id="DESCRIPTIONS:border">
+                  <object class="GtkScrolledWindow" id="DESCRIPTIONSWIN">
                     <property name="visible">True</property>
-                    <property name="sensitive">False</property>
                     <property name="can_focus">True</property>
                     <property name="hexpand">True</property>
                     <property name="vexpand">True</property>
-                    <property name="editable">False</property>
-                    <property name="cursor_visible">False</property>
-                    <property name="accepts_tab">False</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="GtkTextView" id="DESCRIPTIONS">
+                        <property name="visible">True</property>
+                        <property name="sensitive">False</property>
+                        <property name="can_focus">True</property>
+                        <property name="hexpand">True</property>
+                        <property name="vexpand">True</property>
+                        <property name="editable">False</property>
+                        <property name="wrap_mode">word</property>
+                        <property name="cursor_visible">False</property>
+                        <property name="accepts_tab">False</property>
+                      </object>
+                    </child>
                   </object>
                   <packing>
                     <property name="expand">False</property>
@@ -287,14 +342,13 @@
                 </child>
               </object>
               <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
               </packing>
             </child>
           </object>
           <packing>
-            <property name="expand">True</property>
+            <property name="expand">False</property>
             <property name="fill">True</property>
             <property name="position">1</property>
           </packing>
@@ -303,8 +357,20 @@
     </child>
     <action-widgets>
       <action-widget response="-11">help</action-widget>
-      <action-widget response="0">INSTALL</action-widget>
+      <action-widget response="-5">ok</action-widget>
       <action-widget response="-7">close</action-widget>
     </action-widgets>
   </object>
+  <object class="GtkTreeStore" id="liststore1">
+    <columns>
+      <!-- column-name check1 -->
+      <column type="gboolean"/>
+      <!-- column-name text -->
+      <column type="gchararray"/>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+      <!-- column-name checkvis1 -->
+      <column type="gboolean"/>
+    </columns>
+  </object>
 </interface>
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 4673da099fd6..4802713bb086 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -832,6 +832,13 @@ public:
     void connect_value_changed(const Link<Scale&, void>& rLink) { m_aValueChangedHdl = rLink; }
 };
 
+class VCL_DLLPUBLIC Spinner : virtual public Widget
+{
+public:
+    virtual void start() = 0;
+    virtual void stop() = 0;
+};
+
 class VCL_DLLPUBLIC ProgressBar : virtual public Widget
 {
 public:
@@ -1533,6 +1540,8 @@ public:
     virtual std::unique_ptr<ProgressBar> weld_progress_bar(const OString& id,
                                                            bool bTakeOwnership = false)
         = 0;
+    virtual std::unique_ptr<Spinner> weld_spinner(const OString& id, bool bTakeOwnership = false)
+        = 0;
     virtual std::unique_ptr<Image> weld_image(const OString& id, bool bTakeOwnership = false) = 0;
     virtual std::unique_ptr<Calendar> weld_calendar(const OString& id, bool bTakeOwnership = false)
         = 0;
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index ce61bf6c69e5..325d320704fe 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -53,6 +53,7 @@
 #include <vcl/svtabbx.hxx>
 #include <vcl/tabctrl.hxx>
 #include <vcl/tabpage.hxx>
+#include <vcl/throbber.hxx>
 #include <vcl/treelistentry.hxx>
 #include <vcl/toolkit/unowrap.hxx>
 #include <vcl/weld.hxx>
@@ -1867,6 +1868,29 @@ IMPL_LINK_NOARG(SalInstanceScale, SlideHdl, Slider*, void)
     signal_value_changed();
 }
 
+class SalInstanceSpinner : public SalInstanceWidget, public virtual weld::Spinner
+{
+private:
+    VclPtr<Throbber> m_xThrobber;
+
+public:
+    SalInstanceSpinner(Throbber* pThrobber, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
+        : SalInstanceWidget(pThrobber, pBuilder, bTakeOwnership)
+        , m_xThrobber(pThrobber)
+    {
+    }
+
+    virtual void start() override
+    {
+        m_xThrobber->start();
+    }
+
+    virtual void stop() override
+    {
+        m_xThrobber->stop();
+    }
+};
+
 class SalInstanceProgressBar : public SalInstanceWidget, public virtual weld::ProgressBar
 {
 private:
@@ -4209,6 +4233,12 @@ public:
         return pProgress ? std::make_unique<SalInstanceProgressBar>(pProgress, this, bTakeOwnership) : nullptr;
     }
 
+    virtual std::unique_ptr<weld::Spinner> weld_spinner(const OString &id, bool bTakeOwnership) override
+    {
+        Throbber* pThrobber = m_xBuilder->get<Throbber>(id);
+        return pThrobber ? std::make_unique<SalInstanceSpinner>(pThrobber, this, bTakeOwnership) : nullptr;
+    }
+
     virtual std::unique_ptr<weld::Image> weld_image(const OString &id, bool bTakeOwnership) override
     {
         FixedImage* pImage = m_xBuilder->get<FixedImage>(id);
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index d33c59ba316e..8d9ac7f0e434 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -4818,6 +4818,29 @@ public:
     }
 };
 
+class GtkInstanceSpinner : public GtkInstanceWidget, public virtual weld::Spinner
+{
+private:
+    GtkSpinner* m_pSpinner;
+
+public:
+    GtkInstanceSpinner(GtkSpinner* pSpinner, GtkInstanceBuilder* pBuilder, bool bTakeOwnership)
+        : GtkInstanceWidget(GTK_WIDGET(pSpinner), pBuilder, bTakeOwnership)
+        , m_pSpinner(pSpinner)
+    {
+    }
+
+    virtual void start() override
+    {
+        gtk_spinner_start(m_pSpinner);
+    }
+
+    virtual void stop() override
+    {
+        gtk_spinner_stop(m_pSpinner);
+    }
+};
+
 class GtkInstanceImage : public GtkInstanceWidget, public virtual weld::Image
 {
 private:
@@ -8613,6 +8636,15 @@ public:
         return std::make_unique<GtkInstanceProgressBar>(pProgressBar, this, bTakeOwnership);
     }
 
+    virtual std::unique_ptr<weld::Spinner> weld_spinner(const OString &id, bool bTakeOwnership) override
+    {
+        GtkSpinner* pSpinner = GTK_SPINNER(gtk_builder_get_object(m_pBuilder, id.getStr()));
+        if (!pSpinner)
+            return nullptr;
+        auto_add_parentless_widgets_to_container(GTK_WIDGET(pSpinner));
+        return std::make_unique<GtkInstanceSpinner>(pSpinner, this, bTakeOwnership);
+    }
+
     virtual std::unique_ptr<weld::Image> weld_image(const OString &id, bool bTakeOwnership) override
     {
         GtkImage* pImage = GTK_IMAGE(gtk_builder_get_object(m_pBuilder, id.getStr()));


More information about the Libreoffice-commits mailing list