fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / data / dpsave.cxx
blobfc86515368256392c99175ebf5376a05dca6a58b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "dpsave.hxx"
21 #include "dpdimsave.hxx"
22 #include "miscuno.hxx"
23 #include "scerrors.hxx"
24 #include "unonames.hxx"
25 #include "global.hxx"
26 #include "dptabsrc.hxx"
27 #include "dputil.hxx"
29 #include <sal/types.h>
30 #include <osl/diagnose.h>
31 #include <comphelper/string.hxx>
33 #include <com/sun/star/sheet/GeneralFunction.hpp>
34 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
35 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
36 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
37 #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
38 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
39 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
40 #include <com/sun/star/sheet/TableFilterField.hpp>
41 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
42 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
43 #include <com/sun/star/sheet/XMembersSupplier.hpp>
44 #include <com/sun/star/container/XNamed.hpp>
45 #include <com/sun/star/util/XCloneable.hpp>
47 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
48 #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
50 #include <unordered_map>
51 #include <unordered_set>
53 using namespace com::sun::star;
54 using namespace com::sun::star::sheet;
55 using ::com::sun::star::uno::Reference;
56 using ::com::sun::star::uno::Any;
57 using ::std::unique_ptr;
59 #define SC_DPSAVEMODE_DONTKNOW 2
61 static void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp,
62 const OUString& rName, bool bValue )
64 //TODO: move to ScUnoHelpFunctions?
66 xProp->setPropertyValue( rName, uno::Any( &bValue, cppu::UnoType<bool>::get() ) );
69 ScDPSaveMember::ScDPSaveMember(const OUString& rName) :
70 aName( rName ),
71 mpLayoutName(NULL),
72 nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
73 nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
77 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
78 aName( r.aName ),
79 mpLayoutName(NULL),
80 nVisibleMode( r.nVisibleMode ),
81 nShowDetailsMode( r.nShowDetailsMode )
83 if (r.mpLayoutName)
84 mpLayoutName.reset(new OUString(*r.mpLayoutName));
87 ScDPSaveMember::~ScDPSaveMember()
91 bool ScDPSaveMember::operator== ( const ScDPSaveMember& r ) const
93 if ( aName != r.aName ||
94 nVisibleMode != r.nVisibleMode ||
95 nShowDetailsMode != r.nShowDetailsMode )
96 return false;
98 return true;
101 bool ScDPSaveMember::HasIsVisible() const
103 return nVisibleMode != SC_DPSAVEMODE_DONTKNOW;
106 void ScDPSaveMember::SetIsVisible(bool bSet)
108 nVisibleMode = sal_uInt16(bSet);
111 bool ScDPSaveMember::HasShowDetails() const
113 return nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW;
116 void ScDPSaveMember::SetShowDetails(bool bSet)
118 nShowDetailsMode = sal_uInt16(bSet);
121 void ScDPSaveMember::SetName( const OUString& rNew )
123 // Used only if the source member was renamed (groups).
124 // For UI renaming of members, a layout name must be used.
126 aName = rNew;
129 void ScDPSaveMember::SetLayoutName( const OUString& rName )
131 mpLayoutName.reset(new OUString(rName));
134 const OUString* ScDPSaveMember::GetLayoutName() const
136 return mpLayoutName.get();
139 void ScDPSaveMember::RemoveLayoutName()
141 mpLayoutName.reset();
144 void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
146 uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
147 OSL_ENSURE( xMembProp.is(), "no properties at member" );
148 if ( xMembProp.is() )
150 // exceptions are caught at ScDPSaveData::WriteToSource
152 if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW )
153 lcl_SetBoolProperty( xMembProp,
154 OUString(SC_UNO_DP_ISVISIBLE), (bool)nVisibleMode );
156 if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW )
157 lcl_SetBoolProperty( xMembProp,
158 OUString(SC_UNO_DP_SHOWDETAILS), (bool)nShowDetailsMode );
160 if (mpLayoutName)
161 ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_DP_LAYOUTNAME, *mpLayoutName);
163 if ( nPosition >= 0 )
164 ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_DP_POSITION, nPosition);
168 #if DEBUG_PIVOT_TABLE
170 void ScDPSaveMember::Dump(int nIndent) const
172 std::string aIndent(nIndent*4, ' ');
173 cout << aIndent << "* member name: '" << aName << "'" << endl;
175 cout << aIndent << " + layout name: ";
176 if (mpLayoutName)
177 cout << "'" << *mpLayoutName << "'";
178 else
179 cout << "(none)";
180 cout << endl;
182 cout << aIndent << " + visibility: ";
183 if (nVisibleMode == SC_DPSAVEMODE_DONTKNOW)
184 cout << "(unknown)";
185 else
186 cout << (nVisibleMode ? "visible" : "hidden");
187 cout << endl;
190 #endif
192 ScDPSaveDimension::ScDPSaveDimension(const OUString& rName, bool bDataLayout) :
193 aName( rName ),
194 mpLayoutName(NULL),
195 mpSubtotalName(NULL),
196 bIsDataLayout( bDataLayout ),
197 bDupFlag( false ),
198 nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ),
199 nFunction( sheet::GeneralFunction_AUTO ),
200 nUsedHierarchy( -1 ),
201 nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
202 bRepeatItemLabels( false ),
203 bSubTotalDefault( true ),
204 nSubTotalCount( 0 ),
205 pSubTotalFuncs( NULL ),
206 pReferenceValue( NULL ),
207 pSortInfo( NULL ),
208 pAutoShowInfo( NULL ),
209 pLayoutInfo( NULL )
213 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
214 aName( r.aName ),
215 mpLayoutName(NULL),
216 mpSubtotalName(NULL),
217 bIsDataLayout( r.bIsDataLayout ),
218 bDupFlag( r.bDupFlag ),
219 nOrientation( r.nOrientation ),
220 nFunction( r.nFunction ),
221 nUsedHierarchy( r.nUsedHierarchy ),
222 nShowEmptyMode( r.nShowEmptyMode ),
223 bRepeatItemLabels( r.bRepeatItemLabels ),
224 bSubTotalDefault( r.bSubTotalDefault ),
225 nSubTotalCount( r.nSubTotalCount ),
226 pSubTotalFuncs( NULL )
228 if ( nSubTotalCount && r.pSubTotalFuncs )
230 pSubTotalFuncs = new sal_uInt16[nSubTotalCount];
231 for (long nSub=0; nSub<nSubTotalCount; nSub++)
232 pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub];
235 for (MemberList::const_iterator i=r.maMemberList.begin(); i != r.maMemberList.end() ; ++i)
237 const OUString& rName = (*i)->GetName();
238 ScDPSaveMember* pNew = new ScDPSaveMember( **i );
239 maMemberHash[rName] = pNew;
240 maMemberList.push_back( pNew );
242 if (r.pReferenceValue)
243 pReferenceValue = new sheet::DataPilotFieldReference( *(r.pReferenceValue) );
244 else
245 pReferenceValue = NULL;
246 if (r.pSortInfo)
247 pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) );
248 else
249 pSortInfo = NULL;
250 if (r.pAutoShowInfo)
251 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) );
252 else
253 pAutoShowInfo = NULL;
254 if (r.pLayoutInfo)
255 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
256 else
257 pLayoutInfo = NULL;
258 if (r.mpLayoutName)
259 mpLayoutName.reset(new OUString(*r.mpLayoutName));
260 if (r.mpSubtotalName)
261 mpSubtotalName.reset(new OUString(*r.mpSubtotalName));
264 ScDPSaveDimension::~ScDPSaveDimension()
266 for (MemberHash::const_iterator i=maMemberHash.begin(); i != maMemberHash.end() ; ++i)
267 delete i->second;
268 delete pReferenceValue;
269 delete pSortInfo;
270 delete pAutoShowInfo;
271 delete pLayoutInfo;
272 delete [] pSubTotalFuncs;
275 bool ScDPSaveDimension::operator== ( const ScDPSaveDimension& r ) const
277 if ( aName != r.aName ||
278 bIsDataLayout != r.bIsDataLayout ||
279 bDupFlag != r.bDupFlag ||
280 nOrientation != r.nOrientation ||
281 nFunction != r.nFunction ||
282 nUsedHierarchy != r.nUsedHierarchy ||
283 nShowEmptyMode != r.nShowEmptyMode ||
284 bRepeatItemLabels!= r.bRepeatItemLabels||
285 bSubTotalDefault != r.bSubTotalDefault ||
286 nSubTotalCount != r.nSubTotalCount )
287 return false;
289 if ( nSubTotalCount && ( !pSubTotalFuncs || !r.pSubTotalFuncs ) ) // should not happen
290 return false;
292 long i;
293 for (i=0; i<nSubTotalCount; i++)
294 if ( pSubTotalFuncs[i] != r.pSubTotalFuncs[i] )
295 return false;
297 if (maMemberHash.size() != r.maMemberHash.size() )
298 return false;
300 MemberList::const_iterator a=maMemberList.begin();
301 MemberList::const_iterator b=r.maMemberList.begin();
302 for (; a != maMemberList.end() ; ++a, ++b)
303 if (!(**a == **b))
304 return false;
306 if( pReferenceValue && r.pReferenceValue )
308 if ( !(*pReferenceValue == *r.pReferenceValue) )
310 return false;
313 else if ( pReferenceValue || r.pReferenceValue )
315 return false;
317 if( this->pSortInfo && r.pSortInfo )
319 if ( !(*this->pSortInfo == *r.pSortInfo) )
321 return false;
324 else if ( this->pSortInfo || r.pSortInfo )
326 return false;
328 if( this->pAutoShowInfo && r.pAutoShowInfo )
330 if ( !(*this->pAutoShowInfo == *r.pAutoShowInfo) )
332 return false;
335 else if ( this->pAutoShowInfo || r.pAutoShowInfo )
337 return false;
340 return true;
343 void ScDPSaveDimension::AddMember(ScDPSaveMember* pMember)
345 const OUString & rName = pMember->GetName();
346 MemberHash::iterator aExisting = maMemberHash.find( rName );
347 if ( aExisting == maMemberHash.end() )
349 std::pair< const OUString, ScDPSaveMember *> key( rName, pMember );
350 maMemberHash.insert ( key );
352 else
354 maMemberList.remove( aExisting->second );
355 delete aExisting->second;
356 aExisting->second = pMember;
358 maMemberList.push_back( pMember );
361 void ScDPSaveDimension::SetName( const OUString& rNew )
363 // Used only if the source dim was renamed (groups).
364 // For UI renaming of dimensions, the layout name must be used.
366 aName = rNew;
369 void ScDPSaveDimension::SetOrientation(sal_uInt16 nNew)
371 nOrientation = nNew;
374 void ScDPSaveDimension::SetSubTotals(long nCount, const sal_uInt16* pFuncs)
376 if (pSubTotalFuncs)
377 delete [] pSubTotalFuncs;
378 nSubTotalCount = nCount;
379 if ( nCount && pFuncs )
381 pSubTotalFuncs = new sal_uInt16[nCount];
382 for (long i=0; i<nCount; i++)
383 pSubTotalFuncs[i] = pFuncs[i];
385 else
386 pSubTotalFuncs = NULL;
388 bSubTotalDefault = false;
391 bool ScDPSaveDimension::HasShowEmpty() const
393 return nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW;
396 void ScDPSaveDimension::SetShowEmpty(bool bSet)
398 nShowEmptyMode = sal_uInt16(bSet);
401 void ScDPSaveDimension::SetRepeatItemLabels(bool bSet)
403 bRepeatItemLabels = bSet;
406 void ScDPSaveDimension::SetFunction(sal_uInt16 nNew)
408 nFunction = nNew;
411 void ScDPSaveDimension::SetUsedHierarchy(long nNew)
413 nUsedHierarchy = nNew;
416 void ScDPSaveDimension::SetSubtotalName(const OUString& rName)
418 mpSubtotalName.reset(new OUString(rName));
421 const OUString* ScDPSaveDimension::GetSubtotalName() const
423 return mpSubtotalName.get();
426 void ScDPSaveDimension::RemoveSubtotalName()
428 mpSubtotalName.reset();
431 bool ScDPSaveDimension::IsMemberNameInUse(const OUString& rName) const
433 MemberList::const_iterator itr = maMemberList.begin(), itrEnd = maMemberList.end();
434 for (; itr != itrEnd; ++itr)
436 const ScDPSaveMember* pMem = *itr;
437 if (rName.equalsIgnoreAsciiCase(pMem->GetName()))
438 return true;
440 const OUString* pLayoutName = pMem->GetLayoutName();
441 if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName))
442 return true;
444 return false;
447 void ScDPSaveDimension::SetLayoutName(const OUString& rName)
449 mpLayoutName.reset(new OUString(rName));
452 const OUString* ScDPSaveDimension::GetLayoutName() const
454 return mpLayoutName.get();
457 void ScDPSaveDimension::RemoveLayoutName()
459 mpLayoutName.reset();
462 void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
464 delete pReferenceValue;
465 if (pNew)
466 pReferenceValue = new sheet::DataPilotFieldReference(*pNew);
467 else
468 pReferenceValue = NULL;
471 void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew)
473 delete pSortInfo;
474 if (pNew)
475 pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew);
476 else
477 pSortInfo = NULL;
480 void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew)
482 delete pAutoShowInfo;
483 if (pNew)
484 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew);
485 else
486 pAutoShowInfo = NULL;
489 void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew)
491 delete pLayoutInfo;
492 if (pNew)
493 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew);
494 else
495 pLayoutInfo = NULL;
498 void ScDPSaveDimension::SetCurrentPage( const OUString* pPage )
500 // We use member's visibility attribute to filter by page dimension.
502 // pPage == NULL -> all members visible.
503 MemberList::iterator it = maMemberList.begin(), itEnd = maMemberList.end();
504 for (; it != itEnd; ++it)
506 ScDPSaveMember* pMem = *it;
507 bool bVisible = !pPage || pMem->GetName() == *pPage;
508 pMem->SetIsVisible(bVisible);
512 OUString ScDPSaveDimension::GetCurrentPage() const
514 MemberList::const_iterator it = maMemberList.begin(), itEnd = maMemberList.end();
515 for (; it != itEnd; ++it)
517 const ScDPSaveMember* pMem = *it;
518 if (pMem->GetIsVisible())
519 return pMem->GetName();
522 return OUString();
525 ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const OUString& rName)
527 MemberHash::const_iterator res = maMemberHash.find (rName);
528 if (res != maMemberHash.end())
529 return res->second;
530 return NULL;
533 ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const OUString& rName)
535 MemberHash::const_iterator res = maMemberHash.find (rName);
536 if (res != maMemberHash.end())
537 return res->second;
539 ScDPSaveMember* pNew = new ScDPSaveMember( rName );
540 maMemberHash[rName] = pNew;
541 maMemberList.push_back( pNew );
542 return pNew;
545 void ScDPSaveDimension::SetMemberPosition( const OUString& rName, sal_Int32 nNewPos )
547 ScDPSaveMember* pMember = GetMemberByName( rName ); // make sure it exists and is in the hash
549 maMemberList.remove( pMember );
551 MemberList::iterator aIter = maMemberList.begin();
552 for (sal_Int32 i=0; i<nNewPos && aIter != maMemberList.end(); i++)
553 ++aIter;
554 maMemberList.insert( aIter, pMember );
557 void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim )
559 uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
560 OSL_ENSURE( xDimProp.is(), "no properties at dimension" );
561 if ( xDimProp.is() )
563 // exceptions are caught at ScDPSaveData::WriteToSource
564 uno::Any aAny;
566 sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
567 aAny <<= eOrient;
568 xDimProp->setPropertyValue( OUString(SC_UNO_DP_ORIENTATION), aAny );
570 sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
571 aAny <<= eFunc;
572 xDimProp->setPropertyValue( OUString(SC_UNO_DP_FUNCTION), aAny );
574 if ( nUsedHierarchy >= 0 )
576 aAny <<= (sal_Int32)nUsedHierarchy;
577 xDimProp->setPropertyValue( OUString(SC_UNO_DP_USEDHIERARCHY), aAny );
580 if ( pReferenceValue )
582 aAny <<= *pReferenceValue;
583 xDimProp->setPropertyValue( OUString(SC_UNO_DP_REFVALUE), aAny );
586 if (mpLayoutName)
587 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_LAYOUTNAME, *mpLayoutName);
589 const OUString* pSubTotalName = GetSubtotalName();
590 if (pSubTotalName)
591 // Custom subtotal name, with '?' being replaced by the visible field name later.
592 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_FIELD_SUBTOTALNAME, *pSubTotalName);
595 // Level loop outside of maMemberList loop
596 // because SubTotals have to be set independently of known members
598 long nCount = maMemberHash.size();
600 long nHierCount = 0;
601 uno::Reference<container::XIndexAccess> xHiers;
602 uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
603 if ( xHierSupp.is() )
605 uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
606 xHiers = new ScNameToIndexAccess( xHiersName );
607 nHierCount = xHiers->getCount();
610 bool bHasHiddenMember = false;
612 for (long nHier=0; nHier<nHierCount; nHier++)
614 uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
616 long nLevCount = 0;
617 uno::Reference<container::XIndexAccess> xLevels;
618 uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
619 if ( xLevSupp.is() )
621 uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
622 xLevels = new ScNameToIndexAccess( xLevelsName );
623 nLevCount = xLevels->getCount();
626 for (long nLev=0; nLev<nLevCount; nLev++)
628 uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) );
629 uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
630 OSL_ENSURE( xLevProp.is(), "no properties at level" );
631 if ( xLevProp.is() )
633 uno::Any aAny;
634 if ( !bSubTotalDefault )
636 if ( !pSubTotalFuncs )
637 nSubTotalCount = 0;
639 uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount);
640 sheet::GeneralFunction* pArray = aSeq.getArray();
641 for (long i=0; i<nSubTotalCount; i++)
642 pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i];
643 aAny <<= aSeq;
644 xLevProp->setPropertyValue( OUString(SC_UNO_DP_SUBTOTAL), aAny );
646 if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW )
647 lcl_SetBoolProperty( xLevProp,
648 OUString(SC_UNO_DP_SHOWEMPTY), (bool)nShowEmptyMode );
650 lcl_SetBoolProperty( xLevProp,
651 OUString(SC_UNO_DP_REPEATITEMLABELS), bRepeatItemLabels );
653 if ( pSortInfo )
654 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_SORTING, *pSortInfo);
656 if ( pAutoShowInfo )
657 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_AUTOSHOW, *pAutoShowInfo);
659 if ( pLayoutInfo )
660 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_LAYOUT, *pLayoutInfo);
662 // exceptions are caught at ScDPSaveData::WriteToSource
665 if ( nCount > 0 )
667 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
668 if ( xMembSupp.is() )
670 uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
671 if ( xMembers.is() )
673 sal_Int32 nPosition = -1; // set position only in manual mode
674 if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL )
675 nPosition = 0;
677 for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; ++i)
679 ScDPSaveMember* pMember = *i;
680 if (!pMember->GetIsVisible())
681 bHasHiddenMember = true;
682 OUString aMemberName = pMember->GetName();
683 if ( xMembers->hasByName( aMemberName ) )
685 uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
686 xMembers->getByName( aMemberName ) );
687 pMember->WriteToSource( xMemberInt, nPosition );
689 if ( nPosition >= 0 )
690 ++nPosition; // increase if initialized
692 // missing member is no error
700 if (xDimProp.is())
701 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_HAS_HIDDEN_MEMBER, bHasHiddenMember);
704 void ScDPSaveDimension::UpdateMemberVisibility(const std::unordered_map<OUString, bool, OUStringHash>& rData)
706 typedef std::unordered_map<OUString, bool, OUStringHash> DataMap;
707 MemberList::iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
708 for (; itrMem != itrMemEnd; ++itrMem)
710 ScDPSaveMember* pMem = *itrMem;
711 const OUString& rMemName = pMem->GetName();
712 DataMap::const_iterator itr = rData.find(rMemName);
713 if (itr != rData.end())
714 pMem->SetIsVisible(itr->second);
718 bool ScDPSaveDimension::HasInvisibleMember() const
720 MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
721 for (; itrMem != itrMemEnd; ++itrMem)
723 const ScDPSaveMember* pMem = *itrMem;
724 if (!pMem->GetIsVisible())
725 return true;
727 return false;
730 void ScDPSaveDimension::RemoveObsoleteMembers(const MemberSetType& rMembers)
732 maMemberHash.clear();
733 MemberList aNew;
734 MemberList::iterator it = maMemberList.begin(), itEnd = maMemberList.end();
735 for (; it != itEnd; ++it)
737 ScDPSaveMember* pMem = *it;
738 if (rMembers.count(pMem->GetName()))
740 // This member still exists.
741 maMemberHash.insert(MemberHash::value_type(pMem->GetName(), pMem));
742 aNew.push_back(pMem);
744 else
746 // This member no longer exists.
747 delete pMem;
751 maMemberList.swap(aNew);
754 #if DEBUG_PIVOT_TABLE
756 void ScDPSaveDimension::Dump(int nIndent) const
758 static const char* pOrientNames[] = { "hidden", "column", "row", "page", "data" };
759 std::string aIndent(nIndent*4, ' ');
761 cout << aIndent << "* dimension name: '" << aName << "'" << endl;
763 cout << aIndent << " + orientation: ";
764 if (nOrientation <= 4)
765 cout << pOrientNames[nOrientation];
766 else
767 cout << "(invalid)";
768 cout << endl;
770 cout << aIndent << " + layout name: ";
771 if (mpLayoutName)
772 cout << "'" << *mpLayoutName << "'";
773 else
774 cout << "(none)";
775 cout << endl;
777 cout << aIndent << " + subtotal name: ";
778 if (mpSubtotalName)
779 cout << "'" << *mpSubtotalName << "'";
780 else
781 cout << "(none)";
782 cout << endl;
784 cout << aIndent << " + is data layout: " << (bIsDataLayout ? "yes" : "no") << endl;
785 cout << aIndent << " + is duplicate: " << (bDupFlag ? "yes" : "no") << endl;
787 MemberList::const_iterator itMem = maMemberList.begin(), itMemEnd = maMemberList.end();
788 for (; itMem != itMemEnd; ++itMem)
790 ScDPSaveMember* pMem = *itMem;
791 pMem->Dump(nIndent+1);
794 cout << endl; // blank line
797 #endif
799 ScDPSaveData::ScDPSaveData() :
800 pDimensionData( NULL ),
801 nColumnGrandMode( SC_DPSAVEMODE_DONTKNOW ),
802 nRowGrandMode( SC_DPSAVEMODE_DONTKNOW ),
803 nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
804 nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
805 bFilterButton( true ),
806 bDrillDown( true ),
807 mbDimensionMembersBuilt(false),
808 mpGrandTotalName(NULL)
812 ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
813 nColumnGrandMode( r.nColumnGrandMode ),
814 nRowGrandMode( r.nRowGrandMode ),
815 nIgnoreEmptyMode( r.nIgnoreEmptyMode ),
816 nRepeatEmptyMode( r.nRepeatEmptyMode ),
817 bFilterButton( r.bFilterButton ),
818 bDrillDown( r.bDrillDown ),
819 mbDimensionMembersBuilt(r.mbDimensionMembersBuilt),
820 mpGrandTotalName(NULL),
821 mpDimOrder(NULL)
823 if ( r.pDimensionData )
824 pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
825 else
826 pDimensionData = NULL;
828 aDimList = r.aDimList.clone();
830 if (r.mpGrandTotalName)
831 mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
834 ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
836 if ( &r != this )
838 this->~ScDPSaveData();
839 new( this ) ScDPSaveData ( r );
841 return *this;
844 bool ScDPSaveData::operator== ( const ScDPSaveData& r ) const
846 if ( nColumnGrandMode != r.nColumnGrandMode ||
847 nRowGrandMode != r.nRowGrandMode ||
848 nIgnoreEmptyMode != r.nIgnoreEmptyMode ||
849 nRepeatEmptyMode != r.nRepeatEmptyMode ||
850 bFilterButton != r.bFilterButton ||
851 bDrillDown != r.bDrillDown ||
852 mbDimensionMembersBuilt != r.mbDimensionMembersBuilt)
853 return false;
855 if ( pDimensionData || r.pDimensionData )
856 if ( !pDimensionData || !r.pDimensionData || !( *pDimensionData == *r.pDimensionData ) )
857 return false;
859 if ( aDimList.size() != r.aDimList.size() )
860 return false;
862 if (aDimList != r.aDimList)
863 return false;
865 if (mpGrandTotalName)
867 if (!r.mpGrandTotalName)
868 return false;
869 if (!mpGrandTotalName->equals(*r.mpGrandTotalName))
870 return false;
872 else if (r.mpGrandTotalName)
873 return false;
875 return true;
878 ScDPSaveData::~ScDPSaveData()
880 delete pDimensionData;
883 void ScDPSaveData::SetGrandTotalName(const OUString& rName)
885 mpGrandTotalName.reset(new OUString(rName));
888 const OUString* ScDPSaveData::GetGrandTotalName() const
890 return mpGrandTotalName.get();
893 namespace {
895 class DimOrderInserter : std::unary_function<const ScDPSaveDimension*, void>
897 ScDPSaveData::DimOrderType& mrNames;
898 public:
899 DimOrderInserter(ScDPSaveData::DimOrderType& rNames) : mrNames(rNames) {}
901 void operator() (const ScDPSaveDimension* pDim)
903 size_t nRank = mrNames.size();
904 mrNames.insert(
905 ScDPSaveData::DimOrderType::value_type(pDim->GetName(), nRank));
911 const ScDPSaveData::DimOrderType& ScDPSaveData::GetDimensionSortOrder() const
913 if (!mpDimOrder)
915 mpDimOrder.reset(new DimOrderType);
916 std::vector<const ScDPSaveDimension*> aRowDims, aColDims;
917 GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aRowDims);
918 GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aColDims);
920 std::for_each(aRowDims.begin(), aRowDims.end(), DimOrderInserter(*mpDimOrder));
921 std::for_each(aColDims.begin(), aColDims.end(), DimOrderInserter(*mpDimOrder));
923 return *mpDimOrder;
926 void ScDPSaveData::GetAllDimensionsByOrientation(
927 sheet::DataPilotFieldOrientation eOrientation, std::vector<const ScDPSaveDimension*>& rDims) const
929 std::vector<const ScDPSaveDimension*> aDims;
930 DimsType::const_iterator it = aDimList.begin(), itEnd = aDimList.end();
931 for (; it != itEnd; ++it)
933 const ScDPSaveDimension& rDim = *it;
934 if (rDim.GetOrientation() != static_cast<sal_uInt16>(eOrientation))
935 continue;
937 aDims.push_back(&rDim);
940 rDims.swap(aDims);
943 void ScDPSaveData::AddDimension(ScDPSaveDimension* pDim)
945 if (!pDim)
946 return;
948 CheckDuplicateName(*pDim);
949 aDimList.push_back(pDim);
951 DimensionsChanged();
954 ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const OUString& rName)
956 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
957 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
959 if (iter->GetName() == rName && !iter->IsDataLayout() )
960 return const_cast<ScDPSaveDimension*>(&(*iter));
963 return AppendNewDimension(rName, false);
966 ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const OUString& rName) const
968 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
969 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
971 if (iter->GetName() == rName && !iter->IsDataLayout() )
972 return const_cast<ScDPSaveDimension*>(&(*iter));
974 return NULL; // don't create new
977 ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const OUString& rName)
979 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
980 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
982 if (iter->GetName() == rName && !iter->IsDataLayout() )
983 return DuplicateDimension(rName);
986 return AppendNewDimension(rName, false);
989 ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
991 ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
992 if (pDim)
993 return pDim;
995 return AppendNewDimension(OUString(), true);
998 ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const
1000 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
1001 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1003 if ( iter->IsDataLayout() )
1004 return const_cast<ScDPSaveDimension*>(&(*iter));
1006 return NULL;
1009 ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const OUString& rName)
1011 // always insert new
1013 ScDPSaveDimension* pOld = GetExistingDimensionByName(rName);
1014 if (!pOld)
1015 return NULL;
1017 ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld );
1018 AddDimension(pNew);
1019 return pNew;
1022 void ScDPSaveData::RemoveDimensionByName(const OUString& rName)
1024 boost::ptr_vector<ScDPSaveDimension>::iterator iter;
1025 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1027 if (iter->GetName() != rName || iter->IsDataLayout())
1028 continue;
1030 aDimList.erase(iter);
1031 RemoveDuplicateNameCount(rName);
1032 DimensionsChanged();
1033 return;
1037 ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rDim )
1039 ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim );
1040 AddDimension(pNew);
1041 return *pNew;
1044 ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(sal_uInt16 nOrientation)
1046 // return the innermost dimension for the given orientation,
1047 // excluding data layout dimension
1049 boost::ptr_vector<ScDPSaveDimension>::const_reverse_iterator iter;
1050 for (iter = aDimList.rbegin(); iter != aDimList.rend(); ++iter)
1052 if (iter->GetOrientation() == nOrientation && !iter->IsDataLayout())
1053 return const_cast<ScDPSaveDimension*>(&(*iter));
1056 return NULL;
1059 ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)
1061 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
1062 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1064 if (iter->GetOrientation() == eOrientation && !iter->IsDataLayout())
1065 return const_cast<ScDPSaveDimension*>(&(*iter));
1067 return NULL;
1070 long ScDPSaveData::GetDataDimensionCount() const
1072 long nDataCount = 0;
1074 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
1075 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1077 if (iter->GetOrientation() == sheet::DataPilotFieldOrientation_DATA)
1078 ++nDataCount;
1081 return nDataCount;
1084 void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
1086 // position (nNew) is counted within dimensions of the same orientation
1088 sal_uInt16 nOrient = pDim->GetOrientation();
1090 boost::ptr_vector<ScDPSaveDimension>::iterator it;
1091 for ( it = aDimList.begin(); it != aDimList.end(); ++it)
1093 if (pDim == &(*it))
1095 // Tell ptr_vector to give up ownership of this element. Don't
1096 // delete this instance as it is re-inserted into the container
1097 // later.
1098 aDimList.release(it).release();
1099 break;
1103 boost::ptr_vector<ScDPSaveDimension>::iterator iterInsert = aDimList.begin();
1104 while ( nNew > 0 && iterInsert != aDimList.end())
1106 if (iterInsert->GetOrientation() == nOrient )
1107 --nNew;
1109 ++iterInsert;
1112 aDimList.insert(iterInsert,pDim);
1113 DimensionsChanged();
1116 void ScDPSaveData::SetColumnGrand(bool bSet)
1118 nColumnGrandMode = sal_uInt16(bSet);
1121 void ScDPSaveData::SetRowGrand(bool bSet)
1123 nRowGrandMode = sal_uInt16(bSet);
1126 void ScDPSaveData::SetIgnoreEmptyRows(bool bSet)
1128 nIgnoreEmptyMode = sal_uInt16(bSet);
1131 void ScDPSaveData::SetRepeatIfEmpty(bool bSet)
1133 nRepeatEmptyMode = sal_uInt16(bSet);
1136 void ScDPSaveData::SetFilterButton(bool bSet)
1138 bFilterButton = bSet;
1141 void ScDPSaveData::SetDrillDown(bool bSet)
1143 bDrillDown = bSet;
1146 static void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1148 sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN;
1150 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1151 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1152 long nIntCount = xIntDims->getCount();
1153 for (long nIntDim=0; nIntDim<nIntCount; nIntDim++)
1155 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1156 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1157 if (xDimProp.is())
1159 uno::Any aAny;
1160 aAny <<= eOrient;
1161 xDimProp->setPropertyValue( OUString(SC_UNO_DP_ORIENTATION), aAny );
1166 void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1168 if (!xSource.is())
1169 return;
1171 // source options must be first!
1173 uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
1174 OSL_ENSURE( xSourceProp.is(), "no properties at source" );
1175 if ( xSourceProp.is() )
1177 // source options are not available for external sources
1178 //TODO: use XPropertySetInfo to test for availability?
1182 if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1183 lcl_SetBoolProperty( xSourceProp,
1184 OUString(SC_UNO_DP_IGNOREEMPTY), (bool)nIgnoreEmptyMode );
1185 if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1186 lcl_SetBoolProperty( xSourceProp,
1187 OUString(SC_UNO_DP_REPEATEMPTY), (bool)nRepeatEmptyMode );
1189 catch(uno::Exception&)
1191 // no error
1194 const OUString* pGrandTotalName = GetGrandTotalName();
1195 if (pGrandTotalName)
1196 ScUnoHelpFunctions::SetOptionalPropertyValue(xSourceProp, SC_UNO_DP_GRANDTOTAL_NAME, *pGrandTotalName);
1199 // exceptions in the other calls are errors
1202 // reset all orientations
1203 //TODO: "forgetSettings" or similar at source ?????
1204 //TODO: reset all duplicated dimensions, or reuse them below !!!
1205 OSL_FAIL( "ScDPSaveData::WriteToSource" );
1207 lcl_ResetOrient( xSource );
1209 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1210 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1211 long nIntCount = xIntDims->getCount();
1213 boost::ptr_vector<ScDPSaveDimension>::iterator iter = aDimList.begin();
1214 for (long i = 0; iter != aDimList.end(); ++iter, ++i)
1216 OUString aName = iter->GetName();
1217 OUString aCoreName = ScDPUtil::getSourceDimensionName(aName);
1219 SAL_INFO("sc.core", aName);
1221 bool bData = iter->IsDataLayout();
1223 //TODO: getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
1225 bool bFound = false;
1226 for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1228 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1229 if ( bData )
1231 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1232 if ( xDimProp.is() )
1234 bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
1235 OUString(SC_UNO_DP_ISDATALAYOUT) );
1236 //TODO: error checking -- is "IsDataLayoutDimension" property required??
1239 else
1241 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1242 if (xDimName.is() && xDimName->getName() == aCoreName)
1243 bFound = true;
1246 if (bFound)
1248 if (iter->GetDupFlag())
1250 uno::Reference<util::XCloneable> xCloneable(xIntDim, uno::UNO_QUERY);
1251 OSL_ENSURE(xCloneable.is(), "cannot clone dimension");
1252 if (xCloneable.is())
1254 uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
1255 uno::Reference<container::XNamed> xNewName(xNew, uno::UNO_QUERY);
1256 if (xNewName.is())
1258 xNewName->setName(aName);
1259 iter->WriteToSource(xNew);
1263 else
1264 iter->WriteToSource( xIntDim );
1267 OSL_ENSURE(bFound, "WriteToSource: Dimension not found");
1270 if ( xSourceProp.is() )
1272 if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW )
1273 lcl_SetBoolProperty( xSourceProp,
1274 OUString(SC_UNO_DP_COLGRAND), (bool)nColumnGrandMode );
1275 if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW )
1276 lcl_SetBoolProperty( xSourceProp,
1277 OUString(SC_UNO_DP_ROWGRAND), (bool)nRowGrandMode );
1280 catch(uno::Exception&)
1282 OSL_FAIL("exception in WriteToSource");
1286 bool ScDPSaveData::IsEmpty() const
1288 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
1289 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1291 if (iter->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !iter->IsDataLayout())
1292 return false;
1294 return true; // no entries that are not hidden
1297 void ScDPSaveData::RemoveAllGroupDimensions( const OUString& rSrcDimName, std::vector<OUString>* pDeletedNames )
1299 if (!pDimensionData)
1300 // No group dimensions exist. Nothing to do.
1301 return;
1303 // Remove numeric group dimension (exists once at most). No need to delete
1304 // anything in save data (grouping was done inplace in an existing base
1305 // dimension).
1306 pDimensionData->RemoveNumGroupDimension(rSrcDimName);
1308 // Remove named group dimension(s). Dimensions have to be removed from
1309 // dimension save data and from save data too.
1310 const ScDPSaveGroupDimension* pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
1311 while ( pExistingGroup )
1313 OUString aGroupDimName = pExistingGroup->GetGroupDimName();
1314 pDimensionData->RemoveGroupDimension(aGroupDimName); // pExistingGroup is deleted
1316 // also remove SaveData settings for the dimension that no longer exists
1317 RemoveDimensionByName(aGroupDimName);
1319 if (pDeletedNames)
1320 pDeletedNames->push_back(aGroupDimName);
1322 // see if there are more group dimensions
1323 pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
1325 if ( pExistingGroup && pExistingGroup->GetGroupDimName() == aGroupDimName )
1327 // still get the same group dimension?
1328 OSL_FAIL("couldn't remove group dimension");
1329 pExistingGroup = NULL; // avoid endless loop
1334 ScDPDimensionSaveData* ScDPSaveData::GetDimensionData()
1336 if (!pDimensionData)
1337 pDimensionData = new ScDPDimensionSaveData;
1338 return pDimensionData;
1341 void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew )
1343 delete pDimensionData;
1344 if ( pNew )
1345 pDimensionData = new ScDPDimensionSaveData( *pNew );
1346 else
1347 pDimensionData = NULL;
1350 void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
1352 if (mbDimensionMembersBuilt)
1353 return;
1355 // First, build a dimension name-to-index map.
1356 typedef std::unordered_map<OUString, long, OUStringHash> NameIndexMap;
1357 NameIndexMap aMap;
1358 long nColCount = pData->GetColumnCount();
1359 for (long i = 0; i < nColCount; ++i)
1360 aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i));
1362 NameIndexMap::const_iterator itrEnd = aMap.end();
1364 boost::ptr_vector<ScDPSaveDimension>::iterator iter;
1365 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1367 const OUString& rDimName = iter->GetName();
1368 if (rDimName.isEmpty())
1369 // empty dimension name. It must be data layout.
1370 continue;
1372 NameIndexMap::const_iterator itr = aMap.find(rDimName);
1373 if (itr == itrEnd)
1374 // dimension name not in the data. This should never happen!
1375 continue;
1377 long nDimIndex = itr->second;
1378 const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
1379 size_t mMemberCount = rMembers.size();
1380 for (size_t j = 0; j < mMemberCount; ++j)
1382 const ScDPItemData* pMemberData = pData->GetMemberById( nDimIndex, rMembers[j] );
1383 OUString aMemName = pData->GetFormattedString(nDimIndex, *pMemberData);
1384 if (iter->GetExistingMemberByName(aMemName))
1385 // this member instance already exists. nothing to do.
1386 continue;
1388 unique_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName));
1389 pNewMember->SetIsVisible(true);
1390 iter->AddMember(pNewMember.release());
1394 mbDimensionMembersBuilt = true;
1397 void ScDPSaveData::SyncAllDimensionMembers(ScDPTableData* pData)
1399 typedef std::unordered_map<OUString, long, OUStringHash> NameIndexMap;
1401 // First, build a dimension name-to-index map.
1402 NameIndexMap aMap;
1403 long nColCount = pData->GetColumnCount();
1404 for (long i = 0; i < nColCount; ++i)
1405 aMap.insert(NameIndexMap::value_type(pData->getDimensionName(i), i));
1407 NameIndexMap::const_iterator itMapEnd = aMap.end();
1409 DimsType::iterator it = aDimList.begin(), itEnd = aDimList.end();
1410 for (it = aDimList.begin(); it != itEnd; ++it)
1412 const OUString& rDimName = it->GetName();
1413 if (rDimName.isEmpty())
1414 // empty dimension name. It must be data layout.
1415 continue;
1417 NameIndexMap::const_iterator itMap = aMap.find(rDimName);
1418 if (itMap == itMapEnd)
1419 // dimension name not in the data. This should never happen!
1420 continue;
1422 ScDPSaveDimension::MemberSetType aMemNames;
1423 long nDimIndex = itMap->second;
1424 const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
1425 size_t nMemberCount = rMembers.size();
1426 for (size_t j = 0; j < nMemberCount; ++j)
1428 const ScDPItemData* pMemberData = pData->GetMemberById(nDimIndex, rMembers[j]);
1429 OUString aMemName = pData->GetFormattedString(nDimIndex, *pMemberData);
1430 aMemNames.insert(aMemName);
1433 it->RemoveObsoleteMembers(aMemNames);
1437 bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const
1439 ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName);
1440 if (!pDim)
1441 return false;
1443 return pDim->HasInvisibleMember();
1446 #if DEBUG_PIVOT_TABLE
1448 void ScDPSaveData::Dump() const
1450 DimsType::const_iterator itDim = aDimList.begin(), itDimEnd = aDimList.end();
1451 for (; itDim != itDimEnd; ++itDim)
1453 const ScDPSaveDimension& rDim = *itDim;
1454 rDim.Dump();
1458 #endif
1460 void ScDPSaveData::CheckDuplicateName(ScDPSaveDimension& rDim)
1462 const OUString aName = ScDPUtil::getSourceDimensionName(rDim.GetName());
1463 DupNameCountType::iterator it = maDupNameCounts.find(aName);
1464 if (it != maDupNameCounts.end())
1466 rDim.SetName(ScDPUtil::createDuplicateDimensionName(aName, ++it->second));
1467 rDim.SetDupFlag(true);
1469 else
1470 // New name.
1471 maDupNameCounts.insert(DupNameCountType::value_type(aName, 0));
1474 void ScDPSaveData::RemoveDuplicateNameCount(const OUString& rName)
1476 OUString aCoreName = rName;
1477 if (ScDPUtil::isDuplicateDimension(rName))
1478 aCoreName = ScDPUtil::getSourceDimensionName(rName);
1480 DupNameCountType::iterator it = maDupNameCounts.find(aCoreName);
1481 if (it == maDupNameCounts.end())
1482 return;
1484 if (!it->second)
1486 maDupNameCounts.erase(it);
1487 return;
1490 --it->second;
1491 return;
1494 ScDPSaveDimension* ScDPSaveData::AppendNewDimension(const OUString& rName, bool bDataLayout)
1496 if (ScDPUtil::isDuplicateDimension(rName))
1497 // This call is for original dimensions only.
1498 return NULL;
1500 ScDPSaveDimension* pNew = new ScDPSaveDimension(rName, bDataLayout);
1501 aDimList.push_back(pNew);
1502 if (!maDupNameCounts.count(rName))
1503 maDupNameCounts.insert(DupNameCountType::value_type(rName, 0));
1505 DimensionsChanged();
1506 return pNew;
1509 void ScDPSaveData::DimensionsChanged()
1511 mpDimOrder.reset();
1514 bool operator == (const ::com::sun::star::sheet::DataPilotFieldSortInfo &l, const ::com::sun::star::sheet::DataPilotFieldSortInfo &r )
1516 return l.Field == r.Field && l.IsAscending == r.IsAscending && l.Mode == r.Mode;
1518 bool operator == (const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &l, const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &r )
1520 return l.IsEnabled == r.IsEnabled &&
1521 l.ShowItemsMode == r.ShowItemsMode &&
1522 l.ItemCount == r.ItemCount &&
1523 l.DataField == r.DataField;
1525 bool operator == (const ::com::sun::star::sheet::DataPilotFieldReference &l, const ::com::sun::star::sheet::DataPilotFieldReference &r )
1527 return l.ReferenceType == r.ReferenceType &&
1528 l.ReferenceField == r.ReferenceField &&
1529 l.ReferenceItemType == r.ReferenceItemType &&
1530 l.ReferenceItemName == r.ReferenceItemName;
1533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */