diff options
Diffstat (limited to 'chart2/source/model/main/ChartModel_Persistence.cxx')
-rw-r--r-- | chart2/source/model/main/ChartModel_Persistence.cxx | 860 |
1 files changed, 860 insertions, 0 deletions
diff --git a/chart2/source/model/main/ChartModel_Persistence.cxx b/chart2/source/model/main/ChartModel_Persistence.cxx new file mode 100644 index 000000000000..1868c38e094f --- /dev/null +++ b/chart2/source/model/main/ChartModel_Persistence.cxx @@ -0,0 +1,860 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ChartModel.hxx" +#include "MediaDescriptorHelper.hxx" +#include "ChartDebugTrace.hxx" +#include "macros.hxx" +#include "ChartViewHelper.hxx" +#include "ChartModelHelper.hxx" +#include "AxisHelper.hxx" +#include "ThreeDHelper.hxx" + +#include <com/sun/star/chart2/LegendPosition.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/document/XExporter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/ProjectionMode.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/io/XSeekable.hpp> + +#include <ucbhelper/content.hxx> +#ifndef _UNOTOOLS_UCBSTREAMHELPER_HXX +#include <unotools/ucbstreamhelper.hxx> +#endif +#include <vcl/cvtgrf.hxx> +#include <comphelper/storagehelper.hxx> +#include <vcl/svapp.hxx> + +#include <algorithm> +#include <functional> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; +using ::osl::MutexGuard; + +namespace +{ +struct lcl_PropNameEquals : public ::std::unary_function< beans::PropertyValue, bool > +{ + lcl_PropNameEquals( const OUString & rStrToCompareWith ) : + m_aStr( rStrToCompareWith ) + {} + bool operator() ( const beans::PropertyValue & rProp ) + { + return rProp.Name.equals( m_aStr ); + } +private: + OUString m_aStr; +}; + +template< typename T > +T lcl_getProperty( + const Sequence< beans::PropertyValue > & rMediaDescriptor, + const OUString & rPropName ) +{ + T aResult; + if( rMediaDescriptor.getLength()) + { + OUString aPropName( rPropName ); + const beans::PropertyValue * pIt = rMediaDescriptor.getConstArray(); + const beans::PropertyValue * pEndIt = pIt + + rMediaDescriptor.getLength(); + pIt = ::std::find_if( pIt, pEndIt, lcl_PropNameEquals( aPropName )); + if( pIt != pEndIt ) + (*pIt).Value >>= aResult; + } + return aResult; +} + +void lcl_addStorageToMediaDescriptor( + Sequence< beans::PropertyValue > & rOutMD, + const Reference< embed::XStorage > & xStorage ) +{ + rOutMD.realloc( rOutMD.getLength() + 1 ); + rOutMD[rOutMD.getLength() - 1] = beans::PropertyValue( + C2U("Storage"), -1, uno::makeAny( xStorage ), beans::PropertyState_DIRECT_VALUE ); +} + +Reference< embed::XStorage > lcl_createStorage( + const OUString & rURL, + const Reference< uno::XComponentContext > & xContext, + const Sequence< beans::PropertyValue > & rMediaDescriptor ) +{ + // create new storage + Reference< embed::XStorage > xStorage; + if( !xContext.is()) + return xStorage; + + try + { + Reference< io::XStream > xStream( + ::ucbhelper::Content( rURL, Reference< ::com::sun::star::ucb::XCommandEnvironment >()).openStream(), + uno::UNO_QUERY ); + + Reference< lang::XSingleServiceFactory > xStorageFact( + xContext->getServiceManager()->createInstanceWithContext( + C2U("com.sun.star.embed.StorageFactory"), + xContext ), + uno::UNO_QUERY_THROW ); + Sequence< uno::Any > aStorageArgs( 3 ); + aStorageArgs[0] <<= xStream; + aStorageArgs[1] <<= embed::ElementModes::READWRITE; + aStorageArgs[2] <<= rMediaDescriptor; + xStorage.set( + xStorageFact->createInstanceWithArguments( aStorageArgs ), uno::UNO_QUERY_THROW ); + OSL_ENSURE( xStorage.is(), "No Storage" ); + } + catch( ::com::sun::star::ucb::ContentCreationException & rEx ) + { + ASSERT_EXCEPTION( rEx ); + } + + return xStorage; +} + +} // anonymous namespace + +namespace chart +{ + +Reference< document::XFilter > ChartModel::impl_createFilter( + const Sequence< beans::PropertyValue > & rMediaDescriptor ) +{ + Reference< document::XFilter > xFilter; + + // find FilterName in MediaDescriptor + OUString aFilterName( + lcl_getProperty< OUString >( rMediaDescriptor, OUString::createFromAscii("FilterName"))); + + // if FilterName was found, get Filter from factory + if( aFilterName.getLength() > 0 ) + { + try + { + Reference< container::XNameAccess > xFilterFact( + m_xContext->getServiceManager()->createInstanceWithContext( + C2U( "com.sun.star.document.FilterFactory" ), m_xContext ), + uno::UNO_QUERY_THROW ); + uno::Any aFilterProps( xFilterFact->getByName( aFilterName )); + Sequence< beans::PropertyValue > aProps; + + if( aFilterProps.hasValue() && + (aFilterProps >>= aProps)) + { + OUString aFilterServiceName( + lcl_getProperty< OUString >( aProps, OUString::createFromAscii("FilterService"))); + + if( aFilterServiceName.getLength()) + { + xFilter.set( + m_xContext->getServiceManager()->createInstanceWithContext( + aFilterServiceName, m_xContext ), uno::UNO_QUERY_THROW ); + OSL_TRACE( "Filter found for service %s", U2C( aFilterServiceName )); + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + OSL_ENSURE( xFilter.is(), "Filter not found via factory" ); + } + + // fall-back: create XML-Filter + if( ! xFilter.is()) + { + OSL_TRACE( "No FilterName passed in MediaDescriptor" ); + xFilter.set( + m_xContext->getServiceManager()->createInstanceWithContext( + C2U("com.sun.star.comp.chart2.XMLFilter"), m_xContext ), + uno::UNO_QUERY_THROW ); + } + + return xFilter; +} + +//----------------------------------------------------------------- +// frame::XStorable2 +//----------------------------------------------------------------- + +void SAL_CALL ChartModel::storeSelf( const Sequence< beans::PropertyValue >& rMediaDescriptor ) + throw (lang::IllegalArgumentException, + io::IOException, + uno::RuntimeException) +{ + // only some parameters are allowed (see also SfxBaseModel) + // "VersionComment", "Author", "InteractionHandler", "StatusIndicator" + // However, they are ignored here. They would become interesting when + // charts support a standalone format again. + impl_store( rMediaDescriptor, m_xStorage ); +} + +//----------------------------------------------------------------- +// frame::XStorable (base of XStorable2) +//----------------------------------------------------------------- +sal_Bool SAL_CALL ChartModel::hasLocation() + throw(uno::RuntimeException) +{ + //@todo guard + return m_aResource.getLength()!=0; +} + +::rtl::OUString SAL_CALL ChartModel::getLocation() + throw(uno::RuntimeException) +{ + return impl_g_getLocation(); +} + +sal_Bool SAL_CALL ChartModel::isReadonly() + throw(uno::RuntimeException) +{ + //@todo guard + return m_bReadOnly; +} + +void SAL_CALL ChartModel::store() + throw(io::IOException, + uno::RuntimeException) +{ + apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall(sal_True)) //start LongLastingCall + return; //behave passive if already disposed or closed or throw exception @todo? + + ::rtl::OUString aLocation = m_aResource; + + if( aLocation.getLength() == 0 ) + throw io::IOException( C2U( "no location specified" ), static_cast< ::cppu::OWeakObject* >(this)); + //@todo check wether aLocation is something like private:factory... + if( m_bReadOnly ) + throw io::IOException( C2U( "document is read only" ), static_cast< ::cppu::OWeakObject* >(this)); + + aGuard.clear(); + + // store + impl_store( m_aMediaDescriptor, m_xStorage ); +} + +void SAL_CALL ChartModel::storeAsURL( + const ::rtl::OUString& rURL, + const uno::Sequence< beans::PropertyValue >& rMediaDescriptor ) + throw(io::IOException, uno::RuntimeException) +{ + apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall(sal_True)) //start LongLastingCall + return; //behave passive if already disposed or closed or throw exception @todo? + + apphelper::MediaDescriptorHelper aMediaDescriptorHelper(rMediaDescriptor); + uno::Sequence< beans::PropertyValue > aReducedMediaDescriptor( + aMediaDescriptorHelper.getReducedForModel() ); + + m_bReadOnly = sal_False; + aGuard.clear(); + + // create new storage + Reference< embed::XStorage > xStorage( lcl_createStorage( rURL, m_xContext, aReducedMediaDescriptor )); + + if( xStorage.is()) + { + impl_store( aReducedMediaDescriptor, xStorage ); + attachResource( rURL, aReducedMediaDescriptor ); + } +} + +void SAL_CALL ChartModel::storeToURL( + const ::rtl::OUString& rURL, + const uno::Sequence< beans::PropertyValue >& rMediaDescriptor ) + throw(io::IOException, + uno::RuntimeException) +{ + apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall(sal_True)) //start LongLastingCall + return; //behave passive if already disposed or closed or throw exception @todo? + //do not change the internal state of the document here + //... + + aGuard.clear(); + + apphelper::MediaDescriptorHelper aMediaDescriptorHelper(rMediaDescriptor); + uno::Sequence< beans::PropertyValue > aReducedMediaDescriptor( + aMediaDescriptorHelper.getReducedForModel() ); + + if( rURL.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("private:stream"))) + { + try + { + if( m_xContext.is() && aMediaDescriptorHelper.ISSET_OutputStream ) + { + Reference< lang::XMultiServiceFactory > xFact( m_xContext->getServiceManager(), uno::UNO_QUERY_THROW ); + Reference< io::XStream > xStream( + xFact->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.io.TempFile"))), uno::UNO_QUERY_THROW ); + Reference< io::XInputStream > xInputStream( xStream->getInputStream()); + + Reference< embed::XStorage > xStorage( + ::comphelper::OStorageHelper::GetStorageFromStream( xStream, embed::ElementModes::READWRITE, xFact )); + if( xStorage.is()) + { + impl_store( aReducedMediaDescriptor, xStorage ); + + Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY_THROW ); + xSeekable->seek( 0 ); + ::comphelper::OStorageHelper::CopyInputToOutput( xInputStream, aMediaDescriptorHelper.OutputStream ); + } + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + else + { + // create new storage + Reference< embed::XStorage > xStorage( lcl_createStorage( rURL, m_xContext, aReducedMediaDescriptor )); + + if( xStorage.is()) + impl_store( aReducedMediaDescriptor, xStorage ); + } +} + +void ChartModel::impl_store( + const Sequence< beans::PropertyValue >& rMediaDescriptor, + const Reference< embed::XStorage > & xStorage ) +{ + Reference< document::XFilter > xFilter( impl_createFilter( rMediaDescriptor)); + if( xFilter.is() && xStorage.is()) + { + Sequence< beans::PropertyValue > aMD( rMediaDescriptor ); + lcl_addStorageToMediaDescriptor( aMD, xStorage ); + try + { + Reference< document::XExporter > xExporter( xFilter, uno::UNO_QUERY_THROW ); + xExporter->setSourceDocument( Reference< lang::XComponent >( this )); + xFilter->filter( aMD ); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + else + { + OSL_ENSURE( false, "No filter" ); + } + + setModified( sal_False ); + + //#i66865# + //for data change notification during chart is not loaded: + //notify parent data provider after saving thus the parent document can store + //the ranges for which a load and update of the chart will be necessary + Reference< beans::XPropertySet > xPropSet( m_xParent, uno::UNO_QUERY ); + if ( !hasInternalDataProvider() && xPropSet.is() ) + { + apphelper::MediaDescriptorHelper aMDHelper(rMediaDescriptor); + try + { + xPropSet->setPropertyValue( OUString::createFromAscii("SavedObject"), + uno::makeAny( aMDHelper.HierarchicalDocumentName ) ); + } + catch ( uno::Exception& ) + { + } + } +} + +//----------------------------------------------------------------- +// frame::XLoadable +//----------------------------------------------------------------- +void SAL_CALL ChartModel::initNew() + throw (frame::DoubleInitializationException, + io::IOException, + uno::Exception, + uno::RuntimeException) +{ + lockControllers(); + createInternalDataProvider( sal_False ); + try + { + // create default chart + Reference< chart2::XChartTypeTemplate > xTemplate( impl_createDefaultChartTypeTemplate() ); + if( xTemplate.is()) + { + try + { + Reference< chart2::data::XDataSource > xDataSource( impl_createDefaultData() ); + Sequence< beans::PropertyValue > aParam; + + bool bSupportsCategories = xTemplate->supportsCategories(); + if( bSupportsCategories ) + { + aParam.realloc( 1 ); + aParam[0] = beans::PropertyValue( C2U("HasCategories"), -1, uno::makeAny( true ), + beans::PropertyState_DIRECT_VALUE ); + } + + Reference< chart2::XDiagram > xDiagram( xTemplate->createDiagramByDataSource( xDataSource, aParam ) ); + + setFirstDiagram( xDiagram ); + + bool bIsRTL = Application::GetSettings().GetLayoutRTL(); + //reverse x axis for rtl charts + if( bIsRTL ) + AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) ); + + // create and attach legend + Reference< chart2::XLegend > xLegend( + m_xContext->getServiceManager()->createInstanceWithContext( + C2U( "com.sun.star.chart2.Legend" ), m_xContext ), uno::UNO_QUERY_THROW ); + Reference< beans::XPropertySet > xLegendProperties( xLegend, uno::UNO_QUERY ); + if( xLegendProperties.is() ) + { + xLegendProperties->setPropertyValue( C2U( "FillStyle" ), uno::makeAny( drawing::FillStyle_NONE )); + xLegendProperties->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_NONE )); + xLegendProperties->setPropertyValue( C2U( "LineColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) )); // gray30 + xLegendProperties->setPropertyValue( C2U( "FillColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10 + + if( bIsRTL ) + xLegendProperties->setPropertyValue( C2U( "AnchorPosition" ), uno::makeAny( chart2::LegendPosition_LINE_START )); + } + if(xDiagram.is()) + xDiagram->setLegend( xLegend ); + + // set simple 3D look + Reference< beans::XPropertySet > xDiagramProperties( xDiagram, uno::UNO_QUERY ); + if( xDiagramProperties.is() ) + { + xDiagramProperties->setPropertyValue( C2U("RightAngledAxes"), uno::makeAny( sal_True )); + xDiagramProperties->setPropertyValue( C2U("D3DScenePerspective"), uno::makeAny( drawing::ProjectionMode_PARALLEL )); + ThreeDHelper::setScheme( xDiagram, ThreeDLookScheme_Realistic ); + } + + //set some new 'defaults' for wall and floor + if( xDiagram.is() ) + { + Reference< beans::XPropertySet > xWall( xDiagram->getWall() ); + if( xWall.is() ) + { + xWall->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_SOLID ) ); + xWall->setPropertyValue( C2U( "FillStyle" ), uno::makeAny( drawing::FillStyle_NONE ) ); + xWall->setPropertyValue( C2U( "LineColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30 + xWall->setPropertyValue( C2U( "FillColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10 + } + Reference< beans::XPropertySet > xFloor( xDiagram->getFloor() ); + if( xFloor.is() ) + { + xFloor->setPropertyValue( C2U( "LineStyle" ), uno::makeAny( drawing::LineStyle_NONE ) ); + xFloor->setPropertyValue( C2U( "FillStyle" ), uno::makeAny( drawing::FillStyle_SOLID ) ); + xFloor->setPropertyValue( C2U( "LineColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30 + xFloor->setPropertyValue( C2U( "FillColor" ), uno::makeAny( static_cast< sal_Int32 >( 0xcccccc ) ) ); // gray20 + } + + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + ChartModelHelper::setIncludeHiddenCells( false, this ); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + setModified( sal_False ); + unlockControllers(); + +#if OSL_DEBUG_LEVEL >= CHART_TRACE_OSL_DEBUG_LEVEL + OSL_TRACE( "ChartModel::initNew: Showing ChartDocument structure" ); + OSL_TRACE( "----------------------------------------------------" ); + debug::ChartDebugTraceDocument( Reference< chart2::XChartDocument >( this )); +#endif +} + +void SAL_CALL ChartModel::load( + const Sequence< beans::PropertyValue >& rMediaDescriptor ) + throw (frame::DoubleInitializationException, + io::IOException, + uno::Exception, + uno::RuntimeException) +{ + Reference< embed::XStorage > xStorage; + OUString aURL; + try + { + apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor ); + if( aMDHelper.ISSET_Storage ) + { + xStorage = aMDHelper.Storage; + } + else if( aMDHelper.ISSET_Stream || + aMDHelper.ISSET_InputStream ) + { + if( aMDHelper.ISSET_FilterName && + (aMDHelper.FilterName.equals( C2U("StarChart 5.0")) || + aMDHelper.FilterName.equals( C2U("StarChart 4.0")) || + aMDHelper.FilterName.equals( C2U("StarChart 3.0")) )) + { + attachResource( aMDHelper.URL, rMediaDescriptor ); + impl_load( rMediaDescriptor, 0 ); // cannot create a storage from binary streams, but I do not need the storage here anyhow + m_bReadOnly = sal_True; + return; + } + + Reference< lang::XSingleServiceFactory > xStorageFact( + m_xContext->getServiceManager()->createInstanceWithContext( + C2U("com.sun.star.embed.StorageFactory"), + m_xContext ), + uno::UNO_QUERY_THROW ); + + if( aMDHelper.ISSET_Stream ) + { + // convert XStream to XStorage via the storage factory + Sequence< uno::Any > aStorageArgs( 2 ); + aStorageArgs[0] <<= aMDHelper.Stream; + // todo: check if stream is read-only + aStorageArgs[1] <<= (embed::ElementModes::READ); //WRITE | embed::ElementModes::NOCREATE); + + xStorage.set( xStorageFact->createInstanceWithArguments( aStorageArgs ), + uno::UNO_QUERY_THROW ); + } + else + { + OSL_ASSERT( aMDHelper.ISSET_InputStream ); + // convert XInputStream to XStorage via the storage factory + Sequence< uno::Any > aStorageArgs( 2 ); + aStorageArgs[0] <<= aMDHelper.InputStream; + aStorageArgs[1] <<= (embed::ElementModes::READ); + + xStorage.set( xStorageFact->createInstanceWithArguments( aStorageArgs ), + uno::UNO_QUERY_THROW ); + } + } + + if( aMDHelper.ISSET_URL ) + aURL = aMDHelper.URL; + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + if( xStorage.is()) + { + attachResource( aURL, rMediaDescriptor ); + impl_load( rMediaDescriptor, xStorage ); + } +} + +void ChartModel::impl_load( + const Sequence< beans::PropertyValue >& rMediaDescriptor, + const Reference< embed::XStorage >& xStorage ) +{ + { + MutexGuard aGuard( m_aModelMutex ); + m_nInLoad++; + } + + Reference< document::XFilter > xFilter( impl_createFilter( rMediaDescriptor )); + + if( xFilter.is()) + { + Reference< document::XImporter > xImporter( xFilter, uno::UNO_QUERY_THROW ); + xImporter->setTargetDocument( this ); + Sequence< beans::PropertyValue > aMD( rMediaDescriptor ); + lcl_addStorageToMediaDescriptor( aMD, xStorage ); + + xFilter->filter( aMD ); + xFilter.clear(); + } + else + { + OSL_ENSURE( false, "loadFromStorage cannot create filter" ); + } + + if( xStorage.is() ) + impl_loadGraphics( xStorage ); + + setModified( sal_False ); + + // switchToStorage without notifying listeners (which shouldn't exist at + // this time, anyway) + m_xStorage = xStorage; + + { + MutexGuard aGuard( m_aModelMutex ); + m_nInLoad--; + } +} + +void ChartModel::impl_loadGraphics( + const Reference< embed::XStorage >& xStorage ) +{ + try + { + const Reference< embed::XStorage >& xGraphicsStorage( + xStorage->openStorageElement( C2U( "Pictures" ), + embed::ElementModes::READ ) ); + + if( xGraphicsStorage.is() ) + { + const uno::Sequence< ::rtl::OUString > aElementNames( + xGraphicsStorage->getElementNames() ); + + for( int i = 0; i < aElementNames.getLength(); ++i ) + { + if( xGraphicsStorage->isStreamElement( aElementNames[ i ] ) ) + { + uno::Reference< io::XStream > xElementStream( + xGraphicsStorage->openStreamElement( + aElementNames[ i ], + embed::ElementModes::READ ) ); + + if( xElementStream.is() ) + { + std::auto_ptr< SvStream > apIStm( + ::utl::UcbStreamHelper::CreateStream( + xElementStream, true ) ); + + if( apIStm.get() ) + { + Graphic aGraphic; + + if( !GraphicConverter::Import( + *apIStm.get(), + aGraphic ) ) + { + m_aGraphicObjectVector.push_back( aGraphic ); + } + } + } + } + } + } + } + catch ( uno::Exception& ) + { + } +} + +//----------------------------------------------------------------- +// util::XModifiable +//----------------------------------------------------------------- +void SAL_CALL ChartModel::impl_notifyModifiedListeners() + throw( uno::RuntimeException) +{ + { + MutexGuard aGuard( m_aModelMutex ); + m_bUpdateNotificationsPending = false; + } + + //always notify the view first! + ChartViewHelper::setViewToDirtyState( this ); + + ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer + .getContainer( ::getCppuType((const uno::Reference< util::XModifyListener >*)0) ); + if( pIC ) + { + lang::EventObject aEvent( static_cast< lang::XComponent*>(this) ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< util::XModifyListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->modified( aEvent ); + } + } +} + +sal_Bool SAL_CALL ChartModel::isModified() + throw(uno::RuntimeException) +{ + //@todo guard + return m_bModified; +} + +void SAL_CALL ChartModel::setModified( sal_Bool bModified ) + throw(beans::PropertyVetoException, + uno::RuntimeException) +{ + apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager); + if(!aGuard.startApiCall())//@todo ? is this a long lasting call?? + return; //behave passive if already disposed or closed or throw exception @todo? + m_bModified = bModified; + + if( m_nControllerLockCount > 0 ) + { + m_bUpdateNotificationsPending = true; + return;//don't call listeners if controllers are locked + } + aGuard.clear(); + + if(bModified) + impl_notifyModifiedListeners(); +} + +//----------------------------------------------------------------- +// util::XModifyBroadcaster (base of XModifiable) +//----------------------------------------------------------------- +void SAL_CALL ChartModel::addModifyListener( + const uno::Reference< util::XModifyListener >& xListener ) + throw(uno::RuntimeException) +{ + if( m_aLifeTimeManager.impl_isDisposedOrClosed() ) + return; //behave passive if already disposed or closed + + m_aLifeTimeManager.m_aListenerContainer.addInterface( + ::getCppuType((const uno::Reference< util::XModifyListener >*)0), xListener ); +} + +void SAL_CALL ChartModel::removeModifyListener( + const uno::Reference< util::XModifyListener >& xListener ) + throw(uno::RuntimeException) +{ + if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) ) + return; //behave passive if already disposed or closed + + m_aLifeTimeManager.m_aListenerContainer.removeInterface( + ::getCppuType((const uno::Reference< util::XModifyListener >*)0), xListener ); +} + +//----------------------------------------------------------------- +// util::XModifyListener +//----------------------------------------------------------------- +void SAL_CALL ChartModel::modified( const lang::EventObject& ) + throw (uno::RuntimeException) +{ + if( m_nInLoad == 0 ) + setModified( sal_True ); +} + +//----------------------------------------------------------------- +// lang::XEventListener (base of util::XModifyListener) +//----------------------------------------------------------------- +void SAL_CALL ChartModel::disposing( const lang::EventObject& ) + throw (uno::RuntimeException) +{ + // child was disposed -- should not happen from outside +} + + +//----------------------------------------------------------------- +// document::XStorageBasedDocument +//----------------------------------------------------------------- +void SAL_CALL ChartModel::loadFromStorage( + const Reference< embed::XStorage >& xStorage, + const Sequence< beans::PropertyValue >& rMediaDescriptor ) + throw (lang::IllegalArgumentException, + frame::DoubleInitializationException, + io::IOException, + uno::Exception, + uno::RuntimeException) +{ + attachResource( OUString(), rMediaDescriptor ); + impl_load( rMediaDescriptor, xStorage ); +} + +void SAL_CALL ChartModel::storeToStorage( + const Reference< embed::XStorage >& xStorage, + const Sequence< beans::PropertyValue >& rMediaDescriptor ) + throw (lang::IllegalArgumentException, + io::IOException, + uno::Exception, + uno::RuntimeException) +{ + impl_store( rMediaDescriptor, xStorage ); +} + +void SAL_CALL ChartModel::switchToStorage( const Reference< embed::XStorage >& xStorage ) + throw (lang::IllegalArgumentException, + io::IOException, + uno::Exception, + uno::RuntimeException) +{ + m_xStorage = xStorage; + impl_notifyStorageChangeListeners(); +} + +Reference< embed::XStorage > SAL_CALL ChartModel::getDocumentStorage() + throw (io::IOException, + uno::Exception, + uno::RuntimeException) +{ + return m_xStorage; +} + +void SAL_CALL ChartModel::impl_notifyStorageChangeListeners() + throw( uno::RuntimeException) +{ + ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer + .getContainer( ::getCppuType((const uno::Reference< document::XStorageChangeListener >*)0) ); + if( pIC ) + { + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< document::XStorageChangeListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->notifyStorageChange( static_cast< ::cppu::OWeakObject* >( this ), m_xStorage ); + } + } +} + +void SAL_CALL ChartModel::addStorageChangeListener( const Reference< document::XStorageChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + if( m_aLifeTimeManager.impl_isDisposedOrClosed() ) + return; //behave passive if already disposed or closed + + m_aLifeTimeManager.m_aListenerContainer.addInterface( + ::getCppuType((const uno::Reference< document::XStorageChangeListener >*)0), xListener ); +} + +void SAL_CALL ChartModel::removeStorageChangeListener( const Reference< document::XStorageChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) ) + return; //behave passive if already disposed or closed + + m_aLifeTimeManager.m_aListenerContainer.removeInterface( + ::getCppuType((const uno::Reference< document::XStorageChangeListener >*)0), xListener ); +} + +} // namespace chart |