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