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 #include "adtabdlg.hxx" 32 #include "adtabdlg.hrc" 33 #include "sqlmessage.hxx" 34 #include <tools/debug.hxx> 35 #include <tools/diagnose_ex.h> 36 #include <svtools/localresaccess.hxx> 37 #include "dbaccess_helpid.hrc" 38 #include "dbu_resource.hrc" 39 #include "dbu_dlg.hrc" 40 #include <sfx2/sfxsids.hrc> 41 #include "QueryTableView.hxx" 42 #include "QueryDesignView.hxx" 43 #include "querycontroller.hxx" 44 #include <connectivity/dbtools.hxx> 45 #include "browserids.hxx" 46 #include <com/sun/star/sdb/XQueriesSupplier.hpp> 47 #include <com/sun/star/sdbcx/XViewsSupplier.hpp> 48 #include <com/sun/star/sdbcx/XTablesSupplier.hpp> 49 #include <com/sun/star/container/XNameAccess.hpp> 50 #include "UITools.hxx" 51 #include "imageprovider.hxx" 52 53 #include <comphelper/containermultiplexer.hxx> 54 #include "cppuhelper/basemutex.hxx" 55 #include <algorithm> 56 57 // slot ids 58 using namespace dbaui; 59 using namespace ::com::sun::star; 60 using namespace ::com::sun::star::uno; 61 using namespace ::com::sun::star::container; 62 using namespace ::com::sun::star::sdb; 63 using namespace ::com::sun::star::sdbc; 64 using namespace ::com::sun::star::sdbcx; 65 using namespace dbtools; 66 67 //============================================================================== 68 //= TableObjectListFacade 69 //============================================================================== 70 TableObjectListFacade::~TableObjectListFacade() 71 { 72 } 73 74 //============================================================================== 75 //= TableListFacade 76 //============================================================================== 77 class TableListFacade : public ::cppu::BaseMutex 78 , public TableObjectListFacade 79 , public ::comphelper::OContainerListener 80 { 81 OTableTreeListBox& m_rTableList; 82 Reference< XConnection > m_xConnection; 83 ::rtl::Reference< comphelper::OContainerListenerAdapter> 84 m_pContainerListener; 85 bool m_bAllowViews; 86 87 public: 88 TableListFacade( OTableTreeListBox& _rTableList, const Reference< XConnection >& _rxConnection ) 89 : ::comphelper::OContainerListener(m_aMutex) 90 ,m_rTableList( _rTableList ) 91 ,m_xConnection( _rxConnection ) 92 ,m_bAllowViews(true) 93 { 94 } 95 virtual ~TableListFacade(); 96 97 98 private: 99 virtual void updateTableObjectList( bool _bAllowViews ); 100 virtual String getSelectedName( String& _out_rAliasName ) const; 101 virtual bool isLeafSelected() const; 102 // OContainerListener 103 virtual void _elementInserted( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException); 104 virtual void _elementRemoved( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException); 105 virtual void _elementReplaced( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException); 106 }; 107 108 TableListFacade::~TableListFacade() 109 { 110 if ( m_pContainerListener.is() ) 111 m_pContainerListener->dispose(); 112 } 113 //------------------------------------------------------------------------------ 114 String TableListFacade::getSelectedName( String& _out_rAliasName ) const 115 { 116 SvLBoxEntry* pEntry = m_rTableList.FirstSelected(); 117 if ( !pEntry ) 118 return String(); 119 120 ::rtl::OUString aCatalog, aSchema, aTableName; 121 SvLBoxEntry* pSchema = m_rTableList.GetParent(pEntry); 122 if(pSchema && pSchema != m_rTableList.getAllObjectsEntry()) 123 { 124 SvLBoxEntry* pCatalog = m_rTableList.GetParent(pSchema); 125 if(pCatalog && pCatalog != m_rTableList.getAllObjectsEntry()) 126 aCatalog = m_rTableList.GetEntryText(pCatalog); 127 aSchema = m_rTableList.GetEntryText(pSchema); 128 } 129 aTableName = m_rTableList.GetEntryText(pEntry); 130 131 ::rtl::OUString aComposedName; 132 try 133 { 134 Reference< XDatabaseMetaData > xMeta( m_xConnection->getMetaData(), UNO_QUERY_THROW ); 135 if ( !aCatalog.getLength() 136 && aSchema.getLength() 137 && xMeta->supportsCatalogsInDataManipulation() 138 && !xMeta->supportsSchemasInDataManipulation() ) 139 { 140 aCatalog = aSchema; 141 aSchema = ::rtl::OUString(); 142 } 143 144 aComposedName = ::dbtools::composeTableName( 145 xMeta, aCatalog, aSchema, aTableName, sal_False, ::dbtools::eInDataManipulation ); 146 } 147 catch ( const Exception& ) 148 { 149 DBG_UNHANDLED_EXCEPTION(); 150 } 151 152 _out_rAliasName = aTableName; 153 return aComposedName; 154 } 155 // ----------------------------------------------------------------------------- 156 void TableListFacade::_elementInserted( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException) 157 { 158 updateTableObjectList(m_bAllowViews); 159 } 160 // ----------------------------------------------------------------------------- 161 void TableListFacade::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException) 162 { 163 updateTableObjectList(m_bAllowViews); 164 } 165 // ----------------------------------------------------------------------------- 166 void TableListFacade::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException) 167 { 168 } 169 //------------------------------------------------------------------------------ 170 void TableListFacade::updateTableObjectList( bool _bAllowViews ) 171 { 172 m_bAllowViews = _bAllowViews; 173 m_rTableList.Clear(); 174 try 175 { 176 Reference< XTablesSupplier > xTableSupp( m_xConnection, UNO_QUERY_THROW ); 177 178 Reference< XViewsSupplier > xViewSupp; 179 Reference< XNameAccess > xTables, xViews; 180 Sequence< ::rtl::OUString > sTables, sViews; 181 182 xTables = xTableSupp->getTables(); 183 if ( xTables.is() ) 184 { 185 if ( !m_pContainerListener.is() ) 186 { 187 Reference< XContainer> xContainer(xTables,uno::UNO_QUERY); 188 if ( xContainer.is() ) 189 m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer); 190 } 191 sTables = xTables->getElementNames(); 192 } // if ( xTables.is() ) 193 194 xViewSupp.set( xTableSupp, UNO_QUERY ); 195 if ( xViewSupp.is() ) 196 { 197 xViews = xViewSupp->getViews(); 198 if ( xViews.is() ) 199 sViews = xViews->getElementNames(); 200 } 201 202 // if no views are allowed remove the views also out the table name filter 203 if ( !_bAllowViews ) 204 { 205 const ::rtl::OUString* pTableBegin = sTables.getConstArray(); 206 const ::rtl::OUString* pTableEnd = pTableBegin + sTables.getLength(); 207 ::std::vector< ::rtl::OUString > aTables(pTableBegin,pTableEnd); 208 209 const ::rtl::OUString* pViewBegin = sViews.getConstArray(); 210 const ::rtl::OUString* pViewEnd = pViewBegin + sViews.getLength(); 211 ::comphelper::TStringMixEqualFunctor aEqualFunctor; 212 for(;pViewBegin != pViewEnd;++pViewBegin) 213 aTables.erase(::std::remove_if(aTables.begin(),aTables.end(),::std::bind2nd(aEqualFunctor,*pViewBegin)),aTables.end()); 214 ::rtl::OUString* pTables = aTables.empty() ? 0 : &aTables[0]; 215 sTables = Sequence< ::rtl::OUString>(pTables, aTables.size()); 216 sViews = Sequence< ::rtl::OUString>(); 217 } 218 219 m_rTableList.UpdateTableList( m_xConnection, sTables, sViews ); 220 SvLBoxEntry* pEntry = m_rTableList.First(); 221 while( pEntry && m_rTableList.GetModel()->HasChilds( pEntry ) ) 222 { 223 m_rTableList.Expand( pEntry ); 224 pEntry = m_rTableList.Next( pEntry ); 225 } 226 if ( pEntry ) 227 m_rTableList.Select(pEntry); 228 } 229 catch( const Exception& ) 230 { 231 DBG_UNHANDLED_EXCEPTION(); 232 } 233 } 234 235 //------------------------------------------------------------------------------ 236 bool TableListFacade::isLeafSelected() const 237 { 238 SvLBoxEntry* pEntry = m_rTableList.FirstSelected(); 239 return pEntry && !m_rTableList.GetModel()->HasChilds( pEntry ); 240 } 241 242 //============================================================================== 243 //= QueryListFacade 244 //============================================================================== 245 class QueryListFacade : public ::cppu::BaseMutex 246 , public TableObjectListFacade 247 , public ::comphelper::OContainerListener 248 { 249 SvTreeListBox& m_rQueryList; 250 Reference< XConnection > m_xConnection; 251 ::rtl::Reference< comphelper::OContainerListenerAdapter> 252 m_pContainerListener; 253 254 public: 255 QueryListFacade( SvTreeListBox& _rQueryList, const Reference< XConnection >& _rxConnection ) 256 : ::comphelper::OContainerListener(m_aMutex) 257 ,m_rQueryList( _rQueryList ) 258 ,m_xConnection( _rxConnection ) 259 { 260 } 261 virtual ~QueryListFacade(); 262 private: 263 virtual void updateTableObjectList( bool _bAllowViews ); 264 virtual String getSelectedName( String& _out_rAliasName ) const; 265 virtual bool isLeafSelected() const; 266 // OContainerListener 267 virtual void _elementInserted( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException); 268 virtual void _elementRemoved( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException); 269 virtual void _elementReplaced( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException); 270 }; 271 QueryListFacade::~QueryListFacade() 272 { 273 if ( m_pContainerListener.is() ) 274 m_pContainerListener->dispose(); 275 } 276 // ----------------------------------------------------------------------------- 277 void QueryListFacade::_elementInserted( const container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException) 278 { 279 ::rtl::OUString sName; 280 if ( _rEvent.Accessor >>= sName ) 281 m_rQueryList.InsertEntry( sName ); 282 } 283 // ----------------------------------------------------------------------------- 284 void QueryListFacade::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException) 285 { 286 updateTableObjectList(true); 287 } 288 // ----------------------------------------------------------------------------- 289 void QueryListFacade::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException) 290 { 291 } 292 293 //------------------------------------------------------------------------------ 294 void QueryListFacade::updateTableObjectList( bool /*_bAllowViews*/ ) 295 { 296 m_rQueryList.Clear(); 297 try 298 { 299 ImageProvider aImageProvider( m_xConnection ); 300 Image aQueryImage( aImageProvider.getDefaultImage( DatabaseObject::QUERY, false ) ); 301 Image aQueryImageHC( aImageProvider.getDefaultImage( DatabaseObject::QUERY, true ) ); 302 303 m_rQueryList.SetDefaultExpandedEntryBmp( aQueryImage, BMP_COLOR_NORMAL ); 304 m_rQueryList.SetDefaultCollapsedEntryBmp( aQueryImage, BMP_COLOR_NORMAL ); 305 m_rQueryList.SetDefaultExpandedEntryBmp( aQueryImageHC, BMP_COLOR_HIGHCONTRAST ); 306 m_rQueryList.SetDefaultCollapsedEntryBmp( aQueryImageHC, BMP_COLOR_HIGHCONTRAST ); 307 308 Reference< XQueriesSupplier > xSuppQueries( m_xConnection, UNO_QUERY_THROW ); 309 Reference< XNameAccess > xQueries( xSuppQueries->getQueries(), UNO_QUERY_THROW ); 310 if ( !m_pContainerListener.is() ) 311 { 312 Reference< XContainer> xContainer(xQueries,UNO_QUERY_THROW); 313 m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer); 314 } 315 Sequence< ::rtl::OUString > aQueryNames = xQueries->getElementNames(); 316 317 const ::rtl::OUString* pQuery = aQueryNames.getConstArray(); 318 const ::rtl::OUString* pQueryEnd = aQueryNames.getConstArray() + aQueryNames.getLength(); 319 while ( pQuery != pQueryEnd ) 320 m_rQueryList.InsertEntry( *pQuery++ ); 321 } 322 catch( const Exception& ) 323 { 324 DBG_UNHANDLED_EXCEPTION(); 325 } 326 } 327 328 //------------------------------------------------------------------------------ 329 String QueryListFacade::getSelectedName( String& _out_rAliasName ) const 330 { 331 String sSelected; 332 SvLBoxEntry* pEntry = m_rQueryList.FirstSelected(); 333 if ( pEntry ) 334 sSelected = _out_rAliasName = m_rQueryList.GetEntryText( pEntry ); 335 return sSelected; 336 } 337 338 //------------------------------------------------------------------------------ 339 bool QueryListFacade::isLeafSelected() const 340 { 341 SvLBoxEntry* pEntry = m_rQueryList.FirstSelected(); 342 return pEntry && !m_rQueryList.GetModel()->HasChilds( pEntry ); 343 } 344 345 //============================================================================== 346 //= OAddTableDlg 347 //============================================================================== 348 //------------------------------------------------------------------------------ 349 OAddTableDlg::OAddTableDlg( Window* pParent, IAddTableDialogContext& _rContext ) 350 :ModelessDialog( pParent, ModuleRes(DLG_JOIN_TABADD) ) 351 ,m_aCaseTables( this, ModuleRes( RB_CASE_TABLES ) ) 352 ,m_aCaseQueries( this, ModuleRes( RB_CASE_QUERIES ) ) 353 ,m_aTableList( this, NULL, ModuleRes( LB_TABLE_OR_QUERY ), sal_False ) 354 ,m_aQueryList( this, ModuleRes( LB_TABLE_OR_QUERY ) ) 355 ,aAddButton( this, ModuleRes( PB_ADDTABLE ) ) 356 ,aCloseButton( this, ModuleRes( PB_CLOSE ) ) 357 ,aHelpButton( this, ModuleRes( PB_HELP ) ) 358 ,m_rContext( _rContext ) 359 { 360 // der Close-Button hat schon einen Standard-Help-Text, den ich aber hier nicht haben moechte, also den Text ruecksetzen 361 // und eine neue ID verteilen 362 aCloseButton.SetHelpText(String()); 363 aCloseButton.SetHelpId(HID_JOINSH_ADDTAB_CLOSE); 364 365 m_aTableList.SetHelpId( HID_JOINSH_ADDTAB_TABLELIST ); 366 m_aQueryList.SetHelpId( HID_JOINSH_ADDTAB_QUERYLIST ); 367 368 ////////////////////////////////////////////////////////////////////// 369 m_aCaseTables.SetClickHdl( LINK( this, OAddTableDlg, OnTypeSelected ) ); 370 m_aCaseQueries.SetClickHdl( LINK( this, OAddTableDlg, OnTypeSelected ) ); 371 aAddButton.SetClickHdl( LINK( this, OAddTableDlg, AddClickHdl ) ); 372 aCloseButton.SetClickHdl( LINK( this, OAddTableDlg, CloseClickHdl ) ); 373 m_aTableList.SetDoubleClickHdl( LINK( this, OAddTableDlg, TableListDoubleClickHdl ) ); 374 m_aTableList.SetSelectHdl( LINK( this, OAddTableDlg, TableListSelectHdl ) ); 375 m_aQueryList.SetDoubleClickHdl( LINK( this, OAddTableDlg, TableListDoubleClickHdl ) ); 376 m_aQueryList.SetSelectHdl( LINK( this, OAddTableDlg, TableListSelectHdl ) ); 377 378 ////////////////////////////////////////////////////////////////////// 379 m_aTableList.EnableInplaceEditing( sal_False ); 380 m_aTableList.SetStyle(m_aTableList.GetStyle() | WB_BORDER | WB_HASLINES |WB_HASBUTTONS | WB_HASBUTTONSATROOT | WB_HASLINESATROOT | WB_SORT | WB_HSCROLL ); 381 m_aTableList.EnableCheckButton( NULL ); // do not show any buttons 382 m_aTableList.SetSelectionMode( SINGLE_SELECTION ); 383 m_aTableList.notifyHiContrastChanged(); 384 m_aTableList.suppressEmptyFolders(); 385 386 ////////////////////////////////////////////////////////////////////// 387 m_aQueryList.EnableInplaceEditing( sal_False ); 388 m_aQueryList.SetSelectionMode( SINGLE_SELECTION ); 389 390 ////////////////////////////////////////////////////////////////////// 391 if ( !m_rContext.allowQueries() ) 392 { 393 m_aCaseTables.Hide(); 394 m_aCaseQueries.Hide(); 395 396 long nPixelDiff = m_aTableList.GetPosPixel().Y() - m_aCaseTables.GetPosPixel().Y(); 397 398 Point aListPos( m_aTableList.GetPosPixel() ); 399 aListPos.Y() -= nPixelDiff; 400 401 Size aListSize( m_aTableList.GetSizePixel() ); 402 aListSize.Height() += nPixelDiff; 403 404 m_aTableList.SetPosSizePixel( aListPos, aListSize ); 405 } 406 407 FreeResource(); 408 409 SetText( getDialogTitleForContext( m_rContext ) ); 410 } 411 412 //------------------------------------------------------------------------------ 413 OAddTableDlg::~OAddTableDlg() 414 { 415 m_rContext.onWindowClosing( this ); 416 } 417 418 //------------------------------------------------------------------------------ 419 void OAddTableDlg::impl_switchTo( ObjectList _eList ) 420 { 421 switch ( _eList ) 422 { 423 case Tables: 424 m_aTableList.Show( sal_True ); m_aCaseTables.Check( sal_True ); 425 m_aQueryList.Show( sal_False ); m_aCaseQueries.Check( sal_False ); 426 m_pCurrentList.reset( new TableListFacade( m_aTableList, m_rContext.getConnection() ) ); 427 m_aTableList.GrabFocus(); 428 break; 429 430 case Queries: 431 m_aTableList.Show( sal_False ); m_aCaseTables.Check( sal_False ); 432 m_aQueryList.Show( sal_True ); m_aCaseQueries.Check( sal_True ); 433 m_pCurrentList.reset( new QueryListFacade( m_aQueryList, m_rContext.getConnection() ) ); 434 m_aQueryList.GrabFocus(); 435 break; 436 } 437 m_pCurrentList->updateTableObjectList( m_rContext.allowViews() ); 438 } 439 440 //------------------------------------------------------------------------------ 441 void OAddTableDlg::Update() 442 { 443 if ( !m_pCurrentList.get() ) 444 impl_switchTo( Tables ); 445 else 446 m_pCurrentList->updateTableObjectList( m_rContext.allowViews() ); 447 } 448 449 //------------------------------------------------------------------------------ 450 void OAddTableDlg::impl_addTable() 451 { 452 if ( m_pCurrentList->isLeafSelected() ) 453 { 454 String sSelectedName, sAliasName; 455 sSelectedName = m_pCurrentList->getSelectedName( sAliasName ); 456 457 m_rContext.addTableWindow( sSelectedName, sAliasName ); 458 } 459 } 460 461 //------------------------------------------------------------------------------ 462 IMPL_LINK( OAddTableDlg, AddClickHdl, Button*, /*pButton*/ ) 463 { 464 TableListDoubleClickHdl(NULL); 465 return 0; 466 } 467 468 //------------------------------------------------------------------------------ 469 IMPL_LINK( OAddTableDlg, TableListDoubleClickHdl, void*, /*EMPTY_ARG*/ ) 470 { 471 if ( impl_isAddAllowed() ) 472 { 473 impl_addTable(); 474 if ( !impl_isAddAllowed() ) 475 Close(); 476 return 1L; // handled 477 } 478 479 return 0L; // not handled 480 } 481 482 //------------------------------------------------------------------------------ 483 IMPL_LINK( OAddTableDlg, TableListSelectHdl, void*, /*EMPTY_ARG*/ ) 484 { 485 aAddButton.Enable( m_pCurrentList->isLeafSelected() ); 486 return 0; 487 } 488 489 //------------------------------------------------------------------------------ 490 IMPL_LINK( OAddTableDlg, CloseClickHdl, Button*, /*pButton*/ ) 491 { 492 return Close(); 493 } 494 495 //------------------------------------------------------------------------------ 496 IMPL_LINK( OAddTableDlg, OnTypeSelected, void*, /*EMPTY_ARG*/ ) 497 { 498 if ( m_aCaseTables.IsChecked() ) 499 impl_switchTo( Tables ); 500 else 501 impl_switchTo( Queries ); 502 return 0; 503 } 504 505 //------------------------------------------------------------------------------ 506 sal_Bool OAddTableDlg::Close() 507 { 508 m_rContext.onWindowClosing( this ); 509 return ModelessDialog::Close(); 510 } 511 512 //------------------------------------------------------------------------------ 513 bool OAddTableDlg::impl_isAddAllowed() 514 { 515 return m_rContext.allowAddition(); 516 } 517 518 //------------------------------------------------------------------------------ 519 String OAddTableDlg::getDialogTitleForContext( IAddTableDialogContext& _rContext ) 520 { 521 String sTitle; 522 523 ::svt::OLocalResourceAccess aLocalRes( ModuleRes( DLG_JOIN_TABADD ), RSC_MODELESSDIALOG ); 524 if ( _rContext.allowQueries() ) 525 sTitle = String( ModuleRes( STR_ADD_TABLE_OR_QUERY ) ); 526 else 527 sTitle = String( ModuleRes( STR_ADD_TABLES ) ); 528 529 return sTitle; 530 } 531 532 // ----------------------------------------------------------------------------- 533 534