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