[Libreoffice-commits] core.git: Branch 'libreoffice-6-2' - cui/source cui/uiconfig include/sfx2 include/vcl sfx2/source vcl/source vcl/unx

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Sat Nov 24 14:41:51 UTC 2018


 cui/source/customize/cfgutil.cxx     |  779 ++++++++++++++++++++++++++++++++++-
 cui/source/customize/macropg.cxx     |   11 
 cui/source/inc/cfgutil.hxx           |   93 ++++
 cui/source/inc/headertablistbox.hxx  |   16 
 cui/source/inc/macroass.hxx          |   14 
 cui/source/tabpages/macroass.cxx     |  272 +++++-------
 cui/uiconfig/ui/eventassignpage.ui   |  191 +++++---
 include/sfx2/sfxhelp.hxx             |    3 
 include/vcl/help.hxx                 |    3 
 include/vcl/weld.hxx                 |    3 
 sfx2/source/appl/sfxhelp.cxx         |   43 +
 sfx2/source/dialog/filedlghelper.cxx |    2 
 vcl/source/app/help.cxx              |    5 
 vcl/source/app/salvtables.cxx        |   26 +
 vcl/source/treelist/treelistbox.cxx  |    4 
 vcl/source/window/builder.cxx        |    2 
 vcl/source/window/menu.cxx           |    4 
 vcl/unx/gtk/salprn-gtk.cxx           |    2 
 vcl/unx/gtk3/gtk3gtkinst.cxx         |   31 +
 19 files changed, 1261 insertions(+), 243 deletions(-)

New commits:
commit 4be36ad16cf8c43c343b8ff3bfc3f58556b00f7f
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Fri Nov 23 09:14:32 2018 +0000
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Sat Nov 24 15:41:30 2018 +0100

    weld SfxMacroTabPage
    
    Change-Id: I167dd233c8af64e31f0e266bac5cf5b9c4658ca6
    Reviewed-on: https://gerrit.libreoffice.org/63893
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit f27bfc190d4105b9d057980a5e6f0eac07f88aba)
    Reviewed-on: https://gerrit.libreoffice.org/63915

diff --git a/cui/source/customize/cfgutil.cxx b/cui/source/customize/cfgutil.cxx
index 828205e31f93..d0900c2ccbab 100644
--- a/cui/source/customize/cfgutil.cxx
+++ b/cui/source/customize/cfgutil.cxx
@@ -330,7 +330,7 @@ OUString SfxConfigFunctionListBox::GetHelpText( bool bConsiderParent )
                 if (bConsiderParent)
                     return Application::GetHelp()->GetHelpText( pData->sCommand, this );
                 else
-                    return Application::GetHelp()->GetHelpText( pData->sCommand, nullptr );
+                    return Application::GetHelp()->GetHelpText( pData->sCommand, static_cast<weld::Widget*>(nullptr) );
             }
             else if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT )
             {
@@ -365,6 +365,108 @@ OUString SfxConfigFunctionListBox::GetCurLabel()
     return pData->sCommand;
 }
 
+CuiConfigFunctionListBox::CuiConfigFunctionListBox(std::unique_ptr<weld::TreeView> xTreeView)
+    : m_xTreeView(std::move(xTreeView))
+{
+    m_xTreeView->make_sorted();
+}
+
+CuiConfigFunctionListBox::~CuiConfigFunctionListBox()
+{
+    ClearAll();
+}
+
+void CuiConfigFunctionListBox::ClearAll()
+/*  Description
+    Deletes all entries in the FunctionListBox, all UserData and all
+    possibly existing MacroInfo.
+*/
+{
+    sal_uInt16 nCount = aArr.size();
+    for ( sal_uInt16 i=0; i<nCount; ++i )
+    {
+        SfxGroupInfo_Impl *pData = aArr[i].get();
+
+        if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT )
+        {
+            OUString* pScriptURI = static_cast<OUString*>(pData->pObject);
+            delete pScriptURI;
+        }
+
+        if ( pData->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER )
+        {
+            XInterface* xi = static_cast<XInterface *>(pData->pObject);
+            if (xi != nullptr)
+            {
+                xi->release();
+            }
+        }
+    }
+
+    aArr.clear();
+    m_xTreeView->clear();
+}
+
+OUString CuiConfigFunctionListBox::GetSelectedScriptURI()
+{
+    int nSelected = m_xTreeView->get_selected_index();
+    if (nSelected != -1)
+    {
+        SfxGroupInfo_Impl *pData = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(nSelected).toInt64());
+        if (pData && pData->nKind == SfxCfgKind::FUNCTION_SCRIPT)
+            return *static_cast<OUString*>(pData->pObject);
+    }
+    return OUString();
+}
+
+OUString CuiConfigFunctionListBox::GetHelpText( bool bConsiderParent )
+{
+    int nSelected = m_xTreeView->get_selected_index();
+    if (nSelected != -1)
+    {
+        SfxGroupInfo_Impl *pData = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(nSelected).toInt64());
+        if ( pData )
+        {
+            if ( pData->nKind == SfxCfgKind::FUNCTION_SLOT )
+            {
+                if (bConsiderParent)
+                    return Application::GetHelp()->GetHelpText(pData->sCommand, m_xTreeView.get());
+                else
+                    return Application::GetHelp()->GetHelpText(pData->sCommand, static_cast<weld::Widget*>(nullptr));
+            }
+            else if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT )
+            {
+                return pData->sHelpText;
+            }
+        }
+    }
+    return OUString();
+}
+
+OUString CuiConfigFunctionListBox::GetCurCommand()
+{
+    int nSelected = m_xTreeView->get_selected_index();
+    if (nSelected == -1)
+        return OUString();
+    SfxGroupInfo_Impl *pData = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(nSelected).toInt64());
+    if (!pData)
+        return OUString();
+    return pData->sCommand;
+}
+
+OUString CuiConfigFunctionListBox::GetCurLabel()
+{
+    int nSelected = m_xTreeView->get_selected_index();
+    if (nSelected == -1)
+        return OUString();
+    SfxGroupInfo_Impl *pData = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(nSelected).toInt64());
+    if (!pData)
+        return OUString();
+    if (!pData->sLabel.isEmpty())
+        return pData->sLabel;
+    return pData->sCommand;
+}
+
 struct SvxConfigGroupBoxResource_Impl
 {
     Image m_hdImage;
@@ -397,6 +499,34 @@ SvxConfigGroupBoxResource_Impl::SvxConfigGroupBoxResource_Impl() :
 {
 }
 
+struct CuiConfigGroupBoxResource_Impl
+{
+    OUString m_hdImage;
+    OUString m_libImage;
+    OUString m_macImage;
+    OUString m_docImage;
+    OUString m_sMyMacros;
+    OUString m_sProdMacros;
+    OUString m_sMacros;
+    OUString m_sDlgMacros;
+    OUString m_aStrGroupStyles;
+
+    CuiConfigGroupBoxResource_Impl();
+};
+
+CuiConfigGroupBoxResource_Impl::CuiConfigGroupBoxResource_Impl() :
+    m_hdImage(RID_CUIBMP_HARDDISK),
+    m_libImage(RID_CUIBMP_LIB),
+    m_macImage(RID_CUIBMP_MACRO),
+    m_docImage(RID_CUIBMP_DOC),
+    m_sMyMacros(CuiResId(RID_SVXSTR_MYMACROS)),
+    m_sProdMacros(CuiResId(RID_SVXSTR_PRODMACROS)),
+    m_sMacros(CuiResId(RID_SVXSTR_BASICMACROS)),
+    m_sDlgMacros(CuiResId(RID_SVXSTR_PRODMACROS)),
+    m_aStrGroupStyles(CuiResId(RID_SVXSTR_GROUP_STYLES))
+{
+}
+
 SfxConfigGroupListBox::SfxConfigGroupListBox(vcl::Window* pParent, WinBits nStyle)
     : SvTreeListBox(pParent, nStyle)
     , xImp(new SvxConfigGroupBoxResource_Impl())
@@ -1133,6 +1263,653 @@ void SfxConfigGroupListBox::SelectMacro( const OUString& rBasic,
     }
 }
 
+CuiConfigGroupListBox::CuiConfigGroupListBox(std::unique_ptr<weld::TreeView> xTreeView)
+    : xImp(new CuiConfigGroupBoxResource_Impl())
+    , m_pFunctionListBox(nullptr)
+    , m_pStylesInfo(nullptr)
+    , m_xTreeView(std::move(xTreeView))
+{
+    m_xTreeView->connect_row_activated(LINK(this, CuiConfigGroupListBox, OpenCurrentHdl));
+    m_xTreeView->connect_expanding(LINK(this, CuiConfigGroupListBox, ExpandingHdl));
+}
+
+IMPL_LINK_NOARG(CuiConfigGroupListBox, OpenCurrentHdl, weld::TreeView&, void)
+{
+    std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
+    bool bValidIter = m_xTreeView->get_cursor(xIter.get());
+    if (!bValidIter)
+        return;
+    m_xTreeView->expand_row(*xIter);
+}
+
+CuiConfigGroupListBox::~CuiConfigGroupListBox()
+{
+    ClearAll();
+}
+
+void CuiConfigGroupListBox::ClearAll()
+{
+    sal_uInt16 nCount = aArr.size();
+    for ( sal_uInt16 i=0; i<nCount; ++i )
+    {
+        SfxGroupInfo_Impl *pData = aArr[i].get();
+        if (pData->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER)
+        {
+            XInterface* xi = static_cast<XInterface *>(pData->pObject);
+            if (xi != nullptr)
+            {
+                xi->release();
+            }
+        }
+    }
+
+    aArr.clear();
+    m_xTreeView->clear();
+}
+
+void CuiConfigGroupListBox::SetStylesInfo(SfxStylesInfo_Impl* pStyles)
+{
+    m_pStylesInfo = pStyles;
+}
+
+void CuiConfigGroupListBox::InitModule()
+{
+    try
+    {
+        css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider(m_xFrame, css::uno::UNO_QUERY_THROW);
+        css::uno::Sequence< sal_Int16 > lGroups = xProvider->getSupportedCommandGroups();
+        sal_Int32                       c1      = lGroups.getLength();
+        sal_Int32                       i1      = 0;
+
+        if ( c1 )
+        {
+            // Add All Commands category
+            aArr.push_back(o3tl::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_ALLFUNCTIONS, 0));
+            m_xTreeView->append(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get())),
+                                CuiResId(RID_SVXSTR_ALLFUNCTIONS));
+        }
+
+        for (i1=0; i1<c1; ++i1)
+        {
+            sal_Int16&      rGroupID   = lGroups[i1];
+            OUString sGroupID   = OUString::number(rGroupID);
+            OUString sGroupName ;
+
+            try
+            {
+                m_xModuleCategoryInfo->getByName(sGroupID) >>= sGroupName;
+                if (sGroupName.isEmpty())
+                    continue;
+            }
+            catch(const css::container::NoSuchElementException&)
+                { continue; }
+
+            aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_FUNCTION, rGroupID ) );
+            m_xTreeView->append(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get())),
+                                sGroupName);
+        }
+    }
+    catch(const css::uno::RuntimeException&)
+        { throw; }
+    catch(const css::uno::Exception&)
+        {}
+}
+
+void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::script::browse::XBrowseNode >& xRootNode,
+                                           weld::TreeIter* pParentEntry, bool bCheapChildrenOnDemand)
+{
+    try {
+        if ( xRootNode->hasChildNodes() )
+        {
+            // tdf#120362: Don't ask to enable disabled Java when filling script list
+            css::uno::ContextLayer layer(
+                new comphelper::NoEnableJavaInteractionContext(css::uno::getCurrentContext()));
+
+            Sequence< Reference< browse::XBrowseNode > > children =
+                xRootNode->getChildNodes();
+            bool bIsRootNode = false;
+
+            OUString user("user");
+            OUString share("share");
+            if ( xRootNode->getName() == "Root" )
+            {
+                bIsRootNode = true;
+            }
+
+            //To mimic current starbasic behaviour we
+            //need to make sure that only the current document
+            //is displayed in the config tree. Tests below
+            //set the bDisplay flag to FALSE if the current
+            //node is a first level child of the Root and is NOT
+            //either the current document, user or share
+            OUString currentDocTitle;
+            Reference< XModel > xDocument( lcl_getScriptableDocument_nothrow( m_xFrame ) );
+            if ( xDocument.is() )
+            {
+                currentDocTitle = ::comphelper::DocumentInfo::getDocumentTitle( xDocument );
+            }
+
+            for ( sal_Int32 n = 0; n < children.getLength(); ++n )
+            {
+                Reference< browse::XBrowseNode >& theChild = children[n];
+                bool bDisplay = true;
+                OUString uiName = theChild->getName();
+                if ( bIsRootNode )
+                {
+                    if (  ! (theChild->getName() == user  || theChild->getName() == share ||
+                             theChild->getName() == currentDocTitle ) )
+                    {
+                        bDisplay=false;
+                    }
+                    else
+                    {
+                        if ( uiName == user )
+                        {
+                            uiName = xImp->m_sMyMacros;
+                        }
+                        else if ( uiName == share )
+                        {
+                            uiName = xImp->m_sProdMacros;
+                        }
+                    }
+                }
+                if (children[n]->getType() != browse::BrowseNodeTypes::SCRIPT  && bDisplay )
+                {
+//                  We call acquire on the XBrowseNode so that it does not
+//                  get autodestructed and become invalid when accessed later.
+                    theChild->acquire();
+
+                    bool bChildOnDemand = false;
+                    if ( !bCheapChildrenOnDemand && children[n]->hasChildNodes() )
+                    {
+                        Sequence< Reference< browse::XBrowseNode > > grandchildren =
+                            children[n]->getChildNodes();
+
+                        for ( sal_Int32 m = 0; m < grandchildren.getLength(); ++m )
+                        {
+                            if ( grandchildren[m]->getType() == browse::BrowseNodeTypes::CONTAINER )
+                            {
+                                bChildOnDemand = true;
+                                m = grandchildren.getLength();
+                            }
+                        }
+                    }
+                    else
+                    {
+                        /* i30923 - Would be nice if there was a better
+                        * way to determine if a basic lib had children
+                        * without having to ask for them (which forces
+                        * the library to be loaded */
+                        bChildOnDemand = true;
+                    }
+
+                    OUString aImage = GetImage(theChild, m_xContext, bIsRootNode);
+
+                    aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_SCRIPTCONTAINER,
+                            0, static_cast<void *>( theChild.get())));
+
+                    OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get())));
+                    m_xTreeView->insert(pParentEntry, -1, uiName, &sId, nullptr, nullptr, &aImage, bChildOnDemand);
+                }
+            }
+        }
+    }
+    catch (RuntimeException&) {
+        // do nothing, the entry will not be displayed in the UI
+    }
+}
+
+void CuiConfigGroupListBox::FillFunctionsList(const css::uno::Sequence<DispatchInformation>& xCommands)
+{
+    for (const auto & rInfo : xCommands)
+    {
+        OUString sUIName = MapCommand2UIName(rInfo.Command);
+        aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SLOT, 0 ) );
+        SfxGroupInfo_Impl* pGrpInfo = aArr.back().get();
+        pGrpInfo->sCommand = rInfo.Command;
+        pGrpInfo->sLabel   = sUIName;
+        m_pFunctionListBox->append(OUString::number(reinterpret_cast<sal_Int64>(pGrpInfo)), sUIName);
+    }
+}
+
+void CuiConfigGroupListBox::Init(const css::uno::Reference< css::uno::XComponentContext >& xContext,
+    const css::uno::Reference< css::frame::XFrame >& xFrame,
+    const OUString& sModuleLongName,
+    bool bEventMode)
+{
+    m_xTreeView->freeze();
+    ClearAll(); // Remove all old entries from treelist box
+
+    m_xContext = xContext;
+    m_xFrame = xFrame;
+    if( bEventMode )
+    {
+        m_sModuleLongName = sModuleLongName;
+        m_xGlobalCategoryInfo = css::ui::theUICategoryDescription::get( m_xContext );
+        m_xModuleCategoryInfo.set(m_xGlobalCategoryInfo->getByName(m_sModuleLongName), css::uno::UNO_QUERY_THROW);
+        m_xUICmdDescription   = css::frame::theUICommandDescription::get( m_xContext );
+
+        InitModule();
+    }
+
+    SAL_INFO("cui.customize", "** ** About to initialise SF Scripts");
+    // Add Scripting Framework entries
+    Reference< browse::XBrowseNode > rootNode;
+    try
+    {
+        Reference< browse::XBrowseNodeFactory > xFac = browse::theBrowseNodeFactory::get( m_xContext );
+        rootNode.set( xFac->createView( browse::BrowseNodeFactoryViewTypes::MACROSELECTOR ) );
+    }
+    catch( Exception& e )
+    {
+        SAL_INFO("cui.customize", "Caught some exception whilst retrieving browse nodes from factory... Exception: " << e);
+        // TODO exception handling
+    }
+
+
+    if ( rootNode.is() )
+    {
+        if ( bEventMode )
+        {
+                //We call acquire on the XBrowseNode so that it does not
+                //get autodestructed and become invalid when accessed later.
+            rootNode->acquire();
+
+            aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_SCRIPTCONTAINER, 0,
+                    static_cast<void *>(rootNode.get())));
+            OUString aTitle(xImp->m_sDlgMacros);
+            OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get())));
+            m_xTreeView->insert(nullptr, -1, aTitle, &sId, nullptr, nullptr, nullptr, true);
+        }
+        else
+        {
+             //We are only showing scripts not slot APIs so skip
+             //Root node and show location nodes
+            FillScriptList(rootNode, nullptr, false);
+        }
+    }
+
+    // add styles
+    if ( bEventMode )
+    {
+        aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, nullptr ) ); // TODO last parameter should contain user data
+        OUString sStyle(xImp->m_aStrGroupStyles);
+        OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get())));
+        m_xTreeView->insert(nullptr, -1, sStyle, &sId, nullptr, nullptr, nullptr, true);
+    }
+
+    m_xTreeView->scroll_to_row(0);
+    m_xTreeView->thaw();
+    m_xTreeView->select(0);
+}
+
+OUString CuiConfigGroupListBox::GetImage(
+    const Reference< browse::XBrowseNode >& node,
+    Reference< XComponentContext > const & xCtx,
+    bool bIsRootNode)
+{
+    OUString aImage;
+    if ( bIsRootNode )
+    {
+        if (node->getName() == "user" || node->getName() == "share" )
+        {
+            aImage = xImp->m_hdImage;
+        }
+        else
+        {
+            OUString factoryURL;
+            OUString nodeName = node->getName();
+            Reference<XInterface> xDocumentModel = getDocumentModel(xCtx, nodeName );
+            if ( xDocumentModel.is() )
+            {
+                Reference< frame::XModuleManager2 > xModuleManager( frame::ModuleManager::create(xCtx) );
+                // get the long name of the document:
+                OUString appModule( xModuleManager->identify(
+                                    xDocumentModel ) );
+                Sequence<beans::PropertyValue> moduleDescr;
+                Any aAny = xModuleManager->getByName(appModule);
+                if( !( aAny >>= moduleDescr ) )
+                {
+                    throw RuntimeException("SFTreeListBox::Init: failed to get PropertyValue");
+                }
+                beans::PropertyValue const * pmoduleDescr =
+                    moduleDescr.getConstArray();
+                for ( sal_Int32 pos = moduleDescr.getLength(); pos--; )
+                {
+                    if ( pmoduleDescr[ pos ].Name == "ooSetupFactoryEmptyDocumentURL" )
+                    {
+                        pmoduleDescr[ pos ].Value >>= factoryURL;
+                        SAL_INFO("cui.customize", "factory url for doc images is " << factoryURL);
+                        break;
+                    }
+                }
+            }
+            if( !factoryURL.isEmpty() )
+            {
+                aImage = SvFileInformationManager::GetFileImageId(INetURLObject(factoryURL));
+            }
+            else
+            {
+                aImage = xImp->m_docImage;
+            }
+        }
+    }
+    else
+    {
+        if( node->getType() == browse::BrowseNodeTypes::SCRIPT )
+            aImage = xImp->m_macImage;
+        else
+            aImage = xImp->m_libImage;
+    }
+    return aImage;
+}
+
+Reference< XInterface  >
+CuiConfigGroupListBox::getDocumentModel( Reference< XComponentContext > const & xCtx, OUString const & docName )
+{
+    Reference< XInterface > xModel;
+    Reference< frame::XDesktop2 > desktop = frame::Desktop::create( xCtx );
+
+    Reference< container::XEnumerationAccess > componentsAccess =
+        desktop->getComponents();
+    Reference< container::XEnumeration > components =
+        componentsAccess->createEnumeration();
+    while (components->hasMoreElements())
+    {
+        Reference< frame::XModel > model(
+            components->nextElement(), UNO_QUERY );
+        if ( model.is() )
+        {
+            OUString sTdocUrl =
+                ::comphelper::DocumentInfo::getDocumentTitle( model );
+            if( sTdocUrl == docName )
+            {
+                xModel = model;
+                break;
+            }
+        }
+    }
+    return xModel;
+}
+
+OUString CuiConfigGroupListBox::MapCommand2UIName(const OUString& sCommand)
+{
+    OUString sUIName;
+    try
+    {
+        css::uno::Reference< css::container::XNameAccess > xModuleConf;
+        m_xUICmdDescription->getByName(m_sModuleLongName) >>= xModuleConf;
+        if (xModuleConf.is())
+        {
+            ::comphelper::SequenceAsHashMap lProps(xModuleConf->getByName(sCommand));
+            sUIName = lProps.getUnpackedValueOrDefault("Name", OUString());
+        }
+    }
+    catch(const css::uno::RuntimeException&)
+        { throw; }
+    catch(css::uno::Exception&)
+        { sUIName.clear(); }
+
+    // fallback for missing UINames !?
+    if (sUIName.isEmpty())
+    {
+        sUIName = sCommand;
+    }
+
+    return sUIName;
+}
+
+void CuiConfigGroupListBox::GroupSelected()
+/*  Description
+    A function group or a basic module has been selected.
+    All functions/macros are displayed in the functionlistbox.
+*/
+{
+    std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
+    if (!m_xTreeView->get_selected(xIter.get()))
+        return;
+
+    SfxGroupInfo_Impl *pInfo = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(*xIter).toInt64());
+    m_pFunctionListBox->freeze();
+    m_pFunctionListBox->ClearAll();
+
+    switch ( pInfo->nKind )
+    {
+        case SfxCfgKind::GROUP_ALLFUNCTIONS:
+        {
+            css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider( m_xFrame, UNO_QUERY );
+            bool bValidIter = m_xTreeView->get_iter_first(*xIter);
+            while (bValidIter)
+            {
+                SfxGroupInfo_Impl *pCurrentInfo = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(*xIter).toInt64());
+                if (pCurrentInfo->nKind == SfxCfgKind::GROUP_FUNCTION)
+                {
+                    css::uno::Sequence< css::frame::DispatchInformation > lCommands;
+                    try
+                    {
+                        lCommands = xProvider->getConfigurableDispatchInformation( pCurrentInfo->nUniqueID );
+                        FillFunctionsList( lCommands );
+                    }
+                    catch ( container::NoSuchElementException& )
+                    {
+                    }
+                }
+                bValidIter = m_xTreeView->iter_next(*xIter);
+            }
+            break;
+        }
+
+        case SfxCfgKind::GROUP_FUNCTION :
+        {
+            sal_uInt16                                                          nGroup    = pInfo->nUniqueID;
+            css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider (m_xFrame, css::uno::UNO_QUERY_THROW);
+            css::uno::Sequence< css::frame::DispatchInformation >           lCommands = xProvider->getConfigurableDispatchInformation(nGroup);
+            FillFunctionsList( lCommands );
+            break;
+        }
+
+        case SfxCfgKind::GROUP_SCRIPTCONTAINER:
+        {
+            if (!m_xTreeView->iter_has_child(*xIter))
+            {
+                Reference< browse::XBrowseNode > rootNode(
+                    static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ;
+
+                try {
+                    if ( rootNode->hasChildNodes() )
+                    {
+                        Sequence< Reference< browse::XBrowseNode > > children =
+                            rootNode->getChildNodes();
+
+                        for ( sal_Int32 n = 0; n < children.getLength(); ++n )
+                        {
+                            if (children[n]->getType() == browse::BrowseNodeTypes::SCRIPT)
+                            {
+                                OUString uri, description;
+
+                                Reference < beans::XPropertySet >xPropSet( children[n], UNO_QUERY );
+                                if (!xPropSet.is())
+                                {
+                                    continue;
+                                }
+
+                                Any value =
+                                    xPropSet->getPropertyValue("URI");
+                                value >>= uri;
+
+                                try
+                                {
+                                    value = xPropSet->getPropertyValue("Description");
+                                    value >>= description;
+                                }
+                                catch (Exception &) {
+                                    // do nothing, the description will be empty
+                                }
+
+                                OUString* pScriptURI = new OUString( uri );
+
+                                OUString aImage = GetImage(children[n], Reference< XComponentContext >(), false);
+                                m_pFunctionListBox->aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI ));
+                                m_pFunctionListBox->aArr.back()->sCommand = uri;
+                                m_pFunctionListBox->aArr.back()->sLabel = children[n]->getName();
+                                m_pFunctionListBox->aArr.back()->sHelpText = description;
+
+                                OUString sId(OUString::number(reinterpret_cast<sal_Int64>(m_pFunctionListBox->aArr.back().get())));
+                                m_pFunctionListBox->append(sId, children[n]->getName(), aImage);
+                            }
+                        }
+                    }
+                }
+                catch (RuntimeException&) {
+                    // do nothing, the entry will not be displayed in the UI
+                }
+            }
+            break;
+        }
+
+        case SfxCfgKind::GROUP_STYLES :
+        {
+            SfxStyleInfo_Impl* pFamily = static_cast<SfxStyleInfo_Impl*>(pInfo->pObject);
+            if (pFamily)
+            {
+                const std::vector< SfxStyleInfo_Impl > lStyles = m_pStylesInfo->getStyles(pFamily->sFamily);
+                for (auto const& lStyle : lStyles)
+                {
+                    SfxStyleInfo_Impl* pStyle = new SfxStyleInfo_Impl(lStyle);
+                    m_pFunctionListBox->aArr.push_back(o3tl::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_STYLES, 0, pStyle));
+                    m_pFunctionListBox->aArr.back()->sCommand = pStyle->sCommand;
+                    m_pFunctionListBox->aArr.back()->sLabel = pStyle->sLabel;
+                    OUString sId(OUString::number(reinterpret_cast<sal_Int64>(m_pFunctionListBox->aArr.back().get())));
+                    m_pFunctionListBox->append(sId, pStyle->sLabel);
+                }
+            }
+            break;
+        }
+
+        default:
+            // Do nothing, the list box will stay empty
+            SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " <<  static_cast<int>(pInfo->nKind) );
+            break;
+    }
+
+    m_pFunctionListBox->thaw();
+
+    if (m_pFunctionListBox->n_children())
+        m_pFunctionListBox->select(0);
+}
+
+/*  Description
+    A basic or a library is opened.
+*/
+IMPL_LINK(CuiConfigGroupListBox, ExpandingHdl, weld::TreeIter&, rIter, bool)
+{
+    SfxGroupInfo_Impl *pInfo = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(rIter).toInt64());
+    switch ( pInfo->nKind )
+    {
+        case SfxCfgKind::GROUP_SCRIPTCONTAINER:
+        {
+            if (!m_xTreeView->iter_has_child(rIter))
+            {
+                Reference< browse::XBrowseNode > rootNode(
+                    static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ;
+                FillScriptList(rootNode, &rIter, true /* i30923 */ );
+            }
+            break;
+        }
+
+        case SfxCfgKind::GROUP_STYLES:
+        {
+            if (!m_xTreeView->iter_has_child(rIter))
+            {
+                const std::vector<SfxStyleInfo_Impl> lStyleFamilies = m_pStylesInfo->getStyleFamilies();
+                for (auto const& lStyleFamily : lStyleFamilies)
+                {
+                    SfxStyleInfo_Impl* pFamily = new SfxStyleInfo_Impl(lStyleFamily);
+                    aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, pFamily ));
+                    OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get())));
+                    m_xTreeView->insert(&rIter, -1, pFamily->sLabel, &sId, nullptr, nullptr, nullptr, false);
+                }
+            }
+            break;
+        }
+
+        default:
+            OSL_FAIL( "Wrong group type!" );
+            break;
+    }
+    return true;
+}
+
+void CuiConfigGroupListBox::SelectMacro( const SfxMacroInfoItem *pItem )
+{
+    SelectMacro( pItem->GetBasicManager()->GetName(),
+                 pItem->GetQualifiedName() );
+}
+
+void CuiConfigGroupListBox::SelectMacro( const OUString& rBasic,
+         const OUString& rMacro )
+{
+    const OUString aBasicName(rBasic + " " + xImp->m_sMacros);
+    const sal_Int32 nCount = comphelper::string::getTokenCount(rMacro, '.');
+    const OUString aMethod( rMacro.copy(rMacro.lastIndexOf('.')+1) );
+    OUString aLib;
+    OUString aModule;
+    if ( nCount > 2 )
+    {
+        aLib = rMacro.getToken( 0, '.' );
+        aModule = rMacro.getToken( nCount-2, '.' );
+    }
+
+    std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
+    bool bValidIter = m_xTreeView->get_iter_first(*xIter);
+    while (bValidIter)
+    {
+        OUString aEntryBas = m_xTreeView->get_text(*xIter);
+        if (aEntryBas == aBasicName)
+        {
+            m_xTreeView->expand_row(*xIter);
+            std::unique_ptr<weld::TreeIter> xLibIter(m_xTreeView->make_iterator(xIter.get()));
+            bool bValidLibIter = m_xTreeView->iter_children(*xLibIter);
+            while (bValidLibIter)
+            {
+                OUString aEntryLib = m_xTreeView->get_text(*xLibIter);
+                if (aEntryLib == aLib)
+                {
+                    m_xTreeView->expand_row(*xLibIter);
+                    std::unique_ptr<weld::TreeIter> xModIter(m_xTreeView->make_iterator(xLibIter.get()));
+                    bool bValidModIter = m_xTreeView->iter_children(*xModIter);
+                    while (bValidModIter)
+                    {
+                        OUString aEntryMod = m_xTreeView->get_text(*xModIter);
+                        if (aEntryMod == aModule)
+                        {
+                            m_xTreeView->expand_row(*xModIter);
+                            m_xTreeView->scroll_to_row(*xModIter);
+                            m_xTreeView->select(*xModIter);
+                            std::unique_ptr<weld::TreeIter> xMethodIter(m_pFunctionListBox->make_iterator());
+                            bool bValidMethodIter = m_pFunctionListBox->get_iter_first(*xMethodIter);
+                            while (bValidMethodIter)
+                            {
+                                OUString aEntryMethod = m_pFunctionListBox->get_text(*xMethodIter);
+                                if (aEntryMethod == aMethod)
+                                {
+                                    m_pFunctionListBox->scroll_to_row(*xMethodIter);
+                                    m_pFunctionListBox->select(*xMethodIter);
+                                    return;
+                                }
+                                bValidMethodIter = m_pFunctionListBox->iter_next(*xMethodIter);
+                            }
+                        }
+                        bValidModIter = m_xTreeView->iter_next_sibling(*xModIter);
+                    }
+                }
+                bValidLibIter = m_xTreeView->iter_next_sibling(*xLibIter);
+            }
+        }
+        bValidIter = m_xTreeView->iter_next_sibling(*xIter);
+    }
+}
+
 /*
  * Implementation of SvxScriptSelectorDialog
  *
diff --git a/cui/source/customize/macropg.cxx b/cui/source/customize/macropg.cxx
index 3defde6cce9f..3786f11c0692 100644
--- a/cui/source/customize/macropg.cxx
+++ b/cui/source/customize/macropg.cxx
@@ -195,6 +195,17 @@ void MacroEventListBox::Enable()
     maHeaderBar->Enable();
 }
 
+CuiMacroEventListBox::CuiMacroEventListBox(std::unique_ptr<weld::TreeView> xTreeView)
+    : m_xTreeView(std::move(xTreeView))
+{
+    m_xTreeView->set_help_id(HID_MACRO_HEADERTABLISTBOX);
+    m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 40, m_xTreeView->get_height_rows(9));
+}
+
+CuiMacroEventListBox::~CuiMacroEventListBox()
+{
+}
+
 // assign button ("Add Command") is enabled only if it is not read only
 // delete button ("Remove Command") is enabled if a current binding exists
 //     and it is not read only
diff --git a/cui/source/inc/cfgutil.hxx b/cui/source/inc/cfgutil.hxx
index 40661fc20733..1fb47405fd8f 100644
--- a/cui/source/inc/cfgutil.hxx
+++ b/cui/source/inc/cfgutil.hxx
@@ -34,6 +34,7 @@
 #include <vcl/treelistbox.hxx>
 #include <vcl/dialog.hxx>
 #include <vcl/image.hxx>
+#include <vcl/weld.hxx>
 
 class Button;
 class SaveInData;
@@ -123,6 +124,46 @@ public:
     OUString      GetHelpText( bool bConsiderParent = true );
 };
 
+class CuiConfigFunctionListBox
+{
+    friend class CuiConfigGroupListBox;
+    SfxGroupInfoArr_Impl aArr;
+
+    std::unique_ptr<weld::TreeView> m_xTreeView;
+
+public:
+    CuiConfigFunctionListBox(std::unique_ptr<weld::TreeView> xTreeView);
+    void set_sensitive(bool bSensitive) { m_xTreeView->set_sensitive(bSensitive); }
+    void connect_changed(const Link<weld::TreeView&, void>& rLink) { m_xTreeView->connect_changed(rLink); }
+    void connect_row_activated(const Link<weld::TreeView&, void>& rLink) { m_xTreeView->connect_row_activated(rLink); }
+    void freeze() { m_xTreeView->freeze(); }
+    void thaw() { m_xTreeView->thaw(); }
+    void append(const OUString& rId, const OUString& rStr) { m_xTreeView->append(rId, rStr); }
+    void append(const OUString& rId, const OUString& rStr, const OUString& rImage)
+    {
+        m_xTreeView->insert(nullptr, -1, rStr, &rId, nullptr, nullptr, &rImage, false);
+    }
+    int n_children() const { return m_xTreeView->n_children(); }
+    void select(int pos) { m_xTreeView->select(pos); }
+    std::unique_ptr<weld::TreeIter> make_iterator(const weld::TreeIter* pOrig = nullptr) const { return m_xTreeView->make_iterator(pOrig); }
+    bool get_iter_first(weld::TreeIter& rIter) const { return m_xTreeView->get_iter_first(rIter); }
+    // set iter to point to next node at the current level
+    bool iter_next_sibling(weld::TreeIter& rIter) const { return m_xTreeView->iter_next_sibling(rIter); }
+    // set iter to point to next node, depth first, then sibling
+    bool iter_next(weld::TreeIter& rIter) const { return m_xTreeView->iter_next(rIter); }
+    OUString get_text(const weld::TreeIter& rIter) const { return m_xTreeView->get_text(rIter); }
+    void scroll_to_row(const weld::TreeIter& rIter) { return m_xTreeView->scroll_to_row(rIter); }
+    void select(const weld::TreeIter& rIter) { m_xTreeView->select(rIter); }
+
+    ~CuiConfigFunctionListBox();
+
+    void          ClearAll();
+    OUString      GetCurCommand();
+    OUString      GetCurLabel();
+    OUString      GetSelectedScriptURI();
+    OUString      GetHelpText( bool bConsiderParent = true );
+};
+
 struct SvxConfigGroupBoxResource_Impl;
 class SfxConfigGroupListBox : public SvTreeListBox
 {
@@ -178,6 +219,58 @@ public:
     void                SetStylesInfo(SfxStylesInfo_Impl* pStyles);
 };
 
+struct CuiConfigGroupBoxResource_Impl;
+class CuiConfigGroupListBox
+{
+    std::unique_ptr<CuiConfigGroupBoxResource_Impl> xImp;
+    CuiConfigFunctionListBox* m_pFunctionListBox;
+    SfxGroupInfoArr_Impl aArr;
+    OUString m_sModuleLongName;
+    css::uno::Reference< css::uno::XComponentContext > m_xContext;
+    css::uno::Reference< css::frame::XFrame > m_xFrame;
+    css::uno::Reference< css::container::XNameAccess > m_xGlobalCategoryInfo;
+    css::uno::Reference< css::container::XNameAccess > m_xModuleCategoryInfo;
+    css::uno::Reference< css::container::XNameAccess > m_xUICmdDescription;
+    SfxStylesInfo_Impl* m_pStylesInfo;
+    std::unique_ptr<weld::TreeView> m_xTreeView;
+
+    OUString GetImage(
+        const css::uno::Reference< css::script::browse::XBrowseNode >& node,
+        css::uno::Reference< css::uno::XComponentContext > const & xCtx,
+        bool bIsRootNode);
+
+    static css::uno::Reference< css::uno::XInterface  > getDocumentModel(
+        css::uno::Reference< css::uno::XComponentContext > const & xCtx,
+        OUString const & docName);
+
+    void InitModule();
+    void FillScriptList(const css::uno::Reference< css::script::browse::XBrowseNode >& xRootNode,
+                        weld::TreeIter* pParentEntry, bool bCheapChildrenOnDemand);
+    void FillFunctionsList(const css::uno::Sequence< css::frame::DispatchInformation >& xCommands);
+    OUString MapCommand2UIName(const OUString& sCommand);
+
+    DECL_LINK(ExpandingHdl, weld::TreeIter&, bool);
+    DECL_LINK(OpenCurrentHdl, weld::TreeView&, void);
+
+public:
+    CuiConfigGroupListBox(std::unique_ptr<weld::TreeView> xTreeView);
+    void set_sensitive(bool bSensitive) { m_xTreeView->set_sensitive(bSensitive); }
+    void connect_changed(const Link<weld::TreeView&, void>& rLink) { m_xTreeView->connect_changed(rLink); }
+    ~CuiConfigGroupListBox();
+    void                ClearAll();
+
+    void                Init(const css::uno::Reference< css::uno::XComponentContext >& xContext,
+                             const css::uno::Reference< css::frame::XFrame >&          xFrame,
+                             const OUString&                                        sModuleLongName,
+                             bool bEventMode);
+    void                SetFunctionListBox( CuiConfigFunctionListBox *pBox )
+                        { m_pFunctionListBox = pBox; }
+    void                GroupSelected();
+    void                SelectMacro( const SfxMacroInfoItem* );
+    void                SelectMacro( const OUString&, const OUString& );
+    void                SetStylesInfo(SfxStylesInfo_Impl* pStyles);
+};
+
 class SvxScriptSelectorDialog : public ModalDialog
 {
     VclPtr<FixedText>                      m_pDialogDescription;
diff --git a/cui/source/inc/headertablistbox.hxx b/cui/source/inc/headertablistbox.hxx
index 16bad69f85d3..390600c3e6dc 100644
--- a/cui/source/inc/headertablistbox.hxx
+++ b/cui/source/inc/headertablistbox.hxx
@@ -54,6 +54,22 @@ public:
     void                        Enable();  ///< same meaning as Windows::Enable()
 };
 
+class CuiMacroEventListBox final
+{
+private:
+    std::unique_ptr<weld::TreeView> m_xTreeView;
+public:
+    CuiMacroEventListBox(std::unique_ptr<weld::TreeView> xTreeView);
+    void set_sensitive(bool bSensitive) { m_xTreeView->set_sensitive(bSensitive); }
+    void show() { m_xTreeView->show(); }
+    ~CuiMacroEventListBox();
+
+    weld::TreeView& GetListBox()
+    {
+        return *m_xTreeView;
+    }
+};
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/source/inc/macroass.hxx b/cui/source/inc/macroass.hxx
index 3a37af149639..3a7231b374e7 100644
--- a/cui/source/inc/macroass.hxx
+++ b/cui/source/inc/macroass.hxx
@@ -36,13 +36,13 @@ class SfxMacroTabPage_Impl;
 class SfxMacroTabPage final : public SfxTabPage
 {
     SvxMacroTableDtor           aTbl;
-    DECL_LINK( SelectEvent_Impl, SvTreeListBox*, void );
-    DECL_LINK( SelectGroup_Impl, SvTreeListBox*, void );
-    DECL_LINK( SelectMacro_Impl, SvTreeListBox*, void );
+    DECL_LINK(SelectEvent_Impl, weld::TreeView&, void);
+    DECL_LINK(SelectGroup_Impl, weld::TreeView&, void);
+    DECL_LINK(SelectMacro_Impl, weld::TreeView&, void);
 
-    DECL_LINK( AssignDeleteHdl_Impl, SvTreeListBox*, bool );
-    DECL_LINK( AssignDeleteClickHdl_Impl, Button *, void );
-    void                        AssignDeleteHdl(Control const *);
+    DECL_LINK(AssignDeleteHdl_Impl, weld::TreeView&, void);
+    DECL_LINK(AssignDeleteClickHdl_Impl, weld::Button&, void);
+    void AssignDeleteHdl(const weld::Widget*);
     DECL_LINK( TimeOut_Impl, Timer*, void );
 
     std::unique_ptr<SfxMacroTabPage_Impl>       mpImpl;
@@ -53,7 +53,7 @@ class SfxMacroTabPage final : public SfxTabPage
 
 public:
     SfxMacroTabPage(
-        vcl::Window* pParent,
+        TabPageParent pParent,
         const css::uno::Reference< css::frame::XFrame >& rxDocumentFrame,
         const SfxItemSet& rSet
     );
diff --git a/cui/source/tabpages/macroass.cxx b/cui/source/tabpages/macroass.cxx
index 343783b8ccef..e1a3f9060378 100644
--- a/cui/source/tabpages/macroass.cxx
+++ b/cui/source/tabpages/macroass.cxx
@@ -44,31 +44,22 @@ class SfxMacroTabPage_Impl
 public:
     SfxMacroTabPage_Impl();
 
-    OUString                               maStaticMacroLBLabel;
-    VclPtr<PushButton>                     pAssignPB;
-    VclPtr<PushButton>                     pDeletePB;
-    OUString                               sStrEvent;
-    OUString                               sAssignedMacro;
-    VclPtr<MacroEventListBox>              pEventLB;
-    VclPtr<VclFrame>                       pGroupFrame;
-    VclPtr<SfxConfigGroupListBox>          pGroupLB;
-    VclPtr<VclFrame>                       pMacroFrame;
-    VclPtr<SfxConfigFunctionListBox>       pMacroLB;
-
-    Idle                            maFillGroupIdle;
-    bool                            bGotEvents;
+    OUString                               m_aStaticMacroLBLabel;
+    std::unique_ptr<weld::Button>          m_xAssignPB;
+    std::unique_ptr<weld::Button>          m_xDeletePB;
+    std::unique_ptr<CuiMacroEventListBox>  m_xEventLB;
+    std::unique_ptr<weld::Widget>          m_xGroupFrame;
+    std::unique_ptr<CuiConfigGroupListBox> m_xGroupLB;
+    std::unique_ptr<weld::Frame>           m_xMacroFrame;
+    std::unique_ptr<CuiConfigFunctionListBox> m_xMacroLB;
+
+    Idle                            m_aFillGroupIdle;
+    bool                            m_bGotEvents;
     bool m_bDummyActivated; ///< has this tab page already been activated
 };
 
 SfxMacroTabPage_Impl::SfxMacroTabPage_Impl()
-    : pAssignPB(nullptr)
-    , pDeletePB(nullptr)
-    , pEventLB(nullptr)
-    , pGroupFrame(nullptr)
-    , pGroupLB(nullptr)
-    , pMacroFrame(nullptr)
-    , pMacroLB(nullptr)
-    , bGotEvents(false)
+    : m_bGotEvents(false)
     , m_bDummyActivated(false)
 {
 }
@@ -78,19 +69,6 @@ static sal_uInt16 aPageRg[] = {
     0
 };
 
-// attention, this array is indexed directly (0, 1, ...) in the code
-static long const nTabs[] =
-    {
-        0, 90
-    };
-
-// IDs for items in HeaderBar of EventLB
-#define ITEMID_EVENT        1
-#define ITMEID_ASSMACRO     2
-
-
-#define LB_MACROS_ITEMPOS   2
-
 static OUString ConvertToUIName_Impl( SvxMacro const *pMacro )
 {
     OUString aName( pMacro->GetMacName() );
@@ -112,41 +90,40 @@ static OUString ConvertToUIName_Impl( SvxMacro const *pMacro )
 void SfxMacroTabPage::EnableButtons()
 {
     // don't do anything as long as the eventbox is empty
-    const SvTreeListEntry* pE = mpImpl->pEventLB->GetListBox().FirstSelected();
-    if ( pE )
+    weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox();
+    int nSelected = rTreeView.get_selected_index();
+    if (nSelected != -1)
     {
         // get bound macro
-        const SvxMacro* pM = aTbl.Get( static_cast<SvMacroItemId>(reinterpret_cast<sal_uLong>(pE->GetUserData())) );
-        mpImpl->pDeletePB->Enable( nullptr != pM );
+        const SvxMacro* pM = aTbl.Get(static_cast<SvMacroItemId>(rTreeView.get_selected_id().toInt32()));
+        mpImpl->m_xDeletePB->set_sensitive(nullptr != pM);
 
-        OUString sEventMacro = static_cast<const SvLBoxString&>(pE->GetItem( LB_MACROS_ITEMPOS )).GetText();
+        OUString sEventMacro = rTreeView.get_text(nSelected, 1);
 
-        OUString sScriptURI = mpImpl->pMacroLB->GetSelectedScriptURI();
-        mpImpl->pAssignPB->Enable( !sScriptURI.equalsIgnoreAsciiCase( sEventMacro ) );
+        OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI();
+        mpImpl->m_xAssignPB->set_sensitive(!sScriptURI.equalsIgnoreAsciiCase(sEventMacro));
     }
     else
-        mpImpl->pAssignPB->Enable( false );
+        mpImpl->m_xAssignPB->set_sensitive(false);
 }
 
-SfxMacroTabPage::SfxMacroTabPage(vcl::Window* pParent, const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rAttrSet )
-    : SfxTabPage(pParent, "EventAssignPage", "cui/ui/eventassignpage.ui", &rAttrSet)
+SfxMacroTabPage::SfxMacroTabPage(TabPageParent pParent, const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rAttrSet )
+    : SfxTabPage(pParent, "cui/ui/eventassignpage.ui", "EventAssignPage", &rAttrSet)
 {
     mpImpl.reset(new SfxMacroTabPage_Impl);
 
-    mpImpl->maFillGroupIdle.SetInvokeHandler( LINK( this, SfxMacroTabPage, TimeOut_Impl ) );
-    mpImpl->maFillGroupIdle.SetPriority( TaskPriority::HIGHEST );
-    mpImpl->maFillGroupIdle.SetDebugName( "SfxMacroTabPage maFillGroupIdle" );
-
-    mpImpl->sStrEvent = get<FixedText>("eventft")->GetText();
-    mpImpl->sAssignedMacro = get<FixedText>("assignft")->GetText();
-    get(mpImpl->pEventLB , "assignments");
-    get(mpImpl->pAssignPB, "assign");
-    get(mpImpl->pDeletePB, "delete");
-    get(mpImpl->pGroupFrame, "groupframe");
-    get(mpImpl->pGroupLB, "libraries");
-    get(mpImpl->pMacroFrame, "macroframe");
-    mpImpl->maStaticMacroLBLabel = mpImpl->pMacroFrame->get_label();
-    get(mpImpl->pMacroLB, "macros");
+    mpImpl->m_aFillGroupIdle.SetInvokeHandler( LINK( this, SfxMacroTabPage, TimeOut_Impl ) );
+    mpImpl->m_aFillGroupIdle.SetPriority( TaskPriority::HIGHEST );
+    mpImpl->m_aFillGroupIdle.SetDebugName( "SfxMacroTabPage m_aFillGroupIdle" );
+
+    mpImpl->m_xEventLB.reset(new CuiMacroEventListBox(m_xBuilder->weld_tree_view("assignments")));
+    mpImpl->m_xAssignPB = m_xBuilder->weld_button("assign");
+    mpImpl->m_xDeletePB = m_xBuilder->weld_button("delete");
+    mpImpl->m_xGroupFrame = m_xBuilder->weld_widget("groupframe");
+    mpImpl->m_xGroupLB.reset(new CuiConfigGroupListBox(m_xBuilder->weld_tree_view("libraries")));
+    mpImpl->m_xMacroFrame = m_xBuilder->weld_frame("macroframe");
+    mpImpl->m_aStaticMacroLBLabel = mpImpl->m_xMacroFrame->get_label();
+    mpImpl->m_xMacroLB.reset(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view("macros")));
 
     SetFrame( rxDocumentFrame );
 
@@ -166,27 +143,25 @@ void SfxMacroTabPage::dispose()
     SfxTabPage::dispose();
 }
 
-void SfxMacroTabPage::AddEvent( const OUString & rEventName, SvMacroItemId nEventId )
+void SfxMacroTabPage::AddEvent(const OUString& rEventName, SvMacroItemId nEventId)
 {
-    OUString sTmp = rEventName + "\t";
+    weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox();
+    rTreeView.append(OUString::number(static_cast<sal_Int32>(nEventId)), rEventName);
 
     // if the table is valid already
-    SvxMacro* pM = aTbl.Get( nEventId );
-    if( pM )
+    SvxMacro* pM = aTbl.Get(nEventId);
+    if (pM)
     {
-        OUString sNew( ConvertToUIName_Impl( pM ) );
-        sTmp += sNew;
+        OUString sNew(ConvertToUIName_Impl(pM));
+        rTreeView.set_text(rTreeView.n_children() - 1, sNew, 1);
     }
-
-    SvTreeListEntry* pE = mpImpl->pEventLB->GetListBox().InsertEntry( sTmp );
-    pE->SetUserData( reinterpret_cast< void* >( sal::static_int_cast< sal_IntPtr >( nEventId )) );
 }
 
 void SfxMacroTabPage::ScriptChanged()
 {
     // get new areas and their functions
-    mpImpl->pGroupFrame->Show();
-    mpImpl->pMacroFrame->Show();
+    mpImpl->m_xGroupFrame->show();
+    mpImpl->m_xMacroFrame->show();
 
     EnableButtons();
 }
@@ -208,8 +183,8 @@ bool SfxMacroTabPage::FillItemSet( SfxItemSet* rSet )
 
 void SfxMacroTabPage::LaunchFillGroup()
 {
-    if (! mpImpl->maFillGroupIdle.IsActive() )
-        mpImpl->maFillGroupIdle.Start();
+    if (! mpImpl->m_aFillGroupIdle.IsActive() )
+        mpImpl->m_aFillGroupIdle.Start();
 }
 
 void SfxMacroTabPage::ActivatePage( const SfxItemSet& )
@@ -227,9 +202,9 @@ void SfxMacroTabPage::ActivatePage( const SfxItemSet& )
 void SfxMacroTabPage::PageCreated(const SfxAllItemSet& aSet)
 {
     const SfxPoolItem* pEventsItem;
-    if( !mpImpl->bGotEvents && SfxItemState::SET == aSet.GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) )
+    if( !mpImpl->m_bGotEvents && SfxItemState::SET == aSet.GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) )
     {
-        mpImpl->bGotEvents = true;
+        mpImpl->m_bGotEvents = true;
         const SfxEventNamesList& rList = static_cast<const SfxEventNamesItem*>(pEventsItem)->GetEvents();
         for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo )
         {
@@ -246,9 +221,9 @@ void SfxMacroTabPage::Reset( const SfxItemSet* rSet )
         aTbl = static_cast<const SvxMacroItem*>(pItem)->GetMacroTable();
 
     const SfxPoolItem* pEventsItem;
-    if( !mpImpl->bGotEvents && SfxItemState::SET == rSet->GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) )
+    if( !mpImpl->m_bGotEvents && SfxItemState::SET == rSet->GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) )
     {
-        mpImpl->bGotEvents = true;
+        mpImpl->m_bGotEvents = true;
         const SfxEventNamesList& rList = static_cast<const SfxEventNamesItem*>(pEventsItem)->GetEvents();
         for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo )
         {
@@ -259,10 +234,10 @@ void SfxMacroTabPage::Reset( const SfxItemSet* rSet )
 
     FillEvents();
 
-    SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox();
-    SvTreeListEntry* pE = rListBox.GetEntry( 0 );
-    if( pE )
-        rListBox.SetCurEntry( pE );
+    weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox();
+    std::unique_ptr<weld::TreeIter> xIter(rListBox.make_iterator());
+    if (rListBox.get_iter_first(*xIter))
+        rListBox.set_cursor(*xIter);
 }
 
 bool SfxMacroTabPage::IsReadOnly() const
@@ -270,13 +245,13 @@ bool SfxMacroTabPage::IsReadOnly() const
     return false;
 }
 
-IMPL_LINK_NOARG( SfxMacroTabPage, SelectEvent_Impl, SvTreeListBox*, void)
+IMPL_LINK_NOARG(SfxMacroTabPage, SelectEvent_Impl, weld::TreeView&, void)
 {
-    SvHeaderTabListBox&     rListBox = mpImpl->pEventLB->GetListBox();
-    SvTreeListEntry*            pE = rListBox.FirstSelected();
-    if( !pE || LISTBOX_ENTRY_NOTFOUND == rListBox.GetModel()->GetAbsPos( pE ) )
+    weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox();
+    int nSelected = rListBox.get_selected_index();
+    if (nSelected == -1)
     {
-        DBG_ASSERT( pE, "Where does the empty entry come from?" );
+        DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?");
         return;
     }
 
@@ -284,54 +259,53 @@ IMPL_LINK_NOARG( SfxMacroTabPage, SelectEvent_Impl, SvTreeListBox*, void)
     EnableButtons();
 }
 
-IMPL_LINK_NOARG( SfxMacroTabPage, SelectGroup_Impl, SvTreeListBox*, void)
+IMPL_LINK_NOARG(SfxMacroTabPage, SelectGroup_Impl, weld::TreeView&, void)
 {
-    mpImpl->pGroupLB->GroupSelected();
-    const OUString sScriptURI = mpImpl->pMacroLB->GetSelectedScriptURI();
+    mpImpl->m_xGroupLB->GroupSelected();
+    const OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI();
     OUString       aLabelText;
     if( !sScriptURI.isEmpty() )
-        aLabelText = mpImpl->maStaticMacroLBLabel;
-    mpImpl->pMacroFrame->set_label( aLabelText );
+        aLabelText = mpImpl->m_aStaticMacroLBLabel;
+    mpImpl->m_xMacroFrame->set_label( aLabelText );
 
     EnableButtons();
 }
 
-IMPL_LINK_NOARG( SfxMacroTabPage, SelectMacro_Impl, SvTreeListBox*, void)
+IMPL_LINK_NOARG(SfxMacroTabPage, SelectMacro_Impl, weld::TreeView&, void)
 {
     EnableButtons();
 }
 
-IMPL_LINK( SfxMacroTabPage, AssignDeleteClickHdl_Impl, Button*, pBtn, void )
+IMPL_LINK(SfxMacroTabPage, AssignDeleteClickHdl_Impl, weld::Button&, rBtn, void)
 {
-    AssignDeleteHdl(pBtn);
+    AssignDeleteHdl(&rBtn);
 }
 
-IMPL_LINK( SfxMacroTabPage, AssignDeleteHdl_Impl, SvTreeListBox*, pBtn, bool )
+IMPL_LINK(SfxMacroTabPage, AssignDeleteHdl_Impl, weld::TreeView&, rBtn, void)
 {
-    AssignDeleteHdl(pBtn);
-    return false;
+    AssignDeleteHdl(&rBtn);
 }
 
-void SfxMacroTabPage::AssignDeleteHdl(Control const * pBtn)
+void SfxMacroTabPage::AssignDeleteHdl(const weld::Widget* pBtn)
 {
-    SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox();
-    SvTreeListEntry* pE = rListBox.FirstSelected();
-    if( !pE || LISTBOX_ENTRY_NOTFOUND == rListBox.GetModel()->GetAbsPos( pE ) )
+    weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox();
+    int nSelected = rListBox.get_selected_index();
+    if (nSelected == -1)
     {
-        DBG_ASSERT( pE, "Where does the empty entry come from?" );
+        DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?");
         return;
     }
 
-    const bool bAssEnabled = pBtn != mpImpl->pDeletePB && mpImpl->pAssignPB->IsEnabled();
+    const bool bAssEnabled = pBtn != mpImpl->m_xDeletePB.get() && mpImpl->m_xAssignPB->get_sensitive();
 
     // remove from the table
-    SvMacroItemId nEvent = static_cast<SvMacroItemId>(reinterpret_cast<sal_uLong>(pE->GetUserData()));
+    SvMacroItemId nEvent = static_cast<SvMacroItemId>(rListBox.get_selected_id().toInt32());
     aTbl.Erase( nEvent );
 
     OUString sScriptURI;
     if( bAssEnabled )
     {
-        sScriptURI = mpImpl->pMacroLB->GetSelectedScriptURI();
+        sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI();
         if( sScriptURI.startsWith( "vnd.sun.star.script:" ) )
         {
             aTbl.Insert(
@@ -345,12 +319,7 @@ void SfxMacroTabPage::AssignDeleteHdl(Control const * pBtn)
         }
     }
 
-    mpImpl->pEventLB->SetUpdateMode( false );
-    pE->ReplaceItem(o3tl::make_unique<SvLBoxString>(sScriptURI), LB_MACROS_ITEMPOS);
-    rListBox.GetModel()->InvalidateEntry( pE );
-    rListBox.Select( pE );
-    rListBox.MakeVisible( pE );
-    rListBox.SetUpdateMode( true );
+    rListBox.set_text(nSelected, sScriptURI, 1);
 
     EnableButtons();
 }
@@ -366,7 +335,7 @@ IMPL_LINK( SfxMacroTabPage, TimeOut_Impl, Timer*,, void )
         pTabDlg->EnableInput( false );
     }
     // fill macro list
-    mpImpl->pGroupLB->Init(
+    mpImpl->m_xGroupLB->Init(
         comphelper::getProcessComponentContext(),
         GetFrame(),
         OUString(), false);
@@ -379,64 +348,49 @@ IMPL_LINK( SfxMacroTabPage, TimeOut_Impl, Timer*,, void )
 
 void SfxMacroTabPage::InitAndSetHandler()
 {
-    SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox();
-    HeaderBar&          rHeaderBar = mpImpl->pEventLB->GetHeaderBar();
-    Link<SvTreeListBox*,bool> aLnk(LINK(this, SfxMacroTabPage, AssignDeleteHdl_Impl ));
-    mpImpl->pMacroLB->SetDoubleClickHdl( aLnk );
-    mpImpl->pDeletePB->SetClickHdl( LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl ) );
-    mpImpl->pAssignPB->SetClickHdl( LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl ) );
-    rListBox.SetDoubleClickHdl( aLnk );
-
-    rListBox.SetSelectHdl( LINK( this, SfxMacroTabPage, SelectEvent_Impl ));
-    mpImpl->pGroupLB->SetSelectHdl( LINK( this, SfxMacroTabPage, SelectGroup_Impl ));
-    mpImpl->pMacroLB->SetSelectHdl( LINK( this, SfxMacroTabPage, SelectMacro_Impl ));
-
-    rListBox.SetSelectionMode( SelectionMode::Single );
-    rListBox.SetTabs( SAL_N_ELEMENTS(nTabs), nTabs );
-    Size aSize( nTabs[ 1 ], 0 );
-    rHeaderBar.InsertItem( ITEMID_EVENT, mpImpl->sStrEvent, LogicToPixel( aSize, MapMode( MapUnit::MapAppFont ) ).Width() );
-    aSize.setWidth( 1764 );       // don't know what, so 42^2 is best to use...
-    rHeaderBar.InsertItem( ITMEID_ASSMACRO, mpImpl->sAssignedMacro, LogicToPixel( aSize, MapMode( MapUnit::MapAppFont ) ).Width() );
-    rListBox.SetSpaceBetweenEntries( 0 );
-
-    mpImpl->pEventLB->Show();
-    mpImpl->pEventLB->ConnectElements();
-
-    mpImpl->pEventLB->Enable();
-    mpImpl->pGroupLB->Enable();
-    mpImpl->pMacroLB->Enable();
-
-    mpImpl->pGroupLB->SetFunctionListBox( mpImpl->pMacroLB );
+    weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox();
+    Link<weld::TreeView&,void> aLnk(LINK(this, SfxMacroTabPage, AssignDeleteHdl_Impl));
+    mpImpl->m_xMacroLB->connect_row_activated( aLnk);
+    mpImpl->m_xDeletePB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl));
+    mpImpl->m_xAssignPB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl));
+    rListBox.connect_row_activated(aLnk);
 
+    rListBox.connect_changed(LINK(this, SfxMacroTabPage, SelectEvent_Impl));
+    mpImpl->m_xGroupLB->connect_changed(LINK(this, SfxMacroTabPage, SelectGroup_Impl));
+    mpImpl->m_xMacroLB->connect_changed(LINK(this, SfxMacroTabPage, SelectMacro_Impl));
+
+    std::vector<int> aWidths;
+    aWidths.push_back(rListBox.get_approximate_digit_width() * 35);
+    rListBox.set_column_fixed_widths(aWidths);
+
+    mpImpl->m_xEventLB->show();
+
+    mpImpl->m_xEventLB->set_sensitive(true);
+    mpImpl->m_xGroupLB->set_sensitive(true);
+    mpImpl->m_xMacroLB->set_sensitive(true);
+
+    mpImpl->m_xGroupLB->SetFunctionListBox(mpImpl->m_xMacroLB.get());
 }
 
 void SfxMacroTabPage::FillEvents()
 {
-    SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox();
+    weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox();
 
-    sal_uLong       nEntryCnt = rListBox.GetEntryCount();
+    int nEntryCnt = rListBox.n_children();
 
     // get events from the table and fill the EventListBox respectively
-    for( sal_uLong n = 0 ; n < nEntryCnt ; ++n )
+    for (int n = 0 ; n < nEntryCnt; ++n)
     {
-        SvTreeListEntry*    pE = rListBox.GetEntry( n );
-        if( pE )
-        {
-            SvLBoxString&     rLItem = static_cast<SvLBoxString&>( pE->GetItem( LB_MACROS_ITEMPOS ) );
-            DBG_ASSERT( SvLBoxItemType::String == rLItem.GetType(), "SfxMacroTabPage::FillEvents(): no LBoxString" );
-
-            const OUString&   sOld( rLItem.GetText() );
-            OUString          sNew;
-            SvMacroItemId     nEventId = static_cast<SvMacroItemId>(reinterpret_cast<sal_uLong>( pE->GetUserData() ));
-            if( aTbl.IsKeyValid( nEventId ) )
-                sNew = ConvertToUIName_Impl( aTbl.Get( nEventId ) );
-
-            if( sOld != sNew )
-            {
-                pE->ReplaceItem(o3tl::make_unique<SvLBoxString>(sNew), LB_MACROS_ITEMPOS);
-                rListBox.GetModel()->InvalidateEntry( pE );
-            }
-        }
+        OUString sOld = rListBox.get_text(n, 1);
+        OUString sNew;
+        SvMacroItemId nEventId = static_cast<SvMacroItemId>(rListBox.get_id(n).toInt32());
+        if (aTbl.IsKeyValid(nEventId))
+            sNew = ConvertToUIName_Impl(aTbl.Get(nEventId));
+
+        if (sOld == sNew)
+            continue;
+
+        rListBox.set_text(n, sNew, 1);
     }
 }
 
diff --git a/cui/uiconfig/ui/eventassignpage.ui b/cui/uiconfig/ui/eventassignpage.ui
index 48dbbc0bf1b1..3eb926ed88d6 100644
--- a/cui/uiconfig/ui/eventassignpage.ui
+++ b/cui/uiconfig/ui/eventassignpage.ui
@@ -1,8 +1,35 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.1 -->
+<!-- Generated with glade 3.22.1 -->
 <interface domain="cui">
   <requires lib="gtk+" version="3.18"/>
-  <requires lib="LibreOffice" version="1.0"/>
+  <object class="GtkTreeStore" id="liststore1">
+    <columns>
+      <!-- column-name expander -->
+      <column type="GdkPixbuf"/>
+      <!-- column-name text -->
+      <column type="gchararray"/>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkTreeStore" id="liststore2">
+    <columns>
+      <!-- column-name text -->
+      <column type="gchararray"/>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkTreeStore" id="liststore3">
+    <columns>
+      <!-- column-name text -->
+      <column type="gchararray"/>
+      <!-- column-name text2 -->
+      <column type="gchararray"/>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
   <object class="GtkGrid" id="EventAssignPage">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
@@ -27,14 +54,37 @@
             <property name="top_padding">6</property>
             <property name="left_padding">12</property>
             <child>
-              <object class="cuilo-SfxConfigFunctionListBox" id="macros:border">
+              <object class="GtkScrolledWindow">
                 <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>
-                <child internal-child="selection">
-                  <object class="GtkTreeSelection" id="Tree List-selection"/>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="macros">
+                    <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">liststore2</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" id="Tree List-selection1"/>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+                        <child>
+                          <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                          <attributes>
+                            <attribute name="text">0</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
                 </child>
               </object>
             </child>
@@ -55,8 +105,6 @@
       <packing>
         <property name="left_attach">1</property>
         <property name="top_attach">1</property>
-        <property name="width">1</property>
-        <property name="height">1</property>
       </packing>
     </child>
     <child>
@@ -76,14 +124,46 @@
             <property name="top_padding">6</property>
             <property name="left_padding">12</property>
             <child>
-              <object class="cuilo-SfxConfigGroupListBox" id="libraries:border">
+              <object class="GtkScrolledWindow">
                 <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>
-                <child internal-child="selection">
-                  <object class="GtkTreeSelection" id="Macro Library List-selection"/>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="libraries">
+                    <property name="width_request">-1</property>
+                    <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">1</property>
+                    <property name="show_expanders">True</property>
+                    <property name="enable_tree_lines">True</property>
+                    <child internal-child="selection">
+                      <object class="GtkTreeSelection" id="Macro Library List-selection1"/>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkCellRendererPixbuf" id="cellrenderertext4"/>
+                          <attributes>
+                            <attribute name="pixbuf">0</attribute>
+                          </attributes>
+                        </child>
+                        <child>
+                          <object class="GtkCellRendererText" id="cellrenderertext2"/>
+                          <attributes>
+                            <attribute name="text">1</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
                 </child>
               </object>
             </child>
@@ -93,8 +173,8 @@
           <object class="GtkLabel" id="macrotoft">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="xalign">0</property>
             <property name="label" translatable="yes" context="eventassignpage|macrotoft">Macro From</property>
+            <property name="xalign">0</property>
             <attributes>
               <attribute name="weight" value="bold"/>
             </attributes>
@@ -104,8 +184,6 @@
       <packing>
         <property name="left_attach">0</property>
         <property name="top_attach">1</property>
-        <property name="width">1</property>
-        <property name="height">1</property>
       </packing>
     </child>
     <child>
@@ -125,66 +203,52 @@
             <property name="top_padding">6</property>
             <property name="left_padding">12</property>
             <child>
-              <object class="GtkGrid" id="grid1">
+              <object class="GtkScrolledWindow">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can_focus">True</property>
                 <property name="hexpand">True</property>
                 <property name="vexpand">True</property>
+                <property name="shadow_type">in</property>
                 <child>
-                  <object class="cuilo-MacroEventListBox" id="assignments:border">
+                  <object class="GtkTreeView" id="assignments">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</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">liststore3</property>
+                    <property name="search_column">0</property>
+                    <property name="show_expanders">False</property>
                     <child internal-child="selection">
-                      <object class="GtkTreeSelection" id="Macro EventListBox-selection1"/>
+                      <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
                     </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">1</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkGrid" id="grid2">
-                    <property name="can_focus">False</property>
-                    <property name="no_show_all">True</property>
-                    <property name="column_homogeneous">True</property>
                     <child>
-                      <object class="GtkLabel" id="eventft">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes" context="eventassignpage|eventft">Event</property>
+                      <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+                        <property name="resizable">True</property>
+                        <property name="spacing">6</property>
+                        <property name="title" translatable="yes" context="eventassignpage|eventft">Event</property>
+                        <child>
+                          <object class="GtkCellRendererText" id="cellrenderer1"/>
+                          <attributes>
+                            <attribute name="text">0</attribute>
+                          </attributes>
+                        </child>
                       </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">0</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
                     </child>
                     <child>
-                      <object class="GtkLabel" id="assignft">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes" context="eventassignpage|assignft">Assigned Action</property>
+                      <object class="GtkTreeViewColumn" id="treeviewcolumn4">
+                        <property name="resizable">True</property>
+                        <property name="spacing">6</property>
+                        <property name="title" translatable="yes" context="eventassignpage|assignft">Assigned Action</property>
+                        <child>
+                          <object class="GtkCellRendererText" id="cellrenderer2"/>
+                          <attributes>
+                            <attribute name="text">1</attribute>
+                          </attributes>
+                        </child>
                       </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">0</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
                     </child>
                   </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">0</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
                 </child>
               </object>
             </child>
@@ -205,7 +269,6 @@
         <property name="left_attach">0</property>
         <property name="top_attach">0</property>
         <property name="width">2</property>
-        <property name="height">1</property>
       </packing>
     </child>
     <child>
@@ -219,6 +282,7 @@
           <object class="GtkButton" id="assign">
             <property name="label" translatable="yes" context="eventassignpage|assign">Assign</property>
             <property name="visible">True</property>
+            <property name="sensitive">False</property>
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
             <property name="use_underline">True</property>
@@ -247,7 +311,6 @@
       <packing>
         <property name="left_attach">2</property>
         <property name="top_attach">0</property>
-        <property name="width">1</property>
         <property name="height">2</property>
       </packing>
     </child>
@@ -261,9 +324,9 @@
   <object class="GtkSizeGroup" id="sizegroup2">
     <property name="mode">vertical</property>
     <widgets>
-      <widget name="macros:border"/>
-      <widget name="libraries:border"/>
-      <widget name="assignments:border"/>
+      <widget name="macros"/>
+      <widget name="libraries"/>
+      <widget name="assignments"/>
     </widgets>
   </object>
 </interface>
diff --git a/include/sfx2/sfxhelp.hxx b/include/sfx2/sfxhelp.hxx
index bdfaaf867143..99ca1a062f04 100644
--- a/include/sfx2/sfxhelp.hxx
+++ b/include/sfx2/sfxhelp.hxx
@@ -45,7 +45,8 @@ public:
     SfxHelp();
     virtual ~SfxHelp() override;
 
-    virtual OUString        GetHelpText( const OUString&, const vcl::Window* pWindow ) override;
+    virtual OUString        GetHelpText(const OUString&, const vcl::Window* pWindow) override;
+    virtual OUString        GetHelpText(const OUString&, const weld::Widget* pWindow) override;
 
     static OUString         CreateHelpURL( const OUString& aCommandURL, const OUString& rModuleName );
     static OUString         GetDefaultHelpModule();
diff --git a/include/vcl/help.hxx b/include/vcl/help.hxx
index 80353b263c09..2c467974fdc5 100644
--- a/include/vcl/help.hxx
+++ b/include/vcl/help.hxx
@@ -69,7 +69,8 @@ public:
     virtual bool        Start(const OUString& rHelpId, const vcl::Window* pWindow);
     virtual bool        Start(const OUString& rHelpId, weld::Widget* pWidget);
     virtual void        SearchKeyword( const OUString& rKeyWord );
-    virtual OUString    GetHelpText( const OUString& aHelpURL, const vcl::Window* pWindow );
+    virtual OUString    GetHelpText(const OUString& aHelpURL, const vcl::Window* pWindow);
+    virtual OUString    GetHelpText(const OUString& aHelpURL, const weld::Widget* pWidget);
 
     static void         EnableContextHelp();
     static void         DisableContextHelp();
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index f05e3408e207..1b9726ac556e 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -382,6 +382,7 @@ class VCL_DLLPUBLIC TreeView : virtual public Container
 protected:
     Link<TreeView&, void> m_aChangeHdl;
     Link<TreeView&, void> m_aRowActivatedHdl;
+    // if handler returns false, the expansion of the row is refused
     Link<TreeIter&, bool> m_aExpandingHdl;
 
     void signal_changed() { m_aChangeHdl.Call(*this); }
@@ -438,6 +439,7 @@ public:
     virtual void set_top_entry(int pos) = 0;
     virtual std::vector<int> get_selected_rows() const = 0;
     virtual void set_font_color(int pos, const Color& rColor) const = 0;
+    virtual void scroll_to_row(int pos) = 0;
 
     //by text
     virtual OUString get_text(int row, int col = -1) const = 0;
@@ -488,6 +490,7 @@ public:
     virtual void expand_row(TreeIter& rIter) = 0;
     virtual OUString get_text(const TreeIter& rIter) const = 0;
     virtual OUString get_id(const TreeIter& rIter) const = 0;
+    virtual void scroll_to_row(const TreeIter& rIter) = 0;
 
     void connect_expanding(const Link<TreeIter&, bool>& rLink) { m_aExpandingHdl = rLink; }
 
diff --git a/sfx2/source/appl/sfxhelp.cxx b/sfx2/source/appl/sfxhelp.cxx
index 19d08453f1d7..3651e9425c96 100644
--- a/sfx2/source/appl/sfxhelp.cxx
+++ b/sfx2/source/appl/sfxhelp.cxx
@@ -634,6 +634,49 @@ OUString SfxHelp::GetHelpText( const OUString& aCommandURL, const vcl::Window* p
     return sHelpText;
 }
 
+OUString SfxHelp::GetHelpText(const OUString& aCommandURL, const weld::Widget* pWidget)
+{
+    OUString sModuleName = GetHelpModuleName_Impl(aCommandURL);
+    OUString sRealCommand = vcl::CommandInfoProvider::GetRealCommandForCommand( aCommandURL, getCurrentModuleIdentifier_Impl() );
+    OUString sHelpText = SfxHelp_Impl::GetHelpText( sRealCommand.isEmpty() ? aCommandURL : sRealCommand, sModuleName );
+
+    OString aNewHelpId;
+
+    if (pWidget && sHelpText.isEmpty())
+    {
+        // no help text found -> try with parent help id.
+        std::unique_ptr<weld::Widget> xParent(pWidget->weld_parent());
+        while (xParent)
+        {
+            aNewHelpId = xParent->get_help_id();
+            sHelpText = SfxHelp_Impl::GetHelpText( OStringToOUString(aNewHelpId, RTL_TEXTENCODING_UTF8), sModuleName );
+            if (!sHelpText.isEmpty())
+                xParent.reset();
+            else
+                xParent.reset(xParent->weld_parent());
+        }
+
+        if (bIsDebug && sHelpText.isEmpty())
+            aNewHelpId.clear();
+    }
+
+    // add some debug information?
+    if ( bIsDebug )
+    {
+        sHelpText += "\n-------------\n";
+        sHelpText += sModuleName;
+        sHelpText += ": ";
+        sHelpText += aCommandURL;
+        if ( !aNewHelpId.isEmpty() )
+        {
+            sHelpText += " - ";
+            sHelpText += OStringToOUString(aNewHelpId, RTL_TEXTENCODING_UTF8);
+        }
+    }
+
+    return sHelpText;
+}
+
 void SfxHelp::SearchKeyword( const OUString& rKeyword )
 {
     Start_Impl(OUString(), static_cast<vcl::Window*>(nullptr), rKeyword);
diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx
index d0e885c506fa..0e5a3610ee3e 100644
--- a/sfx2/source/dialog/filedlghelper.cxx
+++ b/sfx2/source/dialog/filedlghelper.cxx
@@ -276,7 +276,7 @@ OUString FileDialogHelper_Impl::handleHelpRequested( const FilePickerEvent& aEve
     OUString aHelpText;
     Help* pHelp = Application::GetHelp();
     if ( pHelp )
-        aHelpText = pHelp->GetHelpText( OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), nullptr );
+        aHelpText = pHelp->GetHelpText(OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), static_cast<weld::Widget*>(nullptr));
     return aHelpText;
 }
 
diff --git a/vcl/source/app/help.cxx b/vcl/source/app/help.cxx
index b7143be84d20..ab6767b39adb 100644
--- a/vcl/source/app/help.cxx
+++ b/vcl/source/app/help.cxx
@@ -73,6 +73,11 @@ OUString Help::GetHelpText( const OUString&, const vcl::Window* )
     return OUString();
 }
 
+OUString Help::GetHelpText( const OUString&, const weld::Widget* )
+{
+    return OUString();
+}
+
 void Help::EnableContextHelp()
 {
     ImplGetSVData()->maHelpData.mbContextHelp = true;
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 389a0b03c572..5fa6327688f1 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -1916,6 +1916,14 @@ public:
         enable_notify_events();
     }
 
+    virtual void scroll_to_row(int pos) override
+    {
+        disable_notify_events();
+        SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
+        m_xTreeView->MakeVisible(pEntry);
+        enable_notify_events();
+    }
+
     virtual void unselect(int pos) override
     {
         assert(m_xTreeView->IsUpdateMode() && "don't select when frozen");
@@ -1947,6 +1955,8 @@ public:
         if (col == -1)
             return SvTabListBox::GetEntryText(pEntry, 0);
 
+        ++col; //skip dummy/expander column
+
         if (static_cast<size_t>(col) == pEntry->ItemCount())
             return OUString();
 
@@ -2097,6 +2107,14 @@ public:
         enable_notify_events();
     }
 
+    virtual void scroll_to_row(const weld::TreeIter& rIter) override
+    {
+        disable_notify_events();
+        const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
+        m_xTreeView->MakeVisible(rVclIter.iter);
+        enable_notify_events();
+    }
+
     virtual void unselect(const weld::TreeIter& rIter) override
     {
         assert(m_xTreeView->IsUpdateMode() && "don't unselect when frozen");
@@ -2114,8 +2132,12 @@ public:
 
     virtual bool iter_has_child(const weld::TreeIter& rIter) const override
     {
-        const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
-        return rVclIter.iter->HasChildren();
+        weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter);
+        SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNonConstIter);
+        SvTreeListEntry* restore(rVclIter.iter);
+        bool ret = iter_children(rNonConstIter);
+        rVclIter.iter = restore;
+        return ret;
     }
 
     virtual bool get_row_expanded(const weld::TreeIter& rIter) const override
diff --git a/vcl/source/treelist/treelistbox.cxx b/vcl/source/treelist/treelistbox.cxx
index c1269b26c174..dbf1af9566b0 100644
--- a/vcl/source/treelist/treelistbox.cxx
+++ b/vcl/source/treelist/treelistbox.cxx
@@ -3679,6 +3679,10 @@ bool SvTreeListBox::set_property(const OString &rKey, const OUString &rValue)
             nStyle |= (WB_HASBUTTONS | WB_HASBUTTONSATROOT);
         SetStyle(nStyle);
     }
+    else if (rKey == "enable-search")
+    {
+        SetQuickSearch(toBool(rValue));
+    }
     else
         return Control::set_property(rKey, rValue);
     return true;
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 30981b107533..3b04e1f7ed29 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -1932,6 +1932,7 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString &
                 m_aChildren.emplace_back(containerid, xContainer, true);
 
                 VclPtrInstance<HeaderBar> xHeader(xContainer, WB_BUTTONSTYLE | WB_BORDER | WB_TABSTOP | WB_3DLOOK);
+                xHeader->set_width_request(0); // let the headerbar width not affect the size requistion
                 OString headerid(id + "-header");
                 xHeader->SetHelpId(m_sHelpRoot + headerid);
                 m_aChildren.emplace_back(headerid, xHeader, true);
@@ -1951,6 +1952,7 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString &
             }
             xWindow = xBox;
             xBox->SetNoAutoCurEntry(true);
+            xBox->SetQuickSearch(true);
             xBox->SetHighlightRange(); // select over the whole width
         }
         if (pRealParent != pParent)
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index ebeb2a970e69..b9833ae4a503 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -1099,9 +1099,9 @@ OUString Menu::ImplGetHelpText( sal_uInt16 nItemId ) const
         if ( pHelp )
         {
             if (!pData->aCommandStr.isEmpty())
-                pData->aHelpText = pHelp->GetHelpText( pData->aCommandStr, nullptr );
+                pData->aHelpText = pHelp->GetHelpText( pData->aCommandStr, static_cast<weld::Widget*>(nullptr) );
             if (pData->aHelpText.isEmpty() && !pData->aHelpId.isEmpty())
-                pData->aHelpText = pHelp->GetHelpText( OStringToOUString( pData->aHelpId, RTL_TEXTENCODING_UTF8 ), nullptr );
+                pData->aHelpText = pHelp->GetHelpText( OStringToOUString( pData->aHelpId, RTL_TEXTENCODING_UTF8 ), static_cast<weld::Widget*>(nullptr) );
         }
     }
 
diff --git a/vcl/unx/gtk/salprn-gtk.cxx b/vcl/unx/gtk/salprn-gtk.cxx
index 235d3ccb005b..eab182ecb4c5 100644
--- a/vcl/unx/gtk/salprn-gtk.cxx
+++ b/vcl/unx/gtk/salprn-gtk.cxx
@@ -473,7 +473,7 @@ GtkPrintDialog::impl_initCustomTab()
                     const int nLen = aHelpIds.getLength();
                     aHelpTexts.realloc(nLen);
                     for (int j = 0; j != nLen; ++j)
-                        aHelpTexts[j] = pHelp->GetHelpText(aHelpIds[j], nullptr);
+                        aHelpTexts[j] = pHelp->GetHelpText(aHelpIds[j], static_cast<weld::Widget*>(nullptr));
                 }
                 else // fallback
                     aHelpTexts = aHelpIds;
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index c35088723a29..1fefb9db0169 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -4386,6 +4386,15 @@ public:
         enable_notify_events();
     }
 
+    virtual void scroll_to_row(int pos) override
+    {
+        disable_notify_events();
+        GtkTreePath* path = gtk_tree_path_new_from_indices(pos, -1);
+        gtk_tree_view_scroll_to_cell(m_pTreeView, path, nullptr, false, 0, 0);
+        gtk_tree_path_free(path);
+        enable_notify_events();
+    }
+
     virtual void unselect(int pos) override
     {
         assert(gtk_tree_view_get_model(m_pTreeView) && "don't select when frozen");
@@ -4572,6 +4581,17 @@ public:
         enable_notify_events();
     }
 
+    virtual void scroll_to_row(const weld::TreeIter& rIter) override
+    {
+        disable_notify_events();
+        const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter);
+        GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore);
+        GtkTreePath* path = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter));
+        gtk_tree_view_scroll_to_cell(m_pTreeView, path, nullptr, false, 0, 0);
+        gtk_tree_path_free(path);
+        enable_notify_events();
+    }
+
     virtual void unselect(const weld::TreeIter& rIter) override
     {
         assert(gtk_tree_view_get_model(m_pTreeView) && "don't select when frozen");
@@ -4593,9 +4613,12 @@ public:
 
     virtual bool iter_has_child(const weld::TreeIter& rIter) const override
     {
-        const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter);
-        GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore);
-        return gtk_tree_model_iter_has_child(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter));
+        weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter);
+        GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(rNonConstIter);
+        GtkTreeIter restore(rGtkIter.iter);
+        bool ret = iter_children(rNonConstIter);
+        rGtkIter.iter = restore;
+        return ret;
     }
 
     virtual bool get_row_expanded(const weld::TreeIter& rIter) const override
@@ -6356,7 +6379,7 @@ namespace
             Help* pHelp = !sHelpId.isEmpty() ? Application::GetHelp() : nullptr;
             if (pHelp)
             {
-                OUString sHelpText = pHelp->GetHelpText(OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), nullptr);
+                OUString sHelpText = pHelp->GetHelpText(OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), static_cast<weld::Widget*>(nullptr));
                 if (!sHelpText.isEmpty())
                 {
                     gtk_tooltip_set_text(tooltip, OUStringToOString(sHelpText, RTL_TEXTENCODING_UTF8).getStr());


More information about the Libreoffice-commits mailing list