Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <com/sun/star/frame/Desktop.hpp>
21 : #include <com/sun/star/frame/XFrame.hpp>
22 : #include <com/sun/star/frame/XController.hpp>
23 : #include <com/sun/star/frame/XComponentLoader.hpp>
24 : #include <com/sun/star/awt/XTopWindow.hpp>
25 : #include <com/sun/star/embed/XClassifiedObject.hpp>
26 : #include <com/sun/star/io/TempFile.hpp>
27 : #include <com/sun/star/io/XStream.hpp>
28 : #include <com/sun/star/io/XInputStream.hpp>
29 : #include <com/sun/star/io/XOutputStream.hpp>
30 : #include <com/sun/star/io/XSeekable.hpp>
31 : #include <com/sun/star/task/XInteractionHandler.hpp>
32 : #include <com/sun/star/ucb/SimpleFileAccess.hpp>
33 : #include <com/sun/star/util/XCloseable.hpp>
34 : #include <com/sun/star/beans/XPropertySet.hpp>
35 :
36 : #include <com/sun/star/document/XEventBroadcaster.hpp>
37 : #include <com/sun/star/document/XEventListener.hpp>
38 : #include <com/sun/star/document/XTypeDetection.hpp>
39 : #include <com/sun/star/container/XNameAccess.hpp>
40 : #include <cppuhelper/implbase1.hxx>
41 : #include <comphelper/processfactory.hxx>
42 : #include <comphelper/storagehelper.hxx>
43 : #include <comphelper/mimeconfighelper.hxx>
44 :
45 : #include "ownview.hxx"
46 :
47 :
48 : using namespace ::com::sun::star;
49 : using namespace ::comphelper;
50 :
51 : OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw( io::IOException );
52 : OUString GetNewFilledTempFile_Impl( const uno::Reference< io::XInputStream >& xInStream, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw( io::IOException );
53 : sal_Bool KillFile_Impl( const OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory );
54 : uno::Reference< io::XStream > TryToGetAcceptableFormat_Impl( const uno::Reference< io::XStream >& xStream, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw ( uno::Exception );
55 :
56 :
57 : // Dummy interaction handler
58 :
59 :
60 : class DummyHandler_Impl : public ::cppu::WeakImplHelper1< task::XInteractionHandler >
61 : {
62 : public:
63 0 : DummyHandler_Impl() {}
64 : virtual ~DummyHandler_Impl();
65 :
66 : virtual void SAL_CALL handle( const uno::Reference< task::XInteractionRequest >& xRequest )
67 : throw( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
68 : };
69 :
70 :
71 0 : DummyHandler_Impl::~DummyHandler_Impl()
72 : {
73 0 : }
74 :
75 :
76 0 : void SAL_CALL DummyHandler_Impl::handle( const uno::Reference< task::XInteractionRequest >& )
77 : throw( uno::RuntimeException, std::exception )
78 : {
79 0 : return;
80 : }
81 :
82 :
83 : // Object viewer
84 :
85 :
86 0 : OwnView_Impl::OwnView_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory,
87 : const uno::Reference< io::XInputStream >& xInputStream )
88 : : m_xFactory( xFactory )
89 : , m_bBusy( sal_False )
90 0 : , m_bUseNative( sal_False )
91 : {
92 0 : if ( !xFactory.is() || !xInputStream.is() )
93 0 : throw uno::RuntimeException();
94 :
95 0 : m_aTempFileURL = GetNewFilledTempFile_Impl( xInputStream, m_xFactory );
96 0 : }
97 :
98 :
99 0 : OwnView_Impl::~OwnView_Impl()
100 : {
101 : try {
102 0 : KillFile_Impl( m_aTempFileURL, m_xFactory );
103 0 : } catch( uno::Exception& ) {}
104 :
105 : try {
106 0 : if ( !m_aNativeTempURL.isEmpty() )
107 0 : KillFile_Impl( m_aNativeTempURL, m_xFactory );
108 0 : } catch( uno::Exception& ) {}
109 0 : }
110 :
111 :
112 0 : sal_Bool OwnView_Impl::CreateModelFromURL( const OUString& aFileURL )
113 : {
114 0 : sal_Bool bResult = sal_False;
115 :
116 0 : if ( !aFileURL.isEmpty() )
117 : {
118 : try {
119 0 : uno::Reference < frame::XDesktop2 > xDocumentLoader = frame::Desktop::create(comphelper::getComponentContext(m_xFactory));
120 :
121 0 : uno::Sequence< beans::PropertyValue > aArgs( m_aFilterName.isEmpty() ? 4 : 5 );
122 :
123 0 : aArgs[0].Name = "URL";
124 0 : aArgs[0].Value <<= aFileURL;
125 :
126 0 : aArgs[1].Name = "ReadOnly";
127 0 : aArgs[1].Value <<= sal_True;
128 :
129 0 : aArgs[2].Name = "InteractionHandler";
130 0 : aArgs[2].Value <<= uno::Reference< task::XInteractionHandler >(
131 0 : static_cast< ::cppu::OWeakObject* >( new DummyHandler_Impl() ), uno::UNO_QUERY );
132 :
133 0 : aArgs[3].Name = "DontEdit";
134 0 : aArgs[3].Value <<= sal_True;
135 :
136 0 : if ( !m_aFilterName.isEmpty() )
137 : {
138 0 : aArgs[4].Name = "FilterName";
139 0 : aArgs[4].Value <<= m_aFilterName;
140 : }
141 :
142 0 : uno::Reference< frame::XModel > xModel( xDocumentLoader->loadComponentFromURL(
143 : aFileURL,
144 : OUString( "_blank" ),
145 : 0,
146 0 : aArgs ),
147 0 : uno::UNO_QUERY );
148 :
149 0 : if ( xModel.is() )
150 : {
151 0 : uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY );
152 0 : if ( xBroadCaster.is() )
153 0 : xBroadCaster->addEventListener( uno::Reference< document::XEventListener >(
154 : static_cast< ::cppu::OWeakObject* >( this ),
155 0 : uno::UNO_QUERY ) );
156 :
157 0 : uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
158 0 : if ( xCloseable.is() )
159 : {
160 0 : xCloseable->addCloseListener( uno::Reference< util::XCloseListener >(
161 : static_cast< ::cppu::OWeakObject* >( this ),
162 0 : uno::UNO_QUERY ) );
163 :
164 0 : ::osl::MutexGuard aGuard( m_aMutex );
165 0 : m_xModel = xModel;
166 0 : bResult = sal_True;
167 0 : }
168 0 : }
169 : }
170 0 : catch (uno::Exception const& e)
171 : {
172 : SAL_WARN("embeddedobj.ole", "OwnView_Impl::CreateModelFromURL:"
173 : " exception caught: " << e.Message);
174 : }
175 : }
176 :
177 0 : return bResult;
178 : }
179 :
180 :
181 0 : sal_Bool OwnView_Impl::CreateModel( sal_Bool bUseNative )
182 : {
183 0 : sal_Bool bResult = sal_False;
184 :
185 : try {
186 0 : bResult = CreateModelFromURL( bUseNative ? m_aNativeTempURL : m_aTempFileURL );
187 : }
188 0 : catch( uno::Exception& )
189 : {
190 : }
191 :
192 0 : return bResult;
193 : }
194 :
195 :
196 0 : OUString OwnView_Impl::GetFilterNameFromExtentionAndInStream(
197 : const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory,
198 : const OUString& aNameWithExtention,
199 : const uno::Reference< io::XInputStream >& xInputStream )
200 : {
201 0 : if ( !xInputStream.is() )
202 0 : throw uno::RuntimeException();
203 :
204 : uno::Reference< document::XTypeDetection > xTypeDetection(
205 0 : xFactory->createInstance("com.sun.star.document.TypeDetection"),
206 0 : uno::UNO_QUERY_THROW );
207 :
208 0 : OUString aTypeName;
209 :
210 0 : if ( !aNameWithExtention.isEmpty() )
211 : {
212 : OUString aURLToAnalyze =
213 0 : ( OUString( "file:///" ) + aNameWithExtention );
214 0 : aTypeName = xTypeDetection->queryTypeByURL( aURLToAnalyze );
215 : }
216 :
217 0 : uno::Sequence< beans::PropertyValue > aArgs( aTypeName.isEmpty() ? 2 : 3 );
218 0 : aArgs[0].Name = "URL";
219 0 : aArgs[0].Value <<= OUString( "private:stream" );
220 0 : aArgs[1].Name = "InputStream";
221 0 : aArgs[1].Value <<= xInputStream;
222 0 : if ( !aTypeName.isEmpty() )
223 : {
224 0 : aArgs[2].Name = "TypeName";
225 0 : aArgs[2].Value <<= aTypeName;
226 : }
227 :
228 0 : aTypeName = xTypeDetection->queryTypeByDescriptor( aArgs, sal_True );
229 :
230 0 : OUString aFilterName;
231 0 : for ( sal_Int32 nInd = 0; nInd < aArgs.getLength(); nInd++ )
232 0 : if ( aArgs[nInd].Name == "FilterName" )
233 0 : aArgs[nInd].Value >>= aFilterName;
234 :
235 0 : if ( aFilterName.isEmpty() && !aTypeName.isEmpty() )
236 : {
237 : // get the default filter name for the type
238 0 : uno::Reference< container::XNameAccess > xNameAccess( xTypeDetection, uno::UNO_QUERY_THROW );
239 0 : uno::Sequence< beans::PropertyValue > aTypes;
240 :
241 0 : if ( xNameAccess.is() && ( xNameAccess->getByName( aTypeName ) >>= aTypes ) )
242 : {
243 0 : for ( sal_Int32 nInd = 0; nInd < aTypes.getLength(); nInd++ )
244 : {
245 0 : if ( aTypes[nInd].Name == "PreferredFilter" && ( aTypes[nInd].Value >>= aFilterName ) )
246 : {
247 0 : aTypes[nInd].Value >>= aFilterName;
248 0 : break;
249 : }
250 : }
251 0 : }
252 : }
253 :
254 0 : return aFilterName;
255 : }
256 :
257 :
258 0 : sal_Bool OwnView_Impl::ReadContentsAndGenerateTempFile( const uno::Reference< io::XInputStream >& xInStream,
259 : sal_Bool bParseHeader )
260 : {
261 0 : uno::Reference< io::XSeekable > xSeekable( xInStream, uno::UNO_QUERY_THROW );
262 0 : xSeekable->seek( 0 );
263 :
264 : // create m_aNativeTempURL
265 0 : OUString aNativeTempURL;
266 : uno::Reference < beans::XPropertySet > xNativeTempFile(
267 : io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
268 0 : uno::UNO_QUERY_THROW );
269 0 : uno::Reference < io::XStream > xNativeTempStream( xNativeTempFile, uno::UNO_QUERY_THROW );
270 0 : uno::Reference < io::XOutputStream > xNativeOutTemp = xNativeTempStream->getOutputStream();
271 0 : uno::Reference < io::XInputStream > xNativeInTemp = xNativeTempStream->getInputStream();
272 0 : if ( !xNativeOutTemp.is() || !xNativeInTemp.is() )
273 0 : throw uno::RuntimeException();
274 :
275 : try {
276 0 : xNativeTempFile->setPropertyValue("RemoveFile", uno::makeAny( sal_False ) );
277 0 : uno::Any aUrl = xNativeTempFile->getPropertyValue("Uri");
278 0 : aUrl >>= aNativeTempURL;
279 : }
280 0 : catch ( uno::Exception& )
281 : {
282 : }
283 :
284 0 : sal_Bool bFailed = sal_False;
285 0 : OUString aFileSuffix;
286 :
287 0 : if ( bParseHeader )
288 : {
289 0 : uno::Sequence< sal_Int8 > aReadSeq( 4 );
290 : // read the complete size of the Object Package
291 0 : if ( xInStream->readBytes( aReadSeq, 4 ) != 4 )
292 0 : return sal_False;
293 : // read the first header ( have no idea what does this header mean )
294 0 : if ( xInStream->readBytes( aReadSeq, 2 ) != 2 || aReadSeq[0] != 2 || aReadSeq[1] != 0 )
295 0 : return sal_False;
296 :
297 : // read file name
298 : // only extension is interesting so only subset of symbols is accepted
299 0 : do
300 : {
301 0 : if ( xInStream->readBytes( aReadSeq, 1 ) != 1 )
302 0 : return sal_False;
303 :
304 0 : if (
305 0 : (aReadSeq[0] >= '0' && aReadSeq[0] <= '9') ||
306 0 : (aReadSeq[0] >= 'a' && aReadSeq[0] <= 'z') ||
307 0 : (aReadSeq[0] >= 'A' && aReadSeq[0] <= 'Z') ||
308 0 : aReadSeq[0] == '.'
309 : )
310 : {
311 0 : aFileSuffix += OUString( (sal_Unicode) aReadSeq[0] );
312 : }
313 :
314 0 : } while( aReadSeq[0] );
315 :
316 : // skip url
317 0 : do
318 : {
319 0 : if ( xInStream->readBytes( aReadSeq, 1 ) != 1 )
320 0 : return sal_False;
321 0 : } while( aReadSeq[0] );
322 :
323 : // check the next header
324 0 : if ( xInStream->readBytes( aReadSeq, 4 ) != 4
325 0 : || aReadSeq[0] || aReadSeq[1] || aReadSeq[2] != 3 || aReadSeq[3] )
326 0 : return sal_False;
327 :
328 : // get the size of the next entry
329 0 : if ( xInStream->readBytes( aReadSeq, 4 ) != 4 )
330 0 : return sal_False;
331 :
332 0 : sal_uInt32 nUrlSize = (sal_uInt8)aReadSeq[0]
333 0 : + (sal_uInt8)aReadSeq[1] * 0x100
334 0 : + (sal_uInt8)aReadSeq[2] * 0x10000
335 0 : + (sal_uInt8)aReadSeq[3] * 0x1000000;
336 0 : sal_Int64 nTargetPos = xSeekable->getPosition() + nUrlSize;
337 :
338 0 : xSeekable->seek( nTargetPos );
339 :
340 : // get the size of stored data
341 0 : if ( xInStream->readBytes( aReadSeq, 4 ) != 4 )
342 0 : return sal_False;
343 :
344 0 : sal_uInt32 nDataSize = (sal_uInt8)aReadSeq[0]
345 0 : + (sal_uInt8)aReadSeq[1] * 0x100
346 0 : + (sal_uInt8)aReadSeq[2] * 0x10000
347 0 : + (sal_uInt8)aReadSeq[3] * 0x1000000;
348 :
349 0 : aReadSeq.realloc( 32000 );
350 0 : sal_uInt32 nRead = 0;
351 0 : while ( nRead < nDataSize )
352 : {
353 0 : sal_uInt32 nToRead = ( nDataSize - nRead > 32000 ) ? 32000 : nDataSize - nRead;
354 0 : sal_uInt32 nLocalRead = xInStream->readBytes( aReadSeq, nToRead );
355 :
356 :
357 0 : if ( !nLocalRead )
358 : {
359 0 : bFailed = sal_True;
360 0 : break;
361 : }
362 0 : else if ( nLocalRead == 32000 )
363 0 : xNativeOutTemp->writeBytes( aReadSeq );
364 : else
365 : {
366 0 : uno::Sequence< sal_Int8 > aToWrite( aReadSeq );
367 0 : aToWrite.realloc( nLocalRead );
368 0 : xNativeOutTemp->writeBytes( aToWrite );
369 : }
370 :
371 0 : nRead += nLocalRead;
372 0 : }
373 : }
374 : else
375 : {
376 0 : uno::Sequence< sal_Int8 > aData( 8 );
377 0 : if ( xInStream->readBytes( aData, 8 ) == 8
378 0 : && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1
379 0 : && ( aData[4] == 2 || aData[4] == 3 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 )
380 : {
381 : // the header has to be removed
382 0 : xSeekable->seek( 40 );
383 : }
384 : else
385 : {
386 : // the usual Ole10Native format
387 0 : xSeekable->seek( 4 );
388 : }
389 :
390 0 : ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xNativeOutTemp );
391 : }
392 :
393 0 : xNativeOutTemp->closeOutput();
394 :
395 : // The temporary native file is created, now the filter must be detected
396 0 : if ( !bFailed )
397 : {
398 0 : m_aFilterName = GetFilterNameFromExtentionAndInStream( m_xFactory, aFileSuffix, xNativeInTemp );
399 0 : m_aNativeTempURL = aNativeTempURL;
400 : }
401 :
402 0 : return !bFailed;
403 : }
404 :
405 :
406 0 : void OwnView_Impl::CreateNative()
407 : {
408 0 : if ( !m_aNativeTempURL.isEmpty() )
409 0 : return;
410 :
411 : try
412 : {
413 : uno::Reference < ucb::XSimpleFileAccess3 > xAccess(
414 0 : ucb::SimpleFileAccess::create( comphelper::getComponentContext(m_xFactory) ) );
415 :
416 0 : uno::Reference< io::XInputStream > xInStream = xAccess->openFileRead( m_aTempFileURL );
417 0 : if ( !xInStream.is() )
418 0 : throw uno::RuntimeException();
419 :
420 0 : uno::Sequence< uno::Any > aArgs( 1 );
421 0 : aArgs[0] <<= xInStream;
422 : uno::Reference< container::XNameAccess > xNameAccess(
423 0 : m_xFactory->createInstanceWithArguments(
424 : OUString( "com.sun.star.embed.OLESimpleStorage" ),
425 0 : aArgs ),
426 0 : uno::UNO_QUERY_THROW );
427 :
428 0 : OUString aSubStreamName = "\1Ole10Native";
429 0 : uno::Reference< embed::XClassifiedObject > xStor( xNameAccess, uno::UNO_QUERY_THROW );
430 0 : uno::Sequence< sal_Int8 > aStorClassID = xStor->getClassID();
431 :
432 0 : if ( xNameAccess->hasByName( aSubStreamName ) )
433 : {
434 : sal_uInt8 aClassID[] =
435 0 : { 0x00, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
436 0 : uno::Sequence< sal_Int8 > aPackageClassID( (sal_Int8*)aClassID, 16 );
437 :
438 0 : uno::Reference< io::XStream > xSubStream;
439 0 : xNameAccess->getByName( aSubStreamName ) >>= xSubStream;
440 0 : if ( xSubStream.is() )
441 : {
442 0 : sal_Bool bOk = sal_False;
443 :
444 0 : if ( MimeConfigurationHelper::ClassIDsEqual( aPackageClassID, aStorClassID ) )
445 : {
446 : // the storage represents Object Package
447 :
448 0 : bOk = ReadContentsAndGenerateTempFile( xSubStream->getInputStream(), sal_True );
449 :
450 0 : if ( !bOk && !m_aNativeTempURL.isEmpty() )
451 : {
452 0 : KillFile_Impl( m_aNativeTempURL, m_xFactory );
453 0 : m_aNativeTempURL = OUString();
454 : }
455 : }
456 :
457 0 : if ( !bOk )
458 : {
459 0 : bOk = ReadContentsAndGenerateTempFile( xSubStream->getInputStream(), sal_False );
460 :
461 0 : if ( !bOk && !m_aNativeTempURL.isEmpty() )
462 : {
463 0 : KillFile_Impl( m_aNativeTempURL, m_xFactory );
464 0 : m_aNativeTempURL = OUString();
465 : }
466 : }
467 0 : }
468 : }
469 : else
470 : {
471 : // TODO/LATER: No native stream, needs a new solution
472 0 : }
473 : }
474 0 : catch( uno::Exception& )
475 : {}
476 : }
477 :
478 :
479 0 : sal_Bool OwnView_Impl::Open()
480 : {
481 0 : sal_Bool bResult = sal_False;
482 :
483 0 : uno::Reference< frame::XModel > xExistingModel;
484 :
485 : {
486 0 : ::osl::MutexGuard aGuard( m_aMutex );
487 0 : xExistingModel = m_xModel;
488 0 : if ( m_bBusy )
489 0 : return sal_False;
490 :
491 0 : m_bBusy = sal_True;
492 : }
493 :
494 0 : if ( xExistingModel.is() )
495 : {
496 : try {
497 0 : uno::Reference< frame::XController > xController = xExistingModel->getCurrentController();
498 0 : if ( xController.is() )
499 : {
500 0 : uno::Reference< frame::XFrame > xFrame = xController->getFrame();
501 0 : if ( xFrame.is() )
502 : {
503 0 : xFrame->activate();
504 0 : uno::Reference<awt::XTopWindow> xTopWindow( xFrame->getContainerWindow(), uno::UNO_QUERY );
505 0 : if(xTopWindow.is())
506 0 : xTopWindow->toFront();
507 :
508 0 : bResult = sal_True;
509 0 : }
510 0 : }
511 : }
512 0 : catch( uno::Exception& )
513 : {
514 : }
515 : }
516 : else
517 : {
518 0 : bResult = CreateModel( m_bUseNative );
519 :
520 0 : if ( !bResult && !m_bUseNative )
521 : {
522 : // the original storage can not be recognized
523 0 : if ( m_aNativeTempURL.isEmpty() )
524 : {
525 : // create a temporary file for the native representation if there is no
526 0 : CreateNative();
527 : }
528 :
529 0 : if ( !m_aNativeTempURL.isEmpty() )
530 : {
531 0 : bResult = CreateModel( sal_True );
532 0 : if ( bResult )
533 0 : m_bUseNative = sal_True;
534 : }
535 : }
536 : }
537 :
538 0 : m_bBusy = sal_False;
539 :
540 0 : return bResult;
541 : }
542 :
543 :
544 0 : void OwnView_Impl::Close()
545 : {
546 0 : uno::Reference< frame::XModel > xModel;
547 :
548 : {
549 0 : ::osl::MutexGuard aGuard( m_aMutex );
550 0 : if ( !m_xModel.is() )
551 0 : return;
552 0 : xModel = m_xModel;
553 0 : m_xModel = uno::Reference< frame::XModel >();
554 :
555 0 : if ( m_bBusy )
556 0 : return;
557 :
558 0 : m_bBusy = sal_True;
559 : }
560 :
561 : try {
562 0 : uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY );
563 0 : if ( xBroadCaster.is() )
564 0 : xBroadCaster->removeEventListener( uno::Reference< document::XEventListener >(
565 : static_cast< ::cppu::OWeakObject* >( this ),
566 0 : uno::UNO_QUERY ) );
567 :
568 0 : uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
569 0 : if ( xCloseable.is() )
570 : {
571 0 : xCloseable->removeCloseListener( uno::Reference< util::XCloseListener >(
572 : static_cast< ::cppu::OWeakObject* >( this ),
573 0 : uno::UNO_QUERY ) );
574 0 : xCloseable->close( sal_True );
575 0 : }
576 : }
577 0 : catch( uno::Exception& )
578 : {}
579 :
580 0 : m_bBusy = sal_False;
581 : }
582 :
583 :
584 0 : void SAL_CALL OwnView_Impl::notifyEvent( const document::EventObject& aEvent )
585 : throw ( uno::RuntimeException, std::exception )
586 : {
587 :
588 0 : uno::Reference< frame::XModel > xModel;
589 :
590 : {
591 0 : ::osl::MutexGuard aGuard( m_aMutex );
592 0 : if ( aEvent.Source == m_xModel && aEvent.EventName == "OnSaveAsDone" )
593 : {
594 : // SaveAs operation took place, so just forget the model and deregister listeners
595 0 : xModel = m_xModel;
596 0 : m_xModel = uno::Reference< frame::XModel >();
597 0 : }
598 : }
599 :
600 0 : if ( xModel.is() )
601 : {
602 : try {
603 0 : uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY );
604 0 : if ( xBroadCaster.is() )
605 0 : xBroadCaster->removeEventListener( uno::Reference< document::XEventListener >(
606 : static_cast< ::cppu::OWeakObject* >( this ),
607 0 : uno::UNO_QUERY ) );
608 :
609 0 : uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
610 0 : if ( xCloseable.is() )
611 0 : xCloseable->removeCloseListener( uno::Reference< util::XCloseListener >(
612 : static_cast< ::cppu::OWeakObject* >( this ),
613 0 : uno::UNO_QUERY ) );
614 : }
615 0 : catch( uno::Exception& )
616 : {}
617 0 : }
618 0 : }
619 :
620 :
621 0 : void SAL_CALL OwnView_Impl::queryClosing( const lang::EventObject&, sal_Bool )
622 : throw ( util::CloseVetoException,
623 : uno::RuntimeException, std::exception )
624 : {
625 0 : }
626 :
627 :
628 0 : void SAL_CALL OwnView_Impl::notifyClosing( const lang::EventObject& Source )
629 : throw ( uno::RuntimeException, std::exception )
630 : {
631 0 : ::osl::MutexGuard aGuard( m_aMutex );
632 0 : if ( Source.Source == m_xModel )
633 0 : m_xModel = uno::Reference< frame::XModel >();
634 0 : }
635 :
636 :
637 0 : void SAL_CALL OwnView_Impl::disposing( const lang::EventObject& Source )
638 : throw (uno::RuntimeException, std::exception)
639 : {
640 0 : ::osl::MutexGuard aGuard( m_aMutex );
641 0 : if ( Source.Source == m_xModel )
642 0 : m_xModel = uno::Reference< frame::XModel >();
643 0 : };
644 :
645 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|