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