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