1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 21 #include <bastypes.hxx> 22 #include <bastype2.hxx> 23 #include <strings.hrc> 24 #include <bitmaps.hlst> 25 #include <iderid.hxx> 26 #include <o3tl/make_unique.hxx> 27 #include <tools/urlobj.hxx> 28 #include <tools/diagnose_ex.h> 29 #include <svtools/imagemgr.hxx> 30 #include <svtools/treelistentry.hxx> 31 #include <com/sun/star/script/XLibraryContainerPassword.hpp> 32 #include <com/sun/star/frame/ModuleManager.hpp> 33 #include <comphelper/processfactory.hxx> 34 #include <sfx2/dispatch.hxx> 35 #include <vcl/builderfactory.hxx> 36 37 #include <initializer_list> 38 #include <memory> 39 40 #include <com/sun/star/script/ModuleType.hpp> 41 #include <com/sun/star/script/vba/XVBAModuleInfo.hpp> 42 #include <com/sun/star/lang/XServiceInfo.hpp> 43 #include <com/sun/star/container/XNamed.hpp> 44 45 namespace basctl 46 { 47 48 using namespace ::com::sun::star::uno; 49 using namespace ::com::sun::star; 50 51 void ModuleInfoHelper::getObjectName( const uno::Reference< container::XNameContainer >& rLib, const OUString& rModName, OUString& rObjName ) 52 { 53 try 54 { 55 uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( rLib, uno::UNO_QUERY ); 56 if ( xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo( rModName ) ) 57 { 58 script::ModuleInfo aModuleInfo = xVBAModuleInfo->getModuleInfo( rModName ); 59 uno::Any aObject( aModuleInfo.ModuleObject ); 60 uno::Reference< lang::XServiceInfo > xServiceInfo( aObject, uno::UNO_QUERY ); 61 if( xServiceInfo.is() && xServiceInfo->supportsService( "ooo.vba.excel.Worksheet" ) ) 62 { 63 uno::Reference< container::XNamed > xNamed( aObject, uno::UNO_QUERY ); 64 if( xNamed.is() ) 65 rObjName = xNamed->getName(); 66 } 67 } 68 } 69 catch(const uno::Exception& ) 70 { 71 } 72 } 73 74 sal_Int32 ModuleInfoHelper::getModuleType( const uno::Reference< container::XNameContainer >& rLib, const OUString& rModName ) 75 { 76 sal_Int32 nType = script::ModuleType::NORMAL; 77 uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( rLib, uno::UNO_QUERY ); 78 if ( xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo( rModName ) ) 79 { 80 script::ModuleInfo aModuleInfo = xVBAModuleInfo->getModuleInfo( rModName ); 81 nType = aModuleInfo.ModuleType; 82 } 83 return nType; 84 } 85 86 Entry::~Entry() 87 { } 88 89 DocumentEntry::DocumentEntry ( 90 ScriptDocument const& rDocument, 91 LibraryLocation eLocation, 92 EntryType eType 93 ) : 94 Entry(eType), 95 m_aDocument(rDocument), 96 m_eLocation(eLocation) 97 { 98 OSL_ENSURE( m_aDocument.isValid(), "DocumentEntry::DocumentEntry: illegal document!" ); 99 } 100 101 DocumentEntry::~DocumentEntry() 102 { } 103 104 LibEntry::LibEntry ( 105 ScriptDocument const& rDocument, 106 LibraryLocation eLocation, 107 OUString const& rLibName 108 ) : 109 DocumentEntry(rDocument, eLocation, OBJ_TYPE_LIBRARY), 110 m_aLibName(rLibName) 111 { } 112 113 LibEntry::~LibEntry() 114 { } 115 116 EntryDescriptor::EntryDescriptor () : 117 m_aDocument(ScriptDocument::getApplicationScriptDocument()), 118 m_eLocation(LIBRARY_LOCATION_UNKNOWN), 119 m_eType(OBJ_TYPE_UNKNOWN) 120 { } 121 122 EntryDescriptor::EntryDescriptor ( 123 ScriptDocument const& rDocument, 124 LibraryLocation eLocation, 125 OUString const& rLibName, 126 OUString const& rLibSubName, 127 OUString const& rName, 128 EntryType eType 129 ) : 130 m_aDocument(rDocument), 131 m_eLocation(eLocation), 132 m_aLibName(rLibName), 133 m_aLibSubName(rLibSubName), 134 m_aName(rName), 135 m_eType(eType) 136 { 137 OSL_ENSURE( m_aDocument.isValid(), "EntryDescriptor::EntryDescriptor: invalid document!" ); 138 } 139 140 EntryDescriptor::EntryDescriptor ( 141 ScriptDocument const& rDocument, 142 LibraryLocation eLocation, 143 OUString const& rLibName, 144 OUString const& rLibSubName, 145 OUString const& rName, 146 OUString const& rMethodName, 147 EntryType eType 148 ) : 149 m_aDocument(rDocument), 150 m_eLocation(eLocation), 151 m_aLibName(rLibName), 152 m_aLibSubName(rLibSubName), 153 m_aName(rName), 154 m_aMethodName(rMethodName), 155 m_eType(eType) 156 { 157 OSL_ENSURE( m_aDocument.isValid(), "EntryDescriptor::EntryDescriptor: invalid document!" ); 158 } 159 160 TreeListBox::TreeListBox (vcl::Window* pParent, WinBits nStyle) 161 : SvTreeListBox(pParent, nStyle) 162 , m_aNotifier( *this ) 163 { 164 SetNodeDefaultImages(); 165 SetSelectionMode( SelectionMode::Single ); 166 nMode = BrowseMode::All; // everything 167 } 168 169 VCL_BUILDER_FACTORY_CONSTRUCTOR(TreeListBox, WB_TABSTOP) 170 171 TreeListBox::~TreeListBox () 172 { 173 disposeOnce(); 174 } 175 176 void TreeListBox::dispose() 177 { 178 m_aNotifier.dispose(); 179 180 // destroy user data 181 SvTreeListEntry* pEntry = First(); 182 while ( pEntry ) 183 { 184 delete static_cast<Entry*>( pEntry->GetUserData() ); 185 pEntry->SetUserData( nullptr ); 186 pEntry = Next( pEntry ); 187 } 188 SvTreeListBox::dispose(); 189 } 190 191 void TreeListBox::ScanEntry( const ScriptDocument& rDocument, LibraryLocation eLocation ) 192 { 193 OSL_ENSURE( rDocument.isAlive(), "TreeListBox::ScanEntry: illegal document!" ); 194 if ( !rDocument.isAlive() ) 195 return; 196 197 // can be called multiple times for updating! 198 199 // actually test if basic's in the tree already?! 200 SetUpdateMode(false); 201 202 // level 1: BasicManager (application, document, ...) 203 SvTreeListEntry* pDocumentRootEntry = FindRootEntry( rDocument, eLocation ); 204 if ( pDocumentRootEntry && IsExpanded( pDocumentRootEntry ) ) 205 ImpCreateLibEntries( pDocumentRootEntry, rDocument, eLocation ); 206 if ( !pDocumentRootEntry ) 207 { 208 OUString aRootName( GetRootEntryName( rDocument, eLocation ) ); 209 Image aImage; 210 GetRootEntryBitmaps( rDocument, aImage ); 211 AddEntry( 212 aRootName, 213 aImage, 214 nullptr, true, o3tl::make_unique<DocumentEntry>(rDocument, eLocation)); 215 } 216 217 SetUpdateMode(true); 218 } 219 220 void TreeListBox::ImpCreateLibEntries( SvTreeListEntry* pDocumentRootEntry, const ScriptDocument& rDocument, LibraryLocation eLocation ) 221 { 222 // get a sorted list of library names 223 Sequence< OUString > aLibNames( rDocument.getLibraryNames() ); 224 sal_Int32 nLibCount = aLibNames.getLength(); 225 const OUString* pLibNames = aLibNames.getConstArray(); 226 227 for ( sal_Int32 i = 0 ; i < nLibCount ; i++ ) 228 { 229 OUString aLibName = pLibNames[ i ]; 230 231 if ( eLocation == rDocument.getLibraryLocation( aLibName ) ) 232 { 233 // check, if the module library is loaded 234 bool bModLibLoaded = false; 235 Reference< script::XLibraryContainer > xModLibContainer( rDocument.getLibraryContainer( E_SCRIPTS ) ); 236 if ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && xModLibContainer->isLibraryLoaded( aLibName ) ) 237 bModLibLoaded = true; 238 239 // check, if the dialog library is loaded 240 bool bDlgLibLoaded = false; 241 Reference< script::XLibraryContainer > xDlgLibContainer( rDocument.getLibraryContainer( E_DIALOGS ) ); 242 if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) && xDlgLibContainer->isLibraryLoaded( aLibName ) ) 243 bDlgLibLoaded = true; 244 245 bool bLoaded = bModLibLoaded || bDlgLibLoaded; 246 247 // if only one of the libraries is loaded, load also the other 248 if ( bLoaded ) 249 { 250 if ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && !xModLibContainer->isLibraryLoaded( aLibName ) ) 251 xModLibContainer->loadLibrary( aLibName ); 252 253 if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) && !xDlgLibContainer->isLibraryLoaded( aLibName ) ) 254 xDlgLibContainer->loadLibrary( aLibName ); 255 } 256 257 // create tree list box entry 258 OUString sId; 259 if ( ( nMode & BrowseMode::Dialogs ) && !( nMode & BrowseMode::Modules ) ) 260 sId = bLoaded ? OUStringLiteral(RID_BMP_DLGLIB) : OUStringLiteral(RID_BMP_DLGLIBNOTLOADED); 261 else 262 sId = bLoaded ? OUStringLiteral(RID_BMP_MODLIB) : OUStringLiteral(RID_BMP_MODLIBNOTLOADED); 263 SvTreeListEntry* pLibRootEntry = FindEntry( pDocumentRootEntry, aLibName, OBJ_TYPE_LIBRARY ); 264 if ( pLibRootEntry ) 265 { 266 SetEntryBitmaps(pLibRootEntry, Image(BitmapEx(sId))); 267 if ( IsExpanded(pLibRootEntry)) 268 ImpCreateLibSubEntries( pLibRootEntry, rDocument, aLibName ); 269 } 270 else 271 { 272 AddEntry( 273 aLibName, 274 Image(BitmapEx(sId)), 275 pDocumentRootEntry, true, 276 o3tl::make_unique<Entry>(OBJ_TYPE_LIBRARY)); 277 } 278 } 279 } 280 } 281 282 void TreeListBox::ImpCreateLibSubEntries( SvTreeListEntry* pLibRootEntry, const ScriptDocument& rDocument, const OUString& rLibName ) 283 { 284 // modules 285 if ( nMode & BrowseMode::Modules ) 286 { 287 Reference< script::XLibraryContainer > xModLibContainer( rDocument.getLibraryContainer( E_SCRIPTS ) ); 288 289 if ( xModLibContainer.is() && xModLibContainer->hasByName( rLibName ) && xModLibContainer->isLibraryLoaded( rLibName ) ) 290 { 291 try 292 { 293 if( rDocument.isInVBAMode() ) 294 ImpCreateLibSubEntriesInVBAMode( pLibRootEntry, rDocument, rLibName ); 295 else 296 { 297 // get a sorted list of module names 298 Sequence< OUString > aModNames = rDocument.getObjectNames( E_SCRIPTS, rLibName ); 299 sal_Int32 nModCount = aModNames.getLength(); 300 const OUString* pModNames = aModNames.getConstArray(); 301 302 for ( sal_Int32 i = 0 ; i < nModCount ; i++ ) 303 { 304 OUString aModName = pModNames[ i ]; 305 SvTreeListEntry* pModuleEntry = FindEntry( pLibRootEntry, aModName, OBJ_TYPE_MODULE ); 306 if ( !pModuleEntry ) 307 { 308 pModuleEntry = AddEntry( 309 aModName, 310 Image(BitmapEx(RID_BMP_MODULE)), 311 pLibRootEntry, false, 312 o3tl::make_unique<Entry>(OBJ_TYPE_MODULE)); 313 } 314 315 // methods 316 if ( nMode & BrowseMode::Subs ) 317 { 318 Sequence< OUString > aNames = GetMethodNames( rDocument, rLibName, aModName ); 319 sal_Int32 nCount = aNames.getLength(); 320 const OUString* pNames = aNames.getConstArray(); 321 322 for ( sal_Int32 j = 0 ; j < nCount ; j++ ) 323 { 324 OUString aName = pNames[ j ]; 325 SvTreeListEntry* pEntry = FindEntry( pModuleEntry, aName, OBJ_TYPE_METHOD ); 326 if ( !pEntry ) 327 { 328 AddEntry( 329 aName, 330 Image(BitmapEx(RID_BMP_MACRO)), 331 pModuleEntry, false, 332 o3tl::make_unique<Entry>( 333 OBJ_TYPE_METHOD)); 334 } 335 } 336 } 337 } 338 } 339 } 340 catch ( const container::NoSuchElementException& ) 341 { 342 DBG_UNHANDLED_EXCEPTION("basctl.basicide"); 343 } 344 } 345 } 346 347 // dialogs 348 if ( nMode & BrowseMode::Dialogs ) 349 { 350 Reference< script::XLibraryContainer > xDlgLibContainer( rDocument.getLibraryContainer( E_DIALOGS ) ); 351 352 if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( rLibName ) && xDlgLibContainer->isLibraryLoaded( rLibName ) ) 353 { 354 try 355 { 356 // get a sorted list of dialog names 357 Sequence< OUString > aDlgNames( rDocument.getObjectNames( E_DIALOGS, rLibName ) ); 358 sal_Int32 nDlgCount = aDlgNames.getLength(); 359 const OUString* pDlgNames = aDlgNames.getConstArray(); 360 361 for ( sal_Int32 i = 0 ; i < nDlgCount ; i++ ) 362 { 363 OUString aDlgName = pDlgNames[ i ]; 364 SvTreeListEntry* pDialogEntry = FindEntry( pLibRootEntry, aDlgName, OBJ_TYPE_DIALOG ); 365 if ( !pDialogEntry ) 366 { 367 AddEntry( 368 aDlgName, 369 Image(BitmapEx(RID_BMP_DIALOG)), 370 pLibRootEntry, false, 371 o3tl::make_unique<Entry>(OBJ_TYPE_DIALOG)); 372 } 373 } 374 } 375 catch (const container::NoSuchElementException& ) 376 { 377 DBG_UNHANDLED_EXCEPTION("basctl.basicide"); 378 } 379 } 380 } 381 } 382 383 void TreeListBox::ImpCreateLibSubEntriesInVBAMode( SvTreeListEntry* pLibRootEntry, const ScriptDocument& rDocument, const OUString& rLibName ) 384 { 385 auto const aEntries = { 386 std::make_pair( OBJ_TYPE_DOCUMENT_OBJECTS, IDEResId(RID_STR_DOCUMENT_OBJECTS) ), 387 std::make_pair( OBJ_TYPE_USERFORMS, IDEResId(RID_STR_USERFORMS) ), 388 std::make_pair( OBJ_TYPE_NORMAL_MODULES, IDEResId(RID_STR_NORMAL_MODULES) ), 389 std::make_pair( OBJ_TYPE_CLASS_MODULES, IDEResId(RID_STR_CLASS_MODULES) ) }; 390 for( auto const & iter: aEntries ) 391 { 392 EntryType eType = iter.first; 393 OUString const & aEntryName = iter.second; 394 SvTreeListEntry* pLibSubRootEntry = FindEntry( pLibRootEntry, aEntryName, eType ); 395 if( pLibSubRootEntry ) 396 { 397 SetEntryBitmaps(pLibSubRootEntry, Image(BitmapEx(RID_BMP_MODLIB))); 398 if ( IsExpanded( pLibSubRootEntry ) ) 399 ImpCreateLibSubSubEntriesInVBAMode( pLibSubRootEntry, rDocument, rLibName ); 400 } 401 else 402 { 403 AddEntry( 404 aEntryName, 405 Image(BitmapEx(RID_BMP_MODLIB)), 406 pLibRootEntry, true, o3tl::make_unique<Entry>(eType)); 407 } 408 } 409 } 410 411 void TreeListBox::ImpCreateLibSubSubEntriesInVBAMode( SvTreeListEntry* pLibSubRootEntry, const ScriptDocument& rDocument, const OUString& rLibName ) 412 { 413 uno::Reference< container::XNameContainer > xLib = rDocument.getOrCreateLibrary( E_SCRIPTS, rLibName ); 414 if( !xLib.is() ) 415 return; 416 417 try 418 { 419 // get a sorted list of module names 420 Sequence< OUString > aModNames = rDocument.getObjectNames( E_SCRIPTS, rLibName ); 421 sal_Int32 nModCount = aModNames.getLength(); 422 const OUString* pModNames = aModNames.getConstArray(); 423 424 EntryDescriptor aDesc( GetEntryDescriptor( pLibSubRootEntry ) ); 425 EntryType eCurrentType( aDesc.GetType() ); 426 427 for ( sal_Int32 i = 0 ; i < nModCount ; i++ ) 428 { 429 OUString aModName = pModNames[ i ]; 430 EntryType eType = OBJ_TYPE_UNKNOWN; 431 switch( ModuleInfoHelper::getModuleType( xLib, aModName ) ) 432 { 433 case script::ModuleType::DOCUMENT: 434 eType = OBJ_TYPE_DOCUMENT_OBJECTS; 435 break; 436 case script::ModuleType::FORM: 437 eType = OBJ_TYPE_USERFORMS; 438 break; 439 case script::ModuleType::NORMAL: 440 eType = OBJ_TYPE_NORMAL_MODULES; 441 break; 442 case script::ModuleType::CLASS: 443 eType = OBJ_TYPE_CLASS_MODULES; 444 break; 445 } 446 if( eType != eCurrentType ) 447 continue; 448 449 // display a nice friendly name in the ObjectModule tab, 450 // combining the objectname and module name, e.g. Sheet1 ( Financials ) 451 OUString aEntryName = aModName; 452 if( eType == OBJ_TYPE_DOCUMENT_OBJECTS ) 453 { 454 OUString sObjName; 455 ModuleInfoHelper::getObjectName( xLib, aModName, sObjName ); 456 if( !sObjName.isEmpty() ) 457 { 458 aEntryName += " (" + sObjName + ")"; 459 } 460 } 461 SvTreeListEntry* pModuleEntry = FindEntry( pLibSubRootEntry, aEntryName, OBJ_TYPE_MODULE ); 462 if ( !pModuleEntry ) 463 { 464 pModuleEntry = AddEntry( 465 aEntryName, 466 Image(BitmapEx(RID_BMP_MODULE)), 467 pLibSubRootEntry, false, 468 o3tl::make_unique<Entry>(OBJ_TYPE_MODULE)); 469 } 470 471 // methods 472 if ( nMode & BrowseMode::Subs ) 473 { 474 Sequence< OUString > aNames = GetMethodNames( rDocument, rLibName, aModName ); 475 sal_Int32 nCount = aNames.getLength(); 476 const OUString* pNames = aNames.getConstArray(); 477 478 for ( sal_Int32 j = 0 ; j < nCount ; j++ ) 479 { 480 OUString aName = pNames[ j ]; 481 SvTreeListEntry* pEntry = FindEntry( pModuleEntry, aName, OBJ_TYPE_METHOD ); 482 if ( !pEntry ) 483 { 484 AddEntry( 485 aName, 486 Image(BitmapEx(RID_BMP_MACRO)), 487 pModuleEntry, false, 488 o3tl::make_unique<Entry>(OBJ_TYPE_METHOD)); 489 } 490 } 491 } 492 } 493 } 494 catch ( const container::NoSuchElementException& ) 495 { 496 DBG_UNHANDLED_EXCEPTION("basctl.basicide"); 497 } 498 } 499 500 SvTreeListEntry* TreeListBox::ImpFindEntry( SvTreeListEntry* pParent, const OUString& rText ) 501 { 502 sal_uLong nRootPos = 0; 503 SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : GetEntry( nRootPos ); 504 while ( pEntry ) 505 { 506 if ( rText == GetEntryText( pEntry ) ) 507 return pEntry; 508 509 pEntry = pParent ? pEntry->NextSibling() : GetEntry( ++nRootPos ); 510 } 511 return nullptr; 512 } 513 514 void TreeListBox::onDocumentCreated( const ScriptDocument& /*_rDocument*/ ) 515 { 516 UpdateEntries(); 517 } 518 519 void TreeListBox::onDocumentOpened( const ScriptDocument& /*_rDocument*/ ) 520 { 521 UpdateEntries(); 522 } 523 524 void TreeListBox::onDocumentSave( const ScriptDocument& /*_rDocument*/ ) 525 { 526 // not interested in 527 } 528 529 void TreeListBox::onDocumentSaveDone( const ScriptDocument& /*_rDocument*/ ) 530 { 531 // not interested in 532 } 533 534 void TreeListBox::onDocumentSaveAs( const ScriptDocument& /*_rDocument*/ ) 535 { 536 // not interested in 537 } 538 539 void TreeListBox::onDocumentSaveAsDone( const ScriptDocument& /*_rDocument*/ ) 540 { 541 UpdateEntries(); 542 } 543 544 void TreeListBox::onDocumentClosed( const ScriptDocument& rDocument ) 545 { 546 UpdateEntries(); 547 // The document is not yet actually deleted, so we need to remove its entry 548 // manually. 549 RemoveEntry(rDocument); 550 } 551 552 void TreeListBox::onDocumentTitleChanged( const ScriptDocument& /*_rDocument*/ ) 553 { 554 // not interested in 555 } 556 557 void TreeListBox::onDocumentModeChanged( const ScriptDocument& /*_rDocument*/ ) 558 { 559 // not interested in 560 } 561 562 void TreeListBox::UpdateEntries() 563 { 564 EntryDescriptor aCurDesc( GetEntryDescriptor( FirstSelected() ) ); 565 566 // removing the invalid entries 567 SvTreeListEntry* pLastValid = nullptr; 568 SvTreeListEntry* pEntry = First(); 569 while ( pEntry ) 570 { 571 if ( IsValidEntry( pEntry ) ) 572 pLastValid = pEntry; 573 else 574 RemoveEntry(pEntry); 575 pEntry = pLastValid ? Next( pLastValid ) : First(); 576 } 577 578 ScanAllEntries(); 579 580 SetCurrentEntry( aCurDesc ); 581 } 582 583 // Removes the entry from the tree. 584 void TreeListBox::RemoveEntry (SvTreeListEntry const * pEntry) 585 { 586 // removing the associated user data 587 delete static_cast<Entry*>(pEntry->GetUserData()); 588 // removing the entry 589 GetModel()->Remove( pEntry ); 590 } 591 592 // Removes the entry of rDocument. 593 void TreeListBox::RemoveEntry (ScriptDocument const& rDocument) 594 { 595 // finding the entry of rDocument 596 for (SvTreeListEntry* pEntry = First(); pEntry; pEntry = Next(pEntry)) 597 if (rDocument == GetEntryDescriptor(pEntry).GetDocument()) 598 { 599 RemoveEntry(pEntry); 600 break; 601 } 602 } 603 604 SvTreeListEntry* TreeListBox::CloneEntry( SvTreeListEntry* pSource ) 605 { 606 SvTreeListEntry* pNew = SvTreeListBox::CloneEntry( pSource ); 607 Entry* pUser = static_cast<Entry*>(pSource->GetUserData()); 608 609 assert(pUser && "User data?!"); 610 DBG_ASSERT( pUser->GetType() != OBJ_TYPE_DOCUMENT, "TreeListBox::CloneEntry: document?!" ); 611 612 Entry* pNewUser = new Entry( *pUser ); 613 pNew->SetUserData( pNewUser ); 614 return pNew; 615 } 616 617 SvTreeListEntry* TreeListBox::FindEntry( SvTreeListEntry* pParent, const OUString& rText, EntryType eType ) 618 { 619 sal_uLong nRootPos = 0; 620 SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : GetEntry( nRootPos ); 621 while ( pEntry ) 622 { 623 Entry* pBasicEntry = static_cast<Entry*>(pEntry->GetUserData()); 624 assert(pBasicEntry && "FindEntry: no Entry ?!"); 625 if ( ( pBasicEntry->GetType() == eType ) && ( rText == GetEntryText( pEntry ) ) ) 626 return pEntry; 627 628 pEntry = pParent ? pEntry->NextSibling() : GetEntry( ++nRootPos ); 629 } 630 return nullptr; 631 } 632 633 bool TreeListBox::ExpandingHdl() 634 { 635 // expanding or collapsing? 636 bool bOK = true; 637 if ( GetModel()->GetDepth( GetHdlEntry() ) == 1 ) 638 { 639 SvTreeListEntry* pCurEntry = GetCurEntry(); 640 EntryDescriptor aDesc( GetEntryDescriptor( pCurEntry ) ); 641 const ScriptDocument& aDocument( aDesc.GetDocument() ); 642 OSL_ENSURE( aDocument.isAlive(), "TreeListBox::ExpandingHdl: no document, or document is dead!" ); 643 if ( aDocument.isAlive() ) 644 { 645 const OUString& aLibName( aDesc.GetLibName() ); 646 const OUString& aLibSubName( aDesc.GetLibSubName() ); 647 const OUString& aName( aDesc.GetName() ); 648 const OUString& aMethodName( aDesc.GetMethodName() ); 649 650 if ( !aLibName.isEmpty() && aLibSubName.isEmpty() && aName.isEmpty() && aMethodName.isEmpty() ) 651 { 652 // check password, if library is password protected and not verified 653 Reference< script::XLibraryContainer > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ) ); 654 if ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) ) 655 { 656 Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY ); 657 if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aLibName ) && !xPasswd->isLibraryPasswordVerified( aLibName ) ) 658 { 659 OUString aPassword; 660 bOK = QueryPassword( xModLibContainer, aLibName, aPassword ); 661 } 662 } 663 } 664 } 665 } 666 return bOK; 667 } 668 669 bool TreeListBox::IsEntryProtected( SvTreeListEntry* pEntry ) 670 { 671 bool bProtected = false; 672 if ( pEntry && ( GetModel()->GetDepth( pEntry ) == 1 ) ) 673 { 674 EntryDescriptor aDesc( GetEntryDescriptor( pEntry ) ); 675 const ScriptDocument& aDocument( aDesc.GetDocument() ); 676 OSL_ENSURE( aDocument.isAlive(), "TreeListBox::IsEntryProtected: no document, or document is dead!" ); 677 if ( aDocument.isAlive() ) 678 { 679 const OUString& aOULibName( aDesc.GetLibName() ); 680 Reference< script::XLibraryContainer > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ) ); 681 if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) ) 682 { 683 Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY ); 684 if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aOULibName ) && !xPasswd->isLibraryPasswordVerified( aOULibName ) ) 685 { 686 bProtected = true; 687 } 688 } 689 } 690 } 691 return bProtected; 692 } 693 694 SvTreeListEntry* TreeListBox::AddEntry( 695 OUString const& rText, 696 const Image& rImage, 697 SvTreeListEntry* pParent, 698 bool bChildrenOnDemand, 699 std::unique_ptr<Entry> && aUserData 700 ) 701 { 702 SvTreeListEntry* p = InsertEntry( 703 rText, rImage, rImage, pParent, bChildrenOnDemand, TREELIST_APPEND, 704 aUserData.get() 705 ); 706 aUserData.release(); 707 return p; 708 } 709 710 void TreeListBox::SetEntryBitmaps( SvTreeListEntry * pEntry, const Image& rImage ) 711 { 712 SetExpandedEntryBmp( pEntry, rImage ); 713 SetCollapsedEntryBmp( pEntry, rImage ); 714 } 715 716 LibraryType TreeListBox::GetLibraryType() const 717 { 718 LibraryType eType = LibraryType::All; 719 if ( ( nMode & BrowseMode::Modules ) && !( nMode & BrowseMode::Dialogs ) ) 720 eType = LibraryType::Module; 721 else if ( !( nMode & BrowseMode::Modules ) && ( nMode & BrowseMode::Dialogs ) ) 722 eType = LibraryType::Dialog; 723 return eType; 724 } 725 726 OUString TreeListBox::GetRootEntryName( const ScriptDocument& rDocument, LibraryLocation eLocation ) const 727 { 728 return rDocument.getTitle( eLocation, GetLibraryType() ); 729 } 730 731 void TreeListBox::GetRootEntryBitmaps( const ScriptDocument& rDocument, Image& rImage ) 732 { 733 OSL_ENSURE( rDocument.isValid(), "TreeListBox::GetRootEntryBitmaps: illegal document!" ); 734 if ( !rDocument.isValid() ) 735 return; 736 737 if ( rDocument.isDocument() ) 738 { 739 OUString sFactoryURL; 740 Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() ); 741 Reference< frame::XModuleManager2 > xModuleManager( frame::ModuleManager::create(xContext) ); 742 try 743 { 744 OUString sModule( xModuleManager->identify( rDocument.getDocument() ) ); 745 Reference< container::XNameAccess > xModuleConfig( xModuleManager, UNO_QUERY ); 746 if ( xModuleConfig.is() ) 747 { 748 Sequence< beans::PropertyValue > aModuleDescr; 749 xModuleConfig->getByName( sModule ) >>= aModuleDescr; 750 sal_Int32 nCount = aModuleDescr.getLength(); 751 const beans::PropertyValue* pModuleDescr = aModuleDescr.getConstArray(); 752 for ( sal_Int32 i = 0; i < nCount; ++i ) 753 { 754 if ( pModuleDescr[ i ].Name == "ooSetupFactoryEmptyDocumentURL" ) 755 { 756 pModuleDescr[ i ].Value >>= sFactoryURL; 757 break; 758 } 759 } 760 } 761 } 762 catch( const Exception& ) 763 { 764 DBG_UNHANDLED_EXCEPTION("basctl.basicide"); 765 } 766 767 if ( !sFactoryURL.isEmpty() ) 768 { 769 rImage = SvFileInformationManager::GetFileImage( INetURLObject( sFactoryURL ) ); 770 } 771 else 772 { 773 // default icon 774 rImage = Image(BitmapEx(RID_BMP_DOCUMENT)); 775 } 776 } 777 else 778 { 779 rImage = Image(BitmapEx(RID_BMP_INSTALLATION)); 780 } 781 } 782 783 void TreeListBox::SetCurrentEntry (EntryDescriptor const & rDesc) 784 { 785 SvTreeListEntry* pCurEntry = nullptr; 786 EntryDescriptor aDesc = rDesc; 787 if ( aDesc.GetType() == OBJ_TYPE_UNKNOWN ) 788 { 789 aDesc = EntryDescriptor( 790 ScriptDocument::getApplicationScriptDocument(), 791 LIBRARY_LOCATION_USER, "Standard", 792 OUString(), ".", OBJ_TYPE_UNKNOWN 793 ); 794 } 795 ScriptDocument aDocument = aDesc.GetDocument(); 796 OSL_ENSURE( aDocument.isValid(), "TreeListBox::SetCurrentEntry: invalid document!" ); 797 LibraryLocation eLocation = aDesc.GetLocation(); 798 SvTreeListEntry* pRootEntry = FindRootEntry( aDocument, eLocation ); 799 if ( pRootEntry ) 800 { 801 pCurEntry = pRootEntry; 802 const OUString& aLibName( aDesc.GetLibName() ); 803 if ( !aLibName.isEmpty() ) 804 { 805 Expand( pRootEntry ); 806 SvTreeListEntry* pLibEntry = FindEntry( pRootEntry, aLibName, OBJ_TYPE_LIBRARY ); 807 if ( pLibEntry ) 808 { 809 pCurEntry = pLibEntry; 810 const OUString& aLibSubName( aDesc.GetLibSubName() ); 811 if( !aLibSubName.isEmpty() ) 812 { 813 Expand( pLibEntry ); 814 SvTreeListEntry* pLibSubEntry = ImpFindEntry( pLibEntry, aLibSubName ); 815 if( pLibSubEntry ) 816 { 817 pCurEntry = pLibSubEntry; 818 } 819 } 820 const OUString& aName( aDesc.GetName() ); 821 if ( !aName.isEmpty() ) 822 { 823 Expand( pCurEntry ); 824 EntryType eType = OBJ_TYPE_MODULE; 825 if ( aDesc.GetType() == OBJ_TYPE_DIALOG ) 826 eType = OBJ_TYPE_DIALOG; 827 SvTreeListEntry* pEntry = FindEntry( pCurEntry, aName, eType ); 828 if ( pEntry ) 829 { 830 pCurEntry = pEntry; 831 const OUString& aMethodName( aDesc.GetMethodName() ); 832 if ( !aMethodName.isEmpty() ) 833 { 834 Expand( pEntry ); 835 SvTreeListEntry* pSubEntry = FindEntry( pEntry, aMethodName, OBJ_TYPE_METHOD ); 836 if ( pSubEntry ) 837 { 838 pCurEntry = pSubEntry; 839 } 840 else 841 { 842 pSubEntry = FirstChild( pEntry ); 843 if ( pSubEntry ) 844 pCurEntry = pSubEntry; 845 } 846 } 847 } 848 else 849 { 850 pEntry = FirstChild( pLibEntry ); 851 if ( pEntry ) 852 pCurEntry = pEntry; 853 } 854 } 855 } 856 else 857 { 858 pLibEntry = FirstChild( pRootEntry ); 859 if ( pLibEntry ) 860 pCurEntry = pLibEntry; 861 } 862 } 863 } 864 else 865 { 866 pRootEntry = First(); 867 if ( pRootEntry ) 868 pCurEntry = pRootEntry; 869 } 870 871 SetCurEntry( pCurEntry ); 872 } 873 874 void TreeListBox::MouseButtonDown( const MouseEvent& rMEvt ) 875 { 876 SvTreeListBox::MouseButtonDown( rMEvt ); 877 if ( rMEvt.IsLeft() && ( rMEvt.GetClicks() == 2 ) ) 878 { 879 OpenCurrent(); 880 } 881 } 882 883 void TreeListBox::KeyInput( const KeyEvent& rEvt ) 884 { 885 if ( rEvt.GetKeyCode() == KEY_RETURN && OpenCurrent() ) 886 { 887 return; 888 } 889 SvTreeListBox::KeyInput( rEvt ); 890 } 891 892 bool TreeListBox::OpenCurrent() 893 { 894 EntryDescriptor aDesc = GetEntryDescriptor(GetCurEntry()); 895 switch (aDesc.GetType()) 896 { 897 case OBJ_TYPE_METHOD: 898 case OBJ_TYPE_MODULE: 899 case OBJ_TYPE_DIALOG: 900 if (SfxDispatcher* pDispatcher = GetDispatcher()) 901 { 902 SbxItem aSbxItem( 903 SID_BASICIDE_ARG_SBX, aDesc.GetDocument(), 904 aDesc.GetLibName(), aDesc.GetName(), aDesc.GetMethodName(), 905 ConvertType(aDesc.GetType()) 906 ); 907 pDispatcher->ExecuteList( 908 SID_BASICIDE_SHOWSBX, SfxCallMode::SYNCHRON, 909 { &aSbxItem } 910 ); 911 return true; 912 } 913 break; 914 915 default: 916 break; 917 } 918 return false; 919 } 920 921 } // namespace basctl 922 923 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 924
