weld DBTreeListBox

Change-Id: I4b7369a496339b9bbab0c885c7360a5d7818a62e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100329
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/dbaccess/UIConfig_dbaccess.mk b/dbaccess/UIConfig_dbaccess.mk
index feaa35c..8a4229e 100644
--- a/dbaccess/UIConfig_dbaccess.mk
+++ b/dbaccess/UIConfig_dbaccess.mk
@@ -23,6 +23,7 @@ $(eval $(call gb_UIConfig_add_uifiles,dbaccess, \
    dbaccess/uiconfig/ui/copytablepage \
    dbaccess/uiconfig/ui/dbaseindexdialog \
    dbaccess/uiconfig/ui/dbasepage \
    dbaccess/uiconfig/ui/dbtreelist \
    dbaccess/uiconfig/ui/dbwizconnectionpage \
    dbaccess/uiconfig/ui/dbwizmysqlintropage \
    dbaccess/uiconfig/ui/dbwizmysqlnativepage \
diff --git a/dbaccess/source/ui/app/AppController.cxx b/dbaccess/source/ui/app/AppController.cxx
index 958d5d9c..67bd857 100644
--- a/dbaccess/source/ui/app/AppController.cxx
+++ b/dbaccess/source/ui/app/AppController.cxx
@@ -97,6 +97,7 @@
#include <strings.hrc>
#include <defaultobjectnamecheck.hxx>
#include <databaseobjectview.hxx>
#include <dbtreelistbox.hxx>
#include "AppDetailView.hxx"
#include <linkeddocuments.hxx>
#include <UITools.hxx>
@@ -1683,15 +1684,23 @@ bool OApplicationController::onContainerSelect(ElementType _eType)
    return true;
}

bool OApplicationController::onEntryDoubleClick( SvTreeListBox const & _rTree )
bool OApplicationController::onEntryDoubleClick(const weld::TreeView& rTreeView)
{
    if ( getContainer() && getContainer()->isLeaf( _rTree.GetHdlEntry() ) )
    OApplicationView* pContainer = getContainer();
    if (!pContainer)
        return false;   // not handled

    std::unique_ptr<weld::TreeIter> xHdlEntry = rTreeView.make_iterator();
    if (!rTreeView.get_cursor(xHdlEntry.get()))
        return false;

    if (pContainer->isLeaf(rTreeView, *xHdlEntry))
    {
        try
        {
            // opens a new frame with either the table or the query or report or form or view
            openElementWithArguments(
                getContainer()->getQualifiedName( _rTree.GetHdlEntry() ),
                getContainer()->getQualifiedName(xHdlEntry.get()),
                getContainer()->getElementType(),
                E_OPEN_NORMAL,
                0,
@@ -1703,6 +1712,7 @@ bool OApplicationController::onEntryDoubleClick( SvTreeListBox const & _rTree )
            DBG_UNHANDLED_EXCEPTION("dbaccess");
        }
    }

    return false;   // not handled
}

@@ -2237,7 +2247,7 @@ void OApplicationController::onDeleteEntry()
    executeChecked(nId,Sequence<PropertyValue>());
}

OUString OApplicationController::getContextMenuResourceName( Control& /*_rControl*/ ) const
OUString OApplicationController::getContextMenuResourceName() const
{
    return "edit";
}
@@ -2264,6 +2274,11 @@ bool OApplicationController::requestQuickHelp( const SvTreeListEntry* /*_pEntry*
    return false;
}

bool OApplicationController::requestQuickHelp(const void* /*pUserData*/, OUString& /*rText*/) const
{
    return false;
}

bool OApplicationController::requestDrag(  const Point& /*_rPosPixel*/ )
{
    rtl::Reference<TransferableHelper> pTransfer;
@@ -2288,6 +2303,32 @@ bool OApplicationController::requestDrag(  const Point& /*_rPosPixel*/ )
    return pTransfer.is();
}

bool OApplicationController::requestDrag(const weld::TreeIter& /*rEntry*/)
{
    rtl::Reference<TransferableHelper> pTransfer;

    OApplicationView* pContainer = getContainer();
    if (pContainer && pContainer->getSelectionCount())
    {
        try
        {
            pTransfer = copyObject( );

            if ( pTransfer && getContainer()->getDetailView() )
            {
                ElementType eType = getContainer()->getElementType();
                pTransfer->StartDrag( getContainer()->getDetailView()->getTreeWindow(), ((eType == E_FORM || eType == E_REPORT) ? DND_ACTION_COPYMOVE : DND_ACTION_COPY) );
            }
        }
        catch(const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION("dbaccess");
        }
    }

    return pTransfer.is();
}

sal_Int8 OApplicationController::queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors )
{
    sal_Int8 nActionAskedFor = _rEvt.mnAction;
@@ -2306,11 +2347,11 @@ sal_Int8 OApplicationController::queryDrop( const AcceptDropEvent& _rEvt, const 
                sal_Int8 nAction = OComponentTransferable::canExtractComponentDescriptor(_rFlavors,eType == E_FORM) ? DND_ACTION_COPY : DND_ACTION_NONE;
                if ( nAction != DND_ACTION_NONE )
                {
                    SvTreeListEntry* pHitEntry = pView->getEntry(_rEvt.maPosPixel);
                    auto xHitEntry = pView->getEntry(_rEvt.maPosPixel);
                    OUString sName;
                    if ( pHitEntry )
                    if (xHitEntry)
                    {
                        sName = pView->getQualifiedName( pHitEntry );
                        sName = pView->getQualifiedName(xHitEntry.get());
                        if ( !sName.isEmpty() )
                        {
                            Reference< XHierarchicalNameAccess > xContainer(getElements(pView->getElementType()),UNO_QUERY);
@@ -2371,9 +2412,9 @@ sal_Int8 OApplicationController::executeDrop( const ExecuteDropEvent& _rEvt )
    else if ( OComponentTransferable::canExtractComponentDescriptor(aDroppedData.GetDataFlavorExVector(),m_aAsyncDrop.nType == E_FORM) )
    {
        m_aAsyncDrop.aDroppedData = OComponentTransferable::extractComponentDescriptor(aDroppedData);
        SvTreeListEntry* pHitEntry = pView->getEntry(_rEvt.maPosPixel);
        if ( pHitEntry )
            m_aAsyncDrop.aUrl = pView->getQualifiedName( pHitEntry );
        auto xHitEntry = pView->getEntry(_rEvt.maPosPixel);
        if ( xHitEntry )
            m_aAsyncDrop.aUrl = pView->getQualifiedName(xHitEntry.get());

        sal_Int8 nAction = _rEvt.mnAction;
        Reference<XContent> xContent;
diff --git a/dbaccess/source/ui/app/AppController.hxx b/dbaccess/source/ui/app/AppController.hxx
index 6f7c1f6..1abf501 100644
--- a/dbaccess/source/ui/app/AppController.hxx
+++ b/dbaccess/source/ui/app/AppController.hxx
@@ -57,8 +57,14 @@ namespace com::sun::star {
    }
}

namespace weld
{
    class TreeView;
}

namespace dbaui
{
    class TreeListBox;
    class SubComponentManager;
    class OApplicationController;
    class OApplicationView;
@@ -442,7 +448,8 @@ namespace dbaui
                <TRUE/> if the double click event has been handled by the called, and should not
                be processed further.
        */
        bool onEntryDoubleClick(SvTreeListBox const & _rTree);
        bool onEntryDoubleClick(const weld::TreeView& rTree);

        /** called when a container (category) in the application view has been selected
            @param  _pTree
                The tree list box.
@@ -450,22 +457,28 @@ namespace dbaui
                <TRUE/> if the container could be changed otherwise <FALSE/>
        */
        bool onContainerSelect(ElementType _eType);

        /** called when an entry in a tree view has been selected
            @param  _pEntry
                the selected entry
        */
        void onSelectionChanged();

        /** called when a "Copy" command is executed in a tree view
        */
        void onCopyEntry();

        /** called when a "Paste" command is executed in a tree view
        */
        void onPasteEntry();

        /** called when a "Delete" command is executed in a tree view
        */
        void onDeleteEntry();

        /// called when the preview mode was changed
        void previewChanged( sal_Int32 _nMode);

        /// called when an object container of any kind was found during enumerating tree view elements
        void containerFound( const css::uno::Reference< css::container::XContainer >& _xContainer);

@@ -474,12 +487,14 @@ namespace dbaui

        // IControlActionListener overridables
        virtual bool        requestQuickHelp( const SvTreeListEntry* _pEntry, OUString& _rText ) const override;
        virtual bool        requestQuickHelp(const void* pUserData, OUString& rText) const override;
        virtual bool        requestDrag( const Point& _rPosPixel ) override;
        virtual bool        requestDrag(const weld::TreeIter& rEntry) override;
        virtual sal_Int8    queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors ) override;
        virtual sal_Int8    executeDrop( const ExecuteDropEvent& _rEvt ) override;

        // IContextMenuProvider
        virtual OUString          getContextMenuResourceName( Control& _rControl ) const override;
        virtual OUString          getContextMenuResourceName() const override;
        virtual IController&      getCommandController() override;
        virtual ::comphelper::OInterfaceContainerHelper2*
                                getContextMenuInterceptors() override;
diff --git a/dbaccess/source/ui/app/AppDetailPageHelper.cxx b/dbaccess/source/ui/app/AppDetailPageHelper.cxx
index 502ad24..27a4ed7 100644
--- a/dbaccess/source/ui/app/AppDetailPageHelper.cxx
+++ b/dbaccess/source/ui/app/AppDetailPageHelper.cxx
@@ -54,7 +54,6 @@
#include <toolkit/awt/vclxmenu.hxx>
#include <tools/stream.hxx>
#include <rtl/ustrbuf.hxx>
#include <vcl/treelistentry.hxx>
#include "AppController.hxx"

#include <com/sun/star/document/XDocumentProperties.hpp>
@@ -82,39 +81,44 @@ namespace dbaui

namespace
{
    SvTreeListEntry* lcl_findEntry_impl(DBTreeListBox const & rTree, const OUString& _rName, SvTreeListEntry* _pFirst)
    bool lcl_findEntry_impl(const TreeListBox& rTree, const OUString& rName, weld::TreeIter& rIter)
    {
        SvTreeListEntry* pReturn = nullptr;
        bool bReturn = false;
        sal_Int32 nIndex = 0;
        OUString sName( _rName.getToken(0,'/',nIndex) );
        OUString sName( rName.getToken(0,'/',nIndex) );

        SvTreeListEntry* pEntry = _pFirst;
        while( pEntry )
        const weld::TreeView& rTreeView = rTree.GetWidget();
        bool bEntry = true;
        do
        {
            if ( rTree.GetEntryText(pEntry) == sName )
            if (rTreeView.get_text(rIter) == sName)
            {
                if ( nIndex != -1 )
                {
                    sName = _rName.getToken(0,'/',nIndex);
                    pEntry = rTree.FirstChild(pEntry);
                    sName = rName.getToken(0,'/',nIndex);
                    bEntry = rTreeView.iter_children(rIter);
                }
                else
                {
                    pReturn = pEntry;
                    bReturn = true;
                    break;
                }
            }
            else
                pEntry = pEntry->NextSibling();
                bEntry = rTreeView.iter_next_sibling(rIter);
        }
        return pReturn;
        while (bEntry);

        return bReturn;
    }
    SvTreeListEntry* lcl_findEntry(DBTreeListBox const & rTree, const OUString& _rName,SvTreeListEntry* _pFirst)

    bool lcl_findEntry(const TreeListBox& rTree, const OUString& rName, weld::TreeIter& rIter)
    {
        sal_Int32 nIndex = 0;
        OUString sErase = _rName.getToken(0,'/',nIndex); // we don't want to have the "private:forms" part
        return (nIndex != -1 ? lcl_findEntry_impl(rTree,_rName.copy(sErase.getLength() + 1),_pFirst) : nullptr);
        OUString sErase = rName.getToken(0,'/',nIndex); // we don't want to have the "private:forms" part
        return nIndex != -1 && lcl_findEntry_impl(rTree, rName.copy(sErase.getLength() + 1), rIter);
    }

    class OTablePreviewWindow : public vcl::Window
    {
        DECL_LINK(OnDisableInput, void*, void);
@@ -197,7 +201,7 @@ OAppDetailPageHelper::OAppDetailPageHelper(vcl::Window* _pParent,OAppBorderWindo

    m_xWindow = VCLUnoHelper::GetInterface( m_pTablePreview );

    for (VclPtr<DBTreeListBox> & rpBox : m_pLists)
    for (VclPtr<InterimDBTreeListBox> & rpBox : m_pLists)
        rpBox = nullptr;
    ImplInitSettings();
}
@@ -221,13 +225,11 @@ void OAppDetailPageHelper::dispose()
        OSL_FAIL("Exception thrown while disposing preview frame!");
    }

    for (VclPtr<DBTreeListBox> & rpBox : m_pLists)
    for (VclPtr<InterimDBTreeListBox> & rpBox : m_pLists)
    {
        if ( rpBox )
        {
            rpBox->clearCurrentSelection();
            rpBox->Hide();
            rpBox->clearCurrentSelection();   // why a second time?
            rpBox.disposeAndClear();
        }
    }
@@ -257,77 +259,74 @@ void OAppDetailPageHelper::selectAll()
    int nPos = getVisibleControlIndex();
    if ( nPos < E_ELEMENT_TYPE_COUNT )
    {
        m_pLists[nPos]->SelectAll(true);
        m_pLists[nPos]->GetWidget().select_all();
    }
}

void OAppDetailPageHelper::sort(int _nPos,SvSortMode _eSortMode )
void OAppDetailPageHelper::sort(int nPos, bool bAscending)
{
    OSL_ENSURE(m_pLists[_nPos],"List can not be NULL! ->GPF");
    SvTreeList* pModel = m_pLists[_nPos]->GetModel();
    SvSortMode eOldSortMode = pModel->GetSortMode();
    pModel->SetSortMode(_eSortMode);
    if ( eOldSortMode != _eSortMode )
        pModel->Resort();
    assert(m_pLists[nPos] && "List can not be NULL! ->GPF");
    m_pLists[nPos]->GetWidget().set_sort_order(bAscending);
}

bool OAppDetailPageHelper::isSortUp() const
{
    SvSortMode eSortMode = SortNone;
    bool bAscending = false;

    int nPos = getVisibleControlIndex();
    if ( nPos < E_ELEMENT_TYPE_COUNT )
    {
        SvTreeList* pModel = m_pLists[nPos]->GetModel();
        eSortMode = pModel->GetSortMode();
    }
    return eSortMode == SortAscending;
    if (nPos < E_ELEMENT_TYPE_COUNT)
        bAscending = m_pLists[nPos]->GetWidget().get_sort_order();

    return bAscending;
}

void OAppDetailPageHelper::sortDown()
{
    int nPos = getVisibleControlIndex();
    if ( nPos < E_ELEMENT_TYPE_COUNT )
        sort(nPos,SortDescending);
        sort(nPos, false);
}

void OAppDetailPageHelper::sortUp()
{
    int nPos = getVisibleControlIndex();
    if ( nPos < E_ELEMENT_TYPE_COUNT )
        sort(nPos,SortAscending);
        sort(nPos, true);
}

void OAppDetailPageHelper::getSelectionElementNames( std::vector< OUString>& _rNames ) const
void OAppDetailPageHelper::getSelectionElementNames(std::vector<OUString>& rNames) const
{
    int nPos = getVisibleControlIndex();
    if ( nPos >= E_ELEMENT_TYPE_COUNT )
        return;

    DBTreeListBox& rTree = *m_pLists[nPos];
    sal_Int32 nCount = rTree.GetEntryCount();
    _rNames.reserve(nCount);
    SvTreeListEntry* pEntry = rTree.FirstSelected();
    InterimDBTreeListBox& rTree = *m_pLists[nPos];
    weld::TreeView& rTreeView = rTree.GetWidget();
    sal_Int32 nCount = rTreeView.n_children();
    rNames.reserve(nCount);
    ElementType eType = getElementType();
    while( pEntry )
    {

    rTreeView.selected_foreach([this, eType, &rTreeView, &rNames](weld::TreeIter& rEntry){
        if ( eType == E_TABLE )
        {
            if( rTree.GetChildCount(pEntry) == 0 )
                _rNames.push_back( getQualifiedName( pEntry ) );
            if (!rTreeView.iter_has_child(rEntry))
                rNames.push_back(getQualifiedName(&rEntry));
        }
        else
        {
            OUString sName = rTree.GetEntryText(pEntry);
            SvTreeListEntry* pParent = rTree.GetParent(pEntry);
            while(pParent)
            OUString sName = rTreeView.get_text(rEntry);
            std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator(&rEntry));
            bool bParent = rTreeView.iter_parent(*xParent);
            while (bParent)
            {
                sName = rTree.GetEntryText(pParent) + "/" + sName;
                pParent = rTree.GetParent(pParent);
                sName = rTreeView.get_text(*xParent) + "/" + sName;
                bParent = rTreeView.iter_parent(*xParent);
            }
            _rNames.push_back(sName);
            rNames.push_back(sName);
        }
        pEntry = rTree.NextSelected(pEntry);
    }

        return false;
    });
}

void OAppDetailPageHelper::describeCurrentSelectionForControl( const Control& _rControl, Sequence< NamedDatabaseObject >& _out_rSelectedObjects )
@@ -343,10 +342,10 @@ void OAppDetailPageHelper::describeCurrentSelectionForControl( const Control& _r
    OSL_FAIL( "OAppDetailPageHelper::describeCurrentSelectionForControl: invalid control!" );
}

void OAppDetailPageHelper::describeCurrentSelectionForType( const ElementType _eType, Sequence< NamedDatabaseObject >& _out_rSelectedObjects )
void OAppDetailPageHelper::describeCurrentSelectionForType(const ElementType eType, Sequence< NamedDatabaseObject >& _out_rSelectedObjects)
{
    OSL_ENSURE( _eType < E_ELEMENT_TYPE_COUNT, "OAppDetailPageHelper::describeCurrentSelectionForType: invalid type!" );
    DBTreeListBox* pList = ( _eType < E_ELEMENT_TYPE_COUNT ) ? m_pLists[ _eType ].get() : nullptr;
    OSL_ENSURE( eType < E_ELEMENT_TYPE_COUNT, "OAppDetailPageHelper::describeCurrentSelectionForType: invalid type!" );
    InterimDBTreeListBox* pList = ( eType < E_ELEMENT_TYPE_COUNT ) ? m_pLists[ eType ].get() : nullptr;
    OSL_ENSURE( pList, "OAppDetailPageHelper::describeCurrentSelectionForType: "
                       "You really should ensure this type has already been viewed before!" );
    if ( !pList )
@@ -354,60 +353,57 @@ void OAppDetailPageHelper::describeCurrentSelectionForType( const ElementType _e

    std::vector< NamedDatabaseObject > aSelected;

    SvTreeListEntry* pEntry = pList->FirstSelected();
    while( pEntry )
    {
    weld::TreeView& rTreeView = pList->GetWidget();
    rTreeView.selected_foreach([pList, eType, &rTreeView, &aSelected](weld::TreeIter& rEntry){
        NamedDatabaseObject aObject;
        switch ( _eType )
        switch (eType)
        {
        case E_TABLE:
        {
            OTableTreeListBox& rTableTree = dynamic_cast< OTableTreeListBox& >( *pList );
            aObject = rTableTree.describeObject( pEntry );
        }
        break;
        case E_QUERY:
            aObject.Type = DatabaseObject::QUERY;
            aObject.Name = pList->GetEntryText( pEntry );
            break;

        case E_FORM:
        case E_REPORT:
        {
            OUString sName = pList->GetEntryText(pEntry);
            SvTreeListEntry* pParent = pList->GetParent(pEntry);
            while ( pParent )
            case E_TABLE:
            {
                OUStringBuffer buffer;
                buffer.append( pList->GetEntryText( pParent ) );
                buffer.append( '/' );
                buffer.append( sName );
                sName = buffer.makeStringAndClear();

                pParent = pList->GetParent( pParent );
                OTableTreeListBox& rTableTree = dynamic_cast<OTableTreeListBox&>(*pList);
                aObject = rTableTree.describeObject(rEntry);
                break;
            }
            case E_QUERY:
                aObject.Type = DatabaseObject::QUERY;
                aObject.Name = rTreeView.get_text(rEntry);
                break;
            case E_FORM:
            case E_REPORT:
            {
                OUString sName = rTreeView.get_text(rEntry);
                std::unique_ptr<weld::TreeIter> xParent(rTreeView.make_iterator(&rEntry));
                bool bParent = rTreeView.iter_parent(*xParent);
                while (bParent)
                {
                    OUStringBuffer buffer;
                    buffer.append(rTreeView.get_text(*xParent));
                    buffer.append('/');
                    buffer.append(sName);
                    sName = buffer.makeStringAndClear();

            if ( isLeaf( pEntry ) )
                aObject.Type = ( _eType == E_FORM ) ? DatabaseObject::FORM : DatabaseObject::REPORT;
            else
                aObject.Type = ( _eType == E_FORM ) ? DatabaseObjectContainer::FORMS_FOLDER : DatabaseObjectContainer::REPORTS_FOLDER;
            aObject.Name = sName;
        }
        break;
        default:
            OSL_FAIL( "OAppDetailPageHelper::describeCurrentSelectionForType: unexpected type!" );
            break;
                    bParent = rTreeView.iter_parent(*xParent);
                }

                if (isLeaf(rTreeView, rEntry))
                    aObject.Type = (eType == E_FORM) ? DatabaseObject::FORM : DatabaseObject::REPORT;
                else
                    aObject.Type = (eType == E_FORM) ? DatabaseObjectContainer::FORMS_FOLDER : DatabaseObjectContainer::REPORTS_FOLDER;
                aObject.Name = sName;
                break;
            }
            default:
                OSL_FAIL( "OAppDetailPageHelper::describeCurrentSelectionForType: unexpected type!" );
                break;
        }

        if ( !aObject.Name.isEmpty() )
        {
            aSelected.push_back( aObject );
        }
        if (!aObject.Name.isEmpty())
            aSelected.push_back(aObject);

        pEntry = pList->NextSelected(pEntry);
    }
        return false;
    });

    _out_rSelectedObjects = comphelper::containerToSequence( aSelected );
    _out_rSelectedObjects = comphelper::containerToSequence(aSelected);
}

void OAppDetailPageHelper::selectElements(const Sequence< OUString>& _aNames)
@@ -416,19 +412,21 @@ void OAppDetailPageHelper::selectElements(const Sequence< OUString>& _aNames)
    if ( nPos >= E_ELEMENT_TYPE_COUNT )
        return;

    DBTreeListBox& rTree = *m_pLists[nPos];
    rTree.SelectAll(false);
    InterimDBTreeListBox& rTree = *m_pLists[nPos];
    weld::TreeView& rTreeView = rTree.GetWidget();
    rTreeView.unselect_all();
    const OUString* pIter = _aNames.getConstArray();
    const OUString* pEnd  = pIter + _aNames.getLength();
    for(;pIter != pEnd;++pIter)
    {
        SvTreeListEntry* pEntry = rTree.GetEntryPosByName(*pIter);
        if ( pEntry )
            rTree.Select(pEntry);
        auto xEntry = rTree.GetEntryPosByName(*pIter);
        if (!xEntry)
            continue;
        rTreeView.select(*xEntry);
    }
}

OUString OAppDetailPageHelper::getQualifiedName( SvTreeListEntry* _pEntry ) const
OUString OAppDetailPageHelper::getQualifiedName(weld::TreeIter* _pEntry) const
{
    int nPos = getVisibleControlIndex();
    OUString sComposedName;
@@ -437,28 +435,32 @@ OUString OAppDetailPageHelper::getQualifiedName( SvTreeListEntry* _pEntry ) cons
        return sComposedName;

    OSL_ENSURE(m_pLists[nPos],"Tables tree view is NULL! -> GPF");
    DBTreeListBox& rTree = *m_pLists[nPos];
    InterimDBTreeListBox& rTree = *m_pLists[nPos];
    weld::TreeView& rTreeView = rTree.GetWidget();

    SvTreeListEntry* pEntry = _pEntry;
    if ( !pEntry )
        pEntry = rTree.FirstSelected();
    std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator(_pEntry));
    if (!_pEntry)
    {
        if (!rTreeView.get_selected(xEntry.get()))
            xEntry.reset();
    }

    if ( !pEntry )
    if (!xEntry)
        return sComposedName;

    if ( getElementType() == E_TABLE )
    {
        const OTableTreeListBox& rTreeView = dynamic_cast< const OTableTreeListBox& >( *m_pLists[nPos] );
        sComposedName = rTreeView.getQualifiedTableName( pEntry );
        const OTableTreeListBox& rTableTreeListBox = dynamic_cast<const OTableTreeListBox&>(*m_pLists[nPos]);
        sComposedName = rTableTreeListBox.getQualifiedTableName(*xEntry);
    }
    else
    {
        sComposedName = rTree.GetEntryText(pEntry);
        SvTreeListEntry* pParent = rTree.GetParent(pEntry);
        while(pParent)
        sComposedName = rTreeView.get_text(*xEntry);
        bool bParent = rTreeView.iter_parent(*xEntry);
        while (bParent)
        {
            sComposedName = rTree.GetEntryText(pParent) + "/" + sComposedName;
            pParent = rTree.GetParent(pParent);
            sComposedName = rTreeView.get_text(*xEntry) + "/" + sComposedName;
            bParent = rTreeView.iter_parent(*xEntry);
        }
    }

@@ -477,13 +479,9 @@ sal_Int32 OAppDetailPageHelper::getSelectionCount()
    int nPos = getVisibleControlIndex();
    if ( nPos < E_ELEMENT_TYPE_COUNT )
    {
        DBTreeListBox& rTree = *m_pLists[nPos];
        SvTreeListEntry* pEntry = rTree.FirstSelected();
        while( pEntry )
        {
            ++nCount;
            pEntry = rTree.NextSelected(pEntry);
        }
        InterimDBTreeListBox& rTree = *m_pLists[nPos];
        weld::TreeView& rTreeView = rTree.GetWidget();
        nCount = rTreeView.count_selected_rows();
    }
    return nCount;
}
@@ -494,16 +492,16 @@ sal_Int32 OAppDetailPageHelper::getElementCount() const
    int nPos = getVisibleControlIndex();
    if ( nPos < E_ELEMENT_TYPE_COUNT )
    {
        nCount = m_pLists[nPos]->GetEntryCount();
        InterimDBTreeListBox& rTree = *m_pLists[nPos];
        weld::TreeView& rTreeView = rTree.GetWidget();
        nCount = rTreeView.n_children();
    }
    return nCount;
}

bool OAppDetailPageHelper::isLeaf(SvTreeListEntry const * _pEntry)
bool OAppDetailPageHelper::isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry)
{
    if ( !_pEntry )
        return false;
    sal_Int32 nEntryType = reinterpret_cast< sal_IntPtr >( _pEntry->GetUserData() );
    sal_Int32 nEntryType = rTreeView.get_id(rEntry).toInt32();
    return !(   ( nEntryType == DatabaseObjectContainer::TABLES )
             || ( nEntryType == DatabaseObjectContainer::CATALOG )
             || ( nEntryType == DatabaseObjectContainer::SCHEMA )
@@ -517,24 +515,29 @@ bool OAppDetailPageHelper::isALeafSelected() const
    bool bLeafSelected = false;
    if ( nPos < E_ELEMENT_TYPE_COUNT )
    {
        DBTreeListBox& rTree = *m_pLists[nPos];
        SvTreeListEntry* pEntry = rTree.FirstSelected( );
        while( !bLeafSelected && pEntry )
        {
            bLeafSelected = isLeaf( pEntry );
            pEntry = rTree.NextSelected(pEntry);
        }
        InterimDBTreeListBox& rTree = *m_pLists[nPos];
        weld::TreeView& rTreeView = rTree.GetWidget();
        rTreeView.selected_foreach([&rTreeView, &bLeafSelected](weld::TreeIter& rEntry){
            bLeafSelected = isLeaf(rTreeView, rEntry);
            return bLeafSelected;
        });
    }
    return bLeafSelected;
}

SvTreeListEntry* OAppDetailPageHelper::getEntry( const Point& _aPosPixel) const
std::unique_ptr<weld::TreeIter> OAppDetailPageHelper::getEntry( const Point& _aPosPixel) const
{
    SvTreeListEntry* pReturn = nullptr;
    std::unique_ptr<weld::TreeIter> xReturn;
    int nPos = getVisibleControlIndex();
    if ( nPos < E_ELEMENT_TYPE_COUNT )
        pReturn = m_pLists[nPos]->GetEntry( _aPosPixel, true );
    return pReturn;
    {
        InterimDBTreeListBox& rTree = *m_pLists[nPos];
        weld::TreeView& rTreeView = rTree.GetWidget();
        xReturn = rTreeView.make_iterator();
        if (!rTreeView.get_dest_row_at_pos(_aPosPixel, xReturn.get(), false))
            xReturn.reset();
    }
    return xReturn;
}

void OAppDetailPageHelper::createTablesPage(const Reference< XConnection>& _xConnection)
@@ -543,26 +546,22 @@ void OAppDetailPageHelper::createTablesPage(const Reference< XConnection>& _xCon

    if ( !m_pLists[E_TABLE] )
    {
        VclPtrInstance<OTableTreeListBox> pTreeView(this,
            WB_HASLINES | WB_SORT | WB_HASBUTTONS | WB_HSCROLL |WB_HASBUTTONSATROOT | WB_TABSTOP);
        VclPtrInstance<OTableTreeListBox> pTreeView(this, false); // false means: do not show any buttons
        pTreeView->SetHelpId(HID_APP_TABLE_TREE);
        m_pLists[E_TABLE] = pTreeView;
        m_pLists[E_TABLE] = createTree(pTreeView);

        createTree( pTreeView,
            ImageProvider::getDefaultImage( DatabaseObject::TABLE )
        );

        pTreeView->notifyHiContrastChanged();
        m_aBorder->SetZOrder(pTreeView, ZOrderFlags::Behind);
    }
    if ( !m_pLists[E_TABLE]->GetEntryCount() )

    weld::TreeView& rTreeView = m_pLists[E_TABLE]->GetWidget();
    if (!rTreeView.n_children())
    {
        static_cast<OTableTreeListBox*>(m_pLists[E_TABLE].get())->UpdateTableList(_xConnection);

        SvTreeListEntry* pEntry = m_pLists[E_TABLE]->First();
        if ( pEntry )
            m_pLists[E_TABLE]->Expand(pEntry);
        m_pLists[E_TABLE]->SelectAll(false);
        std::unique_ptr<weld::TreeIter> xFirst(rTreeView.make_iterator());
        if (rTreeView.get_iter_first(*xFirst))
            rTreeView.expand_row(*xFirst);
        rTreeView.unselect_all();
    }

    setDetailPage(m_pLists[E_TABLE]);
@@ -589,20 +588,16 @@ void OAppDetailPageHelper::createPage(ElementType _eType,const Reference< XNameA
    OSL_ENSURE(E_TABLE != _eType,"E_TABLE isn't allowed.");

    OString sHelpId;
    Image aFolderImage;
    switch( _eType )
    {
        case E_FORM:
            sHelpId = HID_APP_FORM_TREE;
            aFolderImage = ImageProvider::getFolderImage( DatabaseObject::FORM );
            break;
        case E_REPORT:
            sHelpId = HID_APP_REPORT_TREE;
            aFolderImage = ImageProvider::getFolderImage( DatabaseObject::REPORT );
            break;
        case E_QUERY:
            sHelpId = HID_APP_QUERY_TREE;
            aFolderImage = ImageProvider::getFolderImage( DatabaseObject::QUERY );
            break;
        default:
            OSL_FAIL("Illegal call!");
@@ -611,16 +606,19 @@ void OAppDetailPageHelper::createPage(ElementType _eType,const Reference< XNameA

    if ( !m_pLists[_eType] )
    {
        m_pLists[_eType] = createSimpleTree( sHelpId, aFolderImage );
        m_pLists[_eType] = createSimpleTree(sHelpId);
    }

    if ( m_pLists[_eType] )
    {
        if ( !m_pLists[_eType]->GetEntryCount() && _xContainer.is() )
        weld::TreeView& rTreeView = m_pLists[_eType]->GetWidget();
        if (!rTreeView.n_children() && _xContainer.is())
        {
            rTreeView.make_unsorted();
            fillNames( _xContainer, _eType, sImageId, nullptr );
            rTreeView.make_sorted();

            m_pLists[_eType]->SelectAll(false);
            rTreeView.unselect_all();
        }
        setDetailPage(m_pLists[_eType]);
    }
@@ -663,12 +661,12 @@ namespace
}

void OAppDetailPageHelper::fillNames( const Reference< XNameAccess >& _xContainer, const ElementType _eType,
                                      const OUString& rImageId, SvTreeListEntry* _pParent )
                                      const OUString& rImageId, weld::TreeIter* _pParent )
{
    OSL_ENSURE(_xContainer.is(),"Data source is NULL! -> GPF");
    OSL_ENSURE( ( _eType >= E_TABLE ) && ( _eType < E_ELEMENT_TYPE_COUNT ), "OAppDetailPageHelper::fillNames: invalid type!" );

    DBTreeListBox* pList = m_pLists[ _eType ].get();
    InterimDBTreeListBox* pList = m_pLists[ _eType ].get();
    OSL_ENSURE( pList, "OAppDetailPageHelper::fillNames: you really should create the list before calling this!" );
    if ( !pList )
        return;
@@ -676,6 +674,9 @@ void OAppDetailPageHelper::fillNames( const Reference< XNameAccess >& _xContaine
    if ( !(_xContainer.is() && _xContainer->hasElements()) )
        return;

    weld::TreeView& rTreeView = pList->GetWidget();

    std::unique_ptr<weld::TreeIter> xRet = rTreeView.make_iterator();
    const sal_Int32 nFolderIndicator = lcl_getFolderIndicatorForType( _eType );

    Sequence< OUString> aSeq = _xContainer->getElementNames();
@@ -683,66 +684,63 @@ void OAppDetailPageHelper::fillNames( const Reference< XNameAccess >& _xContaine
    const OUString* pEnd  = pIter + aSeq.getLength();
    for(;pIter != pEnd;++pIter)
    {
        SvTreeListEntry* pEntry = nullptr;
        Reference<XNameAccess> xSubElements(_xContainer->getByName(*pIter),UNO_QUERY);
        if ( xSubElements.is() )
        {
            pEntry = pList->InsertEntry( *pIter, _pParent, false, TREELIST_APPEND, reinterpret_cast< void* >( nFolderIndicator ) );
            OUString sId(OUString::number(nFolderIndicator));

            rTreeView.insert(_pParent, -1, nullptr, &sId, nullptr, nullptr, false, xRet.get());
            rTreeView.set_text(*xRet, *pIter, 0);
            rTreeView.set_text_emphasis(*xRet, false, 0);
            getBorderWin().getView()->getAppController().containerFound( Reference< XContainer >( xSubElements, UNO_QUERY ) );
            fillNames( xSubElements, _eType, rImageId, pEntry );
            fillNames( xSubElements, _eType, rImageId, xRet.get());
        }
        else
        {
            pEntry = pList->InsertEntry( *pIter, _pParent );

            Image aImage(StockImage::Yes, rImageId);
            pList->SetExpandedEntryBmp(pEntry, aImage);
            pList->SetCollapsedEntryBmp(pEntry, aImage);
            rTreeView.insert(_pParent, -1, nullptr, nullptr, nullptr, nullptr, false, xRet.get());
            rTreeView.set_text(*xRet, *pIter, 0);
            rTreeView.set_text_emphasis(*xRet, false, 0);
            rTreeView.set_image(*xRet, rImageId);
        }
    }
}

DBTreeListBox* OAppDetailPageHelper::createSimpleTree( const OString& _sHelpId, const Image& _rImage)
InterimDBTreeListBox* OAppDetailPageHelper::createSimpleTree(const OString& rHelpId)
{
    VclPtrInstance<DBTreeListBox> pTreeView(this,
                       WB_HASLINES | WB_SORT | WB_HASBUTTONS | WB_HSCROLL |WB_HASBUTTONSATROOT | WB_TABSTOP);
    pTreeView->SetHelpId( _sHelpId );
    return createTree( pTreeView, _rImage );
    VclPtrInstance<InterimDBTreeListBox> pTreeView(this);
    pTreeView->SetHelpId(rHelpId);
    return createTree(pTreeView);
}

DBTreeListBox* OAppDetailPageHelper::createTree( DBTreeListBox* _pTreeView, const Image& _rImage )
InterimDBTreeListBox* OAppDetailPageHelper::createTree(InterimDBTreeListBox* pTreeView)
{
    weld::WaitObject aWaitCursor(GetFrameWeld());

    _pTreeView->SetStyle(_pTreeView->GetStyle() | WB_HASLINES | WB_SORT | WB_HASBUTTONS | WB_HSCROLL |WB_HASBUTTONSATROOT | WB_TABSTOP);
    _pTreeView->GetModel()->SetSortMode(SortAscending);
    _pTreeView->EnableCheckButton( nullptr ); // do not show any buttons
    _pTreeView->SetSelectionMode(SelectionMode::Multiple);
    pTreeView->setCopyHandler(LINK(this, OAppDetailPageHelper, OnCopyEntry));
    pTreeView->setPasteHandler(LINK(this, OAppDetailPageHelper, OnPasteEntry));
    pTreeView->setDeleteHandler(LINK(this, OAppDetailPageHelper, OnDeleteEntry));

    _pTreeView->SetDefaultCollapsedEntryBmp( _rImage );
    _pTreeView->SetDefaultExpandedEntryBmp( _rImage );
    weld::TreeView& rTreeView = pTreeView->GetWidget();
    rTreeView.make_sorted();
    rTreeView.set_selection_mode(SelectionMode::Multiple);

    _pTreeView->SetDoubleClickHdl(LINK(this, OAppDetailPageHelper, OnEntryDoubleClick));
    _pTreeView->SetEnterKeyHdl(LINK(this, OAppDetailPageHelper, OnEntryEnterKey));
    _pTreeView->SetSelChangeHdl(LINK(this, OAppDetailPageHelper, OnEntrySelChange));
    rTreeView.connect_row_activated(LINK(this, OAppDetailPageHelper, OnEntryDoubleClick));

    _pTreeView->setCopyHandler(LINK(this, OAppDetailPageHelper, OnCopyEntry));
    _pTreeView->setPasteHandler(LINK(this, OAppDetailPageHelper, OnPasteEntry));
    _pTreeView->setDeleteHandler(LINK(this, OAppDetailPageHelper, OnDeleteEntry));
    pTreeView->SetSelChangeHdl(LINK(this, OAppDetailPageHelper, OnEntrySelChange));

    _pTreeView->setControlActionListener( &getBorderWin().getView()->getAppController() );
    _pTreeView->setContextMenuProvider( &getBorderWin().getView()->getAppController() );
    pTreeView->setControlActionListener(&getBorderWin().getView()->getAppController());
    pTreeView->setContextMenuProvider(&getBorderWin().getView()->getAppController());

    return _pTreeView;
    return pTreeView;
}

void OAppDetailPageHelper::clearPages()
{
    showPreview(nullptr);
    for (VclPtr<DBTreeListBox> & rpBox : m_pLists)
    for (VclPtr<InterimDBTreeListBox> & rpBox : m_pLists)
    {
        if ( rpBox )
            rpBox->Clear();
            rpBox->GetWidget().clear();
    }
}

@@ -754,51 +752,58 @@ bool OAppDetailPageHelper::isFilled() const
    return i != E_ELEMENT_TYPE_COUNT;
}

void OAppDetailPageHelper::elementReplaced(ElementType _eType
                                                    ,const OUString& _rOldName
                                                    ,const OUString& _rNewName )
void OAppDetailPageHelper::elementReplaced(ElementType eType,
                                           const OUString& rOldName,
                                           const OUString& rNewName)
{
    DBTreeListBox* pTreeView = getCurrentView();
    if ( !pTreeView )
    InterimDBTreeListBox* pTreeView = getCurrentView();
    if (!pTreeView)
        return;

    SvTreeListEntry* pEntry = nullptr;
    switch( _eType )
    weld::TreeView& rTreeView = pTreeView->GetWidget();
    rTreeView.make_unsorted();

    switch (eType)
    {
        case E_TABLE:
            static_cast<OTableTreeListBox*>(pTreeView)->removedTable( _rOldName );
            static_cast<OTableTreeListBox*>(pTreeView)->addedTable( _rNewName );
            return;

        case E_QUERY:
            pEntry = lcl_findEntry_impl(*pTreeView,_rOldName,pTreeView->First());
            static_cast<OTableTreeListBox*>(pTreeView)->removedTable(rOldName);
            static_cast<OTableTreeListBox*>(pTreeView)->addedTable(rNewName);
            break;
        case E_QUERY:
        {
            std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
            if (rTreeView.get_iter_first(*xIter) && lcl_findEntry_impl(*pTreeView, rOldName, *xIter))
                rTreeView.set_text(*xIter, rNewName);
            break;
        }
        case E_FORM:
        case E_REPORT:
            pEntry = lcl_findEntry(*pTreeView,_rOldName,pTreeView->First());
        {
            std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
            if (rTreeView.get_iter_first(*xIter) && lcl_findEntry(*pTreeView, rOldName, *xIter))
                rTreeView.set_text(*xIter, rNewName);
            break;
        }
        default:
            OSL_FAIL("Invalid element type");
    }
    OSL_ENSURE(pEntry,"Do you know that the name isn't existence!");
    if ( pEntry )
    {
        pTreeView->SetEntryText(pEntry,_rNewName);
    }

    rTreeView.make_sorted();
}

SvTreeListEntry* OAppDetailPageHelper::elementAdded(ElementType _eType,const OUString& _rName, const Any& _rObject )
std::unique_ptr<weld::TreeIter> OAppDetailPageHelper::elementAdded(ElementType _eType,const OUString& _rName, const Any& _rObject )
{
    SvTreeListEntry* pRet = nullptr;
    DBTreeListBox* pTreeView = m_pLists[_eType].get();
    std::unique_ptr<weld::TreeIter> xRet;
    InterimDBTreeListBox* pTreeView = m_pLists[_eType].get();
    weld::TreeView& rTreeView = pTreeView->GetWidget();
    rTreeView.make_unsorted();
    if( _eType == E_TABLE && pTreeView )
    {
        pRet = static_cast<OTableTreeListBox*>(pTreeView)->addedTable( _rName );
        xRet = static_cast<OTableTreeListBox*>(pTreeView)->addedTable( _rName );
    }
    else if ( pTreeView )
    {

        SvTreeListEntry* pEntry = nullptr;
        std::unique_ptr<weld::TreeIter> xEntry;
        Reference<XChild> xChild(_rObject,UNO_QUERY);
        if ( xChild.is() && E_QUERY != _eType )
        {
@@ -806,7 +811,9 @@ SvTreeListEntry* OAppDetailPageHelper::elementAdded(ElementType _eType,const OUS
            if ( xContent.is() )
            {
                OUString sName = xContent->getIdentifier()->getContentIdentifier();
                pEntry = lcl_findEntry(*pTreeView,sName,pTreeView->First());
                std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
                if (rTreeView.get_iter_first(*xIter) && lcl_findEntry(*pTreeView, sName, *xIter))
                    xEntry = std::move(xIter);
            }
        }

@@ -815,58 +822,66 @@ SvTreeListEntry* OAppDetailPageHelper::elementAdded(ElementType _eType,const OUS
        if ( xContainer.is() )
        {
            const sal_Int32 nFolderIndicator = lcl_getFolderIndicatorForType( _eType );
            pRet = pTreeView->InsertEntry( _rName, pEntry, false, TREELIST_APPEND, reinterpret_cast< void* >( nFolderIndicator ) );
            fillNames( xContainer, _eType, sImageId, pRet );
            OUString sId(OUString::number(nFolderIndicator));

            xRet = rTreeView.make_iterator();
            rTreeView.insert(xEntry.get(), -1, nullptr, &sId, nullptr, nullptr, false, xRet.get());
            rTreeView.set_text(*xRet, _rName, 0);
            rTreeView.set_text_emphasis(*xRet, false, 0);
            fillNames(xContainer, _eType, sImageId, xRet.get());
        }
        else
        {
            pRet = pTreeView->InsertEntry( _rName, pEntry );

            Image aImage(StockImage::Yes, sImageId);
            pTreeView->SetExpandedEntryBmp(  pRet, aImage );
            pTreeView->SetCollapsedEntryBmp( pRet, aImage );
            xRet = rTreeView.make_iterator();
            rTreeView.insert(xEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xRet.get());
            rTreeView.set_text(*xRet, _rName, 0);
            rTreeView.set_text_emphasis(*xRet, false, 0);
            rTreeView.set_image(*xRet, sImageId);
        }
    }
    return pRet;
    rTreeView.make_sorted();
    return xRet;
}

void OAppDetailPageHelper::elementRemoved( ElementType _eType,const OUString& _rName )
{
    DBTreeListBox* pTreeView = getCurrentView();
    InterimDBTreeListBox* pTreeView = getCurrentView();
    if ( !pTreeView )
        return;

    weld::TreeView& rTreeView = pTreeView->GetWidget();

    switch( _eType )
    {
        case E_TABLE:
            // we don't need to clear the table here, it is already done by the dispose listener
            static_cast< OTableTreeListBox* >( pTreeView )->removedTable( _rName );
            static_cast<OTableTreeListBox*>(pTreeView)->removedTable(_rName);
            break;
        case E_QUERY:
            if (auto pEntry = lcl_findEntry_impl(*pTreeView, _rName, pTreeView->First()))
                pTreeView->GetModel()->Remove(pEntry);
        {
            std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
            if (rTreeView.get_iter_first(*xIter) && lcl_findEntry_impl(*pTreeView, _rName, *xIter))
                rTreeView.remove(*xIter);
            break;
        }
        case E_FORM:
        case E_REPORT:
            if (auto pEntry = lcl_findEntry(*pTreeView, _rName, pTreeView->First()))
                pTreeView->GetModel()->Remove(pEntry);
        {
            std::unique_ptr<weld::TreeIter> xIter(rTreeView.make_iterator());
            if (rTreeView.get_iter_first(*xIter) && lcl_findEntry(*pTreeView, _rName, *xIter))
                rTreeView.remove(*xIter);
            break;
        }
        default:
            OSL_FAIL("Invalid element type");
    }
    if ( !pTreeView->GetEntryCount() )
    if (!rTreeView.n_children())
        showPreview(nullptr);
}

IMPL_LINK(OAppDetailPageHelper, OnEntryEnterKey, DBTreeListBox*, _pTree, void )
IMPL_LINK(OAppDetailPageHelper, OnEntryDoubleClick, weld::TreeView&, rTreeView, bool)
{
    OnEntryDoubleClick(_pTree);
}
IMPL_LINK(OAppDetailPageHelper, OnEntryDoubleClick, SvTreeListBox*, _pTree, bool)
{
    OSL_ENSURE( _pTree, "OAppDetailPageHelper, OnEntryDoubleClick: invalid callback!" );
    bool bHandled = ( _pTree != nullptr ) && getBorderWin().getView()->getAppController().onEntryDoubleClick( *_pTree );
    return bHandled;
    return getBorderWin().getView()->getAppController().onEntryDoubleClick(rTreeView);
}

IMPL_LINK_NOARG(OAppDetailPageHelper, OnEntrySelChange, LinkParamNone*, void)
@@ -970,7 +985,8 @@ void OAppDetailPageHelper::switchPreview(PreviewMode _eMode,bool _bForce)
    // simulate a selectionChanged event at the controller, to force the preview to be updated
    if ( isPreviewEnabled() )
    {
        if ( getCurrentView() && getCurrentView()->FirstSelected() )
        InterimDBTreeListBox* pCurrent = getCurrentView();
        if (pCurrent && pCurrent->GetWidget().get_selected(nullptr))
        {
            getBorderWin().getView()->getAppController().onSelectionChanged();
        }
@@ -1163,14 +1179,14 @@ IMPL_LINK_NOARG(OAppDetailPageHelper, OnDropdownClickHdl, ToolBox*, void)

void OAppDetailPageHelper::KeyInput( const KeyEvent& rKEvt )
{
    SvTreeListBox* pCurrentView = getCurrentView();
    InterimDBTreeListBox* pCurrentView = getCurrentView();
    OSL_PRECOND( pCurrentView, "OAppDetailPageHelper::KeyInput: how this?" );

    sal_uInt16      nCode = rKEvt.GetKeyCode().GetCode();

    if ( ( KEY_RETURN == nCode ) && pCurrentView )
    {
        getBorderWin().getView()->getAppController().onEntryDoubleClick( *pCurrentView );
        getBorderWin().getView()->getAppController().onEntryDoubleClick(pCurrentView->GetWidget());
    }
    else
        Window::KeyInput(rKEvt);
@@ -1185,16 +1201,8 @@ void OAppDetailPageHelper::DataChanged( const DataChangedEvent& rDCEvt )
        (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
        ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
        (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )

    {
        ImplInitSettings();
        if ( m_pLists[ E_TABLE ] )
        {
            OTableTreeListBox* pTableTree = dynamic_cast< OTableTreeListBox* >( m_pLists[ E_TABLE ].get() );
            OSL_ENSURE( pTableTree != nullptr, "OAppDetailPageHelper::DataChanged: a tree list for tables which is no TableTreeList?" );
            if ( pTableTree )
                pTableTree->notifyHiContrastChanged();
        }
    }
}

diff --git a/dbaccess/source/ui/app/AppDetailPageHelper.hxx b/dbaccess/source/ui/app/AppDetailPageHelper.hxx
index 1dd89d8..bda4444 100644
--- a/dbaccess/source/ui/app/AppDetailPageHelper.hxx
+++ b/dbaccess/source/ui/app/AppDetailPageHelper.hxx
@@ -27,12 +27,12 @@
#include <com/sun/star/ucb/XContent.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <AppElementType.hxx>
#include <vcl/treelistbox.hxx>
#include <svtools/DocumentInfoPreview.hxx>
#include <vcl/fixed.hxx>
#include <vcl/toolbox.hxx>
#include <vcl/graph.hxx>
#include <vcl/GraphicObject.hxx>
#include <vcl/weld.hxx>

namespace com::sun::star::awt   { class XWindow; }
namespace com::sun::star::frame { class XFrame2; }
@@ -43,6 +43,8 @@ namespace com::sun::star::io    { class XPersist; }
namespace dbaui
{
    class OAppBorderWindow;
    class InterimDBTreeListBox;
    class TreeListBox;
    class DBTreeListBox;

    class OPreviewWindow : public vcl::Window
@@ -71,11 +73,12 @@ namespace dbaui

        void setGraphic(const Graphic& _rGraphic ) { m_aGraphicObj.SetGraphic(_rGraphic); }
    };

    // A helper class for the controls in the detail page.
    // Combines general functionality.
    class OAppDetailPageHelper : public vcl::Window
    {
        VclPtr<DBTreeListBox>     m_pLists[ELEMENT_COUNT];
        VclPtr<InterimDBTreeListBox> m_pLists[ELEMENT_COUNT];
        OAppBorderWindow&         m_rBorderWin;
        VclPtr<FixedLine>         m_aFL;
        VclPtr<ToolBox>           m_aTBPreview;
@@ -94,12 +97,12 @@ namespace dbaui
        int getVisibleControlIndex() const;

        /** sorts the entries in the tree list box.
            @param  _nPos
            @param  nPos
                Which list should be sorted.
            @param  _eSortMode
                How should be sorted.
            @param  bAscending
                If sort should be Ascending of Descending
        */
        void sort(int _nPos,SvSortMode _eSortMode );
        void sort(int nPos, bool bAscending);

        /** retrieves the resource ids of the images representing elements of the given type
        */
@@ -118,7 +121,7 @@ namespace dbaui
        void fillNames( const css::uno::Reference< css::container::XNameAccess >& _xContainer,
                        const ElementType _eType,
                        const OUString& rImageId,
                        SvTreeListEntry* _pParent );
                        weld::TreeIter* _pParent );

        /** sets the detail page
            @param  _pWindow
@@ -129,25 +132,20 @@ namespace dbaui
        /** sets all HandleCallbacks
            @param  _pTreeView
                The newly created DBTreeListBox
            @param  _rImage
                the resource id of the default icon
            @return
                The new tree.
        */
        DBTreeListBox* createTree( DBTreeListBox* _pTreeView, const Image& _rImage );
        InterimDBTreeListBox* createTree(InterimDBTreeListBox* pTreeView);

        /** creates the tree and sets all HandleCallbacks
            @param  _nHelpId
                The help id of the control
            @param  _nCollapsedBitmap
                The image to use in high contrast mode.
            @return
                The new tree.
        */
        DBTreeListBox* createSimpleTree( const OString& _sHelpId, const Image& _rImage);
        InterimDBTreeListBox* createSimpleTree(const OString& rHelpId);

        DECL_LINK( OnEntryDoubleClick,    SvTreeListBox*, bool );
        DECL_LINK( OnEntryEnterKey,       DBTreeListBox*, void );
        DECL_LINK( OnEntryDoubleClick,    weld::TreeView&, bool );
        DECL_LINK( OnEntrySelChange,      LinkParamNone*, void );

        DECL_LINK( OnCopyEntry,           LinkParamNone*, void );
@@ -185,7 +183,7 @@ namespace dbaui

        /** returns the current visible tree list box
        */
        DBTreeListBox* getCurrentView() const
        InterimDBTreeListBox* getCurrentView() const
        {
            ElementType eType = getElementType();
            return (eType != E_NONE ) ? m_pLists[static_cast<sal_Int32>(eType)].get() : nullptr;
@@ -236,7 +234,7 @@ namespace dbaui
            @return
                the qualified name
        */
        OUString getQualifiedName( SvTreeListEntry* _pEntry ) const;
        OUString getQualifiedName( weld::TreeIter* _pEntry ) const;

        /// return the element of currently select entry
        ElementType getElementType() const;
@@ -248,12 +246,14 @@ namespace dbaui
        sal_Int32 getElementCount() const;

        /** returns if an entry is a leaf
            @param _pEntry
            @param rTreeView
                The TreeView rEntry belongs to
            @param rEntry
                The entry to check
            @return
                <TRUE/> if the entry is a leaf, otherwise <FALSE/>
        */
        static bool isLeaf(SvTreeListEntry const * _pEntry);
        static bool isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry);

        /** returns if one of the selected entries is a leaf
            @return
@@ -261,7 +261,7 @@ namespace dbaui
        */
        bool isALeafSelected() const;

        SvTreeListEntry* getEntry( const Point& _aPosPixel ) const;
        std::unique_ptr<weld::TreeIter> getEntry(const Point& rPosPixel) const;

        /// clears the detail pages
        void clearPages();
@@ -279,9 +279,9 @@ namespace dbaui
            @param  _rxConn
                If we insert a table, the connection must be set.
        */
        SvTreeListEntry*  elementAdded(ElementType eType
                        ,const OUString& _rName
                        ,const css::uno::Any& _rObject );
        std::unique_ptr<weld::TreeIter> elementAdded(ElementType eType,
                                                     const OUString& rName,
                                                     const css::uno::Any& rObject);

        /** replaces an objects name with a new one
            @param  _eType
diff --git a/dbaccess/source/ui/app/AppDetailView.cxx b/dbaccess/source/ui/app/AppDetailView.cxx
index e6e318c..3430d0b 100644
--- a/dbaccess/source/ui/app/AppDetailView.cxx
+++ b/dbaccess/source/ui/app/AppDetailView.cxx
@@ -406,14 +406,14 @@ const TaskPaneData& OApplicationDetailView::impl_getTaskPaneData( ElementType _e
    return rData;
}

OUString OApplicationDetailView::getQualifiedName( SvTreeListEntry* _pEntry ) const
OUString OApplicationDetailView::getQualifiedName(weld::TreeIter* _pEntry) const
{
    return m_pControlHelper->getQualifiedName( _pEntry );
}

bool OApplicationDetailView::isLeaf(SvTreeListEntry const * _pEntry)
bool OApplicationDetailView::isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry)
{
    return OAppDetailPageHelper::isLeaf(_pEntry);
    return OAppDetailPageHelper::isLeaf(rTreeView, rEntry);
}

bool OApplicationDetailView::isALeafSelected() const
@@ -483,9 +483,9 @@ void OApplicationDetailView::selectElements(const Sequence< OUString>& _aNames)
    m_pControlHelper->selectElements( _aNames );
}

SvTreeListEntry* OApplicationDetailView::getEntry( const Point& _aPoint ) const
std::unique_ptr<weld::TreeIter> OApplicationDetailView::getEntry(const Point& rPoint) const
{
    return m_pControlHelper->getEntry(_aPoint);
    return m_pControlHelper->getEntry(rPoint);
}

bool OApplicationDetailView::isCutAllowed()
@@ -506,9 +506,9 @@ void OApplicationDetailView::cut()  { }

void OApplicationDetailView::paste() { }

SvTreeListEntry*  OApplicationDetailView::elementAdded(ElementType _eType,const OUString& _rName, const Any& _rObject )
std::unique_ptr<weld::TreeIter> OApplicationDetailView::elementAdded(ElementType _eType,const OUString& _rName, const Any& _rObject )
{
    return m_pControlHelper->elementAdded(_eType,_rName, _rObject );
    return m_pControlHelper->elementAdded(_eType, _rName, _rObject);
}

void OApplicationDetailView::elementRemoved(ElementType _eType,const OUString& _rName )
diff --git a/dbaccess/source/ui/app/AppDetailView.hxx b/dbaccess/source/ui/app/AppDetailView.hxx
index a00e7f4..c551db1 100644
--- a/dbaccess/source/ui/app/AppDetailView.hxx
+++ b/dbaccess/source/ui/app/AppDetailView.hxx
@@ -158,15 +158,17 @@ namespace dbaui
            @return
                the qualified name
        */
        OUString getQualifiedName( SvTreeListEntry* _pEntry ) const;
        OUString getQualifiedName(weld::TreeIter* _pEntry) const;

        /** returns if an entry is a leaf
            @param _pEntry
            @param rTreeView
                The TreeView pEntry belongs to
            @param rEntry
                The entry to check
            @return
                <TRUE/> if the entry is a leaf, otherwise <FALSE/>
        */
        static bool isLeaf(SvTreeListEntry const * _pEntry);
        static bool isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry);

        /** returns if one of the selected entries is a leaf
            @return
@@ -241,9 +243,9 @@ namespace dbaui
            @param  _rxConn
                If we insert a table, the connection must be set.
        */
        SvTreeListEntry* elementAdded(ElementType eType
                        ,const OUString& _rName
                        ,const css::uno::Any& _rObject );
        std::unique_ptr<weld::TreeIter> elementAdded(ElementType eType,
                                                     const OUString& rName,
                                                     const css::uno::Any& rObject);

        /** replaces an objects name with a new one
            @param  _eType
@@ -303,7 +305,7 @@ namespace dbaui
                            const OUString& _sName,
                            bool _bTable);

        SvTreeListEntry* getEntry( const Point& _aPoint ) const;
        std::unique_ptr<weld::TreeIter> getEntry(const Point& rPosPixel) const;

        vcl::Window* getTreeWindow() const;
    private:
diff --git a/dbaccess/source/ui/app/AppView.cxx b/dbaccess/source/ui/app/AppView.cxx
index 5ab8ba3..5aa3c2c 100644
--- a/dbaccess/source/ui/app/AppView.cxx
+++ b/dbaccess/source/ui/app/AppView.cxx
@@ -294,16 +294,16 @@ void OApplicationView::paste()
        pTest->paste();
}

OUString OApplicationView::getQualifiedName( SvTreeListEntry* _pEntry ) const
OUString OApplicationView::getQualifiedName(weld::TreeIter* _pEntry) const
{
    OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
    return getDetailView()->getQualifiedName( _pEntry );
}

bool OApplicationView::isLeaf(SvTreeListEntry const * _pEntry) const
bool OApplicationView::isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry) const
{
    OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
    return OApplicationDetailView::isLeaf(_pEntry);
    return OApplicationDetailView::isLeaf(rTreeView, rEntry);
}

bool OApplicationView::isALeafSelected() const
@@ -384,7 +384,7 @@ void OApplicationView::selectElements(const Sequence< OUString>& _aNames)
    getDetailView()->selectElements( _aNames );
}

SvTreeListEntry* OApplicationView::elementAdded(ElementType eType,const OUString& _rName, const Any& _rObject )
std::unique_ptr<weld::TreeIter> OApplicationView::elementAdded(ElementType eType,const OUString& _rName, const Any& _rObject )
{
    OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
    return getDetailView()->elementAdded(eType,_rName,_rObject);
@@ -418,10 +418,10 @@ void OApplicationView::selectContainer(ElementType _eType)
    getPanel()->selectContainer(_eType);
}

SvTreeListEntry* OApplicationView::getEntry( const Point& _aPosPixel ) const
std::unique_ptr<weld::TreeIter> OApplicationView::getEntry(const Point& rPosPixel) const
{
    OSL_ENSURE(m_pWin && getDetailView(),"Detail view is NULL! -> GPF");
    return getDetailView()->getEntry(_aPosPixel);
    return getDetailView()->getEntry(rPosPixel);
}

PreviewMode OApplicationView::getPreviewMode() const
diff --git a/dbaccess/source/ui/app/AppView.hxx b/dbaccess/source/ui/app/AppView.hxx
index 0d49295..d8f2224 100644
--- a/dbaccess/source/ui/app/AppView.hxx
+++ b/dbaccess/source/ui/app/AppView.hxx
@@ -31,6 +31,11 @@ namespace com::sun::star::beans    { class XPropertySet; }

class Control;
class SvTreeListEntry;
namespace weld
{
    class TreeIter;
    class TreeView;
}
class MnemonicGenerator;

namespace dbaui
@@ -136,15 +141,17 @@ namespace dbaui
            @return
                the qualified name
        */
        OUString getQualifiedName( SvTreeListEntry* _pEntry ) const;
        OUString getQualifiedName(weld::TreeIter* _pEntry) const;

        /** returns if an entry is a leaf
            @param _pEntry
            @param rTreeView
                The TreeView rEntry belongs to
            @param rEntry
                The entry to check
            @return
                <TRUE/> if the entry is a leaf, otherwise <FALSE/>
        */
        bool isLeaf(SvTreeListEntry const * _pEntry) const;
        bool isLeaf(const weld::TreeView& rTreeView, const weld::TreeIter& rEntry) const;

        /** returns if one of the selected entries is a leaf
            @return
@@ -218,9 +225,9 @@ namespace dbaui
            @param  _rxConn
                If we insert a table, the connection must be set.
        */
        SvTreeListEntry* elementAdded(ElementType _eType
                        ,const OUString& _rName
                        ,const css::uno::Any& _rObject );
        std::unique_ptr<weld::TreeIter> elementAdded(ElementType eType,
                                                     const OUString& rName,
                                                     const css::uno::Any& rObject);

        /** replaces an objects name with a new one
            @param  _eType
@@ -289,7 +296,7 @@ namespace dbaui
                            const OUString& _sName,
                            bool _bTable);

        SvTreeListEntry* getEntry( const Point& _aPosPixel ) const;
        std::unique_ptr<weld::TreeIter> getEntry(const Point& rPosPixel) const;
    };
}
#endif // INCLUDED_DBACCESS_SOURCE_UI_APP_APPVIEW_HXX
diff --git a/dbaccess/source/ui/browser/dsbrowserDnD.cxx b/dbaccess/source/ui/browser/dsbrowserDnD.cxx
index cd8c124..0b9888f 100644
--- a/dbaccess/source/ui/browser/dsbrowserDnD.cxx
+++ b/dbaccess/source/ui/browser/dsbrowserDnD.cxx
@@ -191,6 +191,12 @@ namespace dbaui

        return pTransfer.is();
    }

    bool SbaTableQueryBrowser::requestDrag(const weld::TreeIter& /*rEntry*/)
    {
        return false;
    }

    IMPL_LINK_NOARG(SbaTableQueryBrowser, OnCopyEntry, LinkParamNone*, void)
    {
        SvTreeListEntry* pSelected = m_pTreeView->getListBox().FirstSelected();
diff --git a/dbaccess/source/ui/browser/unodatbr.cxx b/dbaccess/source/ui/browser/unodatbr.cxx
index 43a7006..4caa3f4 100644
--- a/dbaccess/source/ui/browser/unodatbr.cxx
+++ b/dbaccess/source/ui/browser/unodatbr.cxx
@@ -3380,13 +3380,19 @@ bool SbaTableQueryBrowser::requestQuickHelp( const SvTreeListEntry* _pEntry, OUS
    return false;
}

OUString SbaTableQueryBrowser::getContextMenuResourceName( Control& _rControl ) const
bool SbaTableQueryBrowser::requestQuickHelp(const void* pUserData, OUString& rText) const
{
    OSL_PRECOND( &m_pTreeView->getListBox() == &_rControl,
        "SbaTableQueryBrowser::getContextMenuResourceName: where does this come from?" );
    if ( &m_pTreeView->getListBox() != &_rControl )
        return OUString();
    const DBTreeListUserData* pData = static_cast<const DBTreeListUserData*>(pUserData);
    if (pData->eType == etDatasource && !pData->sAccessor.isEmpty())
    {
        rText = ::svt::OFileNotation(pData->sAccessor).get( ::svt::OFileNotation::N_SYSTEM);
        return true;
    }
    return false;
}

OUString SbaTableQueryBrowser::getContextMenuResourceName() const
{
    return "explorer";
}

diff --git a/dbaccess/source/ui/control/dbtreelistbox.cxx b/dbaccess/source/ui/control/dbtreelistbox.cxx
index 4fbb348..8be8061 100644
--- a/dbaccess/source/ui/control/dbtreelistbox.cxx
+++ b/dbaccess/source/ui/control/dbtreelistbox.cxx
@@ -29,13 +29,14 @@
#include <comphelper/interfacecontainer2.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/propertyvalue.hxx>
#include <vcl/help.hxx>
#include <dbaccess/IController.hxx>
#include <framework/actiontriggerhelper.hxx>
#include <toolkit/awt/vclxmenu.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <vcl/treelistentry.hxx>
#include <vcl/commandevent.hxx>
#include <vcl/event.hxx>
#include <vcl/help.hxx>
#include <vcl/treelistentry.hxx>

#include <memory>

@@ -61,6 +62,139 @@ DBTreeListBox::DBTreeListBox( vcl::Window* pParent, WinBits nWinStyle )
    init();
}

InterimDBTreeListBox::InterimDBTreeListBox(vcl::Window* pParent)
    : InterimItemWindow(pParent, "dbaccess/ui/dbtreelist.ui", "DBTreeList")
    , TreeListBox(m_xBuilder->weld_tree_view("treeview"))
{
    InitControlBase(&GetWidget());
}

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

void InterimDBTreeListBox::dispose()
{
    implStopSelectionTimer();
    m_xTreeView.reset();
    InterimItemWindow::dispose();
}

bool InterimDBTreeListBox::DoChildKeyInput(const KeyEvent& rKEvt)
{
    return ChildKeyInput(rKEvt);
}

TreeListBoxDropTarget::TreeListBoxDropTarget(TreeListBox& rTreeView)
    : DropTargetHelper(rTreeView.GetWidget().get_drop_target())
    , m_rTreeView(rTreeView)
{
}

sal_Int8 TreeListBoxDropTarget::AcceptDrop(const AcceptDropEvent& rEvt)
{
    sal_Int8 nAccept = m_rTreeView.AcceptDrop(rEvt);

    if (nAccept != DND_ACTION_NONE)
    {
        // to enable the autoscroll when we're close to the edges
        weld::TreeView& rWidget = m_rTreeView.GetWidget();
        rWidget.get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true);
    }

    return nAccept;
}

sal_Int8 TreeListBoxDropTarget::ExecuteDrop(const ExecuteDropEvent& rEvt)
{
    return m_rTreeView.ExecuteDrop(rEvt);
}

TreeListBox::TreeListBox(std::unique_ptr<weld::TreeView> xTreeView)
    : m_xTreeView(std::move(xTreeView))
    , m_aDropTargetHelper(*this)
    , m_pActionListener(nullptr)
    , m_pContextMenuProvider(nullptr)
{
    m_xTreeView->make_sorted();

    m_xTreeView->connect_key_press(LINK(this, TreeListBox, KeyInputHdl));
    m_xTreeView->connect_changed(LINK(this, TreeListBox, SelectHdl));
    m_xTreeView->connect_query_tooltip(LINK(this, TreeListBox, QueryTooltipHdl));
    m_xTreeView->connect_popup_menu(LINK(this, TreeListBox, CommandHdl));
    m_xTreeView->connect_drag_begin(LINK(this, TreeListBox, DragBeginHdl));

    m_aTimer.SetTimeout(900);
    m_aTimer.SetInvokeHandler(LINK(this, TreeListBox, OnTimeOut));
}

bool TreeListBox::DoChildKeyInput(const KeyEvent& /*rKEvt*/)
{
    // nothing by default
    return false;
}

bool TreeListBox::DoContextMenu(const CommandEvent& /*rCEvt*/)
{
    return false;
}

IMPL_LINK(TreeListBox, CommandHdl, const CommandEvent&, rCEvt, bool)
{
    return DoContextMenu(rCEvt);
}

IMPL_LINK(TreeListBox, KeyInputHdl, const KeyEvent&, rKEvt, bool)
{
    KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
    bool bHandled = false;

    switch (eFunc)
    {
        case KeyFuncType::COPY:
            bHandled = m_aCopyHandler.IsSet() && !m_xTreeView->get_selected(nullptr);
            if (bHandled)
                m_aCopyHandler.Call(nullptr);
            break;
        case KeyFuncType::PASTE:
            bHandled = m_aPasteHandler.IsSet() && !m_xTreeView->get_selected(nullptr);
            if (bHandled)
                m_aPasteHandler.Call(nullptr);
            break;
        case KeyFuncType::DELETE:
            bHandled = m_aDeleteHandler.IsSet() && !m_xTreeView->get_selected(nullptr);
            if (bHandled)
                m_aDeleteHandler.Call(nullptr);
            break;
        default:
            break;
    }

    return bHandled || DoChildKeyInput(rKEvt);
}

void TreeListBox::implStopSelectionTimer()
{
    if ( m_aTimer.IsActive() )
        m_aTimer.Stop();
}

void TreeListBox::implStartSelectionTimer()
{
    implStopSelectionTimer();
    m_aTimer.Start();
}

IMPL_LINK_NOARG(TreeListBox, SelectHdl, weld::TreeView&, void)
{
    implStartSelectionTimer();
}

TreeListBox::~TreeListBox()
{
}

void DBTreeListBox::init()
{
    SetSpaceBetweenEntries(SPACEBETWEENENTRIES);
@@ -121,6 +255,27 @@ SvTreeListEntry* DBTreeListBox::GetEntryPosByName( const OUString& aName, SvTree
    return pEntry;
}

std::unique_ptr<weld::TreeIter> TreeListBox::GetEntryPosByName(const OUString& aName, const weld::TreeIter* pStart, const IEntryFilter* _pFilter) const
{
    auto xEntry(m_xTreeView->make_iterator(pStart));
    if (!pStart && !m_xTreeView->get_iter_first(*xEntry))
        return nullptr;

    do
    {
        if (m_xTreeView->get_text(*xEntry) == aName)
        {
            if (!_pFilter || _pFilter->includeEntry(reinterpret_cast<void*>(m_xTreeView->get_id(*xEntry).toUInt64())))
            {
                // found
                return xEntry;
            }
        }
    } while (m_xTreeView->iter_next(*xEntry));

    return nullptr;
}

void DBTreeListBox::RequestingChildren( SvTreeListEntry* pParent )
{
    if (m_aPreExpandHandler.IsSet() && !m_aPreExpandHandler.Call(pParent))
@@ -262,6 +417,83 @@ sal_Int8 DBTreeListBox::ExecuteDrop( const ExecuteDropEvent& _rEvt )
    return DND_ACTION_NONE;
}

IMPL_LINK(TreeListBox, DragBeginHdl, bool&, rUnsetDragIcon, bool)
{
    rUnsetDragIcon = false;

    if (m_pActionListener)
    {
        m_xDragedEntry = m_xTreeView->make_iterator();
        if (!m_xTreeView->get_selected(m_xDragedEntry.get()))
            m_xDragedEntry.reset();
        if (m_xDragedEntry && m_pActionListener->requestDrag(*m_xDragedEntry))
        {
            // if the (asynchronous) drag started, stop the selection timer
            implStopSelectionTimer();
            return false;
        }
    }

    return true;
}

sal_Int8 TreeListBox::AcceptDrop(const AcceptDropEvent& rEvt)
{
    sal_Int8 nDropOption = DND_ACTION_NONE;
    if ( m_pActionListener )
    {
        ::Point aDropPos = rEvt.maPosPixel;
        std::unique_ptr<weld::TreeIter> xDropTarget(m_xTreeView->make_iterator());
        if (!m_xTreeView->get_dest_row_at_pos(aDropPos, xDropTarget.get(), true))
            xDropTarget.reset();

        // check if drag is on child entry, which is not allowed
        std::unique_ptr<weld::TreeIter> xParent;
        if (rEvt.mnAction & DND_ACTION_MOVE)
        {
            if (!m_xDragedEntry) // no entry to move
                return m_pActionListener->queryDrop(rEvt, m_aDropTargetHelper.GetDataFlavorExVector());

            if (xDropTarget)
            {
                xParent = m_xTreeView->make_iterator(xDropTarget.get());
                if (!m_xTreeView->iter_parent(*xParent))
                    xParent.reset();
            }
            while (xParent && m_xTreeView->iter_compare(*xParent, *m_xDragedEntry) != 0)
            {
                if (!m_xTreeView->iter_parent(*xParent))
                    xParent.reset();
            }
        }

        if (!xParent)
        {
            nDropOption = m_pActionListener->queryDrop(rEvt, m_aDropTargetHelper.GetDataFlavorExVector());
            // check if move is allowed
            if ( nDropOption & DND_ACTION_MOVE )
            {
                if (!m_xDragedEntry || !xDropTarget ||
                    m_xTreeView->iter_compare(*m_xDragedEntry, *xDropTarget) == 0 ||
                    GetEntryPosByName(m_xTreeView->get_text(*m_xDragedEntry), xDropTarget.get()))
                {
                    nDropOption = nDropOption & ~DND_ACTION_MOVE;//DND_ACTION_NONE;
                }
            }
        }
    }

    return nDropOption;
}

sal_Int8 TreeListBox::ExecuteDrop(const ExecuteDropEvent& rEvt)
{
    if (m_pActionListener)
        m_pActionListener->executeDrop(rEvt);
    m_xTreeView->unset_drag_dest_row();
    return DND_ACTION_NONE;
}

void DBTreeListBox::StartDrag( sal_Int8 /*_nAction*/, const Point& _rPosPixel )
{
    if ( m_pActionListener )
@@ -307,6 +539,17 @@ void DBTreeListBox::RequestHelp( const HelpEvent& rHEvt )
    SvTreeListBox::RequestHelp( rHEvt );
}

IMPL_LINK(TreeListBox, QueryTooltipHdl, const weld::TreeIter&, rIter, OUString)
{
    OUString sQuickHelpText;
    if (m_pActionListener &&
        m_pActionListener->requestQuickHelp(reinterpret_cast<void*>(m_xTreeView->get_id(rIter).toUInt64()), sQuickHelpText))
    {
        return sQuickHelpText;
    }
    return m_xTreeView->get_tooltip_text();
}

void DBTreeListBox::KeyInput( const KeyEvent& rKEvt )
{
    KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
@@ -458,12 +701,128 @@ namespace
    }
}

bool InterimDBTreeListBox::DoContextMenu(const CommandEvent& rCEvt)
{
    if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
        return false;

    const ::Point& rPos = rCEvt.GetMousePosPixel();

    std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
    if (m_xTreeView->get_dest_row_at_pos(rPos, xIter.get(), false) && !m_xTreeView->is_selected(*xIter))
    {
        m_xTreeView->unselect_all();
        m_xTreeView->set_cursor(*xIter);
        m_xTreeView->select(*xIter);
        SelectHdl(*m_xTreeView);
    }

    if (!m_pContextMenuProvider)
        return false;

    OUString aResourceName(m_pContextMenuProvider->getContextMenuResourceName());
    if (aResourceName.isEmpty())
        return false;

    css::uno::Sequence< css::uno::Any > aArgs( 3 );
    aArgs[0] <<= comphelper::makePropertyValue( "Value", aResourceName );
    aArgs[1] <<= comphelper::makePropertyValue( "Frame", m_pContextMenuProvider->getCommandController().getXController()->getFrame() );
    aArgs[2] <<= comphelper::makePropertyValue( "IsContextMenu", true );

    css::uno::Reference< css::uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
    css::uno::Reference<css::frame::XPopupMenuController> xMenuController
        (xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
            "com.sun.star.comp.framework.ResourceMenuController", aArgs, xContext), css::uno::UNO_QUERY);

    if (!xMenuController.is())
        return false;

    rtl::Reference xPopupMenu( new VCLXPopupMenu );
    xMenuController->setPopupMenu( xPopupMenu.get() );
    VclPtr<PopupMenu> pContextMenu( static_cast< PopupMenu* >( xPopupMenu->GetMenu() ) );

    // allow context menu interception
    ::comphelper::OInterfaceContainerHelper2* pInterceptors = m_pContextMenuProvider->getContextMenuInterceptors();
    if (pInterceptors && pInterceptors->getLength())
    {
        OUString aMenuIdentifier( "private:resource/popupmenu/" + aResourceName );

        ContextMenuExecuteEvent aEvent;
        aEvent.SourceWindow = VCLUnoHelper::GetInterface( this );
        aEvent.ExecutePosition.X = -1;
        aEvent.ExecutePosition.Y = -1;
        aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu(
            pContextMenu.get(), &aMenuIdentifier );
        aEvent.Selection = new SelectionSupplier( m_pContextMenuProvider->getCurrentSelection( *this ) );

        ::comphelper::OInterfaceIteratorHelper2 aIter( *pInterceptors );
        bool bModifiedMenu = false;
        bool bAskInterceptors = true;
        while ( aIter.hasMoreElements() && bAskInterceptors )
        {
            Reference< XContextMenuInterceptor > xInterceptor( aIter.next(), UNO_QUERY );
            if ( !xInterceptor.is() )
                continue;

            try
            {
                ContextMenuInterceptorAction eAction = xInterceptor->notifyContextMenuExecute( aEvent );
                switch ( eAction )
                {
                    case ContextMenuInterceptorAction_CANCELLED:
                        return false;

                    case ContextMenuInterceptorAction_EXECUTE_MODIFIED:
                        bModifiedMenu = true;
                        bAskInterceptors = false;
                        break;

                    case ContextMenuInterceptorAction_CONTINUE_MODIFIED:
                        bModifiedMenu = true;
                        bAskInterceptors = true;
                        break;

                    default:
                        OSL_FAIL( "DBTreeListBox::CreateContextMenu: unexpected return value of the interceptor call!" );
                        [[fallthrough]];
                    case ContextMenuInterceptorAction_IGNORED:
                        break;
                }
            }
            catch( const DisposedException& e )
            {
                if ( e.Context == xInterceptor )
                    aIter.remove();
            }
        }

        if ( bModifiedMenu )
        {
            pContextMenu->Clear();
            ::framework::ActionTriggerHelper::CreateMenuFromActionTriggerContainer(
                pContextMenu, aEvent.ActionTriggerContainer );
            aEvent.ActionTriggerContainer.clear();
        }
    }

    // do action for selected entry in popup menu
    pContextMenu->Execute(this, rPos);
    pContextMenu.disposeAndClear();

    css::uno::Reference<css::lang::XComponent> xComponent(xMenuController, css::uno::UNO_QUERY);
    if (xComponent.is())
        xComponent->dispose();
    xMenuController.clear();

    return true;
}

VclPtr<PopupMenu> DBTreeListBox::CreateContextMenu()
{
    if ( !m_pContextMenuProvider )
        return nullptr;

    OUString aResourceName( m_pContextMenuProvider->getContextMenuResourceName( *this ) );
    OUString aResourceName( m_pContextMenuProvider->getContextMenuResourceName() );
    if ( aResourceName.isEmpty() )
        return nullptr;

@@ -569,6 +928,13 @@ IMPL_LINK_NOARG(DBTreeListBox, OnTimeOut, Timer*, void)
    m_aSelChangeHdl.Call( nullptr );
}

IMPL_LINK_NOARG(TreeListBox, OnTimeOut, Timer*, void)
{
    implStopSelectionTimer();

    m_aSelChangeHdl.Call( nullptr );
}

void DBTreeListBox::StateChanged( StateChangedType nStateChange )
{
    if ( nStateChange == StateChangedType::Visible )
diff --git a/dbaccess/source/ui/control/tabletree.cxx b/dbaccess/source/ui/control/tabletree.cxx
index b565b62..99bcfad 100644
--- a/dbaccess/source/ui/control/tabletree.cxx
+++ b/dbaccess/source/ui/control/tabletree.cxx
@@ -36,7 +36,6 @@
#include <vcl/event.hxx>
#include <vcl/settings.hxx>
#include <vcl/svapp.hxx>
#include <vcl/treelistentry.hxx>

#include <algorithm>

@@ -59,88 +58,40 @@ namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject;
namespace DatabaseObjectContainer = ::com::sun::star::sdb::application::DatabaseObjectContainer;

// OTableTreeListBox
OTableTreeListBox::OTableTreeListBox(vcl::Window* pParent, WinBits nWinStyle)
    : DBTreeListBox(pParent, nWinStyle)
    , m_xImageProvider( new ImageProvider )
    , m_bVirtualRoot(false)
    , m_bNoEmptyFolders( false )
{
    InitButtonData();

    implSetDefaultImages();
}

void OTableTreeListBox::InitButtonData()
{
    m_pCheckButton.reset( new SvLBoxButtonData( this ) );
    EnableCheckButton( m_pCheckButton.get() );
}

void OTableTreeListBox::dispose()
{
    m_pCheckButton.reset();
    DBTreeListBox::dispose();
}

TableTreeListBox::TableTreeListBox(std::unique_ptr<weld::TreeView> xTreeView)
    : m_xImageProvider(new ImageProvider)
OTableTreeListBox::OTableTreeListBox(vcl::Window* pParent, bool bShowToggles)
    : InterimDBTreeListBox(pParent)
    , m_xImageProvider(new ImageProvider)
    , m_bVirtualRoot(false)
    , m_bNoEmptyFolders(false)
    , m_bShowToggles(true)
    , m_xTreeView(std::move(xTreeView))
    , m_bShowToggles(bShowToggles)
{
    m_xTreeView->enable_toggle_buttons(weld::ColumnToggleType::Check);
    if (m_bShowToggles)
        m_xTreeView->enable_toggle_buttons(weld::ColumnToggleType::Check);
}

void OTableTreeListBox::implSetDefaultImages()
OTableTreeListBox::~OTableTreeListBox()
{
    SetDefaultExpandedEntryBmp(  ImageProvider::getFolderImage( DatabaseObject::TABLE ) );
    SetDefaultCollapsedEntryBmp( ImageProvider::getFolderImage( DatabaseObject::TABLE ) );
}

bool  OTableTreeListBox::isFolderEntry( const SvTreeListEntry* _pEntry )
TableTreeListBox::TableTreeListBox(std::unique_ptr<weld::TreeView> xTreeView, bool bShowToggles)
    : TreeListBox(std::move(xTreeView))
    , m_xImageProvider(new ImageProvider)
    , m_bVirtualRoot(false)
    , m_bNoEmptyFolders(false)
    , m_bShowToggles(bShowToggles)
{
    sal_Int32 nEntryType = reinterpret_cast< sal_IntPtr >( _pEntry->GetUserData() );
    if (m_bShowToggles)
        m_xTreeView->enable_toggle_buttons(weld::ColumnToggleType::Check);
}

bool OTableTreeListBox::isFolderEntry(const weld::TreeIter& rEntry) const
{
    sal_Int32 nEntryType = m_xTreeView->get_id(rEntry).toInt32();
    return ( nEntryType == DatabaseObjectContainer::TABLES )
        ||  ( nEntryType == DatabaseObjectContainer::CATALOG )
        ||  ( nEntryType == DatabaseObjectContainer::SCHEMA );
}

void OTableTreeListBox::notifyHiContrastChanged()
{
    implSetDefaultImages();

    SvTreeListEntry* pEntryLoop = First();
    while (pEntryLoop)
    {
        size_t nCount = pEntryLoop->ItemCount();
        for (size_t i=0;i<nCount;++i)
        {
            SvLBoxItem& rItem = pEntryLoop->GetItem(i);
            if (rItem.GetType() == SvLBoxItemType::ContextBmp)
            {
                SvLBoxContextBmp& rContextBitmapItem = static_cast< SvLBoxContextBmp& >( rItem );

                Image aImage;
                if ( isFolderEntry( pEntryLoop ) )
                {
                    aImage = ImageProvider::getFolderImage( DatabaseObject::TABLE );
                }
                else
                {
                    OUString sCompleteName( getQualifiedTableName( pEntryLoop ) );
                    m_xImageProvider->getImages( sCompleteName, DatabaseObject::TABLE, aImage );
                }

                rContextBitmapItem.SetBitmap1( aImage );
                rContextBitmapItem.SetBitmap2( aImage );
                break;
            }
        }
        pEntryLoop = Next(pEntryLoop);
    }
}

void OTableTreeListBox::implOnNewConnection( const Reference< XConnection >& _rxConnection )
{
    m_xConnection = _rxConnection;
@@ -153,7 +104,7 @@ void TableTreeListBox::implOnNewConnection( const Reference< XConnection >& _rxC
    m_xImageProvider.reset( new ImageProvider( m_xConnection  ) );
}

void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConnection )
void OTableTreeListBox::UpdateTableList(const Reference<XConnection>& _rxConnection)
{
    Sequence< OUString > sTables, sViews;

@@ -324,7 +275,8 @@ void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConn
    implOnNewConnection( _rxConnection );

    // throw away all the old stuff
    Clear();
    m_xTreeView->clear();
    m_xTreeView->make_unsorted();

    try
    {
@@ -339,7 +291,15 @@ void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConn
                sRootEntryText  = DBA_RES(STR_ALL_VIEWS);
            else
                sRootEntryText  = DBA_RES(STR_ALL_TABLES_AND_VIEWS);
            InsertEntry( sRootEntryText, nullptr, false, TREELIST_APPEND, reinterpret_cast< void* >( DatabaseObjectContainer::TABLES ) );
            OUString sId(OUString::number(DatabaseObjectContainer::TABLES));
            OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
            std::unique_ptr<weld::TreeIter> xRet(m_xTreeView->make_iterator());
            m_xTreeView->insert(nullptr, -1, nullptr, &sId, nullptr, nullptr, false, xRet.get());
            m_xTreeView->set_image(*xRet, sImageId, -1);
            if (m_bShowToggles)
                m_xTreeView->set_toggle(*xRet, TRISTATE_FALSE);
            m_xTreeView->set_text(*xRet, sRootEntryText, 0);
            m_xTreeView->set_text_emphasis(*xRet, false, 0);
        }

        if ( _rTables.empty() )
@@ -370,12 +330,23 @@ void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConn
                    bCatalogs ? xMeta->getCatalogs() : xMeta->getSchemas(), 1 ) );
                sal_Int32 nFolderType = bCatalogs ? DatabaseObjectContainer::CATALOG : DatabaseObjectContainer::SCHEMA;

                SvTreeListEntry* pRootEntry = getAllObjectsEntry();
                OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);

                std::unique_ptr<weld::TreeIter> xRootEntry(getAllObjectsEntry());
                std::unique_ptr<weld::TreeIter> xRet(m_xTreeView->make_iterator());
                for (auto const& folderName : aFolderNames)
                {
                    SvTreeListEntry* pFolder = GetEntryPosByName( folderName, pRootEntry );
                    if ( !pFolder )
                        InsertEntry( folderName, pRootEntry, false, TREELIST_APPEND, reinterpret_cast< void* >( nFolderType ) );
                    std::unique_ptr<weld::TreeIter> xFolder(GetEntryPosByName(folderName, xRootEntry.get()));
                    if (!xFolder)
                    {
                        OUString sId(OUString::number(nFolderType));
                        m_xTreeView->insert(xRootEntry.get(), -1, nullptr, &sId, nullptr, nullptr, false, xRet.get());
                        m_xTreeView->set_image(*xRet, sImageId, -1);
                        if (m_bShowToggles)
                            m_xTreeView->set_toggle(*xRet, TRISTATE_FALSE);
                        m_xTreeView->set_text(*xRet, folderName, 0);
                        m_xTreeView->set_text_emphasis(*xRet, false, 0);
                    }
                }
            }
        }
@@ -384,11 +355,8 @@ void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConn
    {
        DBG_UNHANDLED_EXCEPTION("dbaccess");
    }
}

void TableTreeListBox::DisableCheckButtons()
{
    m_bShowToggles = false;
    m_xTreeView->make_sorted();
}

void TableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConnection, const TNames& _rTables )
@@ -480,15 +448,9 @@ void TableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConne
    m_xTreeView->make_sorted();
}

bool OTableTreeListBox::isWildcardChecked(SvTreeListEntry* _pEntry)
bool OTableTreeListBox::isWildcardChecked(const weld::TreeIter& rEntry)
{
    if (_pEntry)
    {
        OBoldListboxString* pTextItem = static_cast<OBoldListboxString*>(_pEntry->GetFirstItem(SvLBoxItemType::String));
        if (pTextItem)
            return pTextItem->isEmphasized();
    }
    return false;
    return m_xTreeView->get_text_emphasis(rEntry, 0);
}

bool TableTreeListBox::isWildcardChecked(const weld::TreeIter& rEntry)
@@ -496,10 +458,12 @@ bool TableTreeListBox::isWildcardChecked(const weld::TreeIter& rEntry)
    return m_xTreeView->get_text_emphasis(rEntry, 0);
}

void OTableTreeListBox::checkWildcard(SvTreeListEntry* _pEntry)
void OTableTreeListBox::checkWildcard(weld::TreeIter& rEntry)
{
    SetCheckButtonState(_pEntry, SvButtonState::Checked);
    checkedButton_noBroadcast(_pEntry);
    if (!m_bShowToggles)
        return;
    m_xTreeView->set_toggle(rEntry, TRISTATE_TRUE);
    checkedButton_noBroadcast(rEntry);
}

void TableTreeListBox::checkWildcard(weld::TreeIter& rEntry)
@@ -510,9 +474,14 @@ void TableTreeListBox::checkWildcard(weld::TreeIter& rEntry)
    checkedButton_noBroadcast(rEntry);
}

SvTreeListEntry* OTableTreeListBox::getAllObjectsEntry() const
std::unique_ptr<weld::TreeIter> OTableTreeListBox::getAllObjectsEntry() const
{
    return haveVirtualRoot() ? First() : nullptr;
    if (!haveVirtualRoot())
        return nullptr;
    auto xRet = m_xTreeView->make_iterator();
    if (!m_xTreeView->get_iter_first(*xRet))
        return nullptr;
    return xRet;
}

std::unique_ptr<weld::TreeIter> TableTreeListBox::getAllObjectsEntry() const
@@ -525,48 +494,61 @@ std::unique_ptr<weld::TreeIter> TableTreeListBox::getAllObjectsEntry() const
    return xRet;
}

void OTableTreeListBox::checkedButton_noBroadcast(SvTreeListEntry* _pEntry)
void OTableTreeListBox::checkedButton_noBroadcast(const weld::TreeIter& rEntry)
{
    SvButtonState eState = GetCheckButtonState( _pEntry);
    if (GetModel()->HasChildren(_pEntry)) // if it has children, check those too
    if (!m_bShowToggles)
        return;
    TriState eState = m_xTreeView->get_toggle(rEntry);
    OSL_ENSURE(TRISTATE_INDET != eState, "OTableTreeListBox::CheckButtonHdl: user action which lead to TRISTATE?");

    if (m_xTreeView->iter_has_child(rEntry)) // if it has children, check those too
    {
        SvTreeListEntry* pChildEntry = GetModel()->Next(_pEntry);
        SvTreeListEntry* pSiblingEntry = _pEntry->NextSibling();
        while(pChildEntry && pChildEntry != pSiblingEntry)
        std::unique_ptr<weld::TreeIter> xChildEntry(m_xTreeView->make_iterator(&rEntry));
        std::unique_ptr<weld::TreeIter> xSiblingEntry(m_xTreeView->make_iterator(&rEntry));
        bool bChildEntry = m_xTreeView->iter_next(*xChildEntry);
        bool bSiblingEntry = m_xTreeView->iter_next_sibling(*xSiblingEntry);
        while (bChildEntry && (!bSiblingEntry || !xChildEntry->equal(*xSiblingEntry)))
        {
            SetCheckButtonState(pChildEntry, eState);
            pChildEntry = GetModel()->Next(pChildEntry);
            m_xTreeView->set_toggle(*xChildEntry, eState);
            bChildEntry = m_xTreeView->iter_next(*xChildEntry);
        }
    }

    SvTreeListEntry* pEntry = IsSelected(_pEntry) ? FirstSelected() : nullptr;
    while(pEntry)
    if (m_xTreeView->is_selected(rEntry))
    {
        SetCheckButtonState(pEntry,eState);
        if(GetModel()->HasChildren(pEntry))   // if it has children, check those too
        {
            SvTreeListEntry* pChildEntry = GetModel()->Next(pEntry);
            SvTreeListEntry* pSiblingEntry = pEntry->NextSibling();
            while(pChildEntry && pChildEntry != pSiblingEntry)
        m_xTreeView->selected_foreach([this, eState](weld::TreeIter& rSelected){
            m_xTreeView->set_toggle(rSelected, eState);
            if (m_xTreeView->iter_has_child(rSelected)) // if it has children, check those too
            {
                SetCheckButtonState(pChildEntry,eState);
                pChildEntry = GetModel()->Next(pChildEntry);
                std::unique_ptr<weld::TreeIter> xChildEntry(m_xTreeView->make_iterator(&rSelected));
                std::unique_ptr<weld::TreeIter> xSiblingEntry(m_xTreeView->make_iterator(&rSelected));
                bool bChildEntry = m_xTreeView->iter_next(*xChildEntry);
                bool bSiblingEntry = m_xTreeView->iter_next_sibling(*xSiblingEntry);
                while (bChildEntry && (!bSiblingEntry || !xChildEntry->equal(*xSiblingEntry)))
                {
                    m_xTreeView->set_toggle(*xChildEntry, eState);
                    bChildEntry = m_xTreeView->iter_next(*xChildEntry);
                }
            }
        }
        pEntry = NextSelected(pEntry);
            return false;
        });
    }

    CheckButtons();

    // if an entry has children, it makes a difference if the entry is checked
    // because all children are checked or if the user checked it explicitly.
    // So we track explicit (un)checking
    implEmphasize(_pEntry, SvButtonState::Checked == eState);
    implEmphasize(rEntry, eState == TRISTATE_TRUE);
}

SvButtonState OTableTreeListBox::implDetermineState(SvTreeListEntry* _pEntry)
TriState OTableTreeListBox::implDetermineState(weld::TreeIter& rEntry)
{
    SvButtonState eState = GetCheckButtonState(_pEntry);
    if (!GetModel()->HasChildren(_pEntry))
    if (!m_bShowToggles)
        return TRISTATE_FALSE;

    TriState eState = m_xTreeView->get_toggle(rEntry);
    if (!m_xTreeView->iter_has_child(rEntry))
        // nothing to do in this bottom-up routine if there are no children ...
        return eState;

@@ -574,109 +556,76 @@ SvButtonState OTableTreeListBox::implDetermineState(SvTreeListEntry* _pEntry)
    sal_uInt16 nCheckedChildren = 0;
    sal_uInt16 nChildrenOverall = 0;

    SvTreeListEntry* pChildLoop = GetModel()->FirstChild(_pEntry);
    while (pChildLoop)
    std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(&rEntry));
    bool bChildLoop = m_xTreeView->iter_children(*xChild);
    while (bChildLoop)
    {
        SvButtonState eChildState = implDetermineState(pChildLoop);
        if (SvButtonState::Tristate == eChildState)
        TriState eChildState = implDetermineState(*xChild);
        if (eChildState == TRISTATE_INDET)
            break;

        if (SvButtonState::Checked == eChildState)
        if (eChildState == TRISTATE_TRUE)
            ++nCheckedChildren;
        ++nChildrenOverall;

        pChildLoop = pChildLoop->NextSibling();
        bChildLoop = m_xTreeView->iter_next_sibling(*xChild);
    }

    if (pChildLoop)
    if (bChildLoop)
    {
        // we did not finish the loop because at least one of the children is in tristate
        eState = SvButtonState::Tristate;
        eState = TRISTATE_INDET;

        // but this means that we did not finish all the siblings of pChildLoop,
        // so their checking may be incorrect at the moment
        // -> correct this
        while (pChildLoop)
        while (bChildLoop)
        {
            implDetermineState(pChildLoop);
            pChildLoop = pChildLoop->NextSibling();
            implDetermineState(*xChild);
            bChildLoop = m_xTreeView->iter_next_sibling(*xChild);
        }
    }
    else
    {
        // none if the children are in tristate
        if (nCheckedChildren)
        {
            // we have at least one child checked
            if (nCheckedChildren != nChildrenOverall)
            {
                // not all children are checked
                eState = SvButtonState::Tristate;
                eState = TRISTATE_INDET;
            }
            else
            {
                // all children are checked
                eState = SvButtonState::Checked;
                eState = TRISTATE_TRUE;
            }
        }
        else
        {
            // no children are checked
            eState = SvButtonState::Unchecked;
            eState = TRISTATE_FALSE;
        }
    }

    // finally set the entry to the state we just determined
    SetCheckButtonState(_pEntry, eState);
    m_xTreeView->set_toggle(rEntry, eState);

    return eState;
}

void OTableTreeListBox::CheckButtons()
{
    SvTreeListEntry* pEntry = GetModel()->First();
    while (pEntry)
    if (!m_bShowToggles)
        return;

    auto xEntry(m_xTreeView->make_iterator());
    if (!m_xTreeView->get_iter_first(*xEntry))
        return;

    do
    {
        implDetermineState(pEntry);
        pEntry = pEntry->NextSibling();
    }
}

void OTableTreeListBox::CheckButtonHdl()
{
    checkedButton_noBroadcast(GetHdlEntry());
    m_aCheckButtonHandler.Call(this);
}

void OTableTreeListBox::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& _rRect)
{
    if (!IsEnabled())
    {
        vcl::Font aOldFont = rRenderContext.GetFont();
        vcl::Font aNewFont(aOldFont);

        StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
        aNewFont.SetColor(aSystemStyle.GetDisableColor());

        rRenderContext.SetFont(aNewFont);
        DBTreeListBox::Paint(rRenderContext, _rRect);
        rRenderContext.SetFont(aOldFont);
    }
    else
        DBTreeListBox::Paint(rRenderContext, _rRect);
}

void OTableTreeListBox::KeyInput( const KeyEvent& rKEvt )
{
    // only if there are spaces
    if (rKEvt.GetKeyCode().GetCode() == KEY_SPACE && !rKEvt.GetKeyCode().IsShift() && !rKEvt.GetKeyCode().IsMod1())
    {
        SvTreeListEntry* pCurrentHandlerEntry = GetHdlEntry();
        if(pCurrentHandlerEntry)
        {
            SvButtonState eState = GetCheckButtonState( pCurrentHandlerEntry);
            if(eState == SvButtonState::Checked)
                SetCheckButtonState( pCurrentHandlerEntry, SvButtonState::Unchecked);
            else
                SetCheckButtonState( pCurrentHandlerEntry, SvButtonState::Checked);

            CheckButtonHdl();
        }
        else
            DBTreeListBox::KeyInput(rKEvt);
    }
    else
        DBTreeListBox::KeyInput(rKEvt);
        implDetermineState(*xEntry);
    } while (m_xTreeView->iter_next_sibling(*xEntry));
}

void TableTreeListBox::checkedButton_noBroadcast(const weld::TreeIter& rEntry)
@@ -727,41 +676,36 @@ void TableTreeListBox::checkedButton_noBroadcast(const weld::TreeIter& rEntry)
    implEmphasize(rEntry, eState == TRISTATE_TRUE);
}

void OTableTreeListBox::implEmphasize(SvTreeListEntry* _pEntry, bool _bChecked, bool _bUpdateDescendants, bool _bUpdateAncestors)
void OTableTreeListBox::implEmphasize(const weld::TreeIter& rEntry, bool _bChecked, bool _bUpdateDescendants, bool _bUpdateAncestors)
{
    OSL_ENSURE(_pEntry, "OTableTreeListBox::implEmphasize: invalid entry (NULL)!");

    // special emphasizing handling for the "all objects" entry
    bool bAllObjectsEntryAffected = haveVirtualRoot() && (getAllObjectsEntry() == _pEntry);
    if  (   GetModel()->HasChildren(_pEntry)              // the entry has children
        ||  bAllObjectsEntryAffected                    // or it is the "all objects" entry
    bool bAllObjectsEntryAffected = haveVirtualRoot() && (getAllObjectsEntry()->equal(rEntry));
    if  (   m_xTreeView->iter_has_child(rEntry) // the entry has children
        ||  bAllObjectsEntryAffected            // or it is the "all objects" entry
        )
    {
        OBoldListboxString* pTextItem = static_cast<OBoldListboxString*>(_pEntry->GetFirstItem(SvLBoxItemType::String));
        if (pTextItem)
            pTextItem->emphasize(_bChecked);

        if (bAllObjectsEntryAffected)
            InvalidateEntry(_pEntry);
        m_xTreeView->set_text_emphasis(rEntry, _bChecked, 0);
    }

    if (_bUpdateDescendants)
    {
        std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(&rEntry));
        // remove the mark for all children of the checked entry
        SvTreeListEntry* pChildLoop = FirstChild(_pEntry);
        while (pChildLoop)
        bool bChildLoop = m_xTreeView->iter_children(*xChild);
        while (bChildLoop)
        {
            if (GetModel()->HasChildren(pChildLoop))
                implEmphasize(pChildLoop, false, true, false);
            pChildLoop = pChildLoop->NextSibling();
            if (m_xTreeView->iter_has_child(*xChild))
                implEmphasize(*xChild, false, true, false);
            bChildLoop = m_xTreeView->iter_next_sibling(*xChild);
        }
    }

    if (_bUpdateAncestors)
    {
        std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rEntry));
        // remove the mark for all ancestors of the entry
        if (GetModel()->HasParent(_pEntry))
            implEmphasize(GetParent(_pEntry), false, false);
        if (m_xTreeView->iter_parent(*xParent))
            implEmphasize(*xParent, false, false);
    }
}

@@ -798,20 +742,7 @@ void TableTreeListBox::implEmphasize(const weld::TreeIter& rEntry, bool _bChecke
    }
}

void OTableTreeListBox::InitEntry(SvTreeListEntry* _pEntry, const OUString& _rString, const Image& _rCollapsedBitmap, const Image& _rExpandedBitmap)
{
    DBTreeListBox::InitEntry(_pEntry, _rString, _rCollapsedBitmap, _rExpandedBitmap);

    // replace the text item with our own one
    SvLBoxItem* pTextItem = _pEntry->GetFirstItem(SvLBoxItemType::String);
    OSL_ENSURE(pTextItem, "OTableTreeListBox::InitEntry: no text item!?");
    size_t nTextPos = _pEntry->GetPos(pTextItem);
    OSL_ENSURE(SvTreeListEntry::ITEM_NOT_FOUND != nTextPos, "OTableTreeListBox::InitEntry: no text item pos!");

    _pEntry->ReplaceItem(std::make_unique<OBoldListboxString>(_rString), nTextPos);
}

SvTreeListEntry* OTableTreeListBox::implAddEntry(
std::unique_ptr<weld::TreeIter> OTableTreeListBox::implAddEntry(
        const Reference< XDatabaseMetaData >& _rxMeta,
        const OUString& _rTableName,
        bool _bCheckName
@@ -825,7 +756,7 @@ SvTreeListEntry* OTableTreeListBox::implAddEntry(
    OUString sCatalog, sSchema, sName;
    qualifiedNameComponents( _rxMeta, _rTableName, sCatalog, sSchema, sName, ::dbtools::EComposeRule::InDataManipulation );

    SvTreeListEntry* pParentEntry = getAllObjectsEntry();
    std::unique_ptr<weld::TreeIter> xParentEntry(getAllObjectsEntry());

    // if the DB uses catalog at the start of identifiers, then our hierarchy is
    //   catalog
@@ -843,32 +774,62 @@ SvTreeListEntry* OTableTreeListBox::implAddEntry(

    if ( !rFirstName.isEmpty() )
    {
        SvTreeListEntry* pFolder = GetEntryPosByName( rFirstName, pParentEntry );
        if ( !pFolder )
            pFolder = InsertEntry( rFirstName, pParentEntry, false, TREELIST_APPEND, reinterpret_cast< void* >( nFirstFolderType ) );
        pParentEntry = pFolder;
        std::unique_ptr<weld::TreeIter> xFolder(GetEntryPosByName(rFirstName, xParentEntry.get()));
        if (!xFolder)
        {
            xFolder = m_xTreeView->make_iterator();
            OUString sId(OUString::number(nFirstFolderType));
            OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
            m_xTreeView->insert(xParentEntry.get(), -1, nullptr, &sId, nullptr, nullptr, false, xFolder.get());
            m_xTreeView->set_image(*xFolder, sImageId, -1);
            if (m_bShowToggles)
                m_xTreeView->set_toggle(*xFolder, TRISTATE_FALSE);
            m_xTreeView->set_text(*xFolder, rFirstName, 0);
            m_xTreeView->set_text_emphasis(*xFolder, false, 0);
        }
        xParentEntry = std::move(xFolder);
    }

    if ( !rSecondName.isEmpty() )
    {
        SvTreeListEntry* pFolder = GetEntryPosByName( rSecondName, pParentEntry );
        if ( !pFolder )
            pFolder = InsertEntry( rSecondName, pParentEntry, false, TREELIST_APPEND, reinterpret_cast< void* >( nSecondFolderType ) );
        pParentEntry = pFolder;
        std::unique_ptr<weld::TreeIter> xFolder(GetEntryPosByName(rSecondName, xParentEntry.get()));
        if (!xFolder)
        {
            xFolder = m_xTreeView->make_iterator();
            OUString sId(OUString::number(nSecondFolderType));
            OUString sImageId = ImageProvider::getFolderImageId(DatabaseObject::TABLE);
            m_xTreeView->insert(xParentEntry.get(), -1, nullptr, &sId, nullptr, nullptr, false, xFolder.get());
            m_xTreeView->set_image(*xFolder, sImageId, -1);
            if (m_bShowToggles)
                m_xTreeView->set_toggle(*xFolder, TRISTATE_FALSE);
            m_xTreeView->set_text(*xFolder, rSecondName, 0);
            m_xTreeView->set_text_emphasis(*xFolder, false, 0);
        }
        xParentEntry = std::move(xFolder);
    }

    SvTreeListEntry* pRet = nullptr;
    if ( !_bCheckName || !GetEntryPosByName( sName, pParentEntry ) )
    if (!_bCheckName || !GetEntryPosByName(sName, xParentEntry.get()))
    {
        pRet = InsertEntry( sName, pParentEntry );
        std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
        m_xTreeView->insert(xParentEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xEntry.get());

        Image aImage;
        m_xImageProvider->getImages( _rTableName, DatabaseObject::TABLE, aImage );
        auto xGraphic = m_xImageProvider->getXGraphic(_rTableName, DatabaseObject::TABLE);
        if (xGraphic.is())
            m_xTreeView->set_image(*xEntry, xGraphic, -1);
        else
        {
            OUString sImageId(m_xImageProvider->getImageId(_rTableName, DatabaseObject::TABLE));
            m_xTreeView->set_image(*xEntry, sImageId, -1);
        }
        if (m_bShowToggles)
            m_xTreeView->set_toggle(*xEntry, TRISTATE_FALSE);
        m_xTreeView->set_text(*xEntry, sName, 0);
        m_xTreeView->set_text_emphasis(*xEntry, false, 0);

        SetExpandedEntryBmp( pRet, aImage );
        SetCollapsedEntryBmp( pRet, aImage );
        return xEntry;
    }
    return pRet;

    return nullptr;
}

void TableTreeListBox::implAddEntry(
@@ -957,11 +918,11 @@ void TableTreeListBox::implAddEntry(
    }
}

NamedDatabaseObject OTableTreeListBox::describeObject( SvTreeListEntry* _pEntry )
NamedDatabaseObject OTableTreeListBox::describeObject(weld::TreeIter& rEntry)
{
    NamedDatabaseObject aObject;

    sal_Int32 nEntryType = reinterpret_cast< sal_IntPtr >( _pEntry->GetUserData() );
    sal_Int32 nEntryType = m_xTreeView->get_id(rEntry).toInt32();

    if  ( nEntryType == DatabaseObjectContainer::TABLES )
    {
@@ -976,19 +937,19 @@ NamedDatabaseObject OTableTreeListBox::describeObject( SvTreeListEntry* _pEntry 
    else
    {
        aObject.Type = DatabaseObject::TABLE;
        aObject.Name = getQualifiedTableName( _pEntry );
        aObject.Name = getQualifiedTableName(rEntry);
    }

    return aObject;
}

SvTreeListEntry* OTableTreeListBox::addedTable( const OUString& _rName )
std::unique_ptr<weld::TreeIter> OTableTreeListBox::addedTable(const OUString& rName)
{
    try
    {
        Reference< XDatabaseMetaData > xMeta;
        if ( impl_getAndAssertMetaData( xMeta ) )
            return implAddEntry( xMeta, _rName );
            return implAddEntry( xMeta, rName );
    }
    catch( const Exception& )
    {
@@ -1005,9 +966,9 @@ bool OTableTreeListBox::impl_getAndAssertMetaData( Reference< XDatabaseMetaData 
    return _out_rMetaData.is();
}

OUString OTableTreeListBox::getQualifiedTableName( SvTreeListEntry* _pEntry ) const
OUString OTableTreeListBox::getQualifiedTableName(weld::TreeIter& rEntry) const
{
    OSL_PRECOND( !isFolderEntry( _pEntry ), "OTableTreeListBox::getQualifiedTableName: folder entries not allowed here!" );
    OSL_PRECOND( !isFolderEntry(rEntry), "OTableTreeListBox::getQualifiedTableName: folder entries not allowed here!" );

    try
    {
@@ -1019,27 +980,29 @@ OUString OTableTreeListBox::getQualifiedTableName( SvTreeListEntry* _pEntry ) co
        OUString sSchema;
        OUString sTable;

        SvTreeListEntry* pSchema = GetParent( _pEntry );
        if ( pSchema )
        std::unique_ptr<weld::TreeIter> xSchema(m_xTreeView->make_iterator(&rEntry));
        bool bSchema = m_xTreeView->iter_parent(*xSchema);
        if (bSchema)
        {
            SvTreeListEntry* pCatalog = GetParent( pSchema );
            if  (   pCatalog
            std::unique_ptr<weld::TreeIter> xCatalog(m_xTreeView->make_iterator(xSchema.get()));
            bool bCatalog = m_xTreeView->iter_parent(*xCatalog);
            if  (   bCatalog
                ||  (   xMeta->supportsCatalogsInDataManipulation()
                    &&  !xMeta->supportsSchemasInDataManipulation()
                    )   // here we support catalog but no schema
                )
            {
                if ( pCatalog == nullptr )
                if (!bCatalog)
                {
                    pCatalog = pSchema;
                    pSchema = nullptr;
                    xCatalog = std::move(xSchema);
                    bSchema = false;
                }
                sCatalog = GetEntryText( pCatalog );
                sCatalog = m_xTreeView->get_text(*xCatalog);
            }
            if ( pSchema )
                sSchema = GetEntryText(pSchema);
            if (bSchema)
                sSchema = m_xTreeView->get_text(*xSchema);
        }
        sTable = GetEntryText( _pEntry );
        sTable = m_xTreeView->get_text(rEntry);

        return ::dbtools::composeTableName( xMeta, sCatalog, sSchema, sTable, false, ::dbtools::EComposeRule::InDataManipulation );
    }
@@ -1050,7 +1013,7 @@ OUString OTableTreeListBox::getQualifiedTableName( SvTreeListEntry* _pEntry ) co
    return OUString();
}

SvTreeListEntry* OTableTreeListBox::getEntryByQualifiedName( const OUString& _rName )
std::unique_ptr<weld::TreeIter> OTableTreeListBox::getEntryByQualifiedName(const OUString& rName)
{
    try
    {
@@ -1060,26 +1023,26 @@ SvTreeListEntry* OTableTreeListBox::getEntryByQualifiedName( const OUString& _rN

        // split the complete name into its components
        OUString sCatalog, sSchema, sName;
        qualifiedNameComponents(xMeta, _rName, sCatalog, sSchema, sName,::dbtools::EComposeRule::InDataManipulation);
        qualifiedNameComponents(xMeta, rName, sCatalog, sSchema, sName,::dbtools::EComposeRule::InDataManipulation);

        SvTreeListEntry* pParent = getAllObjectsEntry();
        SvTreeListEntry* pCat = nullptr;
        SvTreeListEntry* pSchema = nullptr;
        if ( !sCatalog.isEmpty() )
        std::unique_ptr<weld::TreeIter> xParent(getAllObjectsEntry());
        std::unique_ptr<weld::TreeIter> xCat;
        std::unique_ptr<weld::TreeIter> xSchema;
        if (!sCatalog.isEmpty())
        {
            pCat = GetEntryPosByName(sCatalog, pParent);
            if ( pCat )
                pParent = pCat;
            xCat = GetEntryPosByName(sCatalog);
            if (xCat)
                xParent = std::move(xCat);
        }

        if ( !sSchema.isEmpty() )
        if (!sSchema.isEmpty())
        {
            pSchema = GetEntryPosByName(sSchema, pParent);
            if ( pSchema )
                pParent = pSchema;
            xSchema = GetEntryPosByName(sSchema, xParent.get());
            if (xSchema)
                xParent = std::move(xSchema);
        }

        return GetEntryPosByName(sName, pParent);
        return GetEntryPosByName(sName, xParent.get());
    }
    catch( const Exception& )
    {
@@ -1088,13 +1051,13 @@ SvTreeListEntry* OTableTreeListBox::getEntryByQualifiedName( const OUString& _rN
    return nullptr;
}

void OTableTreeListBox::removedTable( const OUString& _rName )
void OTableTreeListBox::removedTable(const OUString& rName)
{
    try
    {
        SvTreeListEntry* pEntry = getEntryByQualifiedName( _rName );
        if ( pEntry )
            GetModel()->Remove( pEntry );
        std::unique_ptr<weld::TreeIter> xEntry = getEntryByQualifiedName(rName);
        if (xEntry)
            m_xTreeView->remove(*xEntry);
    }
    catch( const Exception& )
    {
@@ -1102,27 +1065,6 @@ void OTableTreeListBox::removedTable( const OUString& _rName )
    }
}

std::unique_ptr<weld::TreeIter> TableTreeListBox::GetEntryPosByName(const OUString& aName, const weld::TreeIter* pStart, const IEntryFilter* _pFilter) const
{
    auto xEntry(m_xTreeView->make_iterator(pStart));
    if (!pStart && !m_xTreeView->get_iter_first(*xEntry))
        return nullptr;

    do
    {
        if (m_xTreeView->get_text(*xEntry) == aName)
        {
            if (!_pFilter || _pFilter->includeEntry(reinterpret_cast<void*>(m_xTreeView->get_id(*xEntry).toUInt64())))
            {
                // found
                return xEntry;
            }
        }
    } while (m_xTreeView->iter_next(*xEntry));

    return nullptr;
}

void TableTreeListBox::CheckButtons()
{
    if (!m_bShowToggles)
diff --git a/dbaccess/source/ui/dlg/adtabdlg.cxx b/dbaccess/source/ui/dlg/adtabdlg.cxx
index 35e29ed..485bb39 100644
--- a/dbaccess/source/ui/dlg/adtabdlg.cxx
+++ b/dbaccess/source/ui/dlg/adtabdlg.cxx
@@ -335,7 +335,8 @@ OAddTableDlg::OAddTableDlg(weld::Window* pParent, IAddTableDialogContext& _rCont
   , m_rContext(_rContext)
   , m_xCaseTables(m_xBuilder->weld_radio_button("tables"))
   , m_xCaseQueries(m_xBuilder->weld_radio_button("queries"))
   , m_xTableList(new TableTreeListBox(m_xBuilder->weld_tree_view("tablelist")))
   // false means: do not show any buttons
   , m_xTableList(new TableTreeListBox(m_xBuilder->weld_tree_view("tablelist"), false))
   , m_xQueryList(m_xBuilder->weld_tree_view("querylist"))
   , m_xAddButton(m_xBuilder->weld_button("add"))
   , m_xCloseButton(m_xBuilder->weld_button("close"))
@@ -356,7 +357,6 @@ OAddTableDlg::OAddTableDlg(weld::Window* pParent, IAddTableDialogContext& _rCont
    m_xQueryList->connect_changed( LINK( this, OAddTableDlg, TableListSelectHdl ) );

    rTableList.set_selection_mode(SelectionMode::Single);
    m_xTableList->DisableCheckButtons(); // do not show any buttons
    m_xTableList->SuppressEmptyFolders();

    m_xQueryList->set_selection_mode(SelectionMode::Single);
diff --git a/dbaccess/source/ui/dlg/tablespage.cxx b/dbaccess/source/ui/dlg/tablespage.cxx
index 2fa7195..3440b90 100644
--- a/dbaccess/source/ui/dlg/tablespage.cxx
+++ b/dbaccess/source/ui/dlg/tablespage.cxx
@@ -55,7 +55,7 @@ namespace dbaui
        , m_bCatalogAtStart(true)
        , m_pTablesDlg(pTablesDlg)
        , m_xTables(m_xBuilder->weld_widget("TablesFilterPage"))
        , m_xTablesList(new TableTreeListBox(m_xBuilder->weld_tree_view("treeview")))
        , m_xTablesList(new TableTreeListBox(m_xBuilder->weld_tree_view("treeview"), true))
    {
        m_xTablesList->init();

diff --git a/dbaccess/source/ui/inc/callbacks.hxx b/dbaccess/source/ui/inc/callbacks.hxx
index 8a607db..e18a655 100644
--- a/dbaccess/source/ui/inc/callbacks.hxx
+++ b/dbaccess/source/ui/inc/callbacks.hxx
@@ -31,6 +31,11 @@ struct ExecuteDropEvent;

namespace comphelper { class OInterfaceContainerHelper2; }

namespace weld
{
    class TreeIter;
}

namespace dbaui
{

@@ -43,11 +48,13 @@ namespace dbaui
            @return <FALSE/> if the default quick help text should be used
        */
        virtual bool    requestQuickHelp( const SvTreeListEntry* _pEntry, OUString& _rText ) const = 0;
        virtual bool    requestQuickHelp(const void* pUserData, OUString& rText) const = 0;

        /** handler for StartDrag requests
            @return <TRUE/> if a drag operation was started
        */
        virtual bool    requestDrag( const Point& _rPosPixel ) = 0;
        virtual bool    requestDrag(const Point& _rPosPixel) = 0;
        virtual bool    requestDrag(const weld::TreeIter& rEntry) = 0;

        /** check whether or not a drop request should be accepted
        */
@@ -69,7 +76,7 @@ namespace dbaui

            Supposed to be a valid name from uiconfig/<module>/popupmenu folder.
        */
        virtual OUString getContextMenuResourceName( Control& _rControl ) const = 0;
        virtual OUString getContextMenuResourceName() const = 0;

        /** returns the controller which is responsible for providing states of certain features,
            and executing them.
diff --git a/dbaccess/source/ui/inc/dbtreelistbox.hxx b/dbaccess/source/ui/inc/dbtreelistbox.hxx
index f79abe8..70b891f 100644
--- a/dbaccess/source/ui/inc/dbtreelistbox.hxx
+++ b/dbaccess/source/ui/inc/dbtreelistbox.hxx
@@ -23,8 +23,10 @@

#include <com/sun/star/frame/XPopupMenuController.hpp>

#include <vcl/InterimItemWindow.hxx>
#include <vcl/treelistbox.hxx>
#include <vcl/timer.hxx>
#include <vcl/weld.hxx>

#include <memory>
#include <set>
@@ -133,6 +135,88 @@ namespace dbaui
    protected:
        using SvTreeListBox::ExecuteDrop;
    };

    class TreeListBox;

    class TreeListBoxDropTarget : public DropTargetHelper
    {
    private:
        TreeListBox& m_rTreeView;

        virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override;
        virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override;

    public:
        TreeListBoxDropTarget(TreeListBox& rTreeView);
    };

    class TreeListBox
    {
    protected:
        std::unique_ptr<weld::TreeView> m_xTreeView;
        TreeListBoxDropTarget m_aDropTargetHelper;

        std::unique_ptr<weld::TreeIter> m_xDragedEntry;
        IControlActionListener*     m_pActionListener;
        IContextMenuProvider*       m_pContextMenuProvider;

        DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
        DECL_LINK(SelectHdl, weld::TreeView&, void);
        DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString);
        DECL_LINK(CommandHdl, const CommandEvent&, bool);
        DECL_LINK(DragBeginHdl, bool&, bool);

    private:
        Timer                       m_aTimer; // is needed for table updates

        Link<LinkParamNone*,void>   m_aSelChangeHdl;        // handler to be called (asynchronously) when the selection changes in any way
        Link<LinkParamNone*,void>   m_aCopyHandler;         // called when someone press CTRL+C
        Link<LinkParamNone*,void>   m_aPasteHandler;        // called when someone press CTRL+V
        Link<LinkParamNone*,void>   m_aDeleteHandler;       // called when someone press DELETE Key

        DECL_LINK(OnTimeOut, Timer*, void);

    protected:
        void implStopSelectionTimer();
        void implStartSelectionTimer();

        virtual bool DoChildKeyInput(const KeyEvent& rKEvt);
        virtual bool DoContextMenu(const CommandEvent& rCEvt);

    public:
        TreeListBox(std::unique_ptr<weld::TreeView> xTreeView);
        virtual ~TreeListBox();

        std::unique_ptr<weld::TreeIter> GetEntryPosByName(const OUString& rName,
                                                          const weld::TreeIter* pStart = nullptr,
                                                          const IEntryFilter* pFilter = nullptr) const;

        void setControlActionListener(IControlActionListener* pListener) { m_pActionListener = pListener; }
        void setContextMenuProvider(IContextMenuProvider* pContextMenuProvider) { m_pContextMenuProvider = pContextMenuProvider; }

        weld::TreeView& GetWidget() { return *m_xTreeView; }
        const weld::TreeView& GetWidget() const { return *m_xTreeView; }

        sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt);
        sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt);

        void    SetSelChangeHdl( const Link<LinkParamNone*,void>& _rHdl )      { m_aSelChangeHdl = _rHdl; }
        void    setCopyHandler(const Link<LinkParamNone*,void>& _rHdl)         { m_aCopyHandler = _rHdl; }
        void    setPasteHandler(const Link<LinkParamNone*,void>& _rHdl)        { m_aPasteHandler = _rHdl; }
        void    setDeleteHandler(const Link<LinkParamNone*,void>& _rHdl)       { m_aDeleteHandler = _rHdl; }
    };

    class InterimDBTreeListBox : public InterimItemWindow
                               , public TreeListBox
    {
    public:
        InterimDBTreeListBox(vcl::Window* pParent);
        virtual void dispose() override;
        virtual ~InterimDBTreeListBox() override;
    protected:
        virtual bool DoChildKeyInput(const KeyEvent& rKEvt) override;
        virtual bool DoContextMenu(const CommandEvent& rCEvt) override;
    };
}

#endif // INCLUDED_DBACCESS_SOURCE_UI_INC_DBTREELISTBOX_HXX
diff --git a/dbaccess/source/ui/inc/tabletree.hxx b/dbaccess/source/ui/inc/tabletree.hxx
index 97b1ba7..53e4259 100644
--- a/dbaccess/source/ui/inc/tabletree.hxx
+++ b/dbaccess/source/ui/inc/tabletree.hxx
@@ -26,43 +26,36 @@
#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
#include <com/sun/star/sdbc/XConnection.hpp>
#include <com/sun/star/sdb/application/NamedDatabaseObject.hpp>
#include <vcl/weld.hxx>
#include <memory>

namespace dbaui
{

// OTableTreeListBox
class OTableTreeListBox final : public DBTreeListBox
class OTableTreeListBox final : public InterimDBTreeListBox
{
    std::unique_ptr<SvLBoxButtonData> m_pCheckButton;
    Link<void*,void>    m_aCheckButtonHandler;

    css::uno::Reference< css::sdbc::XConnection >
                    m_xConnection;      // the connection we're working for, set in implOnNewConnection, called by UpdateTableList
    std::unique_ptr< ImageProvider >
                    m_xImageProvider;   // provider for our images
    bool            m_bVirtualRoot;     // should the first entry be visible
    bool            m_bNoEmptyFolders;  // should empty catalogs/schematas be prevented from being displayed?
    bool            m_bShowToggles;     // show toggle buttons

public:
    OTableTreeListBox(vcl::Window* pParent, WinBits nWinStyle);
    virtual void dispose() override;
    OTableTreeListBox(vcl::Window* pParent, bool bShowToggles);
    virtual ~OTableTreeListBox();

    void init() { m_bVirtualRoot = true; }

    typedef std::pair< OUString, bool > TTableViewName;
    typedef std::vector< TTableViewName >         TNames;

    void    suppressEmptyFolders() { m_bNoEmptyFolders = true; }

    /** call when HiContrast change.
    */
    void notifyHiContrastChanged();
    void    SuppressEmptyFolders() { m_bNoEmptyFolders = true; }

    /** determines whether the given entry denotes a tables folder
    */
    static bool isFolderEntry( const SvTreeListEntry* _pEntry );
    bool isFolderEntry(const weld::TreeIter& rEntry) const;

    /** fill the table list with the tables belonging to the connection described by the parameters
        @param _rxConnection
@@ -87,28 +80,21 @@ public:
                const css::uno::Sequence< OUString>& _rViews
            );

    /** returns a NamedDatabaseObject record which describes the given entry
    std::unique_ptr<weld::TreeIter>    getAllObjectsEntry() const;

    /** does a wildcard check of the given entry
        <p>There are two different 'checked' states: If the user checks all children of an entry, this is different
        from checking the entry itself. The second is called 'wildcard' checking, 'cause in the resulting
        table filter it's represented by a wildcard.</p>
    */
    css::sdb::application::NamedDatabaseObject
            describeObject( SvTreeListEntry* _pEntry );
    void            checkWildcard(weld::TreeIter& rEntry);

    /** to be used if a foreign instance added a table
    /** determine if the given entry is 'wildcard checked'
        @see checkWildcard
    */
    SvTreeListEntry* addedTable( const OUString& _rName );
    bool            isWildcardChecked(const weld::TreeIter& rEntry);

    /** to be used if a foreign instance removed a table
    */
    void    removedTable( const OUString& _rName );

    /** returns the fully qualified name of a table entry
        @param _pEntry
            the entry whose name is to be obtained. Must not denote a folder entry.
    */
    OUString getQualifiedTableName( SvTreeListEntry* _pEntry ) const;

    SvTreeListEntry*    getEntryByQualifiedName( const OUString& _rName );

    SvTreeListEntry*    getAllObjectsEntry() const;
    void            CheckButtons();     // make the button states consistent (bottom-up)

    /** does a wildcard check of the given entry
        <p>There are two different 'checked' states: If the user checks all children of an entry, this is different
@@ -123,32 +109,29 @@ public:
    static bool     isWildcardChecked(SvTreeListEntry* pEntry);

private:
    virtual void InitEntry(SvTreeListEntry* _pEntry, const OUString& _rString, const Image& _rCollapsedBitmap, const Image& _rExpandedBitmap) override;
    void CheckButtonHdl();

    virtual void CheckButtonHdl() override;
    void checkedButton_noBroadcast(SvTreeListEntry* _pEntry);
    void checkedButton_noBroadcast(const weld::TreeIter& rEntry);

    void implEmphasize(SvTreeListEntry* _pEntry, bool _bChecked, bool _bUpdateDescendants = true, bool _bUpdateAncestors = true);
    void implEmphasize(const weld::TreeIter& rEntry, bool _bChecked, bool _bUpdateDescendants = true, bool _bUpdateAncestors = true);

    /** adds the given entry to our list
        @precond
            our image provider must already have been reset to the connection to which the meta data
            belong.
    */
    SvTreeListEntry* implAddEntry(
    std::unique_ptr<weld::TreeIter> implAddEntry(
            const css::uno::Reference< css::sdbc::XDatabaseMetaData >& _rxMeta,
            const OUString& _rTableName,
            bool _bCheckName = true
            const OUString& _rTableName, bool _bCheckName = true
        );

    void    implSetDefaultImages();

    void    implOnNewConnection( const css::uno::Reference< css::sdbc::XConnection >& _rxConnection );

    bool    impl_getAndAssertMetaData( css::uno::Reference< css::sdbc::XDatabaseMetaData >& _out_rMetaData ) const;

    bool haveVirtualRoot() const { return m_bVirtualRoot; }

public:
    /** fill the table list with the tables and views determined by the two given containers
        @param      _rxConnection   the connection where you got the object names from. Must not be NULL.
                                    Used to split the full qualified names into its parts.
@@ -159,21 +142,32 @@ private:
                const TNames& _rTables
            );

    void InitButtonData();
    /** returns a NamedDatabaseObject record which describes the given entry
    */
    css::sdb::application::NamedDatabaseObject
            describeObject(weld::TreeIter& rEntry);

    /// the handler given is called whenever the check state of one or more items changed
    void SetCheckHandler(const Link<void*,void>& _rHdl) { m_aCheckButtonHandler = _rHdl; }
    /** to be used if a foreign instance added a table
    */
    std::unique_ptr<weld::TreeIter> addedTable(const OUString& rName);

    SvButtonState   implDetermineState(SvTreeListEntry* _pEntry);
    /** to be used if a foreign instance removed a table
    */
    void    removedTable( const OUString& _rName );

    TriState implDetermineState(weld::TreeIter& rEntry);
        // determines the check state of the given entry, by analyzing the states of all descendants

    void            CheckButtons();     // make the button states consistent (bottom-up)
    /** returns the fully qualified name of a table entry
        @param _pEntry
            the entry whose name is to be obtained. Must not denote a folder entry.
    */
    OUString getQualifiedTableName(weld::TreeIter& rEntry) const;

    virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& _rRect) override;
    virtual void    KeyInput( const KeyEvent& rKEvt ) override;
    std::unique_ptr<weld::TreeIter> getEntryByQualifiedName(const OUString& rName);
};

class TableTreeListBox
class TableTreeListBox : public TreeListBox
{
    css::uno::Reference< css::sdbc::XConnection >
                    m_xConnection;      // the connection we're working for, set in implOnNewConnection, called by UpdateTableList
@@ -182,12 +176,9 @@ class TableTreeListBox
    bool            m_bVirtualRoot;     // should the first entry be visible
    bool            m_bNoEmptyFolders;  // should empty catalogs/schematas be prevented from being displayed?
    bool            m_bShowToggles;     // show toggle buttons
    std::unique_ptr<weld::TreeView> m_xTreeView;

public:
    TableTreeListBox(std::unique_ptr<weld::TreeView> xTreeView);

    weld::TreeView& GetWidget() { return *m_xTreeView; }
    TableTreeListBox(std::unique_ptr<weld::TreeView> xTreeView, bool bShowToggles);

    void init() { m_bVirtualRoot = true; }

@@ -195,7 +186,6 @@ public:
    typedef std::vector< TTableViewName >         TNames;

    void    SuppressEmptyFolders() { m_bNoEmptyFolders = true; }
    void    DisableCheckButtons();

    /** determines whether the given entry denotes a tables folder
    */
@@ -231,7 +221,7 @@ public:

    /** to be used if a foreign instance added a table
    */
    SvTreeListEntry* addedTable( const OUString& _rName );
    std::unique_ptr<weld::TreeIter> addedTable( const OUString& _rName );

    /** to be used if a foreign instance removed a table
    */
@@ -259,8 +249,6 @@ public:
    */
    bool            isWildcardChecked(const weld::TreeIter& rEntry);

    std::unique_ptr<weld::TreeIter> GetEntryPosByName(const OUString& aName, const weld::TreeIter* pStart = nullptr, const IEntryFilter* _pFilter = nullptr) const;

    void            CheckButtons();     // make the button states consistent (bottom-up)

    void            checkedButton_noBroadcast(const weld::TreeIter& rEntry);
@@ -284,6 +272,7 @@ private:

    bool haveVirtualRoot() const { return m_bVirtualRoot; }

public:
    /** fill the table list with the tables and views determined by the two given containers
        @param      _rxConnection   the connection where you got the object names from. Must not be NULL.
                                    Used to split the full qualified names into its parts.
@@ -293,6 +282,17 @@ private:
                const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
                const TNames& _rTables
            );

    /** returns a NamedDatabaseObject record which describes the given entry
    */
    css::sdb::application::NamedDatabaseObject
            describeObject(weld::TreeIter& rEntry);

    /** returns the fully qualified name of a table entry
        @param _pEntry
            the entry whose name is to be obtained. Must not denote a folder entry.
    */
    OUString getQualifiedTableName(weld::TreeIter& rEntry) const;
};

}   // namespace dbaui
diff --git a/dbaccess/source/ui/inc/unodatbr.hxx b/dbaccess/source/ui/inc/unodatbr.hxx
index 498b634..810586a 100644
--- a/dbaccess/source/ui/inc/unodatbr.hxx
+++ b/dbaccess/source/ui/inc/unodatbr.hxx
@@ -214,12 +214,14 @@ namespace dbaui

        // IControlActionListener overridables
        virtual bool        requestQuickHelp( const SvTreeListEntry* _pEntry, OUString& _rText ) const override;
        virtual bool        requestQuickHelp(const void* pUserData, OUString& rText) const override;
        virtual bool        requestDrag( const Point& _rPosPixel ) override;
        virtual bool        requestDrag(const weld::TreeIter& rEntry) override;
        virtual sal_Int8    queryDrop( const AcceptDropEvent& _rEvt, const DataFlavorExVector& _rFlavors ) override;
        virtual sal_Int8    executeDrop( const ExecuteDropEvent& _rEvt ) override;

        // IContextMenuProvider
        virtual OUString          getContextMenuResourceName( Control& _rControl ) const override;
        virtual OUString          getContextMenuResourceName() const override;
        virtual IController&      getCommandController() override;
        virtual ::comphelper::OInterfaceContainerHelper2*
                                  getContextMenuInterceptors() override;
diff --git a/dbaccess/source/ui/querydesign/QTableWindow.cxx b/dbaccess/source/ui/querydesign/QTableWindow.cxx
index 754c6e1..cc70e12 100644
--- a/dbaccess/source/ui/querydesign/QTableWindow.cxx
+++ b/dbaccess/source/ui/querydesign/QTableWindow.cxx
@@ -30,7 +30,6 @@
#include <com/sun/star/sdbc/SQLException.hpp>
#include "TableFieldInfo.hxx"
#include <comphelper/stl_types.hxx>
#include <vcl/treelistentry.hxx>
#include <comphelper/types.hxx>

using namespace ::com::sun::star::sdbc;
diff --git a/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx b/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx
index 2b23a3e..1e00cc9b 100644
--- a/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx
+++ b/dbaccess/source/ui/querydesign/SelectionBrowseBox.cxx
@@ -42,7 +42,6 @@
#include <o3tl/safeint.hxx>
#include <osl/diagnose.h>
#include <i18nlangtag/languagetag.hxx>
#include <vcl/treelistentry.hxx>
#include <vcl/commandevent.hxx>
#include <vcl/svapp.hxx>

diff --git a/dbaccess/source/ui/querydesign/TableWindow.cxx b/dbaccess/source/ui/querydesign/TableWindow.cxx
index f7ec40c..02f45af 100644
--- a/dbaccess/source/ui/querydesign/TableWindow.cxx
+++ b/dbaccess/source/ui/querydesign/TableWindow.cxx
@@ -39,8 +39,8 @@
#include <bitmaps.hlst>
#include <TableWindowAccess.hxx>
#include <connectivity/dbtools.hxx>
#include <vcl/treelistentry.hxx>
#include <vcl/builder.hxx>
#include <vcl/menu.hxx>

using namespace dbaui;
using namespace ::utl;
diff --git a/dbaccess/uiconfig/ui/dbtreelist.ui b/dbaccess/uiconfig/ui/dbtreelist.ui
new file mode 100644
index 0000000..042e770
--- /dev/null
+++ b/dbaccess/uiconfig/ui/dbtreelist.ui
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<interface domain="dba">
  <requires lib="gtk+" version="3.18"/>
  <object class="GtkTreeStore" id="liststore1">
    <columns>
      <!-- column-name expander -->
      <column type="GdkPixbuf"/>
      <!-- column-name check1 -->
      <column type="gboolean"/>
      <!-- column-name text -->
      <column type="gchararray"/>
      <!-- column-name id -->
      <column type="gchararray"/>
      <!-- column-name checkvis1 -->
      <column type="gboolean"/>
      <!-- column-name checktri1 -->
      <column type="gboolean"/>
      <!-- column-name weight1 -->
      <column type="gint"/>
    </columns>
  </object>
  <object class="GtkBox" id="DBTreeList">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="hexpand">True</property>
    <property name="vexpand">True</property>
    <property name="border_width">0</property>
    <property name="spacing">6</property>
    <property name="homogeneous">True</property>
    <child>
      <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>
          <object class="GtkTreeView" id="treeview">
            <property name="width_request">-1</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <property name="model">liststore1</property>
            <property name="headers_visible">False</property>
            <property name="reorderable">True</property>
            <property name="search_column">2</property>
            <property name="enable_tree_lines">True</property>
            <child internal-child="selection">
              <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="treeviewcolumn8">
                <property name="spacing">6</property>
                <child>
                  <object class="GtkCellRendererPixbuf" id="cellrenderertext5"/>
                  <attributes>
                    <attribute name="pixbuf">0</attribute>
                  </attributes>
                </child>
                <child>
                  <object class="GtkCellRendererToggle" id="cellrenderer5"/>
                  <attributes>
                    <attribute name="visible">4</attribute>
                    <attribute name="active">1</attribute>
                    <attribute name="inconsistent">5</attribute>
                  </attributes>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="treeviewcolumn9">
                <property name="spacing">6</property>
                <child>
                  <object class="GtkCellRendererText" id="cellrenderertext6"/>
                  <attributes>
                    <attribute name="text">2</attribute>
                    <attribute name="weight">6</attribute>
                  </attributes>
                </child>
              </object>
            </child>
          </object>
        </child>
      </object>
      <packing>
        <property name="expand">True</property>
        <property name="fill">True</property>
        <property name="position">0</property>
      </packing>
    </child>
  </object>
</interface>