office-gobmx/dbaccess/source/ui/control/tabletree.cxx
Ivo Hinkelmann e80d22ed35 INTEGRATION: CWS jl49 (1.33.36); FILE MERGED
2006/12/01 12:18:07 sb 1.33.36.1: #i70481# Extended SvLBoxButton.
2006-12-20 13:14:03 +00:00

612 lines
22 KiB
C++

/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: tabletree.cxx,v $
*
* $Revision: 1.34 $
*
* last change: $Author: ihi $ $Date: 2006-12-20 14:14:03 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dbaccess.hxx"
#ifndef _DBAUI_TABLETREE_HXX_
#include "tabletree.hxx"
#endif
#ifndef _DBAUI_TABLETREE_HRC_
#include "tabletree.hrc"
#endif
#ifndef DBACCESS_IMAGEPROVIDER_HXX
#include "imageprovider.hxx"
#endif
#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif
#ifndef _DBU_CONTROL_HRC_
#include "dbu_control.hrc"
#endif
#ifndef _SV_MENU_HXX
#include <vcl/menu.hxx>
#endif
#ifndef _CONNECTIVITY_DBTOOLS_HXX_
#include <connectivity/dbtools.hxx>
#endif
#ifndef _COMPHELPER_TYPES_HXX_
#include <comphelper/types.hxx>
#endif
#ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
#include "dbustrings.hrc"
#endif
#ifndef _COM_SUN_STAR_SDB_APPLICATION_DATABASEOBJECT_HPP_
#include <com/sun/star/sdb/application/DatabaseObject.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XDRIVERACCESS_HPP_
#include <com/sun/star/sdbc/XDriverAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XDATADEFINITIONSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XVIEWSSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_
#include <com/sun/star/sdb/SQLContext.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_
#include <com/sun/star/sdbc/XRow.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _DBAUI_COMMON_TYPES_HXX_
#include "commontypes.hxx"
#endif
#ifndef _DBAUI_LISTVIEWITEMS_HXX_
#include "listviewitems.hxx"
#endif
#ifndef TOOLS_DIAGNOSE_EX_H
#include <tools/diagnose_ex.h>
#endif
#include <algorithm>
//.........................................................................
namespace dbaui
{
//.........................................................................
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::dbtools;
using namespace ::comphelper;
namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject;
//========================================================================
//= OTableTreeListBox
//========================================================================
OTableTreeListBox::OTableTreeListBox( Window* pParent, const Reference< XMultiServiceFactory >& _rxORB, WinBits nWinStyle,sal_Bool _bVirtualRoot )
:OMarkableTreeListBox(pParent,_rxORB,nWinStyle)
,m_pImageProvider( new ImageProvider )
,m_bVirtualRoot(_bVirtualRoot)
{
implSetDefaultImages();
}
//------------------------------------------------------------------------
OTableTreeListBox::OTableTreeListBox( Window* pParent, const Reference< XMultiServiceFactory >& _rxORB, const ResId& rResId ,sal_Bool _bVirtualRoot)
:OMarkableTreeListBox(pParent,_rxORB,rResId)
,m_pImageProvider( new ImageProvider )
,m_bVirtualRoot(_bVirtualRoot)
{
implSetDefaultImages();
}
// -----------------------------------------------------------------------------
OTableTreeListBox::~OTableTreeListBox()
{
}
// -----------------------------------------------------------------------------
void OTableTreeListBox::implSetDefaultImages()
{
ImageProvider aImageProvider;
SetDefaultExpandedEntryBmp( aImageProvider.getFolderImage( DatabaseObject::TABLE, false ), BMP_COLOR_NORMAL );
SetDefaultExpandedEntryBmp( aImageProvider.getFolderImage( DatabaseObject::TABLE, true ), BMP_COLOR_HIGHCONTRAST );
SetDefaultCollapsedEntryBmp( aImageProvider.getFolderImage( DatabaseObject::TABLE, false ), BMP_COLOR_NORMAL );
SetDefaultCollapsedEntryBmp( aImageProvider.getFolderImage( DatabaseObject::TABLE, true ), BMP_COLOR_HIGHCONTRAST );
}
// -----------------------------------------------------------------------------
bool OTableTreeListBox::isFolderEntry( const SvLBoxEntry* _pEntry ) const
{
return _pEntry->GetUserData() == reinterpret_cast< void* >(FOLDER_INDICATOR);
}
// -----------------------------------------------------------------------------
void OTableTreeListBox::notifyHiContrastChanged()
{
implSetDefaultImages();
SvLBoxEntry* pEntryLoop = First();
while (pEntryLoop)
{
USHORT nCount = pEntryLoop->ItemCount();
for (USHORT i=0;i<nCount;++i)
{
SvLBoxItem* pItem = pEntryLoop->GetItem(i);
if ( pItem && pItem->IsA() == SV_ITEM_ID_LBOXCONTEXTBMP)
{
SvLBoxContextBmp* pContextBitmapItem = static_cast< SvLBoxContextBmp* >( pItem );
Image aImage, aImageHC;
if ( isFolderEntry( pEntryLoop ) )
{
aImage = m_pImageProvider->getFolderImage( DatabaseObject::TABLE, false );
aImageHC = m_pImageProvider->getFolderImage( DatabaseObject::TABLE, true );
}
else
{
String sCompleteName( getQualifiedTableName( pEntryLoop ) );
aImage = m_pImageProvider->getImage( sCompleteName, DatabaseObject::TABLE, false );
aImageHC = m_pImageProvider->getImage( sCompleteName, DatabaseObject::TABLE, true );
}
pContextBitmapItem->SetBitmap1( aImage, BMP_COLOR_NORMAL );
pContextBitmapItem->SetBitmap2( aImage, BMP_COLOR_NORMAL );
pContextBitmapItem->SetBitmap1( aImageHC, BMP_COLOR_HIGHCONTRAST );
pContextBitmapItem->SetBitmap2( aImageHC, BMP_COLOR_HIGHCONTRAST );
// TODO: Now that we give both images to the entry item, it is not necessary anymore
// to do this anytime HC changes - the tree control will do this itself now.
// We would only need to properly initialize newly inserted entries.
break;
}
}
pEntryLoop = Next(pEntryLoop);
}
}
//------------------------------------------------------------------------
void OTableTreeListBox::implOnNewConnection( const Reference< XConnection >& _rxConnection )
{
m_xConnection = _rxConnection;
m_pImageProvider.reset( new ImageProvider( m_xConnection ) );
}
//------------------------------------------------------------------------
void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConnection ) throw(SQLException)
{
Sequence< ::rtl::OUString > sTables, sViews;
String sCurrentActionError;
try
{
Reference< XTablesSupplier > xTableSupp( _rxConnection, UNO_QUERY_THROW );
sCurrentActionError = String(ModuleRes(STR_NOTABLEINFO));
Reference< XNameAccess > xTables,xViews;
Reference< XViewsSupplier > xViewSupp( _rxConnection, UNO_QUERY );
if ( xViewSupp.is() )
{
xViews = xViewSupp->getViews();
if (xViews.is())
sViews = xViews->getElementNames();
}
xTables = xTableSupp->getTables();
if (xTables.is())
sTables = xTables->getElementNames();
}
catch(RuntimeException&)
{
DBG_ERROR("OTableTreeListBox::UpdateTableList : caught an RuntimeException!");
}
catch ( const SQLException& )
{
throw;
}
catch(Exception&)
{
// a non-SQLException exception occured ... simply throw an SQLException
SQLException aInfo;
aInfo.Message = sCurrentActionError;
throw aInfo;
}
UpdateTableList( _rxConnection, sTables, sViews );
}
// -----------------------------------------------------------------------------
namespace
{
struct OViewSetter : public ::std::unary_function< OTableTreeListBox::TNames::value_type, bool>
{
const Sequence< ::rtl::OUString> m_aViews;
::comphelper::TStringMixEqualFunctor m_aEqualFunctor;
OViewSetter(const Sequence< ::rtl::OUString>& _rViews,sal_Bool _bCase) : m_aViews(_rViews),m_aEqualFunctor(_bCase){}
OTableTreeListBox::TNames::value_type operator() (const ::rtl::OUString& lhs)
{
OTableTreeListBox::TNames::value_type aRet;
aRet.first = lhs;
const ::rtl::OUString* pIter = m_aViews.getConstArray();
const ::rtl::OUString* pEnd = m_aViews.getConstArray() + m_aViews.getLength();
aRet.second = (::std::find_if(pIter,pEnd,::std::bind2nd(m_aEqualFunctor,lhs)) != pEnd);
return aRet;
}
};
}
// -----------------------------------------------------------------------------
void OTableTreeListBox::UpdateTableList(
const Reference< XConnection >& _rxConnection,
const Sequence< ::rtl::OUString>& _rTables,
const Sequence< ::rtl::OUString>& _rViews
)
{
TNames aTables;
aTables.resize(_rTables.getLength());
const ::rtl::OUString* pIter = _rTables.getConstArray();
const ::rtl::OUString* pEnd = _rTables.getConstArray() + _rTables.getLength();
try
{
Reference< XDatabaseMetaData > xMeta( _rxConnection->getMetaData(), UNO_QUERY_THROW );
::std::transform( pIter, pEnd,
aTables.begin(), OViewSetter( _rViews, xMeta->supportsMixedCaseQuotedIdentifiers() ) );
}
catch(Exception&)
{
DBG_UNHANDLED_EXCEPTION();
}
UpdateTableList( _rxConnection, aTables );
}
//------------------------------------------------------------------------
void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConnection, const TNames& _rTables )
{
implOnNewConnection( _rxConnection );
// throw away all the old stuff
Clear();
try
{
// the root entry saying "all objects"
SvLBoxEntry* pAllObjects = NULL;
if (haveVirtualRoot())
{
String sRootEntryText;
TNames::const_iterator aViews = ::std::find_if(_rTables.begin(),_rTables.end(),
::std::compose1(::std::bind2nd(::std::equal_to<sal_Bool>(),sal_False),::std::select2nd<TNames::value_type>()));
TNames::const_iterator aTables = ::std::find_if(_rTables.begin(),_rTables.end(),
::std::compose1(::std::bind2nd(::std::equal_to<sal_Bool>(),sal_True),::std::select2nd<TNames::value_type>()));
if ( aViews == _rTables.end() )
sRootEntryText = String(ModuleRes(STR_ALL_TABLES));
else if ( aTables == _rTables.end() )
sRootEntryText = String(ModuleRes(STR_ALL_VIEWS));
else
sRootEntryText = String(ModuleRes(STR_ALL_TABLES_AND_VIEWS));
pAllObjects = InsertEntry( sRootEntryText, NULL, FALSE, LIST_APPEND, reinterpret_cast< void* >( FOLDER_INDICATOR ) );
}
if ( _rTables.empty() )
// nothing to do (besides inserting the root entry)
return;
// get the table/view names
TNames::const_iterator aIter = _rTables.begin();
TNames::const_iterator aEnd = _rTables.end();
Reference< XDatabaseMetaData > xMeta( _rxConnection->getMetaData(), UNO_QUERY_THROW );
for ( ; aIter != aEnd; ++aIter )
{
// add the entry
implAddEntry(
xMeta,
aIter->first,
sal_False
);
}
}
catch ( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
//------------------------------------------------------------------------
sal_Bool OTableTreeListBox::isWildcardChecked(SvLBoxEntry* _pEntry) const
{
if (_pEntry)
{
OBoldListboxString* pTextItem = static_cast<OBoldListboxString*>(_pEntry->GetFirstItem(SV_ITEM_ID_BOLDLBSTRING));
if (pTextItem)
return pTextItem->isEmphasized();
}
return sal_False;
}
//------------------------------------------------------------------------
void OTableTreeListBox::checkWildcard(SvLBoxEntry* _pEntry)
{
SetCheckButtonState(_pEntry, SV_BUTTON_CHECKED);
checkedButton_noBroadcast(_pEntry);
}
//------------------------------------------------------------------------
SvLBoxEntry* OTableTreeListBox::getAllObjectsEntry() const
{
return haveVirtualRoot() ? First() : NULL;
}
//------------------------------------------------------------------------
void OTableTreeListBox::checkedButton_noBroadcast(SvLBoxEntry* _pEntry)
{
OMarkableTreeListBox::checkedButton_noBroadcast(_pEntry);
// if an entry has children, it makes a difference if the entry is checked because alls children are checked
// or if the user checked it explicitly.
// So we track explicit (un)checking
SvButtonState eState = GetCheckButtonState(_pEntry);
DBG_ASSERT(SV_BUTTON_TRISTATE != eState, "OTableTreeListBox::CheckButtonHdl: user action which lead to TRISTATE?");
implEmphasize(_pEntry, SV_BUTTON_CHECKED == eState);
}
//------------------------------------------------------------------------
void OTableTreeListBox::implEmphasize(SvLBoxEntry* _pEntry, sal_Bool _bChecked, sal_Bool _bUpdateDescendants, sal_Bool _bUpdateAncestors)
{
DBG_ASSERT(_pEntry, "OTableTreeListBox::implEmphasize: invalid entry (NULL)!");
// special emphasizing handling for the "all objects" entry
// 89709 - 16.07.2001 - frank.schoenheit@sun.com
sal_Bool bAllObjectsEntryAffected = haveVirtualRoot() && (getAllObjectsEntry() == _pEntry);
if ( GetModel()->HasChilds(_pEntry) // the entry has children
|| bAllObjectsEntryAffected // or it is the "all objects" entry
)
{
OBoldListboxString* pTextItem = static_cast<OBoldListboxString*>(_pEntry->GetFirstItem(SV_ITEM_ID_BOLDLBSTRING));
if (pTextItem)
pTextItem->emphasize(_bChecked);
if (bAllObjectsEntryAffected)
InvalidateEntry(_pEntry);
}
if (_bUpdateDescendants)
{
// remove the mark for all children of the checked entry
SvLBoxEntry* pChildLoop = FirstChild(_pEntry);
while (pChildLoop)
{
if (GetModel()->HasChilds(pChildLoop))
implEmphasize(pChildLoop, sal_False, sal_True, sal_False);
pChildLoop = NextSibling(pChildLoop);
}
}
if (_bUpdateAncestors)
{
// remove the mark for all ancestors of the entry
if (GetModel()->HasParent(_pEntry))
implEmphasize(GetParent(_pEntry), sal_False, sal_False, sal_True);
}
}
//------------------------------------------------------------------------
void OTableTreeListBox::InitEntry(SvLBoxEntry* _pEntry, const XubString& _rString, const Image& _rCollapsedBitmap, const Image& _rExpandedBitmap, SvLBoxButtonKind _eButtonKind)
{
OMarkableTreeListBox::InitEntry(_pEntry, _rString, _rCollapsedBitmap, _rExpandedBitmap, _eButtonKind);
// replace the text item with our own one
SvLBoxItem* pTextItem = _pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING);
DBG_ASSERT(pTextItem, "OTableTreeListBox::InitEntry: no text item!?");
sal_uInt16 nTextPos = _pEntry->GetPos(pTextItem);
DBG_ASSERT(((sal_uInt16)-1) != nTextPos, "OTableTreeListBox::InitEntry: no text item pos!");
_pEntry->ReplaceItem(new OBoldListboxString(_pEntry, 0, _rString), nTextPos);
}
//------------------------------------------------------------------------
SvLBoxEntry* OTableTreeListBox::implAddEntry(
const Reference< XDatabaseMetaData >& _rxMeta,
const ::rtl::OUString& _rTableName,
sal_Bool _bCheckName
)
{
OSL_PRECOND( _rxMeta.is(), "OTableTreeListBox::implAddEntry: invalid meta data!" );
if ( !_rxMeta.is() )
return NULL;
// split the complete name into it's components
::rtl::OUString sCatalog, sSchema, sName;
qualifiedNameComponents( _rxMeta, _rTableName, sCatalog, sSchema, sName, ::dbtools::eInDataManipulation );
SvLBoxEntry* pParentEntry = getAllObjectsEntry();
SvLBoxEntry* pCat = NULL;
SvLBoxEntry* pSchema = NULL;
if (sCatalog.getLength())
{
pCat = GetEntryPosByName(sCatalog, pParentEntry);
if (!pCat)
pCat = InsertEntry( sCatalog, pParentEntry, FALSE, LIST_APPEND, reinterpret_cast< void* >( FOLDER_INDICATOR ) );
pParentEntry = pCat;
}
if (sSchema.getLength())
{
pSchema = GetEntryPosByName(sSchema, pParentEntry);
if (!pSchema)
pSchema = InsertEntry( sSchema, pParentEntry, FALSE, LIST_APPEND, reinterpret_cast< void* >( FOLDER_INDICATOR ) );
pParentEntry = pSchema;
}
SvLBoxEntry* pRet = NULL;
if ( !_bCheckName || !GetEntryPosByName( sName, pParentEntry ) )
{
pRet = InsertEntry( sName, pParentEntry, FALSE, LIST_APPEND );
Image aImage( m_pImageProvider->getImage( _rTableName, DatabaseObject::TABLE, false ) );
Image aImageHC( m_pImageProvider->getImage( _rTableName, DatabaseObject::TABLE, true ) );
SetExpandedEntryBmp( pRet, aImage, BMP_COLOR_NORMAL );
SetCollapsedEntryBmp( pRet, aImage, BMP_COLOR_NORMAL );
SetExpandedEntryBmp( pRet, aImageHC, BMP_COLOR_HIGHCONTRAST );
SetCollapsedEntryBmp( pRet, aImageHC, BMP_COLOR_HIGHCONTRAST );
}
return pRet;
}
//------------------------------------------------------------------------
SvLBoxEntry* OTableTreeListBox::addedTable( const ::rtl::OUString& _rName )
{
try
{
Reference< XDatabaseMetaData > xMeta;
if ( impl_getAndAssertMetaData( xMeta ) )
return implAddEntry( xMeta, _rName );
}
catch( const Exception& )
{
DBG_ERROR( "OTableTreeListBox::addedTable: caught an exception!" );
}
return NULL;
}
//------------------------------------------------------------------------
bool OTableTreeListBox::impl_getAndAssertMetaData( Reference< XDatabaseMetaData >& _out_rMetaData ) const
{
if ( m_xConnection.is() )
_out_rMetaData = m_xConnection->getMetaData();
OSL_PRECOND( _out_rMetaData.is(), "OTableTreeListBox::impl_getAndAssertMetaData: invalid current connection!" );
return _out_rMetaData.is();
}
//------------------------------------------------------------------------
String OTableTreeListBox::getQualifiedTableName( SvLBoxEntry* _pEntry ) const
{
OSL_PRECOND( !isFolderEntry( _pEntry ), "OTableTreeListBox::getQualifiedTableName: folder entries not allowed here!" );
Reference< XDatabaseMetaData > xMeta;
if ( !impl_getAndAssertMetaData( xMeta ) )
return String();
::rtl::OUString sCatalog;
::rtl::OUString sSchema;
::rtl::OUString sTable;
SvLBoxEntry* pSchema = GetParent( _pEntry );
if ( pSchema )
{
SvLBoxEntry* pCatalog = GetParent( pSchema );
if ( pCatalog
|| ( xMeta->supportsCatalogsInDataManipulation()
&& !xMeta->supportsSchemasInDataManipulation()
) // here we support catalog but no schema
)
{
if ( pCatalog == NULL )
{
pCatalog = pSchema;
pSchema = NULL;
}
sCatalog = GetEntryText( pCatalog );
}
if ( pSchema )
sSchema = GetEntryText(pSchema);
}
sTable = GetEntryText( _pEntry );
return ::dbtools::composeTableName( xMeta, sCatalog, sSchema, sTable, sal_False, ::dbtools::eInDataManipulation );
}
//------------------------------------------------------------------------
SvLBoxEntry* OTableTreeListBox::getEntryByQualifiedName( const ::rtl::OUString& _rName )
{
try
{
Reference< XDatabaseMetaData > xMeta;
if ( !impl_getAndAssertMetaData( xMeta ) )
return NULL;
// split the complete name into it's components
::rtl::OUString sCatalog, sSchema, sName;
qualifiedNameComponents(xMeta, _rName, sCatalog, sSchema, sName,::dbtools::eInDataManipulation);
SvLBoxEntry* pParent = getAllObjectsEntry();
SvLBoxEntry* pCat = NULL;
SvLBoxEntry* pSchema = NULL;
if ( sCatalog.getLength() )
{
pCat = GetEntryPosByName(sCatalog, pParent);
if ( pCat )
pParent = pCat;
}
if ( sSchema.getLength() )
{
pSchema = GetEntryPosByName(sSchema, pParent);
if ( pSchema )
pParent = pSchema;
}
return GetEntryPosByName(sName, pParent);
}
catch( const Exception& )
{
DBG_ERROR( "OTableTreeListBox::removedTable: caught an exception!" );
}
return NULL;
}
//------------------------------------------------------------------------
void OTableTreeListBox::removedTable( const ::rtl::OUString& _rName )
{
try
{
SvLBoxEntry* pEntry = getEntryByQualifiedName( _rName );
if ( pEntry )
GetModel()->Remove( pEntry );
}
catch( const Exception& )
{
DBG_ERROR( "OTableTreeListBox::removedTable: caught an exception!" );
}
}
//.........................................................................
} // namespace dbaui
//.........................................................................