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 #include <basic/basicmanagerrepository.hxx> 21 #include <basic/basmgr.hxx> 22 #include <scriptcont.hxx> 23 #include <dlgcont.hxx> 24 #include <basic/sbuno.hxx> 25 #include <sbintern.hxx> 26 27 #include <com/sun/star/document/XStorageBasedDocument.hpp> 28 #include <com/sun/star/document/XEmbeddedScripts.hpp> 29 #include <com/sun/star/frame/Desktop.hpp> 30 #include <svtools/ehdl.hxx> 31 #include <svtools/sfxecode.hxx> 32 #include <unotools/pathoptions.hxx> 33 #include <svl/hint.hxx> 34 #include <vcl/svapp.hxx> 35 #include <tools/debug.hxx> 36 #include <tools/diagnose_ex.h> 37 #include <tools/urlobj.hxx> 38 #include <comphelper/stl_types.hxx> 39 #include <comphelper/processfactory.hxx> 40 #include <comphelper/documentinfo.hxx> 41 #include <unotools/eventlisteneradapter.hxx> 42 43 #include <osl/getglobalmutex.hxx> 44 #include <rtl/instance.hxx> 45 #include <rtl/strbuf.hxx> 46 47 #include <map> 48 49 50 namespace basic 51 { 52 using ::com::sun::star::uno::Reference; 53 using ::com::sun::star::uno::XComponentContext; 54 using ::com::sun::star::frame::XModel; 55 using ::com::sun::star::frame::Desktop; 56 using ::com::sun::star::uno::XInterface; 57 using ::com::sun::star::uno::UNO_QUERY; 58 using ::com::sun::star::embed::XStorage; 59 using ::com::sun::star::script::XPersistentLibraryContainer; 60 using ::com::sun::star::uno::UNO_QUERY_THROW; 61 using ::com::sun::star::uno::Exception; 62 using ::com::sun::star::document::XStorageBasedDocument; 63 using ::com::sun::star::lang::XComponent; 64 using ::com::sun::star::document::XEmbeddedScripts; 65 66 typedef std::map< Reference< XInterface >, std::unique_ptr<BasicManager>, ::comphelper::OInterfaceCompare< XInterface > > BasicManagerStore; 67 68 typedef std::vector< BasicManagerCreationListener* > CreationListeners; 69 70 class ImplRepository : public ::utl::OEventListenerAdapter, public SfxListener 71 { 72 private: 73 friend struct CreateImplRepository; 74 ImplRepository(); 75 76 private: 77 BasicManagerStore m_aStore; 78 CreationListeners m_aCreationListeners; 79 80 public: 81 static ImplRepository& Instance(); 82 83 BasicManager* getDocumentBasicManager( const Reference< XModel >& _rxDocumentModel ); 84 BasicManager* getOrCreateApplicationBasicManager(); 85 static BasicManager* getApplicationBasicManager(); 86 static void setApplicationBasicManager( std::unique_ptr<BasicManager> _pBasicManager ); 87 void registerCreationListener( BasicManagerCreationListener& _rListener ); 88 void revokeCreationListener( BasicManagerCreationListener& _rListener ); 89 90 private: 91 /** retrieves the location at which the BasicManager for the given model 92 is stored. 93 94 If previously, the BasicManager for this model has never been requested, 95 then the model is added to the map, with an initial NULL BasicManager. 96 97 @param _rxDocumentModel 98 the model whose BasicManager's location is to be retrieved. Must not be <NULL/>. 99 100 @precond 101 our mutex is locked 102 */ 103 std::unique_ptr<BasicManager>& 104 impl_getLocationForModel( const Reference< XModel >& _rxDocumentModel ); 105 106 /** tests if there is a location set at which the BasicManager for the given model 107 is stored. 108 109 @param _rxDocumentModel 110 the model whose BasicManager's location is to be retrieved. Must not be <NULL/>. 111 112 @precond 113 our mutex is locked 114 */ 115 bool impl_hasLocationForModel( const Reference< XModel >& _rxDocumentModel ) const; 116 117 /** creates a new BasicManager instance for the given model 118 119 @param _out_rpBasicManager 120 reference to the pointer variable that will hold the new 121 BasicManager. 122 123 @param _rxDocumentModel 124 the model whose BasicManager will be created. Must not be <NULL/>. 125 */ 126 bool impl_createManagerForModel( 127 std::unique_ptr<BasicManager>& _out_rpBasicManager, 128 const Reference< XModel >& _rxDocumentModel ); 129 130 /** creates the application-wide BasicManager 131 */ 132 BasicManager* impl_createApplicationBasicManager(); 133 134 /** notifies all listeners which expressed interest in the creation of BasicManager instances. 135 */ 136 void impl_notifyCreationListeners( 137 const Reference< XModel >& _rxDocumentModel, 138 BasicManager& _rManager 139 ); 140 141 /** retrieves the current storage of a given document 142 143 @param _rxDocument 144 the document whose storage is to be retrieved. 145 146 @param _out_rStorage 147 takes the storage upon successful return. Note that this might be <NULL/> even 148 if <TRUE/> is returned. In this case, the document has not yet been saved. 149 150 @return 151 <TRUE/> if the storage could be successfully retrieved (in which case 152 <arg>_out_rStorage</arg> might or might not be <NULL/>), <FALSE/> otherwise. 153 In the latter case, processing this document should stop. 154 */ 155 static bool impl_getDocumentStorage_nothrow( const Reference< XModel >& _rxDocument, Reference< XStorage >& _out_rStorage ); 156 157 /** retrieves the containers for Basic and Dialog libraries for a given document 158 159 @param _rxDocument 160 the document whose containers are to be retrieved. 161 162 @param _out_rxBasicLibraries 163 takes the basic library container upon successful return 164 165 @param _out_rxDialogLibraries 166 takes the dialog library container upon successful return 167 168 @return 169 <TRUE/> if and only if both containers exist, and could successfully be retrieved 170 */ 171 static bool impl_getDocumentLibraryContainers_nothrow( 172 const Reference< XModel >& _rxDocument, 173 Reference< XPersistentLibraryContainer >& _out_rxBasicLibraries, 174 Reference< XPersistentLibraryContainer >& _out_rxDialogLibraries 175 ); 176 177 /** initializes the given library containers, which belong to a document 178 */ 179 static void impl_initDocLibraryContainers_nothrow( 180 const Reference< XPersistentLibraryContainer >& _rxBasicLibraries, 181 const Reference< XPersistentLibraryContainer >& _rxDialogLibraries 182 ); 183 184 // OEventListenerAdapter overridables 185 virtual void _disposing( const css::lang::EventObject& _rSource ) override; 186 187 // SfxListener overridables 188 virtual void Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint ) override; 189 190 /** removes the Model/BasicManager pair given by iterator from our store 191 */ 192 void impl_removeFromRepository( const BasicManagerStore::iterator& _pos ); 193 194 private: 195 StarBASIC* impl_getDefaultAppBasicLibrary(); 196 }; 197 198 199 struct CreateImplRepository 200 { 201 ImplRepository* operator()() 202 { 203 static ImplRepository* pRepository = new ImplRepository; 204 return pRepository; 205 } 206 }; 207 208 209 ImplRepository::ImplRepository() 210 { 211 } 212 213 214 ImplRepository& ImplRepository::Instance() 215 { 216 return *rtl_Instance< ImplRepository, CreateImplRepository, ::osl::MutexGuard, ::osl::GetGlobalMutex >:: 217 create( CreateImplRepository(), ::osl::GetGlobalMutex() ); 218 } 219 220 BasicManager* ImplRepository::getDocumentBasicManager( const Reference< XModel >& _rxDocumentModel ) 221 { 222 SolarMutexGuard g; 223 224 /* #163556# (DR) - This function may be called recursively while 225 constructing the Basic manager and loading the Basic storage. By 226 passing the map entry received from impl_getLocationForModel() to 227 the function impl_createManagerForModel(), the new Basic manager 228 will be put immediately into the map of existing Basic managers, 229 thus a recursive call of this function will find and return it 230 without creating another instance. 231 */ 232 std::unique_ptr<BasicManager>& pBasicManager = impl_getLocationForModel( _rxDocumentModel ); 233 if (pBasicManager != nullptr) 234 return pBasicManager.get(); 235 if (impl_createManagerForModel(pBasicManager, _rxDocumentModel)) 236 return pBasicManager.get(); 237 return nullptr; 238 } 239 240 BasicManager* ImplRepository::getOrCreateApplicationBasicManager() 241 { 242 SolarMutexGuard g; 243 244 BasicManager* pAppManager = GetSbData()->pAppBasMgr.get(); 245 if (pAppManager == nullptr) 246 pAppManager = impl_createApplicationBasicManager(); 247 return pAppManager; 248 } 249 250 BasicManager* ImplRepository::getApplicationBasicManager() 251 { 252 SolarMutexGuard g; 253 254 return GetSbData()->pAppBasMgr.get(); 255 } 256 257 void ImplRepository::setApplicationBasicManager( std::unique_ptr<BasicManager> _pBasicManager ) 258 { 259 SolarMutexGuard g; 260 261 GetSbData()->pAppBasMgr = std::move(_pBasicManager); 262 } 263 264 265 BasicManager* ImplRepository::impl_createApplicationBasicManager() 266 { 267 SolarMutexGuard g; 268 269 OSL_PRECOND(getApplicationBasicManager() == nullptr, "ImplRepository::impl_createApplicationBasicManager: there already is one!"); 270 271 // Determine Directory 272 SvtPathOptions aPathCFG; 273 OUString aAppBasicDir( aPathCFG.GetBasicPath() ); 274 if ( aAppBasicDir.isEmpty() ) 275 { 276 aPathCFG.SetBasicPath("$(prog)"); 277 } 278 279 // Create basic and load it 280 // AppBasicDir is now a PATH 281 INetURLObject aAppBasic( SvtPathOptions().SubstituteVariable("$(progurl)") ); 282 aAppBasic.insertName( Application::GetAppName() ); 283 284 BasicManager* pBasicManager = new BasicManager( new StarBASIC, &aAppBasicDir ); 285 setApplicationBasicManager( std::unique_ptr<BasicManager>(pBasicManager) ); 286 287 // The first dir in the path as destination: 288 OUString aFileName( aAppBasic.getName() ); 289 aAppBasic = INetURLObject( aAppBasicDir.getToken(1, ';') ); 290 DBG_ASSERT(aAppBasic.GetProtocol() != INetProtocol::NotValid, 291 OString("Invalid URL: \"" + 292 OUStringToOString(aAppBasicDir, osl_getThreadTextEncoding()) + 293 "\"").getStr()); 294 aAppBasic.insertName( aFileName ); 295 pBasicManager->SetStorageName( aAppBasic.PathToFileName() ); 296 297 // Basic container 298 SfxScriptLibraryContainer* pBasicCont = new SfxScriptLibraryContainer( Reference< XStorage >() ); 299 Reference< XPersistentLibraryContainer > xBasicCont( pBasicCont ); 300 pBasicCont->setBasicManager( pBasicManager ); 301 302 // Dialog container 303 SfxDialogLibraryContainer* pDialogCont = new SfxDialogLibraryContainer( Reference< XStorage >() ); 304 Reference< XPersistentLibraryContainer > xDialogCont( pDialogCont ); 305 306 LibraryContainerInfo aInfo( xBasicCont, xDialogCont, static_cast< OldBasicPassword* >( pBasicCont ) ); 307 pBasicManager->SetLibraryContainerInfo( aInfo ); 308 309 // global constants 310 311 // StarDesktop 312 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext(); 313 pBasicManager->SetGlobalUNOConstant( "StarDesktop", css::uno::Any( Desktop::create(xContext))); 314 315 // (BasicLibraries and DialogLibraries have automatically been added in SetLibraryContainerInfo) 316 317 // notify 318 impl_notifyCreationListeners( nullptr, *pBasicManager ); 319 320 // outta here 321 return pBasicManager; 322 } 323 324 325 void ImplRepository::registerCreationListener( BasicManagerCreationListener& _rListener ) 326 { 327 SolarMutexGuard g; 328 329 m_aCreationListeners.push_back( &_rListener ); 330 } 331 332 333 void ImplRepository::revokeCreationListener( BasicManagerCreationListener& _rListener ) 334 { 335 SolarMutexGuard g; 336 337 CreationListeners::iterator pos = std::find( m_aCreationListeners.begin(), m_aCreationListeners.end(), &_rListener ); 338 if ( pos != m_aCreationListeners.end() ) 339 m_aCreationListeners.erase( pos ); 340 else { 341 OSL_FAIL( "ImplRepository::revokeCreationListener: listener is not registered!" ); 342 } 343 } 344 345 346 void ImplRepository::impl_notifyCreationListeners( const Reference< XModel >& _rxDocumentModel, BasicManager& _rManager ) 347 { 348 for (auto const& creationListener : m_aCreationListeners) 349 { 350 creationListener->onBasicManagerCreated( _rxDocumentModel, _rManager ); 351 } 352 } 353 354 355 StarBASIC* ImplRepository::impl_getDefaultAppBasicLibrary() 356 { 357 BasicManager* pAppManager = getOrCreateApplicationBasicManager(); 358 359 StarBASIC* pAppBasic = pAppManager ? pAppManager->GetLib(0) : nullptr; 360 DBG_ASSERT( pAppBasic != nullptr, "impl_getApplicationBasic: unable to determine the default application's Basic library!" ); 361 return pAppBasic; 362 } 363 364 std::unique_ptr<BasicManager>& ImplRepository::impl_getLocationForModel( const Reference< XModel >& _rxDocumentModel ) 365 { 366 Reference< XInterface > xNormalized( _rxDocumentModel, UNO_QUERY ); 367 DBG_ASSERT( _rxDocumentModel.is(), "ImplRepository::impl_getLocationForModel: invalid model!" ); 368 369 std::unique_ptr<BasicManager>& location = m_aStore[ xNormalized ]; 370 return location; 371 } 372 373 bool ImplRepository::impl_hasLocationForModel( const Reference< XModel >& _rxDocumentModel ) const 374 { 375 Reference< XInterface > xNormalized( _rxDocumentModel, UNO_QUERY ); 376 DBG_ASSERT( _rxDocumentModel.is(), "ImplRepository::impl_getLocationForModel: invalid model!" ); 377 378 return m_aStore.find(xNormalized) != m_aStore.end(); 379 } 380 381 void ImplRepository::impl_initDocLibraryContainers_nothrow( const Reference< XPersistentLibraryContainer >& _rxBasicLibraries, const Reference< XPersistentLibraryContainer >& _rxDialogLibraries ) 382 { 383 OSL_PRECOND( _rxBasicLibraries.is() && _rxDialogLibraries.is(), 384 "ImplRepository::impl_initDocLibraryContainers_nothrow: illegal library containers, this will crash!" ); 385 386 try 387 { 388 // ensure there's a standard library in the basic container 389 OUString aStdLibName( "Standard" ); 390 if ( !_rxBasicLibraries->hasByName( aStdLibName ) ) 391 { 392 _rxBasicLibraries->createLibrary( aStdLibName ); 393 } 394 // as well as in the dialog container 395 if ( !_rxDialogLibraries->hasByName( aStdLibName ) ) 396 { 397 _rxDialogLibraries->createLibrary( aStdLibName ); 398 } 399 } 400 catch( const Exception& ) 401 { 402 DBG_UNHANDLED_EXCEPTION("basic"); 403 } 404 } 405 406 bool ImplRepository::impl_createManagerForModel( std::unique_ptr<BasicManager>& _out_rpBasicManager, const Reference< XModel >& _rxDocumentModel ) 407 { 408 StarBASIC* pAppBasic = impl_getDefaultAppBasicLibrary(); 409 410 _out_rpBasicManager = nullptr; 411 Reference< XStorage > xStorage; 412 if ( !impl_getDocumentStorage_nothrow( _rxDocumentModel, xStorage ) ) 413 { 414 // the document is not able to provide the storage it is based on. 415 return false; 416 } 417 Reference< XPersistentLibraryContainer > xBasicLibs; 418 Reference< XPersistentLibraryContainer > xDialogLibs; 419 if ( !impl_getDocumentLibraryContainers_nothrow( _rxDocumentModel, xBasicLibs, xDialogLibs ) ) 420 // the document does not have BasicLibraries and DialogLibraries 421 return false; 422 423 if ( xStorage.is() ) 424 { 425 // load BASIC-manager 426 SfxErrorContext aErrContext( ERRCTX_SFX_LOADBASIC, 427 ::comphelper::DocumentInfo::getDocumentTitle( _rxDocumentModel ) ); 428 OUString aAppBasicDir = SvtPathOptions().GetBasicPath(); 429 430 // Storage and BaseURL are only needed by binary documents! 431 tools::SvRef<SotStorage> xDummyStor = new SotStorage( OUString() ); 432 _out_rpBasicManager.reset(new BasicManager( *xDummyStor, OUString() /* TODO/LATER: xStorage */, 433 pAppBasic, 434 &aAppBasicDir, true )); 435 if ( !_out_rpBasicManager->GetErrors().empty() ) 436 { 437 // handle errors 438 std::vector<BasicError>& aErrors = _out_rpBasicManager->GetErrors(); 439 for(const auto& rError : aErrors) 440 { 441 // show message to user 442 if ( ErrorHandler::HandleError( rError.GetErrorId() ) == DialogMask::ButtonsCancel ) 443 { 444 // user wants to break loading of BASIC-manager 445 _out_rpBasicManager.reset(); 446 xStorage.clear(); 447 break; 448 } 449 } 450 } 451 } 452 453 // not loaded? 454 if ( !xStorage.is() ) 455 { 456 // create new BASIC-manager 457 StarBASIC* pBasic = new StarBASIC( pAppBasic ); 458 pBasic->SetFlag( SbxFlagBits::ExtSearch ); 459 _out_rpBasicManager.reset(new BasicManager( pBasic, nullptr, true )); 460 } 461 462 // knit the containers with the BasicManager 463 LibraryContainerInfo aInfo( xBasicLibs, xDialogLibs, dynamic_cast< OldBasicPassword* >( xBasicLibs.get() ) ); 464 OSL_ENSURE( aInfo.mpOldBasicPassword, "ImplRepository::impl_createManagerForModel: wrong BasicLibraries implementation!" ); 465 _out_rpBasicManager->SetLibraryContainerInfo( aInfo ); 466 467 // initialize the containers 468 impl_initDocLibraryContainers_nothrow( xBasicLibs, xDialogLibs ); 469 470 // so that also dialogs etc. could be 'qualified' addressed 471 _out_rpBasicManager->GetLib(0)->SetParent( pAppBasic ); 472 473 // global properties in the document's Basic 474 _out_rpBasicManager->SetGlobalUNOConstant( "ThisComponent", css::uno::Any( _rxDocumentModel ) ); 475 476 // notify 477 impl_notifyCreationListeners( _rxDocumentModel, *_out_rpBasicManager ); 478 479 // register as listener for this model being disposed/closed 480 OSL_ENSURE( _rxDocumentModel.is(), "ImplRepository::impl_createManagerForModel: the document must be an XComponent!" ); 481 assert(impl_hasLocationForModel(_rxDocumentModel)); 482 startComponentListening( _rxDocumentModel ); 483 484 bool bOk = false; 485 // startComponentListening may fail in a disposed _rxDocumentModel, in which case _out_rpBasicManager will be removed 486 // from the map and destroyed 487 if (impl_hasLocationForModel(_rxDocumentModel)) 488 { 489 bOk = true; 490 // register as listener for the BasicManager being destroyed 491 StartListening( *_out_rpBasicManager ); 492 } 493 494 // #i104876: Library container must not be modified just after 495 // creation. This happens as side effect when creating default 496 // "Standard" libraries and needs to be corrected here 497 xBasicLibs->setModified( false ); 498 xDialogLibs->setModified( false ); 499 return bOk; 500 } 501 502 bool ImplRepository::impl_getDocumentStorage_nothrow( const Reference< XModel >& _rxDocument, Reference< XStorage >& _out_rStorage ) 503 { 504 _out_rStorage.clear(); 505 try 506 { 507 Reference< XStorageBasedDocument > xStorDoc( _rxDocument, UNO_QUERY_THROW ); 508 _out_rStorage.set( xStorDoc->getDocumentStorage() ); 509 } 510 catch( const Exception& ) 511 { 512 DBG_UNHANDLED_EXCEPTION("basic"); 513 return false; 514 } 515 return true; 516 } 517 518 519 bool ImplRepository::impl_getDocumentLibraryContainers_nothrow( const Reference< XModel >& _rxDocument, 520 Reference< XPersistentLibraryContainer >& _out_rxBasicLibraries, Reference< XPersistentLibraryContainer >& _out_rxDialogLibraries ) 521 { 522 _out_rxBasicLibraries.clear(); 523 _out_rxDialogLibraries.clear(); 524 try 525 { 526 Reference< XEmbeddedScripts > xScripts( _rxDocument, UNO_QUERY_THROW ); 527 _out_rxBasicLibraries.set( xScripts->getBasicLibraries(), UNO_QUERY_THROW ); 528 _out_rxDialogLibraries.set( xScripts->getDialogLibraries(), UNO_QUERY_THROW ); 529 } 530 catch( const Exception& ) 531 { 532 DBG_UNHANDLED_EXCEPTION("basic"); 533 } 534 return _out_rxBasicLibraries.is() && _out_rxDialogLibraries.is(); 535 } 536 537 538 void ImplRepository::impl_removeFromRepository( const BasicManagerStore::iterator& _pos ) 539 { 540 OSL_PRECOND( _pos != m_aStore.end(), "ImplRepository::impl_removeFromRepository: invalid position!" ); 541 542 std::unique_ptr<BasicManager> pManager = std::move(_pos->second); 543 544 // *first* remove from map (else Notify won't work properly) 545 m_aStore.erase( _pos ); 546 547 // *then* delete the BasicManager 548 EndListening( *pManager ); 549 } 550 551 552 void ImplRepository::_disposing( const css::lang::EventObject& _rSource ) 553 { 554 SolarMutexGuard g; 555 556 Reference< XInterface > xNormalizedSource( _rSource.Source, UNO_QUERY ); 557 558 for ( BasicManagerStore::iterator loop = m_aStore.begin(); 559 loop != m_aStore.end(); 560 ++loop 561 ) 562 { 563 if ( loop->first.get() == xNormalizedSource.get() ) 564 { 565 impl_removeFromRepository( loop ); 566 return; 567 } 568 } 569 570 OSL_FAIL( "ImplRepository::_disposing: where does this come from?" ); 571 } 572 573 574 void ImplRepository::Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint ) 575 { 576 if ( _rHint.GetId() != SfxHintId::Dying ) 577 // not interested in 578 return; 579 580 BasicManager* pManager = dynamic_cast< BasicManager* >( &_rBC ); 581 OSL_ENSURE( pManager, "ImplRepository::Notify: where does this come from?" ); 582 583 for ( BasicManagerStore::iterator loop = m_aStore.begin(); 584 loop != m_aStore.end(); 585 ++loop 586 ) 587 { 588 if ( loop->second.get() == pManager ) 589 { 590 // a BasicManager which is still in our repository is being deleted. 591 // That's bad, since by definition, we *own* all instances in our 592 // repository. 593 OSL_FAIL( "ImplRepository::Notify: nobody should tamper with the managers, except ourself!" ); 594 m_aStore.erase( loop ); 595 break; 596 } 597 } 598 } 599 600 BasicManager* BasicManagerRepository::getDocumentBasicManager( const Reference< XModel >& _rxDocumentModel ) 601 { 602 return ImplRepository::Instance().getDocumentBasicManager( _rxDocumentModel ); 603 } 604 605 BasicManager* BasicManagerRepository::getApplicationBasicManager() 606 { 607 return ImplRepository::Instance().getOrCreateApplicationBasicManager(); 608 } 609 610 void BasicManagerRepository::resetApplicationBasicManager() 611 { 612 ImplRepository::setApplicationBasicManager( nullptr ); 613 } 614 615 void BasicManagerRepository::registerCreationListener( BasicManagerCreationListener& _rListener ) 616 { 617 ImplRepository::Instance().registerCreationListener( _rListener ); 618 } 619 620 void BasicManagerRepository::revokeCreationListener( BasicManagerCreationListener& _rListener ) 621 { 622 ImplRepository::Instance().revokeCreationListener( _rListener ); 623 } 624 625 } // namespace basic 626 627 628 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 629
