diff options
author | Caolán McNamara <caolanm@redhat.com> | 2020-08-07 14:33:07 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2020-08-12 20:21:10 +0200 |
commit | 46c34d5abcc3fb709de4c3a6a62649f1fe41ec9c (patch) | |
tree | cb2033f6b83d3109e9144dddade1a92dc3d1e54c | |
parent | c299e1255974c5564333480a5f8f0877c1011bc4 (diff) |
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>
23 files changed, 1254 insertions, 675 deletions
diff --git a/dbaccess/UIConfig_dbaccess.mk b/dbaccess/UIConfig_dbaccess.mk index feaa35c10708..8a4229e02f38 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 958d5d9c7b4f..67bd857b60d4 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 6f7c1f658545..1abf501328fb 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 502ad243cd76..27a4ed7e16ea 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 ) - { - case E_TABLE: + switch (eType) { - 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 ( !aObject.Name.isEmpty() ) - { - aSelected.push_back( aObject ); + 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; } - pEntry = pList->NextSelected(pEntry); - } + if (!aObject.Name.isEmpty()) + aSelected.push_back(aObject); + + 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; - + static_cast<OTableTreeListBox*>(pTreeView)->removedTable(rOldName); + static_cast<OTableTreeListBox*>(pTreeView)->addedTable(rNewName); + break; case E_QUERY: - pEntry = lcl_findEntry_impl(*pTreeView,_rOldName,pTreeView->First()); + { + 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 1dd89d84a28a..bda44447edcb 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 e6e318c661d4..3430d0bebb77 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 a00e7f4ba642..c551db1a3adc 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 5ab8ba34ebf0..5aa3c2ceb3a0 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 0d492953a5e4..d8f222433685 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 cd8c124f059a..0b9888f3f34e 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 43a7006fe40e..4caa3f4cc31f 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 4fbb3485e263..8be8061628cc 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 b565b62cbbf6..99bcfad77a71 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 ) +OTableTreeListBox::OTableTreeListBox(vcl::Window* pParent, bool bShowToggles) + : InterimDBTreeListBox(pParent) + , m_xImageProvider(new ImageProvider) , m_bVirtualRoot(false) - , m_bNoEmptyFolders( false ) -{ - InitButtonData(); - - implSetDefaultImages(); -} - -void OTableTreeListBox::InitButtonData() + , m_bNoEmptyFolders(false) + , m_bShowToggles(bShowToggles) { - m_pCheckButton.reset( new SvLBoxButtonData( this ) ); - EnableCheckButton( m_pCheckButton.get() ); + if (m_bShowToggles) + m_xTreeView->enable_toggle_buttons(weld::ColumnToggleType::Check); } -void OTableTreeListBox::dispose() +OTableTreeListBox::~OTableTreeListBox() { - m_pCheckButton.reset(); - DBTreeListBox::dispose(); } -TableTreeListBox::TableTreeListBox(std::unique_ptr<weld::TreeView> xTreeView) - : m_xImageProvider(new ImageProvider) +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(true) - , m_xTreeView(std::move(xTreeView)) -{ - m_xTreeView->enable_toggle_buttons(weld::ColumnToggleType::Check); -} - -void OTableTreeListBox::implSetDefaultImages() + , m_bShowToggles(bShowToggles) { - SetDefaultExpandedEntryBmp( ImageProvider::getFolderImage( DatabaseObject::TABLE ) ); - SetDefaultCollapsedEntryBmp( ImageProvider::getFolderImage( DatabaseObject::TABLE ) ); + if (m_bShowToggles) + m_xTreeView->enable_toggle_buttons(weld::ColumnToggleType::Check); } -bool OTableTreeListBox::isFolderEntry( const SvTreeListEntry* _pEntry ) +bool OTableTreeListBox::isFolderEntry(const weld::TreeIter& rEntry) const { - sal_Int32 nEntryType = reinterpret_cast< sal_IntPtr >( _pEntry->GetUserData() ); + 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) - { - 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()); + if (!m_bShowToggles) + return; - rRenderContext.SetFont(aNewFont); - DBTreeListBox::Paint(rRenderContext, _rRect); - rRenderContext.SetFont(aOldFont); - } - else - DBTreeListBox::Paint(rRenderContext, _rRect); -} + auto xEntry(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_iter_first(*xEntry)) + return; -void OTableTreeListBox::KeyInput( const KeyEvent& rKEvt ) -{ - // only if there are spaces - if (rKEvt.GetKeyCode().GetCode() == KEY_SPACE && !rKEvt.GetKeyCode().IsShift() && !rKEvt.GetKeyCode().IsMod1()) + do { - 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 35e29ed17f31..485bb394630a 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 2fa719517a91..3440b90b0c73 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 8a607db34eff..e18a6556036f 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 f79abe8f5df7..70b891f0ef56 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 97b1ba7cc666..53e425980b13 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 - */ - css::sdb::application::NamedDatabaseObject - describeObject( SvTreeListEntry* _pEntry ); - - /** to be used if a foreign instance added a table - */ - SvTreeListEntry* addedTable( const OUString& _rName ); + std::unique_ptr<weld::TreeIter> getAllObjectsEntry() const; - /** to be used if a foreign instance removed a table + /** 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> */ - void removedTable( const OUString& _rName ); + void checkWildcard(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. + /** determine if the given entry is 'wildcard checked' + @see checkWildcard */ - OUString getQualifiedTableName( SvTreeListEntry* _pEntry ) const; - - SvTreeListEntry* getEntryByQualifiedName( const OUString& _rName ); + bool isWildcardChecked(const weld::TreeIter& rEntry); - 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); + + /** to be used if a foreign instance added a table + */ + std::unique_ptr<weld::TreeIter> addedTable(const OUString& rName); - /// 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 removed a table + */ + void removedTable( const OUString& _rName ); - SvButtonState implDetermineState(SvTreeListEntry* _pEntry); + 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 498b634f2575..810586a2d70c 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 754c6e169636..cc70e1276a19 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 2b23a3eb226c..1e00cc9b3908 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 f7ec40c33518..02f45afb416f 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 000000000000..042e770f78d6 --- /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> |