weld SfxAcceleratorConfigPage

fixes a leak in the KeyList too

Change-Id: I603218ff99481bc006df329c770ea6fe6f147483
Reviewed-on: https://gerrit.libreoffice.org/68694
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/cui/source/customize/acccfg.cxx b/cui/source/customize/acccfg.cxx
index a5a63ee..4146be2a 100644
--- a/cui/source/customize/acccfg.cxx
+++ b/cui/source/customize/acccfg.cxx
@@ -779,43 +779,6 @@ static const sal_uInt16 KEYCODE_ARRAY[] =

static const sal_uInt16 KEYCODE_ARRAY_SIZE = SAL_N_ELEMENTS(KEYCODE_ARRAY);

// seems to be needed to layout the list box, which shows all
// assignable shortcuts
static const long AccCfgTabs[] =
{
    0,
    120 // Function
};


class SfxAccCfgLBoxString_Impl : public SvLBoxString
{
public:
    explicit SfxAccCfgLBoxString_Impl(const OUString& sText);

    virtual void Paint(const Point& aPos, SvTreeListBox& rDevice, vcl::RenderContext& rRenderContext,
                       const SvViewDataEntry* pView, const SvTreeListEntry& rEntry) override;
};


SfxAccCfgLBoxString_Impl::SfxAccCfgLBoxString_Impl(const OUString& sText)
    : SvLBoxString(sText)
{}

void SfxAccCfgLBoxString_Impl::Paint(const Point& aPos, SvTreeListBox& /*rDevice*/, vcl::RenderContext& rRenderContext,
                                     const SvViewDataEntry* /*pView*/, const SvTreeListEntry& rEntry)
{
    TAccInfo* pUserData = static_cast<TAccInfo*>(rEntry.GetUserData());
    if (!pUserData)
        return;

    if (pUserData->m_bIsConfigurable)
        rRenderContext.DrawText(aPos, GetText());
    else
        rRenderContext.DrawCtrlText(aPos, GetText(), 0, -1, DrawTextFlags::Disable);

}

extern "C" SAL_DLLPUBLIC_EXPORT void makeSfxAccCfgTabListBox(VclPtr<vcl::Window> & rRet, VclPtr<vcl::Window> & pParent, VclBuilder::stringmap & rMap)
{
    WinBits nWinBits = WB_TABSTOP;
@@ -876,8 +839,8 @@ void SfxAccCfgTabListBox_Impl::KeyInput(const KeyEvent& aKey)
    SvTabListBox::KeyInput(aKey);
}

SfxAcceleratorConfigPage::SfxAcceleratorConfigPage( vcl::Window* pParent, const SfxItemSet& aSet )
    : SfxTabPage(pParent, "AccelConfigPage", "cui/ui/accelconfigpage.ui", &aSet)
SfxAcceleratorConfigPage::SfxAcceleratorConfigPage(TabPageParent pParent, const SfxItemSet& aSet )
    : SfxTabPage(pParent, "cui/ui/accelconfigpage.ui", "AccelConfigPage", &aSet)
    , m_pMacroInfoItem()
    , aLoadAccelConfigStr(CuiResId(RID_SVXSTR_LOADACCELCONFIG))
    , aSaveAccelConfigStr(CuiResId(RID_SVXSTR_SAVEACCELCONFIG))
@@ -886,70 +849,60 @@ SfxAcceleratorConfigPage::SfxAcceleratorConfigPage( vcl::Window* pParent, const 
    , m_xGlobal()
    , m_xModule()
    , m_xAct()
    , m_aUpdateDataTimer("UpdateDataTimer")
    , m_xEntriesBox(m_xBuilder->weld_tree_view("shortcuts"))
    , m_xOfficeButton(m_xBuilder->weld_radio_button("office"))
    , m_xModuleButton(m_xBuilder->weld_radio_button("module"))
    , m_xChangeButton(m_xBuilder->weld_button("change"))
    , m_xRemoveButton(m_xBuilder->weld_button("delete"))
    , m_xGroupLBox(new CuiConfigGroupListBox(m_xBuilder->weld_tree_view("category")))
    , m_xFunctionBox(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view("function")))
    , m_xKeyBox(m_xBuilder->weld_tree_view("keys"))
    , m_xSearchEdit(m_xBuilder->weld_entry("searchEntry"))
    , m_xLoadButton(m_xBuilder->weld_button("load"))
    , m_xSaveButton(m_xBuilder->weld_button("save"))
    , m_xResetButton(m_xBuilder->weld_button("reset"))
{
    get(m_pOfficeButton, "office");
    get(m_pModuleButton, "module");
    get(m_pChangeButton, "change");
    get(m_pRemoveButton, "delete");
    get(m_pLoadButton, "load");
    get(m_pSaveButton, "save");
    get(m_pResetButton, "reset");
    get(m_pEntriesBox, "shortcuts");
    Size aSize(LogicToPixel(Size(174, 100), MapMode(MapUnit::MapAppFont)));
    m_pEntriesBox->set_width_request(aSize.Width());
    m_pEntriesBox->set_height_request(aSize.Height());
    get(m_pGroupLBox, "category");
    m_xEntriesBox->set_size_request(aSize.Width(), aSize.Height());
    aSize = LogicToPixel(Size(78 , 91), MapMode(MapUnit::MapAppFont));
    m_pGroupLBox->set_width_request(aSize.Width());
    m_pGroupLBox->set_height_request(aSize.Height());
    get(m_pFunctionBox, "function");
    m_xGroupLBox->set_size_request(aSize.Width(), aSize.Height());
    aSize = LogicToPixel(Size(88, 91), MapMode(MapUnit::MapAppFont));
    m_pFunctionBox->set_width_request(aSize.Width());
    m_pFunctionBox->set_height_request(aSize.Height());
    get(m_pKeyBox, "keys");
    m_xFunctionBox->set_size_request(aSize.Width(), aSize.Height());
    aSize = LogicToPixel(Size(80, 91), MapMode(MapUnit::MapAppFont));
    m_pKeyBox->set_width_request(aSize.Width());
    m_pKeyBox->set_height_request(aSize.Height());
    get(m_pSearchEdit, "searchEntry");
    m_xKeyBox->set_size_request(aSize.Width(), aSize.Height());

    aFilterAllStr = SfxResId( STR_SFX_FILTERNAME_ALL );

    // install handler functions
    m_pChangeButton->SetClickHdl( LINK( this, SfxAcceleratorConfigPage, ChangeHdl ));
    m_pRemoveButton->SetClickHdl( LINK( this, SfxAcceleratorConfigPage, RemoveHdl ));
    m_pEntriesBox->SetSelectHdl ( LINK( this, SfxAcceleratorConfigPage, SelectHdl ));
    m_pGroupLBox->SetSelectHdl  ( LINK( this, SfxAcceleratorConfigPage, SelectHdl ));
    m_pFunctionBox->SetSelectHdl( LINK( this, SfxAcceleratorConfigPage, SelectHdl ));
    m_pKeyBox->SetSelectHdl     ( LINK( this, SfxAcceleratorConfigPage, SelectHdl ));
    m_pLoadButton->SetClickHdl  ( LINK( this, SfxAcceleratorConfigPage, Load      ));
    m_pSaveButton->SetClickHdl  ( LINK( this, SfxAcceleratorConfigPage, Save      ));
    m_pResetButton->SetClickHdl ( LINK( this, SfxAcceleratorConfigPage, Default   ));
    m_pOfficeButton->SetClickHdl( LINK( this, SfxAcceleratorConfigPage, RadioHdl  ));
    m_pModuleButton->SetClickHdl( LINK( this, SfxAcceleratorConfigPage, RadioHdl  ));

    m_pSearchEdit->SetUpdateDataHdl ( LINK( this, SfxAcceleratorConfigPage, SearchUpdateHdl ));
    m_pSearchEdit->EnableUpdateData();

    // initialize Entriesbox
    m_pEntriesBox->SetStyle(m_pEntriesBox->GetStyle()|WB_HSCROLL|WB_CLIPCHILDREN);
    m_pEntriesBox->SetSelectionMode(SelectionMode::Single);
    m_pEntriesBox->SetTabs(SAL_N_ELEMENTS(AccCfgTabs), AccCfgTabs);
    m_pEntriesBox->Resize(); // OS: Hack for right selection
    m_pEntriesBox->SetSpaceBetweenEntries(0);
    m_pEntriesBox->SetDragDropMode(DragDropMode::NONE);
    m_xChangeButton->connect_clicked( LINK( this, SfxAcceleratorConfigPage, ChangeHdl ));
    m_xRemoveButton->connect_clicked( LINK( this, SfxAcceleratorConfigPage, RemoveHdl ));
    m_xEntriesBox->connect_changed ( LINK( this, SfxAcceleratorConfigPage, SelectHdl ));
    m_xGroupLBox->connect_changed  ( LINK( this, SfxAcceleratorConfigPage, SelectHdl ));
    m_xFunctionBox->connect_changed( LINK( this, SfxAcceleratorConfigPage, SelectHdl ));
    m_xKeyBox->connect_changed     ( LINK( this, SfxAcceleratorConfigPage, SelectHdl ));
    m_xLoadButton->connect_clicked  ( LINK( this, SfxAcceleratorConfigPage, Load      ));
    m_xSaveButton->connect_clicked  ( LINK( this, SfxAcceleratorConfigPage, Save      ));
    m_xResetButton->connect_clicked ( LINK( this, SfxAcceleratorConfigPage, Default   ));
    m_xOfficeButton->connect_clicked( LINK( this, SfxAcceleratorConfigPage, RadioHdl  ));
    m_xModuleButton->connect_clicked( LINK( this, SfxAcceleratorConfigPage, RadioHdl  ));
    m_xSearchEdit->connect_changed( LINK( this, SfxAcceleratorConfigPage, SearchUpdateHdl ));

    // detect max keyname width
    long nMaxWidth  = 0;
    int nMaxWidth  = 0;
    for (unsigned short i : KEYCODE_ARRAY)
    {
        long nTmp = GetTextWidth( vcl::KeyCode( i ).GetName() );
        int nTmp = m_xEntriesBox->get_pixel_size(vcl::KeyCode(i).GetName()).Width();
        if ( nTmp > nMaxWidth )
            nMaxWidth = nTmp;
    }
    // recalc second tab
    long nNewTab = PixelToLogic(Size(nMaxWidth, 0), MapMode(MapUnit::MapAppFont)).Width();
    nNewTab = nNewTab + 5; // additional space
    m_pEntriesBox->SetTab( 1, nNewTab );
    auto nNewTab = nMaxWidth + 5; // additional space

    // initialize Entriesbox
    std::vector<int> aWidths;
    aWidths.push_back(nNewTab);
    m_xEntriesBox->set_column_fixed_widths(aWidths);

    //Initialize search util
    m_options.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE;
@@ -957,10 +910,18 @@ SfxAcceleratorConfigPage::SfxAcceleratorConfigPage( vcl::Window* pParent, const 
    m_options.searchFlag |= (util::SearchFlags::REG_NOT_BEGINOFLINE |
                                        util::SearchFlags::REG_NOT_ENDOFLINE);
    // initialize GroupBox
    m_pGroupLBox->SetFunctionListBox(m_pFunctionBox);
    m_xGroupLBox->SetFunctionListBox(m_xFunctionBox.get());

    // initialize KeyBox
    m_pKeyBox->SetStyle(m_pKeyBox->GetStyle()|WB_CLIPCHILDREN|WB_HSCROLL|WB_SORT);
    m_xKeyBox->make_sorted();

    m_aUpdateDataTimer.SetInvokeHandler(LINK(this, SfxAcceleratorConfigPage, ImplUpdateDataHdl));
    m_aUpdateDataTimer.SetDebugName( "SfxAcceleratorConfigPage UpdateDataTimer" );
    m_aUpdateDataTimer.SetTimeout(EDIT_UPDATEDATA_TIMEOUT);

    m_aFillGroupIdle.SetInvokeHandler(LINK(this, SfxAcceleratorConfigPage, TimeOut_Impl));
    m_aFillGroupIdle.SetPriority(TaskPriority::HIGHEST);
    m_aFillGroupIdle.SetDebugName("SfxAcceleratorConfigPage m_aFillGroupIdle");
}

SfxAcceleratorConfigPage::~SfxAcceleratorConfigPage()
@@ -970,40 +931,15 @@ SfxAcceleratorConfigPage::~SfxAcceleratorConfigPage()

void SfxAcceleratorConfigPage::dispose()
{
    m_aFillGroupIdle.Stop();

    // free memory - remove all dynamic user data
    SvTreeListEntry* pEntry = m_pEntriesBox->First();
    while (pEntry)
    for (int i = 0, nCount = m_xEntriesBox->n_children(); i < nCount; ++i)
    {
        TAccInfo* pUserData = static_cast<TAccInfo*>(pEntry->GetUserData());
        TAccInfo* pUserData = reinterpret_cast<TAccInfo*>(m_xEntriesBox->get_id(i).toInt64());
        delete pUserData;
        pEntry = m_pEntriesBox->Next(pEntry);
    }

    pEntry = m_pKeyBox->First();
    while (pEntry)
    {
        TAccInfo* pUserData = static_cast<TAccInfo*>(pEntry->GetUserData());
        delete pUserData;
        pEntry = m_pKeyBox->Next(pEntry);
    }

    m_pEntriesBox->Clear();
    m_pKeyBox->Clear();

    m_pFileDlg.reset();
    m_pEntriesBox.clear();
    m_pOfficeButton.clear();
    m_pModuleButton.clear();
    m_pChangeButton.clear();
    m_pRemoveButton.clear();
    m_pGroupLBox.clear();
    m_pFunctionBox.clear();
    m_pKeyBox.clear();
    m_pSearchEdit.clear();
    m_pLoadButton.clear();
    m_pSaveButton.clear();
    m_pResetButton.clear();

    SfxTabPage::dispose();
}

@@ -1057,19 +993,6 @@ void SfxAcceleratorConfigPage::InitAccCfg()
    }
}

/** Initialize text columns with own class to enable custom painting
    This is needed as we have to paint disabled entries by ourself. No support for that in the
    original SvTabListBox!
  */
void SfxAcceleratorConfigPage::CreateCustomItems(SvTreeListEntry* pEntry,
                                                 const OUString& sCol1 ,
                                                 const OUString& sCol2)
{
    pEntry->ReplaceItem(std::make_unique<SfxAccCfgLBoxString_Impl>(sCol1), 1);
    pEntry->ReplaceItem(std::make_unique<SfxAccCfgLBoxString_Impl>(sCol2), 2);
}


void SfxAcceleratorConfigPage::Init(const uno::Reference<ui::XAcceleratorConfiguration>& xAccMgr)
{
    if (!xAccMgr.is())
@@ -1085,7 +1008,7 @@ void SfxAcceleratorConfigPage::Init(const uno::Reference<ui::XAcceleratorConfigu
            xModel = xController->getModel();

        m_aStylesInfo.init(m_sModuleLongName, xModel);
        m_pGroupLBox->SetStylesInfo(&m_aStylesInfo);
        m_xGroupLBox->SetStylesInfo(&m_aStylesInfo);
        m_bStylesInfoInitialized = true;
    }

@@ -1099,15 +1022,14 @@ void SfxAcceleratorConfigPage::Init(const uno::Reference<ui::XAcceleratorConfigu
        if (sKey.isEmpty())
            continue;
        TAccInfo*    pEntry   = new TAccInfo(i1, 0/*nListPos*/, aKey);
        SvTreeListEntry* pLBEntry = m_pEntriesBox->InsertEntryToColumn(sKey, nullptr, TREELIST_APPEND, 0xFFFF);
        pLBEntry->SetUserData(pEntry);
        m_xEntriesBox->append(OUString::number(reinterpret_cast<sal_Int64>(pEntry)), sKey);
        m_xEntriesBox->set_text(m_xEntriesBox->n_children() - 1, OUString(), 1);
    }

    // Assign all commands to its shortcuts - reading the accelerator config.
    uno::Sequence<awt::KeyEvent> lKeys = xAccMgr->getAllKeyEvents();
    sal_Int32 c2 = lKeys.getLength();
    sal_Int32 i2 = 0;
    sal_uInt16 nCol = m_pEntriesBox->TabCount()-1;

    for (i2=0; i2<c2; ++i2)
    {
@@ -1120,14 +1042,12 @@ void SfxAcceleratorConfigPage::Init(const uno::Reference<ui::XAcceleratorConfigu
        if (nPos == -1)
            continue;

        m_pEntriesBox->SetEntryText(sLabel, nPos, nCol);
        m_xEntriesBox->set_text(nPos, sLabel, 1);

        SvTreeListEntry* pLBEntry = m_pEntriesBox->GetEntry(nullptr, nPos);
        TAccInfo* pEntry = static_cast<TAccInfo*>(pLBEntry->GetUserData());

        TAccInfo* pEntry = reinterpret_cast<TAccInfo*>(m_xEntriesBox->get_id(nPos).toInt64());
        pEntry->m_bIsConfigurable = true;

        pEntry->m_sCommand = sCommand;
        CreateCustomItems(pLBEntry, SvTabListBox::GetEntryText(pLBEntry, 0), sLabel);
    }

    // Map the VCL hardcoded key codes and mark them as not changeable
@@ -1142,11 +1062,10 @@ void SfxAcceleratorConfigPage::Init(const uno::Reference<ui::XAcceleratorConfigu
            continue;

        // Hardcoded function mapped so no ID possible and mark entry as not changeable
        SvTreeListEntry* pLBEntry = m_pEntriesBox->GetEntry(nullptr, nPos);
        TAccInfo* pEntry = static_cast<TAccInfo*>(pLBEntry->GetUserData());

        TAccInfo* pEntry = reinterpret_cast<TAccInfo*>(m_xEntriesBox->get_id(nPos).toInt64());
        pEntry->m_bIsConfigurable = false;
        CreateCustomItems(pLBEntry, SvTabListBox::GetEntryText(pLBEntry, 0), OUString());

        m_xEntriesBox->set_sensitive(nPos, false);
    }
}

@@ -1158,10 +1077,9 @@ void SfxAcceleratorConfigPage::Apply(const uno::Reference<ui::XAcceleratorConfig
    // Go through the list from the bottom to the top ...
    // because logical accelerator must be preferred instead of
    // physical ones!
    SvTreeListEntry* pEntry = m_pEntriesBox->First();
    while (pEntry)
    for (int i = 0, nCount = m_xEntriesBox->n_children(); i < nCount; ++i)
    {
        TAccInfo* pUserData = static_cast<TAccInfo*>(pEntry->GetUserData());
        TAccInfo* pUserData = reinterpret_cast<TAccInfo*>(m_xEntriesBox->get_id(i).toInt64());
        OUString sCommand;
        awt::KeyEvent aAWTKey;

@@ -1178,214 +1096,218 @@ void SfxAcceleratorConfigPage::Apply(const uno::Reference<ui::XAcceleratorConfig
            else
                xAccMgr->removeKeyEvent(aAWTKey);
        }
        catch(const uno::RuntimeException&)
        catch (const uno::RuntimeException&)
        {
            throw;
        }
        catch(const uno::Exception&)
        catch (const uno::Exception&)
        {
        }

        pEntry = m_pEntriesBox->Next(pEntry);
    }
}

void SfxAcceleratorConfigPage::ResetConfig()
{
    m_pEntriesBox->Clear();
    m_xEntriesBox->clear();
}

IMPL_LINK_NOARG(SfxAcceleratorConfigPage, SearchUpdateHdl, Edit&, void)
IMPL_LINK_NOARG(SfxAcceleratorConfigPage, ImplUpdateDataHdl, Timer*, void)
{
    m_pGroupLBox->GetSelectHdl().Call( m_pGroupLBox );
    SelectHdl(m_xGroupLBox->get_widget());
}

IMPL_LINK_NOARG(SfxAcceleratorConfigPage, Load, Button*, void)
IMPL_LINK_NOARG(SfxAcceleratorConfigPage, SearchUpdateHdl, weld::Entry&, void)
{
    m_aUpdateDataTimer.Start();
}

IMPL_LINK_NOARG(SfxAcceleratorConfigPage, Load, weld::Button&, void)
{
    // ask for filename, where we should load the new config data from
    StartFileDialog( StartFileDialogType::Open, aLoadAccelConfigStr );
}

IMPL_LINK_NOARG(SfxAcceleratorConfigPage, Save, Button*, void)
IMPL_LINK_NOARG(SfxAcceleratorConfigPage, Save, weld::Button&, void)
{
    StartFileDialog( StartFileDialogType::SaveAs, aSaveAccelConfigStr );
}

IMPL_LINK_NOARG(SfxAcceleratorConfigPage, Default, Button*, void)
IMPL_LINK_NOARG(SfxAcceleratorConfigPage, Default, weld::Button&, void)
{
    uno::Reference<form::XReset> xReset(m_xAct, uno::UNO_QUERY);
    if (xReset.is())
        xReset->reset();

    m_pEntriesBox->SetUpdateMode(false);
    m_xEntriesBox->freeze();
    ResetConfig();
    Init(m_xAct);
    m_pEntriesBox->SetUpdateMode(true);
    m_pEntriesBox->Invalidate();
    m_pEntriesBox->Select(m_pEntriesBox->GetEntry(nullptr, 0));
    m_xEntriesBox->thaw();
    m_xEntriesBox->select(0);
    SelectHdl(*m_xEntriesBox);
}

IMPL_LINK_NOARG(SfxAcceleratorConfigPage, ChangeHdl, Button*, void)
IMPL_LINK_NOARG(SfxAcceleratorConfigPage, ChangeHdl, weld::Button&, void)
{
    sal_uLong nPos = SvTreeList::GetRelPos( m_pEntriesBox->FirstSelected() );
    TAccInfo* pEntry = static_cast<TAccInfo*>(m_pEntriesBox->GetEntry(nullptr, nPos)->GetUserData());
    OUString sNewCommand = m_pFunctionBox->GetCurCommand();
    OUString sLabel = m_pFunctionBox->GetCurLabel();
    int nPos = m_xEntriesBox->get_selected_index();
    if (nPos == -1)
        return;

    TAccInfo* pEntry = reinterpret_cast<TAccInfo*>(m_xEntriesBox->get_id(nPos).toInt64());
    OUString sNewCommand = m_xFunctionBox->GetCurCommand();
    OUString sLabel = m_xFunctionBox->GetCurLabel();
    if (sLabel.isEmpty())
        sLabel = GetLabel4Command(sNewCommand);

    pEntry->m_sCommand = sNewCommand;
    sal_uInt16 nCol = m_pEntriesBox->TabCount() - 1;
    m_pEntriesBox->SetEntryText(sLabel, nPos, nCol);
    m_xEntriesBox->set_text(nPos, sLabel, 1);

    m_pFunctionBox->GetSelectHdl().Call( m_pFunctionBox );
    SelectHdl(m_xFunctionBox->get_widget());
}

IMPL_LINK_NOARG(SfxAcceleratorConfigPage, RemoveHdl, Button*, void)
IMPL_LINK_NOARG(SfxAcceleratorConfigPage, RemoveHdl, weld::Button&, void)
{
    // get selected entry
    sal_uLong nPos = SvTreeList::GetRelPos( m_pEntriesBox->FirstSelected() );
    TAccInfo* pEntry = static_cast<TAccInfo*>(m_pEntriesBox->GetEntry(nullptr, nPos)->GetUserData());
    int nPos = m_xEntriesBox->get_selected_index();
    if (nPos == -1)
        return;

    TAccInfo* pEntry = reinterpret_cast<TAccInfo*>(m_xEntriesBox->get_id(nPos).toInt64());

    // remove function name from selected entry
    sal_uInt16 nCol = m_pEntriesBox->TabCount() - 1;
    m_pEntriesBox->SetEntryText( OUString(), nPos, nCol );
    m_xEntriesBox->set_text(nPos, OUString(), 1);
    pEntry->m_sCommand.clear();

    m_pFunctionBox->GetSelectHdl().Call( m_pFunctionBox );
    SelectHdl(m_xFunctionBox->get_widget());
}

IMPL_LINK( SfxAcceleratorConfigPage, SelectHdl, SvTreeListBox*, pListBox, void )
IMPL_LINK(SfxAcceleratorConfigPage, SelectHdl, weld::TreeView&, rListBox, void)
{
    // disable help
    Help::ShowBalloon( this, Point(), ::tools::Rectangle(), OUString() );
    if (pListBox == m_pEntriesBox)
    if (&rListBox == m_xEntriesBox.get())
    {
        sal_uLong nPos = SvTreeList::GetRelPos( m_pEntriesBox->FirstSelected() );
        TAccInfo* pEntry = static_cast<TAccInfo*>(m_pEntriesBox->GetEntry(nullptr, nPos)->GetUserData());
        OUString sPossibleNewCommand = m_pFunctionBox->GetCurCommand();
        TAccInfo* pEntry = reinterpret_cast<TAccInfo*>(m_xEntriesBox->get_selected_id().toInt64());

        m_pRemoveButton->Enable( false );
        m_pChangeButton->Enable( false );
        OUString sPossibleNewCommand = m_xFunctionBox->GetCurCommand();

        m_xRemoveButton->set_sensitive( false );
        m_xChangeButton->set_sensitive( false );

        if (pEntry->m_bIsConfigurable)
        {
            if (pEntry->isConfigured())
                m_pRemoveButton->Enable();
            m_pChangeButton->Enable( pEntry->m_sCommand != sPossibleNewCommand );
                m_xRemoveButton->set_sensitive(true);
            m_xChangeButton->set_sensitive( pEntry->m_sCommand != sPossibleNewCommand );
        }
    }
    else if ( pListBox == m_pGroupLBox )
    else if (&rListBox == &m_xGroupLBox->get_widget())
    {
        m_pGroupLBox->GroupSelected();
        m_xGroupLBox->GroupSelected();

        // Pause redraw (Do not redraw at each removal)
        m_pFunctionBox->SetUpdateMode(false);
        m_xFunctionBox->freeze();
        // Apply the search filter to the functions list
        OUString aSearchTerm( m_pSearchEdit->GetText() );
        SvTreeListEntry* aMatchFound = applySearchFilter(aSearchTerm, m_pFunctionBox);
        OUString aSearchTerm(m_xSearchEdit->get_text());
        int nMatchFound = applySearchFilter(aSearchTerm);
        // Resume redraw
        m_pFunctionBox->SetUpdateMode(true);
        if (aMatchFound)
            m_pFunctionBox->Select(aMatchFound);
        m_xFunctionBox->thaw();
        if (nMatchFound != -1)
        {
            m_xFunctionBox->select(nMatchFound);
            SelectHdl(m_xFunctionBox->get_widget());
        }
        else
            m_pKeyBox->Clear();

        if ( !m_pFunctionBox->FirstSelected() )
            m_pChangeButton->Enable( false );
        {
            m_xKeyBox->clear();
            m_xChangeButton->set_sensitive(false);
        }
    }
    else if ( pListBox == m_pFunctionBox )
    else if (&rListBox == &m_xFunctionBox->get_widget())
    {
        m_pRemoveButton->Enable( false );
        m_pChangeButton->Enable( false );
        m_xRemoveButton->set_sensitive( false );
        m_xChangeButton->set_sensitive( false );

        // #i36994 First selected can return zero!
        SvTreeListEntry* pLBEntry = m_pEntriesBox->FirstSelected();
        if ( pLBEntry != nullptr )
        TAccInfo* pEntry = reinterpret_cast<TAccInfo*>(m_xEntriesBox->get_selected_id().toInt64());
        if (pEntry)
        {
            sal_uLong nPos = SvTreeList::GetRelPos( pLBEntry );
            TAccInfo* pEntry = static_cast<TAccInfo*>(m_pEntriesBox->GetEntry(nullptr, nPos)->GetUserData());
            OUString sPossibleNewCommand = m_pFunctionBox->GetCurCommand();
            OUString sPossibleNewCommand = m_xFunctionBox->GetCurCommand();

            if (pEntry->m_bIsConfigurable)
            {
                if (pEntry->isConfigured())
                    m_pRemoveButton->Enable();
                m_pChangeButton->Enable( pEntry->m_sCommand != sPossibleNewCommand );
                    m_xRemoveButton->set_sensitive(true);
                m_xChangeButton->set_sensitive( pEntry->m_sCommand != sPossibleNewCommand );
            }

            // update key box
            m_pKeyBox->Clear();
            SvTreeListEntry* pIt = m_pEntriesBox->First();
            while ( pIt )
            m_xKeyBox->clear();
            for (int i = 0, nCount = m_xEntriesBox->n_children(); i < nCount; ++i)
            {
                TAccInfo* pUserData = static_cast<TAccInfo*>(pIt->GetUserData());
                if ( pUserData && pUserData->m_sCommand == sPossibleNewCommand )
                TAccInfo* pUserData = reinterpret_cast<TAccInfo*>(m_xEntriesBox->get_id(i).toInt64());
                if (pUserData && pUserData->m_sCommand == sPossibleNewCommand)
                {
                    TAccInfo* pU1 = new TAccInfo(-1, -1, pUserData->m_aKey);
                    SvTreeListEntry* pE1 = m_pKeyBox->InsertEntry( pUserData->m_aKey.GetName(), nullptr, true );
                    pE1->SetUserData(pU1);
                    pE1->EnableChildrenOnDemand( false );
                    m_xKeyBox->append(OUString::number(reinterpret_cast<sal_Int64>(pUserData)), pUserData->m_aKey.GetName());
                }
                pIt = m_pEntriesBox->Next(pIt);
            }
        }
    }
    else
    {
        // goto selected "key" entry of the key box
        SvTreeListEntry* pE2 = nullptr;
        TAccInfo* pU2 = nullptr;
        sal_Int32 nP2 = -1;
        SvTreeListEntry* pE3 = nullptr;

        pE2 = m_pKeyBox->FirstSelected();
        if (pE2)
            pU2 = static_cast<TAccInfo*>(pE2->GetUserData());
        int nP2 = -1;
        TAccInfo* pU2 = reinterpret_cast<TAccInfo*>(m_xKeyBox->get_selected_id().toInt64());
        if (pU2)
            nP2 = MapKeyCodeToPos(pU2->m_aKey);
        if (nP2 != -1)
            pE3 = m_pEntriesBox->GetEntry( nullptr, nP2 );
        if (pE3)
        {
            m_pEntriesBox->Select( pE3 );
            m_pEntriesBox->MakeVisible( pE3 );
            m_xEntriesBox->select(nP2);
            m_xEntriesBox->scroll_to_row(nP2);
            SelectHdl(*m_xEntriesBox);
        }
    }
}

IMPL_LINK_NOARG(SfxAcceleratorConfigPage, RadioHdl, Button*, void)
IMPL_LINK_NOARG(SfxAcceleratorConfigPage, RadioHdl, weld::Button&, void)
{
    uno::Reference<ui::XAcceleratorConfiguration> xOld = m_xAct;

    if (m_pOfficeButton->IsChecked())
    if (m_xOfficeButton->get_active())
        m_xAct = m_xGlobal;
    else if (m_pModuleButton->IsChecked())
    else if (m_xModuleButton->get_active())
        m_xAct = m_xModule;

    // nothing changed? => do nothing!
    if ( m_xAct.is() && ( xOld == m_xAct ) )
        return;

    m_pEntriesBox->SetUpdateMode( false );
    m_xEntriesBox->freeze();
    ResetConfig();
    Init(m_xAct);
    m_pEntriesBox->SetUpdateMode( true );
    m_pEntriesBox->Invalidate();
    m_xEntriesBox->thaw();

    m_pGroupLBox->Init(m_xContext, m_xFrame, m_sModuleLongName, true);
    m_xGroupLBox->Init(m_xContext, m_xFrame, m_sModuleLongName, true);

    // pb: #133213# do not select NULL entries
    SvTreeListEntry* pEntry = m_pEntriesBox->GetEntry( nullptr, 0 );
    if ( pEntry )
        m_pEntriesBox->Select( pEntry );
    pEntry = m_pGroupLBox->GetEntry( nullptr, 0 );
    if ( pEntry )
        m_pGroupLBox->Select( pEntry );
    if (m_xEntriesBox->n_children())
        m_xEntriesBox->select(0);

    m_pFunctionBox->GetSelectHdl().Call( m_pFunctionBox );
    m_aFillGroupIdle.Start();
}

IMPL_LINK_NOARG(SfxAcceleratorConfigPage, TimeOut_Impl, Timer*, void)
{
    // activating the selection, typically "all commands", can take a long time
    // -> show wait cursor and disable input
    weld::Window* pDialog = GetDialogFrameWeld();
    // perhaps the tabpage is part of a SingleTabDialog then pDialog == nullptr
    std::unique_ptr<weld::WaitObject> xWait(pDialog ? new weld::WaitObject(pDialog) : nullptr);

    weld::TreeView& rTreeView = m_xGroupLBox->get_widget();
    SelectHdl(rTreeView);

    SelectHdl(m_xFunctionBox->get_widget());
}

IMPL_LINK_NOARG(SfxAcceleratorConfigPage, LoadHdl, sfx2::FileDialogHelper*, void)
{
@@ -1425,13 +1347,15 @@ IMPL_LINK_NOARG(SfxAcceleratorConfigPage, LoadHdl, sfx2::FileDialogHelper*, void
            // open the configuration and update our UI
            uno::Reference<ui::XAcceleratorConfiguration> xTempAccMgr(xCfgMgr->getShortCutManager(), uno::UNO_QUERY_THROW);

            m_pEntriesBox->SetUpdateMode(false);
            m_xEntriesBox->freeze();
            ResetConfig();
            Init(xTempAccMgr);
            m_pEntriesBox->SetUpdateMode(true);
            m_pEntriesBox->Invalidate();
            m_pEntriesBox->Select(m_pEntriesBox->GetEntry(nullptr, 0));

            m_xEntriesBox->thaw();
            if (m_xEntriesBox->n_children())
            {
                m_xEntriesBox->select(0);
                SelectHdl(m_xFunctionBox->get_widget());
            }
        }

        // don't forget to close the new opened storage!
@@ -1587,45 +1511,40 @@ void SfxAcceleratorConfigPage::Reset( const SfxItemSet* rSet )

    // change the description of the radio button, which switch to the module
    // dependent accelerator configuration
    OUString sButtonText = m_pModuleButton->GetText();
    OUString sButtonText = m_xModuleButton->get_label();
    sButtonText = sButtonText.replaceFirst("$(MODULE)", m_sModuleUIName);
    m_pModuleButton->SetText(sButtonText);
    m_xModuleButton->set_label(sButtonText);

    if (m_xModule.is())
        m_pModuleButton->Check();
        m_xModuleButton->set_active(true);
    else
    {
        m_pModuleButton->Hide();
        m_pOfficeButton->Check();
        m_xModuleButton->hide();
        m_xOfficeButton->set_active(true);
    }

    RadioHdl(nullptr);
    RadioHdl(*m_xOfficeButton);

    const SfxPoolItem* pMacroItem=nullptr;
    if( SfxItemState::SET == rSet->GetItemState( SID_MACROINFO, true, &pMacroItem ) )
    {
        m_pMacroInfoItem = &dynamic_cast<const SfxMacroInfoItem&>(*pMacroItem);
        m_pGroupLBox->SelectMacro( m_pMacroInfoItem );
        m_xGroupLBox->SelectMacro( m_pMacroInfoItem );
    }
}

sal_Int32 SfxAcceleratorConfigPage::MapKeyCodeToPos(const vcl::KeyCode& aKey) const
{
    sal_uInt16 nCode1 = aKey.GetCode() + aKey.GetModifier();
    SvTreeListEntry* pEntry = m_pEntriesBox->First();
    sal_Int32 i = 0;

    while (pEntry)
    for (int i = 0, nCount = m_xEntriesBox->n_children(); i < nCount; ++i)
    {
        TAccInfo* pUserData = static_cast<TAccInfo*>(pEntry->GetUserData());
        TAccInfo* pUserData = reinterpret_cast<TAccInfo*>(m_xEntriesBox->get_id(i).toInt64());
        if (pUserData)
        {
            sal_uInt16 nCode2 = pUserData->m_aKey.GetCode()+pUserData->m_aKey.GetModifier();
            if (nCode1 == nCode2)
                return i;
        }
        pEntry = m_pEntriesBox->Next(pEntry);
        ++i;
    }

    return -1;
@@ -1669,39 +1588,26 @@ OUString SfxAcceleratorConfigPage::GetLabel4Command(const OUString& sCommand)
/*
 * Remove entries which doesn't contain the search term
 */
SvTreeListEntry* SfxAcceleratorConfigPage::applySearchFilter(OUString const & rSearchTerm, SvTreeListBox* rListBox)
int SfxAcceleratorConfigPage::applySearchFilter(OUString const & rSearchTerm)
{
    if ( rSearchTerm.isEmpty() || !rListBox )
    {
        return nullptr;
    }

    SvTreeListEntry* pFirstMatch = nullptr;
    SvTreeListEntry* pEntry = rListBox->First();
    if (rSearchTerm.isEmpty())
        return -1;

    m_options.searchString = rSearchTerm;
    utl::TextSearch textSearch( m_options );

    while(pEntry)
    for (int i = m_xFunctionBox->n_children(); i > 0; --i)
    {
        OUString aStr = rListBox->GetEntryText(pEntry);
        SvTreeListEntry* pNextEntry = rListBox->Next(pEntry);
        int nEntry = i - 1;
        OUString aStr = m_xFunctionBox->get_text(nEntry);
        sal_Int32 aStartPos = 0;
        sal_Int32 aEndPos = aStr.getLength();

        if (!textSearch.SearchForward( aStr, &aStartPos, &aEndPos ))
        {
            rListBox->RemoveEntry(pEntry);
        }
        else if (!pFirstMatch)
        {
            pFirstMatch = pEntry;
        }

        pEntry = pNextEntry;
            m_xFunctionBox->remove(nEntry);
    }

    return pFirstMatch;
    return m_xFunctionBox->n_children() ? 0 : -1;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/source/customize/cfg.cxx b/cui/source/customize/cfg.cxx
index 63db3c5..0fd8d4a 100644
--- a/cui/source/customize/cfg.cxx
+++ b/cui/source/customize/cfg.cxx
@@ -188,7 +188,7 @@ static VclPtr<SfxTabPage> CreateSvxContextMenuConfigPage( TabPageParent pParent,

static VclPtr<SfxTabPage> CreateKeyboardConfigPage( TabPageParent pParent, const SfxItemSet* rSet )
{
       return VclPtr<SfxAcceleratorConfigPage>::Create( pParent.pParent, *rSet );
       return VclPtr<SfxAcceleratorConfigPage>::Create(pParent, *rSet);
}

static VclPtr<SfxTabPage> CreateSvxToolbarConfigPage( TabPageParent pParent, const SfxItemSet* rSet )
diff --git a/cui/source/customize/cfgutil.cxx b/cui/source/customize/cfgutil.cxx
index c00d17e..2510066 100644
--- a/cui/source/customize/cfgutil.cxx
+++ b/cui/source/customize/cfgutil.cxx
@@ -351,24 +351,23 @@ OUString CuiConfigFunctionListBox::GetHelpText( bool bConsiderParent )
    return OUString();
}


OUString SfxConfigFunctionListBox::GetCurCommand()
OUString CuiConfigFunctionListBox::GetCurCommand()
{
    SvTreeListEntry *pEntry = FirstSelected();
    if (!pEntry)
    int nSelected = m_xTreeView->get_selected_index();
    if (nSelected == -1)
        return OUString();
    SfxGroupInfo_Impl *pData = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData());
    SfxGroupInfo_Impl *pData = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(nSelected).toInt64());
    if (!pData)
        return OUString();
    return pData->sCommand;
}

OUString SfxConfigFunctionListBox::GetCurLabel()
OUString CuiConfigFunctionListBox::GetCurLabel()
{
    SvTreeListEntry *pEntry = FirstSelected();
    if (!pEntry)
    int nSelected = m_xTreeView->get_selected_index();
    if (nSelected == -1)
        return OUString();
    SfxGroupInfo_Impl *pData = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData());
    SfxGroupInfo_Impl *pData = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(nSelected).toInt64());
    if (!pData)
        return OUString();
    if (!pData->sLabel.isEmpty())
@@ -431,42 +430,11 @@ OUString CuiConfigFunctionListBox::GetSelectedScriptURI()
    return OUString();
}

struct SvxConfigGroupBoxResource_Impl
{
    Image m_hdImage;
    Image m_libImage;
    Image m_macImage;
    Image m_docImage;
    OUString m_sMyMacros;
    OUString m_sProdMacros;
    OUString m_sMacros;
    OUString m_sDlgMacros;
    OUString m_aStrGroupStyles;
    Image m_collapsedImage;
    Image m_expandedImage;

    SvxConfigGroupBoxResource_Impl();
};

SvxConfigGroupBoxResource_Impl::SvxConfigGroupBoxResource_Impl() :
    m_hdImage(StockImage::Yes, RID_CUIBMP_HARDDISK),
    m_libImage(StockImage::Yes, RID_CUIBMP_LIB),
    m_macImage(StockImage::Yes, RID_CUIBMP_MACRO),
    m_docImage(StockImage::Yes, 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)),
    m_collapsedImage(StockImage::Yes, RID_CUIBMP_COLLAPSED),
    m_expandedImage(StockImage::Yes, RID_CUIBMP_EXPANDED)
{
}

struct CuiConfigGroupBoxResource_Impl
{
    OUString m_sMyMacros;
    OUString m_sProdMacros;
    OUString m_sMacros;
    OUString m_sDlgMacros;
    OUString m_aStrGroupStyles;

@@ -476,109 +444,17 @@ struct CuiConfigGroupBoxResource_Impl
CuiConfigGroupBoxResource_Impl::CuiConfigGroupBoxResource_Impl() :
    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())
    , pFunctionListBox(nullptr)
    , pStylesInfo(nullptr)
{
    SetStyle( GetStyle() | WB_CLIPCHILDREN | WB_HSCROLL | WB_HASBUTTONS | WB_HASLINES | WB_HASLINESATROOT | WB_HASBUTTONSATROOT );
    SetNodeBitmaps(xImp->m_collapsedImage, xImp->m_expandedImage);
}

VCL_BUILDER_FACTORY_CONSTRUCTOR(SfxConfigGroupListBox, WB_TABSTOP)

SfxConfigGroupListBox::~SfxConfigGroupListBox()
{
    disposeOnce();
}

void SfxConfigGroupListBox::dispose()
{
    ClearAll();
    pFunctionListBox.clear();
    SvTreeListBox::dispose();
}

void SfxConfigGroupListBox::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();
    Clear();
}

void SfxConfigGroupListBox::SetStylesInfo(SfxStylesInfo_Impl* pStyles)
{
    pStylesInfo = pStyles;
}

void CuiConfigGroupListBox::SetStylesInfo(SfxStylesInfo_Impl* pStyles)
{
    m_pStylesInfo = pStyles;
}

void SfxConfigGroupListBox::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
            SvTreeListEntry* pEntry = InsertEntry( CuiResId(RID_SVXSTR_ALLFUNCTIONS) );
            aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_ALLFUNCTIONS, 0 ) );
            pEntry->SetUserData(aArr.back().get());
        }

        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; }

            SvTreeListEntry*        pEntry = InsertEntry(sGroupName);
            aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_FUNCTION, rGroupID ) );
            pEntry->SetUserData(aArr.back().get());
        }
    }
    catch(const css::uno::RuntimeException&)
        { throw; }
    catch(const css::uno::Exception&)
        {}
}


namespace
{

@@ -631,602 +507,6 @@ namespace
    }
}


void SfxConfigGroupListBox::FillScriptList(const css::uno::Reference< css::script::browse::XBrowseNode >& xRootNode,
                                           SvTreeListEntry* 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();

                    Image aImage = GetImage( theChild, m_xContext, bIsRootNode );
                    SvTreeListEntry* pNewEntry =
                        InsertEntry( uiName, pParentEntry );
                    SetExpandedEntryBmp(  pNewEntry, aImage );
                    SetCollapsedEntryBmp( pNewEntry, aImage );

                    aArr.push_back( std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_SCRIPTCONTAINER,
                            0, static_cast<void *>( theChild.get())));

                    pNewEntry->SetUserData( aArr.back().get() );

                    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 )
                            {
                                pNewEntry->EnableChildrenOnDemand();
                                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 */
                        pNewEntry->EnableChildrenOnDemand();
                    }
                }
            }
        }
    }
    catch (RuntimeException&) {
        // do nothing, the entry will not be displayed in the UI
    }
}

void SfxConfigGroupListBox::FillFunctionsList(const css::uno::Sequence<DispatchInformation>& xCommands)
{
    for (const auto & rInfo : xCommands)
    {
        OUString sUIName = MapCommand2UIName(rInfo.Command);
        SvTreeListEntry* pFuncEntry = pFunctionListBox->InsertEntry(sUIName );
        aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SLOT, 0 ) );
        SfxGroupInfo_Impl* pGrpInfo = aArr.back().get();
        pGrpInfo->sCommand = rInfo.Command;
        pGrpInfo->sLabel   = sUIName;
        pFuncEntry->SetUserData(pGrpInfo);
    }
}

void SfxConfigGroupListBox::Init(const css::uno::Reference< css::uno::XComponentContext >& xContext,
    const css::uno::Reference< css::frame::XFrame >& xFrame,
    const OUString& sModuleLongName,
    bool bEventMode)
{
    SetUpdateMode(false);
    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( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_SCRIPTCONTAINER, 0,
                    static_cast<void *>(rootNode.get())));
            OUString aTitle(xImp->m_sDlgMacros);
            SvTreeListEntry *pNewEntry = InsertEntry( aTitle );
            pNewEntry->SetUserData( aArr.back().get() );
            pNewEntry->EnableChildrenOnDemand();
        }
        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 )
    {
        OUString sStyle(xImp->m_aStrGroupStyles);
        SvTreeListEntry *pEntry = InsertEntry( sStyle );
        aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, nullptr ) ); // TODO last parameter should contain user data
        pEntry->SetUserData( aArr.back().get() );
        pEntry->EnableChildrenOnDemand();
    }

    MakeVisible( GetEntry( nullptr,0 ) );
    SetUpdateMode( true );
}

Image SfxConfigGroupListBox::GetImage(
    const Reference< browse::XBrowseNode >& node,
    Reference< XComponentContext > const & xCtx,
    bool bIsRootNode
)
{
    Image 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::GetFileImage( 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  >
SfxConfigGroupListBox::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 SfxConfigGroupListBox::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 SfxConfigGroupListBox::GroupSelected()
/*  Description
    A function group or a basic module has been selected.
    All functions/macros are displayed in the functionlistbox.
*/
{
    SvTreeListEntry *pEntry = FirstSelected();
    SfxGroupInfo_Impl *pInfo = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData());
    pFunctionListBox->SetUpdateMode(false);
    pFunctionListBox->ClearAll();

    switch ( pInfo->nKind )
    {
        case SfxCfgKind::GROUP_ALLFUNCTIONS:
        {
            css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider( m_xFrame, UNO_QUERY );
            SvTreeListEntry *pCurrEntry = First();
            while( pCurrEntry )
            {
                SfxGroupInfo_Impl *pCurrentInfo = static_cast<SfxGroupInfo_Impl*>(pCurrEntry->GetUserData());
                if (pCurrentInfo->nKind == SfxCfgKind::GROUP_FUNCTION)
                {
                    css::uno::Sequence< css::frame::DispatchInformation > lCommands;
                    try
                    {
                        lCommands = xProvider->getConfigurableDispatchInformation( pCurrentInfo->nUniqueID );
                        FillFunctionsList( lCommands );
                    }
                    catch ( container::NoSuchElementException& )
                    {
                    }
                }
                pCurrEntry = Next( pCurrEntry );
            }
            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 ( !GetChildCount( pEntry ) )
            {
                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 );

                                Image aImage = GetImage( children[n], Reference< XComponentContext >(), false );
                                SvTreeListEntry* pNewEntry =
                                    pFunctionListBox->InsertEntry( children[n]->getName() );
                                pFunctionListBox->SetExpandedEntryBmp( pNewEntry, aImage );
                                pFunctionListBox->SetCollapsedEntryBmp(pNewEntry, aImage );

                                pFunctionListBox->aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI ));
                                pFunctionListBox->aArr.back()->sCommand = uri;
                                pFunctionListBox->aArr.back()->sLabel = children[n]->getName();
                                pFunctionListBox->aArr.back()->sHelpText = description;
                                pNewEntry->SetUserData( pFunctionListBox->aArr.back().get() );
                            }
                        }
                    }
                }
                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 = pStylesInfo->getStyles(pFamily->sFamily);
                for (auto const& lStyle : lStyles)
                {
                    SfxStyleInfo_Impl* pStyle = new SfxStyleInfo_Impl(lStyle);
                    SvTreeListEntry* pFuncEntry = pFunctionListBox->InsertEntry( pStyle->sLabel );
                    pFunctionListBox->aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, pStyle ) );
                    pFunctionListBox->aArr.back()->sCommand = pStyle->sCommand;
                    pFunctionListBox->aArr.back()->sLabel = pStyle->sLabel;
                    pFuncEntry->SetUserData( pFunctionListBox->aArr.back().get() );
                }
            }
            break;
        }

        default:
            // Do nothing, the list box will stay empty
            SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " <<  static_cast<int>(pInfo->nKind) );
            break;
    }

    if ( pFunctionListBox->GetEntryCount() )
        pFunctionListBox->Select( pFunctionListBox->GetEntry( nullptr, 0 ) );

    pFunctionListBox->SetUpdateMode(true);
}

bool SfxConfigGroupListBox::Expand( SvTreeListEntry* pParent )
{
    bool bRet = SvTreeListBox::Expand( pParent );
    if ( bRet )
    {
        sal_uLong nEntries = GetOutputSizePixel().Height() / GetEntryHeight();

        sal_uLong nChildCount = GetVisibleChildCount( pParent );

        if ( nChildCount+1 > nEntries )
        {
            MakeVisible( pParent, true );
        }
        else
        {
            SvTreeListEntry *pEntry = GetFirstEntryInView();
            sal_uLong nParentPos = 0;
            while ( pEntry && pEntry != pParent )
            {
                ++nParentPos;
                pEntry = GetNextEntryInView( pEntry );
            }

            if ( nParentPos + nChildCount + 1 > nEntries )
                ScrollOutputArea( static_cast<short>( nEntries - ( nParentPos + nChildCount + 1 ) ) );
        }
    }

    return bRet;
}

void SfxConfigGroupListBox::RequestingChildren( SvTreeListEntry *pEntry )
/*  Description
    A basic or a library is opened.
*/
{
    SfxGroupInfo_Impl *pInfo = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData());
    switch ( pInfo->nKind )
    {
        case SfxCfgKind::GROUP_SCRIPTCONTAINER:
        {
            if ( !GetChildCount( pEntry ) )
            {
                Reference< browse::XBrowseNode > rootNode(
                    static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ;
                FillScriptList(rootNode, pEntry, true /* i30923 */ );
            }
            break;
        }

        case SfxCfgKind::GROUP_STYLES:
        {
            if ( !GetChildCount( pEntry ) )
            {
                const std::vector< SfxStyleInfo_Impl >                 lStyleFamilies = pStylesInfo->getStyleFamilies();
                for (auto const& lStyleFamily : lStyleFamilies)
                {
                    SfxStyleInfo_Impl* pFamily = new SfxStyleInfo_Impl(lStyleFamily);
                    SvTreeListEntry* pStyleEntry = InsertEntry( pFamily->sLabel, pEntry );
                    aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, pFamily ));
                    pStyleEntry->SetUserData( aArr.back().get() );
                    pStyleEntry->EnableChildrenOnDemand( false );
                }
            }
            break;
        }

        default:
            OSL_FAIL( "Wrong group type!" );
            break;
    }
}

void SfxConfigGroupListBox::SelectMacro( const SfxMacroInfoItem *pItem )
{
    SelectMacro( pItem->GetBasicManager()->GetName(),
                 pItem->GetQualifiedName() );
}

void SfxConfigGroupListBox::SelectMacro( const OUString& rBasic,
         const OUString& rMacro )
{
    const OUString aBasicName(rBasic + " " + xImp->m_sMacros);
    sal_Int32 nIdx {rMacro.lastIndexOf('.')};
    const OUString aMethod( rMacro.copy(nIdx+1) );
    OUString aLib;
    OUString aModule;
    if ( nIdx>0 )
    {
        // string contains at least 2 tokens
        nIdx = rMacro.lastIndexOf('.', nIdx);
        if (nIdx>=0)
        {
            // string contains at least 3 tokens
            aLib = rMacro.getToken( 0, '.' );
            aModule = rMacro.getToken( 0, '.', ++nIdx );
        }
    }

    SvTreeListEntry *pEntry = FirstChild(nullptr);
    while ( pEntry )
    {
        OUString aEntryBas = GetEntryText( pEntry );
        if ( aEntryBas == aBasicName )
        {
            Expand( pEntry );
            SvTreeListEntry *pLib = FirstChild( pEntry );
            while ( pLib )
            {
                OUString aEntryLib = GetEntryText( pLib );
                if ( aEntryLib == aLib )
                {
                    Expand( pLib );
                    SvTreeListEntry *pMod = FirstChild( pLib );
                    while ( pMod )
                    {
                        OUString aEntryMod = GetEntryText( pMod );
                        if ( aEntryMod == aModule )
                        {
                            Expand( pMod );
                            MakeVisible( pMod );
                            Select( pMod );
                            SvTreeListEntry *pMethod = pFunctionListBox->First();
                            while ( pMethod )
                            {
                                OUString aEntryMethod = GetEntryText( pMethod );
                                if ( aEntryMethod == aMethod )
                                {
                                    pFunctionListBox->Select( pMethod );
                                    pFunctionListBox->MakeVisible( pMethod );
                                    return;
                                }
                                pMethod = pFunctionListBox->Next( pMethod );
                            }
                        }
                        pMod = pMod->NextSibling();
                    }
                }
                pLib = pLib->NextSibling();
            }
        }
        pEntry = pEntry->NextSibling();
    }
}

CuiConfigGroupListBox::CuiConfigGroupListBox(std::unique_ptr<weld::TreeView> xTreeView)
    : xImp(new CuiConfigGroupBoxResource_Impl())
    , m_pFunctionListBox(nullptr)
@@ -1424,6 +704,7 @@ void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::scrip

void CuiConfigGroupListBox::FillFunctionsList(const css::uno::Sequence<DispatchInformation>& xCommands)
{
    m_pFunctionListBox->freeze();
    for (const auto & rInfo : xCommands)
    {
        OUString sUIName = MapCommand2UIName(rInfo.Command);
@@ -1433,6 +714,7 @@ void CuiConfigGroupListBox::FillFunctionsList(const css::uno::Sequence<DispatchI
        pGrpInfo->sLabel   = sUIName;
        m_pFunctionListBox->append(OUString::number(reinterpret_cast<sal_Int64>(pGrpInfo)), sUIName);
    }
    m_pFunctionListBox->thaw();
}

void CuiConfigGroupListBox::Init(const css::uno::Reference< css::uno::XComponentContext >& xContext,
@@ -1803,6 +1085,82 @@ IMPL_LINK(CuiConfigGroupListBox, ExpandingHdl, weld::TreeIter&, rIter, bool)
    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);
    sal_Int32 nIdx {rMacro.lastIndexOf('.')};
    const OUString aMethod( rMacro.copy(nIdx+1) );
    OUString aLib;
    OUString aModule;
    if ( nIdx>0 )
    {
        // string contains at least 2 tokens
        nIdx = rMacro.lastIndexOf('.', nIdx);
        if (nIdx>=0)
        {
            // string contains at least 3 tokens
            aLib = rMacro.getToken( 0, '.' );
            aModule = rMacro.getToken( 0, '.', ++nIdx );
        }
    }

    std::unique_ptr<weld::TreeIter> xIter = m_xTreeView->make_iterator();
    if (!m_xTreeView->get_iter_first(*xIter))
        return;

    do
    {
        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());
            if (m_xTreeView->get_iter_first(*xLibIter))
            {
                do
                {
                    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());
                        if (m_xTreeView->get_iter_first(*xModIter))
                        {
                            do
                            {
                                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);
                                    for (int i = 0, nCount = m_pFunctionListBox->n_children(); i < nCount; ++i)
                                    {
                                        OUString aEntryMethod = m_pFunctionListBox->get_text(i);
                                        if (aEntryMethod == aMethod)
                                        {
                                            m_pFunctionListBox->select(i);
                                            m_pFunctionListBox->scroll_to_row(i);
                                            return;
                                        }
                                    }
                                }
                            } while (m_xTreeView->iter_next_sibling(*xModIter));
                        }
                    }
                } while (m_xTreeView->iter_next_sibling(*xLibIter));
            }
        }
    } while (m_xTreeView->iter_next_sibling(*xIter));
}

/*
 * Implementation of SvxScriptSelectorDialog
 *
diff --git a/cui/source/inc/acccfg.hxx b/cui/source/inc/acccfg.hxx
index 436fbbe..b4bbae8 100644
--- a/cui/source/inc/acccfg.hxx
+++ b/cui/source/inc/acccfg.hxx
@@ -100,18 +100,6 @@ private:
    const SfxMacroInfoItem*         m_pMacroInfoItem;
    std::unique_ptr<sfx2::FileDialogHelper> m_pFileDlg;

    VclPtr<SfxAccCfgTabListBox_Impl>    m_pEntriesBox;
    VclPtr<RadioButton>                 m_pOfficeButton;
    VclPtr<RadioButton>                 m_pModuleButton;
    VclPtr<PushButton>                  m_pChangeButton;
    VclPtr<PushButton>                  m_pRemoveButton;
    VclPtr<SfxConfigGroupListBox>       m_pGroupLBox;
    VclPtr<SfxConfigFunctionListBox>    m_pFunctionBox;
    VclPtr<SvTreeListBox>               m_pKeyBox;
    VclPtr<Edit>                        m_pSearchEdit;
    VclPtr<PushButton>                  m_pLoadButton;
    VclPtr<PushButton>                  m_pSaveButton;
    VclPtr<PushButton>                  m_pResetButton;
    OUString                            aLoadAccelConfigStr;
    OUString                            aSaveAccelConfigStr;
    OUString                            aFilterAllStr;
@@ -130,22 +118,40 @@ private:
    OUString m_sModuleUIName;

    // For search
    Timer m_aUpdateDataTimer;
    i18nutil::SearchOptions2 m_options;

    DECL_LINK(ChangeHdl,            Button *,       void);
    DECL_LINK(RemoveHdl,            Button *,       void);
    DECL_LINK(SelectHdl,            SvTreeListBox*, void);
    DECL_LINK(SearchUpdateHdl,      Edit&,          void);
    DECL_LINK(Save,                 Button *,       void);
    DECL_LINK(Load,                 Button *,       void);
    DECL_LINK(Default,              Button *,       void);
    DECL_LINK(RadioHdl,             Button *,       void);
    Idle m_aFillGroupIdle;

    std::unique_ptr<weld::TreeView>     m_xEntriesBox;
    std::unique_ptr<weld::RadioButton>  m_xOfficeButton;
    std::unique_ptr<weld::RadioButton>  m_xModuleButton;
    std::unique_ptr<weld::Button>       m_xChangeButton;
    std::unique_ptr<weld::Button>       m_xRemoveButton;
    std::unique_ptr<CuiConfigGroupListBox> m_xGroupLBox;
    std::unique_ptr<CuiConfigFunctionListBox> m_xFunctionBox;
    std::unique_ptr<weld::TreeView>     m_xKeyBox;
    std::unique_ptr<weld::Entry>        m_xSearchEdit;
    std::unique_ptr<weld::Button>       m_xLoadButton;
    std::unique_ptr<weld::Button>       m_xSaveButton;
    std::unique_ptr<weld::Button>       m_xResetButton;

    DECL_LINK(ChangeHdl,           weld::Button&,   void);
    DECL_LINK(RemoveHdl,           weld::Button&,   void);
    DECL_LINK(SelectHdl,           weld::TreeView&, void);
    DECL_LINK(SearchUpdateHdl,     weld::Entry&,    void);
    DECL_LINK(Save,                weld::Button&,   void);
    DECL_LINK(Load,                weld::Button&,   void);
    DECL_LINK(Default,             weld::Button&,   void);
    DECL_LINK(RadioHdl,            weld::Button&,   void);
    DECL_LINK(ImplUpdateDataHdl,   Timer*,          void);
    DECL_LINK(TimeOut_Impl,        Timer*,          void);

    DECL_LINK(LoadHdl, sfx2::FileDialogHelper *, void);
    DECL_LINK(SaveHdl, sfx2::FileDialogHelper *, void);

    OUString                    GetLabel4Command(const OUString& rCommand);
    SvTreeListEntry*            applySearchFilter(OUString const & rSearchTerm, SvTreeListBox* rListBox);
    int                         applySearchFilter(OUString const & rSearchTerm);
    void                        InitAccCfg();
    sal_Int32                   MapKeyCodeToPos(const vcl::KeyCode &rCode) const;
    void                        StartFileDialog( StartFileDialogType nType, const OUString& rTitle );
@@ -153,10 +159,8 @@ private:
    void                        Init(const css::uno::Reference< css::ui::XAcceleratorConfiguration >& pAccMgr);
    void                        ResetConfig();

    static void                 CreateCustomItems( SvTreeListEntry* pEntry, const OUString& aCol1, const OUString& aCol2 );

public:
                                SfxAcceleratorConfigPage( vcl::Window *pParent, const SfxItemSet& rItemSet );
                                SfxAcceleratorConfigPage(TabPageParent pParent, const SfxItemSet& rItemSet);
    virtual                     ~SfxAcceleratorConfigPage() override;
    virtual void                dispose() override;

diff --git a/cui/source/inc/cfgutil.hxx b/cui/source/inc/cfgutil.hxx
index ed1ccd1..423cb05 100644
--- a/cui/source/inc/cfgutil.hxx
+++ b/cui/source/inc/cfgutil.hxx
@@ -106,7 +106,6 @@ typedef std::vector<std::unique_ptr<SfxGroupInfo_Impl> > SfxGroupInfoArr_Impl;

class SfxConfigFunctionListBox : public SvTreeListBox
{
    friend class SfxConfigGroupListBox;
    SfxGroupInfoArr_Impl aArr;

    virtual void  MouseMove( const MouseEvent& rMEvt ) override;
@@ -142,79 +141,30 @@ public:
    {
        m_xTreeView->insert(nullptr, -1, &rStr, &rId, nullptr, nullptr, &rImage, false, nullptr);
    }
    void remove(int nPos) { m_xTreeView->remove(nPos); }
    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, depth first, then sibling
    bool iter_next(weld::TreeIter& rIter) const { return m_xTreeView->iter_next(rIter); }
    bool iter_next_sibling(weld::TreeIter& rIter) const { return m_xTreeView->iter_next_sibling(rIter); }
    OUString get_text(const weld::TreeIter& rIter) const { return m_xTreeView->get_text(rIter); }
    OUString get_text(int nPos) const { return m_xTreeView->get_text(nPos); }
    OUString get_id(const weld::TreeIter& rIter) const { return m_xTreeView->get_id(rIter); }
    bool get_selected(weld::TreeIter* pIter) const { return m_xTreeView->get_selected(pIter); }
    void scroll_to_row(const weld::TreeIter& rIter) { return m_xTreeView->scroll_to_row(rIter); }
    void scroll_to_row(int nRow) { return m_xTreeView->scroll_to_row(nRow); }
    void select(const weld::TreeIter& rIter) { m_xTreeView->select(rIter); }
    void select(int pos) { m_xTreeView->select(pos); }
    void set_size_request(int nWidth, int nHeight) { m_xTreeView->set_size_request(nWidth, nHeight); }
    weld::TreeView& get_widget() { return *m_xTreeView; }

    ~CuiConfigFunctionListBox();

    void          ClearAll();
    OUString      GetSelectedScriptURI();
    OUString      GetHelpText( bool bConsiderParent = true );
};

struct SvxConfigGroupBoxResource_Impl;
class SfxConfigGroupListBox : public SvTreeListBox
{
    std::unique_ptr<SvxConfigGroupBoxResource_Impl> xImp;
    VclPtr<SfxConfigFunctionListBox>  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;

    Image 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,
                         SvTreeListEntry* pParentEntry, bool bCheapChildrenOnDemand);
    void FillFunctionsList(const css::uno::Sequence< css::frame::DispatchInformation >& xCommands);
    OUString MapCommand2UIName(const OUString& sCommand);

    SfxStylesInfo_Impl* pStylesInfo;

protected:
    virtual void        RequestingChildren( SvTreeListEntry *pEntry) override;
    virtual bool        Expand( SvTreeListEntry* pParent ) override;

public:
    SfxConfigGroupListBox(vcl::Window* pParent, WinBits nStyle);
    virtual ~SfxConfigGroupListBox() override;
    virtual void        dispose() override;
    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( SfxConfigFunctionListBox *pBox )
                        { pFunctionListBox = pBox; }
    void                GroupSelected();
    void                SelectMacro( const SfxMacroInfoItem* );
    void                SelectMacro( const OUString&, const OUString& );
    void                SetStylesInfo(SfxStylesInfo_Impl* pStyles);
    OUString      GetCurCommand();
    OUString      GetCurLabel();
};

struct CuiConfigGroupBoxResource_Impl;
@@ -254,7 +204,8 @@ 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); }
    const weld::TreeView& get_widget() const { return *m_xTreeView; }
    void set_size_request(int nWidth, int nHeight) { m_xTreeView->set_size_request(nWidth, nHeight); }
    weld::TreeView& get_widget() { return *m_xTreeView; }
    ~CuiConfigGroupListBox();
    void                ClearAll();

@@ -265,6 +216,8 @@ public:
    void                SetFunctionListBox( CuiConfigFunctionListBox *pBox )
                        { m_pFunctionListBox = pBox; }
    void                GroupSelected();
    void                SelectMacro(const SfxMacroInfoItem*);
    void                SelectMacro(const OUString&, const OUString&);
    void                SetStylesInfo(SfxStylesInfo_Impl* pStyles);
};

diff --git a/cui/uiconfig/ui/accelconfigpage.ui b/cui/uiconfig/ui/accelconfigpage.ui
index 17827e0..d651300 100644
--- a/cui/uiconfig/ui/accelconfigpage.ui
+++ b/cui/uiconfig/ui/accelconfigpage.ui
@@ -1,8 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- 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 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"/>
      <!-- column-name sensitive -->
      <column type="gboolean"/>
    </columns>
  </object>
  <object class="GtkTreeStore" id="liststore4">
    <columns>
      <!-- column-name text -->
      <column type="gchararray"/>
      <!-- column-name id -->
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkGrid" id="AccelConfigPage">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
@@ -35,13 +70,51 @@
                <property name="yalign">0</property>
                <property name="top_padding">6</property>
                <child>
                  <object class="cuilo-SfxAccCfgTabListBox" id="shortcuts:border">
                  <object class="GtkScrolledWindow">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="hexpand">True</property>
                    <property name="vexpand">True</property>
                    <child internal-child="selection">
                      <object class="GtkTreeSelection" id="AccCfgTabListBox-selection"/>
                    <property name="shadow_type">in</property>
                    <child>
                      <object class="GtkTreeView" id="shortcuts">
                        <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">liststore3</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="Macro Library List-selection2"/>
                        </child>
                        <child>
                          <object class="GtkTreeViewColumn" id="treeviewcolumn3">
                            <property name="resizable">True</property>
                            <property name="spacing">6</property>
                            <child>
                              <object class="GtkCellRendererText" id="cellrenderer1"/>
                              <attributes>
                                <attribute name="text">0</attribute>
                              </attributes>
                            </child>
                          </object>
                        </child>
                        <child>
                          <object class="GtkTreeViewColumn" id="treeviewcolumn4">
                            <property name="resizable">True</property>
                            <property name="spacing">6</property>
                            <child>
                              <object class="GtkCellRendererText" id="cellrenderer2"/>
                              <attributes>
                                <attribute name="text">1</attribute>
                              </attributes>
                            </child>
                          </object>
                        </child>
                      </object>
                    </child>
                  </object>
                </child>
@@ -53,7 +126,7 @@
                <property name="can_focus">False</property>
                <property name="label" translatable="yes" context="accelconfigpage|label21">Shortcu_t Keys</property>
                <property name="use_underline">True</property>
                <property name="mnemonic_widget">shortcuts:border</property>
                <property name="mnemonic_widget">shortcuts</property>
              </object>
            </child>
          </object>
@@ -83,8 +156,8 @@
                    <property name="receives_default">False</property>
                    <property name="use_underline">True</property>
                    <property name="xalign">0</property>
                    <property name="active">True</property>
                    <property name="draw_indicator">True</property>
                    <property name="group">module</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -266,7 +339,7 @@
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes" context="accelconfigpage|label23">_Category</property>
                        <property name="use_underline">True</property>
                        <property name="mnemonic_widget">category:border</property>
                        <property name="mnemonic_widget">category</property>
                        <property name="xalign">0</property>
                      </object>
                      <packing>
@@ -280,7 +353,7 @@
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes" context="accelconfigpage|label24">_Function</property>
                        <property name="use_underline">True</property>
                        <property name="mnemonic_widget">function:border</property>
                        <property name="mnemonic_widget">function</property>
                        <property name="xalign">0</property>
                      </object>
                      <packing>
@@ -294,7 +367,7 @@
                        <property name="can_focus">False</property>
                        <property name="label" translatable="yes" context="accelconfigpage|label25">_Keys</property>
                        <property name="use_underline">True</property>
                        <property name="mnemonic_widget">keys:border</property>
                        <property name="mnemonic_widget">keys</property>
                        <property name="xalign">0</property>
                      </object>
                      <packing>
@@ -303,13 +376,39 @@
                      </packing>
                    </child>
                    <child>
                      <object class="cuilo-SfxConfigGroupListBox" id="category:border">
                      <object class="GtkScrolledWindow">
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="hexpand">True</property>
                        <property name="vexpand">True</property>
                        <child internal-child="selection">
                          <object class="GtkTreeSelection" id="ConfigGroup ListBox-selection"/>
                        <property name="shadow_type">in</property>
                        <child>
                          <object class="GtkTreeView" id="category">
                            <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" id="Macro Library List-selection1"/>
                            </child>
                            <child>
                              <object class="GtkTreeViewColumn" id="treeviewcolumn1">
                                <property name="resizable">True</property>
                                <property name="spacing">6</property>
                                <child>
                                  <object class="GtkCellRendererText" id="cellrenderer4"/>
                                  <attributes>
                                    <attribute name="text">0</attribute>
                                  </attributes>
                                </child>
                              </object>
                            </child>
                          </object>
                        </child>
                      </object>
                      <packing>
@@ -318,13 +417,39 @@
                      </packing>
                    </child>
                    <child>
                      <object class="cuilo-SfxConfigFunctionListBox" id="function:border">
                      <object class="GtkScrolledWindow">
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="hexpand">True</property>
                        <property name="vexpand">True</property>
                        <child internal-child="selection">
                          <object class="GtkTreeSelection" id="ConfigGroupFunction ListBox-selection"/>
                        <property name="shadow_type">in</property>
                        <child>
                          <object class="GtkTreeView" id="function">
                            <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="Macro Library List-selection3"/>
                            </child>
                            <child>
                              <object class="GtkTreeViewColumn" id="treeviewcolumn5">
                                <property name="resizable">True</property>
                                <property name="spacing">6</property>
                                <child>
                                  <object class="GtkCellRendererText" id="cellrenderer5"/>
                                  <attributes>
                                    <attribute name="text">0</attribute>
                                  </attributes>
                                </child>
                              </object>
                            </child>
                          </object>
                        </child>
                      </object>
                      <packing>
@@ -333,13 +458,39 @@
                      </packing>
                    </child>
                    <child>
                      <object class="vcllo-SvTreeListBox" id="keys:border">
                      <object class="GtkScrolledWindow">
                        <property name="visible">True</property>
                        <property name="can_focus">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="keys">
                            <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">liststore4</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="Macro Library List-selection4"/>
                            </child>
                            <child>
                              <object class="GtkTreeViewColumn" id="treeviewcolumn6">
                                <property name="resizable">True</property>
                                <property name="spacing">6</property>
                                <child>
                                  <object class="GtkCellRendererText" id="cellrenderer7"/>
                                  <attributes>
                                    <attribute name="text">0</attribute>
                                  </attributes>
                                </child>
                              </object>
                            </child>
                          </object>
                        </child>
                      </object>
                      <packing>
diff --git a/extras/source/glade/libreoffice-catalog.xml.in b/extras/source/glade/libreoffice-catalog.xml.in
index ac23c4e..967ee3c 100644
--- a/extras/source/glade/libreoffice-catalog.xml.in
+++ b/extras/source/glade/libreoffice-catalog.xml.in
@@ -186,12 +186,6 @@
    <glade-widget-class title="SwDBTreeList" name="swlo-SwDBTreeList"
                        generic-name="SwDBTreeList" parent="GtkTreeView"
                        icon-name="widget-gtk-treeview"/>
    <glade-widget-class title="ConfigGroup ListBox" name="cuilo-SfxConfigGroupListBox"
                        generic-name="ConfigGroup ListBox" parent="GtkTreeView"
                        icon-name="widget-gtk-treeview"/>
    <glade-widget-class title="SfxAccCfgTabListBox" name="cuilo-SfxAccCfgTabListBox"
                        generic-name="AccCfgTabListBox" parent="GtkTreeView"
                        icon-name="widget-gtk-treeview"/>
    <glade-widget-class title="ConfigGroupFunction ListBox" name="cuilo-SfxConfigFunctionListBox"
                        generic-name="ConfigGroupFunction ListBox" parent="GtkTreeView"
                        icon-name="widget-gtk-treeview"/>
diff --git a/include/vcl/treelistbox.hxx b/include/vcl/treelistbox.hxx
index adf35cb..c03f300 100644
--- a/include/vcl/treelistbox.hxx
+++ b/include/vcl/treelistbox.hxx
@@ -133,12 +133,16 @@ public:

class VCL_DLLPUBLIC SvLBoxItem
{
protected:
    bool mbDisabled;

public:
                        SvLBoxItem();
    virtual             ~SvLBoxItem();
    virtual SvLBoxItemType GetType() const = 0;
    const Size&         GetSize(const SvTreeListBox* pView, const SvTreeListEntry* pEntry) const;
    static const Size&  GetSize(const SvViewDataEntry* pData, sal_uInt16 nItemPos);
    void Enable(bool bEnabled) { mbDisabled = !bEnabled; }

    virtual void Paint(const Point& rPos, SvTreeListBox& rOutDev, vcl::RenderContext& rRenderContext, const SvViewDataEntry* pView, const SvTreeListEntry& rEntry) = 0;

diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 5511879..e25911f 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -576,6 +576,7 @@ public:
    virtual void remove(int pos) = 0;
    virtual OUString get_text(int row, int col = -1) const = 0;
    virtual void set_text(int row, const OUString& rText, int col = -1) = 0;
    virtual void set_sensitive(int row, bool bSensitive, int col = -1) = 0;
    virtual void set_id(int row, const OUString& rId) = 0;
    virtual void set_toggle(int row, bool bOn, int col) = 0;
    virtual bool get_toggle(int row, int col) const = 0;
@@ -692,6 +693,8 @@ public:
    virtual int count_selected_rows() const = 0;

    void set_toggle_columns_as_radio(const std::vector<int>& rCols) { m_aRadioIndexes = rCols; }

    using Widget::set_sensitive;
};

class VCL_DLLPUBLIC Button : virtual public Container
diff --git a/solenv/bin/native-code.py b/solenv/bin/native-code.py
index 6f3094a..4e9b590 100755
--- a/solenv/bin/native-code.py
+++ b/solenv/bin/native-code.py
@@ -487,9 +487,7 @@ custom_widgets = [
    'SearchResultsBox',
    'SelectionListBox',
    'SentenceEditWindow',
    'SfxAccCfgTabListBox',
    'SfxConfigFunctionListBox',
    'SfxConfigGroupListBox',
    'ShowNupOrderWindow',
    'ShowNupOrderWindow',
    'SidebarDialControl',
diff --git a/solenv/sanitizers/ui/cui.suppr b/solenv/sanitizers/ui/cui.suppr
index 8ea1c0e..cea9c99 100644
--- a/solenv/sanitizers/ui/cui.suppr
+++ b/solenv/sanitizers/ui/cui.suppr
@@ -263,7 +263,6 @@ cui/uiconfig/ui/linestyletabpage.ui://GtkSpinButton[@id='NUM_FLD_2'] no-labelled
cui/uiconfig/ui/linestyletabpage.ui://GtkSpinButton[@id='MTR_FLD_LENGTH_2'] no-labelled-by
cui/uiconfig/ui/macroselectordialog.ui://GtkLabel[@id='helpmacro'] orphan-label
cui/uiconfig/ui/macroselectordialog.ui://GtkLabel[@id='helptoolbar'] orphan-label
cui/uiconfig/ui/macroselectordialog.ui://cuilo-SfxConfigGroupListBox[@id='categories:border'] no-labelled-by
cui/uiconfig/ui/macroselectordialog.ui://GtkLabel[@id='libraryft'] orphan-label
cui/uiconfig/ui/macroselectordialog.ui://GtkLabel[@id='categoryft'] orphan-label
cui/uiconfig/ui/macroselectordialog.ui://cuilo-SfxConfigFunctionListBox[@id='commands:border'] no-labelled-by
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index f0efbf9..35bf1e6 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -2344,8 +2344,10 @@ public:

    virtual void remove(int pos) override
    {
        disable_notify_events();
        SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
        m_xTreeView->RemoveEntry(pEntry);
        enable_notify_events();
    }

    virtual int find_text(const OUString& rText) const override
@@ -2502,6 +2504,41 @@ public:
        set_text(pEntry, rText, col);
    }

    void set_sensitive(SvTreeListEntry* pEntry, bool bSensitive, int col)
    {
        if (col == -1)
        {
            const sal_uInt16 nCount = pEntry->ItemCount();
            for (sal_uInt16 nCur = 0; nCur < nCount; ++nCur)
            {
                SvLBoxItem& rItem = pEntry->GetItem(nCur);
                if (rItem.GetType() == SvLBoxItemType::String)
                {
                    rItem.Enable(bSensitive);
                    m_xTreeView->ModelHasEntryInvalidated(pEntry);
                    break;
                }
            }
            return;
        }

        ++col; //skip dummy/expander column

        assert(col >= 0 && static_cast<size_t>(col) < pEntry->ItemCount());
        SvLBoxItem& rItem = pEntry->GetItem(col);
        rItem.Enable(bSensitive);

        m_xTreeView->ModelHasEntryInvalidated(pEntry);
    }

    using SalInstanceWidget::set_sensitive;

    virtual void set_sensitive(int pos, bool bSensitive, int col) override
    {
        SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
        set_sensitive(pEntry, bSensitive, col);
    }

    virtual bool get_toggle(int pos, int col) const override
    {
        SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
@@ -2693,8 +2730,10 @@ public:

    virtual void remove(const weld::TreeIter& rIter) override
    {
        disable_notify_events();
        const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
        m_xTreeView->RemoveEntry(rVclIter.iter);
        enable_notify_events();
    }

    virtual void select(const weld::TreeIter& rIter) override
diff --git a/vcl/source/treelist/svlbitm.cxx b/vcl/source/treelist/svlbitm.cxx
index 7f45fdf..8edd585 100644
--- a/vcl/source/treelist/svlbitm.cxx
+++ b/vcl/source/treelist/svlbitm.cxx
@@ -173,11 +173,11 @@ bool SvLBoxButtonData::IsRadio() {


SvLBoxString::SvLBoxString(const OUString& rStr)
    : maText(rStr)
{
    SetText(rStr);
}

SvLBoxString::SvLBoxString() : SvLBoxItem()
SvLBoxString::SvLBoxString()
{
}

@@ -195,7 +195,7 @@ void SvLBoxString::Paint(
    const SvViewDataEntry* /*pView*/, const SvTreeListEntry& rEntry)
{
    Size aSize = GetSize(&rDev, &rEntry);
    DrawTextFlags nStyle = rDev.IsEnabled() ? DrawTextFlags::NONE : DrawTextFlags::Disable;
    DrawTextFlags nStyle = (rDev.IsEnabled() && !mbDisabled) ? DrawTextFlags::NONE : DrawTextFlags::Disable;
    if (rDev.IsEntryMnemonicsEnabled())
        nStyle |= DrawTextFlags::Mnemonic;
    if (rDev.TextCenterAndClipEnabled())
diff --git a/vcl/source/treelist/treelistbox.cxx b/vcl/source/treelist/treelistbox.cxx
index cfaccea..7355f06 100644
--- a/vcl/source/treelist/treelistbox.cxx
+++ b/vcl/source/treelist/treelistbox.cxx
@@ -295,6 +295,7 @@ long SvLBoxTab::CalcOffset( long nItemWidth, long nTabWidth )


SvLBoxItem::SvLBoxItem()
    : mbDisabled(false)
{
}

diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 222bd91..a11c943 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -6000,7 +6000,7 @@ public:
            col = m_nTextCol;
        else
            col = get_model_col(col);
        return set(pos, col, rText);
        set(pos, col, rText);
    }

    virtual bool get_toggle(int pos, int col) const override
@@ -6013,7 +6013,17 @@ public:
        col = get_model_col(col);
        // checkbuttons are invisible until toggled on or off
        set(pos, m_aToggleVisMap[col], true);
        return set(pos, col, bOn);
        set(pos, col, bOn);
    }

    using GtkInstanceWidget::set_sensitive;

    virtual void set_sensitive(int pos, bool bSensitive, int col) override
    {
        col = get_model_col(col);
        ++col; // skip over id column
        col += m_aToggleVisMap.size(); // skip over toggle columns
        set(pos, col, bSensitive);
    }

    virtual void set_image(int pos, const OUString& rImage, int col) override