1. mst
  2. ooo340

Commits

kso  committed c84b140

#163732# - Defer removal of documents until XCloseListener::notifyClosing.

  • Participants
  • Parent commits 06bbd30
  • Branches default

Comments (0)

Files changed (2)

File ucb/source/ucp/tdoc/tdoc_docmgr.cxx

View file
 /*************************************************************************
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- * 
+ *
  * Copyright 2000, 2010 Oracle and/or its affiliates.
  *
  * OpenOffice.org - a multi-platform office productivity suite
 
 // MARKER(update_precomp.py): autogen include statement, do not remove
 #include "precompiled_ucb.hxx"
+
 /**************************************************************************
-								TODO
+                                TODO
  **************************************************************************
 
- - filter unwanted models notified by global document event broadcaster
-   - help documents
-   - others, which I don't know yet
-
  *************************************************************************/
 
 #include "osl/diagnose.h"
 #include "comphelper/namedvaluecollection.hxx"
 #include "comphelper/documentinfo.hxx"
 
+#include "com/sun/star/awt/XTopWindow.hpp"
 #include "com/sun/star/beans/XPropertySet.hpp"
 #include "com/sun/star/container/XEnumerationAccess.hpp"
+#include "com/sun/star/document/XStorageBasedDocument.hpp"
 #include "com/sun/star/frame/XStorable.hpp"
 #include "com/sun/star/lang/DisposedException.hpp"
-#include "com/sun/star/document/XStorageBasedDocument.hpp"
-#include "com/sun/star/awt/XTopWindow.hpp"
+#include "com/sun/star/util/XCloseBroadcaster.hpp"
 
 #include "tdoc_docmgr.hxx"
 
 //=========================================================================
 //=========================================================================
 //
+// OfficeDocumentsCloseListener Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+//=========================================================================
+//
+// util::XCloseListener
+//
+//=========================================================================
+
+// virtual
+void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::queryClosing(
+         const lang::EventObject& Source, sal_Bool GetsOwnership )
+    throw ( util::CloseVetoException,
+            uno::RuntimeException )
+{
+}
+
+//=========================================================================
+void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::notifyClosing(
+         const lang::EventObject& Source )
+    throw ( uno::RuntimeException )
+{
+    document::EventObject aDocEvent;
+    aDocEvent.Source = Source.Source;
+    aDocEvent.EventName = rtl::OUString(
+        RTL_CONSTASCII_USTRINGPARAM( "OfficeDocumentsListener::notifyClosing" ) );
+    m_pManager->notifyEvent( aDocEvent );
+}
+
+//=========================================================================
+//
+// lang::XEventListener (base of util::XCloseListener)
+//
+//=========================================================================
+
+// virtual
+void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::disposing(
+        const lang::EventObject& /*Source*/ )
+    throw ( uno::RuntimeException )
+{
+}
+
+//=========================================================================
+//=========================================================================
+//
 // OfficeDocumentsManager Implementation.
 //
 //=========================================================================
             OfficeDocumentsEventListener * pDocEventListener )
 : m_xSMgr( xSMgr ),
   m_xDocEvtNotifier( createDocumentEventNotifier( xSMgr ) ),
-  m_pDocEventListener( pDocEventListener )
+  m_pDocEventListener( pDocEventListener ),
+  m_xDocCloseListener( new OfficeDocumentsCloseListener( this ) )
 {
     if ( m_xDocEvtNotifier.is() )
     {
                 OSL_ENSURE( xStorage.is(), "Got no document storage!" );
 
                 rtl:: OUString aDocId = getDocumentId( Event.Source );
-                rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
+                rtl:: OUString aTitle = DocumentInfo::getDocumentTitle(
+                    uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
 
                 m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel );
 
+                uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
+                    Event.Source, uno::UNO_QUERY );
+                OSL_ENSURE( xCloseBroadcaster.is(),
+                    "OnLoadFinished/OnCreate event: got no close broadcaster!" );
+
+                if ( xCloseBroadcaster.is() )
+                    xCloseBroadcaster->addCloseListener( m_xDocCloseListener );
+
                 // Propagate document closure.
                 OSL_ENSURE( m_pDocEventListener,
                     "OnLoadFinished/OnCreate event: no owner for insert event propagation!" );
         }
     }
     else if ( Event.EventName.equalsAsciiL(
-                RTL_CONSTASCII_STRINGPARAM( "OnUnload" ) ) )
+                RTL_CONSTASCII_STRINGPARAM( "OfficeDocumentsListener::notifyClosing" ) ) )
     {
         if ( isOfficeDocument( Event.Source ) )
         {
             // Document has been closed (unloaded)
 
+            // #163732# - Official event "OnUnload" does not work here. Event
+            // gets fired to early. Other OnUnload listeners called after this
+            // listener may still need TDOC access to the document. Remove the
+            // document from TDOC docs list on XCloseListener::notifyClosing.
+            // See OfficeDocumentsManager::OfficeDocumentsListener::notifyClosing.
+
             osl::MutexGuard aGuard( m_aMtx );
 
             uno::Reference< frame::XModel >
                         rtl::OUString aDocId( (*it).first );
                         m_pDocEventListener->notifyDocumentClosed( aDocId );
                     }
-
-
                     break;
                 }
                 ++it;
             OSL_ENSURE( it != m_aDocs.end(),
                         "OnUnload event notified for unknown document!" );
 
-            if( it != m_aDocs.end() )
+            if ( it != m_aDocs.end() )
+            {
+                uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
+                    Event.Source, uno::UNO_QUERY );
+                OSL_ENSURE( xCloseBroadcaster.is(),
+                    "OnUnload event: got no XCloseBroadcaster from XModel" );
+
+                if ( xCloseBroadcaster.is() )
+                    xCloseBroadcaster->removeCloseListener( m_xDocCloseListener );
+
                 m_aDocs.erase( it );
+            }
         }
     }
     else if ( Event.EventName.equalsAsciiL(
                     (*it).second.xStorage = xStorage;
 
                     // Adjust title.
-                    (*it).second.aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
+                    (*it).second.aTitle = DocumentInfo::getDocumentTitle( xModel );
                     break;
                 }
                 ++it;
                 if ( (*it).second.xModel == xModel )
                 {
                     // Adjust title.
-                    rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
+                    rtl:: OUString aTitle = DocumentInfo::getDocumentTitle( xModel );
                     (*it).second.aTitle = aTitle;
 
                     // Adjust storage.

File ucb/source/ucp/tdoc/tdoc_docmgr.hxx

View file
 /*************************************************************************
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- * 
+ *
  * Copyright 2000, 2010 Oracle and/or its affiliates.
  *
  * OpenOffice.org - a multi-platform office productivity suite
 #include "com/sun/star/embed/XStorage.hpp"
 #include "com/sun/star/frame/XModel.hpp"
 #include "com/sun/star/frame/XModuleManager.hpp"
+#include "com/sun/star/util/XCloseListener.hpp"
 
 namespace tdoc_ucp {
 
     class OfficeDocumentsManager :
         public cppu::WeakImplHelper1< com::sun::star::document::XEventListener >
     {
+        class OfficeDocumentsCloseListener :
+           public cppu::WeakImplHelper1< com::sun::star::util::XCloseListener >
+
+        {
+        public:
+            OfficeDocumentsCloseListener( OfficeDocumentsManager * pMgr )
+            : m_pManager( pMgr ) {};
+
+            // util::XCloseListener
+            virtual void SAL_CALL queryClosing(
+                    const ::com::sun::star::lang::EventObject& Source,
+                    ::sal_Bool GetsOwnership )
+                throw (::com::sun::star::util::CloseVetoException,
+                       ::com::sun::star::uno::RuntimeException);
+
+            virtual void SAL_CALL notifyClosing(
+                    const ::com::sun::star::lang::EventObject& Source )
+                throw (::com::sun::star::uno::RuntimeException);
+
+            // lang::XEventListener (base of util::XCloseListener)
+            virtual void SAL_CALL disposing(
+                    const com::sun::star::lang::EventObject & Source )
+                throw ( com::sun::star::uno::RuntimeException );
+        private:
+            OfficeDocumentsManager * m_pManager;
+        };
+
     public:
         OfficeDocumentsManager(
             const com::sun::star::uno::Reference<
         createDocumentEventNotifier(
             const com::sun::star::uno::Reference<
                 com::sun::star::lang::XMultiServiceFactory >& rXSMgr );
+
         void buildDocumentsList();
+
         bool
         isOfficeDocument(
             const com::sun::star::uno::Reference<
         com::sun::star::uno::Reference<
             com::sun::star::document::XEventBroadcaster >   m_xDocEvtNotifier;
         com::sun::star::uno::Reference<
-            com::sun::star::frame::XModuleManager > m_xModuleMgr;
+            com::sun::star::frame::XModuleManager >         m_xModuleMgr;
         DocumentList                                        m_aDocs;
         OfficeDocumentsEventListener *                      m_pDocEventListener;
+        com::sun::star::uno::Reference<
+            com::sun::star::util::XCloseListener >          m_xDocCloseListener;
     };
 
 } // namespace tdoc_ucp