LibreOffice Module chart2 (master) 1
ChartModel.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <ChartModel.hxx>
21#include <ChartTypeManager.hxx>
22#include <ChartTypeTemplate.hxx>
23#include <servicenames.hxx>
24#include <DataSource.hxx>
25#include <DataSourceHelper.hxx>
26#include <ChartModelHelper.hxx>
27#include <DisposeHelper.hxx>
30#include <ObjectIdentifier.hxx>
31#include "PageBackground.hxx"
32#include <CloneHelper.hxx>
33#include <NameContainer.hxx>
34#include "UndoManager.hxx"
35#include <ChartView.hxx>
36#include <PopupRequest.hxx>
38#include <RangeHighlighter.hxx>
39#include <Diagram.hxx>
40#include <dumpxmltostring.hxx>
41
42#include <com/sun/star/chart/ChartDataRowSource.hpp>
43#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
44
48
49#include <svl/numformat.hxx>
50#include <svl/numuno.hxx>
51#include <com/sun/star/lang/DisposedException.hpp>
52#include <com/sun/star/view/XSelectionSupplier.hpp>
53#include <com/sun/star/embed/EmbedMapUnits.hpp>
54#include <com/sun/star/embed/Aspects.hpp>
55#include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp>
56#include <com/sun/star/datatransfer/XTransferable.hpp>
57#include <com/sun/star/drawing/XShapes.hpp>
58#include <com/sun/star/document/DocumentProperties.hpp>
59#include <com/sun/star/util/CloseVetoException.hpp>
60#include <com/sun/star/util/XModifyBroadcaster.hpp>
61
62#include <sal/log.hxx>
63#include <utility>
65#include <libxml/xmlwriter.h>
66
67using ::com::sun::star::uno::Sequence;
68using ::com::sun::star::uno::Reference;
69using ::com::sun::star::uno::Any;
70using ::osl::MutexGuard;
71
72using namespace ::com::sun::star;
73using namespace ::apphelper;
74using namespace ::chart::CloneHelper;
75
76namespace
77{
78constexpr OUStringLiteral lcl_aGDIMetaFileMIMEType(
79 u"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"");
80constexpr OUStringLiteral lcl_aGDIMetaFileMIMETypeHighContrast(
81 u"application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"");
82
83} // anonymous namespace
84
85// ChartModel Constructor and Destructor
86
87namespace chart
88{
89
90ChartModel::ChartModel(uno::Reference<uno::XComponentContext > xContext)
91 : m_aLifeTimeManager( this, this )
92 , m_bReadOnly( false )
93 , m_bModified( false )
94 , m_nInLoad(0)
95 , m_bUpdateNotificationsPending(false)
96 , mbTimeBased(false)
97 , m_aControllers( m_aModelMutex )
98 , m_nControllerLockCount(0)
99 , m_xContext(std::move( xContext ))
100 , m_aVisualAreaSize( ChartModelHelper::getDefaultPageSize() )
101 , m_xPageBackground( new PageBackground )
102 , m_xXMLNamespaceMap( new NameContainer() )
103 , mnStart(0)
104 , mnEnd(0)
105{
106 osl_atomic_increment(&m_refCount);
107 {
108 m_xOldModelAgg.set(
109 m_xContext->getServiceManager()->createInstanceWithContext(
111 m_xContext ), uno::UNO_QUERY_THROW );
112 m_xOldModelAgg->setDelegator( *this );
113 }
114
115 {
116 m_xPageBackground->addModifyListener( this );
117 m_xChartTypeManager = new ::chart::ChartTypeManager( m_xContext );
118 }
119 osl_atomic_decrement(&m_refCount);
120}
121
122ChartModel::ChartModel( const ChartModel & rOther )
123 : impl::ChartModel_Base(rOther)
124 , m_aLifeTimeManager( this, this )
125 , m_bReadOnly( rOther.m_bReadOnly )
126 , m_bModified( rOther.m_bModified )
127 , m_nInLoad(0)
128 , m_bUpdateNotificationsPending(false)
129 , mbTimeBased(rOther.mbTimeBased)
130 , m_aResource( rOther.m_aResource )
131 , m_aMediaDescriptor( rOther.m_aMediaDescriptor )
132 , m_aControllers( m_aModelMutex )
133 , m_nControllerLockCount(0)
134 , m_xContext( rOther.m_xContext )
135 // @note: the old model aggregate must not be shared with other models if it
136 // is, you get mutex deadlocks
137 //, m_xOldModelAgg( nullptr ) //rOther.m_xOldModelAgg )
138 // m_xStorage( nullptr ) //rOther.m_xStorage )
139 , m_aVisualAreaSize( rOther.m_aVisualAreaSize )
140 , m_aGraphicObjectVector( rOther.m_aGraphicObjectVector )
141 , m_xDataProvider( rOther.m_xDataProvider )
142 , m_xInternalDataProvider( rOther.m_xInternalDataProvider )
143 , mnStart(rOther.mnStart)
144 , mnEnd(rOther.mnEnd)
145{
146 osl_atomic_increment(&m_refCount);
147 {
148 m_xOldModelAgg.set(
149 m_xContext->getServiceManager()->createInstanceWithContext(
151 m_xContext ), uno::UNO_QUERY_THROW );
152 m_xOldModelAgg->setDelegator( *this );
153
154 Reference< util::XModifyListener > xListener;
155 rtl::Reference< Title > xNewTitle;
156 if ( rOther.m_xTitle )
157 xNewTitle = new Title(*rOther.m_xTitle);
159 if (rOther.m_xDiagram.is())
160 xNewDiagram = new ::chart::Diagram( *rOther.m_xDiagram );
161 rtl::Reference< ::chart::PageBackground > xNewPageBackground = new PageBackground( *rOther.m_xPageBackground );
162 rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager; // does not implement XCloneable
163 rtl::Reference< ::chart::NameContainer > xXMLNamespaceMap = new NameContainer( *rOther.m_xXMLNamespaceMap );
164
165 {
166 MutexGuard aGuard( m_aModelMutex );
167 xListener = this;
168 m_xTitle = xNewTitle;
169 m_xDiagram = xNewDiagram;
170 m_xPageBackground = xNewPageBackground;
171 m_xChartTypeManager = xChartTypeManager;
172 m_xXMLNamespaceMap = xXMLNamespaceMap;
173 }
174
175 ModifyListenerHelper::addListener( xNewTitle, xListener );
176 if( xNewDiagram && xListener)
177 xNewDiagram->addModifyListener( xListener );
178 if( xNewPageBackground && xListener)
179 xNewPageBackground->addModifyListener( xListener );
180 xListener.clear();
181 }
182 osl_atomic_decrement(&m_refCount);
183}
184
185ChartModel::~ChartModel()
186{
187 if( m_xOldModelAgg.is())
188 m_xOldModelAgg->setDelegator( nullptr );
189}
190
191void SAL_CALL ChartModel::initialize( const Sequence< Any >& /*rArguments*/ )
192{
193 //#i113722# avoid duplicate creation
194
195 //maybe additional todo?:
196 //support argument "EmbeddedObject"?
197 //support argument "EmbeddedScriptSupport"?
198 //support argument "DocumentRecoverySupport"?
199}
200
201ChartView* ChartModel::getChartView() const
202{
203 return mxChartView.get();
204}
205
206// private methods
207
208OUString ChartModel::impl_g_getLocation()
209{
210
211 LifeTimeGuard aGuard(m_aLifeTimeManager);
212 if(!aGuard.startApiCall())
213 return OUString(); //behave passive if already disposed or closed or throw exception @todo?
214 //mutex is acquired
215 return m_aResource;
216}
217
218bool ChartModel::impl_isControllerConnected( const uno::Reference< frame::XController >& xController )
219{
220 try
221 {
222 std::vector< uno::Reference<uno::XInterface> > aSeq = m_aControllers.getElements();
223 for( const auto & r : aSeq )
224 {
225 if( r == xController )
226 return true;
227 }
228 }
229 catch (const uno::Exception&)
230 {
231 }
232 return false;
233}
234
235uno::Reference< frame::XController > ChartModel::impl_getCurrentController()
236{
237 //@todo? hold only weak references to controllers
238
239 // get the last active controller of this model
240 if( m_xCurrentController.is() )
241 return m_xCurrentController;
242
243 // get the first controller of this model
244 if( m_aControllers.getLength() )
245 {
246 uno::Reference<uno::XInterface> xI = m_aControllers.getInterface(0);
247 return uno::Reference<frame::XController>( xI, uno::UNO_QUERY );
248 }
249
250 //return nothing if no controllers are connected at all
251 return uno::Reference< frame::XController > ();
252}
253
254void ChartModel::impl_notifyCloseListeners()
255{
256 std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
257 if( m_aLifeTimeManager.m_aCloseListeners.getLength(aGuard) )
258 {
259 lang::EventObject aEvent( static_cast< lang::XComponent*>(this) );
260 m_aLifeTimeManager.m_aCloseListeners.notifyEach(aGuard, &util::XCloseListener::notifyClosing, aEvent);
261 }
262}
263
264void ChartModel::impl_adjustAdditionalShapesPositionAndSize( const awt::Size& aVisualAreaSize )
265{
266 uno::Reference< beans::XPropertySet > xProperties( static_cast< ::cppu::OWeakObject* >( this ), uno::UNO_QUERY );
267 if ( !xProperties.is() )
268 return;
269
270 uno::Reference< drawing::XShapes > xShapes;
271 xProperties->getPropertyValue( "AdditionalShapes" ) >>= xShapes;
272 if ( !xShapes.is() )
273 return;
274
275 sal_Int32 nCount = xShapes->getCount();
276 for ( sal_Int32 i = 0; i < nCount; ++i )
277 {
278 Reference< drawing::XShape > xShape;
279 if ( xShapes->getByIndex( i ) >>= xShape )
280 {
281 if ( xShape.is() )
282 {
283 awt::Point aPos( xShape->getPosition() );
284 awt::Size aSize( xShape->getSize() );
285
286 double fWidth = static_cast< double >( aVisualAreaSize.Width ) / m_aVisualAreaSize.Width;
287 double fHeight = static_cast< double >( aVisualAreaSize.Height ) / m_aVisualAreaSize.Height;
288
289 aPos.X = static_cast< tools::Long >( aPos.X * fWidth );
290 aPos.Y = static_cast< tools::Long >( aPos.Y * fHeight );
291 aSize.Width = static_cast< tools::Long >( aSize.Width * fWidth );
292 aSize.Height = static_cast< tools::Long >( aSize.Height * fHeight );
293
294 xShape->setPosition( aPos );
295 xShape->setSize( aSize );
296 }
297 }
298 }
299}
300
301// lang::XServiceInfo
302
303OUString SAL_CALL ChartModel::getImplementationName()
304{
306}
307
308sal_Bool SAL_CALL ChartModel::supportsService( const OUString& rServiceName )
309{
310 return cppu::supportsService(this, rServiceName);
311}
312
313css::uno::Sequence< OUString > SAL_CALL ChartModel::getSupportedServiceNames()
314{
315 return {
317 "com.sun.star.document.OfficeDocument",
318 "com.sun.star.chart.ChartDocument"
319 };
320}
321
322// frame::XModel (required interface)
323
324sal_Bool SAL_CALL ChartModel::attachResource( const OUString& rURL
325 , const uno::Sequence< beans::PropertyValue >& rMediaDescriptor )
326{
327 /*
328 The method attachResource() is used by the frame loader implementations
329 to inform the model about its URL and MediaDescriptor.
330 */
331
332 LifeTimeGuard aGuard(m_aLifeTimeManager);
333 if(!aGuard.startApiCall())
334 return false; //behave passive if already disposed or closed or throw exception @todo?
335 //mutex is acquired
336
337 if(!m_aResource.isEmpty())//we have a resource already //@todo? or is setting a new resource allowed?
338 return false;
339 m_aResource = rURL;
340 m_aMediaDescriptor = rMediaDescriptor;
341
342 //@todo ? check rURL ??
343 //@todo ? evaluate m_aMediaDescriptor;
344 //@todo ? ... ??? --> nothing, this method is only for setting information
345
346 return true;
347}
348
349OUString SAL_CALL ChartModel::getURL()
350{
351 return impl_g_getLocation();
352}
353
354uno::Sequence< beans::PropertyValue > SAL_CALL ChartModel::getArgs()
355{
356 /*
357 The method getArgs() returns a sequence of property values
358 that report the resource description according to com.sun.star.document.MediaDescriptor,
359 specified on loading or saving with storeAsURL.
360 */
361
362 LifeTimeGuard aGuard(m_aLifeTimeManager);
363 if(!aGuard.startApiCall())
364 return uno::Sequence< beans::PropertyValue >(); //behave passive if already disposed or closed or throw exception @todo?
365 //mutex is acquired
366
367 return m_aMediaDescriptor;
368}
369
370void SAL_CALL ChartModel::connectController( const uno::Reference< frame::XController >& xController )
371{
372 //@todo? this method is declared as oneway -> ...?
373
374 LifeTimeGuard aGuard(m_aLifeTimeManager);
375 if(!aGuard.startApiCall())
376 return ; //behave passive if already disposed or closed
377 //mutex is acquired
378
379 //--add controller
380 m_aControllers.addInterface(xController);
381}
382
383void SAL_CALL ChartModel::disconnectController( const uno::Reference< frame::XController >& xController )
384{
385 //@todo? this method is declared as oneway -> ...?
386
387 LifeTimeGuard aGuard(m_aLifeTimeManager);
388 if(!aGuard.startApiCall())
389 return; //behave passive if already disposed or closed
390
391 //--remove controller
392 m_aControllers.removeInterface(xController);
393
394 //case: current controller is disconnected:
395 if( m_xCurrentController == xController )
396 m_xCurrentController.clear();
397
398 if (m_xRangeHighlighter)
399 {
400 m_xRangeHighlighter->dispose();
401 m_xRangeHighlighter.clear();
402 }
403 DisposeHelper::DisposeAndClear(m_xPopupRequest);
404}
405
406void SAL_CALL ChartModel::lockControllers()
407{
408 /*
409 suspends some notifications to the controllers which are used for display updates.
410
411 The calls to lockControllers() and unlockControllers() may be nested
412 and even overlapping, but they must be in pairs. While there is at least one lock
413 remaining, some notifications for display updates are not broadcasted.
414 */
415
416 //@todo? this method is declared as oneway -> ...?
417
418 LifeTimeGuard aGuard(m_aLifeTimeManager);
419 if(!aGuard.startApiCall())
420 return; //behave passive if already disposed or closed or throw exception @todo?
421 ++m_nControllerLockCount;
422}
423
424void SAL_CALL ChartModel::unlockControllers()
425{
426 /*
427 resumes the notifications which were suspended by lockControllers() .
428
429 The calls to lockControllers() and unlockControllers() may be nested
430 and even overlapping, but they must be in pairs. While there is at least one lock
431 remaining, some notifications for display updates are not broadcasted.
432 */
433
434 //@todo? this method is declared as oneway -> ...?
435
436 LifeTimeGuard aGuard(m_aLifeTimeManager);
437 if(!aGuard.startApiCall())
438 return; //behave passive if already disposed or closed or throw exception @todo?
439 if( m_nControllerLockCount == 0 )
440 {
441 SAL_WARN("chart2", "ChartModel: unlockControllers called with m_nControllerLockCount == 0" );
442 return;
443 }
444 --m_nControllerLockCount;
445 if( m_nControllerLockCount == 0 && m_bUpdateNotificationsPending )
446 {
447 aGuard.clear();
448 impl_notifyModifiedListeners();
449 }
450}
451
452sal_Bool SAL_CALL ChartModel::hasControllersLocked()
453{
454 LifeTimeGuard aGuard(m_aLifeTimeManager);
455 if(!aGuard.startApiCall())
456 return false; //behave passive if already disposed or closed or throw exception @todo?
457 return ( m_nControllerLockCount != 0 ) ;
458}
459
460uno::Reference< frame::XController > SAL_CALL ChartModel::getCurrentController()
461{
462 LifeTimeGuard aGuard(m_aLifeTimeManager);
463 if(!aGuard.startApiCall())
464 throw lang::DisposedException(
465 "getCurrentController was called on an already disposed or closed model",
466 static_cast< ::cppu::OWeakObject* >(this) );
467
468 return impl_getCurrentController();
469}
470
471void SAL_CALL ChartModel::setCurrentController( const uno::Reference< frame::XController >& xController )
472{
473 LifeTimeGuard aGuard(m_aLifeTimeManager);
474 if(!aGuard.startApiCall())
475 throw lang::DisposedException(
476 "setCurrentController was called on an already disposed or closed model",
477 static_cast< ::cppu::OWeakObject* >(this) );
478
479 //OSL_ENSURE( impl_isControllerConnected(xController), "setCurrentController is called with a Controller which is not connected" );
480 if(!impl_isControllerConnected(xController))
481 throw container::NoSuchElementException(
482 "setCurrentController is called with a Controller which is not connected",
483 static_cast< ::cppu::OWeakObject* >(this) );
484
485 m_xCurrentController = xController;
486
487 if (m_xRangeHighlighter)
488 {
489 m_xRangeHighlighter->dispose();
490 m_xRangeHighlighter.clear();
491 }
492 DisposeHelper::DisposeAndClear(m_xPopupRequest);
493}
494
495uno::Reference< uno::XInterface > SAL_CALL ChartModel::getCurrentSelection()
496{
497 LifeTimeGuard aGuard(m_aLifeTimeManager);
498 if(!aGuard.startApiCall())
499 throw lang::DisposedException(
500 "getCurrentSelection was called on an already disposed or closed model",
501 static_cast< ::cppu::OWeakObject* >(this) );
502
503 uno::Reference< uno::XInterface > xReturn;
504 uno::Reference< frame::XController > xController = impl_getCurrentController();
505
506 aGuard.clear();
507 if( xController.is() )
508 {
509 uno::Reference< view::XSelectionSupplier > xSelectionSupl( xController, uno::UNO_QUERY );
510 if ( xSelectionSupl.is() )
511 {
512 uno::Any aSel = xSelectionSupl->getSelection();
513 OUString aObjectCID;
514 if( aSel >>= aObjectCID )
515 xReturn.set( ObjectIdentifier::getObjectPropertySet( aObjectCID, this));
516 }
517 }
518 return xReturn;
519}
520
521// lang::XComponent (base of XModel)
522void SAL_CALL ChartModel::dispose()
523{
524 Reference< XInterface > xKeepAlive( *this );
525
526 //This object should release all resources and references in the
527 //easiest possible manner
528 //This object must notify all registered listeners using the method
529 //<member>XEventListener::disposing</member>
530
531 //hold no mutex
532 if( !m_aLifeTimeManager.dispose() )
533 return;
534
535 //--release all resources and references
537
538 if ( m_xDiagram.is() )
539 m_xDiagram->removeModifyListener( this );
540
541 if ( m_xDataProvider.is() )
542 {
543 Reference<util::XModifyBroadcaster> xModifyBroadcaster( m_xDataProvider, uno::UNO_QUERY );
544 if ( xModifyBroadcaster.is() )
545 xModifyBroadcaster->removeModifyListener( this );
546 }
547
548 m_xDataProvider.clear();
549 m_xInternalDataProvider.clear();
550 m_xNumberFormatsSupplier.clear();
551 m_xOwnNumberFormatsSupplier.clear();
552 m_xChartTypeManager.clear();
553 m_xDiagram.clear();
554 m_xTitle.clear();
555 m_xPageBackground.clear();
556 m_xXMLNamespaceMap.clear();
557
558 m_xStorage.clear();
559 // just clear, don't dispose - we're not the owner
560
561 if ( m_pUndoManager.is() )
562 m_pUndoManager->disposing();
563 m_pUndoManager.clear();
564 // that's important, since the UndoManager implementation delegates its ref counting to ourself.
565
566 if( m_xOldModelAgg.is()) // #i120828#, to release cyclic reference to ChartModel object
567 m_xOldModelAgg->setDelegator( nullptr );
568
569 m_aControllers.disposeAndClear( lang::EventObject( static_cast< cppu::OWeakObject * >( this )));
570 m_xCurrentController.clear();
571
572 if (m_xRangeHighlighter)
573 {
574 m_xRangeHighlighter->dispose();
575 m_xRangeHighlighter.clear();
576 }
577 DisposeHelper::DisposeAndClear(m_xPopupRequest);
578
579 if( m_xOldModelAgg.is())
580 m_xOldModelAgg->setDelegator( nullptr );
581}
582
583void SAL_CALL ChartModel::addEventListener( const uno::Reference< lang::XEventListener > & xListener )
584{
585 if( m_aLifeTimeManager.impl_isDisposedOrClosed() )
586 return; //behave passive if already disposed or closed
587
588 std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
589 m_aLifeTimeManager.m_aEventListeners.addInterface( aGuard, xListener );
590}
591
592void SAL_CALL ChartModel::removeEventListener( const uno::Reference< lang::XEventListener > & xListener )
593{
594 if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
595 return; //behave passive if already disposed or closed
596
597 std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
598 m_aLifeTimeManager.m_aEventListeners.removeInterface( aGuard, xListener );
599}
600
601// util::XCloseBroadcaster (base of XCloseable)
602void SAL_CALL ChartModel::addCloseListener( const uno::Reference< util::XCloseListener > & xListener )
603{
604 m_aLifeTimeManager.g_addCloseListener( xListener );
605}
606
607void SAL_CALL ChartModel::removeCloseListener( const uno::Reference< util::XCloseListener > & xListener )
608{
609 if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
610 return; //behave passive if already disposed or closed
611
612 std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
613 m_aLifeTimeManager.m_aCloseListeners.removeInterface( aGuard, xListener );
614}
615
616// util::XCloseable
617void SAL_CALL ChartModel::close( sal_Bool bDeliverOwnership )
618{
619 //hold no mutex
620
621 if( !m_aLifeTimeManager.g_close_startTryClose( bDeliverOwnership ) )
622 return;
623 //no mutex is acquired
624
625 // At the end of this method may we must dispose ourself ...
626 // and may nobody from outside hold a reference to us ...
627 // then it's a good idea to do that by ourself.
628 uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) );
629
630 //the listeners have had no veto
631 //check whether we self can close
632 {
633 util::CloseVetoException aVetoException(
634 "the model itself could not be closed",
635 static_cast< ::cppu::OWeakObject* >(this) );
636
637 m_aLifeTimeManager.g_close_isNeedToCancelLongLastingCalls( bDeliverOwnership, aVetoException );
638 }
639 m_aLifeTimeManager.g_close_endTryClose_doClose();
640
641 // BM @todo: is it ok to call the listeners here?
642 impl_notifyCloseListeners();
643}
644
645// lang::XTypeProvider
646uno::Sequence< uno::Type > SAL_CALL ChartModel::getTypes()
647{
648 uno::Reference< lang::XTypeProvider > xAggTypeProvider;
649 if( (m_xOldModelAgg->queryAggregation( cppu::UnoType<decltype(xAggTypeProvider)>::get()) >>= xAggTypeProvider)
650 && xAggTypeProvider.is())
651 {
653 impl::ChartModel_Base::getTypes(),
654 xAggTypeProvider->getTypes());
655 }
656
657 return impl::ChartModel_Base::getTypes();
658}
659
660// document::XDocumentPropertiesSupplier
661uno::Reference< document::XDocumentProperties > SAL_CALL
662 ChartModel::getDocumentProperties()
663{
664 ::osl::MutexGuard aGuard( m_aModelMutex );
665 if ( !m_xDocumentProperties.is() )
666 {
667 m_xDocumentProperties.set( document::DocumentProperties::create( ::comphelper::getProcessComponentContext() ) );
668 }
669 return m_xDocumentProperties;
670}
671
672// document::XDocumentPropertiesSupplier
673Reference< document::XUndoManager > SAL_CALL ChartModel::getUndoManager( )
674{
675 ::osl::MutexGuard aGuard( m_aModelMutex );
676 if ( !m_pUndoManager.is() )
677 m_pUndoManager.set( new UndoManager( *this, m_aModelMutex ) );
678 return m_pUndoManager;
679}
680
681// chart2::XChartDocument
682
683uno::Reference< chart2::XDiagram > SAL_CALL ChartModel::getFirstDiagram()
684{
685 MutexGuard aGuard( m_aModelMutex );
686 return m_xDiagram;
687}
688
689void SAL_CALL ChartModel::setFirstDiagram( const uno::Reference< chart2::XDiagram >& xDiagram )
690{
692 Reference< util::XModifyListener > xListener;
693 {
694 MutexGuard aGuard( m_aModelMutex );
695 if( xDiagram.get() == m_xDiagram.get() )
696 return;
697 xOldDiagram = m_xDiagram;
698 assert(!xDiagram || dynamic_cast<::chart::Diagram*>(xDiagram.get()));
699 m_xDiagram = dynamic_cast<::chart::Diagram*>(xDiagram.get());
700 xListener = this;
701 }
702 //don't keep the mutex locked while calling out
703 if( xOldDiagram && xListener )
704 xOldDiagram->removeModifyListener( xListener );
705 ModifyListenerHelper::addListener( xDiagram, xListener );
706 setModified( true );
707}
708
709Reference< chart2::data::XDataSource > ChartModel::impl_createDefaultData()
710{
711 Reference< chart2::data::XDataSource > xDataSource;
712 if( hasInternalDataProvider() )
713 {
714 //init internal dataprovider
715 {
716 beans::NamedValue aParam( "CreateDefaultData" ,uno::Any(true) );
717 uno::Sequence< uno::Any > aArgs{ uno::Any(aParam) };
718 m_xInternalDataProvider->initialize(aArgs);
719 }
720 //create data
721 uno::Sequence<beans::PropertyValue> aArgs( comphelper::InitPropertySequence({
722 { "CellRangeRepresentation", uno::Any( OUString("all") ) },
723 { "HasCategories", uno::Any( true ) },
724 { "FirstCellAsLabel", uno::Any( true ) },
725 { "DataRowSource", uno::Any( css::chart::ChartDataRowSource_COLUMNS ) }
726 }));
727 xDataSource = m_xInternalDataProvider->createDataSource( aArgs );
728 }
729 return xDataSource;
730}
731
732void SAL_CALL ChartModel::createInternalDataProvider( sal_Bool bCloneExistingData )
733{
734 // don't lock the mutex, because this call calls out to code that tries to
735 // lock the solar mutex. On the other hand, a paint locks the solar mutex
736 // and calls to the model lock the model's mutex => deadlock
737 // @todo: lock a separate mutex in the InternalData class
738 if( !hasInternalDataProvider() )
739 {
740 if( bCloneExistingData )
741 m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider( this, true );
742 else
743 m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider( nullptr, true );
744 m_xDataProvider.set( m_xInternalDataProvider );
745 }
746 setModified( true );
747}
748
749void ChartModel::removeDataProviders()
750{
751 if (m_xInternalDataProvider.is())
752 m_xInternalDataProvider.clear();
753 if (m_xDataProvider.is())
754 m_xDataProvider.clear();
755}
756
757void ChartModel::dumpAsXml(xmlTextWriterPtr pWriter) const
758{
759 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ChartModel"));
760 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
761
762 if (mxChartView.is())
763 {
764 mxChartView->dumpAsXml(pWriter);
765 }
766
767 (void)xmlTextWriterEndElement(pWriter);
768}
769
770sal_Bool SAL_CALL ChartModel::hasInternalDataProvider()
771{
772 return m_xDataProvider.is() && m_xInternalDataProvider.is();
773}
774
775uno::Reference< chart2::data::XDataProvider > SAL_CALL ChartModel::getDataProvider()
776{
777 MutexGuard aGuard( m_aModelMutex );
778 return m_xDataProvider;
779}
780
781// ____ XDataReceiver ____
782
783void SAL_CALL ChartModel::attachDataProvider( const uno::Reference< chart2::data::XDataProvider >& xDataProvider )
784{
785 {
786 MutexGuard aGuard( m_aModelMutex );
787 uno::Reference< beans::XPropertySet > xProp( xDataProvider, uno::UNO_QUERY );
788 if( xProp.is() )
789 {
790 try
791 {
792 bool bIncludeHiddenCells = ChartModelHelper::isIncludeHiddenCells( this );
793 xProp->setPropertyValue("IncludeHiddenCells", uno::Any(bIncludeHiddenCells));
794 }
795 catch (const beans::UnknownPropertyException&)
796 {
797 }
798 }
799
800 uno::Reference<util::XModifyBroadcaster> xModifyBroadcaster(xDataProvider, uno::UNO_QUERY);
801 if (xModifyBroadcaster.is())
802 {
803 xModifyBroadcaster->addModifyListener(this);
804 }
805
806 m_xDataProvider.set( xDataProvider );
807 m_xInternalDataProvider.clear();
808
809 //the numberformatter is kept independent of the data provider!
810 }
811 setModified( true );
812}
813
814void SAL_CALL ChartModel::attachNumberFormatsSupplier( const uno::Reference< util::XNumberFormatsSupplier >& xNewSupplier )
815{
816 {
817 MutexGuard aGuard( m_aModelMutex );
818 if( xNewSupplier == m_xNumberFormatsSupplier )
819 return;
820 if( xNewSupplier == uno::Reference<XNumberFormatsSupplier>(m_xOwnNumberFormatsSupplier) )
821 return;
822 if( m_xOwnNumberFormatsSupplier.is() && xNewSupplier.is() )
823 {
824 //@todo
825 //merge missing numberformats from own to new formatter
826 }
827 else if( !xNewSupplier.is() )
828 {
829 if( m_xNumberFormatsSupplier.is() )
830 {
831 //@todo
832 //merge missing numberformats from old numberformatter to own numberformatter
833 //create own numberformatter if necessary
834 }
835 }
836
837 m_xNumberFormatsSupplier.set( xNewSupplier );
838 m_xOwnNumberFormatsSupplier.clear();
839 }
840 setModified( true );
841}
842
843void SAL_CALL ChartModel::setArguments( const Sequence< beans::PropertyValue >& aArguments )
844{
845 {
846 MutexGuard aGuard( m_aModelMutex );
847 if( !m_xDataProvider.is() )
848 return;
849 lockControllers();
850
851 try
852 {
853 Reference< chart2::data::XDataSource > xDataSource( m_xDataProvider->createDataSource( aArguments ) );
854 if( xDataSource.is() )
855 {
856 rtl::Reference< Diagram > xDia = getFirstChartDiagram();
857 if( !xDia.is() )
858 {
859 rtl::Reference< ::chart::ChartTypeTemplate > xTemplate( impl_createDefaultChartTypeTemplate() );
860 if( xTemplate.is())
861 setFirstDiagram( xTemplate->createDiagramByDataSource( xDataSource, aArguments ) );
862 }
863 else
864 xDia->setDiagramData( xDataSource, aArguments );
865 }
866 }
867 catch (const lang::IllegalArgumentException&)
868 {
869 throw;
870 }
871 catch (const uno::Exception&)
872 {
873 DBG_UNHANDLED_EXCEPTION("chart2");
874 }
875 unlockControllers();
876 }
877 setModified( true );
878}
879
880Sequence< OUString > SAL_CALL ChartModel::getUsedRangeRepresentations()
881{
882 return DataSourceHelper::getUsedDataRanges( this );
883}
884
885Reference< chart2::data::XDataSource > SAL_CALL ChartModel::getUsedData()
886{
887 return DataSourceHelper::getUsedData( *this );
888}
889
890Reference< chart2::data::XRangeHighlighter > SAL_CALL ChartModel::getRangeHighlighter()
891{
892 if( ! m_xRangeHighlighter.is())
893 m_xRangeHighlighter = new RangeHighlighter( this );
894 return m_xRangeHighlighter;
895}
896
897Reference<awt::XRequestCallback> SAL_CALL ChartModel::getPopupRequest()
898{
899 if (!m_xPopupRequest.is())
900 m_xPopupRequest.set(new PopupRequest);
901 return m_xPopupRequest;
902}
903
904rtl::Reference< ::chart::ChartTypeTemplate > ChartModel::impl_createDefaultChartTypeTemplate()
905{
907 if( m_xChartTypeManager.is() )
908 xTemplate = m_xChartTypeManager->createTemplate( "com.sun.star.chart2.template.Column" );
909 return xTemplate;
910}
911
912void SAL_CALL ChartModel::setChartTypeManager( const uno::Reference< chart2::XChartTypeManager >& xNewManager )
913{
914 {
915 MutexGuard aGuard( m_aModelMutex );
916 m_xChartTypeManager = dynamic_cast<::chart::ChartTypeManager*>(xNewManager.get());
917 assert(!xNewManager || m_xChartTypeManager);
918 }
919 setModified( true );
920}
921
922uno::Reference< chart2::XChartTypeManager > SAL_CALL ChartModel::getChartTypeManager()
923{
924 MutexGuard aGuard( m_aModelMutex );
925 return m_xChartTypeManager;
926}
927
928uno::Reference< beans::XPropertySet > SAL_CALL ChartModel::getPageBackground()
929{
930 MutexGuard aGuard( m_aModelMutex );
931 return m_xPageBackground;
932}
933
934void SAL_CALL ChartModel::createDefaultChart()
935{
936 insertDefaultChart();
937}
938
939// ____ XTitled ____
940uno::Reference< chart2::XTitle > SAL_CALL ChartModel::getTitleObject()
941{
942 MutexGuard aGuard( m_aModelMutex );
943 return m_xTitle;
944}
945
946rtl::Reference< Title > ChartModel::getTitleObject2() const
947{
948 MutexGuard aGuard( m_aModelMutex );
949 return m_xTitle;
950}
951
952void SAL_CALL ChartModel::setTitleObject( const uno::Reference< chart2::XTitle >& xNewTitle )
953{
954 rtl::Reference<Title> xTitle = dynamic_cast<Title*>(xNewTitle.get());
955 assert(!xNewTitle || xTitle);
956 setTitleObject(xTitle);
957}
958
959void ChartModel::setTitleObject( const rtl::Reference< Title >& xTitle )
960{
961 {
962 MutexGuard aGuard( m_aModelMutex );
963 if( m_xTitle.is() )
964 ModifyListenerHelper::removeListener( m_xTitle, this );
965 m_xTitle = xTitle;
966 ModifyListenerHelper::addListener( m_xTitle, this );
967 }
968 setModified( true );
969}
970
971// ____ XInterface (for old API wrapper) ____
972uno::Any SAL_CALL ChartModel::queryInterface( const uno::Type& aType )
973{
974 uno::Any aResult( impl::ChartModel_Base::queryInterface( aType ));
975
976 if( ! aResult.hasValue())
977 {
978 // try old API wrapper
979 try
980 {
981 if( m_xOldModelAgg.is())
982 aResult = m_xOldModelAgg->queryAggregation( aType );
983 }
984 catch (const uno::Exception&)
985 {
986 DBG_UNHANDLED_EXCEPTION("chart2");
987 }
988 }
989
990 return aResult;
991}
992
993// ____ XCloneable ____
994Reference< util::XCloneable > SAL_CALL ChartModel::createClone()
995{
996 return Reference< util::XCloneable >( new ChartModel( *this ));
997}
998
999// ____ XVisualObject ____
1000void SAL_CALL ChartModel::setVisualAreaSize( ::sal_Int64 nAspect, const awt::Size& aSize )
1001{
1002 if( nAspect == embed::Aspects::MSOLE_CONTENT )
1003 {
1004 ControllerLockGuard aLockGuard( *this );
1005 bool bChanged =
1006 (m_aVisualAreaSize.Width != aSize.Width ||
1007 m_aVisualAreaSize.Height != aSize.Height);
1008
1009 // #i12587# support for shapes in chart
1010 if ( bChanged )
1011 {
1012 impl_adjustAdditionalShapesPositionAndSize( aSize );
1013 }
1014
1015 m_aVisualAreaSize = aSize;
1016 if( bChanged )
1017 setModified( true );
1018 }
1019 else
1020 {
1021 OSL_FAIL( "setVisualAreaSize: Aspect not implemented yet.");
1022 }
1023}
1024
1025awt::Size SAL_CALL ChartModel::getVisualAreaSize( ::sal_Int64 nAspect )
1026{
1027 OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT,
1028 "No aspects other than content are supported" );
1029 // other possible aspects are MSOLE_THUMBNAIL, MSOLE_ICON and MSOLE_DOCPRINT
1030
1031 return m_aVisualAreaSize;
1032}
1033
1034embed::VisualRepresentation SAL_CALL ChartModel::getPreferredVisualRepresentation( ::sal_Int64 nAspect )
1035{
1036 OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT,
1037 "No aspects other than content are supported" );
1038
1039 embed::VisualRepresentation aResult;
1040
1041 try
1042 {
1043 Sequence< sal_Int8 > aMetafile;
1044
1045 //get view from old api wrapper
1046 Reference< datatransfer::XTransferable > xTransferable(
1047 createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY );
1048 if( xTransferable.is() )
1049 {
1050 datatransfer::DataFlavor aDataFlavor( lcl_aGDIMetaFileMIMEType,
1051 "GDIMetaFile",
1052 cppu::UnoType<uno::Sequence< sal_Int8 >>::get() );
1053
1054 uno::Any aData( xTransferable->getTransferData( aDataFlavor ) );
1055 aData >>= aMetafile;
1056 }
1057
1058 aResult.Flavor.MimeType = lcl_aGDIMetaFileMIMEType;
1059 aResult.Flavor.DataType = cppu::UnoType<decltype(aMetafile)>::get();
1060
1061 aResult.Data <<= aMetafile;
1062 }
1063 catch (const uno::Exception&)
1064 {
1065 DBG_UNHANDLED_EXCEPTION("chart2");
1066 }
1067
1068 return aResult;
1069}
1070
1071::sal_Int32 SAL_CALL ChartModel::getMapUnit( ::sal_Int64 nAspect )
1072{
1073 OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT,
1074 "No aspects other than content are supported" );
1075 return embed::EmbedMapUnits::ONE_100TH_MM;
1076}
1077
1078// ____ datatransfer::XTransferable ____
1079uno::Any SAL_CALL ChartModel::getTransferData( const datatransfer::DataFlavor& aFlavor )
1080{
1081 uno::Any aResult;
1082 if( !isDataFlavorSupported( aFlavor ) )
1083 throw datatransfer::UnsupportedFlavorException(
1084 aFlavor.MimeType, static_cast< ::cppu::OWeakObject* >( this ));
1085
1086 try
1087 {
1088 //get view from old api wrapper
1089 Reference< datatransfer::XTransferable > xTransferable(
1090 createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY );
1091 if( xTransferable.is() &&
1092 xTransferable->isDataFlavorSupported( aFlavor ))
1093 {
1094 aResult = xTransferable->getTransferData( aFlavor );
1095 }
1096 }
1097 catch (const uno::Exception&)
1098 {
1099 DBG_UNHANDLED_EXCEPTION("chart2");
1100 }
1101
1102 return aResult;
1103}
1104
1105Sequence< datatransfer::DataFlavor > SAL_CALL ChartModel::getTransferDataFlavors()
1106{
1107 return { datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast,
1108 "GDIMetaFile",
1109 cppu::UnoType<uno::Sequence< sal_Int8 >>::get() ) };
1110}
1111
1112sal_Bool SAL_CALL ChartModel::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
1113{
1114 return aFlavor.MimeType == lcl_aGDIMetaFileMIMETypeHighContrast;
1115}
1116
1117namespace
1118{
1119enum eServiceType
1120{
1121 SERVICE_DASH_TABLE,
1122 SERVICE_GRADIENT_TABLE,
1123 SERVICE_HATCH_TABLE,
1124 SERVICE_BITMAP_TABLE,
1125 SERVICE_TRANSP_GRADIENT_TABLE,
1126 SERVICE_MARKER_TABLE,
1127 SERVICE_NAMESPACE_MAP
1128};
1129
1130typedef std::map< OUString, enum eServiceType > tServiceNameMap;
1131
1132tServiceNameMap & lcl_getStaticServiceNameMap()
1133{
1134 static tServiceNameMap aServiceNameMap{
1135 {"com.sun.star.drawing.DashTable", SERVICE_DASH_TABLE},
1136 {"com.sun.star.drawing.GradientTable", SERVICE_GRADIENT_TABLE},
1137 {"com.sun.star.drawing.HatchTable", SERVICE_HATCH_TABLE},
1138 {"com.sun.star.drawing.BitmapTable", SERVICE_BITMAP_TABLE},
1139 {"com.sun.star.drawing.TransparencyGradientTable", SERVICE_TRANSP_GRADIENT_TABLE},
1140 {"com.sun.star.drawing.MarkerTable", SERVICE_MARKER_TABLE},
1141 {"com.sun.star.xml.NamespaceMap", SERVICE_NAMESPACE_MAP}};
1142 return aServiceNameMap;
1143}
1144}
1145// ____ XMultiServiceFactory ____
1146Reference< uno::XInterface > SAL_CALL ChartModel::createInstance( const OUString& rServiceSpecifier )
1147{
1148 tServiceNameMap & rMap = lcl_getStaticServiceNameMap();
1149
1150 tServiceNameMap::const_iterator aIt( rMap.find( rServiceSpecifier ));
1151 if( aIt != rMap.end())
1152 {
1153 switch( (*aIt).second )
1154 {
1155 case SERVICE_DASH_TABLE:
1156 case SERVICE_GRADIENT_TABLE:
1157 case SERVICE_HATCH_TABLE:
1158 case SERVICE_BITMAP_TABLE:
1159 case SERVICE_TRANSP_GRADIENT_TABLE:
1160 case SERVICE_MARKER_TABLE:
1161 {
1162 if(!mxChartView.is())
1163 {
1164 mxChartView = new ChartView( m_xContext, *this);
1165 }
1166 return mxChartView->createInstance( rServiceSpecifier );
1167 }
1168 break;
1169 case SERVICE_NAMESPACE_MAP:
1170 return static_cast<cppu::OWeakObject*>(m_xXMLNamespaceMap.get());
1171 }
1172 }
1173 else if(rServiceSpecifier == CHART_VIEW_SERVICE_NAME)
1174 {
1175 if(!mxChartView.is())
1176 {
1177 mxChartView = new ChartView( m_xContext, *this);
1178 }
1179
1180 return static_cast< ::cppu::OWeakObject* >( mxChartView.get() );
1181 }
1182 else
1183 {
1184 if( m_xOldModelAgg.is() )
1185 {
1186 Any aAny = m_xOldModelAgg->queryAggregation( cppu::UnoType<lang::XMultiServiceFactory>::get());
1187 uno::Reference< lang::XMultiServiceFactory > xOldModelFactory;
1188 if( (aAny >>= xOldModelFactory) && xOldModelFactory.is() )
1189 {
1190 return xOldModelFactory->createInstance( rServiceSpecifier );
1191 }
1192 }
1193 }
1194 return nullptr;
1195}
1196
1197Reference< uno::XInterface > SAL_CALL ChartModel::createInstanceWithArguments(
1198 const OUString& rServiceSpecifier , const Sequence< Any >& Arguments )
1199{
1200 OSL_ENSURE( Arguments.hasElements(), "createInstanceWithArguments: Warning: Arguments are ignored" );
1201 return createInstance( rServiceSpecifier );
1202}
1203
1204Sequence< OUString > SAL_CALL ChartModel::getAvailableServiceNames()
1205{
1206 uno::Sequence< OUString > aResult;
1207
1208 if( m_xOldModelAgg.is())
1209 {
1210 Any aAny = m_xOldModelAgg->queryAggregation( cppu::UnoType<lang::XMultiServiceFactory>::get());
1211 uno::Reference< lang::XMultiServiceFactory > xOldModelFactory;
1212 if( (aAny >>= xOldModelFactory) && xOldModelFactory.is() )
1213 {
1214 return xOldModelFactory->getAvailableServiceNames();
1215 }
1216 }
1217 return aResult;
1218}
1219
1220Reference< util::XNumberFormatsSupplier > const & ChartModel::getNumberFormatsSupplier()
1221{
1222 if( !m_xNumberFormatsSupplier.is() )
1223 {
1224 if( !m_xOwnNumberFormatsSupplier.is() )
1225 {
1226 m_apSvNumberFormatter.reset( new SvNumberFormatter( m_xContext, LANGUAGE_SYSTEM ) );
1227 m_xOwnNumberFormatsSupplier = new SvNumberFormatsSupplierObj( m_apSvNumberFormatter.get() );
1228 //pOwnNumberFormatter->ChangeStandardPrec( 15 ); todo?
1229 }
1230 m_xNumberFormatsSupplier = m_xOwnNumberFormatsSupplier;
1231 }
1232 return m_xNumberFormatsSupplier;
1233}
1234
1235// ____ XUnoTunnel ___
1236::sal_Int64 SAL_CALL ChartModel::getSomething( const Sequence< ::sal_Int8 >& aIdentifier )
1237{
1238 if( comphelper::isUnoTunnelId<SvNumberFormatsSupplierObj>(aIdentifier) )
1239 {
1240 Reference< lang::XUnoTunnel > xTunnel( getNumberFormatsSupplier(), uno::UNO_QUERY );
1241 if( xTunnel.is() )
1242 return xTunnel->getSomething( aIdentifier );
1243 }
1244 return 0;
1245}
1246
1247// ____ XNumberFormatsSupplier ____
1248uno::Reference< beans::XPropertySet > SAL_CALL ChartModel::getNumberFormatSettings()
1249{
1250 Reference< util::XNumberFormatsSupplier > xSupplier( getNumberFormatsSupplier() );
1251 if( xSupplier.is() )
1252 return xSupplier->getNumberFormatSettings();
1253 return uno::Reference< beans::XPropertySet >();
1254}
1255
1256uno::Reference< util::XNumberFormats > SAL_CALL ChartModel::getNumberFormats()
1257{
1258 Reference< util::XNumberFormatsSupplier > xSupplier( getNumberFormatsSupplier() );
1259 if( xSupplier.is() )
1260 return xSupplier->getNumberFormats();
1261 return uno::Reference< util::XNumberFormats >();
1262}
1263
1264// ____ XChild ____
1265Reference< uno::XInterface > SAL_CALL ChartModel::getParent()
1266{
1267 return Reference< uno::XInterface >(m_xParent,uno::UNO_QUERY);
1268}
1269
1270void SAL_CALL ChartModel::setParent( const Reference< uno::XInterface >& Parent )
1271{
1272 if( Parent != m_xParent )
1273 m_xParent.set( Parent, uno::UNO_QUERY );
1274}
1275
1276// ____ XDataSource ____
1277uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL ChartModel::getDataSequences()
1278{
1279 rtl::Reference< DataSource > xSource = DataSourceHelper::getUsedData( *this );
1280 if( xSource.is())
1281 return xSource->getDataSequences();
1282
1283 return uno::Sequence< Reference< chart2::data::XLabeledDataSequence > >();
1284}
1285
1286//XDumper
1287OUString SAL_CALL ChartModel::dump(OUString const & kind)
1288{
1289 if (kind.isEmpty()) {
1290 return dumpXmlToString([this](auto writer) { return dumpAsXml(writer); });
1291 }
1292
1293 // kind == "shapes":
1294 uno::Reference< qa::XDumper > xDumper(
1295 createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY );
1296 if (xDumper.is())
1297 return xDumper->dump(kind);
1298
1299 return OUString();
1300}
1301
1302void ChartModel::setTimeBasedRange(sal_Int32 nStart, sal_Int32 nEnd)
1303{
1304 mnStart = nStart;
1305 mnEnd = nEnd;
1306 mbTimeBased = true;
1307}
1308
1309void ChartModel::update()
1310{
1311 if(!mxChartView.is())
1312 {
1313 mxChartView = new ChartView( m_xContext, *this);
1314 }
1315 mxChartView->setViewDirty();
1316 mxChartView->update();
1317}
1318
1319bool ChartModel::isDataFromSpreadsheet()
1320{
1321 return !isDataFromPivotTable() && !hasInternalDataProvider();
1322}
1323
1324bool ChartModel::isDataFromPivotTable() const
1325{
1326 uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(m_xDataProvider, uno::UNO_QUERY);
1327 return xPivotTableDataProvider.is();
1328}
1329
1330} // namespace chart
1331
1332extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1334 css::uno::Sequence<css::uno::Any> const &)
1335{
1336 return cppu::acquire(new ::chart::ChartModel(context));
1337}
1338
1339/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_chart2_ChartModel_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Reference< uno::XComponentContext > m_xContext
HRESULT createInstance(REFIID iid, Ifc **ppIfc)
AnyEventRef aEvent
size_t mnEnd
int nCount
#define DBG_UNHANDLED_EXCEPTION(...)
struct _xmlTextWriter * xmlTextWriterPtr
bool m_bReadOnly
Sequence< sal_Int8 > aSeq
#define SAL_WARN(area, stream)
constexpr OUStringLiteral aData
void DisposeAndClear(css::uno::Reference< T > &rInterface)
void addListener(const InterfaceRef &xObject, const css::uno::Reference< css::lang::XEventListener > &xListener)
void removeListener(const InterfaceRef &xObject, const css::uno::Reference< css::lang::XEventListener > &xListener)
cppu::WeakImplHelper< css::util::XCloseable,css::frame::XStorable2,css::util::XModifiable,css::lang::XServiceInfo,css::lang::XInitialization,css::chart2::XChartDocument,css::chart2::data::XDataReceiver,css::chart2::XTitled,css::frame::XLoadable,css::util::XCloneable,css::embed::XVisualObject,css::lang::XMultiServiceFactory,css::document::XStorageBasedDocument,css::lang::XUnoTunnel,css::util::XNumberFormatsSupplier,css::container::XChild,css::util::XModifyListener,css::datatransfer::XTransferable,css::document::XDocumentPropertiesSupplier,css::chart2::data::XDataSource,css::document::XUndoManagerSupplier,css::util::XUpdatable,css::qa::XDumper > ChartModel_Base
Definition: ChartModel.hxx:112
OUString dumpXmlToString(F f)
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &rS1, const Ss &... rSn)
css::uno::Sequence< css::beans::PropertyValue > InitPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
Title
long Long
constexpr OUStringLiteral CHART_VIEW_SERVICE_NAME
constexpr OUStringLiteral CHART_MODEL_SERVICE_NAME
constexpr OUStringLiteral CHART_MODEL_SERVICE_IMPLEMENTATION_NAME
constexpr OUStringLiteral CHART_CHARTAPIWRAPPER_SERVICE_NAME
Reference< XController > xController
unsigned char sal_Bool
sal_Int32 mnStart