xref: /trunk/main/dbaccess/source/ui/control/tabletree.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 
31 #ifndef _DBAUI_TABLETREE_HXX_
32 #include "tabletree.hxx"
33 #endif
34 #ifndef _DBAUI_TABLETREE_HRC_
35 #include "tabletree.hrc"
36 #endif
37 #ifndef DBACCESS_IMAGEPROVIDER_HXX
38 #include "imageprovider.hxx"
39 #endif
40 #ifndef _DBAUI_MODULE_DBU_HXX_
41 #include "moduledbu.hxx"
42 #endif
43 #ifndef _DBU_CONTROL_HRC_
44 #include "dbu_control.hrc"
45 #endif
46 #ifndef _SV_MENU_HXX
47 #include <vcl/menu.hxx>
48 #endif
49 #ifndef _CONNECTIVITY_DBTOOLS_HXX_
50 #include <connectivity/dbtools.hxx>
51 #endif
52 #ifndef _COMPHELPER_TYPES_HXX_
53 #include <comphelper/types.hxx>
54 #endif
55 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
56 #include "dbustrings.hrc"
57 #endif
58 #ifndef _COM_SUN_STAR_SDB_APPLICATION_DATABASEOBJECT_HPP_
59 #include <com/sun/star/sdb/application/DatabaseObject.hpp>
60 #endif
61 #ifndef _COM_SUN_STAR_SDB_APPLICATION_DATABASEOBJECTFOLDER_HPP_
62 #include <com/sun/star/sdb/application/DatabaseObjectContainer.hpp>
63 #endif
64 #ifndef _COM_SUN_STAR_SDBC_XDRIVERACCESS_HPP_
65 #include <com/sun/star/sdbc/XDriverAccess.hpp>
66 #endif
67 #ifndef _COM_SUN_STAR_SDBCX_XDATADEFINITIONSUPPLIER_HPP_
68 #include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
69 #endif
70 #ifndef _COM_SUN_STAR_SDBCX_XVIEWSSUPPLIER_HPP_
71 #include <com/sun/star/sdbcx/XViewsSupplier.hpp>
72 #endif
73 #ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_
74 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
75 #endif
76 #ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_
77 #include <com/sun/star/sdb/SQLContext.hpp>
78 #endif
79 #ifndef _COM_SUN_STAR_SDBC_XROW_HPP_
80 #include <com/sun/star/sdbc/XRow.hpp>
81 #endif
82 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
83 #include <com/sun/star/beans/XPropertySet.hpp>
84 #endif
85 #ifndef _DBAUI_COMMON_TYPES_HXX_
86 #include "commontypes.hxx"
87 #endif
88 #ifndef _DBAUI_LISTVIEWITEMS_HXX_
89 #include "listviewitems.hxx"
90 #endif
91 #ifndef TOOLS_DIAGNOSE_EX_H
92 #include <tools/diagnose_ex.h>
93 #endif
94 #ifndef _RTL_USTRBUF_HXX_
95 #include <rtl/ustrbuf.hxx>
96 #endif
97 #include <connectivity/dbmetadata.hxx>
98 
99 #include <algorithm>
100 
101 //.........................................................................
102 namespace dbaui
103 {
104 //.........................................................................
105 
106 using namespace ::com::sun::star::uno;
107 using namespace ::com::sun::star::sdb;
108 using namespace ::com::sun::star::lang;
109 using namespace ::com::sun::star::sdbc;
110 using namespace ::com::sun::star::sdbcx;
111 using namespace ::com::sun::star::beans;
112 using namespace ::com::sun::star::container;
113 using namespace ::com::sun::star::sdb::application;
114 
115 using namespace ::dbtools;
116 using namespace ::comphelper;
117 
118 namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject;
119 namespace DatabaseObjectContainer = ::com::sun::star::sdb::application::DatabaseObjectContainer;
120 
121 //========================================================================
122 //= OTableTreeListBox
123 //========================================================================
124 OTableTreeListBox::OTableTreeListBox( Window* pParent, const Reference< XMultiServiceFactory >& _rxORB, WinBits nWinStyle,sal_Bool _bVirtualRoot )
125     :OMarkableTreeListBox(pParent,_rxORB,nWinStyle)
126     ,m_pImageProvider( new ImageProvider )
127     ,m_bVirtualRoot(_bVirtualRoot)
128     ,m_bNoEmptyFolders( false )
129 {
130     implSetDefaultImages();
131 }
132 //------------------------------------------------------------------------
133 OTableTreeListBox::OTableTreeListBox( Window* pParent, const Reference< XMultiServiceFactory >& _rxORB, const ResId& rResId ,sal_Bool _bVirtualRoot)
134     :OMarkableTreeListBox(pParent,_rxORB,rResId)
135     ,m_pImageProvider( new ImageProvider )
136     ,m_bVirtualRoot(_bVirtualRoot)
137     ,m_bNoEmptyFolders( false )
138 {
139     implSetDefaultImages();
140 }
141 
142 // -----------------------------------------------------------------------------
143 OTableTreeListBox::~OTableTreeListBox()
144 {
145 }
146 
147 // -----------------------------------------------------------------------------
148 void OTableTreeListBox::implSetDefaultImages()
149 {
150     ImageProvider aImageProvider;
151     SetDefaultExpandedEntryBmp( aImageProvider.getFolderImage( DatabaseObject::TABLE, false ), BMP_COLOR_NORMAL );
152     SetDefaultExpandedEntryBmp( aImageProvider.getFolderImage( DatabaseObject::TABLE, true ), BMP_COLOR_HIGHCONTRAST );
153     SetDefaultCollapsedEntryBmp( aImageProvider.getFolderImage( DatabaseObject::TABLE, false ), BMP_COLOR_NORMAL );
154     SetDefaultCollapsedEntryBmp( aImageProvider.getFolderImage( DatabaseObject::TABLE, true ), BMP_COLOR_HIGHCONTRAST );
155 }
156 
157 // -----------------------------------------------------------------------------
158 bool  OTableTreeListBox::isFolderEntry( const SvLBoxEntry* _pEntry ) const
159 {
160     sal_Int32 nEntryType = reinterpret_cast< sal_IntPtr >( _pEntry->GetUserData() );
161     if  (   ( nEntryType == DatabaseObjectContainer::TABLES )
162         ||  ( nEntryType == DatabaseObjectContainer::CATALOG )
163         ||  ( nEntryType == DatabaseObjectContainer::SCHEMA )
164         )
165         return true;
166     return false;
167 }
168 
169 // -----------------------------------------------------------------------------
170 void OTableTreeListBox::notifyHiContrastChanged()
171 {
172     implSetDefaultImages();
173 
174     SvLBoxEntry* pEntryLoop = First();
175     while (pEntryLoop)
176     {
177         sal_uInt16 nCount = pEntryLoop->ItemCount();
178         for (sal_uInt16 i=0;i<nCount;++i)
179         {
180             SvLBoxItem* pItem = pEntryLoop->GetItem(i);
181             if ( pItem && pItem->IsA() == SV_ITEM_ID_LBOXCONTEXTBMP)
182             {
183                 SvLBoxContextBmp* pContextBitmapItem = static_cast< SvLBoxContextBmp* >( pItem );
184 
185                 Image aImage, aImageHC;
186                 if ( isFolderEntry( pEntryLoop ) )
187                 {
188                     aImage = m_pImageProvider->getFolderImage( DatabaseObject::TABLE, false );
189                     aImageHC = m_pImageProvider->getFolderImage( DatabaseObject::TABLE, true );
190                 }
191                 else
192                 {
193                     String sCompleteName( getQualifiedTableName( pEntryLoop ) );
194                     m_pImageProvider->getImages( sCompleteName, DatabaseObject::TABLE, aImage, aImageHC );
195                 }
196 
197                 pContextBitmapItem->SetBitmap1( aImage, BMP_COLOR_NORMAL );
198                 pContextBitmapItem->SetBitmap2( aImage, BMP_COLOR_NORMAL );
199                 pContextBitmapItem->SetBitmap1( aImageHC, BMP_COLOR_HIGHCONTRAST );
200                 pContextBitmapItem->SetBitmap2( aImageHC, BMP_COLOR_HIGHCONTRAST );
201                 // TODO: Now that we give both images to the entry item, it is not necessary anymore
202                 // to do this anytime HC changes - the tree control will do this itself now.
203                 // We would only need to properly initialize newly inserted entries.
204                 break;
205             }
206         }
207         pEntryLoop = Next(pEntryLoop);
208     }
209 }
210 
211 //------------------------------------------------------------------------
212 void OTableTreeListBox::implOnNewConnection( const Reference< XConnection >& _rxConnection )
213 {
214     m_xConnection = _rxConnection;
215     m_pImageProvider.reset( new ImageProvider( m_xConnection  ) );
216 }
217 
218 //------------------------------------------------------------------------
219 void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConnection ) throw(SQLException)
220 {
221     Sequence< ::rtl::OUString > sTables, sViews;
222 
223     String sCurrentActionError;
224     try
225     {
226         Reference< XTablesSupplier > xTableSupp( _rxConnection, UNO_QUERY_THROW );
227         sCurrentActionError = String(ModuleRes(STR_NOTABLEINFO));
228 
229         Reference< XNameAccess > xTables,xViews;
230 
231         Reference< XViewsSupplier > xViewSupp( _rxConnection, UNO_QUERY );
232         if ( xViewSupp.is() )
233         {
234             xViews = xViewSupp->getViews();
235             if (xViews.is())
236                 sViews = xViews->getElementNames();
237         }
238 
239         xTables = xTableSupp->getTables();
240         if (xTables.is())
241             sTables = xTables->getElementNames();
242     }
243     catch(RuntimeException&)
244     {
245         DBG_ERROR("OTableTreeListBox::UpdateTableList : caught an RuntimeException!");
246     }
247     catch ( const SQLException& )
248     {
249         throw;
250     }
251     catch(Exception&)
252     {
253         // a non-SQLException exception occured ... simply throw an SQLException
254         SQLException aInfo;
255         aInfo.Message = sCurrentActionError;
256         throw aInfo;
257     }
258 
259     UpdateTableList( _rxConnection, sTables, sViews );
260 }
261 // -----------------------------------------------------------------------------
262 namespace
263 {
264     struct OViewSetter : public ::std::unary_function< OTableTreeListBox::TNames::value_type, bool>
265     {
266         const Sequence< ::rtl::OUString> m_aViews;
267         ::comphelper::TStringMixEqualFunctor m_aEqualFunctor;
268 
269         OViewSetter(const Sequence< ::rtl::OUString>& _rViews,sal_Bool _bCase) : m_aViews(_rViews),m_aEqualFunctor(_bCase){}
270         OTableTreeListBox::TNames::value_type operator() (const ::rtl::OUString& lhs)
271         {
272             OTableTreeListBox::TNames::value_type aRet;
273             aRet.first = lhs;
274             const ::rtl::OUString* pIter = m_aViews.getConstArray();
275             const ::rtl::OUString* pEnd = m_aViews.getConstArray() + m_aViews.getLength();
276             aRet.second = (::std::find_if(pIter,pEnd,::std::bind2nd(m_aEqualFunctor,lhs)) != pEnd);
277 
278             return aRet;
279         }
280     };
281 
282 }
283 // -----------------------------------------------------------------------------
284 void OTableTreeListBox::UpdateTableList(
285                 const Reference< XConnection >& _rxConnection,
286                 const Sequence< ::rtl::OUString>& _rTables,
287                 const Sequence< ::rtl::OUString>& _rViews
288             )
289 {
290     TNames aTables;
291     aTables.resize(_rTables.getLength());
292     const ::rtl::OUString* pIter = _rTables.getConstArray();
293     const ::rtl::OUString* pEnd = _rTables.getConstArray() + _rTables.getLength();
294     try
295     {
296         Reference< XDatabaseMetaData > xMeta( _rxConnection->getMetaData(), UNO_QUERY_THROW );
297         ::std::transform( pIter, pEnd,
298             aTables.begin(), OViewSetter( _rViews, xMeta->supportsMixedCaseQuotedIdentifiers() ) );
299     }
300     catch(Exception&)
301     {
302         DBG_UNHANDLED_EXCEPTION();
303     }
304     UpdateTableList( _rxConnection, aTables );
305 }
306 
307 //------------------------------------------------------------------------
308 namespace
309 {
310     ::std::vector< ::rtl::OUString > lcl_getMetaDataStrings_throw( const Reference< XResultSet >& _rxMetaDataResult, sal_Int32 _nColumnIndex )
311     {
312         ::std::vector< ::rtl::OUString > aStrings;
313         Reference< XRow > xRow( _rxMetaDataResult, UNO_QUERY_THROW );
314         while ( _rxMetaDataResult->next() )
315             aStrings.push_back( xRow->getString( _nColumnIndex ) );
316         return aStrings;
317     }
318 
319     bool lcl_shouldDisplayEmptySchemasAndCatalogs( const Reference< XConnection >& _rxConnection )
320     {
321         ::dbtools::DatabaseMetaData aMetaData( _rxConnection );
322         return aMetaData.displayEmptyTableFolders();
323     }
324 }
325 
326 //------------------------------------------------------------------------
327 void OTableTreeListBox::UpdateTableList( const Reference< XConnection >& _rxConnection, const TNames& _rTables )
328 {
329     implOnNewConnection( _rxConnection );
330 
331     // throw away all the old stuff
332     Clear();
333 
334     try
335     {
336         // the root entry saying "all objects"
337         SvLBoxEntry* pAllObjects = NULL;
338         if (haveVirtualRoot())
339         {
340             String sRootEntryText;
341             TNames::const_iterator aViews = ::std::find_if(_rTables.begin(),_rTables.end(),
342             ::std::compose1(::std::bind2nd(::std::equal_to<sal_Bool>(),sal_False),::std::select2nd<TNames::value_type>()));
343             TNames::const_iterator aTables = ::std::find_if(_rTables.begin(),_rTables.end(),
344             ::std::compose1(::std::bind2nd(::std::equal_to<sal_Bool>(),sal_True),::std::select2nd<TNames::value_type>()));
345 
346             if ( aViews == _rTables.end() )
347                 sRootEntryText  = String(ModuleRes(STR_ALL_TABLES));
348             else if ( aTables == _rTables.end() )
349                 sRootEntryText  = String(ModuleRes(STR_ALL_VIEWS));
350             else
351                 sRootEntryText  = String(ModuleRes(STR_ALL_TABLES_AND_VIEWS));
352             pAllObjects = InsertEntry( sRootEntryText, NULL, sal_False, LIST_APPEND, reinterpret_cast< void* >( DatabaseObjectContainer::TABLES ) );
353         }
354 
355         if ( _rTables.empty() )
356             // nothing to do (besides inserting the root entry)
357             return;
358 
359         // get the table/view names
360         TNames::const_iterator aIter = _rTables.begin();
361         TNames::const_iterator aEnd = _rTables.end();
362 
363         Reference< XDatabaseMetaData > xMeta( _rxConnection->getMetaData(), UNO_QUERY_THROW );
364         for ( ; aIter != aEnd; ++aIter )
365         {
366             // add the entry
367             implAddEntry(
368                 xMeta,
369                 aIter->first,
370                 sal_False
371             );
372         }
373 
374         if ( !m_bNoEmptyFolders && lcl_shouldDisplayEmptySchemasAndCatalogs( _rxConnection ) )
375         {
376             sal_Bool bSupportsCatalogs = xMeta->supportsCatalogsInDataManipulation();
377             sal_Bool bSupportsSchemas = xMeta->supportsSchemasInDataManipulation();
378 
379             if ( bSupportsCatalogs || bSupportsSchemas )
380             {
381                 // we display empty catalogs if the DB supports catalogs, and they're noted at the beginning of a
382                 // composed name. Otherwise, we display empty schematas. (also see the tree structure explained in
383                 // implAddEntry)
384                 bool bCatalogs = bSupportsCatalogs && xMeta->isCatalogAtStart();
385 
386                 ::std::vector< ::rtl::OUString > aFolderNames( lcl_getMetaDataStrings_throw(
387                     bCatalogs ? xMeta->getCatalogs() : xMeta->getSchemas(), 1 ) );
388                 sal_Int32 nFolderType = bCatalogs ? DatabaseObjectContainer::CATALOG : DatabaseObjectContainer::SCHEMA;
389 
390                 SvLBoxEntry* pRootEntry = getAllObjectsEntry();
391                 for (   ::std::vector< ::rtl::OUString >::const_iterator folder = aFolderNames.begin();
392                         folder != aFolderNames.end();
393                         ++folder
394                     )
395                 {
396                     SvLBoxEntry* pFolder = GetEntryPosByName( *folder, pRootEntry );
397                     if ( !pFolder )
398                         pFolder = InsertEntry( *folder, pRootEntry, sal_False, LIST_APPEND, reinterpret_cast< void* >( nFolderType ) );
399                 }
400             }
401         }
402     }
403     catch ( const Exception& )
404     {
405         DBG_UNHANDLED_EXCEPTION();
406     }
407 }
408 //------------------------------------------------------------------------
409 sal_Bool OTableTreeListBox::isWildcardChecked(SvLBoxEntry* _pEntry) const
410 {
411     if (_pEntry)
412     {
413         OBoldListboxString* pTextItem = static_cast<OBoldListboxString*>(_pEntry->GetFirstItem(SV_ITEM_ID_BOLDLBSTRING));
414         if (pTextItem)
415             return pTextItem->isEmphasized();
416     }
417     return sal_False;
418 }
419 
420 //------------------------------------------------------------------------
421 void OTableTreeListBox::checkWildcard(SvLBoxEntry* _pEntry)
422 {
423     SetCheckButtonState(_pEntry, SV_BUTTON_CHECKED);
424     checkedButton_noBroadcast(_pEntry);
425 }
426 
427 //------------------------------------------------------------------------
428 SvLBoxEntry* OTableTreeListBox::getAllObjectsEntry() const
429 {
430     return haveVirtualRoot() ? First() : NULL;
431 }
432 
433 //------------------------------------------------------------------------
434 void OTableTreeListBox::checkedButton_noBroadcast(SvLBoxEntry* _pEntry)
435 {
436     OMarkableTreeListBox::checkedButton_noBroadcast(_pEntry);
437 
438     // if an entry has children, it makes a difference if the entry is checked because alls children are checked
439     // or if the user checked it explicitly.
440     // So we track explicit (un)checking
441 
442     SvButtonState eState = GetCheckButtonState(_pEntry);
443     DBG_ASSERT(SV_BUTTON_TRISTATE != eState, "OTableTreeListBox::CheckButtonHdl: user action which lead to TRISTATE?");
444     implEmphasize(_pEntry, SV_BUTTON_CHECKED == eState);
445 }
446 
447 //------------------------------------------------------------------------
448 void OTableTreeListBox::implEmphasize(SvLBoxEntry* _pEntry, sal_Bool _bChecked, sal_Bool _bUpdateDescendants, sal_Bool _bUpdateAncestors)
449 {
450     DBG_ASSERT(_pEntry, "OTableTreeListBox::implEmphasize: invalid entry (NULL)!");
451 
452     // special emphasizing handling for the "all objects" entry
453     // 89709 - 16.07.2001 - frank.schoenheit@sun.com
454     sal_Bool bAllObjectsEntryAffected = haveVirtualRoot() && (getAllObjectsEntry() == _pEntry);
455     if  (   GetModel()->HasChilds(_pEntry)              // the entry has children
456         ||  bAllObjectsEntryAffected                    // or it is the "all objects" entry
457         )
458     {
459         OBoldListboxString* pTextItem = static_cast<OBoldListboxString*>(_pEntry->GetFirstItem(SV_ITEM_ID_BOLDLBSTRING));
460         if (pTextItem)
461             pTextItem->emphasize(_bChecked);
462 
463         if (bAllObjectsEntryAffected)
464             InvalidateEntry(_pEntry);
465     }
466 
467     if (_bUpdateDescendants)
468     {
469         // remove the mark for all children of the checked entry
470         SvLBoxEntry* pChildLoop = FirstChild(_pEntry);
471         while (pChildLoop)
472         {
473             if (GetModel()->HasChilds(pChildLoop))
474                 implEmphasize(pChildLoop, sal_False, sal_True, sal_False);
475             pChildLoop = NextSibling(pChildLoop);
476         }
477     }
478 
479     if (_bUpdateAncestors)
480     {
481         // remove the mark for all ancestors of the entry
482         if (GetModel()->HasParent(_pEntry))
483             implEmphasize(GetParent(_pEntry), sal_False, sal_False, sal_True);
484     }
485 }
486 
487 //------------------------------------------------------------------------
488 void OTableTreeListBox::InitEntry(SvLBoxEntry* _pEntry, const XubString& _rString, const Image& _rCollapsedBitmap, const Image& _rExpandedBitmap, SvLBoxButtonKind _eButtonKind)
489 {
490     OMarkableTreeListBox::InitEntry(_pEntry, _rString, _rCollapsedBitmap, _rExpandedBitmap, _eButtonKind);
491 
492     // replace the text item with our own one
493     SvLBoxItem* pTextItem = _pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING);
494     DBG_ASSERT(pTextItem, "OTableTreeListBox::InitEntry: no text item!?");
495     sal_uInt16 nTextPos = _pEntry->GetPos(pTextItem);
496     DBG_ASSERT(((sal_uInt16)-1) != nTextPos, "OTableTreeListBox::InitEntry: no text item pos!");
497 
498     _pEntry->ReplaceItem(new OBoldListboxString(_pEntry, 0, _rString), nTextPos);
499 }
500 
501 //------------------------------------------------------------------------
502 SvLBoxEntry* OTableTreeListBox::implAddEntry(
503         const Reference< XDatabaseMetaData >& _rxMeta,
504         const ::rtl::OUString& _rTableName,
505         sal_Bool _bCheckName
506     )
507 {
508     OSL_PRECOND( _rxMeta.is(), "OTableTreeListBox::implAddEntry: invalid meta data!" );
509     if ( !_rxMeta.is() )
510         return NULL;
511 
512     // split the complete name into it's components
513     ::rtl::OUString sCatalog, sSchema, sName;
514     qualifiedNameComponents( _rxMeta, _rTableName, sCatalog, sSchema, sName, ::dbtools::eInDataManipulation );
515 
516     SvLBoxEntry* pParentEntry = getAllObjectsEntry();
517 
518     // if the DB uses catalog at the start of identifiers, then our hierarchy is
519     //   catalog
520     //   +- schema
521     //      +- table
522     // else it is
523     //   schema
524     //   +- catalog
525     //      +- table
526     sal_Bool bCatalogAtStart = _rxMeta->isCatalogAtStart();
527     const ::rtl::OUString& rFirstName  = bCatalogAtStart ? sCatalog : sSchema;
528     const sal_Int32 nFirstFolderType   = bCatalogAtStart ? DatabaseObjectContainer::CATALOG : DatabaseObjectContainer::SCHEMA;
529     const ::rtl::OUString& rSecondName = bCatalogAtStart ? sSchema : sCatalog;
530     const sal_Int32 nSecondFolderType  = bCatalogAtStart ? DatabaseObjectContainer::SCHEMA : DatabaseObjectContainer::CATALOG;
531 
532     if ( rFirstName.getLength() )
533     {
534         SvLBoxEntry* pFolder = GetEntryPosByName( rFirstName, pParentEntry );
535         if ( !pFolder )
536             pFolder = InsertEntry( rFirstName, pParentEntry, sal_False, LIST_APPEND, reinterpret_cast< void* >( nFirstFolderType ) );
537         pParentEntry = pFolder;
538     }
539 
540     if ( rSecondName.getLength() )
541     {
542         SvLBoxEntry* pFolder = GetEntryPosByName( rSecondName, pParentEntry );
543         if ( !pFolder )
544             pFolder = InsertEntry( rSecondName, pParentEntry, sal_False, LIST_APPEND, reinterpret_cast< void* >( nSecondFolderType ) );
545         pParentEntry = pFolder;
546     }
547 
548     SvLBoxEntry* pRet = NULL;
549     if ( !_bCheckName || !GetEntryPosByName( sName, pParentEntry ) )
550     {
551         pRet = InsertEntry( sName, pParentEntry, sal_False, LIST_APPEND );
552 
553         Image aImage, aImageHC;
554         m_pImageProvider->getImages( _rTableName, DatabaseObject::TABLE, aImage, aImageHC );
555 
556         SetExpandedEntryBmp( pRet, aImage, BMP_COLOR_NORMAL );
557         SetCollapsedEntryBmp( pRet, aImage, BMP_COLOR_NORMAL );
558         SetExpandedEntryBmp( pRet, aImageHC, BMP_COLOR_HIGHCONTRAST );
559         SetCollapsedEntryBmp( pRet, aImageHC, BMP_COLOR_HIGHCONTRAST );
560     }
561     return pRet;
562 }
563 
564 //------------------------------------------------------------------------
565 NamedDatabaseObject OTableTreeListBox::describeObject( SvLBoxEntry* _pEntry )
566 {
567     NamedDatabaseObject aObject;
568 
569     sal_Int32 nEntryType = reinterpret_cast< sal_IntPtr >( _pEntry->GetUserData() );
570 
571     if  ( nEntryType == DatabaseObjectContainer::TABLES )
572     {
573         aObject.Type = DatabaseObjectContainer::TABLES;
574     }
575     else if (   ( nEntryType == DatabaseObjectContainer::CATALOG )
576             ||  ( nEntryType == DatabaseObjectContainer::SCHEMA )
577             )
578     {
579         SvLBoxEntry* pParent = GetParent( _pEntry );
580         sal_Int32 nParentEntryType = pParent ? reinterpret_cast< sal_IntPtr >( pParent->GetUserData() ) : -1;
581 
582         ::rtl::OUStringBuffer buffer;
583         if  ( nEntryType == DatabaseObjectContainer::CATALOG )
584         {
585             if ( nParentEntryType == DatabaseObjectContainer::SCHEMA )
586             {
587                 buffer.append( GetEntryText( pParent ) );
588                 buffer.append( sal_Unicode( '.' ) );
589             }
590             buffer.append( GetEntryText( _pEntry ) );
591         }
592         else if ( nEntryType == DatabaseObjectContainer::SCHEMA )
593         {
594             if ( nParentEntryType == DatabaseObjectContainer::CATALOG )
595             {
596                 buffer.append( GetEntryText( pParent ) );
597                 buffer.append( sal_Unicode( '.' ) );
598             }
599             buffer.append( GetEntryText( _pEntry ) );
600         }
601     }
602     else
603     {
604         aObject.Type = DatabaseObject::TABLE;
605         aObject.Name = getQualifiedTableName( _pEntry );
606     }
607 
608     return aObject;
609 }
610 
611 //------------------------------------------------------------------------
612 SvLBoxEntry* OTableTreeListBox::addedTable( const ::rtl::OUString& _rName )
613 {
614     try
615     {
616         Reference< XDatabaseMetaData > xMeta;
617         if ( impl_getAndAssertMetaData( xMeta ) )
618             return implAddEntry( xMeta, _rName );
619     }
620     catch( const Exception& )
621     {
622         DBG_UNHANDLED_EXCEPTION();
623     }
624     return NULL;
625 }
626 
627 //------------------------------------------------------------------------
628 bool OTableTreeListBox::impl_getAndAssertMetaData( Reference< XDatabaseMetaData >& _out_rMetaData ) const
629 {
630     if ( m_xConnection.is() )
631         _out_rMetaData = m_xConnection->getMetaData();
632     OSL_PRECOND( _out_rMetaData.is(), "OTableTreeListBox::impl_getAndAssertMetaData: invalid current connection!" );
633     return _out_rMetaData.is();
634 }
635 
636 //------------------------------------------------------------------------
637 String OTableTreeListBox::getQualifiedTableName( SvLBoxEntry* _pEntry ) const
638 {
639     OSL_PRECOND( !isFolderEntry( _pEntry ), "OTableTreeListBox::getQualifiedTableName: folder entries not allowed here!" );
640 
641     try
642     {
643         Reference< XDatabaseMetaData > xMeta;
644         if ( !impl_getAndAssertMetaData( xMeta ) )
645             return String();
646 
647         ::rtl::OUString sCatalog;
648         ::rtl::OUString sSchema;
649         ::rtl::OUString sTable;
650 
651         SvLBoxEntry* pSchema = GetParent( _pEntry );
652         if ( pSchema )
653         {
654             SvLBoxEntry* pCatalog = GetParent( pSchema );
655             if  (   pCatalog
656                 ||  (   xMeta->supportsCatalogsInDataManipulation()
657                     &&  !xMeta->supportsSchemasInDataManipulation()
658                     )   // here we support catalog but no schema
659                 )
660             {
661                 if ( pCatalog == NULL )
662                 {
663                     pCatalog = pSchema;
664                     pSchema = NULL;
665                 }
666                 sCatalog = GetEntryText( pCatalog );
667             }
668             if ( pSchema )
669                 sSchema = GetEntryText(pSchema);
670         }
671         sTable = GetEntryText( _pEntry );
672 
673         return ::dbtools::composeTableName( xMeta, sCatalog, sSchema, sTable, sal_False, ::dbtools::eInDataManipulation );
674     }
675     catch( const Exception& )
676     {
677         DBG_UNHANDLED_EXCEPTION();
678     }
679     return String();
680 }
681 
682 //------------------------------------------------------------------------
683 SvLBoxEntry* OTableTreeListBox::getEntryByQualifiedName( const ::rtl::OUString& _rName )
684 {
685     try
686     {
687         Reference< XDatabaseMetaData > xMeta;
688         if ( !impl_getAndAssertMetaData( xMeta ) )
689             return NULL;
690 
691         // split the complete name into it's components
692         ::rtl::OUString sCatalog, sSchema, sName;
693         qualifiedNameComponents(xMeta, _rName, sCatalog, sSchema, sName,::dbtools::eInDataManipulation);
694 
695         SvLBoxEntry* pParent = getAllObjectsEntry();
696         SvLBoxEntry* pCat = NULL;
697         SvLBoxEntry* pSchema = NULL;
698         if ( sCatalog.getLength() )
699         {
700             pCat = GetEntryPosByName(sCatalog, pParent);
701             if ( pCat )
702                 pParent = pCat;
703         }
704 
705         if ( sSchema.getLength() )
706         {
707             pSchema = GetEntryPosByName(sSchema, pParent);
708             if ( pSchema )
709                 pParent = pSchema;
710         }
711 
712         return GetEntryPosByName(sName, pParent);
713     }
714     catch( const Exception& )
715     {
716         DBG_UNHANDLED_EXCEPTION();
717     }
718     return NULL;
719 }
720 //------------------------------------------------------------------------
721 void OTableTreeListBox::removedTable( const ::rtl::OUString& _rName )
722 {
723     try
724     {
725         SvLBoxEntry* pEntry = getEntryByQualifiedName( _rName );
726         if ( pEntry )
727             GetModel()->Remove( pEntry );
728     }
729     catch( const Exception& )
730     {
731         DBG_UNHANDLED_EXCEPTION();
732     }
733 }
734 
735 //.........................................................................
736 }   // namespace dbaui
737 //.........................................................................
738 
739