12f86921cSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 32f86921cSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 42f86921cSAndrew Rist * or more contributor license agreements. See the NOTICE file 52f86921cSAndrew Rist * distributed with this work for additional information 62f86921cSAndrew Rist * regarding copyright ownership. The ASF licenses this file 72f86921cSAndrew Rist * to you under the Apache License, Version 2.0 (the 82f86921cSAndrew Rist * "License"); you may not use this file except in compliance 92f86921cSAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 112f86921cSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 132f86921cSAndrew Rist * Unless required by applicable law or agreed to in writing, 142f86921cSAndrew Rist * software distributed under the License is distributed on an 152f86921cSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 162f86921cSAndrew Rist * KIND, either express or implied. See the License for the 172f86921cSAndrew Rist * specific language governing permissions and limitations 182f86921cSAndrew Rist * under the License. 19cdf0e10cSrcweir * 202f86921cSAndrew Rist *************************************************************/ 212f86921cSAndrew Rist 222f86921cSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25421ed02eSdamjan #include "precompiled_tdoc.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir /************************************************************************** 28cdf0e10cSrcweir TODO 29cdf0e10cSrcweir ************************************************************************** 30cdf0e10cSrcweir 31cdf0e10cSrcweir *************************************************************************/ 32cdf0e10cSrcweir 33cdf0e10cSrcweir #include "osl/diagnose.h" 34cdf0e10cSrcweir #include "rtl/ref.hxx" 35cdf0e10cSrcweir #include "cppuhelper/weak.hxx" 36cdf0e10cSrcweir 37cdf0e10cSrcweir #include "comphelper/namedvaluecollection.hxx" 38cdf0e10cSrcweir #include "comphelper/documentinfo.hxx" 39cdf0e10cSrcweir 40cdf0e10cSrcweir #include "com/sun/star/awt/XTopWindow.hpp" 41cdf0e10cSrcweir #include "com/sun/star/beans/XPropertySet.hpp" 42cdf0e10cSrcweir #include "com/sun/star/container/XEnumerationAccess.hpp" 43cdf0e10cSrcweir #include "com/sun/star/document/XStorageBasedDocument.hpp" 44cdf0e10cSrcweir #include "com/sun/star/frame/XStorable.hpp" 45cdf0e10cSrcweir #include "com/sun/star/lang/DisposedException.hpp" 46cdf0e10cSrcweir #include "com/sun/star/util/XCloseBroadcaster.hpp" 47cdf0e10cSrcweir 48cdf0e10cSrcweir #include "tdoc_docmgr.hxx" 49cdf0e10cSrcweir 50cdf0e10cSrcweir using namespace com::sun::star; 51cdf0e10cSrcweir using namespace tdoc_ucp; 52cdf0e10cSrcweir using ::comphelper::DocumentInfo; 53cdf0e10cSrcweir 54cdf0e10cSrcweir //========================================================================= 55cdf0e10cSrcweir //========================================================================= 56cdf0e10cSrcweir // 57cdf0e10cSrcweir // OfficeDocumentsCloseListener Implementation. 58cdf0e10cSrcweir // 59cdf0e10cSrcweir //========================================================================= 60cdf0e10cSrcweir //========================================================================= 61cdf0e10cSrcweir 62cdf0e10cSrcweir //========================================================================= 63cdf0e10cSrcweir // 64cdf0e10cSrcweir // util::XCloseListener 65cdf0e10cSrcweir // 66cdf0e10cSrcweir //========================================================================= 67cdf0e10cSrcweir 68cdf0e10cSrcweir // virtual 69cdf0e10cSrcweir void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::queryClosing( 70cdf0e10cSrcweir const lang::EventObject& /*Source*/, sal_Bool /*GetsOwnership*/ ) 71cdf0e10cSrcweir throw ( util::CloseVetoException, 72cdf0e10cSrcweir uno::RuntimeException ) 73cdf0e10cSrcweir { 74cdf0e10cSrcweir } 75cdf0e10cSrcweir 76cdf0e10cSrcweir //========================================================================= 77cdf0e10cSrcweir void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::notifyClosing( 78cdf0e10cSrcweir const lang::EventObject& Source ) 79cdf0e10cSrcweir throw ( uno::RuntimeException ) 80cdf0e10cSrcweir { 81cdf0e10cSrcweir document::EventObject aDocEvent; 82cdf0e10cSrcweir aDocEvent.Source = Source.Source; 83cdf0e10cSrcweir aDocEvent.EventName = rtl::OUString( 84cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM( "OfficeDocumentsListener::notifyClosing" ) ); 85cdf0e10cSrcweir m_pManager->notifyEvent( aDocEvent ); 86cdf0e10cSrcweir } 87cdf0e10cSrcweir 88cdf0e10cSrcweir //========================================================================= 89cdf0e10cSrcweir // 90cdf0e10cSrcweir // lang::XEventListener (base of util::XCloseListener) 91cdf0e10cSrcweir // 92cdf0e10cSrcweir //========================================================================= 93cdf0e10cSrcweir 94cdf0e10cSrcweir // virtual 95cdf0e10cSrcweir void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::disposing( 96cdf0e10cSrcweir const lang::EventObject& /*Source*/ ) 97cdf0e10cSrcweir throw ( uno::RuntimeException ) 98cdf0e10cSrcweir { 99cdf0e10cSrcweir } 100cdf0e10cSrcweir 101cdf0e10cSrcweir //========================================================================= 102cdf0e10cSrcweir //========================================================================= 103cdf0e10cSrcweir // 104cdf0e10cSrcweir // OfficeDocumentsManager Implementation. 105cdf0e10cSrcweir // 106cdf0e10cSrcweir //========================================================================= 107cdf0e10cSrcweir //========================================================================= 108cdf0e10cSrcweir 109cdf0e10cSrcweir OfficeDocumentsManager::OfficeDocumentsManager( 110cdf0e10cSrcweir const uno::Reference< lang::XMultiServiceFactory > & xSMgr, 111cdf0e10cSrcweir OfficeDocumentsEventListener * pDocEventListener ) 112cdf0e10cSrcweir : m_xSMgr( xSMgr ), 113cdf0e10cSrcweir m_xDocEvtNotifier( createDocumentEventNotifier( xSMgr ) ), 114cdf0e10cSrcweir m_pDocEventListener( pDocEventListener ), 115cdf0e10cSrcweir m_xDocCloseListener( new OfficeDocumentsCloseListener( this ) ) 116cdf0e10cSrcweir { 117cdf0e10cSrcweir if ( m_xDocEvtNotifier.is() ) 118cdf0e10cSrcweir { 119cdf0e10cSrcweir // Order is important (multithreaded environment) 120cdf0e10cSrcweir m_xDocEvtNotifier->addEventListener( this ); 121cdf0e10cSrcweir buildDocumentsList(); 122cdf0e10cSrcweir } 123cdf0e10cSrcweir } 124cdf0e10cSrcweir 125cdf0e10cSrcweir //========================================================================= 126cdf0e10cSrcweir // virtual 127cdf0e10cSrcweir OfficeDocumentsManager::~OfficeDocumentsManager() 128cdf0e10cSrcweir { 129cdf0e10cSrcweir //OSL_ENSURE( m_aDocs.empty(), "document list not empty!" ); 130cdf0e10cSrcweir // no need to assert this: Normal shutdown of OOo could already trigger it, since the order in which 131cdf0e10cSrcweir // objects are actually released/destroyed upon shutdown is not defined. And when we arrive *here*, 132cdf0e10cSrcweir // OOo *is* shutting down currently, since we're held by the TDOC provider, which is disposed 133cdf0e10cSrcweir // upon shutdown. 134cdf0e10cSrcweir } 135cdf0e10cSrcweir 136cdf0e10cSrcweir //========================================================================= 137cdf0e10cSrcweir void OfficeDocumentsManager::destroy() 138cdf0e10cSrcweir { 139cdf0e10cSrcweir if ( m_xDocEvtNotifier.is() ) 140cdf0e10cSrcweir m_xDocEvtNotifier->removeEventListener( this ); 141cdf0e10cSrcweir } 142cdf0e10cSrcweir 143cdf0e10cSrcweir //========================================================================= 144cdf0e10cSrcweir static rtl::OUString 145cdf0e10cSrcweir getDocumentId( const uno::Reference< uno::XInterface > & xDoc ) 146cdf0e10cSrcweir { 147cdf0e10cSrcweir rtl::OUString aId; 148cdf0e10cSrcweir 149cdf0e10cSrcweir // Try to get the UID directly from the document. 150cdf0e10cSrcweir uno::Reference< beans::XPropertySet > xPropSet( xDoc, uno::UNO_QUERY ); 151cdf0e10cSrcweir if ( xPropSet.is() ) 152cdf0e10cSrcweir { 153cdf0e10cSrcweir try 154cdf0e10cSrcweir { 155cdf0e10cSrcweir uno::Any aValue = xPropSet->getPropertyValue( 156cdf0e10cSrcweir rtl::OUString( 157cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM( "RuntimeUID" ) ) ); 158cdf0e10cSrcweir aValue >>= aId; 159cdf0e10cSrcweir } 160cdf0e10cSrcweir catch ( beans::UnknownPropertyException const & ) 161cdf0e10cSrcweir { 162cdf0e10cSrcweir // Not actually an error. Property is optional. 163cdf0e10cSrcweir } 164cdf0e10cSrcweir catch ( lang::WrappedTargetException const & ) 165cdf0e10cSrcweir { 166cdf0e10cSrcweir OSL_ENSURE( false, "Caught WrappedTargetException!" ); 167cdf0e10cSrcweir } 168cdf0e10cSrcweir } 169cdf0e10cSrcweir 170cdf0e10cSrcweir if ( aId.getLength() == 0 ) 171cdf0e10cSrcweir { 172cdf0e10cSrcweir // fallback: generate UID from document's this pointer. 173cdf0e10cSrcweir // normalize the interface pointer first. Else, calls with different 174cdf0e10cSrcweir // interfaces to the same object (say, XFoo and XBar) will produce 175cdf0e10cSrcweir // different IDs 176cdf0e10cSrcweir uno::Reference< uno::XInterface > xNormalizedIFace( xDoc, uno::UNO_QUERY ); 177cdf0e10cSrcweir sal_Int64 nId = reinterpret_cast< sal_Int64 >( xNormalizedIFace.get() ); 178cdf0e10cSrcweir aId = rtl::OUString::valueOf( nId ); 179cdf0e10cSrcweir } 180cdf0e10cSrcweir 181cdf0e10cSrcweir OSL_ENSURE( aId.getLength() > 0, "getDocumentId - Empty id!" ); 182cdf0e10cSrcweir return aId; 183cdf0e10cSrcweir } 184cdf0e10cSrcweir 185cdf0e10cSrcweir //========================================================================= 186cdf0e10cSrcweir // 187cdf0e10cSrcweir // document::XEventListener 188cdf0e10cSrcweir // 189cdf0e10cSrcweir //========================================================================= 190cdf0e10cSrcweir 191cdf0e10cSrcweir // virtual 192cdf0e10cSrcweir void SAL_CALL OfficeDocumentsManager::notifyEvent( 193cdf0e10cSrcweir const document::EventObject & Event ) 194cdf0e10cSrcweir throw ( uno::RuntimeException ) 195cdf0e10cSrcweir { 196cdf0e10cSrcweir /* 197cdf0e10cSrcweir Events documentation: OOo Developer's Guide / Writing UNO Components / Jobs 198cdf0e10cSrcweir */ 199cdf0e10cSrcweir 200cdf0e10cSrcweir if ( Event.EventName.equalsAsciiL( 201cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM( "OnLoadFinished" ) ) // document loaded 202cdf0e10cSrcweir || Event.EventName.equalsAsciiL( 203cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM( "OnCreate" ) ) ) // document created 204cdf0e10cSrcweir { 205cdf0e10cSrcweir if ( isOfficeDocument( Event.Source ) ) 206cdf0e10cSrcweir { 207cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMtx ); 208cdf0e10cSrcweir 209cdf0e10cSrcweir uno::Reference< frame::XModel > 210cdf0e10cSrcweir xModel( Event.Source, uno::UNO_QUERY ); 211cdf0e10cSrcweir OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); 212cdf0e10cSrcweir 213cdf0e10cSrcweir DocumentList::const_iterator it = m_aDocs.begin(); 214cdf0e10cSrcweir while ( it != m_aDocs.end() ) 215cdf0e10cSrcweir { 216cdf0e10cSrcweir if ( (*it).second.xModel == xModel ) 217cdf0e10cSrcweir { 218cdf0e10cSrcweir // already known. 219cdf0e10cSrcweir break; 220cdf0e10cSrcweir } 221cdf0e10cSrcweir ++it; 222cdf0e10cSrcweir } 223cdf0e10cSrcweir 224cdf0e10cSrcweir if ( it == m_aDocs.end() ) 225cdf0e10cSrcweir { 226cdf0e10cSrcweir // new document 227cdf0e10cSrcweir 228cdf0e10cSrcweir uno::Reference< document::XStorageBasedDocument > 229cdf0e10cSrcweir xDoc( Event.Source, uno::UNO_QUERY ); 230cdf0e10cSrcweir OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" ); 231cdf0e10cSrcweir 232cdf0e10cSrcweir uno::Reference< embed::XStorage > xStorage 233cdf0e10cSrcweir = xDoc->getDocumentStorage(); 234cdf0e10cSrcweir OSL_ENSURE( xStorage.is(), "Got no document storage!" ); 235cdf0e10cSrcweir 236cdf0e10cSrcweir rtl:: OUString aDocId = getDocumentId( Event.Source ); 237cdf0e10cSrcweir rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( 238cdf0e10cSrcweir uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) ); 239cdf0e10cSrcweir 240cdf0e10cSrcweir m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel ); 241cdf0e10cSrcweir 242cdf0e10cSrcweir uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( 243cdf0e10cSrcweir Event.Source, uno::UNO_QUERY ); 244cdf0e10cSrcweir OSL_ENSURE( xCloseBroadcaster.is(), 245cdf0e10cSrcweir "OnLoadFinished/OnCreate event: got no close broadcaster!" ); 246cdf0e10cSrcweir 247cdf0e10cSrcweir if ( xCloseBroadcaster.is() ) 248cdf0e10cSrcweir xCloseBroadcaster->addCloseListener( m_xDocCloseListener ); 249cdf0e10cSrcweir 250cdf0e10cSrcweir // Propagate document closure. 251cdf0e10cSrcweir OSL_ENSURE( m_pDocEventListener, 252cdf0e10cSrcweir "OnLoadFinished/OnCreate event: no owner for insert event propagation!" ); 253cdf0e10cSrcweir 254cdf0e10cSrcweir if ( m_pDocEventListener ) 255cdf0e10cSrcweir m_pDocEventListener->notifyDocumentOpened( aDocId ); 256cdf0e10cSrcweir } 257cdf0e10cSrcweir } 258cdf0e10cSrcweir } 259cdf0e10cSrcweir else if ( Event.EventName.equalsAsciiL( 260cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM( "OfficeDocumentsListener::notifyClosing" ) ) ) 261cdf0e10cSrcweir { 262cdf0e10cSrcweir if ( isOfficeDocument( Event.Source ) ) 263cdf0e10cSrcweir { 264cdf0e10cSrcweir // Document has been closed (unloaded) 265cdf0e10cSrcweir 266cdf0e10cSrcweir // #163732# - Official event "OnUnload" does not work here. Event 267cdf0e10cSrcweir // gets fired to early. Other OnUnload listeners called after this 268cdf0e10cSrcweir // listener may still need TDOC access to the document. Remove the 269cdf0e10cSrcweir // document from TDOC docs list on XCloseListener::notifyClosing. 270cdf0e10cSrcweir // See OfficeDocumentsManager::OfficeDocumentsListener::notifyClosing. 271cdf0e10cSrcweir 272cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMtx ); 273cdf0e10cSrcweir 274cdf0e10cSrcweir uno::Reference< frame::XModel > 275cdf0e10cSrcweir xModel( Event.Source, uno::UNO_QUERY ); 276cdf0e10cSrcweir OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); 277cdf0e10cSrcweir 278cdf0e10cSrcweir DocumentList::iterator it = m_aDocs.begin(); 279cdf0e10cSrcweir while ( it != m_aDocs.end() ) 280cdf0e10cSrcweir { 281cdf0e10cSrcweir if ( (*it).second.xModel == xModel ) 282cdf0e10cSrcweir { 283cdf0e10cSrcweir // Propagate document closure. 284cdf0e10cSrcweir OSL_ENSURE( m_pDocEventListener, 285cdf0e10cSrcweir "OnUnload event: no owner for close event propagation!" ); 286cdf0e10cSrcweir 287cdf0e10cSrcweir if ( m_pDocEventListener ) 288cdf0e10cSrcweir { 289cdf0e10cSrcweir rtl::OUString aDocId( (*it).first ); 290cdf0e10cSrcweir m_pDocEventListener->notifyDocumentClosed( aDocId ); 291cdf0e10cSrcweir } 292cdf0e10cSrcweir break; 293cdf0e10cSrcweir } 294cdf0e10cSrcweir ++it; 295cdf0e10cSrcweir } 296cdf0e10cSrcweir 297cdf0e10cSrcweir OSL_ENSURE( it != m_aDocs.end(), 298cdf0e10cSrcweir "OnUnload event notified for unknown document!" ); 299cdf0e10cSrcweir 300cdf0e10cSrcweir if ( it != m_aDocs.end() ) 301cdf0e10cSrcweir { 302cdf0e10cSrcweir uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( 303cdf0e10cSrcweir Event.Source, uno::UNO_QUERY ); 304cdf0e10cSrcweir OSL_ENSURE( xCloseBroadcaster.is(), 305cdf0e10cSrcweir "OnUnload event: got no XCloseBroadcaster from XModel" ); 306cdf0e10cSrcweir 307cdf0e10cSrcweir if ( xCloseBroadcaster.is() ) 308cdf0e10cSrcweir xCloseBroadcaster->removeCloseListener( m_xDocCloseListener ); 309cdf0e10cSrcweir 310cdf0e10cSrcweir m_aDocs.erase( it ); 311cdf0e10cSrcweir } 312cdf0e10cSrcweir } 313cdf0e10cSrcweir } 314cdf0e10cSrcweir else if ( Event.EventName.equalsAsciiL( 315cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM( "OnSaveDone" ) ) ) 316cdf0e10cSrcweir { 317cdf0e10cSrcweir if ( isOfficeDocument( Event.Source ) ) 318cdf0e10cSrcweir { 319cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMtx ); 320cdf0e10cSrcweir 321cdf0e10cSrcweir uno::Reference< frame::XModel > 322cdf0e10cSrcweir xModel( Event.Source, uno::UNO_QUERY ); 323cdf0e10cSrcweir OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); 324cdf0e10cSrcweir 325cdf0e10cSrcweir DocumentList::iterator it = m_aDocs.begin(); 326cdf0e10cSrcweir while ( it != m_aDocs.end() ) 327cdf0e10cSrcweir { 328cdf0e10cSrcweir if ( (*it).second.xModel == xModel ) 329cdf0e10cSrcweir { 330cdf0e10cSrcweir // Storage gets exchanged while saving. 331cdf0e10cSrcweir uno::Reference< document::XStorageBasedDocument > 332cdf0e10cSrcweir xDoc( Event.Source, uno::UNO_QUERY ); 333cdf0e10cSrcweir OSL_ENSURE( xDoc.is(), 334cdf0e10cSrcweir "Got no document::XStorageBasedDocument!" ); 335cdf0e10cSrcweir 336cdf0e10cSrcweir uno::Reference< embed::XStorage > xStorage 337cdf0e10cSrcweir = xDoc->getDocumentStorage(); 338cdf0e10cSrcweir OSL_ENSURE( xStorage.is(), "Got no document storage!" ); 339cdf0e10cSrcweir 340cdf0e10cSrcweir (*it).second.xStorage = xStorage; 341cdf0e10cSrcweir break; 342cdf0e10cSrcweir } 343cdf0e10cSrcweir ++it; 344cdf0e10cSrcweir } 345cdf0e10cSrcweir 346cdf0e10cSrcweir OSL_ENSURE( it != m_aDocs.end(), 347cdf0e10cSrcweir "OnSaveDone event notified for unknown document!" ); 348cdf0e10cSrcweir } 349cdf0e10cSrcweir } 350cdf0e10cSrcweir else if ( Event.EventName.equalsAsciiL( 351cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM( "OnSaveAsDone" ) ) ) 352cdf0e10cSrcweir { 353cdf0e10cSrcweir if ( isOfficeDocument( Event.Source ) ) 354cdf0e10cSrcweir { 355cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMtx ); 356cdf0e10cSrcweir 357cdf0e10cSrcweir uno::Reference< frame::XModel > 358cdf0e10cSrcweir xModel( Event.Source, uno::UNO_QUERY ); 359cdf0e10cSrcweir OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); 360cdf0e10cSrcweir 361cdf0e10cSrcweir DocumentList::iterator it = m_aDocs.begin(); 362cdf0e10cSrcweir while ( it != m_aDocs.end() ) 363cdf0e10cSrcweir { 364cdf0e10cSrcweir if ( (*it).second.xModel == xModel ) 365cdf0e10cSrcweir { 366cdf0e10cSrcweir // Storage gets exchanged while saving. 367cdf0e10cSrcweir uno::Reference< document::XStorageBasedDocument > 368cdf0e10cSrcweir xDoc( Event.Source, uno::UNO_QUERY ); 369cdf0e10cSrcweir OSL_ENSURE( xDoc.is(), 370cdf0e10cSrcweir "Got no document::XStorageBasedDocument!" ); 371cdf0e10cSrcweir 372cdf0e10cSrcweir uno::Reference< embed::XStorage > xStorage 373cdf0e10cSrcweir = xDoc->getDocumentStorage(); 374cdf0e10cSrcweir OSL_ENSURE( xStorage.is(), "Got no document storage!" ); 375cdf0e10cSrcweir 376cdf0e10cSrcweir (*it).second.xStorage = xStorage; 377cdf0e10cSrcweir 378cdf0e10cSrcweir // Adjust title. 379cdf0e10cSrcweir (*it).second.aTitle = DocumentInfo::getDocumentTitle( xModel ); 380cdf0e10cSrcweir break; 381cdf0e10cSrcweir } 382cdf0e10cSrcweir ++it; 383cdf0e10cSrcweir } 384cdf0e10cSrcweir 385cdf0e10cSrcweir OSL_ENSURE( it != m_aDocs.end(), 386cdf0e10cSrcweir "OnSaveAsDone event notified for unknown document!" ); 387cdf0e10cSrcweir } 388cdf0e10cSrcweir } 389cdf0e10cSrcweir else if ( Event.EventName.equalsAsciiL( 390cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM( "OnTitleChanged" ) ) ) 391cdf0e10cSrcweir { 392cdf0e10cSrcweir if ( isOfficeDocument( Event.Source ) ) 393cdf0e10cSrcweir { 394cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMtx ); 395cdf0e10cSrcweir 396cdf0e10cSrcweir uno::Reference< frame::XModel > 397cdf0e10cSrcweir xModel( Event.Source, uno::UNO_QUERY ); 398cdf0e10cSrcweir OSL_ENSURE( xModel.is(), "Got no frame::XModel!" ); 399cdf0e10cSrcweir 400cdf0e10cSrcweir DocumentList::iterator it = m_aDocs.begin(); 401cdf0e10cSrcweir while ( it != m_aDocs.end() ) 402cdf0e10cSrcweir { 403cdf0e10cSrcweir if ( (*it).second.xModel == xModel ) 404cdf0e10cSrcweir { 405cdf0e10cSrcweir // Adjust title. 406cdf0e10cSrcweir rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( xModel ); 407cdf0e10cSrcweir (*it).second.aTitle = aTitle; 408cdf0e10cSrcweir 409cdf0e10cSrcweir // Adjust storage. 410cdf0e10cSrcweir uno::Reference< document::XStorageBasedDocument > 411cdf0e10cSrcweir xDoc( Event.Source, uno::UNO_QUERY ); 412cdf0e10cSrcweir OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" ); 413cdf0e10cSrcweir 414cdf0e10cSrcweir uno::Reference< embed::XStorage > xStorage 415cdf0e10cSrcweir = xDoc->getDocumentStorage(); 416cdf0e10cSrcweir OSL_ENSURE( xDoc.is(), "Got no document storage!" ); 417cdf0e10cSrcweir 418cdf0e10cSrcweir rtl:: OUString aDocId = getDocumentId( Event.Source ); 419cdf0e10cSrcweir 420cdf0e10cSrcweir m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel ); 421cdf0e10cSrcweir break; 422cdf0e10cSrcweir } 423cdf0e10cSrcweir ++it; 424cdf0e10cSrcweir } 425cdf0e10cSrcweir 426cdf0e10cSrcweir // OSL_ENSURE( it != m_aDocs.end(), 427cdf0e10cSrcweir // "TitleChanged event notified for unknown document!" ); 428cdf0e10cSrcweir // TODO: re-enable this assertion. It has been disabled for now, since it breaks the assertion-free smoketest, 429cdf0e10cSrcweir // and the fix is more difficult than what can be done now. 430cdf0e10cSrcweir // The problem is that at the moment, when you close a SFX-based document via API, it will first 431cdf0e10cSrcweir // fire the notifyClosing event, which will make the OfficeDocumentsManager remove the doc from its list. 432cdf0e10cSrcweir // Then, it will notify an OnTitleChanged, then an OnUnload. Documents closed via call the notifyClosing 433cdf0e10cSrcweir // *after* OnUnload and all other On* events. 434cdf0e10cSrcweir // In agreement with MBA, the implementation for SfxBaseModel::Close should be changed to also send notifyClosing 435cdf0e10cSrcweir // as last event. When this happens, the assertion here must be enabled, again. 436cdf0e10cSrcweir // There is no bug for this, yet - IZ is currently down due to the Kenai migration. 437cdf0e10cSrcweir // 2011-02-23 / frank.schoenheit@sun.com 438cdf0e10cSrcweir } 439cdf0e10cSrcweir } 440cdf0e10cSrcweir } 441cdf0e10cSrcweir 442cdf0e10cSrcweir //========================================================================= 443cdf0e10cSrcweir // 444cdf0e10cSrcweir // lang::XEventListener (base of document::XEventListener) 445cdf0e10cSrcweir // 446cdf0e10cSrcweir //========================================================================= 447cdf0e10cSrcweir 448cdf0e10cSrcweir // virtual 449cdf0e10cSrcweir void SAL_CALL OfficeDocumentsManager::disposing( 450cdf0e10cSrcweir const lang::EventObject& /*Source*/ ) 451cdf0e10cSrcweir throw ( uno::RuntimeException ) 452cdf0e10cSrcweir { 453cdf0e10cSrcweir } 454cdf0e10cSrcweir 455cdf0e10cSrcweir //========================================================================= 456cdf0e10cSrcweir // 457cdf0e10cSrcweir // Non-interface. 458cdf0e10cSrcweir // 459cdf0e10cSrcweir //========================================================================= 460cdf0e10cSrcweir 461cdf0e10cSrcweir // static 462cdf0e10cSrcweir uno::Reference< document::XEventBroadcaster > 463cdf0e10cSrcweir OfficeDocumentsManager::createDocumentEventNotifier( 464cdf0e10cSrcweir const uno::Reference< lang::XMultiServiceFactory >& rXSMgr ) 465cdf0e10cSrcweir { 466cdf0e10cSrcweir uno::Reference< uno::XInterface > xIfc; 467cdf0e10cSrcweir try 468cdf0e10cSrcweir { 469cdf0e10cSrcweir xIfc = rXSMgr->createInstance( 470cdf0e10cSrcweir rtl::OUString( 471cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM( 472cdf0e10cSrcweir "com.sun.star.frame.GlobalEventBroadcaster" ) ) ); 473cdf0e10cSrcweir } 474cdf0e10cSrcweir catch ( uno::Exception const & ) 475cdf0e10cSrcweir { 476cdf0e10cSrcweir // handled below. 477cdf0e10cSrcweir } 478cdf0e10cSrcweir 479cdf0e10cSrcweir OSL_ENSURE( 480cdf0e10cSrcweir xIfc.is(), 481*5e7dbebbSJohn Bampton "Could not instantiate com.sun.star.frame.GlobalEventBroadcaster" ); 482cdf0e10cSrcweir 483cdf0e10cSrcweir if ( xIfc.is() ) 484cdf0e10cSrcweir { 485cdf0e10cSrcweir uno::Reference< document::XEventBroadcaster > xBC( 486cdf0e10cSrcweir xIfc, uno::UNO_QUERY ); 487cdf0e10cSrcweir 488cdf0e10cSrcweir OSL_ENSURE( 489cdf0e10cSrcweir xBC.is(), 490cdf0e10cSrcweir "com.sun.star.frame.GlobalEventBroadcaster does not implement " 491cdf0e10cSrcweir "interface com.sun.star.document.XEventBroadcaster!" ); 492cdf0e10cSrcweir 493cdf0e10cSrcweir return xBC; 494cdf0e10cSrcweir } 495cdf0e10cSrcweir else 496cdf0e10cSrcweir return uno::Reference< document::XEventBroadcaster >(); 497cdf0e10cSrcweir } 498cdf0e10cSrcweir 499cdf0e10cSrcweir //========================================================================= 500cdf0e10cSrcweir void OfficeDocumentsManager::buildDocumentsList() 501cdf0e10cSrcweir { 502cdf0e10cSrcweir OSL_ENSURE( m_xDocEvtNotifier.is(), 503cdf0e10cSrcweir "OfficeDocumentsManager::buildDocumentsList - " 504cdf0e10cSrcweir "No document event notifier!" ); 505cdf0e10cSrcweir 506cdf0e10cSrcweir uno::Reference< container::XEnumerationAccess > xEnumAccess( 507cdf0e10cSrcweir m_xDocEvtNotifier, uno::UNO_QUERY_THROW ); 508cdf0e10cSrcweir 509cdf0e10cSrcweir uno::Reference< container::XEnumeration > xEnum 510cdf0e10cSrcweir = xEnumAccess->createEnumeration(); 511cdf0e10cSrcweir 512cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMtx ); 513cdf0e10cSrcweir 514cdf0e10cSrcweir while ( xEnum->hasMoreElements() ) 515cdf0e10cSrcweir { 516cdf0e10cSrcweir uno::Any aValue = xEnum->nextElement(); 517cdf0e10cSrcweir // container::NoSuchElementException 518cdf0e10cSrcweir // lang::WrappedTargetException 519cdf0e10cSrcweir 520cdf0e10cSrcweir try 521cdf0e10cSrcweir { 522cdf0e10cSrcweir uno::Reference< frame::XModel > xModel; 523cdf0e10cSrcweir aValue >>= xModel; 524cdf0e10cSrcweir 525cdf0e10cSrcweir if ( xModel.is() ) 526cdf0e10cSrcweir { 527cdf0e10cSrcweir if ( isOfficeDocument( xModel ) ) 528cdf0e10cSrcweir { 529cdf0e10cSrcweir DocumentList::const_iterator it = m_aDocs.begin(); 530cdf0e10cSrcweir while ( it != m_aDocs.end() ) 531cdf0e10cSrcweir { 532cdf0e10cSrcweir if ( (*it).second.xModel == xModel ) 533cdf0e10cSrcweir { 534cdf0e10cSrcweir // already known. 535cdf0e10cSrcweir break; 536cdf0e10cSrcweir } 537cdf0e10cSrcweir ++it; 538cdf0e10cSrcweir } 539cdf0e10cSrcweir 540cdf0e10cSrcweir if ( it == m_aDocs.end() ) 541cdf0e10cSrcweir { 542cdf0e10cSrcweir // new document 543cdf0e10cSrcweir rtl::OUString aDocId = getDocumentId( xModel ); 544cdf0e10cSrcweir rtl::OUString aTitle = DocumentInfo::getDocumentTitle( xModel ); 545cdf0e10cSrcweir 546cdf0e10cSrcweir uno::Reference< document::XStorageBasedDocument > 547cdf0e10cSrcweir xDoc( xModel, uno::UNO_QUERY ); 548cdf0e10cSrcweir OSL_ENSURE( xDoc.is(), 549cdf0e10cSrcweir "Got no document::XStorageBasedDocument!" ); 550cdf0e10cSrcweir 551cdf0e10cSrcweir uno::Reference< embed::XStorage > xStorage 552cdf0e10cSrcweir = xDoc->getDocumentStorage(); 553cdf0e10cSrcweir OSL_ENSURE( xDoc.is(), "Got no document storage!" ); 554cdf0e10cSrcweir 555cdf0e10cSrcweir m_aDocs[ aDocId ] 556cdf0e10cSrcweir = StorageInfo( aTitle, xStorage, xModel ); 557cdf0e10cSrcweir 558cdf0e10cSrcweir uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( 559cdf0e10cSrcweir xModel, uno::UNO_QUERY ); 560cdf0e10cSrcweir OSL_ENSURE( xCloseBroadcaster.is(), 561cdf0e10cSrcweir "buildDocumentsList: got no close broadcaster!" ); 562cdf0e10cSrcweir 563cdf0e10cSrcweir if ( xCloseBroadcaster.is() ) 564cdf0e10cSrcweir xCloseBroadcaster->addCloseListener( m_xDocCloseListener ); 565cdf0e10cSrcweir } 566cdf0e10cSrcweir } 567cdf0e10cSrcweir } 568cdf0e10cSrcweir } 569cdf0e10cSrcweir catch ( lang::DisposedException const & ) 570cdf0e10cSrcweir { 571cdf0e10cSrcweir // Note: Due to race conditions the XEnumeration can 572cdf0e10cSrcweir // contains docs that already have been closed 573cdf0e10cSrcweir } 574cdf0e10cSrcweir } 575cdf0e10cSrcweir } 576cdf0e10cSrcweir 577cdf0e10cSrcweir //========================================================================= 578cdf0e10cSrcweir uno::Reference< embed::XStorage > 579cdf0e10cSrcweir OfficeDocumentsManager::queryStorage( const rtl::OUString & rDocId ) 580cdf0e10cSrcweir { 581cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMtx ); 582cdf0e10cSrcweir 583cdf0e10cSrcweir DocumentList::const_iterator it = m_aDocs.find( rDocId ); 584cdf0e10cSrcweir if ( it == m_aDocs.end() ) 585cdf0e10cSrcweir return uno::Reference< embed::XStorage >(); 586cdf0e10cSrcweir 587cdf0e10cSrcweir return (*it).second.xStorage; 588cdf0e10cSrcweir } 589cdf0e10cSrcweir 590cdf0e10cSrcweir //========================================================================= 591cdf0e10cSrcweir rtl::OUString OfficeDocumentsManager::queryDocumentId( 592cdf0e10cSrcweir const uno::Reference< frame::XModel > & xModel ) 593cdf0e10cSrcweir { 594cdf0e10cSrcweir return getDocumentId( xModel ); 595cdf0e10cSrcweir } 596cdf0e10cSrcweir 597cdf0e10cSrcweir //========================================================================= 598cdf0e10cSrcweir uno::Reference< frame::XModel > 599cdf0e10cSrcweir OfficeDocumentsManager::queryDocumentModel( const rtl::OUString & rDocId ) 600cdf0e10cSrcweir { 601cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMtx ); 602cdf0e10cSrcweir 603cdf0e10cSrcweir DocumentList::const_iterator it = m_aDocs.find( rDocId ); 604cdf0e10cSrcweir if ( it == m_aDocs.end() ) 605cdf0e10cSrcweir return uno::Reference< frame::XModel >(); 606cdf0e10cSrcweir 607cdf0e10cSrcweir return (*it).second.xModel; 608cdf0e10cSrcweir } 609cdf0e10cSrcweir 610cdf0e10cSrcweir //========================================================================= 611cdf0e10cSrcweir uno::Sequence< rtl::OUString > OfficeDocumentsManager::queryDocuments() 612cdf0e10cSrcweir { 613cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMtx ); 614cdf0e10cSrcweir 615cdf0e10cSrcweir uno::Sequence< rtl::OUString > aRet( m_aDocs.size() ); 616cdf0e10cSrcweir sal_Int32 nPos = 0; 617cdf0e10cSrcweir 618cdf0e10cSrcweir DocumentList::const_iterator it = m_aDocs.begin(); 619cdf0e10cSrcweir while ( it != m_aDocs.end() ) 620cdf0e10cSrcweir { 621cdf0e10cSrcweir aRet[ nPos ] = (*it).first; 622cdf0e10cSrcweir ++it; 623cdf0e10cSrcweir ++nPos; 624cdf0e10cSrcweir } 625cdf0e10cSrcweir return aRet; 626cdf0e10cSrcweir } 627cdf0e10cSrcweir 628cdf0e10cSrcweir //========================================================================= 629cdf0e10cSrcweir rtl::OUString 630cdf0e10cSrcweir OfficeDocumentsManager::queryStorageTitle( const rtl::OUString & rDocId ) 631cdf0e10cSrcweir { 632cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMtx ); 633cdf0e10cSrcweir 634cdf0e10cSrcweir DocumentList::const_iterator it = m_aDocs.find( rDocId ); 635cdf0e10cSrcweir if ( it == m_aDocs.end() ) 636cdf0e10cSrcweir return rtl::OUString(); 637cdf0e10cSrcweir 638cdf0e10cSrcweir return (*it).second.aTitle; 639cdf0e10cSrcweir } 640cdf0e10cSrcweir 641cdf0e10cSrcweir //========================================================================= 642cdf0e10cSrcweir bool OfficeDocumentsManager::isDocumentPreview( 643cdf0e10cSrcweir const uno::Reference< frame::XModel > & xModel ) 644cdf0e10cSrcweir { 645cdf0e10cSrcweir if ( !xModel.is() ) 646cdf0e10cSrcweir return false; 647cdf0e10cSrcweir 648cdf0e10cSrcweir ::comphelper::NamedValueCollection aArgs( 649cdf0e10cSrcweir xModel->getArgs() ); 650cdf0e10cSrcweir sal_Bool bIsPreview = aArgs.getOrDefault( "Preview", sal_False ); 651cdf0e10cSrcweir return bIsPreview; 652cdf0e10cSrcweir } 653cdf0e10cSrcweir 654cdf0e10cSrcweir //========================================================================= 655cdf0e10cSrcweir bool OfficeDocumentsManager::isHelpDocument( 656cdf0e10cSrcweir const uno::Reference< frame::XModel > & xModel ) 657cdf0e10cSrcweir { 658cdf0e10cSrcweir if ( !xModel.is() ) 659cdf0e10cSrcweir return false; 660cdf0e10cSrcweir 661cdf0e10cSrcweir ::rtl::OUString sURL( xModel->getURL() ); 662cdf0e10cSrcweir if ( sURL.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.help://" ) ) ) 663cdf0e10cSrcweir return true; 664cdf0e10cSrcweir 665cdf0e10cSrcweir return false; 666cdf0e10cSrcweir } 667cdf0e10cSrcweir 668cdf0e10cSrcweir //========================================================================= 669cdf0e10cSrcweir bool OfficeDocumentsManager::isWithoutOrInTopLevelFrame( 670cdf0e10cSrcweir const uno::Reference< frame::XModel > & xModel ) 671cdf0e10cSrcweir { 672cdf0e10cSrcweir if ( !xModel.is() ) 673cdf0e10cSrcweir return false; 674cdf0e10cSrcweir 675cdf0e10cSrcweir uno::Reference< frame::XController > xController 676cdf0e10cSrcweir = xModel->getCurrentController(); 677cdf0e10cSrcweir if ( xController.is() ) 678cdf0e10cSrcweir { 679cdf0e10cSrcweir uno::Reference< frame::XFrame > xFrame 680cdf0e10cSrcweir = xController->getFrame(); 681cdf0e10cSrcweir if ( xFrame.is() ) 682cdf0e10cSrcweir { 683cdf0e10cSrcweir // don't use XFrame::isTop here. This nowadays excludes 684cdf0e10cSrcweir // "sub documents" such as forms embedded in database documents 685cdf0e10cSrcweir uno::Reference< awt::XTopWindow > xFrameContainer( 686cdf0e10cSrcweir xFrame->getContainerWindow(), uno::UNO_QUERY ); 687cdf0e10cSrcweir if ( !xFrameContainer.is() ) 688cdf0e10cSrcweir return false; 689cdf0e10cSrcweir } 690cdf0e10cSrcweir } 691cdf0e10cSrcweir 692cdf0e10cSrcweir return true; 693cdf0e10cSrcweir } 694cdf0e10cSrcweir 695cdf0e10cSrcweir //========================================================================= 696cdf0e10cSrcweir bool OfficeDocumentsManager::isBasicIDE( 697cdf0e10cSrcweir const uno::Reference< frame::XModel > & xModel ) 698cdf0e10cSrcweir { 699cdf0e10cSrcweir if ( !m_xModuleMgr.is() ) 700cdf0e10cSrcweir { 701cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMtx ); 702cdf0e10cSrcweir if ( !m_xModuleMgr.is() ) 703cdf0e10cSrcweir { 704cdf0e10cSrcweir try 705cdf0e10cSrcweir { 706cdf0e10cSrcweir m_xModuleMgr 707cdf0e10cSrcweir = uno::Reference< 708cdf0e10cSrcweir frame::XModuleManager >( 709cdf0e10cSrcweir m_xSMgr->createInstance( 710cdf0e10cSrcweir rtl::OUString( 711cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM( 712cdf0e10cSrcweir "com.sun.star.frame.ModuleManager" ) ) ), 713cdf0e10cSrcweir uno::UNO_QUERY ); 714cdf0e10cSrcweir } 715cdf0e10cSrcweir catch ( uno::Exception const & ) 716cdf0e10cSrcweir { 717cdf0e10cSrcweir // handled below. 718cdf0e10cSrcweir } 719cdf0e10cSrcweir 720cdf0e10cSrcweir OSL_ENSURE( m_xModuleMgr .is(), 721*5e7dbebbSJohn Bampton "Could not instantiate ModuleManager service!" ); 722cdf0e10cSrcweir } 723cdf0e10cSrcweir } 724cdf0e10cSrcweir 725cdf0e10cSrcweir if ( m_xModuleMgr.is() ) 726cdf0e10cSrcweir { 727cdf0e10cSrcweir rtl::OUString aModule; 728cdf0e10cSrcweir try 729cdf0e10cSrcweir { 730cdf0e10cSrcweir aModule = m_xModuleMgr->identify( xModel ); 731cdf0e10cSrcweir } 732cdf0e10cSrcweir catch ( lang::IllegalArgumentException const & ) 733cdf0e10cSrcweir { 734cdf0e10cSrcweir OSL_ENSURE( false, "Caught IllegalArgumentException!" ); 735cdf0e10cSrcweir } 736cdf0e10cSrcweir catch ( frame::UnknownModuleException const & ) 737cdf0e10cSrcweir { 738cdf0e10cSrcweir OSL_ENSURE( false, "Caught UnknownModuleException!" ); 739cdf0e10cSrcweir } 740cdf0e10cSrcweir 741cdf0e10cSrcweir if ( aModule.getLength() > 0 ) 742cdf0e10cSrcweir { 743cdf0e10cSrcweir // Filter unwanted items, that are no real documents. 744cdf0e10cSrcweir if ( aModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( 745cdf0e10cSrcweir "com.sun.star.script.BasicIDE" ) ) ) 746cdf0e10cSrcweir { 747cdf0e10cSrcweir return true; 748cdf0e10cSrcweir } 749cdf0e10cSrcweir } 750cdf0e10cSrcweir } 751cdf0e10cSrcweir 752cdf0e10cSrcweir return false; 753cdf0e10cSrcweir } 754cdf0e10cSrcweir 755cdf0e10cSrcweir //========================================================================= 756cdf0e10cSrcweir bool OfficeDocumentsManager::isOfficeDocument( 757cdf0e10cSrcweir const uno::Reference< uno::XInterface > & xDoc ) 758cdf0e10cSrcweir { 759cdf0e10cSrcweir uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY ); 760cdf0e10cSrcweir uno::Reference< document::XStorageBasedDocument > 761cdf0e10cSrcweir xStorageBasedDoc( xModel, uno::UNO_QUERY ); 762cdf0e10cSrcweir if ( !xStorageBasedDoc.is() ) 763cdf0e10cSrcweir return false; 764cdf0e10cSrcweir 765cdf0e10cSrcweir if ( !isWithoutOrInTopLevelFrame( xModel ) ) 766cdf0e10cSrcweir return false; 767cdf0e10cSrcweir 768cdf0e10cSrcweir if ( isDocumentPreview( xModel ) ) 769cdf0e10cSrcweir return false; 770cdf0e10cSrcweir 771cdf0e10cSrcweir if ( isHelpDocument( xModel ) ) 772cdf0e10cSrcweir return false; 773cdf0e10cSrcweir 774cdf0e10cSrcweir if ( isBasicIDE( xModel ) ) 775cdf0e10cSrcweir return false; 776cdf0e10cSrcweir 777cdf0e10cSrcweir return true; 778cdf0e10cSrcweir } 779