1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <ChartModel.hxx>
22 #include <MediaDescriptorHelper.hxx>
23 #include <ChartViewHelper.hxx>
24 #include <ChartModelHelper.hxx>
25 #include <ChartTypeManager.hxx>
26 #include <ChartTypeTemplate.hxx>
27 #include <DataSourceHelper.hxx>
28 #include <AxisHelper.hxx>
29 #include <ThreeDHelper.hxx>
30 #include <Diagram.hxx>
31 #include <BaseCoordinateSystem.hxx>
33 #include <XMLFilter.hxx>
35 #include <com/sun/star/chart2/LegendPosition.hpp>
36 #include <com/sun/star/container/XNameAccess.hpp>
37 #include <com/sun/star/document/XExporter.hpp>
38 #include <com/sun/star/document/XImporter.hpp>
39 #include <com/sun/star/document/XFilter.hpp>
40 #include <com/sun/star/drawing/FillStyle.hpp>
41 #include <com/sun/star/drawing/LineStyle.hpp>
42 #include <com/sun/star/drawing/ProjectionMode.hpp>
43 #include <com/sun/star/embed/ElementModes.hpp>
44 #include <com/sun/star/embed/XStorage.hpp>
45 #include <com/sun/star/embed/StorageFactory.hpp>
46 #include <com/sun/star/io/IOException.hpp>
47 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
48 #include <com/sun/star/uno/XComponentContext.hpp>
49 #include <com/sun/star/ucb/CommandFailedException.hpp>
50 #include <com/sun/star/ucb/ContentCreationException.hpp>
52 #include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
54 #include <ucbhelper/content.hxx>
55 #include <unotools/ucbstreamhelper.hxx>
56 #include <unotools/tempfile.hxx>
58 #include <vcl/cvtgrf.hxx>
59 #include <comphelper/processfactory.hxx>
60 #include <comphelper/storagehelper.hxx>
61 #include <vcl/settings.hxx>
62 #include <vcl/svapp.hxx>
63 #include <comphelper/diagnose_ex.hxx>
64 #include <sal/log.hxx>
65 #include <sfx2/objsh.hxx>
69 using namespace ::com::sun::star
;
71 using ::com::sun::star::uno::Reference
;
72 using ::com::sun::star::uno::Sequence
;
73 using ::osl::MutexGuard
;
77 template< typename T
>
79 const Sequence
< beans::PropertyValue
> & rMediaDescriptor
,
80 const OUString
& rPropName
)
83 if( rMediaDescriptor
.hasElements())
85 auto pIt
= std::find_if(rMediaDescriptor
.begin(), rMediaDescriptor
.end(),
86 [&rPropName
](auto& prop
) { return prop
.Name
== rPropName
; });
87 if (pIt
!= rMediaDescriptor
.end())
88 (*pIt
).Value
>>= aResult
;
93 void lcl_addStorageToMediaDescriptor(
94 Sequence
< beans::PropertyValue
> & rOutMD
,
95 const Reference
< embed::XStorage
> & xStorage
)
97 rOutMD
.realloc( rOutMD
.getLength() + 1 );
98 rOutMD
.getArray()[rOutMD
.getLength() - 1] = beans::PropertyValue(
99 u
"Storage"_ustr
, -1, uno::Any( xStorage
), beans::PropertyState_DIRECT_VALUE
);
102 Reference
< embed::XStorage
> lcl_createStorage(
103 const OUString
& rURL
,
104 const Reference
< uno::XComponentContext
> & xContext
,
105 const Sequence
< beans::PropertyValue
> & rMediaDescriptor
)
107 // create new storage
108 Reference
< embed::XStorage
> xStorage
;
114 Reference
< io::XStream
> xStream(
115 ::ucbhelper::Content( rURL
, Reference
< css::ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext()).openStream(),
118 Reference
< lang::XSingleServiceFactory
> xStorageFact( embed::StorageFactory::create( xContext
) );
119 Sequence
< uno::Any
> aStorageArgs
{ uno::Any(xStream
),
120 uno::Any(embed::ElementModes::READWRITE
),
121 uno::Any(rMediaDescriptor
) };
123 xStorageFact
->createInstanceWithArguments( aStorageArgs
), uno::UNO_QUERY_THROW
);
125 catch(const css::ucb::ContentCreationException
&)
127 DBG_UNHANDLED_EXCEPTION("chart2");
129 catch(const css::ucb::CommandFailedException
&)
131 DBG_UNHANDLED_EXCEPTION("chart2");
137 } // anonymous namespace
142 Reference
< document::XFilter
> ChartModel::impl_createFilter(
143 const Sequence
< beans::PropertyValue
> & rMediaDescriptor
)
145 Reference
< document::XFilter
> xFilter
;
147 // find FilterName in MediaDescriptor
148 OUString
aFilterName(
149 lcl_getProperty
< OUString
>( rMediaDescriptor
, u
"FilterName"_ustr
) );
151 // if FilterName was found, get Filter from factory
152 if( !aFilterName
.isEmpty() )
156 Reference
< container::XNameAccess
> xFilterFact(
157 m_xContext
->getServiceManager()->createInstanceWithContext(
158 u
"com.sun.star.document.FilterFactory"_ustr
, m_xContext
),
159 uno::UNO_QUERY_THROW
);
160 uno::Any
aFilterProps( xFilterFact
->getByName( aFilterName
));
161 Sequence
< beans::PropertyValue
> aProps
;
163 if( aFilterProps
.hasValue() &&
164 (aFilterProps
>>= aProps
))
166 OUString
aFilterServiceName(
167 lcl_getProperty
< OUString
>( aProps
, u
"FilterService"_ustr
) );
169 if( !aFilterServiceName
.isEmpty())
172 m_xContext
->getServiceManager()->createInstanceWithContext(
173 aFilterServiceName
, m_xContext
), uno::UNO_QUERY_THROW
);
174 SAL_INFO("chart2", "Filter found for service " << aFilterServiceName
);
178 catch( const uno::Exception
& )
180 DBG_UNHANDLED_EXCEPTION("chart2");
182 OSL_ENSURE( xFilter
.is(), "Filter not found via factory" );
185 // fall-back: create XML-Filter
188 SAL_WARN("chart2", "No FilterName passed in MediaDescriptor" );
189 xFilter
= new XMLFilter(m_xContext
);
197 void SAL_CALL
ChartModel::storeSelf( const Sequence
< beans::PropertyValue
>& rMediaDescriptor
)
199 // only some parameters are allowed (see also SfxBaseModel)
200 // "VersionComment", "Author", "InteractionHandler", "StatusIndicator"
201 // However, they are ignored here. They would become interesting when
202 // charts support a standalone format again.
203 impl_store( rMediaDescriptor
, m_xStorage
);
206 // frame::XStorable (base of XStorable2)
207 sal_Bool SAL_CALL
ChartModel::hasLocation()
209 std::unique_lock
aGuard(m_aLifeTimeManager
.m_aAccessMutex
);
210 return !m_aResource
.isEmpty();
213 OUString SAL_CALL
ChartModel::getLocation()
215 return impl_g_getLocation();
218 sal_Bool SAL_CALL
ChartModel::isReadonly()
224 void SAL_CALL
ChartModel::store()
226 apphelper::LifeTimeGuard
aGuard(m_aLifeTimeManager
);
227 if(!aGuard
.startApiCall(true)) //start LongLastingCall
228 return; //behave passive if already disposed or closed or throw exception @todo?
230 OUString aLocation
= m_aResource
;
232 if( aLocation
.isEmpty() )
233 throw io::IOException( u
"no location specified"_ustr
, static_cast< ::cppu::OWeakObject
* >(this));
234 //@todo check whether aLocation is something like private:factory...
236 throw io::IOException( u
"document is read only"_ustr
, static_cast< ::cppu::OWeakObject
* >(this));
241 impl_store( m_aMediaDescriptor
, m_xStorage
);
244 void SAL_CALL
ChartModel::storeAsURL(
245 const OUString
& rURL
,
246 const uno::Sequence
< beans::PropertyValue
>& rMediaDescriptor
)
248 apphelper::LifeTimeGuard
aGuard(m_aLifeTimeManager
);
249 if(!aGuard
.startApiCall(true)) //start LongLastingCall
250 return; //behave passive if already disposed or closed or throw exception @todo?
252 apphelper::MediaDescriptorHelper
aMediaDescriptorHelper(rMediaDescriptor
);
253 const uno::Sequence
< beans::PropertyValue
>& aReducedMediaDescriptor(
254 aMediaDescriptorHelper
.getReducedForModel() );
259 // create new storage
260 Reference
< embed::XStorage
> xStorage( lcl_createStorage( rURL
, m_xContext
, aReducedMediaDescriptor
));
264 impl_store( aReducedMediaDescriptor
, xStorage
);
265 attachResource( rURL
, aReducedMediaDescriptor
);
269 void SAL_CALL
ChartModel::storeToURL(
270 const OUString
& rURL
,
271 const uno::Sequence
< beans::PropertyValue
>& rMediaDescriptor
)
273 apphelper::LifeTimeGuard
aGuard(m_aLifeTimeManager
);
274 if(!aGuard
.startApiCall(true)) //start LongLastingCall
275 return; //behave passive if already disposed or closed or throw exception @todo?
276 //do not change the internal state of the document here
280 apphelper::MediaDescriptorHelper
aMediaDescriptorHelper(rMediaDescriptor
);
281 const uno::Sequence
< beans::PropertyValue
>& aReducedMediaDescriptor(
282 aMediaDescriptorHelper
.getReducedForModel() );
284 if ( rURL
== "private:stream" )
288 if( m_xContext
.is() && aMediaDescriptorHelper
.ISSET_OutputStream
)
290 rtl::Reference
< utl::TempFileFastService
> xStream
= new utl::TempFileFastService
;
291 Reference
< io::XInputStream
> xInputStream( xStream
->getInputStream());
293 Reference
< embed::XStorage
> xStorage(
294 ::comphelper::OStorageHelper::GetStorageFromStream( xStream
, embed::ElementModes::READWRITE
, m_xContext
));
297 impl_store( aReducedMediaDescriptor
, xStorage
);
300 ::comphelper::OStorageHelper::CopyInputToOutput( xInputStream
, aMediaDescriptorHelper
.OutputStream
);
304 catch( const uno::Exception
& )
306 DBG_UNHANDLED_EXCEPTION("chart2");
311 // create new storage
312 Reference
< embed::XStorage
> xStorage( lcl_createStorage( rURL
, m_xContext
, aReducedMediaDescriptor
));
315 impl_store( aReducedMediaDescriptor
, xStorage
);
319 void ChartModel::impl_store(
320 const Sequence
< beans::PropertyValue
>& rMediaDescriptor
,
321 const Reference
< embed::XStorage
> & xStorage
)
323 Reference
< document::XFilter
> xFilter( impl_createFilter( rMediaDescriptor
));
324 if( xFilter
.is() && xStorage
.is())
326 Sequence
< beans::PropertyValue
> aMD( rMediaDescriptor
);
327 lcl_addStorageToMediaDescriptor( aMD
, xStorage
);
330 Reference
< document::XExporter
> xExporter( xFilter
, uno::UNO_QUERY_THROW
);
331 xExporter
->setSourceDocument( Reference
< lang::XComponent
>( this ));
332 xFilter
->filter( aMD
);
334 catch( const uno::Exception
& )
336 DBG_UNHANDLED_EXCEPTION("chart2");
341 OSL_FAIL( "No filter" );
344 setModified( false );
347 //for data change notification during chart is not loaded:
348 //notify parent data provider after saving thus the parent document can store
349 //the ranges for which a load and update of the chart will be necessary
350 Reference
< beans::XPropertySet
> xPropSet( m_xParent
, uno::UNO_QUERY
);
351 if ( hasInternalDataProvider() || !xPropSet
.is() )
354 apphelper::MediaDescriptorHelper
aMDHelper(rMediaDescriptor
);
357 xPropSet
->setPropertyValue(
359 uno::Any( aMDHelper
.HierarchicalDocumentName
) );
361 catch ( const uno::Exception
& )
366 void ChartModel::insertDefaultChart()
369 createInternalDataProvider( false );
372 // create default chart
373 rtl::Reference
< ::chart::ChartTypeTemplate
> xTemplate( impl_createDefaultChartTypeTemplate() );
378 Reference
< chart2::data::XDataSource
> xDataSource( impl_createDefaultData() );
379 Sequence
< beans::PropertyValue
> aParam
;
381 bool bSupportsCategories
= xTemplate
->supportsCategories();
382 if( bSupportsCategories
)
384 aParam
= { beans::PropertyValue( u
"HasCategories"_ustr
, -1, uno::Any( true ),
385 beans::PropertyState_DIRECT_VALUE
) };
388 rtl::Reference
< Diagram
> xDiagram( xTemplate
->createDiagramByDataSource2( xDataSource
, aParam
) );
390 setFirstDiagram( xDiagram
);
392 bool bIsRTL
= AllSettings::GetMathLayoutRTL();
393 //reverse x axis for rtl charts
395 AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram
, 0 ) );
397 // create and attach legend
398 rtl::Reference
< Legend
> xLegend
= new Legend();
399 xLegend
->setPropertyValue( u
"FillStyle"_ustr
, uno::Any( drawing::FillStyle_NONE
));
400 xLegend
->setPropertyValue( u
"LineStyle"_ustr
, uno::Any( drawing::LineStyle_NONE
));
401 xLegend
->setPropertyValue( u
"LineColor"_ustr
, uno::Any( static_cast< sal_Int32
>( 0xb3b3b3 ) )); // gray30
402 xLegend
->setPropertyValue( u
"FillColor"_ustr
, uno::Any( static_cast< sal_Int32
>( 0xe6e6e6 ) ) ); // gray10
405 xLegend
->setPropertyValue( u
"AnchorPosition"_ustr
, uno::Any( chart2::LegendPosition_LINE_START
));
408 xDiagram
->setLegend( xLegend
);
410 // set simple 3D look
411 xDiagram
->setPropertyValue( u
"RightAngledAxes"_ustr
, uno::Any( true ));
412 xDiagram
->setPropertyValue( u
"D3DScenePerspective"_ustr
, uno::Any( drawing::ProjectionMode_PARALLEL
));
413 xDiagram
->setScheme( ThreeDLookScheme::ThreeDLookScheme_Realistic
);
415 //set some new 'defaults' for wall and floor
416 Reference
< beans::XPropertySet
> xWall( xDiagram
->getWall() );
419 xWall
->setPropertyValue( u
"LineStyle"_ustr
, uno::Any( drawing::LineStyle_SOLID
) );
420 xWall
->setPropertyValue( u
"FillStyle"_ustr
, uno::Any( drawing::FillStyle_NONE
) );
421 xWall
->setPropertyValue( u
"LineColor"_ustr
, uno::Any( static_cast< sal_Int32
>( 0xb3b3b3 ) ) ); // gray30
422 xWall
->setPropertyValue( u
"FillColor"_ustr
, uno::Any( static_cast< sal_Int32
>( 0xe6e6e6 ) ) ); // gray10
424 Reference
< beans::XPropertySet
> xFloor( xDiagram
->getFloor() );
427 xFloor
->setPropertyValue( u
"LineStyle"_ustr
, uno::Any( drawing::LineStyle_NONE
) );
428 xFloor
->setPropertyValue( u
"FillStyle"_ustr
, uno::Any( drawing::FillStyle_SOLID
) );
429 xFloor
->setPropertyValue( u
"LineColor"_ustr
, uno::Any( static_cast< sal_Int32
>( 0xb3b3b3 ) ) ); // gray30
430 xFloor
->setPropertyValue( u
"FillColor"_ustr
, uno::Any( static_cast< sal_Int32
>( 0xcccccc ) ) ); // gray20
435 catch( const uno::Exception
& )
437 DBG_UNHANDLED_EXCEPTION("chart2");
440 ChartModelHelper::setIncludeHiddenCells( false, *this );
442 catch( const uno::Exception
& )
444 DBG_UNHANDLED_EXCEPTION("chart2");
446 setModified( false );
451 void SAL_CALL
ChartModel::initNew()
455 void SAL_CALL
ChartModel::load(
456 const Sequence
< beans::PropertyValue
>& rMediaDescriptor
)
458 Reference
< embed::XStorage
> xStorage
;
462 apphelper::MediaDescriptorHelper
aMDHelper( rMediaDescriptor
);
463 if( aMDHelper
.ISSET_Storage
)
465 xStorage
= aMDHelper
.Storage
;
467 else if( aMDHelper
.ISSET_Stream
||
468 aMDHelper
.ISSET_InputStream
)
470 if( aMDHelper
.ISSET_FilterName
&&
471 (aMDHelper
.FilterName
== "StarChart 5.0" ||
472 aMDHelper
.FilterName
== "StarChart 4.0" ||
473 aMDHelper
.FilterName
== "StarChart 3.0" ))
475 attachResource( aMDHelper
.URL
, rMediaDescriptor
);
476 impl_load( rMediaDescriptor
, nullptr ); // cannot create a storage from binary streams, but I do not need the storage here anyhow
481 Reference
< lang::XSingleServiceFactory
> xStorageFact( embed::StorageFactory::create(m_xContext
) );
483 if( aMDHelper
.ISSET_Stream
)
485 // convert XStream to XStorage via the storage factory
486 Sequence
< uno::Any
> aStorageArgs
{ uno::Any(aMDHelper
.Stream
),
487 // todo: check if stream is read-only
488 uno::Any(embed::ElementModes::READ
) }; //WRITE | embed::ElementModes::NOCREATE);
490 xStorage
.set( xStorageFact
->createInstanceWithArguments( aStorageArgs
),
491 uno::UNO_QUERY_THROW
);
495 OSL_ASSERT( aMDHelper
.ISSET_InputStream
);
496 // convert XInputStream to XStorage via the storage factory
497 Sequence
< uno::Any
> aStorageArgs
{ uno::Any(aMDHelper
.InputStream
),
498 uno::Any(embed::ElementModes::READ
) };
500 xStorage
.set( xStorageFact
->createInstanceWithArguments( aStorageArgs
),
501 uno::UNO_QUERY_THROW
);
505 if( aMDHelper
.ISSET_URL
)
506 aURL
= aMDHelper
.URL
;
508 catch( const uno::Exception
& )
510 DBG_UNHANDLED_EXCEPTION("chart2");
515 attachResource( aURL
, rMediaDescriptor
);
516 impl_load( rMediaDescriptor
, xStorage
);
520 void ChartModel::impl_load(
521 const Sequence
< beans::PropertyValue
>& rMediaDescriptor
,
522 const Reference
< embed::XStorage
>& xStorage
)
525 MutexGuard
aGuard( m_aModelMutex
);
529 Reference
< document::XFilter
> xFilter( impl_createFilter( rMediaDescriptor
));
533 Reference
< document::XImporter
> xImporter( xFilter
, uno::UNO_QUERY_THROW
);
534 xImporter
->setTargetDocument( this );
535 Sequence
< beans::PropertyValue
> aMD( rMediaDescriptor
);
536 lcl_addStorageToMediaDescriptor( aMD
, xStorage
);
538 xFilter
->filter( aMD
);
543 OSL_FAIL( "loadFromStorage cannot create filter" );
547 impl_loadGraphics( xStorage
);
549 setModified( false );
551 // switchToStorage without notifying listeners (which shouldn't exist at
552 // this time, anyway)
553 m_xStorage
= xStorage
;
556 MutexGuard
aGuard( m_aModelMutex
);
561 void ChartModel::impl_loadGraphics(
562 const Reference
< embed::XStorage
>& xStorage
)
566 const Reference
< embed::XStorage
> xGraphicsStorage(
567 xStorage
->openStorageElement( u
"Pictures"_ustr
,
568 embed::ElementModes::READ
) );
570 if( xGraphicsStorage
.is() )
572 const uno::Sequence
< OUString
> aElementNames(
573 xGraphicsStorage
->getElementNames() );
575 for( OUString
const & streamName
: aElementNames
)
577 if( xGraphicsStorage
->isStreamElement( streamName
) )
579 uno::Reference
< io::XStream
> xElementStream(
580 xGraphicsStorage
->openStreamElement(
582 embed::ElementModes::READ
) );
584 if( xElementStream
.is() )
586 std::unique_ptr
< SvStream
> apIStm(
587 ::utl::UcbStreamHelper::CreateStream(
588 xElementStream
, true ) );
592 SolarMutexGuard aGuard
;
594 if (!GraphicConverter::Import(*apIStm
, aGraphic
))
596 m_aGraphicObjectVector
.emplace_back(aGraphic
);
604 catch ( const uno::Exception
& )
610 void ChartModel::impl_notifyModifiedListeners()
613 MutexGuard
aGuard( m_aModelMutex
);
614 m_bUpdateNotificationsPending
= false;
617 //always notify the view first!
618 ChartViewHelper::setViewToDirtyState( this );
620 std::unique_lock
aGuard(m_aLifeTimeManager
.m_aAccessMutex
);
621 if( m_aLifeTimeManager
.m_aModifyListeners
.getLength(aGuard
) )
623 lang::EventObject
aEvent( static_cast< lang::XComponent
*>(this) );
624 m_aLifeTimeManager
.m_aModifyListeners
.notifyEach(aGuard
, &util::XModifyListener::modified
, aEvent
);
628 sal_Bool SAL_CALL
ChartModel::isModified()
634 void SAL_CALL
ChartModel::setModified( sal_Bool bModified
)
636 // tdf#141914: allow to set *unmodified* when parent does not allow to set modified
639 // tdf#77007: honor parent's IsEnableSetModified
640 // Check it before LifeTimeGuard, to avoid deadlocking solar mutex and this guard
641 if (auto pParentShell
= SfxObjectShell::GetShellFromComponent(getParent());
642 pParentShell
&& !pParentShell
->IsEnableSetModified())
646 apphelper::LifeTimeGuard
aGuard(m_aLifeTimeManager
);
647 if(!aGuard
.startApiCall())//@todo ? is this a long lasting call??
648 return; //behave passive if already disposed or closed or throw exception @todo?
649 m_bModified
= bModified
;
651 if( m_nControllerLockCount
> 0 )
654 m_bUpdateNotificationsPending
= true; // Maybe !bModified should reset it?
655 return;//don't call listeners if controllers are locked
660 impl_notifyModifiedListeners();
663 // util::XModifyBroadcaster (base of XModifiable)
664 void SAL_CALL
ChartModel::addModifyListener(
665 const uno::Reference
< util::XModifyListener
>& xListener
)
667 if( m_aLifeTimeManager
.impl_isDisposedOrClosed() )
668 return; //behave passive if already disposed or closed
670 std::unique_lock
aGuard(m_aLifeTimeManager
.m_aAccessMutex
);
671 m_aLifeTimeManager
.m_aModifyListeners
.addInterface( aGuard
, xListener
);
674 void SAL_CALL
ChartModel::removeModifyListener(
675 const uno::Reference
< util::XModifyListener
>& xListener
)
677 if( m_aLifeTimeManager
.impl_isDisposedOrClosed(false) )
678 return; //behave passive if already disposed or closed
680 std::unique_lock
aGuard(m_aLifeTimeManager
.m_aAccessMutex
);
681 m_aLifeTimeManager
.m_aModifyListeners
.removeInterface( aGuard
, xListener
);
684 // util::XModifyListener
685 void SAL_CALL
ChartModel::modified( const lang::EventObject
& rEvenObject
)
687 uno::Reference
<chart2::data::XPivotTableDataProvider
> xPivotTableDataProvider(rEvenObject
.Source
, uno::UNO_QUERY
);
688 if (xPivotTableDataProvider
.is())
691 uno::Reference
<chart2::data::XDataProvider
> xDataProvider(xPivotTableDataProvider
, uno::UNO_QUERY
);
694 uno::Sequence
<beans::PropertyValue
> aArguments
=
695 DataSourceHelper::createArguments(u
"PivotChart"_ustr
, uno::Sequence
<sal_Int32
>(), true, true, true);
697 Reference
<chart2::data::XDataSource
> xDataSource(xDataProvider
->createDataSource(aArguments
));
698 rtl::Reference
< ::chart::ChartTypeManager
> xChartTypeManager
= getTypeManager();
699 rtl::Reference
<Diagram
> xDiagram(getFirstChartDiagram());
701 Diagram::tTemplateWithServiceName aTemplateAndService
= xDiagram
->getTemplate(xChartTypeManager
);
702 aTemplateAndService
.xChartTypeTemplate
->changeDiagramData(xDiagram
, xDataSource
, aArguments
);
704 catch (const uno::Exception
&)
706 DBG_UNHANDLED_EXCEPTION("chart2");
715 // lang::XEventListener (base of util::XModifyListener)
716 void SAL_CALL
ChartModel::disposing( const lang::EventObject
& )
718 // child was disposed -- should not happen from outside
721 // document::XStorageBasedDocument
722 void SAL_CALL
ChartModel::loadFromStorage(
723 const Reference
< embed::XStorage
>& xStorage
,
724 const Sequence
< beans::PropertyValue
>& rMediaDescriptor
)
726 attachResource( OUString(), rMediaDescriptor
);
727 impl_load( rMediaDescriptor
, xStorage
);
730 void SAL_CALL
ChartModel::storeToStorage(
731 const Reference
< embed::XStorage
>& xStorage
,
732 const Sequence
< beans::PropertyValue
>& rMediaDescriptor
)
734 impl_store( rMediaDescriptor
, xStorage
);
737 void SAL_CALL
ChartModel::switchToStorage( const Reference
< embed::XStorage
>& xStorage
)
739 m_xStorage
= xStorage
;
740 impl_notifyStorageChangeListeners();
743 Reference
< embed::XStorage
> SAL_CALL
ChartModel::getDocumentStorage()
748 void ChartModel::impl_notifyStorageChangeListeners()
750 std::unique_lock
aGuard(m_aLifeTimeManager
.m_aAccessMutex
);
751 if( m_aLifeTimeManager
.m_aStorageChangeListeners
.getLength(aGuard
) )
753 m_aLifeTimeManager
.m_aStorageChangeListeners
.forEach(aGuard
,
754 [this](const uno::Reference
<document::XStorageChangeListener
>& l
)
756 l
->notifyStorageChange( static_cast< ::cppu::OWeakObject
* >( this ), m_xStorage
);
761 void SAL_CALL
ChartModel::addStorageChangeListener( const Reference
< document::XStorageChangeListener
>& xListener
)
763 if( m_aLifeTimeManager
.impl_isDisposedOrClosed() )
764 return; //behave passive if already disposed or closed
766 std::unique_lock
aGuard(m_aLifeTimeManager
.m_aAccessMutex
);
767 m_aLifeTimeManager
.m_aStorageChangeListeners
.addInterface( aGuard
, xListener
);
770 void SAL_CALL
ChartModel::removeStorageChangeListener( const Reference
< document::XStorageChangeListener
>& xListener
)
772 if( m_aLifeTimeManager
.impl_isDisposedOrClosed(false) )
773 return; //behave passive if already disposed or closed
775 std::unique_lock
aGuard(m_aLifeTimeManager
.m_aAccessMutex
);
776 m_aLifeTimeManager
.m_aStorageChangeListeners
.removeInterface(aGuard
, xListener
);
781 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */