| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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.isEmpty() ) |
| { |
| 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.isEmpty() ) |
| { |
| 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.isEmpty(); |
| } |
| |
| ::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.isEmpty() ) |
| 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 |