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