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
queryClosing(const lang::EventObject &,sal_Bool)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 //=========================================================================
notifyClosing(const lang::EventObject & Source)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
disposing(const lang::EventObject &)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
OfficeDocumentsManager(const uno::Reference<lang::XMultiServiceFactory> & xSMgr,OfficeDocumentsEventListener * pDocEventListener)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
~OfficeDocumentsManager()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 //=========================================================================
destroy()137cdf0e10cSrcweir void OfficeDocumentsManager::destroy()
138cdf0e10cSrcweir {
139cdf0e10cSrcweir if ( m_xDocEvtNotifier.is() )
140cdf0e10cSrcweir m_xDocEvtNotifier->removeEventListener( this );
141cdf0e10cSrcweir }
142cdf0e10cSrcweir
143cdf0e10cSrcweir //=========================================================================
144cdf0e10cSrcweir static rtl::OUString
getDocumentId(const uno::Reference<uno::XInterface> & xDoc)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
notifyEvent(const document::EventObject & Event)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
disposing(const lang::EventObject &)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 >
createDocumentEventNotifier(const uno::Reference<lang::XMultiServiceFactory> & rXSMgr)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 //=========================================================================
buildDocumentsList()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 >
queryStorage(const rtl::OUString & rDocId)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 //=========================================================================
queryDocumentId(const uno::Reference<frame::XModel> & xModel)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 >
queryDocumentModel(const rtl::OUString & rDocId)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 //=========================================================================
queryDocuments()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
queryStorageTitle(const rtl::OUString & rDocId)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 //=========================================================================
isDocumentPreview(const uno::Reference<frame::XModel> & xModel)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 //=========================================================================
isHelpDocument(const uno::Reference<frame::XModel> & xModel)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 //=========================================================================
isWithoutOrInTopLevelFrame(const uno::Reference<frame::XModel> & xModel)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 //=========================================================================
isBasicIDE(const uno::Reference<frame::XModel> & xModel)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 //=========================================================================
isOfficeDocument(const uno::Reference<uno::XInterface> & xDoc)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