summaryrefslogtreecommitdiffstats
path: root/sc/source
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/ui/drawfunc/fuins2.cxx95
-rw-r--r--sc/source/ui/inc/tabview.hxx2
-rw-r--r--sc/source/ui/unoobj/ChartTools.cxx127
-rw-r--r--sc/source/ui/unoobj/PivotTableDataProvider.cxx843
-rw-r--r--sc/source/ui/unoobj/PivotTableDataSequence.cxx278
-rw-r--r--sc/source/ui/unoobj/PivotTableDataSource.cxx51
-rw-r--r--sc/source/ui/unoobj/TablePivotChart.cxx104
-rw-r--r--sc/source/ui/unoobj/TablePivotCharts.cxx279
-rw-r--r--sc/source/ui/unoobj/cellsuno.cxx17
-rw-r--r--sc/source/ui/unoobj/chartuno.cxx48
-rw-r--r--sc/source/ui/unoobj/servuno.cxx7
-rw-r--r--sc/source/ui/view/tabview3.cxx18
-rw-r--r--sc/source/ui/view/tabvwshb.cxx32
13 files changed, 1811 insertions, 90 deletions
diff --git a/sc/source/ui/drawfunc/fuins2.cxx b/sc/source/ui/drawfunc/fuins2.cxx
index 7f351853e575..f6cf018b0d75 100644
--- a/sc/source/ui/drawfunc/fuins2.cxx
+++ b/sc/source/ui/drawfunc/fuins2.cxx
@@ -63,8 +63,7 @@
#include <com/sun/star/chart/ChartDataRowSource.hpp>
#include <cppuhelper/bootstrap.hxx>
-using namespace ::com::sun::star;
-
+#include "PivotTableDataProvider.hxx"
#include "chart2uno.hxx"
#include "fuinsert.hxx"
#include "tabvwsh.hxx"
@@ -79,18 +78,23 @@ using namespace ::com::sun::star;
#include "drawview.hxx"
#include "markdata.hxx"
#include "gridwin.hxx"
+#include "dpobject.hxx"
#include <memory>
-namespace {
+using namespace css;
+
+namespace
+{
-void lcl_ChartInit( const uno::Reference < embed::XEmbeddedObject >& xObj, ScViewData* pViewData,
- const OUString& rRangeParam )
+void lcl_ChartInit(const uno::Reference <embed::XEmbeddedObject>& xObj, ScViewData* pViewData,
+ const OUString& rRangeParam, bool bRangeIsPivotTable)
{
ScDocShell* pDocShell = pViewData->GetDocShell();
ScDocument& rScDoc = pDocShell->GetDocument();
- OUString aRangeString( rRangeParam );
- if ( aRangeString.isEmpty() )
+ OUString aRangeString(rRangeParam);
+
+ if (aRangeString.isEmpty() && !bRangeIsPivotTable)
{
SCCOL nCol1 = 0;
SCROW nRow1 = 0;
@@ -118,7 +122,7 @@ void lcl_ChartInit( const uno::Reference < embed::XEmbeddedObject >& xObj, ScVie
}
}
- if ( !aRangeString.isEmpty() )
+ if (!aRangeString.isEmpty())
{
// connect to Calc data (if no range string, leave chart alone, with its own data)
@@ -129,8 +133,19 @@ void lcl_ChartInit( const uno::Reference < embed::XEmbeddedObject >& xObj, ScVie
OSL_ASSERT( xReceiver.is());
if( xReceiver.is() )
{
- uno::Reference< chart2::data::XDataProvider > xDataProvider = new ScChart2DataProvider( &rScDoc );
- xReceiver->attachDataProvider( xDataProvider );
+ uno::Reference<chart2::data::XDataProvider> xDataProvider;
+ if (bRangeIsPivotTable)
+ {
+ std::unique_ptr<sc::PivotTableDataProvider> pPivotTableDataProvider(new sc::PivotTableDataProvider(&rScDoc));
+ pPivotTableDataProvider->setPivotTableName(aRangeString);
+ xDataProvider.set(pPivotTableDataProvider.release());
+ }
+ else
+ {
+ xDataProvider.set(new ScChart2DataProvider(&rScDoc));
+ }
+
+ xReceiver->attachDataProvider(xDataProvider);
uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( pDocShell->GetModel(), uno::UNO_QUERY );
xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
@@ -329,7 +344,7 @@ FuInsertOLE::FuInsertOLE(ScTabViewShell* pViewSh, vcl::Window* pWin, ScDrawView*
// Chart initialisieren ?
if ( SvtModuleOptions().IsChart() && SotExchange::IsChart( SvGlobalName( xObj->getClassID() ) ) )
- lcl_ChartInit( xObj, &pViewSh->GetViewData(), OUString() );
+ lcl_ChartInit(xObj, &pViewSh->GetViewData(), OUString(), false);
ScViewData& rData = pViewSh->GetViewData();
@@ -393,7 +408,7 @@ FuInsertChart::FuInsertChart(ScTabViewShell* pViewSh, vcl::Window* pWin, ScDrawV
SdrModel* pDoc, SfxRequest& rReq)
: FuPoor(pViewSh, pWin, pViewP, pDoc, rReq)
{
- const SfxItemSet* pReqArgs = rReq.GetArgs();
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
if( ! rReq.IsAPI() )
rReq.Done();
@@ -405,6 +420,7 @@ FuInsertChart::FuInsertChart(ScTabViewShell* pViewSh, vcl::Window* pWin, ScDrawV
// get range
OUString aRangeString;
+ bool bRangeIsPivotTable = false;
ScRange aPositionRange; // cell range for chart positioning
ScMarkData aMark = pViewSh->GetViewData().GetMarkData();
if( pReqArgs )
@@ -417,35 +433,46 @@ FuInsertChart::FuInsertChart(ScTabViewShell* pViewSh, vcl::Window* pWin, ScDrawV
}
else
{
- bool bAutomaticMark = false;
- if ( !aMark.IsMarked() && !aMark.IsMultiMarked() )
+ ScDocument* pDocument = pViewSh->GetViewData().GetDocument();
+ ScDPObject* pObject = pDocument->GetDPAtCursor(pViewSh->GetViewData().GetCurX(),
+ pViewSh->GetViewData().GetCurY(),
+ pViewSh->GetViewData().GetTabNo());
+ if (pObject)
{
- pViewSh->GetViewData().GetView()->MarkDataArea();
- bAutomaticMark = true;
+ aRangeString = pObject->GetName();
+ bRangeIsPivotTable = true;
}
+ else
+ {
+ bool bAutomaticMark = false;
+ if ( !aMark.IsMarked() && !aMark.IsMultiMarked() )
+ {
+ pViewSh->GetViewData().GetView()->MarkDataArea();
+ bAutomaticMark = true;
+ }
- ScMarkData aMultiMark( aMark );
- aMultiMark.MarkToMulti();
+ ScMarkData aMultiMark( aMark );
+ aMultiMark.MarkToMulti();
- ScRangeList aRanges;
- aMultiMark.FillRangeListWithMarks( &aRanges, false );
- OUString aStr;
- ScDocument* pDocument = pViewSh->GetViewData().GetDocument();
- aRanges.Format( aStr, ScRefFlags::RANGE_ABS_3D, pDocument, pDocument->GetAddressConvention() );
- aRangeString = aStr;
+ ScRangeList aRanges;
+ aMultiMark.FillRangeListWithMarks( &aRanges, false );
+ OUString aStr;
+ aRanges.Format( aStr, ScRefFlags::RANGE_ABS_3D, pDocument, pDocument->GetAddressConvention() );
+ aRangeString = aStr;
- // get "total" range for positioning
- if ( !aRanges.empty() )
- {
- aPositionRange = *aRanges[ 0 ];
- for ( size_t i = 1, nCount = aRanges.size(); i < nCount; ++i )
+ // get "total" range for positioning
+ if ( !aRanges.empty() )
{
- aPositionRange.ExtendTo( *aRanges[ i ] );
+ aPositionRange = *aRanges[ 0 ];
+ for ( size_t i = 1, nCount = aRanges.size(); i < nCount; ++i )
+ {
+ aPositionRange.ExtendTo( *aRanges[ i ] );
+ }
}
- }
- if(bAutomaticMark)
- pViewSh->GetViewData().GetView()->Unmark();
+ if(bAutomaticMark)
+ pViewSh->GetViewData().GetView()->Unmark();
+ }
}
// adapted old code
@@ -568,7 +595,7 @@ FuInsertChart::FuInsertChart(ScTabViewShell* pViewSh, vcl::Window* pWin, ScDrawV
}
}
- lcl_ChartInit( xObj, &rData, aRangeString ); // set source range, auto-detect column/row headers
+ lcl_ChartInit(xObj, &rData, aRangeString, bRangeIsPivotTable); // set source range, auto-detect column/row headers
// Objekt-Position
diff --git a/sc/source/ui/inc/tabview.hxx b/sc/source/ui/inc/tabview.hxx
index b217c5ba0b2a..a9cccb10bbbd 100644
--- a/sc/source/ui/inc/tabview.hxx
+++ b/sc/source/ui/inc/tabview.hxx
@@ -487,7 +487,7 @@ public:
void ClearHighlightRanges();
void DoChartSelection( const css::uno::Sequence< css::chart2::data::HighlightedRange > & rHilightRanges );
- void DoDPFieldPopup(Point aPoint, Size aSize);
+ void DoDPFieldPopup(OUString const & rPivotTableName, sal_Int32 nDimensionIndex, Point aPoint, Size aSize);
long GetGridWidth( ScHSplitPos eWhich );
long GetGridHeight( ScVSplitPos eWhich );
diff --git a/sc/source/ui/unoobj/ChartTools.cxx b/sc/source/ui/unoobj/ChartTools.cxx
new file mode 100644
index 000000000000..77818723c7aa
--- /dev/null
+++ b/sc/source/ui/unoobj/ChartTools.cxx
@@ -0,0 +1,127 @@
+/* -*- 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/.
+ *
+ */
+
+#include "ChartTools.hxx"
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
+
+#include <svx/svditer.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdundo.hxx>
+#include <sfx2/app.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <comphelper/classids.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/globname.hxx>
+#include <svx/charthelper.hxx>
+#include <svtools/embedhlp.hxx>
+
+using namespace css;
+
+namespace sc {
+namespace tools {
+
+ChartIterator::ChartIterator(ScDocShell* pDocShell, SCTAB nTab, ChartSourceType eChartSourceType)
+ : m_eChartSourceType(eChartSourceType)
+{
+ if (!pDocShell)
+ return;
+ ScDocument& rDoc = pDocShell->GetDocument();
+ ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
+ if (!pDrawLayer)
+ return;
+ SdrPage* pPage = pDrawLayer->GetPage(sal_uInt16(nTab));
+ if (!pPage)
+ return;
+ m_pIterator.reset(new SdrObjListIter(*pPage, SdrIterMode::DeepNoGroups));
+}
+
+SdrOle2Obj* ChartIterator::next()
+{
+ if (!m_pIterator)
+ return nullptr;
+
+ SdrObject* pObject = m_pIterator->Next();
+ while (pObject)
+ {
+ if (pObject->GetObjIdentifier() == OBJ_OLE2 && ScDocument::IsChart(pObject))
+ {
+ SdrOle2Obj* pOleObject = static_cast<SdrOle2Obj*>(pObject);
+ uno::Reference<embed::XEmbeddedObject> xObject = pOleObject->GetObjRef();
+ if (xObject.is())
+ {
+ uno::Reference<chart2::XChartDocument> xChartDoc(xObject->getComponent(), uno::UNO_QUERY);
+ if (xChartDoc.is())
+ {
+ uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(xChartDoc->getDataProvider(), uno::UNO_QUERY);
+ if (xPivotTableDataProvider.is() && m_eChartSourceType == ChartSourceType::PIVOT_TABLE)
+ {
+ return pOleObject;
+ }
+ else if (!xPivotTableDataProvider.is() && m_eChartSourceType == ChartSourceType::CELL_RANGE)
+ {
+ return pOleObject;
+ }
+ }
+ }
+ }
+ pObject = m_pIterator->Next();
+ }
+ return nullptr;
+}
+
+SdrOle2Obj* findChartsByName(ScDocShell* pDocShell, SCTAB nTab, OUString const & rName, ChartSourceType eChartSourceType)
+{
+ if (!pDocShell)
+ return nullptr;
+
+ ChartIterator aIterator(pDocShell, nTab, eChartSourceType);
+
+ SdrOle2Obj* pObject = aIterator.next();
+ while (pObject)
+ {
+ uno::Reference<embed::XEmbeddedObject> xObject = pObject->GetObjRef();
+ if (xObject.is())
+ {
+ OUString aObjectName = pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName(xObject);
+ if (aObjectName == rName)
+ return pObject;
+ }
+ pObject = aIterator.next();
+ }
+ return nullptr;
+}
+
+SdrOle2Obj* getChartByIndex(ScDocShell* pDocShell, SCTAB nTab, long nIndex, ChartSourceType eChartSourceType)
+{
+ if (!pDocShell)
+ return nullptr;
+
+ ChartIterator aIterator(pDocShell, nTab, eChartSourceType);
+
+ SdrOle2Obj* pObject = aIterator.next();
+ long i = 0;
+ while (pObject)
+ {
+ if (i == nIndex)
+ {
+ return pObject;
+ }
+
+ i++;
+ pObject = aIterator.next();
+ }
+ return nullptr;
+}
+
+}} // end sc::tools
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/unoobj/PivotTableDataProvider.cxx b/sc/source/ui/unoobj/PivotTableDataProvider.cxx
new file mode 100644
index 000000000000..84eb756c3bf3
--- /dev/null
+++ b/sc/source/ui/unoobj/PivotTableDataProvider.cxx
@@ -0,0 +1,843 @@
+/* -*- 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/.
+ */
+
+#include <sal/config.h>
+
+#include "PivotTableDataProvider.hxx"
+#include "PivotTableDataSource.hxx"
+#include "PivotTableDataSequence.hxx"
+
+#include <vcl/svapp.hxx>
+
+#include "miscuno.hxx"
+#include "document.hxx"
+#include "unonames.hxx"
+#include "docsh.hxx"
+
+#include <sfx2/objsh.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+
+#include <com/sun/star/sheet/XDataPilotResults.hpp>
+#include <com/sun/star/sheet/DataResultFlags.hpp>
+
+#include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
+#include <com/sun/star/sheet/XLevelsSupplier.hpp>
+#include <com/sun/star/sheet/XDataPilotMemberResults.hpp>
+#include <com/sun/star/sheet/MemberResultFlags.hpp>
+
+#include "dpobject.hxx"
+
+#include "hints.hxx"
+
+#include <com/sun/star/chart/ChartDataChangeEvent.hpp>
+
+#include <unordered_map>
+
+using namespace css;
+
+namespace sc
+{
+namespace
+{
+
+const SfxItemPropertyMapEntry* lcl_GetDataProviderPropertyMap()
+{
+ static const SfxItemPropertyMapEntry aDataProviderPropertyMap_Impl[] =
+ {
+ { OUString(SC_UNONAME_INCLUDEHIDDENCELLS), 0, cppu::UnoType<bool>::get(), 0, 0 },
+ { OUString(SC_UNONAME_USE_INTERNAL_DATA_PROVIDER), 0, cppu::UnoType<bool>::get(), 0, 0 },
+ { OUString(), 0, css::uno::Type(), 0, 0 }
+ };
+ return aDataProviderPropertyMap_Impl;
+}
+
+uno::Reference<frame::XModel> lcl_GetXModel(ScDocument * pDoc)
+{
+ uno::Reference<frame::XModel> xModel;
+ SfxObjectShell* pObjSh(pDoc ? pDoc->GetDocumentShell() : nullptr);
+ if (pObjSh)
+ xModel.set(pObjSh->GetModel());
+ return xModel;
+}
+
+OUString lcl_identifierForData(sal_Int32 index)
+{
+ return "Data " + OUString::number(index + 1);
+}
+
+OUString lcl_identifierForLabel(sal_Int32 index)
+{
+ return "Label " + OUString::number(index + 1);
+}
+
+} // end anonymous namespace
+
+SC_SIMPLE_SERVICE_INFO(PivotTableDataProvider, "PivotTableDataProvider", SC_SERVICENAME_CHART_PIVOTTABLE_DATAPROVIDER)
+
+// DataProvider ==============================================================
+
+PivotTableDataProvider::PivotTableDataProvider(ScDocument* pDoc)
+ : m_pDocument(pDoc)
+ , m_aPropSet(lcl_GetDataProviderPropertyMap())
+ , m_bIncludeHiddenCells(true)
+ , m_bNeedsUpdate(true)
+ , m_xContext(comphelper::getProcessComponentContext())
+{
+ if (m_pDocument)
+ m_pDocument->AddUnoObject(*this);
+}
+
+PivotTableDataProvider::~PivotTableDataProvider()
+{
+ SolarMutexGuard g;
+
+ if (m_pDocument)
+ m_pDocument->RemoveUnoObject( *this);
+}
+
+void PivotTableDataProvider::Notify(SfxBroadcaster& /*rBroadcaster*/, const SfxHint& rHint)
+{
+ if (rHint.GetId() == SfxHintId::Dying)
+ {
+ m_pDocument = nullptr;
+ }
+ else if (dynamic_cast<const ScDataPilotModifiedHint*>(&rHint))
+ {
+ if (m_pDocument)
+ {
+ OUString sPivotTableName = static_cast<const ScDataPilotModifiedHint&>(rHint).GetName();
+ if (sPivotTableName == m_sPivotTableName)
+ {
+ m_bNeedsUpdate = true;
+ for (uno::Reference<util::XModifyListener> const & xListener : m_aValueListeners)
+ {
+ css::chart::ChartDataChangeEvent aEvent(static_cast<cppu::OWeakObject*>(this),
+ css::chart::ChartDataChangeType_ALL,
+ 0, 0, 0, 0);
+ xListener->modified(aEvent);
+ }
+ }
+ }
+ }
+}
+
+sal_Bool SAL_CALL PivotTableDataProvider::createDataSourcePossible(const uno::Sequence<beans::PropertyValue>& /*aArguments*/)
+{
+ SolarMutexGuard aGuard;
+ if (!m_pDocument)
+ return false;
+
+ if (m_sPivotTableName.isEmpty())
+ return false;
+
+ ScDPCollection* pDPCollection = m_pDocument->GetDPCollection();
+ return bool(pDPCollection->GetByName(m_sPivotTableName));
+}
+
+uno::Reference<chart2::data::XDataSource> SAL_CALL
+ PivotTableDataProvider::createDataSource(const uno::Sequence<beans::PropertyValue>& aArguments)
+{
+ SolarMutexGuard aGuard;
+ if (!m_pDocument)
+ throw uno::RuntimeException();
+
+ bool bLabel = true;
+ bool bCategories = false;
+ bool bOrientCol = true;
+ OUString aRangeRepresentation;
+ OUString sPivotTable;
+ uno::Sequence<sal_Int32> aSequenceMapping;
+ bool bTimeBased = false;
+
+ for (beans::PropertyValue const & rProperty : aArguments)
+ {
+ if (rProperty.Name == "DataRowSource")
+ {
+ chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS;
+ if (!(rProperty.Value >>= eSource))
+ {
+ sal_Int32 nSource(0);
+ if (rProperty.Value >>= nSource)
+ eSource = chart::ChartDataRowSource(nSource);
+ }
+ bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS);
+ }
+ else if (rProperty.Name == "FirstCellAsLabel")
+ rProperty.Value >>= bLabel;
+ else if (rProperty.Name == "HasCategories")
+ rProperty.Value >>= bCategories;
+ else if (rProperty.Name == "CellRangeRepresentation")
+ rProperty.Value >>= aRangeRepresentation;
+ else if (rProperty.Name == "SequenceMapping")
+ rProperty.Value >>= aSequenceMapping;
+ else if (rProperty.Name == "TimeBased")
+ rProperty.Value >>= bTimeBased;
+ else if (rProperty.Name == "ConnectedPivotTable")
+ rProperty.Value >>= sPivotTable;
+ }
+
+ uno::Reference<chart2::data::XDataSource> xResult;
+
+ if (aRangeRepresentation == "Categories")
+ xResult = createCategoriesDataSource(aRangeRepresentation, bOrientCol);
+ else
+ xResult = createValuesDataSource(aRangeRepresentation);
+
+ return xResult;
+}
+
+uno::Reference<chart2::data::XLabeledDataSequence>
+ PivotTableDataProvider::newLabeledDataSequence()
+{
+ uno::Reference<chart2::data::XLabeledDataSequence> xResult;
+ if (!m_xContext.is())
+ return xResult;
+ xResult.set(chart2::data::LabeledDataSequence::create(m_xContext), uno::UNO_QUERY_THROW);
+ return xResult;
+}
+
+void PivotTableDataProvider::setLabeledDataSequenceValues(uno::Reference<chart2::data::XLabeledDataSequence> & xResult,
+ OUString const & sRoleValues, OUString const & sIdValues,
+ std::vector<ValueAndFormat> const & rValues)
+{
+ std::unique_ptr<PivotTableDataSequence> pSequence(
+ new PivotTableDataSequence(m_pDocument, m_sPivotTableName, sIdValues, rValues));
+ pSequence->setRole(sRoleValues);
+ xResult->setValues(uno::Reference<chart2::data::XDataSequence>(pSequence.release()));
+}
+
+void PivotTableDataProvider::setLabeledDataSequence(uno::Reference<chart2::data::XLabeledDataSequence> & xResult,
+ OUString const & sRoleValues, OUString const & sIdValues,
+ std::vector<ValueAndFormat> const & rValues,
+ OUString const & sRoleLabel, OUString const & sIdLabel,
+ std::vector<ValueAndFormat> const & rLabel)
+{
+ setLabeledDataSequenceValues(xResult, sRoleValues, sIdValues, rValues);
+
+ std::unique_ptr<PivotTableDataSequence> pLabelSequence(
+ new PivotTableDataSequence(m_pDocument, m_sPivotTableName, sIdLabel, rLabel));
+ pLabelSequence->setRole(sRoleLabel);
+ xResult->setLabel(uno::Reference<chart2::data::XDataSequence>(pLabelSequence.release()));
+}
+
+uno::Reference<chart2::data::XDataSource>
+PivotTableDataProvider::createCategoriesDataSource(OUString const & rRangeRepresentation,
+ bool bOrientationIsColumn)
+{
+ if (m_bNeedsUpdate)
+ collectPivotTableData();
+
+ uno::Reference<chart2::data::XDataSource> xDataSource;
+ std::vector<uno::Reference<chart2::data::XLabeledDataSequence>> aLabeledSequences;
+
+ if (bOrientationIsColumn)
+ {
+ for (std::vector<ValueAndFormat> const & rCategories : m_aCategoriesColumnOrientation)
+ {
+ uno::Reference<chart2::data::XLabeledDataSequence> xResult = newLabeledDataSequence();
+ setLabeledDataSequenceValues(xResult, "categories", "Categories", rCategories);
+ aLabeledSequences.push_back(xResult);
+ }
+ }
+ else
+ {
+ for (std::vector<ValueAndFormat> const & rCategories : m_aCategoriesRowOrientation)
+ {
+ uno::Reference<chart2::data::XLabeledDataSequence> xResult = newLabeledDataSequence();
+ setLabeledDataSequenceValues(xResult, "categories", "Categories", rCategories);
+ aLabeledSequences.push_back(xResult);
+ }
+ }
+
+ xDataSource.set(new PivotTableDataSource(rRangeRepresentation, aLabeledSequences));
+ return xDataSource;
+}
+
+void PivotTableDataProvider::collectPivotTableData()
+{
+ ScDPCollection* pDPCollection = m_pDocument->GetDPCollection();
+ ScDPObject* pDPObject = pDPCollection->GetByName(m_sPivotTableName);
+
+ uno::Reference<sheet::XDataPilotResults> xDPResults(pDPObject->GetSource(), uno::UNO_QUERY);
+ uno::Sequence<uno::Sequence<sheet::DataResult>> xDataResultsSequence = xDPResults->getResults();
+
+ m_aCategoriesColumnOrientation.clear();
+ m_aCategoriesRowOrientation.clear();
+ m_aLabels.clear();
+ m_aDataRowVector.clear();
+ m_aColumnFields.clear();
+ m_aRowFields.clear();
+ m_aPageFields.clear();
+ m_aDataFields.clear();
+
+ double fNan;
+ rtl::math::setNan(&fNan);
+
+ for (uno::Sequence<sheet::DataResult> const & xDataResults : xDataResultsSequence)
+ {
+ size_t nIndex = 0;
+ for (sheet::DataResult const & rDataResult : xDataResults)
+ {
+ if (rDataResult.Flags == 0 || rDataResult.Flags & css::sheet::DataResultFlags::HASDATA)
+ {
+ if (nIndex >= m_aDataRowVector.size())
+ m_aDataRowVector.resize(nIndex + 1);
+ m_aDataRowVector[nIndex].push_back(ValueAndFormat(rDataResult.Flags ? rDataResult.Value : fNan, 0));
+ }
+ nIndex++;
+ }
+ }
+
+ uno::Reference<sheet::XDimensionsSupplier> xDimensionsSupplier(pDPObject->GetSource());
+ uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess(xDimensionsSupplier->getDimensions());
+
+ std::unordered_map<OUString, sal_Int32, OUStringHash> aDataFieldNumberFormatMap;
+ std::vector<OUString> aDataFieldNamesVectors;
+
+ std::unordered_map<OUString, OUString, OUStringHash> aDataFieldCaptionNames;
+ std::vector<std::pair<OUString, sal_Int32>> aDataFieldPairs;
+
+ sheet::DataPilotFieldOrientation eDataFieldOrientation = sheet::DataPilotFieldOrientation_HIDDEN;
+
+ for (sal_Int32 nDim = 0; nDim < xDims->getCount(); nDim++)
+ {
+ uno::Reference<uno::XInterface> xDim = ScUnoHelpFunctions::AnyToInterface(xDims->getByIndex(nDim));
+ uno::Reference<beans::XPropertySet> xDimProp(xDim, uno::UNO_QUERY);
+ uno::Reference<container::XNamed> xDimName(xDim, uno::UNO_QUERY);
+ uno::Reference<sheet::XHierarchiesSupplier> xDimSupp(xDim, uno::UNO_QUERY);
+
+ if (!xDimProp.is() || !xDimSupp.is())
+ continue;
+
+ sheet::DataPilotFieldOrientation eDimOrient = sheet::DataPilotFieldOrientation(
+ ScUnoHelpFunctions::GetEnumProperty(xDimProp, SC_UNO_DP_ORIENTATION,
+ sheet::DataPilotFieldOrientation_HIDDEN));
+
+ if (eDimOrient == sheet::DataPilotFieldOrientation_HIDDEN)
+ continue;
+
+ uno::Reference<container::XIndexAccess> xHierarchies = new ScNameToIndexAccess(xDimSupp->getHierarchies());
+ sal_Int32 nHierarchy = ScUnoHelpFunctions::GetLongProperty(xDimProp, SC_UNO_DP_USEDHIERARCHY);
+ if (nHierarchy >= xHierarchies->getCount())
+ nHierarchy = 0;
+
+ uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface(xHierarchies->getByIndex(nHierarchy));
+
+ uno::Reference<sheet::XLevelsSupplier> xLevelsSupplier(xHierarchy, uno::UNO_QUERY);
+
+ if (!xLevelsSupplier.is())
+ continue;
+
+ uno::Reference<container::XIndexAccess> xLevels = new ScNameToIndexAccess(xLevelsSupplier->getLevels());
+
+ for (long nLevel = 0; nLevel < xLevels->getCount(); nLevel++)
+ {
+ uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface(xLevels->getByIndex(nLevel));
+ uno::Reference<container::XNamed> xLevelName(xLevel, uno::UNO_QUERY);
+ uno::Reference<sheet::XDataPilotMemberResults> xLevelResult(xLevel, uno::UNO_QUERY );
+
+ bool bIsDataLayout = ScUnoHelpFunctions::GetBoolProperty(xDimProp, SC_UNO_DP_ISDATALAYOUT);
+ long nDimPos = ScUnoHelpFunctions::GetLongProperty(xDimProp, SC_UNO_DP_POSITION);
+ sal_Int32 nNumberFormat = ScUnoHelpFunctions::GetLongProperty(xDimProp, SC_UNO_DP_NUMBERFO);
+
+ if (xLevelName.is() && xLevelResult.is())
+ {
+ switch (eDimOrient)
+ {
+ case sheet::DataPilotFieldOrientation_COLUMN:
+ {
+ m_aColumnFields.push_back(chart2::data::PivotTableFieldEntry{xLevelName->getName(), nDim});
+
+ uno::Sequence<sheet::MemberResult> aSequence = xLevelResult->getResults();
+ size_t i = 0;
+ OUString sCaption;
+ OUString sName;
+ m_aLabels.resize(aSequence.getLength());
+ for (sheet::MemberResult & rMember : aSequence)
+ {
+ if (rMember.Flags & sheet::MemberResultFlags::HASMEMBER ||
+ rMember.Flags & sheet::MemberResultFlags::CONTINUE)
+ {
+ if (!(rMember.Flags & sheet::MemberResultFlags::CONTINUE))
+ {
+ sCaption = rMember.Caption;
+ sName = rMember.Name;
+ }
+
+ if (size_t(nDimPos) >= m_aLabels[i].size())
+ m_aLabels[i].resize(nDimPos + 1);
+ m_aLabels[i][nDimPos] = ValueAndFormat(sCaption);
+
+ if (bIsDataLayout)
+ {
+ // Remember data fields to determine the number format of data
+ aDataFieldNamesVectors.push_back(sName);
+ eDataFieldOrientation = sheet::DataPilotFieldOrientation_COLUMN;
+ // Remember the caption name
+ aDataFieldCaptionNames[rMember.Name] = rMember.Caption;
+ }
+ i++;
+ }
+ }
+ }
+ break;
+
+ case sheet::DataPilotFieldOrientation_ROW:
+ {
+ m_aRowFields.push_back(chart2::data::PivotTableFieldEntry{xLevelName->getName(), nDim});
+
+ uno::Sequence<sheet::MemberResult> aSequence = xLevelResult->getResults();
+ m_aCategoriesRowOrientation.resize(aSequence.getLength());
+ size_t i = 0;
+ for (sheet::MemberResult & rMember : aSequence)
+ {
+ bool bHasContinueFlag = rMember.Flags & sheet::MemberResultFlags::CONTINUE;
+
+ if (rMember.Flags & sheet::MemberResultFlags::HASMEMBER || bHasContinueFlag)
+ {
+ std::unique_ptr<ValueAndFormat> pItem;
+
+ double fValue = rMember.Value;
+
+ if (rtl::math::isNan(fValue))
+ {
+ OUString sStringValue = bHasContinueFlag ? "" : rMember.Caption;
+ pItem.reset(new ValueAndFormat(sStringValue));
+ }
+ else
+ {
+ if (bHasContinueFlag)
+ pItem.reset(new ValueAndFormat());
+ else
+ pItem.reset(new ValueAndFormat(fValue, nNumberFormat));
+ }
+
+ if (size_t(nDimPos) >= m_aCategoriesColumnOrientation.size())
+ m_aCategoriesColumnOrientation.resize(nDimPos + 1);
+ m_aCategoriesColumnOrientation[nDimPos].push_back(*pItem);
+
+ if (size_t(nDimPos) >= m_aCategoriesRowOrientation[i].size())
+ m_aCategoriesRowOrientation[i].resize(nDimPos + 1);
+ m_aCategoriesRowOrientation[i][nDimPos] = *pItem;
+
+ if (bIsDataLayout)
+ {
+ // Remember data fields to determine the number format of data
+ aDataFieldNamesVectors.push_back(rMember.Name);
+ eDataFieldOrientation = sheet::DataPilotFieldOrientation_ROW;
+
+ // Remember the caption name
+ aDataFieldCaptionNames[rMember.Name] = rMember.Caption;
+ }
+ i++;
+ }
+ }
+ }
+ break;
+
+ case sheet::DataPilotFieldOrientation_PAGE:
+ {
+ m_aPageFields.push_back(chart2::data::PivotTableFieldEntry{xLevelName->getName(), nDim});
+ }
+ break;
+
+ case sheet::DataPilotFieldOrientation_DATA:
+ {
+ aDataFieldNumberFormatMap[xLevelName->getName()] = nNumberFormat;
+ aDataFieldPairs.push_back(std::pair<OUString, sal_Int32>(xLevelName->getName(), nDim));
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ // Fill data field entry info
+ for (std::pair<OUString, sal_Int32> & rPair : aDataFieldPairs)
+ {
+ m_aDataFields.push_back(chart2::data::PivotTableFieldEntry{
+ aDataFieldCaptionNames[rPair.first],
+ rPair.second});
+ }
+
+ // Apply number format to the data
+ if (eDataFieldOrientation == sheet::DataPilotFieldOrientation_ROW)
+ {
+ for (std::vector<ValueAndFormat> & rDataRow : m_aDataRowVector)
+ {
+ size_t i = 0;
+ for (ValueAndFormat & rItem : rDataRow)
+ {
+ OUString sName = aDataFieldNamesVectors[i];
+ sal_Int32 nNumberFormat = aDataFieldNumberFormatMap[sName];
+ rItem.m_nNumberFormat = nNumberFormat;
+ i++;
+ }
+ }
+ }
+ else if (eDataFieldOrientation == sheet::DataPilotFieldOrientation_COLUMN)
+ {
+ size_t i = 0;
+ for (std::vector<ValueAndFormat> & rDataRow : m_aDataRowVector)
+ {
+ OUString sName = aDataFieldNamesVectors[i];
+ sal_Int32 nNumberFormat = aDataFieldNumberFormatMap[sName];
+ for (ValueAndFormat & rItem : rDataRow)
+ {
+ rItem.m_nNumberFormat = nNumberFormat;
+ }
+ i++;
+ }
+ }
+
+ m_bNeedsUpdate = false;
+}
+
+void PivotTableDataProvider::assignValuesToDataSequence(uno::Reference<chart2::data::XDataSequence> & rDataSequence,
+ size_t nIndex)
+{
+ if (nIndex >= m_aDataRowVector.size())
+ return;
+
+ OUString sDataID = lcl_identifierForData(nIndex);
+
+ std::vector<ValueAndFormat> const & rRowOfData = m_aDataRowVector[size_t(nIndex)];
+ std::unique_ptr<PivotTableDataSequence> pSequence(new PivotTableDataSequence(m_pDocument, m_sPivotTableName,
+ sDataID, rRowOfData));
+ pSequence->setRole("values-y");
+ rDataSequence.set(uno::Reference<chart2::data::XDataSequence>(pSequence.release()));
+}
+
+void PivotTableDataProvider::assignLabelsToDataSequence(uno::Reference<chart2::data::XDataSequence> & rDataSequence,
+ size_t nIndex)
+{
+ if (nIndex >= m_aLabels.size())
+ return;
+
+ OUString sLabelID = lcl_identifierForLabel(nIndex);
+
+ OUString aLabel;
+ bool bFirst = true;
+ for (ValueAndFormat const & rItem : m_aLabels[size_t(nIndex)])
+ {
+ if (bFirst)
+ {
+ aLabel += rItem.m_aString;
+ bFirst = false;
+ }
+ else
+ {
+ aLabel += " - " + rItem.m_aString;
+ }
+ }
+
+ std::vector<ValueAndFormat> aLabelVector { ValueAndFormat(aLabel) };
+
+ std::unique_ptr<PivotTableDataSequence> pSequence(new PivotTableDataSequence(m_pDocument, m_sPivotTableName,
+ sLabelID, aLabelVector));
+ pSequence->setRole("values-y");
+ rDataSequence.set(uno::Reference<chart2::data::XDataSequence>(pSequence.release()));
+}
+
+uno::Reference<chart2::data::XDataSource>
+ PivotTableDataProvider::createValuesDataSource(OUString const & rRangeRepresentation)
+{
+ if (m_bNeedsUpdate)
+ collectPivotTableData();
+
+ uno::Reference<chart2::data::XDataSource> xDataSource;
+ std::vector<uno::Reference<chart2::data::XLabeledDataSequence>> aLabeledSequences;
+
+ {
+ std::vector<ValueAndFormat> aFirstCategories;
+ if (!m_aCategoriesColumnOrientation.empty())
+ {
+ std::copy(m_aCategoriesColumnOrientation[0].begin(),
+ m_aCategoriesColumnOrientation[0].end(),
+ std::back_inserter(aFirstCategories));
+ }
+ uno::Reference<chart2::data::XLabeledDataSequence> xResult = newLabeledDataSequence();
+ setLabeledDataSequenceValues(xResult, "categories", "Categories", aFirstCategories);
+ aLabeledSequences.push_back(xResult);
+ }
+
+ {
+ int i = 0;
+ for (std::vector<ValueAndFormat> const & rRowOfData : m_aDataRowVector)
+ {
+ OUString aValuesId = lcl_identifierForData(i);
+ OUString aLabelsId = lcl_identifierForLabel(i);
+
+ OUString aLabel;
+ bool bFirst = true;
+ for (ValueAndFormat const & rItem : m_aLabels[i])
+ {
+ if (bFirst)
+ {
+ aLabel += rItem.m_aString;
+ bFirst = false;
+ }
+ else
+ {
+ aLabel += " - " + rItem.m_aString;
+ }
+ }
+
+ std::vector<ValueAndFormat> aLabelVector { ValueAndFormat(aLabel) };
+
+ uno::Reference<chart2::data::XLabeledDataSequence> xResult = newLabeledDataSequence();
+ setLabeledDataSequence(xResult, "values-y", aValuesId, rRowOfData,
+ "values-y", aLabelsId, aLabelVector);
+ aLabeledSequences.push_back(xResult);
+ i++;
+ }
+ }
+
+ xDataSource.set(new PivotTableDataSource(rRangeRepresentation, aLabeledSequences));
+ return xDataSource;
+}
+
+
+uno::Sequence<beans::PropertyValue> SAL_CALL PivotTableDataProvider::detectArguments(
+ const uno::Reference<chart2::data::XDataSource> & xDataSource)
+{
+ uno::Sequence<beans::PropertyValue> aArguments;
+
+ if (!m_pDocument ||!xDataSource.is())
+ return aArguments;
+
+ aArguments.realloc(4);
+
+ aArguments[0] = beans::PropertyValue("CellRangeRepresentation", -1, uno::Any(OUString("PivotChart")),
+ beans::PropertyState_DIRECT_VALUE);
+
+ aArguments[1] = beans::PropertyValue("DataRowSource", -1, uno::Any(chart::ChartDataRowSource_COLUMNS),
+ beans::PropertyState_DIRECT_VALUE);
+
+ aArguments[2] = beans::PropertyValue("FirstCellAsLabel", -1, uno::Any(false),
+ beans::PropertyState_DIRECT_VALUE);
+
+ aArguments[3] = beans::PropertyValue("HasCategories", -1, uno::Any(true),
+ beans::PropertyState_DIRECT_VALUE);
+
+ return aArguments;
+}
+
+sal_Bool SAL_CALL PivotTableDataProvider::createDataSequenceByRangeRepresentationPossible(const OUString& /*aRangeRepresentation*/)
+{
+ SolarMutexGuard aGuard;
+ return false;
+}
+
+uno::Reference<chart2::data::XDataSequence> SAL_CALL
+ PivotTableDataProvider::createDataSequenceByRangeRepresentation(const OUString& /*rRangeRepresentation*/)
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<chart2::data::XDataSequence> xDataSequence;
+ return xDataSequence;
+}
+
+uno::Reference<chart2::data::XDataSequence> SAL_CALL
+ PivotTableDataProvider::createDataSequenceByValueArray(const OUString& /*aRole*/,
+ const OUString& /*aRangeRepresentation*/)
+{
+ return uno::Reference<chart2::data::XDataSequence>();
+}
+
+uno::Reference<sheet::XRangeSelection> SAL_CALL PivotTableDataProvider::getRangeSelection()
+{
+ uno::Reference<sheet::XRangeSelection> xResult;
+
+ uno::Reference<frame::XModel> xModel(lcl_GetXModel(m_pDocument));
+ if (xModel.is())
+ xResult.set(xModel->getCurrentController(), uno::UNO_QUERY);
+
+ return xResult;
+}
+
+uno::Sequence<chart2::data::PivotTableFieldEntry> PivotTableDataProvider::getColumnFields()
+{
+ return comphelper::containerToSequence(m_aColumnFields);
+}
+
+uno::Sequence<chart2::data::PivotTableFieldEntry> PivotTableDataProvider::getRowFields()
+{
+ return comphelper::containerToSequence(m_aRowFields);
+}
+
+uno::Sequence<chart2::data::PivotTableFieldEntry> PivotTableDataProvider::getPageFields()
+{
+ return comphelper::containerToSequence(m_aPageFields);
+}
+
+uno::Sequence<chart2::data::PivotTableFieldEntry> PivotTableDataProvider::getDataFields()
+{
+ return comphelper::containerToSequence(m_aDataFields);
+}
+
+OUString PivotTableDataProvider::getPivotTableName()
+{
+ return m_sPivotTableName;
+}
+
+void PivotTableDataProvider::setPivotTableName(const OUString& sPivotTableName)
+{
+ ScDPCollection* pDPCollection = m_pDocument->GetDPCollection();
+ ScDPObject* pDPObject = pDPCollection->GetByName(sPivotTableName);
+ if (pDPObject)
+ m_sPivotTableName = sPivotTableName;
+}
+
+uno::Reference<chart2::data::XDataSequence>
+ PivotTableDataProvider::createDataSequenceOfValuesByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+
+ if (m_bNeedsUpdate)
+ collectPivotTableData();
+
+ uno::Reference<chart2::data::XDataSequence> xDataSequence;
+ assignValuesToDataSequence(xDataSequence, size_t(nIndex));
+ return xDataSequence;
+}
+
+uno::Reference<css::chart2::data::XDataSequence>
+ PivotTableDataProvider::createDataSequenceOfLabelsByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+
+ if (m_bNeedsUpdate)
+ collectPivotTableData();
+
+ uno::Reference<chart2::data::XDataSequence> xDataSequence;
+ assignLabelsToDataSequence(xDataSequence, size_t(nIndex));
+ return xDataSequence;
+}
+
+uno::Reference<css::chart2::data::XDataSequence>
+ PivotTableDataProvider::createDataSequenceOfCategories()
+{
+ SolarMutexGuard aGuard;
+
+ if (m_bNeedsUpdate)
+ collectPivotTableData();
+
+ uno::Reference<chart2::data::XDataSequence> xDataSequence;
+
+ if (m_aCategoriesColumnOrientation.empty())
+ return xDataSequence;
+
+ std::vector<ValueAndFormat> const & rCategories = m_aCategoriesColumnOrientation[0];
+
+ std::unique_ptr<PivotTableDataSequence> pSequence(new PivotTableDataSequence(m_pDocument, m_sPivotTableName,
+ "Categories", rCategories));
+ pSequence->setRole("categories");
+ xDataSequence.set(uno::Reference<chart2::data::XDataSequence>(pSequence.release()));
+
+ return xDataSequence;
+}
+
+// XModifyBroadcaster ========================================================
+
+void SAL_CALL PivotTableDataProvider::addModifyListener(const uno::Reference< util::XModifyListener>& aListener)
+{
+ SolarMutexGuard aGuard;
+
+ m_aValueListeners.push_back(uno::Reference<util::XModifyListener>(aListener));
+}
+
+void SAL_CALL PivotTableDataProvider::removeModifyListener(const uno::Reference<util::XModifyListener>& aListener )
+{
+ SolarMutexGuard aGuard;
+
+ sal_uInt16 nCount = m_aValueListeners.size();
+ for (sal_uInt16 n = nCount; n--;)
+ {
+ uno::Reference<util::XModifyListener>& rObject = m_aValueListeners[n];
+ if (rObject == aListener)
+ {
+ m_aValueListeners.erase(m_aValueListeners.begin() + n);
+ }
+ }
+}
+
+// DataProvider XPropertySet -------------------------------------------------
+
+uno::Reference< beans::XPropertySetInfo> SAL_CALL
+ PivotTableDataProvider::getPropertySetInfo()
+{
+ SolarMutexGuard aGuard;
+ static uno::Reference<beans::XPropertySetInfo> aRef =
+ new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
+ return aRef;
+}
+
+void SAL_CALL PivotTableDataProvider::setPropertyValue(const OUString& rPropertyName, const uno::Any& rValue)
+{
+ if (rPropertyName == SC_UNONAME_INCLUDEHIDDENCELLS)
+ {
+ if (!(rValue >>= m_bIncludeHiddenCells))
+ throw lang::IllegalArgumentException();
+ }
+ else
+ throw beans::UnknownPropertyException();
+}
+
+uno::Any SAL_CALL PivotTableDataProvider::getPropertyValue(const OUString& rPropertyName)
+{
+ uno::Any aRet;
+ if (rPropertyName == SC_UNONAME_INCLUDEHIDDENCELLS)
+ aRet <<= m_bIncludeHiddenCells;
+ else if (rPropertyName == SC_UNONAME_USE_INTERNAL_DATA_PROVIDER)
+ {
+ // This is a read-only property.
+ aRet <<= m_pDocument->PastingDrawFromOtherDoc();
+ }
+ else
+ throw beans::UnknownPropertyException();
+ return aRet;
+}
+
+void SAL_CALL PivotTableDataProvider::addPropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference<beans::XPropertyChangeListener>& /*xListener*/)
+{
+ OSL_FAIL("Not yet implemented");
+}
+
+void SAL_CALL PivotTableDataProvider::removePropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference<beans::XPropertyChangeListener>& /*rListener*/)
+{
+ OSL_FAIL("Not yet implemented");
+}
+
+void SAL_CALL PivotTableDataProvider::addVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference<beans::XVetoableChangeListener>& /*rListener*/)
+{
+ OSL_FAIL("Not yet implemented");
+}
+
+void SAL_CALL PivotTableDataProvider::removeVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference<beans::XVetoableChangeListener>& /*rListener*/ )
+{
+ OSL_FAIL("Not yet implemented");
+}
+
+} // end sc namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/unoobj/PivotTableDataSequence.cxx b/sc/source/ui/unoobj/PivotTableDataSequence.cxx
new file mode 100644
index 000000000000..da8bb26c3dc3
--- /dev/null
+++ b/sc/source/ui/unoobj/PivotTableDataSequence.cxx
@@ -0,0 +1,278 @@
+/* -*- 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/.
+ */
+
+#include "PivotTableDataSequence.hxx"
+
+#include <sal/config.h>
+
+#include "miscuno.hxx"
+#include "document.hxx"
+#include "docsh.hxx"
+#include "hints.hxx"
+
+#include <com/sun/star/chart/ChartDataChangeEvent.hpp>
+
+using namespace css;
+
+namespace sc
+{
+
+SC_SIMPLE_SERVICE_INFO( PivotTableDataSequence, "PivotTableDataSequence", "com.sun.star.chart2.data.DataSequence")
+
+const SfxItemPropertyMapEntry* lcl_GetDataSequencePropertyMap()
+{
+ static const SfxItemPropertyMapEntry aDataSequencePropertyMap_Impl[] =
+ {
+ { OUString(SC_UNONAME_HIDDENVALUES), 0, cppu::UnoType<uno::Sequence<sal_Int32>>::get(), 0, 0 },
+ { OUString(SC_UNONAME_ROLE), 0, cppu::UnoType<css::chart2::data::DataSequenceRole>::get(), 0, 0 },
+ { OUString(SC_UNONAME_INCLUDEHIDDENCELLS), 0, cppu::UnoType<bool>::get(), 0, 0 },
+ { OUString(), 0, css::uno::Type(), 0, 0 }
+ };
+ return aDataSequencePropertyMap_Impl;
+}
+
+PivotTableDataSequence::PivotTableDataSequence(ScDocument* pDocument, OUString const & sPivotTableName, OUString const & sID,
+ std::vector<ValueAndFormat> const & rData)
+ : m_pDocument(pDocument)
+ , m_sPivotTableName(sPivotTableName)
+ , m_aID(sID)
+ , m_aData(rData)
+ , m_aPropSet(lcl_GetDataSequencePropertyMap())
+{
+ if (m_pDocument)
+ m_pDocument->AddUnoObject(*this);
+}
+
+PivotTableDataSequence::~PivotTableDataSequence()
+{
+ SolarMutexGuard g;
+
+ if (m_pDocument)
+ m_pDocument->RemoveUnoObject(*this);
+}
+
+void PivotTableDataSequence::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
+{
+ if (rHint.GetId() == SfxHintId::Dying)
+ {
+ m_pDocument = nullptr;
+ }
+}
+
+uno::Sequence<uno::Any> SAL_CALL PivotTableDataSequence::getData()
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pDocument)
+ throw uno::RuntimeException();
+
+ uno::Sequence<uno::Any> aSeq(m_aData.size());
+
+ size_t i = 0;
+ for (ValueAndFormat const & rItem : m_aData)
+ {
+ if (rItem.m_bIsValue)
+ aSeq[i] <<= double(rItem.m_fValue);
+ else
+ aSeq[i] <<= OUString(rItem.m_aString);
+ i++;
+ }
+ return aSeq;
+}
+
+// XNumericalDataSequence --------------------------------------------------
+
+uno::Sequence<double> SAL_CALL PivotTableDataSequence::getNumericalData()
+{
+ SolarMutexGuard aGuard;
+ if (!m_pDocument)
+ throw uno::RuntimeException();
+
+ uno::Sequence<double> aSeq(m_aData.size());
+
+ size_t i = 0;
+ for (ValueAndFormat const & rItem : m_aData)
+ {
+ aSeq[i] = rItem.m_fValue;
+ i++;
+ }
+ return aSeq;
+}
+
+// XTextualDataSequence --------------------------------------------------
+
+uno::Sequence<OUString> SAL_CALL PivotTableDataSequence::getTextualData()
+{
+ SolarMutexGuard aGuard;
+ if (!m_pDocument)
+ throw uno::RuntimeException();
+
+ uno::Sequence<OUString> aSeq(m_aData.size());
+
+ size_t i = 0;
+ for (ValueAndFormat const & rItem : m_aData)
+ {
+ if (!rItem.m_bIsValue)
+ aSeq[i] = rItem.m_aString;
+ i++;
+ }
+ return aSeq;
+}
+
+OUString SAL_CALL PivotTableDataSequence::getSourceRangeRepresentation()
+{
+ SolarMutexGuard aGuard;
+
+ return m_aID;
+}
+
+uno::Sequence<OUString> SAL_CALL PivotTableDataSequence::generateLabel(chart2::data::LabelOrigin /*eOrigin*/)
+{
+ SolarMutexGuard aGuard;
+ if (!m_pDocument)
+ throw uno::RuntimeException();
+
+ uno::Sequence<OUString> aSeq;
+ return aSeq;
+}
+
+sal_Int32 SAL_CALL PivotTableDataSequence::getNumberFormatKeyByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+ if (nIndex == -1 && !m_aData.empty())
+ {
+ return m_aData[0].m_nNumberFormat;
+ }
+ else if (nIndex < 0 && size_t(nIndex) >= m_aData.size())
+ {
+ SAL_WARN("sc.ui", "Passed invalid index to getNumberFormatKeyByIndex(). Will return default value '0'.");
+ return 0;
+ }
+ return m_aData[size_t(nIndex)].m_nNumberFormat;
+}
+
+// XCloneable ================================================================
+
+uno::Reference<util::XCloneable> SAL_CALL PivotTableDataSequence::createClone()
+{
+ SolarMutexGuard aGuard;
+
+ std::unique_ptr<PivotTableDataSequence> pClone;
+ pClone.reset(new PivotTableDataSequence(m_pDocument, m_sPivotTableName, m_aID, m_aData));
+ pClone->setRole(m_aRole);
+
+ uno::Reference<util::XCloneable> xClone(pClone.release());
+
+ return xClone;
+}
+
+// XModifyBroadcaster ========================================================
+
+void SAL_CALL PivotTableDataSequence::addModifyListener(const uno::Reference<util::XModifyListener>& aListener)
+{
+ SolarMutexGuard aGuard;
+ m_aValueListeners.push_back(uno::Reference<util::XModifyListener>(aListener));
+}
+
+void SAL_CALL PivotTableDataSequence::removeModifyListener(const uno::Reference<util::XModifyListener>& aListener)
+{
+ SolarMutexGuard aGuard;
+
+ sal_uInt16 nCount = m_aValueListeners.size();
+ for (sal_uInt16 n = nCount; n--; )
+ {
+ uno::Reference<util::XModifyListener>& rObj = m_aValueListeners[n];
+ if (rObj == aListener)
+ {
+ m_aValueListeners.erase(m_aValueListeners.begin() + n);
+ }
+ }
+}
+
+// DataSequence XPropertySet -------------------------------------------------
+
+uno::Reference< beans::XPropertySetInfo> SAL_CALL PivotTableDataSequence::getPropertySetInfo()
+{
+ SolarMutexGuard aGuard;
+ static uno::Reference<beans::XPropertySetInfo> aRef = new SfxItemPropertySetInfo(m_aPropSet.getPropertyMap());
+ return aRef;
+}
+
+void SAL_CALL PivotTableDataSequence::setPropertyValue(const OUString& rPropertyName, const uno::Any& rValue)
+{
+ if (rPropertyName == SC_UNONAME_ROLE)
+ {
+ if (!(rValue >>= m_aRole))
+ throw lang::IllegalArgumentException();
+ }
+ else if (rPropertyName == SC_UNONAME_INCLUDEHIDDENCELLS
+ || rPropertyName == SC_UNONAME_HIDDENVALUES
+ || rPropertyName == SC_UNONAME_TIME_BASED
+ || rPropertyName == SC_UNONAME_HAS_STRING_LABEL)
+ {}
+ else
+ throw beans::UnknownPropertyException();
+}
+
+uno::Any SAL_CALL PivotTableDataSequence::getPropertyValue(const OUString& rPropertyName)
+{
+ uno::Any aReturn;
+ if (rPropertyName == SC_UNONAME_ROLE)
+ aReturn <<= m_aRole;
+ else if (rPropertyName == SC_UNONAME_INCLUDEHIDDENCELLS)
+ aReturn <<= false;
+ else if (rPropertyName == SC_UNONAME_HIDDENVALUES)
+ {
+ css::uno::Sequence<sal_Int32> aHiddenValues;
+ aReturn <<= aHiddenValues;
+ }
+ else if (rPropertyName == SC_UNONAME_TIME_BASED)
+ {
+ aReturn <<= false;
+ }
+ else if (rPropertyName == SC_UNONAME_HAS_STRING_LABEL)
+ {
+ aReturn <<= false;
+ }
+ else
+ throw beans::UnknownPropertyException();
+ return aReturn;
+}
+
+void SAL_CALL PivotTableDataSequence::addPropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
+{
+ OSL_FAIL("Not yet implemented");
+}
+
+void SAL_CALL PivotTableDataSequence::removePropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
+{
+ OSL_FAIL("Not yet implemented");
+}
+
+void SAL_CALL PivotTableDataSequence::addVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
+{
+ OSL_FAIL("Not yet implemented");
+}
+
+void SAL_CALL PivotTableDataSequence::removeVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
+{
+ OSL_FAIL("Not yet implemented");
+}
+
+} // end sc namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/unoobj/PivotTableDataSource.cxx b/sc/source/ui/unoobj/PivotTableDataSource.cxx
new file mode 100644
index 000000000000..752f8a4b4efe
--- /dev/null
+++ b/sc/source/ui/unoobj/PivotTableDataSource.cxx
@@ -0,0 +1,51 @@
+/* -*- 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/.
+ */
+
+#include "PivotTableDataSource.hxx"
+
+#include <sal/config.h>
+
+#include "miscuno.hxx"
+#include "docsh.hxx"
+
+#include <comphelper/sequence.hxx>
+
+using namespace css;
+
+namespace sc
+{
+
+SC_SIMPLE_SERVICE_INFO(PivotTableDataSource, "PivotTableDataSource", "com.sun.star.chart2.data.DataSource")
+
+PivotTableDataSource::PivotTableDataSource(OUString const & aRangeRepresentation,
+ std::vector<css::uno::Reference<css::chart2::data::XLabeledDataSequence>>& xLabeledSequence)
+ : m_xLabeledSequence(xLabeledSequence)
+ , m_aRangeRepresentation(aRangeRepresentation)
+{
+}
+
+PivotTableDataSource::~PivotTableDataSource()
+{
+}
+
+void PivotTableDataSource::Notify(SfxBroadcaster& /*rBroadcaster*/, const SfxHint& /*rHint*/)
+{
+}
+
+uno::Sequence<uno::Reference<chart2::data::XLabeledDataSequence>> SAL_CALL
+ PivotTableDataSource::getDataSequences()
+{
+ SolarMutexGuard aGuard;
+
+ return comphelper::containerToSequence(m_xLabeledSequence);
+}
+
+} // end sc namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/unoobj/TablePivotChart.cxx b/sc/source/ui/unoobj/TablePivotChart.cxx
new file mode 100644
index 000000000000..64d2d87890b1
--- /dev/null
+++ b/sc/source/ui/unoobj/TablePivotChart.cxx
@@ -0,0 +1,104 @@
+/* -*- 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/.
+ */
+
+#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
+#include <svx/charthelper.hxx>
+#include <svtools/embedhlp.hxx>
+
+#include "miscuno.hxx"
+#include "docsh.hxx"
+
+#include "TablePivotChart.hxx"
+#include "ChartTools.hxx"
+
+using namespace css;
+
+namespace sc
+{
+
+SC_SIMPLE_SERVICE_INFO(TablePivotChart, "TablePivotChart", "com.sun.star.table.TablePivotChart")
+
+TablePivotChart::TablePivotChart(ScDocShell* pDocShell, SCTAB nTab, const OUString& rName)
+ : TablePivotChart_Base(m_aMutex)
+ , m_pDocShell(pDocShell)
+ , m_nTab(nTab)
+ , m_aChartName(rName)
+{
+ if (m_pDocShell)
+ m_pDocShell->GetDocument().AddUnoObject(*this);
+}
+
+TablePivotChart::~TablePivotChart()
+{
+ SolarMutexGuard aGuard;
+
+ if (m_pDocShell)
+ m_pDocShell->GetDocument().RemoveUnoObject(*this);
+}
+
+void TablePivotChart::Notify(SfxBroadcaster&, const SfxHint& rHint)
+{
+ if (rHint.GetId() == SfxHintId::Dying)
+ m_pDocShell = nullptr;
+}
+
+// XEmbeddedObjectSupplier
+
+uno::Reference<lang::XComponent> SAL_CALL TablePivotChart::getEmbeddedObject()
+{
+ SolarMutexGuard aGuard;
+ SdrOle2Obj* pObject = sc::tools::findChartsByName(m_pDocShell, m_nTab, m_aChartName, sc::tools::ChartSourceType::PIVOT_TABLE);
+ if (pObject && svt::EmbeddedObjectRef::TryRunningState(pObject->GetObjRef()))
+ return uno::Reference<lang::XComponent>(pObject->GetObjRef()->getComponent(), uno::UNO_QUERY);
+ return nullptr;
+}
+
+// XNamed
+
+OUString SAL_CALL TablePivotChart::getName()
+{
+ SolarMutexGuard aGuard;
+ return m_aChartName;
+}
+
+void SAL_CALL TablePivotChart::setName(OUString const & /* aName */)
+{
+ SolarMutexGuard aGuard;
+ throw uno::RuntimeException(); // name cannot be changed
+}
+
+// XTablePivotChart
+
+OUString SAL_CALL TablePivotChart::getPivotTableName()
+{
+ SolarMutexGuard aGuard;
+ OUString aPivotTableName;
+
+ SdrOle2Obj* pObject = sc::tools::findChartsByName(m_pDocShell, m_nTab, m_aChartName, sc::tools::ChartSourceType::PIVOT_TABLE);
+
+ uno::Reference<embed::XEmbeddedObject> xObject = pObject->GetObjRef();
+ if (xObject.is())
+ {
+ uno::Reference<chart2::XChartDocument> xChartDoc(xObject->getComponent(), uno::UNO_QUERY);
+ if (xChartDoc.is())
+ {
+ uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(xChartDoc->getDataProvider(), uno::UNO_QUERY);
+ if (xPivotTableDataProvider.is())
+ {
+ aPivotTableName = xPivotTableDataProvider->getPivotTableName();
+ }
+ }
+ }
+
+ return aPivotTableName;
+}
+
+} // end sc namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/unoobj/TablePivotCharts.cxx b/sc/source/ui/unoobj/TablePivotCharts.cxx
new file mode 100644
index 000000000000..e76a88b05f25
--- /dev/null
+++ b/sc/source/ui/unoobj/TablePivotCharts.cxx
@@ -0,0 +1,279 @@
+/* -*- 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/.
+ */
+
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/chart2/data/XDataReceiver.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+#include <tools/gen.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdundo.hxx>
+#include <svx/charthelper.hxx>
+#include <sfx2/app.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <comphelper/classids.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/globname.hxx>
+#include <svtools/embedhlp.hxx>
+#include <comphelper/sequence.hxx>
+
+#include "TablePivotChart.hxx"
+#include "TablePivotCharts.hxx"
+#include "PivotTableDataProvider.hxx"
+#include "ChartTools.hxx"
+
+#include "miscuno.hxx"
+#include "docsh.hxx"
+#include "drwlayer.hxx"
+#include "undodat.hxx"
+#include "convuno.hxx"
+
+using namespace css;
+
+namespace sc
+{
+
+SC_SIMPLE_SERVICE_INFO(TablePivotCharts, "TablePivotCharts", "com.sun.star.table.TablePivotCharts")
+
+TablePivotCharts::TablePivotCharts(ScDocShell* pDocShell, SCTAB nTab)
+ : m_pDocShell(pDocShell)
+ , m_nTab(nTab)
+{
+ m_pDocShell->GetDocument().AddUnoObject(*this);
+}
+
+TablePivotCharts::~TablePivotCharts()
+{
+ SolarMutexGuard aGuard;
+
+ if (m_pDocShell)
+ m_pDocShell->GetDocument().RemoveUnoObject(*this);
+}
+
+void TablePivotCharts::Notify(SfxBroadcaster& /*rBroadcaster*/, const SfxHint& rHint)
+{
+ if (rHint.GetId() == SfxHintId::Dying)
+ m_pDocShell = nullptr;
+}
+
+// XTablePivotCharts
+void SAL_CALL TablePivotCharts::addNewByName(OUString const & rName,
+ const awt::Rectangle& aRect,
+ OUString const & rDataPilotName)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pDocShell)
+ return;
+
+ ScDocument& rDoc = m_pDocShell->GetDocument();
+ ScDrawLayer* pModel = m_pDocShell->MakeDrawLayer();
+ SdrPage* pPage = pModel->GetPage(sal_uInt16(m_nTab));
+ if (!pPage)
+ return;
+
+ // chart can't be inserted if any ole object with that name exists on any table
+ // (empty string: generate valid name)
+
+ OUString aName = rName;
+ SCTAB nDummy;
+ if (!aName.isEmpty() && pModel->GetNamedObject(aName, OBJ_OLE2, nDummy))
+ {
+ // object exists - only RuntimeException is specified
+ throw uno::RuntimeException();
+ }
+
+ uno::Reference<embed::XEmbeddedObject> xObject;
+
+ if (SvtModuleOptions().IsChart())
+ xObject = m_pDocShell->GetEmbeddedObjectContainer().CreateEmbeddedObject(SvGlobalName(SO3_SCH_CLASSID).GetByteSequence(), aName);
+
+ if (xObject.is())
+ {
+ Point aRectPos(aRect.X, aRect.Y);
+ bool bLayoutRTL = rDoc.IsLayoutRTL(m_nTab);
+ if ((aRectPos.X() < 0 && !bLayoutRTL) || (aRectPos.X() > 0 && bLayoutRTL))
+ aRectPos.X() = 0;
+
+ if (aRectPos.Y() < 0)
+ aRectPos.Y() = 0;
+
+ Size aRectSize(aRect.Width, aRect.Height);
+ if (aRectSize.Width() <= 0)
+ aRectSize.Width() = 5000; // default size
+
+ if (aRectSize.Height() <= 0)
+ aRectSize.Height() = 5000;
+
+ ::tools::Rectangle aInsRect(aRectPos, aRectSize);
+
+ sal_Int64 nAspect(embed::Aspects::MSOLE_CONTENT);
+ MapUnit aMapUnit(VCLUnoHelper::UnoEmbed2VCLMapUnit(xObject->getMapUnit(nAspect)));
+ Size aSize(aInsRect.GetSize());
+ aSize = vcl::Window::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(aMapUnit));
+ awt::Size aAwtSize;
+ aAwtSize.Width = aSize.Width();
+ aAwtSize.Height = aSize.Height();
+
+ std::unique_ptr<sc::PivotTableDataProvider> pPivotTableDataProvider(new sc::PivotTableDataProvider(&rDoc));
+ pPivotTableDataProvider->setPivotTableName(rDataPilotName);
+
+ uno::Reference<chart2::data::XDataProvider> xDataProvider(pPivotTableDataProvider.release());
+
+ uno::Reference<chart2::data::XDataReceiver> xReceiver;
+ uno::Reference<embed::XComponentSupplier> xCompSupp(xObject, uno::UNO_QUERY);
+
+ if (xCompSupp.is())
+ xReceiver.set(xCompSupp->getComponent(), uno::UNO_QUERY);
+
+ if (xReceiver.is())
+ {
+ xReceiver->attachDataProvider(xDataProvider);
+
+ uno::Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier(m_pDocShell->GetModel(), uno::UNO_QUERY);
+ xReceiver->attachNumberFormatsSupplier(xNumberFormatsSupplier);
+
+ uno::Sequence<beans::PropertyValue> aArgs(3);
+ aArgs[0] = beans::PropertyValue("CellRangeRepresentation", -1, uno::makeAny(OUString(rDataPilotName)), beans::PropertyState_DIRECT_VALUE);
+ aArgs[1] = beans::PropertyValue("HasCategories", -1, uno::makeAny(true), beans::PropertyState_DIRECT_VALUE);
+ aArgs[2] = beans::PropertyValue("DataRowSource", -1, uno::makeAny(chart::ChartDataRowSource_COLUMNS), beans::PropertyState_DIRECT_VALUE);
+ xReceiver->setArguments(aArgs);
+ }
+
+ SdrOle2Obj* pObject = new SdrOle2Obj(svt::EmbeddedObjectRef(xObject, embed::Aspects::MSOLE_CONTENT),
+ aName, aInsRect);
+
+ if (xObject.is())
+ xObject->setVisualAreaSize(nAspect, aAwtSize);
+
+ pPage->InsertObject(pObject);
+ pModel->AddUndo(new SdrUndoInsertObj(*pObject));
+ }
+}
+
+void SAL_CALL TablePivotCharts::removeByName(const OUString& rName)
+{
+ SolarMutexGuard aGuard;
+ SdrOle2Obj* pObject = sc::tools::findChartsByName(m_pDocShell, m_nTab, rName, sc::tools::ChartSourceType::PIVOT_TABLE);
+ if (pObject)
+ {
+ ScDocument& rDoc = m_pDocShell->GetDocument();
+ ScDrawLayer* pModel = rDoc.GetDrawLayer();
+ SdrPage* pPage = pModel->GetPage(sal_uInt16(m_nTab));
+ pModel->AddUndo(new SdrUndoDelObj(*pObject));
+ pPage->RemoveObject(pObject->GetOrdNum());
+ }
+}
+
+// XIndexAccess
+sal_Int32 SAL_CALL TablePivotCharts::getCount()
+{
+ SolarMutexGuard aGuard;
+ sal_Int32 nCount = 0;
+
+ if (!m_pDocShell)
+ return nCount;
+
+ sc::tools::ChartIterator aIterator(m_pDocShell, m_nTab, sc::tools::ChartSourceType::PIVOT_TABLE);
+
+ SdrOle2Obj* pOleObject = aIterator.next();
+ while (pOleObject)
+ {
+ if (pOleObject->GetObjRef().is())
+ nCount++;
+ pOleObject = aIterator.next();
+ }
+ return nCount;
+}
+
+uno::Any SAL_CALL TablePivotCharts::getByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+ SdrOle2Obj* pObject = sc::tools::getChartByIndex(m_pDocShell, m_nTab, nIndex,
+ sc::tools::ChartSourceType::PIVOT_TABLE);
+ if (!pObject)
+ throw lang::IndexOutOfBoundsException();
+
+ OUString aName;
+ uno::Reference<embed::XEmbeddedObject> xObject = pObject->GetObjRef();
+ if (xObject.is())
+ aName = m_pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName(xObject);
+
+ if (aName.isEmpty())
+ throw lang::IndexOutOfBoundsException();
+
+ uno::Reference<table::XTablePivotChart> xChart(new TablePivotChart(m_pDocShell, m_nTab, aName));
+ if (xChart.is())
+ return uno::makeAny(xChart);
+ else
+ throw lang::IndexOutOfBoundsException();
+}
+
+uno::Type SAL_CALL TablePivotCharts::getElementType()
+{
+ SolarMutexGuard aGuard;
+ return cppu::UnoType<table::XTablePivotChart>::get();
+}
+
+sal_Bool SAL_CALL TablePivotCharts::hasElements()
+{
+ SolarMutexGuard aGuard;
+ return getCount() != 0;
+}
+
+uno::Any SAL_CALL TablePivotCharts::getByName(OUString const & rName)
+{
+ SolarMutexGuard aGuard;
+
+ if (!sc::tools::findChartsByName(m_pDocShell, m_nTab, rName, sc::tools::ChartSourceType::PIVOT_TABLE))
+ throw container::NoSuchElementException();
+
+ uno::Reference<table::XTablePivotChart> xChart(new TablePivotChart(m_pDocShell, m_nTab, rName));
+ if (xChart.is())
+ return uno::makeAny(xChart);
+ else
+ throw container::NoSuchElementException();
+}
+
+uno::Sequence<OUString> SAL_CALL TablePivotCharts::getElementNames()
+{
+ SolarMutexGuard aGuard;
+
+ std::vector<OUString> aElements;
+ sc::tools::ChartIterator aIterator(m_pDocShell, m_nTab, sc::tools::ChartSourceType::PIVOT_TABLE);
+
+ SdrOle2Obj* pOleObject = aIterator.next();
+ while (pOleObject)
+ {
+ uno::Reference<embed::XEmbeddedObject> xObject = pOleObject->GetObjRef();
+ if (xObject.is())
+ {
+ OUString aName = m_pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName(xObject);
+ aElements.push_back(aName);
+ }
+ pOleObject = aIterator.next();
+ }
+ return comphelper::containerToSequence(aElements);
+}
+
+sal_Bool SAL_CALL TablePivotCharts::hasByName(OUString const & rName)
+{
+ SolarMutexGuard aGuard;
+
+ return sc::tools::findChartsByName(m_pDocShell, m_nTab, rName, sc::tools::ChartSourceType::PIVOT_TABLE) != nullptr;
+}
+
+} // end sc namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index 0c597a82934e..6a4f61012ba9 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -130,6 +130,7 @@
#include "dputil.hxx"
#include <sortparam.hxx>
#include "condformatuno.hxx"
+#include "TablePivotCharts.hxx"
#include <list>
#include <memory>
@@ -6726,6 +6727,7 @@ uno::Any SAL_CALL ScTableSheetObj::queryInterface( const uno::Type& rType )
SC_QUERYINTERFACE( sheet::XSheetLinkable )
SC_QUERYINTERFACE( sheet::XExternalSheetName )
SC_QUERYINTERFACE( document::XEventsSupplier )
+ SC_QUERYINTERFACE( table::XTablePivotChartsSupplier )
return ScCellRangeObj::queryInterface( rType );
}
@@ -6749,7 +6751,8 @@ uno::Sequence<uno::Type> SAL_CALL ScTableSheetObj::getTypes()
long nParentLen = aParentTypes.getLength();
const uno::Type* pParentPtr = aParentTypes.getConstArray();
- aTypes.realloc( nParentLen + 18 );
+ aTypes.realloc(nParentLen + 19);
+
uno::Type* pPtr = aTypes.getArray();
pPtr[nParentLen + 0] = cppu::UnoType<sheet::XSpreadsheet>::get();
pPtr[nParentLen + 1] = cppu::UnoType<container::XNamed>::get();
@@ -6769,6 +6772,7 @@ uno::Sequence<uno::Type> SAL_CALL ScTableSheetObj::getTypes()
pPtr[nParentLen +15] = cppu::UnoType<sheet::XSheetLinkable>::get();
pPtr[nParentLen +16] = cppu::UnoType<sheet::XExternalSheetName>::get();
pPtr[nParentLen +17] = cppu::UnoType<document::XEventsSupplier>::get();
+ pPtr[nParentLen +18] = cppu::UnoType<table::XTablePivotChartsSupplier>::get();
for (long i=0; i<nParentLen; i++)
pPtr[i] = pParentPtr[i]; // parent types first
@@ -6808,6 +6812,17 @@ uno::Reference<table::XTableCharts> SAL_CALL ScTableSheetObj::getCharts()
return nullptr;
}
+uno::Reference<table::XTablePivotCharts> SAL_CALL ScTableSheetObj::getPivotCharts()
+{
+ SolarMutexGuard aGuard;
+ ScDocShell* pDocSh = GetDocShell();
+ if (pDocSh)
+ return new sc::TablePivotCharts(pDocSh, GetTab_Impl());
+
+ OSL_FAIL("no Document");
+ return nullptr;
+}
+
uno::Reference<sheet::XDataPilotTables> SAL_CALL ScTableSheetObj::getDataPilotTables()
{
SolarMutexGuard aGuard;
diff --git a/sc/source/ui/unoobj/chartuno.cxx b/sc/source/ui/unoobj/chartuno.cxx
index 78152703066f..20c3f9e1f989 100644
--- a/sc/source/ui/unoobj/chartuno.cxx
+++ b/sc/source/ui/unoobj/chartuno.cxx
@@ -38,6 +38,7 @@
#include <svx/charthelper.hxx>
#include <svtools/embedhlp.hxx>
+#include "ChartTools.hxx"
#include "chartuno.hxx"
#include "miscuno.hxx"
#include "docsh.hxx"
@@ -48,47 +49,13 @@
#include "chart2uno.hxx"
#include "convuno.hxx"
-using namespace com::sun::star;
+using namespace css;
#define PROP_HANDLE_RELATED_CELLRANGES 1
SC_SIMPLE_SERVICE_INFO( ScChartObj, "ScChartObj", "com.sun.star.table.TableChart" )
SC_SIMPLE_SERVICE_INFO( ScChartsObj, "ScChartsObj", "com.sun.star.table.TableCharts" )
-static SdrOle2Obj* lcl_FindChartObj( ScDocShell* pDocShell, SCTAB nTab, const OUString& rName )
-{
- if (pDocShell)
- {
- ScDocument& rDoc = pDocShell->GetDocument();
- ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
- if (pDrawLayer)
- {
- SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
- OSL_ENSURE(pPage, "Page nicht gefunden");
- if (pPage)
- {
- SdrObjListIter aIter( *pPage, SdrIterMode::DeepNoGroups );
- SdrObject* pObject = aIter.Next();
- while (pObject)
- {
- if ( pObject->GetObjIdentifier() == OBJ_OLE2 && ScDocument::IsChart(pObject) )
- {
- uno::Reference < embed::XEmbeddedObject > xObj = static_cast<SdrOle2Obj*>(pObject)->GetObjRef();
- if ( xObj.is() )
- {
- OUString aObjName = pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName( xObj );
- if ( aObjName == rName )
- return static_cast<SdrOle2Obj*>(pObject);
- }
- }
- pObject = aIter.Next();
- }
- }
- }
- }
- return nullptr;
-}
-
ScChartsObj::ScChartsObj(ScDocShell* pDocSh, SCTAB nT) :
pDocShell( pDocSh ),
nTab( nT )
@@ -156,7 +123,7 @@ ScChartObj* ScChartsObj::GetObjectByIndex_Impl(long nIndex) const
ScChartObj* ScChartsObj::GetObjectByName_Impl(const OUString& aName) const
{
- if ( lcl_FindChartObj( pDocShell, nTab, aName ) )
+ if (sc::tools::findChartsByName(pDocShell, nTab, aName, sc::tools::ChartSourceType::CELL_RANGE))
return new ScChartObj( pDocShell, nTab, aName );
return nullptr;
}
@@ -297,7 +264,7 @@ void SAL_CALL ScChartsObj::addNewByName( const OUString& rName,
void SAL_CALL ScChartsObj::removeByName( const OUString& aName )
{
SolarMutexGuard aGuard;
- SdrOle2Obj* pObj = lcl_FindChartObj( pDocShell, nTab, aName );
+ SdrOle2Obj* pObj = sc::tools::findChartsByName(pDocShell, nTab, aName, sc::tools::ChartSourceType::CELL_RANGE);
if (pObj)
{
ScDocument& rDoc = pDocShell->GetDocument();
@@ -429,7 +396,9 @@ uno::Sequence<OUString> SAL_CALL ScChartsObj::getElementNames()
sal_Bool SAL_CALL ScChartsObj::hasByName( const OUString& aName )
{
SolarMutexGuard aGuard;
- return ( lcl_FindChartObj( pDocShell, nTab, aName ) != nullptr );
+ SdrOle2Obj* aOle2Obj = sc::tools::findChartsByName(pDocShell, nTab, aName,
+ sc::tools::ChartSourceType::CELL_RANGE);
+ return aOle2Obj != nullptr;
}
ScChartObj::ScChartObj(ScDocShell* pDocSh, SCTAB nT, const OUString& rN)
@@ -742,7 +711,8 @@ void SAL_CALL ScChartObj::setRanges( const uno::Sequence<table::CellRangeAddress
uno::Reference<lang::XComponent> SAL_CALL ScChartObj::getEmbeddedObject()
{
SolarMutexGuard aGuard;
- SdrOle2Obj* pObject = lcl_FindChartObj( pDocShell, nTab, aChartName );
+ SdrOle2Obj* pObject = sc::tools::findChartsByName(pDocShell, nTab, aChartName,
+ sc::tools::ChartSourceType::CELL_RANGE);
if ( pObject && svt::EmbeddedObjectRef::TryRunningState( pObject->GetObjRef() ) )
{
//TODO/LATER: is it OK that something is returned for *all* objects, not only own objects?
diff --git a/sc/source/ui/unoobj/servuno.cxx b/sc/source/ui/unoobj/servuno.cxx
index 6b2fac6b79e8..04fb81f7776f 100644
--- a/sc/source/ui/unoobj/servuno.cxx
+++ b/sc/source/ui/unoobj/servuno.cxx
@@ -44,6 +44,7 @@
#include "addruno.hxx"
#include "chart2uno.hxx"
#include "tokenuno.hxx"
+#include "PivotTableDataProvider.hxx"
// Support creation of GraphicObjectResolver and EmbeddedObjectResolver
#include <svx/xmleohlp.hxx>
@@ -292,6 +293,7 @@ const ProvNamesId_Type aProvNamesId[] =
{ "com.sun.star.sheet.DocumentSettings",Type::SHEETDOCSET },
{ SC_SERVICENAME_CHDATAPROV, Type::CHDATAPROV },
+ { SC_SERVICENAME_CHART_PIVOTTABLE_DATAPROVIDER, Type::CHART_PIVOTTABLE_DATAPROVIDER },
{ SC_SERVICENAME_FORMULAPARS, Type::FORMULAPARS },
{ SC_SERVICENAME_OPCODEMAPPER, Type::OPCODEMAPPER },
{ "ooo.vba.VBAObjectModuleObjectProvider", Type::VBAOBJECTPROVIDER },
@@ -388,6 +390,7 @@ uno::Reference<uno::XInterface> ScServiceProvider::MakeInstance(
Type nType, ScDocShell* pDocShell )
{
uno::Reference<uno::XInterface> xRet;
+
switch (nType)
{
case Type::SHEET:
@@ -523,6 +526,10 @@ uno::Reference<uno::XInterface> ScServiceProvider::MakeInstance(
if (pDocShell)
xRet = *new ScChart2DataProvider( &pDocShell->GetDocument() );
break;
+ case Type::CHART_PIVOTTABLE_DATAPROVIDER:
+ if (pDocShell)
+ xRet = *new sc::PivotTableDataProvider(&pDocShell->GetDocument());
+ break;
case Type::FORMULAPARS:
if (pDocShell)
xRet.set(static_cast<sheet::XFormulaParser*>(new ScFormulaParserObj( pDocShell )));
diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx
index 84c56659065e..71204128ce60 100644
--- a/sc/source/ui/view/tabview3.cxx
+++ b/sc/source/ui/view/tabview3.cxx
@@ -2469,27 +2469,23 @@ void ScTabView::DoChartSelection(
}
}
-void ScTabView::DoDPFieldPopup(Point aPoint, Size /*aSize*/)
+void ScTabView::DoDPFieldPopup(OUString const & rPivotTableName, sal_Int32 nDimensionIndex, Point aPoint, Size aSize)
{
ScDocument& rDocument = aViewData.GetDocShell()->GetDocument();
ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()].get();
+
if (!pWin)
return;
- ScDPCollection* pDPs = rDocument.GetDPCollection();
- // TODO - DP name should be a parameter
- ScDPObject* pDPObj = pDPs->GetByName("DataPilot1");
-
- pDPObj->BuildAllDimensionMembers();
+ ScDPCollection* pDPCollection = rDocument.GetDPCollection();
+ ScDPObject* pDPObject = pDPCollection->GetByName(rPivotTableName);
- //const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
- //bool bIsDataLayout;
- //OUString aDimName = pDPObj->GetDimName(0, bIsDataLayout);
+ pDPObject->BuildAllDimensionMembers();
Point aScreenPoint = pWin->OutputToScreenPixel(pWin->LogicToPixel(aPoint));
- //Size aScreenSize = pWin->LogicToPixel(aSize);
+ Size aScreenSize = pWin->LogicToPixel(aSize);
- pWin->DPLaunchFieldPopupMenu(aScreenPoint, Size(1, 1), 1, pDPObj);
+ pWin->DPLaunchFieldPopupMenu(aScreenPoint, aScreenSize, nDimensionIndex, pDPObject);
}
// PaintGrid - repaint data range
diff --git a/sc/source/ui/view/tabvwshb.cxx b/sc/source/ui/view/tabvwshb.cxx
index 3dced2749fd7..52990c0f9428 100644
--- a/sc/source/ui/view/tabvwshb.cxx
+++ b/sc/source/ui/view/tabvwshb.cxx
@@ -19,6 +19,8 @@
#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
#include <com/sun/star/chart2/data/XDataReceiver.hpp>
+#include <com/sun/star/awt/XRequestCallback.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/embed/EmbedMisc.hpp>
#include <com/sun/star/embed/EmbedStates.hpp>
@@ -111,10 +113,32 @@ public:
{}
// XCallback
- virtual void SAL_CALL notify(const css::uno::Any& /*aData*/) override
+ virtual void SAL_CALL notify(const css::uno::Any& aData) override
{
- tools::Rectangle aRect = m_pObject->GetLogicRect();
- m_pViewShell->DoDPFieldPopup(aRect.TopLeft(), aRect.GetSize());
+ uno::Sequence<beans::PropertyValue> aProperties;
+ if (aData >>= aProperties)
+ {
+ awt::Rectangle xRectangle;
+ sal_Int32 dimensionIndex = 0;
+ OUString sPivotTableName("DataPilot1");
+
+ for (beans::PropertyValue const & rProperty : aProperties)
+ {
+ if (rProperty.Name == "Rectangle")
+ rProperty.Value >>= xRectangle;
+ if (rProperty.Name == "DimensionIndex")
+ rProperty.Value >>= dimensionIndex;
+ if (rProperty.Name == "PivotTableName")
+ rProperty.Value >>= sPivotTableName;
+ }
+
+ tools::Rectangle aChartRect = m_pObject->GetLogicRect();
+
+ Point aPoint(xRectangle.X + aChartRect.Left(), xRectangle.Y + aChartRect.Top());
+ Size aSize(xRectangle.Width, xRectangle.Height);
+
+ m_pViewShell->DoDPFieldPopup(sPivotTableName, dimensionIndex, aPoint, aSize);
+ }
}
};
@@ -209,7 +233,7 @@ void ScTabViewShell::ActivateObject( SdrOle2Obj* pObj, long nVerb )
new ScChartRangeSelectionListener( this ));
xRangeHightlighter->addSelectionChangeListener( xListener );
}
- uno::Reference<chart2::data::XPopupRequest> xPopupRequest(xDataReceiver->getPopupRequest());
+ uno::Reference<awt::XRequestCallback> xPopupRequest(xDataReceiver->getPopupRequest());
if (xPopupRequest.is())
{
uno::Reference<awt::XCallback> xCallback(new PopupCallback(this, pObj));