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 "ChartModel.hxx"
21 : #include "MediaDescriptorHelper.hxx"
22 : #include "macros.hxx"
23 : #include "ChartViewHelper.hxx"
24 : #include "ChartModelHelper.hxx"
25 : #include "AxisHelper.hxx"
26 : #include "ThreeDHelper.hxx"
27 :
28 : #include <com/sun/star/chart2/LegendPosition.hpp>
29 : #include <com/sun/star/container/XNameAccess.hpp>
30 : #include <com/sun/star/document/XExporter.hpp>
31 : #include <com/sun/star/document/XImporter.hpp>
32 : #include <com/sun/star/document/XFilter.hpp>
33 : #include <com/sun/star/drawing/FillStyle.hpp>
34 : #include <com/sun/star/drawing/LineStyle.hpp>
35 : #include <com/sun/star/drawing/ProjectionMode.hpp>
36 : #include <com/sun/star/embed/ElementModes.hpp>
37 : #include <com/sun/star/embed/XStorage.hpp>
38 : #include <com/sun/star/embed/StorageFactory.hpp>
39 : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
40 : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
41 : #include <com/sun/star/uno/XComponentContext.hpp>
42 : #include <com/sun/star/io/TempFile.hpp>
43 : #include <com/sun/star/io/XSeekable.hpp>
44 : #include <com/sun/star/ucb/CommandFailedException.hpp>
45 :
46 : #include <ucbhelper/content.hxx>
47 : #include <unotools/ucbstreamhelper.hxx>
48 : #include <vcl/cvtgrf.hxx>
49 : #include <comphelper/processfactory.hxx>
50 : #include <comphelper/storagehelper.hxx>
51 : #include <vcl/svapp.hxx>
52 : #include <vcl/settings.hxx>
53 :
54 : #include <algorithm>
55 : #include <functional>
56 :
57 : using namespace ::com::sun::star;
58 :
59 : using ::com::sun::star::uno::Reference;
60 : using ::com::sun::star::uno::Sequence;
61 : using ::osl::MutexGuard;
62 :
63 : namespace
64 : {
65 14148 : struct lcl_PropNameEquals : public ::std::unary_function< beans::PropertyValue, bool >
66 : {
67 1572 : lcl_PropNameEquals( const OUString & rStrToCompareWith ) :
68 1572 : m_aStr( rStrToCompareWith )
69 1572 : {}
70 3174 : bool operator() ( const beans::PropertyValue & rProp )
71 : {
72 3174 : return rProp.Name.equals( m_aStr );
73 : }
74 : private:
75 : OUString m_aStr;
76 : };
77 :
78 : template< typename T >
79 1572 : T lcl_getProperty(
80 : const Sequence< beans::PropertyValue > & rMediaDescriptor,
81 : const OUString & rPropName )
82 : {
83 1572 : T aResult;
84 1572 : if( rMediaDescriptor.getLength())
85 : {
86 1572 : OUString aPropName( rPropName );
87 1572 : const beans::PropertyValue * pIt = rMediaDescriptor.getConstArray();
88 1572 : const beans::PropertyValue * pEndIt = pIt + + rMediaDescriptor.getLength();
89 1572 : pIt = ::std::find_if( pIt, pEndIt, lcl_PropNameEquals( aPropName ));
90 1572 : if( pIt != pEndIt )
91 1572 : (*pIt).Value >>= aResult;
92 : }
93 1572 : return aResult;
94 : }
95 :
96 786 : void lcl_addStorageToMediaDescriptor(
97 : Sequence< beans::PropertyValue > & rOutMD,
98 : const Reference< embed::XStorage > & xStorage )
99 : {
100 786 : rOutMD.realloc( rOutMD.getLength() + 1 );
101 1572 : rOutMD[rOutMD.getLength() - 1] = beans::PropertyValue(
102 786 : "Storage", -1, uno::makeAny( xStorage ), beans::PropertyState_DIRECT_VALUE );
103 786 : }
104 :
105 0 : Reference< embed::XStorage > lcl_createStorage(
106 : const OUString & rURL,
107 : const Reference< uno::XComponentContext > & xContext,
108 : const Sequence< beans::PropertyValue > & rMediaDescriptor )
109 : {
110 : // create new storage
111 0 : Reference< embed::XStorage > xStorage;
112 0 : if( !xContext.is())
113 0 : return xStorage;
114 :
115 : try
116 : {
117 : Reference< io::XStream > xStream(
118 : ::ucbhelper::Content( rURL, Reference< ::com::sun::star::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext()).openStream(),
119 0 : uno::UNO_QUERY );
120 :
121 0 : Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create( xContext ) );
122 0 : Sequence< uno::Any > aStorageArgs( 3 );
123 0 : aStorageArgs[0] <<= xStream;
124 0 : aStorageArgs[1] <<= embed::ElementModes::READWRITE;
125 0 : aStorageArgs[2] <<= rMediaDescriptor;
126 : xStorage.set(
127 0 : xStorageFact->createInstanceWithArguments( aStorageArgs ), uno::UNO_QUERY_THROW );
128 0 : OSL_ENSURE( xStorage.is(), "No Storage" );
129 : }
130 0 : catch(const css::ucb::ContentCreationException& rEx)
131 : {
132 : ASSERT_EXCEPTION( rEx );
133 : }
134 0 : catch(const css::ucb::CommandFailedException& rEx)
135 : {
136 : ASSERT_EXCEPTION( rEx );
137 : }
138 :
139 0 : return xStorage;
140 : }
141 :
142 : } // anonymous namespace
143 :
144 : namespace chart
145 : {
146 :
147 786 : Reference< document::XFilter > ChartModel::impl_createFilter(
148 : const Sequence< beans::PropertyValue > & rMediaDescriptor )
149 : {
150 786 : Reference< document::XFilter > xFilter;
151 :
152 : // find FilterName in MediaDescriptor
153 : OUString aFilterName(
154 1572 : lcl_getProperty< OUString >( rMediaDescriptor, "FilterName" ) );
155 :
156 : // if FilterName was found, get Filter from factory
157 786 : if( !aFilterName.isEmpty() )
158 : {
159 : try
160 : {
161 : Reference< container::XNameAccess > xFilterFact(
162 1572 : m_xContext->getServiceManager()->createInstanceWithContext(
163 786 : "com.sun.star.document.FilterFactory", m_xContext ),
164 786 : uno::UNO_QUERY_THROW );
165 1572 : uno::Any aFilterProps( xFilterFact->getByName( aFilterName ));
166 1572 : Sequence< beans::PropertyValue > aProps;
167 :
168 1572 : if( aFilterProps.hasValue() &&
169 786 : (aFilterProps >>= aProps))
170 : {
171 : OUString aFilterServiceName(
172 786 : lcl_getProperty< OUString >( aProps, "FilterService" ) );
173 :
174 786 : if( !aFilterServiceName.isEmpty())
175 : {
176 : xFilter.set(
177 1572 : m_xContext->getServiceManager()->createInstanceWithContext(
178 786 : aFilterServiceName, m_xContext ), uno::UNO_QUERY_THROW );
179 : SAL_INFO("chart2", "Filter found for service " << aFilterServiceName );
180 786 : }
181 786 : }
182 : }
183 0 : catch( const uno::Exception & ex )
184 : {
185 : ASSERT_EXCEPTION( ex );
186 : }
187 : OSL_ENSURE( xFilter.is(), "Filter not found via factory" );
188 : }
189 :
190 : // fall-back: create XML-Filter
191 786 : if( ! xFilter.is())
192 : {
193 : OSL_TRACE( "No FilterName passed in MediaDescriptor" );
194 : xFilter.set(
195 0 : m_xContext->getServiceManager()->createInstanceWithContext(
196 0 : "com.sun.star.comp.chart2.XMLFilter", m_xContext ),
197 0 : uno::UNO_QUERY_THROW );
198 : }
199 :
200 1572 : return xFilter;
201 : }
202 :
203 : // frame::XStorable2
204 :
205 0 : void SAL_CALL ChartModel::storeSelf( const Sequence< beans::PropertyValue >& rMediaDescriptor )
206 : throw (lang::IllegalArgumentException,
207 : io::IOException,
208 : uno::RuntimeException, std::exception)
209 : {
210 : // only some parameters are allowed (see also SfxBaseModel)
211 : // "VersionComment", "Author", "InteractionHandler", "StatusIndicator"
212 : // However, they are ignored here. They would become interesting when
213 : // charts support a standalone format again.
214 0 : impl_store( rMediaDescriptor, m_xStorage );
215 0 : }
216 :
217 : // frame::XStorable (base of XStorable2)
218 0 : sal_Bool SAL_CALL ChartModel::hasLocation()
219 : throw(uno::RuntimeException, std::exception)
220 : {
221 : //@todo guard
222 0 : return !m_aResource.isEmpty();
223 : }
224 :
225 0 : OUString SAL_CALL ChartModel::getLocation()
226 : throw(uno::RuntimeException, std::exception)
227 : {
228 0 : return impl_g_getLocation();
229 : }
230 :
231 1637 : sal_Bool SAL_CALL ChartModel::isReadonly()
232 : throw(uno::RuntimeException, std::exception)
233 : {
234 : //@todo guard
235 1637 : return m_bReadOnly;
236 : }
237 :
238 0 : void SAL_CALL ChartModel::store()
239 : throw(io::IOException,
240 : uno::RuntimeException, std::exception)
241 : {
242 0 : apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager);
243 0 : if(!aGuard.startApiCall(true)) //start LongLastingCall
244 0 : return; //behave passive if already disposed or closed or throw exception @todo?
245 :
246 0 : OUString aLocation = m_aResource;
247 :
248 0 : if( aLocation.isEmpty() )
249 0 : throw io::IOException( "no location specified", static_cast< ::cppu::OWeakObject* >(this));
250 : //@todo check whether aLocation is something like private:factory...
251 0 : if( m_bReadOnly )
252 0 : throw io::IOException( "document is read only", static_cast< ::cppu::OWeakObject* >(this));
253 :
254 0 : aGuard.clear();
255 :
256 : // store
257 0 : impl_store( m_aMediaDescriptor, m_xStorage );
258 : }
259 :
260 0 : void SAL_CALL ChartModel::storeAsURL(
261 : const OUString& rURL,
262 : const uno::Sequence< beans::PropertyValue >& rMediaDescriptor )
263 : throw(io::IOException, uno::RuntimeException, std::exception)
264 : {
265 0 : apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager);
266 0 : if(!aGuard.startApiCall(true)) //start LongLastingCall
267 0 : return; //behave passive if already disposed or closed or throw exception @todo?
268 :
269 0 : apphelper::MediaDescriptorHelper aMediaDescriptorHelper(rMediaDescriptor);
270 : uno::Sequence< beans::PropertyValue > aReducedMediaDescriptor(
271 0 : aMediaDescriptorHelper.getReducedForModel() );
272 :
273 0 : m_bReadOnly = false;
274 0 : aGuard.clear();
275 :
276 : // create new storage
277 0 : Reference< embed::XStorage > xStorage( lcl_createStorage( rURL, m_xContext, aReducedMediaDescriptor ));
278 :
279 0 : if( xStorage.is())
280 : {
281 0 : impl_store( aReducedMediaDescriptor, xStorage );
282 0 : attachResource( rURL, aReducedMediaDescriptor );
283 0 : }
284 : }
285 :
286 0 : void SAL_CALL ChartModel::storeToURL(
287 : const OUString& rURL,
288 : const uno::Sequence< beans::PropertyValue >& rMediaDescriptor )
289 : throw(io::IOException,
290 : uno::RuntimeException, std::exception)
291 : {
292 0 : apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager);
293 0 : if(!aGuard.startApiCall(true)) //start LongLastingCall
294 0 : return; //behave passive if already disposed or closed or throw exception @todo?
295 : //do not change the internal state of the document here
296 :
297 0 : aGuard.clear();
298 :
299 0 : apphelper::MediaDescriptorHelper aMediaDescriptorHelper(rMediaDescriptor);
300 : uno::Sequence< beans::PropertyValue > aReducedMediaDescriptor(
301 0 : aMediaDescriptorHelper.getReducedForModel() );
302 :
303 0 : if ( rURL == "private:stream" )
304 : {
305 : try
306 : {
307 0 : if( m_xContext.is() && aMediaDescriptorHelper.ISSET_OutputStream )
308 : {
309 : Reference< io::XStream > xStream(
310 0 : io::TempFile::create(m_xContext), uno::UNO_QUERY_THROW );
311 0 : Reference< io::XInputStream > xInputStream( xStream->getInputStream());
312 :
313 : Reference< embed::XStorage > xStorage(
314 0 : ::comphelper::OStorageHelper::GetStorageFromStream( xStream, embed::ElementModes::READWRITE, m_xContext ));
315 0 : if( xStorage.is())
316 : {
317 0 : impl_store( aReducedMediaDescriptor, xStorage );
318 :
319 0 : Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY_THROW );
320 0 : xSeekable->seek( 0 );
321 0 : ::comphelper::OStorageHelper::CopyInputToOutput( xInputStream, aMediaDescriptorHelper.OutputStream );
322 0 : }
323 : }
324 : }
325 0 : catch( const uno::Exception & ex )
326 : {
327 : ASSERT_EXCEPTION( ex );
328 : }
329 : }
330 : else
331 : {
332 : // create new storage
333 0 : Reference< embed::XStorage > xStorage( lcl_createStorage( rURL, m_xContext, aReducedMediaDescriptor ));
334 :
335 0 : if( xStorage.is())
336 0 : impl_store( aReducedMediaDescriptor, xStorage );
337 0 : }
338 : }
339 :
340 544 : void ChartModel::impl_store(
341 : const Sequence< beans::PropertyValue >& rMediaDescriptor,
342 : const Reference< embed::XStorage > & xStorage )
343 : {
344 544 : Reference< document::XFilter > xFilter( impl_createFilter( rMediaDescriptor));
345 544 : if( xFilter.is() && xStorage.is())
346 : {
347 544 : Sequence< beans::PropertyValue > aMD( rMediaDescriptor );
348 544 : lcl_addStorageToMediaDescriptor( aMD, xStorage );
349 : try
350 : {
351 544 : Reference< document::XExporter > xExporter( xFilter, uno::UNO_QUERY_THROW );
352 544 : xExporter->setSourceDocument( Reference< lang::XComponent >( this ));
353 544 : xFilter->filter( aMD );
354 : }
355 0 : catch( const uno::Exception & ex )
356 : {
357 : ASSERT_EXCEPTION( ex );
358 544 : }
359 : }
360 : else
361 : {
362 : OSL_FAIL( "No filter" );
363 : }
364 :
365 544 : setModified( sal_False );
366 :
367 : //#i66865#
368 : //for data change notification during chart is not loaded:
369 : //notify parent data provider after saving thus the parent document can store
370 : //the ranges for which a load and update of the chart will be necessary
371 1088 : Reference< beans::XPropertySet > xPropSet( m_xParent, uno::UNO_QUERY );
372 544 : if ( !hasInternalDataProvider() && xPropSet.is() )
373 : {
374 16 : apphelper::MediaDescriptorHelper aMDHelper(rMediaDescriptor);
375 : try
376 : {
377 16 : xPropSet->setPropertyValue(
378 : "SavedObject",
379 22 : uno::makeAny( aMDHelper.HierarchicalDocumentName ) );
380 : }
381 6 : catch ( const uno::Exception& )
382 : {
383 16 : }
384 544 : }
385 544 : }
386 :
387 28 : void ChartModel::insertDefaultChart()
388 : {
389 28 : lockControllers();
390 28 : createInternalDataProvider( sal_False );
391 : try
392 : {
393 : // create default chart
394 28 : Reference< chart2::XChartTypeTemplate > xTemplate( impl_createDefaultChartTypeTemplate() );
395 28 : if( xTemplate.is())
396 : {
397 : try
398 : {
399 28 : Reference< chart2::data::XDataSource > xDataSource( impl_createDefaultData() );
400 56 : Sequence< beans::PropertyValue > aParam;
401 :
402 28 : bool bSupportsCategories = xTemplate->supportsCategories();
403 28 : if( bSupportsCategories )
404 : {
405 28 : aParam.realloc( 1 );
406 56 : aParam[0] = beans::PropertyValue( "HasCategories", -1, uno::makeAny( true ),
407 28 : beans::PropertyState_DIRECT_VALUE );
408 : }
409 :
410 56 : Reference< chart2::XDiagram > xDiagram( xTemplate->createDiagramByDataSource( xDataSource, aParam ) );
411 :
412 28 : setFirstDiagram( xDiagram );
413 :
414 28 : bool bIsRTL = Application::GetSettings().GetMathLayoutRTL();
415 : //reverse x axis for rtl charts
416 28 : if( bIsRTL )
417 0 : AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) );
418 :
419 : // create and attach legend
420 : Reference< chart2::XLegend > xLegend(
421 56 : m_xContext->getServiceManager()->createInstanceWithContext(
422 56 : "com.sun.star.chart2.Legend", m_xContext ), uno::UNO_QUERY_THROW );
423 56 : Reference< beans::XPropertySet > xLegendProperties( xLegend, uno::UNO_QUERY );
424 28 : if( xLegendProperties.is() )
425 : {
426 28 : xLegendProperties->setPropertyValue( "FillStyle", uno::makeAny( drawing::FillStyle_NONE ));
427 28 : xLegendProperties->setPropertyValue( "LineStyle", uno::makeAny( drawing::LineStyle_NONE ));
428 28 : xLegendProperties->setPropertyValue( "LineColor", uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) )); // gray30
429 28 : xLegendProperties->setPropertyValue( "FillColor", uno::makeAny( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10
430 :
431 28 : if( bIsRTL )
432 0 : xLegendProperties->setPropertyValue( "AnchorPosition", uno::makeAny( chart2::LegendPosition_LINE_START ));
433 : }
434 28 : if(xDiagram.is())
435 28 : xDiagram->setLegend( xLegend );
436 :
437 : // set simple 3D look
438 56 : Reference< beans::XPropertySet > xDiagramProperties( xDiagram, uno::UNO_QUERY );
439 28 : if( xDiagramProperties.is() )
440 : {
441 28 : xDiagramProperties->setPropertyValue( "RightAngledAxes", uno::makeAny( sal_True ));
442 28 : xDiagramProperties->setPropertyValue( "D3DScenePerspective", uno::makeAny( drawing::ProjectionMode_PARALLEL ));
443 28 : ThreeDHelper::setScheme( xDiagram, ThreeDLookScheme_Realistic );
444 : }
445 :
446 : //set some new 'defaults' for wall and floor
447 28 : if( xDiagram.is() )
448 : {
449 28 : Reference< beans::XPropertySet > xWall( xDiagram->getWall() );
450 28 : if( xWall.is() )
451 : {
452 28 : xWall->setPropertyValue( "LineStyle", uno::makeAny( drawing::LineStyle_SOLID ) );
453 28 : xWall->setPropertyValue( "FillStyle", uno::makeAny( drawing::FillStyle_NONE ) );
454 28 : xWall->setPropertyValue( "LineColor", uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30
455 28 : xWall->setPropertyValue( "FillColor", uno::makeAny( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10
456 : }
457 56 : Reference< beans::XPropertySet > xFloor( xDiagram->getFloor() );
458 28 : if( xFloor.is() )
459 : {
460 28 : xFloor->setPropertyValue( "LineStyle", uno::makeAny( drawing::LineStyle_NONE ) );
461 28 : xFloor->setPropertyValue( "FillStyle", uno::makeAny( drawing::FillStyle_SOLID ) );
462 28 : xFloor->setPropertyValue( "LineColor", uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30
463 28 : xFloor->setPropertyValue( "FillColor", uno::makeAny( static_cast< sal_Int32 >( 0xcccccc ) ) ); // gray20
464 28 : }
465 :
466 28 : }
467 : }
468 0 : catch( const uno::Exception & ex )
469 : {
470 : ASSERT_EXCEPTION( ex );
471 : }
472 : }
473 28 : ChartModelHelper::setIncludeHiddenCells( false, *this );
474 : }
475 0 : catch( const uno::Exception & ex )
476 : {
477 : ASSERT_EXCEPTION( ex );
478 : }
479 28 : setModified( sal_False );
480 28 : unlockControllers();
481 28 : }
482 :
483 : // frame::XLoadable
484 364 : void SAL_CALL ChartModel::initNew()
485 : throw (frame::DoubleInitializationException,
486 : io::IOException,
487 : uno::Exception,
488 : uno::RuntimeException, std::exception)
489 : {
490 364 : }
491 :
492 10 : void SAL_CALL ChartModel::load(
493 : const Sequence< beans::PropertyValue >& rMediaDescriptor )
494 : throw (frame::DoubleInitializationException,
495 : io::IOException,
496 : uno::Exception,
497 : uno::RuntimeException, std::exception)
498 : {
499 10 : Reference< embed::XStorage > xStorage;
500 20 : OUString aURL;
501 : try
502 : {
503 10 : apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor );
504 10 : if( aMDHelper.ISSET_Storage )
505 : {
506 0 : xStorage = aMDHelper.Storage;
507 : }
508 10 : else if( aMDHelper.ISSET_Stream ||
509 : aMDHelper.ISSET_InputStream )
510 : {
511 40 : if( aMDHelper.ISSET_FilterName &&
512 60 : (aMDHelper.FilterName.equals( "StarChart 5.0") ||
513 50 : aMDHelper.FilterName.equals( "StarChart 4.0") ||
514 30 : aMDHelper.FilterName.equals( "StarChart 3.0") ))
515 : {
516 0 : attachResource( aMDHelper.URL, rMediaDescriptor );
517 0 : impl_load( rMediaDescriptor, 0 ); // cannot create a storage from binary streams, but I do not need the storage here anyhow
518 0 : m_bReadOnly = true;
519 10 : return;
520 : }
521 :
522 10 : Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create(m_xContext) );
523 :
524 10 : if( aMDHelper.ISSET_Stream )
525 : {
526 : // convert XStream to XStorage via the storage factory
527 6 : Sequence< uno::Any > aStorageArgs( 2 );
528 6 : aStorageArgs[0] <<= aMDHelper.Stream;
529 : // todo: check if stream is read-only
530 6 : aStorageArgs[1] <<= (embed::ElementModes::READ); //WRITE | embed::ElementModes::NOCREATE);
531 :
532 6 : xStorage.set( xStorageFact->createInstanceWithArguments( aStorageArgs ),
533 6 : uno::UNO_QUERY_THROW );
534 : }
535 : else
536 : {
537 : OSL_ASSERT( aMDHelper.ISSET_InputStream );
538 : // convert XInputStream to XStorage via the storage factory
539 4 : Sequence< uno::Any > aStorageArgs( 2 );
540 4 : aStorageArgs[0] <<= aMDHelper.InputStream;
541 4 : aStorageArgs[1] <<= (embed::ElementModes::READ);
542 :
543 4 : xStorage.set( xStorageFact->createInstanceWithArguments( aStorageArgs ),
544 4 : uno::UNO_QUERY_THROW );
545 10 : }
546 : }
547 :
548 10 : if( aMDHelper.ISSET_URL )
549 10 : aURL = aMDHelper.URL;
550 : }
551 0 : catch( const uno::Exception & ex )
552 : {
553 : ASSERT_EXCEPTION( ex );
554 : }
555 :
556 10 : if( xStorage.is())
557 : {
558 10 : attachResource( aURL, rMediaDescriptor );
559 10 : impl_load( rMediaDescriptor, xStorage );
560 10 : }
561 : }
562 :
563 242 : void ChartModel::impl_load(
564 : const Sequence< beans::PropertyValue >& rMediaDescriptor,
565 : const Reference< embed::XStorage >& xStorage )
566 : {
567 : {
568 242 : MutexGuard aGuard( m_aModelMutex );
569 242 : m_nInLoad++;
570 : }
571 :
572 242 : Reference< document::XFilter > xFilter( impl_createFilter( rMediaDescriptor ));
573 :
574 242 : if( xFilter.is())
575 : {
576 242 : Reference< document::XImporter > xImporter( xFilter, uno::UNO_QUERY_THROW );
577 242 : xImporter->setTargetDocument( this );
578 484 : Sequence< beans::PropertyValue > aMD( rMediaDescriptor );
579 242 : lcl_addStorageToMediaDescriptor( aMD, xStorage );
580 :
581 242 : xFilter->filter( aMD );
582 484 : xFilter.clear();
583 : }
584 : else
585 : {
586 : OSL_FAIL( "loadFromStorage cannot create filter" );
587 : }
588 :
589 242 : if( xStorage.is() )
590 242 : impl_loadGraphics( xStorage );
591 :
592 242 : setModified( sal_False );
593 :
594 : // switchToStorage without notifying listeners (which shouldn't exist at
595 : // this time, anyway)
596 242 : m_xStorage = xStorage;
597 :
598 : {
599 242 : MutexGuard aGuard( m_aModelMutex );
600 242 : m_nInLoad--;
601 242 : }
602 242 : }
603 :
604 242 : void ChartModel::impl_loadGraphics(
605 : const Reference< embed::XStorage >& xStorage )
606 : {
607 : try
608 : {
609 : const Reference< embed::XStorage >& xGraphicsStorage(
610 242 : xStorage->openStorageElement( "Pictures",
611 466 : embed::ElementModes::READ ) );
612 :
613 18 : if( xGraphicsStorage.is() )
614 : {
615 : const uno::Sequence< OUString > aElementNames(
616 18 : xGraphicsStorage->getElementNames() );
617 :
618 42 : for( int i = 0; i < aElementNames.getLength(); ++i )
619 : {
620 24 : if( xGraphicsStorage->isStreamElement( aElementNames[ i ] ) )
621 : {
622 : uno::Reference< io::XStream > xElementStream(
623 24 : xGraphicsStorage->openStreamElement(
624 24 : aElementNames[ i ],
625 48 : embed::ElementModes::READ ) );
626 :
627 24 : if( xElementStream.is() )
628 : {
629 : boost::scoped_ptr< SvStream > apIStm(
630 : ::utl::UcbStreamHelper::CreateStream(
631 24 : xElementStream, true ) );
632 :
633 24 : if( apIStm.get() )
634 : {
635 24 : Graphic aGraphic;
636 :
637 24 : if( !GraphicConverter::Import(
638 24 : *apIStm.get(),
639 24 : aGraphic ) )
640 : {
641 24 : m_aGraphicObjectVector.push_back( aGraphic );
642 24 : }
643 24 : }
644 24 : }
645 : }
646 18 : }
647 18 : }
648 : }
649 224 : catch ( const uno::Exception& )
650 : {
651 : }
652 242 : }
653 :
654 : // util::XModifiable
655 3507 : void SAL_CALL ChartModel::impl_notifyModifiedListeners()
656 : throw( uno::RuntimeException)
657 : {
658 : {
659 3507 : MutexGuard aGuard( m_aModelMutex );
660 3507 : m_bUpdateNotificationsPending = false;
661 : }
662 :
663 : //always notify the view first!
664 3507 : ChartViewHelper::setViewToDirtyState( this );
665 :
666 : ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer
667 3507 : .getContainer( cppu::UnoType<util::XModifyListener>::get());
668 3507 : if( pIC )
669 : {
670 3069 : lang::EventObject aEvent( static_cast< lang::XComponent*>(this) );
671 6138 : ::cppu::OInterfaceIteratorHelper aIt( *pIC );
672 16531 : while( aIt.hasMoreElements() )
673 : {
674 10393 : uno::Reference< util::XModifyListener > xListener( aIt.next(), uno::UNO_QUERY );
675 10393 : if( xListener.is() )
676 10393 : xListener->modified( aEvent );
677 13462 : }
678 : }
679 3507 : }
680 :
681 4566 : sal_Bool SAL_CALL ChartModel::isModified()
682 : throw(uno::RuntimeException, std::exception)
683 : {
684 : //@todo guard
685 4566 : return m_bModified;
686 : }
687 :
688 14729 : void SAL_CALL ChartModel::setModified( sal_Bool bModified )
689 : throw(beans::PropertyVetoException,
690 : uno::RuntimeException, std::exception)
691 : {
692 14729 : apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager);
693 14729 : if(!aGuard.startApiCall())//@todo ? is this a long lasting call??
694 2 : return; //behave passive if already disposed or closed or throw exception @todo?
695 14727 : m_bModified = bModified;
696 :
697 14727 : if( m_nControllerLockCount > 0 )
698 : {
699 10376 : m_bUpdateNotificationsPending = true;
700 10376 : return;//don't call listeners if controllers are locked
701 : }
702 4351 : aGuard.clear();
703 :
704 4351 : if(bModified)
705 2091 : impl_notifyModifiedListeners();
706 : }
707 :
708 : // util::XModifyBroadcaster (base of XModifiable)
709 2146 : void SAL_CALL ChartModel::addModifyListener(
710 : const uno::Reference< util::XModifyListener >& xListener )
711 : throw(uno::RuntimeException, std::exception)
712 : {
713 2146 : if( m_aLifeTimeManager.impl_isDisposedOrClosed() )
714 2146 : return; //behave passive if already disposed or closed
715 :
716 : m_aLifeTimeManager.m_aListenerContainer.addInterface(
717 2146 : cppu::UnoType<util::XModifyListener>::get(), xListener );
718 : }
719 :
720 978 : void SAL_CALL ChartModel::removeModifyListener(
721 : const uno::Reference< util::XModifyListener >& xListener )
722 : throw(uno::RuntimeException, std::exception)
723 : {
724 978 : if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
725 978 : return; //behave passive if already disposed or closed
726 :
727 : m_aLifeTimeManager.m_aListenerContainer.removeInterface(
728 978 : cppu::UnoType<util::XModifyListener>::get(), xListener );
729 : }
730 :
731 : // util::XModifyListener
732 42043 : void SAL_CALL ChartModel::modified( const lang::EventObject& )
733 : throw (uno::RuntimeException, std::exception)
734 : {
735 42043 : if( m_nInLoad == 0 )
736 9367 : setModified( sal_True );
737 42043 : }
738 :
739 : // lang::XEventListener (base of util::XModifyListener)
740 756 : void SAL_CALL ChartModel::disposing( const lang::EventObject& )
741 : throw (uno::RuntimeException, std::exception)
742 : {
743 : // child was disposed -- should not happen from outside
744 756 : }
745 :
746 : // document::XStorageBasedDocument
747 232 : void SAL_CALL ChartModel::loadFromStorage(
748 : const Reference< embed::XStorage >& xStorage,
749 : const Sequence< beans::PropertyValue >& rMediaDescriptor )
750 : throw (lang::IllegalArgumentException,
751 : frame::DoubleInitializationException,
752 : io::IOException,
753 : uno::Exception,
754 : uno::RuntimeException, std::exception)
755 : {
756 232 : attachResource( OUString(), rMediaDescriptor );
757 232 : impl_load( rMediaDescriptor, xStorage );
758 232 : }
759 :
760 544 : void SAL_CALL ChartModel::storeToStorage(
761 : const Reference< embed::XStorage >& xStorage,
762 : const Sequence< beans::PropertyValue >& rMediaDescriptor )
763 : throw (lang::IllegalArgumentException,
764 : io::IOException,
765 : uno::Exception,
766 : uno::RuntimeException, std::exception)
767 : {
768 544 : impl_store( rMediaDescriptor, xStorage );
769 544 : }
770 :
771 534 : void SAL_CALL ChartModel::switchToStorage( const Reference< embed::XStorage >& xStorage )
772 : throw (lang::IllegalArgumentException,
773 : io::IOException,
774 : uno::Exception,
775 : uno::RuntimeException, std::exception)
776 : {
777 534 : m_xStorage = xStorage;
778 534 : impl_notifyStorageChangeListeners();
779 534 : }
780 :
781 958 : Reference< embed::XStorage > SAL_CALL ChartModel::getDocumentStorage()
782 : throw (io::IOException,
783 : uno::Exception,
784 : uno::RuntimeException, std::exception)
785 : {
786 958 : return m_xStorage;
787 : }
788 :
789 534 : void SAL_CALL ChartModel::impl_notifyStorageChangeListeners()
790 : throw( uno::RuntimeException)
791 : {
792 : ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer
793 534 : .getContainer( cppu::UnoType<document::XStorageChangeListener>::get());
794 534 : if( pIC )
795 : {
796 0 : ::cppu::OInterfaceIteratorHelper aIt( *pIC );
797 0 : while( aIt.hasMoreElements() )
798 : {
799 0 : uno::Reference< document::XStorageChangeListener > xListener( aIt.next(), uno::UNO_QUERY );
800 0 : if( xListener.is() )
801 0 : xListener->notifyStorageChange( static_cast< ::cppu::OWeakObject* >( this ), m_xStorage );
802 0 : }
803 : }
804 534 : }
805 :
806 0 : void SAL_CALL ChartModel::addStorageChangeListener( const Reference< document::XStorageChangeListener >& xListener )
807 : throw (uno::RuntimeException, std::exception)
808 : {
809 0 : if( m_aLifeTimeManager.impl_isDisposedOrClosed() )
810 0 : return; //behave passive if already disposed or closed
811 :
812 : m_aLifeTimeManager.m_aListenerContainer.addInterface(
813 0 : cppu::UnoType<document::XStorageChangeListener>::get(), xListener );
814 : }
815 :
816 0 : void SAL_CALL ChartModel::removeStorageChangeListener( const Reference< document::XStorageChangeListener >& xListener )
817 : throw (uno::RuntimeException, std::exception)
818 : {
819 0 : if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
820 0 : return; //behave passive if already disposed or closed
821 :
822 : m_aLifeTimeManager.m_aListenerContainer.removeInterface(
823 0 : cppu::UnoType<document::XStorageChangeListener>::get(), xListener );
824 : }
825 :
826 108 : } // namespace chart
827 :
828 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|