tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / chart2 / source / model / main / ChartModel_Persistence.cxx
blobfe5db160cf321e5d7eaeff90208137fa3a967278
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <memory>
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>
32 #include <Legend.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>
57 #include <utility>
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>
67 #include <algorithm>
69 using namespace ::com::sun::star;
71 using ::com::sun::star::uno::Reference;
72 using ::com::sun::star::uno::Sequence;
73 using ::osl::MutexGuard;
75 namespace
77 template< typename T >
78 T lcl_getProperty(
79 const Sequence< beans::PropertyValue > & rMediaDescriptor,
80 const OUString & rPropName )
82 T aResult;
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;
90 return 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;
109 if( !xContext.is())
110 return xStorage;
114 Reference< io::XStream > xStream(
115 ::ucbhelper::Content( rURL, Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext()).openStream(),
116 uno::UNO_QUERY );
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) };
122 xStorage.set(
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");
134 return xStorage;
137 } // anonymous namespace
139 namespace chart
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())
171 xFilter.set(
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
186 if( ! xFilter.is())
188 SAL_WARN("chart2", "No FilterName passed in MediaDescriptor" );
189 xFilter = new XMLFilter(m_xContext);
192 return xFilter;
195 // frame::XStorable2
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()
220 //@todo guard
221 return m_bReadOnly;
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...
235 if( m_bReadOnly )
236 throw io::IOException( u"document is read only"_ustr, static_cast< ::cppu::OWeakObject* >(this));
238 aGuard.clear();
240 // store
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() );
256 m_bReadOnly = false;
257 aGuard.clear();
259 // create new storage
260 Reference< embed::XStorage > xStorage( lcl_createStorage( rURL, m_xContext, aReducedMediaDescriptor ));
262 if( xStorage.is())
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
278 aGuard.clear();
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 ));
295 if( xStorage.is())
297 impl_store( aReducedMediaDescriptor, xStorage );
299 xStream->seek( 0 );
300 ::comphelper::OStorageHelper::CopyInputToOutput( xInputStream, aMediaDescriptorHelper.OutputStream );
304 catch( const uno::Exception & )
306 DBG_UNHANDLED_EXCEPTION("chart2");
309 else
311 // create new storage
312 Reference< embed::XStorage > xStorage( lcl_createStorage( rURL, m_xContext, aReducedMediaDescriptor ));
314 if( xStorage.is())
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");
339 else
341 OSL_FAIL( "No filter" );
344 setModified( false );
346 //#i66865#
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() )
352 return;
354 apphelper::MediaDescriptorHelper aMDHelper(rMediaDescriptor);
357 xPropSet->setPropertyValue(
358 u"SavedObject"_ustr,
359 uno::Any( aMDHelper.HierarchicalDocumentName ) );
361 catch ( const uno::Exception& )
366 void ChartModel::insertDefaultChart()
368 lockControllers();
369 createInternalDataProvider( false );
372 // create default chart
373 rtl::Reference< ::chart::ChartTypeTemplate > xTemplate( impl_createDefaultChartTypeTemplate() );
374 if( xTemplate.is())
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
394 if( bIsRTL )
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
404 if( bIsRTL )
405 xLegend->setPropertyValue( u"AnchorPosition"_ustr, uno::Any( chart2::LegendPosition_LINE_START ));
406 if(xDiagram.is())
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() );
417 if( xWall.is() )
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() );
425 if( xFloor.is() )
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 );
447 unlockControllers();
450 // frame::XLoadable
451 void SAL_CALL ChartModel::initNew()
455 void SAL_CALL ChartModel::load(
456 const Sequence< beans::PropertyValue >& rMediaDescriptor )
458 Reference< embed::XStorage > xStorage;
459 OUString aURL;
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
477 m_bReadOnly = true;
478 return;
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 );
493 else
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");
513 if( xStorage.is())
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 );
526 m_nInLoad++;
529 Reference< document::XFilter > xFilter( impl_createFilter( rMediaDescriptor ));
531 if( xFilter.is())
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 );
539 xFilter.clear();
541 else
543 OSL_FAIL( "loadFromStorage cannot create filter" );
546 if( xStorage.is() )
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 );
557 m_nInLoad--;
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(
581 streamName,
582 embed::ElementModes::READ ) );
584 if( xElementStream.is() )
586 std::unique_ptr< SvStream > apIStm(
587 ::utl::UcbStreamHelper::CreateStream(
588 xElementStream, true ) );
590 if (apIStm)
592 SolarMutexGuard aGuard;
593 Graphic aGraphic;
594 if (!GraphicConverter::Import(*apIStm, aGraphic))
596 m_aGraphicObjectVector.emplace_back(aGraphic );
604 catch ( const uno::Exception& )
609 // util::XModifiable
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()
630 //@todo guard
631 return m_bModified;
634 void SAL_CALL ChartModel::setModified( sal_Bool bModified )
636 // tdf#141914: allow to set *unmodified* when parent does not allow to set modified
637 if (bModified)
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())
643 return;
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 )
653 if (bModified)
654 m_bUpdateNotificationsPending = true; // Maybe !bModified should reset it?
655 return;//don't call listeners if controllers are locked
657 aGuard.clear();
659 if(bModified)
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())
690 lockControllers();
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");
708 unlockControllers();
711 if (m_nInLoad == 0)
712 setModified(true);
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()
745 return m_xStorage;
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 );
779 } // namespace chart
781 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */