Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/chart2/source/model/main/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 27 kB image not shown  

Quellcode-Bibliothek ChartModel_Persistence.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   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 .
 */


#include <memory>
#include <ChartModel.hxx>
#include <MediaDescriptorHelper.hxx>
#include <ChartViewHelper.hxx>
#include <ChartTypeManager.hxx>
#include <ChartTypeTemplate.hxx>
#include <DataSourceHelper.hxx>
#include <AxisHelper.hxx>
#include <ThreeDHelper.hxx>
#include <Diagram.hxx>
#include <BaseCoordinateSystem.hxx>
#include <Legend.hxx>
#include <XMLFilter.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/embed/StorageFactory.hpp>
#include <com/sun/star/io/IOException.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/ucb/CommandFailedException.hpp>
#include <com/sun/star/ucb/ContentCreationException.hpp>

#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>

#include <ucbhelper/content.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/tempfile.hxx>
#include <utility>
#include <vcl/cvtgrf.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/storagehelper.hxx>
#include <vcl/settings.hxx>
#include <vcl/svapp.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <sal/log.hxx>
#include <sfx2/objsh.hxx>

#include <algorithm>

using namespace ::com::sun::star;

using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::osl::MutexGuard;

namespace
{
templatetypename T >
T lcl_getProperty(
    const Sequence< beans::PropertyValue > & rMediaDescriptor,
    const OUString & rPropName )
{
    T aResult;
    if( rMediaDescriptor.hasElements())
    {
        auto pIt = std::find_if(rMediaDescriptor.begin(), rMediaDescriptor.end(),
                                [&rPropName](auto& prop) { return prop.Name == rPropName; });
        if (pIt != rMediaDescriptor.end())
            (*pIt).Value >>= aResult;
    }
    return aResult;
}

void lcl_addStorageToMediaDescriptor(
    Sequence< beans::PropertyValue > & rOutMD,
    const Reference< embed::XStorage > & xStorage )
{
    rOutMD.realloc( rOutMD.getLength() + 1 );
    rOutMD.getArray()[rOutMD.getLength() - 1] = beans::PropertyValue(
        u"Storage"_ustr, -1, uno::Any( 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< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext()).openStream(),
            uno::UNO_QUERY );

        Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create( xContext ) );
        Sequence< uno::Any > aStorageArgs{ uno::Any(xStream),
                                           uno::Any(embed::ElementModes::READWRITE),
                                           uno::Any(rMediaDescriptor) };
        xStorage.set(
            xStorageFact->createInstanceWithArguments( aStorageArgs ), uno::UNO_QUERY_THROW );
    }
    catch(const css::ucb::ContentCreationException&)
    {
        DBG_UNHANDLED_EXCEPTION("chart2");
    }
    catch(const css::ucb::CommandFailedException&)
    {
        DBG_UNHANDLED_EXCEPTION("chart2");
    }

    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, u"FilterName"_ustr ) );

    // if FilterName was found, get Filter from factory
    if( !aFilterName.isEmpty() )
    {
        try
        {
            Reference< container::XNameAccess > xFilterFact(
                m_xContext->getServiceManager()->createInstanceWithContext(
                    u"com.sun.star.document.FilterFactory"_ustr, 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, u"FilterService"_ustr ) );

                if( !aFilterServiceName.isEmpty())
                {
                    xFilter.set(
                        m_xContext->getServiceManager()->createInstanceWithContext(
                            aFilterServiceName, m_xContext ), uno::UNO_QUERY_THROW );
                    SAL_INFO("chart2""Filter found for service " << aFilterServiceName );
                }
            }
        }
        catchconst uno::Exception & )
        {
            DBG_UNHANDLED_EXCEPTION("chart2");
        }
        OSL_ENSURE( xFilter.is(), "Filter not found via factory" );
    }

    // fall-back: create XML-Filter
    if( ! xFilter.is())
    {
        SAL_WARN("chart2""No FilterName passed in MediaDescriptor" );
        xFilter = new XMLFilter(m_xContext);
    }

    return xFilter;
}

// frame::XStorable2

void SAL_CALL ChartModel::storeSelf( const Sequence< beans::PropertyValue >& rMediaDescriptor )
{
    // 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()
{
    std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
    return !m_aResource.isEmpty();
}

OUString SAL_CALL ChartModel::getLocation()
{
    return impl_g_getLocation();
}

sal_Bool SAL_CALL ChartModel::isReadonly()
{
    //@todo guard
    return m_bReadOnly;
}

void SAL_CALL ChartModel::store()
{
    apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager);
    if(!aGuard.startApiCall(true)) //start LongLastingCall
        return//behave passive if already disposed or closed or throw exception @todo?

    OUString aLocation = m_aResource;

    if( aLocation.isEmpty() )
        throw io::IOException( u"no location specified"_ustr, static_cast< ::cppu::OWeakObject* >(this));
    //@todo check whether aLocation is something like private:factory...
    if( m_bReadOnly )
        throw io::IOException( u"document is read only"_ustr, static_cast< ::cppu::OWeakObject* >(this));

    aGuard.clear();

    // store
    impl_store( m_aMediaDescriptor, m_xStorage );
}

void SAL_CALL ChartModel::storeAsURL(
    const OUString& rURL,
    const uno::Sequence< beans::PropertyValue >& rMediaDescriptor )
{
    apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager);
    if(!aGuard.startApiCall(true)) //start LongLastingCall
        return//behave passive if already disposed or closed or throw exception @todo?

    apphelper::MediaDescriptorHelper aMediaDescriptorHelper(rMediaDescriptor);
    const uno::Sequence< beans::PropertyValue >& aReducedMediaDescriptor(
        aMediaDescriptorHelper.getReducedForModel() );

    m_bReadOnly = 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 OUString& rURL,
    const uno::Sequence< beans::PropertyValue >& rMediaDescriptor )
{
    apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager);
    if(!aGuard.startApiCall(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);
    const uno::Sequence< beans::PropertyValue >& aReducedMediaDescriptor(
        aMediaDescriptorHelper.getReducedForModel() );

    if ( rURL == "private:stream" )
    {
        try
        {
            if( m_xContext.is() && aMediaDescriptorHelper.ISSET_OutputStream )
            {
                rtl::Reference< utl::TempFileFastService > xStream = new utl::TempFileFastService;
                Reference< io::XInputStream > xInputStream( xStream->getInputStream());

                Reference< embed::XStorage > xStorage(
                    ::comphelper::OStorageHelper::GetStorageFromStream( xStream, embed::ElementModes::READWRITE, m_xContext ));
                if( xStorage.is())
                {
                    impl_store( aReducedMediaDescriptor, xStorage );

                    xStream->seek( 0 );
                    ::comphelper::OStorageHelper::CopyInputToOutput( xInputStream, aMediaDescriptorHelper.OutputStream );
                }
            }
        }
        catchconst uno::Exception & )
        {
            DBG_UNHANDLED_EXCEPTION("chart2");
        }
    }
    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 );
        }
        catchconst uno::Exception & )
        {
            DBG_UNHANDLED_EXCEPTION("chart2");
        }
    }
    else
    {
        OSL_FAIL( "No filter" );
    }

    setModified( 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() )
        return;

    apphelper::MediaDescriptorHelper aMDHelper(rMediaDescriptor);
    try
    {
        xPropSet->setPropertyValue(
            u"SavedObject"_ustr,
            uno::Any( aMDHelper.HierarchicalDocumentName ) );
    }
    catch ( const uno::Exception& )
    {
    }
}

void ChartModel::insertDefaultChart()
{
    lockControllers();
    createInternalDataProvider( false );
    try
    {
        // create default chart
        rtl::Reference< ::chart::ChartTypeTemplate > 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 = { beans::PropertyValue( u"HasCategories"_ustr, -1, uno::Any( true ),
                                                     beans::PropertyState_DIRECT_VALUE ) };
                }

                rtl::Reference< Diagram > xDiagram( xTemplate->createDiagramByDataSource2( xDataSource, aParam ) );

                setFirstDiagram( xDiagram );

                bool bIsRTL = AllSettings::GetMathLayoutRTL();
                //reverse x axis for rtl charts
                if( bIsRTL )
                    AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) );

                // create and attach legend
                rtl::Reference< Legend > xLegend = new Legend();
                xLegend->setPropertyValue( u"FillStyle"_ustr, uno::Any( drawing::FillStyle_NONE ));
                xLegend->setPropertyValue( u"LineStyle"_ustr, uno::Any( drawing::LineStyle_NONE ));
                xLegend->setPropertyValue( u"LineColor"_ustr, uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) ));  // gray30
                xLegend->setPropertyValue( u"FillColor"_ustr, uno::Any( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10

                if( bIsRTL )
                    xLegend->setPropertyValue( u"AnchorPosition"_ustr, uno::Any( chart2::LegendPosition_LINE_START ));
                if(xDiagram.is())
                {
                    xDiagram->setLegend( xLegend );

                    // set simple 3D look
                    xDiagram->setPropertyValue( u"RightAngledAxes"_ustr, uno::Any( true ));
                    xDiagram->setPropertyValue( u"D3DScenePerspective"_ustr, uno::Any( drawing::ProjectionMode_PARALLEL ));
                    xDiagram->setScheme( ThreeDLookScheme::ThreeDLookScheme_Realistic );

                    //set some new 'defaults' for wall and floor
                    Reference< beans::XPropertySet > xWall( xDiagram->getWall() );
                    if( xWall.is() )
                    {
                        xWall->setPropertyValue( u"LineStyle"_ustr, uno::Any( drawing::LineStyle_SOLID ) );
                        xWall->setPropertyValue( u"FillStyle"_ustr, uno::Any( drawing::FillStyle_NONE ) );
                        xWall->setPropertyValue( u"LineColor"_ustr, uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30
                        xWall->setPropertyValue( u"FillColor"_ustr, uno::Any( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10
                    }
                    Reference< beans::XPropertySet > xFloor( xDiagram->getFloor() );
                    if( xFloor.is() )
                    {
                        xFloor->setPropertyValue( u"LineStyle"_ustr, uno::Any( drawing::LineStyle_NONE ) );
                        xFloor->setPropertyValue( u"FillStyle"_ustr, uno::Any( drawing::FillStyle_SOLID ) );
                        xFloor->setPropertyValue( u"LineColor"_ustr, uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30
                        xFloor->setPropertyValue( u"FillColor"_ustr, uno::Any( static_cast< sal_Int32 >( 0xcccccc ) ) ); // gray20
                    }

                }
            }
            catchconst uno::Exception & )
            {
                DBG_UNHANDLED_EXCEPTION("chart2");
            }
        }
        setIncludeHiddenCells( false );
    }
    catchconst uno::Exception & )
    {
        DBG_UNHANDLED_EXCEPTION("chart2");
    }
    setModified( false );
    unlockControllers();
}

// frame::XLoadable
void SAL_CALL ChartModel::initNew()
{
}

void SAL_CALL ChartModel::load(
    const Sequence< beans::PropertyValue >& rMediaDescriptor )
{
    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 == "StarChart 5.0" ||
                 aMDHelper.FilterName == "StarChart 4.0" ||
                 aMDHelper.FilterName == "StarChart 3.0" ))
            {
                attachResource( aMDHelper.URL, rMediaDescriptor );
                impl_load( rMediaDescriptor, nullptr ); // cannot create a storage from binary streams, but I do not need the storage here anyhow
                m_bReadOnly = true;
                return;
            }

            Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create(m_xContext) );

            if( aMDHelper.ISSET_Stream )
            {
                // convert XStream to XStorage via the storage factory
                Sequence< uno::Any > aStorageArgs{ uno::Any(aMDHelper.Stream),
                                                   // todo: check if stream is read-only
                                                   uno::Any(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{ uno::Any(aMDHelper.InputStream),
                                                   uno::Any(embed::ElementModes::READ) };

                xStorage.set( xStorageFact->createInstanceWithArguments( aStorageArgs ),
                    uno::UNO_QUERY_THROW );
            }
        }

        if( aMDHelper.ISSET_URL )
            aURL = aMDHelper.URL;
    }
    catchconst uno::Exception & )
    {
        DBG_UNHANDLED_EXCEPTION("chart2");
    }

    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( 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( u"Pictures"_ustr,
                                          embed::ElementModes::READ ) );

        if( xGraphicsStorage.is() )
        {
            const uno::Sequence< OUString > aElementNames(
                xGraphicsStorage->getElementNames() );

            for( OUString const & streamName : aElementNames )
            {
                if( xGraphicsStorage->isStreamElement( streamName ) )
                {
                    uno::Reference< io::XStream > xElementStream(
                        xGraphicsStorage->openStreamElement(
                            streamName,
                            embed::ElementModes::READ ) );

                    if( xElementStream.is() )
                    {
                        std::unique_ptr< SvStream > apIStm(
                            ::utl::UcbStreamHelper::CreateStream(
                                xElementStream, true ) );

                        if (apIStm)
                        {
                            SolarMutexGuard aGuard;
                            Graphic aGraphic;
                            if (!GraphicConverter::Import(*apIStm, aGraphic))
                            {
                                m_aGraphicObjectVector.emplace_back(aGraphic );
                            }
                        }
                    }
                }
            }
        }
    }
    catch ( const uno::Exception& )
    {
    }
}

// util::XModifiable
void ChartModel::impl_notifyModifiedListeners()
{
    {
        MutexGuard aGuard( m_aModelMutex );
        m_bUpdateNotificationsPending = false;
    }

    //always notify the view first!
    ChartViewHelper::setViewToDirtyState( this );

    std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
    if( m_aLifeTimeManager.m_aModifyListeners.getLength(aGuard) )
    {
        lang::EventObject aEvent( static_cast< lang::XComponent*>(this) );
        m_aLifeTimeManager.m_aModifyListeners.notifyEach(aGuard, &util::XModifyListener::modified, aEvent);
    }
}

sal_Bool SAL_CALL ChartModel::isModified()
{
    //@todo guard
    return m_bModified;
}

void SAL_CALL ChartModel::setModified( sal_Bool bModified )
{
    // tdf#141914: allow to set *unmodified* when parent does not allow to set modified
    if (bModified)
    {
        // tdf#77007: honor parent's IsEnableSetModified
        // Check it before LifeTimeGuard, to avoid deadlocking solar mutex and this guard
        if (auto pParentShell = SfxObjectShell::GetShellFromComponent(getParent());
            pParentShell && !pParentShell->IsEnableSetModified())
            return;
    }

    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 )
    {
        if (bModified)
            m_bUpdateNotificationsPending = true// Maybe !bModified should reset it?
        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 )
{
    if( m_aLifeTimeManager.impl_isDisposedOrClosed() )
        return//behave passive if already disposed or closed

    std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
    m_aLifeTimeManager.m_aModifyListeners.addInterface( aGuard, xListener );
}

void SAL_CALL ChartModel::removeModifyListener(
    const uno::Reference< util::XModifyListener >& xListener )
{
    if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
        return//behave passive if already disposed or closed

    std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
    m_aLifeTimeManager.m_aModifyListeners.removeInterface( aGuard, xListener );
}

// util::XModifyListener
void SAL_CALL ChartModel::modified( const lang::EventObject& rEvenObject)
{
    uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(rEvenObject.Source, uno::UNO_QUERY);
    if (xPivotTableDataProvider.is())
    {
        lockControllers();
        uno::Reference<chart2::data::XDataProvider> xDataProvider(xPivotTableDataProvider, uno::UNO_QUERY);
        try
        {
            uno::Sequence<beans::PropertyValue> aArguments =
                DataSourceHelper::createArguments(u"PivotChart"_ustr, uno::Sequence<sal_Int32>(), truetruetrue);

            Reference<chart2::data::XDataSource> xDataSource(xDataProvider->createDataSource(aArguments));
            rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = getTypeManager();
            rtl::Reference<Diagram> xDiagram(getFirstChartDiagram());

            Diagram::tTemplateWithServiceName aTemplateAndService = xDiagram->getTemplate(xChartTypeManager);
            aTemplateAndService.xChartTypeTemplate->changeDiagramData(xDiagram, xDataSource, aArguments);
        }
        catch (const uno::Exception &)
        {
            DBG_UNHANDLED_EXCEPTION("chart2");
        }
        unlockControllers();
    }

    if (m_nInLoad == 0)
        setModified(true);
}

// lang::XEventListener (base of util::XModifyListener)
void SAL_CALL ChartModel::disposing( const lang::EventObject& )
{
    // 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 )
{
    attachResource( OUString(), rMediaDescriptor );
    impl_load( rMediaDescriptor, xStorage );
}

void SAL_CALL ChartModel::storeToStorage(
    const Reference< embed::XStorage >& xStorage,
    const Sequence< beans::PropertyValue >& rMediaDescriptor )
{
    impl_store( rMediaDescriptor, xStorage );
}

void SAL_CALL ChartModel::switchToStorage( const Reference< embed::XStorage >& xStorage )
{
    m_xStorage = xStorage;
    impl_notifyStorageChangeListeners();
}

Reference< embed::XStorage > SAL_CALL ChartModel::getDocumentStorage()
{
    return m_xStorage;
}

void ChartModel::impl_notifyStorageChangeListeners()
{
    std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
    if( m_aLifeTimeManager.m_aStorageChangeListeners.getLength(aGuard) )
    {
        m_aLifeTimeManager.m_aStorageChangeListeners.forEach(aGuard,
            [this](const uno::Reference<document::XStorageChangeListener>& l)
            {
                l->notifyStorageChange( static_cast< ::cppu::OWeakObject* >( this ), m_xStorage );
            });
    }
}

void SAL_CALL ChartModel::addStorageChangeListener( const Reference< document::XStorageChangeListener >& xListener )
{
    if( m_aLifeTimeManager.impl_isDisposedOrClosed() )
        return//behave passive if already disposed or closed

    std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
    m_aLifeTimeManager.m_aStorageChangeListeners.addInterface( aGuard, xListener );
}

void SAL_CALL ChartModel::removeStorageChangeListener( const Reference< document::XStorageChangeListener >& xListener )
{
    if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
        return//behave passive if already disposed or closed

    std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
    m_aLifeTimeManager.m_aStorageChangeListeners.removeInterface(aGuard, xListener );
}

//  namespace chart

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=89 H=94 G=91

¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.15Bemerkung:  (vorverarbeitet)  ¤

*Bot Zugriff






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.