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