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_sw.hxx" 26 27 // INCLUDE --------------------------------------------------------------- 28 29 30 #include <sot/formats.hxx> 31 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 32 #include <com/sun/star/container/XNameAccess.hpp> 33 #include <com/sun/star/sdbc/XDataSource.hpp> 34 #include <com/sun/star/sdbcx/XTablesSupplier.hpp> 35 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 36 #include <com/sun/star/sdb/XQueriesSupplier.hpp> 37 #include <com/sun/star/sdb/XDatabaseAccess.hpp> 38 #include <com/sun/star/sdb/CommandType.hpp> 39 #include <com/sun/star/beans/XPropertySet.hpp> 40 #include <comphelper/processfactory.hxx> 41 #include <com/sun/star/sdb/XCompletedConnection.hpp> 42 #include <com/sun/star/container/XContainerListener.hpp> 43 #include <com/sun/star/container/XContainer.hpp> 44 #include <cppuhelper/implbase1.hxx> 45 #include <svx/dbaexchange.hxx> 46 47 #ifndef _DBMGR_HXX 48 #include <dbmgr.hxx> 49 #endif 50 #include <swmodule.hxx> 51 #ifndef _VIEW_HXX 52 #include <view.hxx> 53 #endif 54 #include <wrtsh.hxx> 55 #include <dbtree.hxx> 56 #include <vos/mutex.hxx> 57 #include <vcl/svapp.hxx> 58 59 #ifndef _HELPID_H 60 #include <helpid.h> 61 #endif 62 #ifndef _UTLUI_HRC 63 #include <utlui.hrc> 64 #endif 65 66 #include <unomid.h> 67 68 using namespace ::com::sun::star; 69 using namespace ::com::sun::star::uno; 70 using namespace ::com::sun::star::container; 71 using namespace ::com::sun::star::lang; 72 using namespace ::com::sun::star::sdb; 73 using namespace ::com::sun::star::sdbc; 74 using namespace ::com::sun::star::sdbcx; 75 using namespace ::com::sun::star::task; 76 using namespace ::com::sun::star::beans; 77 78 /* -----------------------------17.07.01 13:10-------------------------------- 79 80 ---------------------------------------------------------------------------*/ 81 struct SwConnectionData 82 { 83 ::rtl::OUString sSourceName; 84 Reference<XConnection> xConnection; 85 }; 86 87 typedef SwConnectionData* SwConnectionDataPtr; 88 SV_DECL_PTRARR_DEL( SwConnectionArr, SwConnectionDataPtr, 32, 32 ) 89 SV_IMPL_PTRARR( SwConnectionArr, SwConnectionDataPtr ) 90 /* -----------------------------17.07.01 13:24-------------------------------- 91 92 ---------------------------------------------------------------------------*/ 93 class SwDBTreeList_Impl : public cppu::WeakImplHelper1 < XContainerListener > 94 { 95 Reference< XNameAccess > xDBContext; 96 SwConnectionArr aConnections; 97 SwWrtShell* pWrtSh; 98 99 public: 100 SwDBTreeList_Impl(SwWrtShell* pShell) : 101 pWrtSh(pShell) {} 102 ~SwDBTreeList_Impl(); 103 104 virtual void SAL_CALL elementInserted( const ContainerEvent& Event ) throw (RuntimeException); 105 virtual void SAL_CALL elementRemoved( const ContainerEvent& Event ) throw (RuntimeException); 106 virtual void SAL_CALL elementReplaced( const ContainerEvent& Event ) throw (RuntimeException); 107 virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException); 108 109 sal_Bool HasContext(); 110 SwWrtShell* GetWrtShell() { return pWrtSh;} 111 void SetWrtShell(SwWrtShell& rSh) { pWrtSh = &rSh;} 112 Reference< XNameAccess > GetContext() {return xDBContext;} 113 Reference<XConnection> GetConnection(const rtl::OUString& rSourceName); 114 }; 115 /* -----------------------------17.07.01 13:24-------------------------------- 116 117 ---------------------------------------------------------------------------*/ 118 SwDBTreeList_Impl::~SwDBTreeList_Impl() 119 { 120 Reference<XContainer> xContainer(xDBContext, UNO_QUERY); 121 if(xContainer.is()) 122 { 123 m_refCount++; 124 //block necessary due to solaris' compiler behaviour to 125 //remove temporaries at the block's end 126 { 127 xContainer->removeContainerListener( this ); 128 } 129 m_refCount--; 130 } 131 } 132 /* -----------------------------17.07.01 13:24-------------------------------- 133 134 ---------------------------------------------------------------------------*/ 135 void SwDBTreeList_Impl::elementInserted( const ContainerEvent& ) throw (RuntimeException) 136 { 137 // information not needed 138 } 139 /* -----------------------------17.07.01 13:24-------------------------------- 140 141 ---------------------------------------------------------------------------*/ 142 void SwDBTreeList_Impl::elementRemoved( const ContainerEvent& rEvent ) throw (RuntimeException) 143 { 144 vos::OGuard aGuard(Application::GetSolarMutex()); 145 ::rtl::OUString sSource; 146 rEvent.Accessor >>= sSource; 147 for(sal_uInt16 i = 0; i < aConnections.Count(); i++) 148 { 149 SwConnectionDataPtr pPtr = aConnections[i]; 150 if(pPtr->sSourceName == sSource) 151 { 152 // SwConnectionDataPtr pPtr = aConnections[i]; 153 // Reference<XComponent> xComp(pPtr->xConnection, UNO_QUERY); 154 // if(xComp.is()) 155 // xComp->dispose(); 156 aConnections.DeleteAndDestroy(i); 157 break; 158 } 159 } 160 } 161 /* -----------------------------17.07.01 13:24-------------------------------- 162 163 ---------------------------------------------------------------------------*/ 164 void SwDBTreeList_Impl::disposing( const EventObject& ) throw (RuntimeException) 165 { 166 xDBContext = 0; 167 } 168 /* -----------------------------17.07.01 13:24-------------------------------- 169 170 ---------------------------------------------------------------------------*/ 171 void SwDBTreeList_Impl::elementReplaced( const ContainerEvent& rEvent ) throw (RuntimeException) 172 { 173 elementRemoved(rEvent); 174 } 175 /* -----------------------------17.07.01 13:24-------------------------------- 176 177 ---------------------------------------------------------------------------*/ 178 sal_Bool SwDBTreeList_Impl::HasContext() 179 { 180 if(!xDBContext.is()) 181 { 182 Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); 183 if( xMgr.is() ) 184 { 185 Reference<XInterface> xInstance = xMgr->createInstance( 186 C2U( "com.sun.star.sdb.DatabaseContext" )); 187 xDBContext = Reference<XNameAccess>(xInstance, UNO_QUERY) ; 188 Reference<XContainer> xContainer(xDBContext, UNO_QUERY); 189 if(xContainer.is()) 190 xContainer->addContainerListener( this ); 191 } 192 DBG_ASSERT(xDBContext.is(), "com.sun.star.sdb.DataBaseContext: service not available"); 193 } 194 return xDBContext.is(); 195 } 196 /* -----------------------------17.07.01 13:24-------------------------------- 197 198 ---------------------------------------------------------------------------*/ 199 Reference<XConnection> SwDBTreeList_Impl::GetConnection(const rtl::OUString& rSourceName) 200 { 201 Reference<XConnection> xRet; 202 for(sal_uInt16 i = 0; i < aConnections.Count(); i++) 203 { 204 SwConnectionDataPtr pPtr = aConnections[i]; 205 if(pPtr->sSourceName == rSourceName) 206 { 207 xRet = pPtr->xConnection; 208 break; 209 } 210 } 211 if(!xRet.is() && xDBContext.is() && pWrtSh) 212 { 213 SwConnectionDataPtr pPtr = new SwConnectionData(); 214 pPtr->sSourceName = rSourceName; 215 xRet = pWrtSh->GetNewDBMgr()->RegisterConnection(pPtr->sSourceName); 216 aConnections.Insert(pPtr, aConnections.Count()); 217 } 218 return xRet; 219 } 220 /*------------------------------------------------------------------------ 221 Beschreibung: 222 ------------------------------------------------------------------------*/ 223 SwDBTreeList::SwDBTreeList(Window *pParent, const ResId& rResId, 224 SwWrtShell* pSh, 225 const String& rDefDBName, const sal_Bool bShowCol): 226 227 SvTreeListBox (pParent, rResId), 228 aImageList (SW_RES(ILIST_DB_DLG )), 229 aImageListHC (SW_RES(ILIST_DB_DLG_HC )), 230 sDefDBName (rDefDBName), 231 bInitialized (sal_False), 232 bShowColumns (bShowCol), 233 pImpl(new SwDBTreeList_Impl(pSh)) 234 { 235 SetHelpId(HID_DB_SELECTION_TLB); 236 237 if (IsVisible()) 238 InitTreeList(); 239 } 240 241 /*------------------------------------------------------------------------ 242 Beschreibung: 243 ------------------------------------------------------------------------*/ 244 SwDBTreeList::~SwDBTreeList() 245 { 246 delete pImpl; 247 } 248 249 /*------------------------------------------------------------------------ 250 Beschreibung: 251 ------------------------------------------------------------------------*/ 252 253 254 void SwDBTreeList::InitTreeList() 255 { 256 if(!pImpl->HasContext() && pImpl->GetWrtShell()) 257 return; 258 SetSelectionMode(SINGLE_SELECTION); 259 SetStyle(GetStyle()|WB_HASLINES|WB_CLIPCHILDREN|WB_SORT|WB_HASBUTTONS|WB_HASBUTTONSATROOT|WB_HSCROLL); 260 // Font nicht setzen, damit der Font des Controls uebernommen wird! 261 SetSpaceBetweenEntries(0); 262 SetNodeBitmaps( aImageList.GetImage(IMG_COLLAPSE), 263 aImageList.GetImage(IMG_EXPAND ), BMP_COLOR_NORMAL ); 264 SetNodeBitmaps( aImageListHC.GetImage(IMG_COLLAPSE), 265 aImageListHC.GetImage(IMG_EXPAND ), BMP_COLOR_HIGHCONTRAST ); 266 267 SetDragDropMode(SV_DRAGDROP_APP_COPY); 268 269 GetModel()->SetCompareHdl(LINK(this, SwDBTreeList, DBCompare)); 270 271 Sequence< ::rtl::OUString > aDBNames = pImpl->GetContext()->getElementNames(); 272 const ::rtl::OUString* pDBNames = aDBNames.getConstArray(); 273 long nCount = aDBNames.getLength(); 274 275 Image aImg = aImageList.GetImage(IMG_DB); 276 Image aHCImg = aImageListHC.GetImage(IMG_DB); 277 for(long i = 0; i < nCount; i++) 278 { 279 String sDBName(pDBNames[i]); 280 SvLBoxEntry* pEntry = InsertEntry(sDBName, aImg, aImg, NULL, sal_True); 281 SetExpandedEntryBmp(pEntry, aHCImg, BMP_COLOR_HIGHCONTRAST); 282 SetCollapsedEntryBmp(pEntry, aHCImg, BMP_COLOR_HIGHCONTRAST); 283 } 284 String sDBName(sDefDBName.GetToken(0, DB_DELIM)); 285 String sTableName(sDefDBName.GetToken(1, DB_DELIM)); 286 String sColumnName(sDefDBName.GetToken(2, DB_DELIM)); 287 Select(sDBName, sTableName, sColumnName); 288 289 290 bInitialized = sal_True; 291 } 292 /*-- 27.05.2004 09:19:09--------------------------------------------------- 293 294 -----------------------------------------------------------------------*/ 295 void SwDBTreeList::AddDataSource(const String& rSource) 296 { 297 Image aImg = aImageList.GetImage(IMG_DB); 298 Image aHCImg = aImageListHC.GetImage(IMG_DB); 299 SvLBoxEntry* pEntry = InsertEntry(rSource, aImg, aImg, NULL, sal_True); 300 SetExpandedEntryBmp(pEntry, aHCImg, BMP_COLOR_HIGHCONTRAST); 301 SetCollapsedEntryBmp(pEntry, aHCImg, BMP_COLOR_HIGHCONTRAST); 302 SvTreeListBox::Select(pEntry); 303 } 304 /*------------------------------------------------------------------------ 305 Beschreibung: 306 ------------------------------------------------------------------------*/ 307 308 void SwDBTreeList::ShowColumns(sal_Bool bShowCol) 309 { 310 if (bShowCol != bShowColumns) 311 { 312 bShowColumns = bShowCol; 313 String sTableName, sColumnName; 314 String sDBName(GetDBName(sTableName, sColumnName)); 315 316 SetUpdateMode(sal_False); 317 318 SvLBoxEntry* pEntry = First(); 319 320 while (pEntry) 321 { 322 pEntry = (SvLBoxEntry*)GetRootLevelParent( pEntry ); 323 Collapse(pEntry); // zuklappen 324 325 SvLBoxEntry* pChild; 326 while ((pChild = FirstChild(pEntry)) != 0L) 327 GetModel()->Remove(pChild); 328 329 pEntry = Next(pEntry); 330 } 331 332 if (sDBName.Len()) 333 { 334 Select(sDBName, sTableName, sColumnName); // force RequestingChilds 335 } 336 SetUpdateMode(sal_True); 337 } 338 } 339 340 /*------------------------------------------------------------------------ 341 Beschreibung: 342 ------------------------------------------------------------------------*/ 343 344 void SwDBTreeList::RequestingChilds(SvLBoxEntry* pParent) 345 { 346 if (!pParent->HasChilds()) 347 { 348 if (GetParent(pParent)) // column names 349 { 350 try 351 { 352 353 String sSourceName = GetEntryText(GetParent(pParent)); 354 String sTableName = GetEntryText(pParent); 355 356 if(!pImpl->GetContext()->hasByName(sSourceName)) 357 return; 358 Reference<XConnection> xConnection = pImpl->GetConnection(sSourceName); 359 sal_Bool bTable = pParent->GetUserData() == 0; 360 Reference<XColumnsSupplier> xColsSupplier; 361 if(bTable) 362 { 363 Reference<XTablesSupplier> xTSupplier = Reference<XTablesSupplier>(xConnection, UNO_QUERY); 364 if(xTSupplier.is()) 365 { 366 Reference<XNameAccess> xTbls = xTSupplier->getTables(); 367 DBG_ASSERT(xTbls->hasByName(sTableName), "table not available anymore?"); 368 try 369 { 370 Any aTable = xTbls->getByName(sTableName); 371 Reference<XPropertySet> xPropSet; 372 aTable >>= xPropSet; 373 xColsSupplier = Reference<XColumnsSupplier>(xPropSet, UNO_QUERY); 374 } 375 catch(Exception&) 376 {} 377 } 378 } 379 else 380 { 381 Reference<XQueriesSupplier> xQSupplier = Reference<XQueriesSupplier>(xConnection, UNO_QUERY); 382 if(xQSupplier.is()) 383 { 384 Reference<XNameAccess> xQueries = xQSupplier->getQueries(); 385 DBG_ASSERT(xQueries->hasByName(sTableName), "table not available anymore?"); 386 try 387 { 388 Any aQuery = xQueries->getByName(sTableName); 389 Reference<XPropertySet> xPropSet; 390 aQuery >>= xPropSet; 391 xColsSupplier = Reference<XColumnsSupplier>(xPropSet, UNO_QUERY); 392 } 393 catch(Exception&) 394 {} 395 } 396 } 397 398 if(xColsSupplier.is()) 399 { 400 Reference <XNameAccess> xCols = xColsSupplier->getColumns(); 401 Sequence< ::rtl::OUString> aColNames = xCols->getElementNames(); 402 const ::rtl::OUString* pColNames = aColNames.getConstArray(); 403 long nCount = aColNames.getLength(); 404 for (long i = 0; i < nCount; i++) 405 { 406 String sName = pColNames[i]; 407 if(bTable) 408 InsertEntry(sName, pParent); 409 else 410 InsertEntry(sName, pParent); 411 } 412 } 413 } 414 catch(const Exception&) 415 { 416 } 417 } 418 else // Tabellennamen 419 { 420 try 421 { 422 String sSourceName = GetEntryText(pParent); 423 if(!pImpl->GetContext()->hasByName(sSourceName)) 424 return; 425 Reference<XConnection> xConnection = pImpl->GetConnection(sSourceName); 426 if (xConnection.is()) 427 { 428 Reference<XTablesSupplier> xTSupplier = Reference<XTablesSupplier>(xConnection, UNO_QUERY); 429 if(xTSupplier.is()) 430 { 431 Reference<XNameAccess> xTbls = xTSupplier->getTables(); 432 Sequence< ::rtl::OUString> aTblNames = xTbls->getElementNames(); 433 String sTableName; 434 long nCount = aTblNames.getLength(); 435 const ::rtl::OUString* pTblNames = aTblNames.getConstArray(); 436 Image aImg = aImageList.GetImage(IMG_DBTABLE); 437 Image aHCImg = aImageListHC.GetImage(IMG_DBTABLE); 438 for (long i = 0; i < nCount; i++) 439 { 440 sTableName = pTblNames[i]; 441 SvLBoxEntry* pTableEntry = InsertEntry(sTableName, aImg, aImg, pParent, bShowColumns); 442 //to discriminate between queries and tables the user data of table entries is set 443 pTableEntry->SetUserData((void*)0); 444 SetExpandedEntryBmp(pTableEntry, aHCImg, BMP_COLOR_HIGHCONTRAST); 445 SetCollapsedEntryBmp(pTableEntry, aHCImg, BMP_COLOR_HIGHCONTRAST); 446 } 447 } 448 449 Reference<XQueriesSupplier> xQSupplier = Reference<XQueriesSupplier>(xConnection, UNO_QUERY); 450 if(xQSupplier.is()) 451 { 452 Reference<XNameAccess> xQueries = xQSupplier->getQueries(); 453 Sequence< ::rtl::OUString> aQueryNames = xQueries->getElementNames(); 454 String sQueryName; 455 long nCount = aQueryNames.getLength(); 456 const ::rtl::OUString* pQueryNames = aQueryNames.getConstArray(); 457 Image aImg = aImageList.GetImage(IMG_DBQUERY); 458 Image aHCImg = aImageListHC.GetImage(IMG_DBQUERY); 459 for (long i = 0; i < nCount; i++) 460 { 461 sQueryName = pQueryNames[i]; 462 SvLBoxEntry* pQueryEntry = InsertEntry(sQueryName, aImg, aImg, pParent, bShowColumns); 463 pQueryEntry->SetUserData((void*)1); 464 SetExpandedEntryBmp(pQueryEntry, aHCImg, BMP_COLOR_HIGHCONTRAST); 465 SetCollapsedEntryBmp( pQueryEntry, aHCImg, BMP_COLOR_HIGHCONTRAST); 466 } 467 } 468 } 469 } 470 catch(const Exception&) 471 { 472 } 473 } 474 } 475 } 476 477 /*------------------------------------------------------------------------ 478 Beschreibung: 479 ------------------------------------------------------------------------*/ 480 481 IMPL_LINK( SwDBTreeList, DBCompare, SvSortData*, pData ) 482 { 483 SvLBoxEntry* pRight = (SvLBoxEntry*)(pData->pRight ); 484 485 if (GetParent(pRight) && GetParent(GetParent(pRight))) 486 return COMPARE_GREATER; // Spaltennamen nicht sortieren 487 488 return DefaultCompare(pData); // Sonst Basisklasse rufen 489 } 490 491 /*------------------------------------------------------------------------ 492 Beschreibung: 493 ------------------------------------------------------------------------*/ 494 495 String SwDBTreeList::GetDBName(String& rTableName, String& rColumnName, sal_Bool* pbIsTable) 496 { 497 String sDBName; 498 SvLBoxEntry* pEntry = FirstSelected(); 499 500 if (pEntry && GetParent(pEntry)) 501 { 502 if (GetParent(GetParent(pEntry))) 503 { 504 rColumnName = GetEntryText(pEntry); 505 pEntry = GetParent(pEntry); // Spaltenname war selektiert 506 } 507 sDBName = GetEntryText(GetParent(pEntry)); 508 if(pbIsTable) 509 { 510 *pbIsTable = pEntry->GetUserData() == 0; 511 } 512 rTableName = GetEntryText(pEntry); 513 } 514 return sDBName; 515 } 516 517 /*------------------------------------------------------------------------ 518 Beschreibung: Format: Datenbank.Tabelle 519 ------------------------------------------------------------------------*/ 520 521 522 void SwDBTreeList::Select(const String& rDBName, const String& rTableName, const String& rColumnName) 523 { 524 SvLBoxEntry* pParent; 525 SvLBoxEntry* pChild; 526 sal_uInt16 nParent = 0; 527 sal_uInt16 nChild = 0; 528 529 while ((pParent = GetEntry(nParent++)) != NULL) 530 { 531 if (rDBName == GetEntryText(pParent)) 532 { 533 if (!pParent->HasChilds()) 534 RequestingChilds(pParent); 535 while ((pChild = GetEntry(pParent, nChild++)) != NULL) 536 { 537 if (rTableName == GetEntryText(pChild)) 538 { 539 pParent = pChild; 540 541 if (bShowColumns && rColumnName.Len()) 542 { 543 nChild = 0; 544 545 if (!pParent->HasChilds()) 546 RequestingChilds(pParent); 547 548 while ((pChild = GetEntry(pParent, nChild++)) != NULL) 549 if (rColumnName == GetEntryText(pChild)) 550 break; 551 } 552 if (!pChild) 553 pChild = pParent; 554 555 MakeVisible(pChild); 556 SvTreeListBox::Select(pChild); 557 return; 558 } 559 } 560 } 561 } 562 } 563 564 /*------------------------------------------------------------------------ 565 Beschreibung: 566 ------------------------------------------------------------------------*/ 567 568 void SwDBTreeList::StartDrag( sal_Int8 /*nAction*/, const Point& /*rPosPixel*/ ) 569 { 570 String sTableName, sColumnName; 571 String sDBName( GetDBName( sTableName, sColumnName )); 572 if( sDBName.Len() ) 573 { 574 TransferDataContainer* pContainer = new TransferDataContainer; 575 STAR_REFERENCE( datatransfer::XTransferable ) xRef( pContainer ); 576 if( sColumnName.Len() ) 577 { 578 // Datenbankfeld draggen 579 svx::OColumnTransferable aColTransfer( 580 sDBName 581 ,::rtl::OUString() 582 , sdb::CommandType::TABLE 583 ,sTableName 584 , sColumnName 585 ,(CTF_FIELD_DESCRIPTOR |CTF_COLUMN_DESCRIPTOR )); 586 aColTransfer.addDataToContainer( pContainer ); 587 } 588 589 sDBName += '.'; 590 sDBName += sTableName; 591 if( sColumnName.Len() ) 592 { 593 sDBName += '.'; 594 sDBName += sColumnName; 595 } 596 597 pContainer->CopyString( FORMAT_STRING, sDBName ); 598 pContainer->StartDrag( this, DND_ACTION_COPY | DND_ACTION_LINK, 599 Link() ); 600 } 601 } 602 603 /*------------------------------------------------------------------------ 604 Beschreibung: 605 ------------------------------------------------------------------------*/ 606 sal_Int8 SwDBTreeList::AcceptDrop( const AcceptDropEvent& /*rEvt*/ ) 607 { 608 return DND_ACTION_NONE; 609 } 610 /*-- 07.10.2003 13:28:22--------------------------------------------------- 611 612 -----------------------------------------------------------------------*/ 613 void SwDBTreeList::SetWrtShell(SwWrtShell& rSh) 614 { 615 pImpl->SetWrtShell(rSh); 616 if (IsVisible() && !bInitialized) 617 InitTreeList(); 618 } 619