summaryrefslogtreecommitdiff
path: root/chart2/source/model/main/ChartModel_Persistence.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'chart2/source/model/main/ChartModel_Persistence.cxx')
-rw-r--r--chart2/source/model/main/ChartModel_Persistence.cxx861
1 files changed, 861 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..b1cbbd0d3db8
--- /dev/null
+++ b/chart2/source/model/main/ChartModel_Persistence.cxx
@@ -0,0 +1,861 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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>
+#include <unotools/ucbstreamhelper.hxx>
+#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( RTL_CONSTASCII_USTRINGPARAM( "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( RTL_CONSTASCII_USTRINGPARAM( "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_FAIL( "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( RTL_CONSTASCII_USTRINGPARAM( "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_FAIL( "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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */