Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / data / dpsave.cxx
blobc0328ce1fe42b4ad1dfb55b346c575aa9d20c8e5
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 "comphelper/string.hxx"
32 #include <com/sun/star/sheet/GeneralFunction.hpp>
33 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
34 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
35 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
36 #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
37 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
38 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
39 #include <com/sun/star/sheet/TableFilterField.hpp>
40 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
41 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
42 #include <com/sun/star/sheet/XMembersSupplier.hpp>
43 #include <com/sun/star/container/XNamed.hpp>
44 #include <com/sun/star/util/XCloneable.hpp>
46 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
47 #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
49 #include <boost/unordered_map.hpp>
50 #include <boost/unordered_set.hpp>
52 using namespace com::sun::star;
53 using namespace com::sun::star::sheet;
54 using ::com::sun::star::uno::Reference;
55 using ::com::sun::star::uno::Any;
56 using ::std::auto_ptr;
58 #define SC_DPSAVEMODE_DONTKNOW 2
60 static void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp,
61 const OUString& rName, sal_Bool bValue )
63 //! move to ScUnoHelpFunctions?
65 xProp->setPropertyValue( rName, uno::Any( &bValue, getBooleanCppuType() ) );
68 ScDPSaveMember::ScDPSaveMember(const OUString& rName) :
69 aName( rName ),
70 mpLayoutName(NULL),
71 nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
72 nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
76 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
77 aName( r.aName ),
78 mpLayoutName(NULL),
79 nVisibleMode( r.nVisibleMode ),
80 nShowDetailsMode( r.nShowDetailsMode )
82 if (r.mpLayoutName)
83 mpLayoutName.reset(new OUString(*r.mpLayoutName));
86 ScDPSaveMember::~ScDPSaveMember()
90 bool ScDPSaveMember::operator== ( const ScDPSaveMember& r ) const
92 if ( aName != r.aName ||
93 nVisibleMode != r.nVisibleMode ||
94 nShowDetailsMode != r.nShowDetailsMode )
95 return false;
97 return true;
100 bool ScDPSaveMember::HasIsVisible() const
102 return nVisibleMode != SC_DPSAVEMODE_DONTKNOW;
105 void ScDPSaveMember::SetIsVisible(bool bSet)
107 nVisibleMode = bSet;
110 bool ScDPSaveMember::HasShowDetails() const
112 return nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW;
115 void ScDPSaveMember::SetShowDetails(bool bSet)
117 nShowDetailsMode = bSet;
120 void ScDPSaveMember::SetName( const OUString& rNew )
122 // Used only if the source member was renamed (groups).
123 // For UI renaming of members, a layout name must be used.
125 aName = rNew;
128 void ScDPSaveMember::SetLayoutName( const OUString& rName )
130 mpLayoutName.reset(new OUString(rName));
133 const OUString* ScDPSaveMember::GetLayoutName() const
135 return mpLayoutName.get();
138 void ScDPSaveMember::RemoveLayoutName()
140 mpLayoutName.reset(NULL);
143 void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
145 uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
146 OSL_ENSURE( xMembProp.is(), "no properties at member" );
147 if ( xMembProp.is() )
149 // exceptions are caught at ScDPSaveData::WriteToSource
151 if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW )
152 lcl_SetBoolProperty( xMembProp,
153 OUString(SC_UNO_DP_ISVISIBLE), (bool)nVisibleMode );
155 if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW )
156 lcl_SetBoolProperty( xMembProp,
157 OUString(SC_UNO_DP_SHOWDETAILS), (bool)nShowDetailsMode );
159 if (mpLayoutName)
160 ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_DP_LAYOUTNAME, *mpLayoutName);
162 if ( nPosition >= 0 )
163 ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_DP_POSITION, nPosition);
167 #if DEBUG_PIVOT_TABLE
169 void ScDPSaveMember::Dump(int nIndent) const
171 std::string aIndent(nIndent*4, ' ');
172 cout << aIndent << "* member name: '" << aName << "'" << endl;
174 cout << aIndent << " + layout name: ";
175 if (mpLayoutName)
176 cout << "'" << *mpLayoutName << "'";
177 else
178 cout << "(none)";
179 cout << endl;
181 cout << aIndent << " + visibility: ";
182 if (nVisibleMode == SC_DPSAVEMODE_DONTKNOW)
183 cout << "(unknown)";
184 else
185 cout << (nVisibleMode ? "visible" : "hidden");
186 cout << endl;
189 #endif
191 ScDPSaveDimension::ScDPSaveDimension(const OUString& rName, bool bDataLayout) :
192 aName( rName ),
193 mpLayoutName(NULL),
194 mpSubtotalName(NULL),
195 bIsDataLayout( bDataLayout ),
196 bDupFlag( false ),
197 nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ),
198 nFunction( sheet::GeneralFunction_AUTO ),
199 nUsedHierarchy( -1 ),
200 nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
201 bSubTotalDefault( true ),
202 nSubTotalCount( 0 ),
203 pSubTotalFuncs( NULL ),
204 pReferenceValue( NULL ),
205 pSortInfo( NULL ),
206 pAutoShowInfo( NULL ),
207 pLayoutInfo( NULL )
211 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
212 aName( r.aName ),
213 mpLayoutName(NULL),
214 mpSubtotalName(NULL),
215 bIsDataLayout( r.bIsDataLayout ),
216 bDupFlag( r.bDupFlag ),
217 nOrientation( r.nOrientation ),
218 nFunction( r.nFunction ),
219 nUsedHierarchy( r.nUsedHierarchy ),
220 nShowEmptyMode( r.nShowEmptyMode ),
221 bSubTotalDefault( r.bSubTotalDefault ),
222 nSubTotalCount( r.nSubTotalCount ),
223 pSubTotalFuncs( NULL )
225 if ( nSubTotalCount && r.pSubTotalFuncs )
227 pSubTotalFuncs = new sal_uInt16[nSubTotalCount];
228 for (long nSub=0; nSub<nSubTotalCount; nSub++)
229 pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub];
232 for (MemberList::const_iterator i=r.maMemberList.begin(); i != r.maMemberList.end() ; ++i)
234 const OUString& rName = (*i)->GetName();
235 ScDPSaveMember* pNew = new ScDPSaveMember( **i );
236 maMemberHash[rName] = pNew;
237 maMemberList.push_back( pNew );
239 if (r.pReferenceValue)
240 pReferenceValue = new sheet::DataPilotFieldReference( *(r.pReferenceValue) );
241 else
242 pReferenceValue = NULL;
243 if (r.pSortInfo)
244 pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) );
245 else
246 pSortInfo = NULL;
247 if (r.pAutoShowInfo)
248 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) );
249 else
250 pAutoShowInfo = NULL;
251 if (r.pLayoutInfo)
252 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
253 else
254 pLayoutInfo = NULL;
255 if (r.mpLayoutName)
256 mpLayoutName.reset(new OUString(*r.mpLayoutName));
257 if (r.mpSubtotalName)
258 mpSubtotalName.reset(new OUString(*r.mpSubtotalName));
261 ScDPSaveDimension::~ScDPSaveDimension()
263 for (MemberHash::const_iterator i=maMemberHash.begin(); i != maMemberHash.end() ; ++i)
264 delete i->second;
265 delete pReferenceValue;
266 delete pSortInfo;
267 delete pAutoShowInfo;
268 delete pLayoutInfo;
269 delete [] pSubTotalFuncs;
272 bool ScDPSaveDimension::operator== ( const ScDPSaveDimension& r ) const
274 if ( aName != r.aName ||
275 bIsDataLayout != r.bIsDataLayout ||
276 bDupFlag != r.bDupFlag ||
277 nOrientation != r.nOrientation ||
278 nFunction != r.nFunction ||
279 nUsedHierarchy != r.nUsedHierarchy ||
280 nShowEmptyMode != r.nShowEmptyMode ||
281 bSubTotalDefault != r.bSubTotalDefault ||
282 nSubTotalCount != r.nSubTotalCount )
283 return false;
285 if ( nSubTotalCount && ( !pSubTotalFuncs || !r.pSubTotalFuncs ) ) // should not happen
286 return false;
288 long i;
289 for (i=0; i<nSubTotalCount; i++)
290 if ( pSubTotalFuncs[i] != r.pSubTotalFuncs[i] )
291 return false;
293 if (maMemberHash.size() != r.maMemberHash.size() )
294 return false;
296 MemberList::const_iterator a=maMemberList.begin();
297 MemberList::const_iterator b=r.maMemberList.begin();
298 for (; a != maMemberList.end() ; ++a, ++b)
299 if (!(**a == **b))
300 return false;
302 if( pReferenceValue && r.pReferenceValue )
304 if ( !(*pReferenceValue == *r.pReferenceValue) )
306 return false;
309 else if ( pReferenceValue || r.pReferenceValue )
311 return false;
313 if( this->pSortInfo && r.pSortInfo )
315 if ( !(*this->pSortInfo == *r.pSortInfo) )
317 return false;
320 else if ( this->pSortInfo || r.pSortInfo )
322 return false;
324 if( this->pAutoShowInfo && r.pAutoShowInfo )
326 if ( !(*this->pAutoShowInfo == *r.pAutoShowInfo) )
328 return false;
331 else if ( this->pAutoShowInfo || r.pAutoShowInfo )
333 return false;
336 return true;
339 void ScDPSaveDimension::AddMember(ScDPSaveMember* pMember)
341 const OUString & rName = pMember->GetName();
342 MemberHash::iterator aExisting = maMemberHash.find( rName );
343 if ( aExisting == maMemberHash.end() )
345 std::pair< const OUString, ScDPSaveMember *> key( rName, pMember );
346 maMemberHash.insert ( key );
348 else
350 maMemberList.remove( aExisting->second );
351 delete aExisting->second;
352 aExisting->second = pMember;
354 maMemberList.push_back( pMember );
357 void ScDPSaveDimension::SetName( const OUString& rNew )
359 // Used only if the source dim was renamed (groups).
360 // For UI renaming of dimensions, the layout name must be used.
362 aName = rNew;
365 void ScDPSaveDimension::SetOrientation(sal_uInt16 nNew)
367 nOrientation = nNew;
370 void ScDPSaveDimension::SetSubTotals(long nCount, const sal_uInt16* pFuncs)
372 if (pSubTotalFuncs)
373 delete [] pSubTotalFuncs;
374 nSubTotalCount = nCount;
375 if ( nCount && pFuncs )
377 pSubTotalFuncs = new sal_uInt16[nCount];
378 for (long i=0; i<nCount; i++)
379 pSubTotalFuncs[i] = pFuncs[i];
381 else
382 pSubTotalFuncs = NULL;
384 bSubTotalDefault = false;
387 bool ScDPSaveDimension::HasShowEmpty() const
389 return nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW;
392 void ScDPSaveDimension::SetShowEmpty(bool bSet)
394 nShowEmptyMode = bSet;
397 void ScDPSaveDimension::SetFunction(sal_uInt16 nNew)
399 nFunction = nNew;
402 void ScDPSaveDimension::SetUsedHierarchy(long nNew)
404 nUsedHierarchy = nNew;
407 void ScDPSaveDimension::SetSubtotalName(const OUString& rName)
409 mpSubtotalName.reset(new OUString(rName));
412 const OUString* ScDPSaveDimension::GetSubtotalName() const
414 return mpSubtotalName.get();
417 void ScDPSaveDimension::RemoveSubtotalName()
419 mpSubtotalName.reset();
422 bool ScDPSaveDimension::IsMemberNameInUse(const OUString& rName) const
424 MemberList::const_iterator itr = maMemberList.begin(), itrEnd = maMemberList.end();
425 for (; itr != itrEnd; ++itr)
427 const ScDPSaveMember* pMem = *itr;
428 if (rName.equalsIgnoreAsciiCase(pMem->GetName()))
429 return true;
431 const OUString* pLayoutName = pMem->GetLayoutName();
432 if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName))
433 return true;
435 return false;
438 void ScDPSaveDimension::SetLayoutName(const OUString& rName)
440 mpLayoutName.reset(new OUString(rName));
443 const OUString* ScDPSaveDimension::GetLayoutName() const
445 return mpLayoutName.get();
448 void ScDPSaveDimension::RemoveLayoutName()
450 mpLayoutName.reset(NULL);
453 void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
455 delete pReferenceValue;
456 if (pNew)
457 pReferenceValue = new sheet::DataPilotFieldReference(*pNew);
458 else
459 pReferenceValue = NULL;
462 void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew)
464 delete pSortInfo;
465 if (pNew)
466 pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew);
467 else
468 pSortInfo = NULL;
471 void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew)
473 delete pAutoShowInfo;
474 if (pNew)
475 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew);
476 else
477 pAutoShowInfo = NULL;
480 void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew)
482 delete pLayoutInfo;
483 if (pNew)
484 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew);
485 else
486 pLayoutInfo = NULL;
489 void ScDPSaveDimension::SetCurrentPage( const OUString* pPage )
491 // We use member's visibility attribute to filter by page dimension.
493 // pPage == NULL -> all members visible.
494 MemberList::iterator it = maMemberList.begin(), itEnd = maMemberList.end();
495 for (; it != itEnd; ++it)
497 ScDPSaveMember* pMem = *it;
498 bool bVisible = !pPage || pMem->GetName() == *pPage;
499 pMem->SetIsVisible(bVisible);
503 ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const OUString& rName)
505 MemberHash::const_iterator res = maMemberHash.find (rName);
506 if (res != maMemberHash.end())
507 return res->second;
508 return NULL;
511 ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const OUString& rName)
513 MemberHash::const_iterator res = maMemberHash.find (rName);
514 if (res != maMemberHash.end())
515 return res->second;
517 ScDPSaveMember* pNew = new ScDPSaveMember( rName );
518 maMemberHash[rName] = pNew;
519 maMemberList.push_back( pNew );
520 return pNew;
523 void ScDPSaveDimension::SetMemberPosition( const OUString& rName, sal_Int32 nNewPos )
525 ScDPSaveMember* pMember = GetMemberByName( rName ); // make sure it exists and is in the hash
527 maMemberList.remove( pMember );
529 MemberList::iterator aIter = maMemberList.begin();
530 for (sal_Int32 i=0; i<nNewPos && aIter != maMemberList.end(); i++)
531 ++aIter;
532 maMemberList.insert( aIter, pMember );
535 void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim )
537 uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
538 OSL_ENSURE( xDimProp.is(), "no properties at dimension" );
539 if ( xDimProp.is() )
541 // exceptions are caught at ScDPSaveData::WriteToSource
542 uno::Any aAny;
544 sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
545 aAny <<= eOrient;
546 xDimProp->setPropertyValue( OUString(SC_UNO_DP_ORIENTATION), aAny );
548 sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
549 aAny <<= eFunc;
550 xDimProp->setPropertyValue( OUString(SC_UNO_DP_FUNCTION), aAny );
552 if ( nUsedHierarchy >= 0 )
554 aAny <<= (sal_Int32)nUsedHierarchy;
555 xDimProp->setPropertyValue( OUString(SC_UNO_DP_USEDHIERARCHY), aAny );
558 if ( pReferenceValue )
560 aAny <<= *pReferenceValue;
561 xDimProp->setPropertyValue( OUString(SC_UNO_DP_REFVALUE), aAny );
564 if (mpLayoutName)
565 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_LAYOUTNAME, *mpLayoutName);
567 const OUString* pSubTotalName = GetSubtotalName();
568 if (pSubTotalName)
569 // Custom subtotal name, with '?' being replaced by the visible field name later.
570 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_FIELD_SUBTOTALNAME, *pSubTotalName);
573 // Level loop outside of maMemberList loop
574 // because SubTotals have to be set independently of known members
576 long nCount = maMemberHash.size();
578 long nHierCount = 0;
579 uno::Reference<container::XIndexAccess> xHiers;
580 uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
581 if ( xHierSupp.is() )
583 uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
584 xHiers = new ScNameToIndexAccess( xHiersName );
585 nHierCount = xHiers->getCount();
588 bool bHasHiddenMember = false;
590 for (long nHier=0; nHier<nHierCount; nHier++)
592 uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
594 long nLevCount = 0;
595 uno::Reference<container::XIndexAccess> xLevels;
596 uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
597 if ( xLevSupp.is() )
599 uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
600 xLevels = new ScNameToIndexAccess( xLevelsName );
601 nLevCount = xLevels->getCount();
604 for (long nLev=0; nLev<nLevCount; nLev++)
606 uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) );
607 uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
608 OSL_ENSURE( xLevProp.is(), "no properties at level" );
609 if ( xLevProp.is() )
611 uno::Any aAny;
612 if ( !bSubTotalDefault )
614 if ( !pSubTotalFuncs )
615 nSubTotalCount = 0;
617 uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount);
618 sheet::GeneralFunction* pArray = aSeq.getArray();
619 for (long i=0; i<nSubTotalCount; i++)
620 pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i];
621 aAny <<= aSeq;
622 xLevProp->setPropertyValue( OUString(SC_UNO_DP_SUBTOTAL), aAny );
624 if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW )
625 lcl_SetBoolProperty( xLevProp,
626 OUString(SC_UNO_DP_SHOWEMPTY), (bool)nShowEmptyMode );
628 if ( pSortInfo )
629 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_SORTING, *pSortInfo);
631 if ( pAutoShowInfo )
632 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_AUTOSHOW, *pAutoShowInfo);
634 if ( pLayoutInfo )
635 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_LAYOUT, *pLayoutInfo);
637 // exceptions are caught at ScDPSaveData::WriteToSource
640 if ( nCount > 0 )
642 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
643 if ( xMembSupp.is() )
645 uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
646 if ( xMembers.is() )
648 sal_Int32 nPosition = -1; // set position only in manual mode
649 if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL )
650 nPosition = 0;
652 for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; ++i)
654 ScDPSaveMember* pMember = *i;
655 if (!pMember->GetIsVisible())
656 bHasHiddenMember = true;
657 OUString aMemberName = pMember->GetName();
658 if ( xMembers->hasByName( aMemberName ) )
660 uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
661 xMembers->getByName( aMemberName ) );
662 pMember->WriteToSource( xMemberInt, nPosition );
664 if ( nPosition >= 0 )
665 ++nPosition; // increase if initialized
667 // missing member is no error
675 if (xDimProp.is())
676 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_HAS_HIDDEN_MEMBER, bHasHiddenMember);
679 void ScDPSaveDimension::UpdateMemberVisibility(const boost::unordered_map<OUString, bool, OUStringHash>& rData)
681 typedef boost::unordered_map<OUString, bool, OUStringHash> DataMap;
682 MemberList::iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
683 for (; itrMem != itrMemEnd; ++itrMem)
685 ScDPSaveMember* pMem = *itrMem;
686 const OUString& rMemName = pMem->GetName();
687 DataMap::const_iterator itr = rData.find(rMemName);
688 if (itr != rData.end())
689 pMem->SetIsVisible(itr->second);
693 bool ScDPSaveDimension::HasInvisibleMember() const
695 MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
696 for (; itrMem != itrMemEnd; ++itrMem)
698 const ScDPSaveMember* pMem = *itrMem;
699 if (!pMem->GetIsVisible())
700 return true;
702 return false;
705 void ScDPSaveDimension::RemoveObsoleteMembers(const MemberSetType& rMembers)
707 maMemberHash.clear();
708 MemberList aNew;
709 MemberList::iterator it = maMemberList.begin(), itEnd = maMemberList.end();
710 for (; it != itEnd; ++it)
712 ScDPSaveMember* pMem = *it;
713 if (rMembers.count(pMem->GetName()))
715 // This member still exists.
716 maMemberHash.insert(MemberHash::value_type(pMem->GetName(), pMem));
717 aNew.push_back(pMem);
719 else
721 // This member no longer exists.
722 delete pMem;
726 maMemberList.swap(aNew);
729 #if DEBUG_PIVOT_TABLE
731 void ScDPSaveDimension::Dump(int nIndent) const
733 static const char* pOrientNames[] = { "hidden", "column", "row", "page", "data" };
734 std::string aIndent(nIndent*4, ' ');
736 cout << aIndent << "* dimension name: '" << aName << "'" << endl;
738 cout << aIndent << " + orientation: ";
739 if (nOrientation <= 4)
740 cout << pOrientNames[nOrientation];
741 else
742 cout << "(invalid)";
743 cout << endl;
745 cout << aIndent << " + layout name: ";
746 if (mpLayoutName)
747 cout << "'" << *mpLayoutName << "'";
748 else
749 cout << "(none)";
750 cout << endl;
752 cout << aIndent << " + subtotal name: ";
753 if (mpSubtotalName)
754 cout << "'" << *mpSubtotalName << "'";
755 else
756 cout << "(none)";
757 cout << endl;
759 cout << aIndent << " + is data layout: " << (bIsDataLayout ? "yes" : "no") << endl;
760 cout << aIndent << " + is duplicate: " << (bDupFlag ? "yes" : "no") << endl;
762 MemberList::const_iterator itMem = maMemberList.begin(), itMemEnd = maMemberList.end();
763 for (; itMem != itMemEnd; ++itMem)
765 ScDPSaveMember* pMem = *itMem;
766 pMem->Dump(nIndent+1);
769 cout << endl; // blank line
772 #endif
774 ScDPSaveData::ScDPSaveData() :
775 pDimensionData( NULL ),
776 nColumnGrandMode( SC_DPSAVEMODE_DONTKNOW ),
777 nRowGrandMode( SC_DPSAVEMODE_DONTKNOW ),
778 nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
779 nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
780 bFilterButton( true ),
781 bDrillDown( true ),
782 mbDimensionMembersBuilt(false),
783 mpGrandTotalName(NULL)
787 ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
788 nColumnGrandMode( r.nColumnGrandMode ),
789 nRowGrandMode( r.nRowGrandMode ),
790 nIgnoreEmptyMode( r.nIgnoreEmptyMode ),
791 nRepeatEmptyMode( r.nRepeatEmptyMode ),
792 bFilterButton( r.bFilterButton ),
793 bDrillDown( r.bDrillDown ),
794 mbDimensionMembersBuilt(r.mbDimensionMembersBuilt),
795 mpGrandTotalName(NULL),
796 mpDimOrder(NULL)
798 if ( r.pDimensionData )
799 pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
800 else
801 pDimensionData = NULL;
803 aDimList = r.aDimList.clone();
805 if (r.mpGrandTotalName)
806 mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
809 ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
811 if ( &r != this )
813 this->~ScDPSaveData();
814 new( this ) ScDPSaveData ( r );
816 return *this;
819 bool ScDPSaveData::operator== ( const ScDPSaveData& r ) const
821 if ( nColumnGrandMode != r.nColumnGrandMode ||
822 nRowGrandMode != r.nRowGrandMode ||
823 nIgnoreEmptyMode != r.nIgnoreEmptyMode ||
824 nRepeatEmptyMode != r.nRepeatEmptyMode ||
825 bFilterButton != r.bFilterButton ||
826 bDrillDown != r.bDrillDown ||
827 mbDimensionMembersBuilt != r.mbDimensionMembersBuilt)
828 return false;
830 if ( pDimensionData || r.pDimensionData )
831 if ( !pDimensionData || !r.pDimensionData || !( *pDimensionData == *r.pDimensionData ) )
832 return false;
834 if ( aDimList.size() != r.aDimList.size() )
835 return false;
837 if (aDimList != r.aDimList)
838 return false;
840 if (mpGrandTotalName)
842 if (!r.mpGrandTotalName)
843 return false;
844 if (!mpGrandTotalName->equals(*r.mpGrandTotalName))
845 return false;
847 else if (r.mpGrandTotalName)
848 return false;
850 return true;
853 ScDPSaveData::~ScDPSaveData()
855 delete pDimensionData;
858 void ScDPSaveData::SetGrandTotalName(const OUString& rName)
860 mpGrandTotalName.reset(new OUString(rName));
863 const OUString* ScDPSaveData::GetGrandTotalName() const
865 return mpGrandTotalName.get();
868 const ScDPSaveData::DimsType& ScDPSaveData::GetDimensions() const
870 return aDimList;
873 namespace {
875 class DimOrderInserter : std::unary_function<const ScDPSaveDimension*, void>
877 ScDPSaveData::DimOrderType& mrNames;
878 public:
879 DimOrderInserter(ScDPSaveData::DimOrderType& rNames) : mrNames(rNames) {}
881 void operator() (const ScDPSaveDimension* pDim)
883 size_t nRank = mrNames.size();
884 mrNames.insert(
885 ScDPSaveData::DimOrderType::value_type(pDim->GetName(), nRank));
891 const ScDPSaveData::DimOrderType& ScDPSaveData::GetDimensionSortOrder() const
893 if (!mpDimOrder)
895 mpDimOrder.reset(new DimOrderType);
896 std::vector<const ScDPSaveDimension*> aRowDims, aColDims;
897 GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aRowDims);
898 GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aColDims);
900 std::for_each(aRowDims.begin(), aRowDims.end(), DimOrderInserter(*mpDimOrder));
901 std::for_each(aColDims.begin(), aColDims.end(), DimOrderInserter(*mpDimOrder));
903 return *mpDimOrder;
906 void ScDPSaveData::GetAllDimensionsByOrientation(
907 sheet::DataPilotFieldOrientation eOrientation, std::vector<const ScDPSaveDimension*>& rDims) const
909 std::vector<const ScDPSaveDimension*> aDims;
910 DimsType::const_iterator it = aDimList.begin(), itEnd = aDimList.end();
911 for (; it != itEnd; ++it)
913 const ScDPSaveDimension& rDim = *it;
914 if (rDim.GetOrientation() != static_cast<sal_uInt16>(eOrientation))
915 continue;
917 aDims.push_back(&rDim);
920 rDims.swap(aDims);
923 void ScDPSaveData::AddDimension(ScDPSaveDimension* pDim)
925 if (!pDim)
926 return;
928 CheckDuplicateName(*pDim);
929 aDimList.push_back(pDim);
931 DimensionsChanged();
934 ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const OUString& rName)
936 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
937 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
939 if (iter->GetName() == rName && !iter->IsDataLayout() )
940 return const_cast<ScDPSaveDimension*>(&(*iter));
943 return AppendNewDimension(rName, false);
946 ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const OUString& rName) const
948 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
949 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
951 if (iter->GetName() == rName && !iter->IsDataLayout() )
952 return const_cast<ScDPSaveDimension*>(&(*iter));
954 return NULL; // don't create new
957 ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const OUString& rName)
959 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
960 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
962 if (iter->GetName() == rName && !iter->IsDataLayout() )
963 return DuplicateDimension(rName);
966 return AppendNewDimension(rName, false);
969 ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
971 ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
972 if (pDim)
973 return pDim;
975 return AppendNewDimension(OUString(), true);
978 ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const
980 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
981 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
983 if ( iter->IsDataLayout() )
984 return const_cast<ScDPSaveDimension*>(&(*iter));
986 return NULL;
989 ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const OUString& rName)
991 // always insert new
993 ScDPSaveDimension* pOld = GetExistingDimensionByName(rName);
994 if (!pOld)
995 return NULL;
997 ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld );
998 AddDimension(pNew);
999 return pNew;
1002 void ScDPSaveData::RemoveDimensionByName(const OUString& rName)
1004 boost::ptr_vector<ScDPSaveDimension>::iterator iter;
1005 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1007 if (iter->GetName() != rName || iter->IsDataLayout())
1008 continue;
1010 aDimList.erase(iter);
1011 RemoveDuplicateNameCount(rName);
1012 DimensionsChanged();
1013 return;
1017 ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rDim )
1019 ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim );
1020 AddDimension(pNew);
1021 return *pNew;
1024 ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(sal_uInt16 nOrientation)
1026 // return the innermost dimension for the given orientation,
1027 // excluding data layout dimension
1029 boost::ptr_vector<ScDPSaveDimension>::const_reverse_iterator iter;
1030 for (iter = aDimList.rbegin(); iter != aDimList.rend(); ++iter)
1032 if (iter->GetOrientation() == nOrientation && !iter->IsDataLayout())
1033 return const_cast<ScDPSaveDimension*>(&(*iter));
1036 return NULL;
1039 ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)
1041 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
1042 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1044 if (iter->GetOrientation() == eOrientation && !iter->IsDataLayout())
1045 return const_cast<ScDPSaveDimension*>(&(*iter));
1047 return NULL;
1050 long ScDPSaveData::GetDataDimensionCount() const
1052 long nDataCount = 0;
1054 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
1055 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1057 if (iter->GetOrientation() == sheet::DataPilotFieldOrientation_DATA)
1058 ++nDataCount;
1061 return nDataCount;
1064 void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
1066 // position (nNew) is counted within dimensions of the same orientation
1068 sal_uInt16 nOrient = pDim->GetOrientation();
1070 boost::ptr_vector<ScDPSaveDimension>::iterator it;
1071 for ( it = aDimList.begin(); it != aDimList.end(); ++it)
1073 if (pDim == &(*it))
1075 // Tell ptr_vector to give up ownership of this element. Don't
1076 // delete this instance as it is re-inserted into the container
1077 // later.
1078 aDimList.release(it).release();
1079 break;
1083 boost::ptr_vector<ScDPSaveDimension>::iterator iterInsert = aDimList.begin();
1084 while ( nNew > 0 && iterInsert != aDimList.end())
1086 if (iterInsert->GetOrientation() == nOrient )
1087 --nNew;
1089 ++iterInsert;
1092 aDimList.insert(iterInsert,pDim);
1093 DimensionsChanged();
1096 void ScDPSaveData::SetColumnGrand(bool bSet)
1098 nColumnGrandMode = bSet;
1101 void ScDPSaveData::SetRowGrand(bool bSet)
1103 nRowGrandMode = bSet;
1106 void ScDPSaveData::SetIgnoreEmptyRows(bool bSet)
1108 nIgnoreEmptyMode = bSet;
1111 void ScDPSaveData::SetRepeatIfEmpty(bool bSet)
1113 nRepeatEmptyMode = bSet;
1116 void ScDPSaveData::SetFilterButton(bool bSet)
1118 bFilterButton = bSet;
1121 void ScDPSaveData::SetDrillDown(bool bSet)
1123 bDrillDown = bSet;
1126 static void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1128 sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN;
1130 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1131 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1132 long nIntCount = xIntDims->getCount();
1133 for (long nIntDim=0; nIntDim<nIntCount; nIntDim++)
1135 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1136 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1137 if (xDimProp.is())
1139 uno::Any aAny;
1140 aAny <<= eOrient;
1141 xDimProp->setPropertyValue( OUString(SC_UNO_DP_ORIENTATION), aAny );
1146 void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1148 if (!xSource.is())
1149 return;
1151 // source options must be first!
1153 uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
1154 OSL_ENSURE( xSourceProp.is(), "no properties at source" );
1155 if ( xSourceProp.is() )
1157 // source options are not available for external sources
1158 //! use XPropertySetInfo to test for availability?
1162 if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1163 lcl_SetBoolProperty( xSourceProp,
1164 OUString(SC_UNO_DP_IGNOREEMPTY), (bool)nIgnoreEmptyMode );
1165 if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1166 lcl_SetBoolProperty( xSourceProp,
1167 OUString(SC_UNO_DP_REPEATEMPTY), (bool)nRepeatEmptyMode );
1169 catch(uno::Exception&)
1171 // no error
1174 const OUString* pGrandTotalName = GetGrandTotalName();
1175 if (pGrandTotalName)
1176 ScUnoHelpFunctions::SetOptionalPropertyValue(xSourceProp, SC_UNO_DP_GRANDTOTAL_NAME, *pGrandTotalName);
1179 // exceptions in the other calls are errors
1182 // reset all orientations
1183 //! "forgetSettings" or similar at source ?????
1184 //! reset all duplicated dimensions, or reuse them below !!!
1185 OSL_FAIL( "ScDPSaveData::WriteToSource" );
1187 lcl_ResetOrient( xSource );
1189 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1190 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1191 long nIntCount = xIntDims->getCount();
1193 boost::ptr_vector<ScDPSaveDimension>::iterator iter = aDimList.begin();
1194 for (long i = 0; iter != aDimList.end(); ++iter, ++i)
1196 OUString aName = iter->GetName();
1197 OUString aCoreName = ScDPUtil::getSourceDimensionName(aName);
1199 OSL_TRACE( "%s", aName.getStr() );
1201 bool bData = iter->IsDataLayout();
1203 //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
1205 bool bFound = false;
1206 for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1208 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1209 if ( bData )
1211 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1212 if ( xDimProp.is() )
1214 bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
1215 OUString(SC_UNO_DP_ISDATALAYOUT) );
1216 //! error checking -- is "IsDataLayoutDimension" property required??
1219 else
1221 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1222 if (xDimName.is() && xDimName->getName() == aCoreName)
1223 bFound = true;
1226 if (bFound)
1228 if (iter->GetDupFlag())
1230 uno::Reference<util::XCloneable> xCloneable(xIntDim, uno::UNO_QUERY);
1231 OSL_ENSURE(xCloneable.is(), "cannot clone dimension");
1232 if (xCloneable.is())
1234 uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
1235 uno::Reference<container::XNamed> xNewName(xNew, uno::UNO_QUERY);
1236 if (xNewName.is())
1238 xNewName->setName(aName);
1239 iter->WriteToSource(xNew);
1243 else
1244 iter->WriteToSource( xIntDim );
1247 OSL_ENSURE(bFound, "WriteToSource: Dimension not found");
1250 if ( xSourceProp.is() )
1252 if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW )
1253 lcl_SetBoolProperty( xSourceProp,
1254 OUString(SC_UNO_DP_COLGRAND), (bool)nColumnGrandMode );
1255 if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW )
1256 lcl_SetBoolProperty( xSourceProp,
1257 OUString(SC_UNO_DP_ROWGRAND), (bool)nRowGrandMode );
1260 catch(uno::Exception&)
1262 OSL_FAIL("exception in WriteToSource");
1266 bool ScDPSaveData::IsEmpty() const
1268 boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
1269 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1271 if (iter->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !iter->IsDataLayout())
1272 return false;
1274 return true; // no entries that are not hidden
1277 void ScDPSaveData::RemoveAllGroupDimensions( const OUString& rSrcDimName, std::vector<OUString>* pDeletedNames )
1279 if (!pDimensionData)
1280 // No group dimensions exist. Nothing to do.
1281 return;
1283 // Remove numeric group dimension (exists once at most). No need to delete
1284 // anything in save data (grouping was done inplace in an existing base
1285 // dimension).
1286 pDimensionData->RemoveNumGroupDimension(rSrcDimName);
1288 // Remove named group dimension(s). Dimensions have to be removed from
1289 // dimension save data and from save data too.
1290 const ScDPSaveGroupDimension* pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
1291 while ( pExistingGroup )
1293 OUString aGroupDimName = pExistingGroup->GetGroupDimName();
1294 pDimensionData->RemoveGroupDimension(aGroupDimName); // pExistingGroup is deleted
1296 // also remove SaveData settings for the dimension that no longer exists
1297 RemoveDimensionByName(aGroupDimName);
1299 if (pDeletedNames)
1300 pDeletedNames->push_back(aGroupDimName);
1302 // see if there are more group dimensions
1303 pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
1305 if ( pExistingGroup && pExistingGroup->GetGroupDimName() == aGroupDimName )
1307 // still get the same group dimension?
1308 OSL_FAIL("couldn't remove group dimension");
1309 pExistingGroup = NULL; // avoid endless loop
1314 ScDPDimensionSaveData* ScDPSaveData::GetDimensionData()
1316 if (!pDimensionData)
1317 pDimensionData = new ScDPDimensionSaveData;
1318 return pDimensionData;
1321 void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew )
1323 delete pDimensionData;
1324 if ( pNew )
1325 pDimensionData = new ScDPDimensionSaveData( *pNew );
1326 else
1327 pDimensionData = NULL;
1330 void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
1332 if (mbDimensionMembersBuilt)
1333 return;
1335 // First, build a dimension name-to-index map.
1336 typedef boost::unordered_map<OUString, long, OUStringHash> NameIndexMap;
1337 NameIndexMap aMap;
1338 long nColCount = pData->GetColumnCount();
1339 for (long i = 0; i < nColCount; ++i)
1340 aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i));
1342 NameIndexMap::const_iterator itrEnd = aMap.end();
1344 boost::ptr_vector<ScDPSaveDimension>::iterator iter;
1345 for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1347 const OUString& rDimName = iter->GetName();
1348 if (rDimName.isEmpty())
1349 // empty dimension name. It must be data layout.
1350 continue;
1352 NameIndexMap::const_iterator itr = aMap.find(rDimName);
1353 if (itr == itrEnd)
1354 // dimension name not in the data. This should never happen!
1355 continue;
1357 long nDimIndex = itr->second;
1358 const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
1359 size_t mMemberCount = rMembers.size();
1360 for (size_t j = 0; j < mMemberCount; ++j)
1362 const ScDPItemData* pMemberData = pData->GetMemberById( nDimIndex, rMembers[j] );
1363 OUString aMemName = pData->GetFormattedString(nDimIndex, *pMemberData);
1364 if (iter->GetExistingMemberByName(aMemName))
1365 // this member instance already exists. nothing to do.
1366 continue;
1368 auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName));
1369 pNewMember->SetIsVisible(true);
1370 iter->AddMember(pNewMember.release());
1374 mbDimensionMembersBuilt = true;
1377 void ScDPSaveData::SyncAllDimensionMembers(ScDPTableData* pData)
1379 typedef boost::unordered_map<OUString, long, OUStringHash> NameIndexMap;
1381 // First, build a dimension name-to-index map.
1382 NameIndexMap aMap;
1383 long nColCount = pData->GetColumnCount();
1384 for (long i = 0; i < nColCount; ++i)
1385 aMap.insert(NameIndexMap::value_type(pData->getDimensionName(i), i));
1387 NameIndexMap::const_iterator itMapEnd = aMap.end();
1389 DimsType::iterator it = aDimList.begin(), itEnd = aDimList.end();
1390 for (it = aDimList.begin(); it != itEnd; ++it)
1392 const OUString& rDimName = it->GetName();
1393 if (rDimName.isEmpty())
1394 // empty dimension name. It must be data layout.
1395 continue;
1397 NameIndexMap::const_iterator itMap = aMap.find(rDimName);
1398 if (itMap == itMapEnd)
1399 // dimension name not in the data. This should never happen!
1400 continue;
1402 ScDPSaveDimension::MemberSetType aMemNames;
1403 long nDimIndex = itMap->second;
1404 const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
1405 size_t nMemberCount = rMembers.size();
1406 for (size_t j = 0; j < nMemberCount; ++j)
1408 const ScDPItemData* pMemberData = pData->GetMemberById(nDimIndex, rMembers[j]);
1409 OUString aMemName = pData->GetFormattedString(nDimIndex, *pMemberData);
1410 aMemNames.insert(aMemName);
1413 it->RemoveObsoleteMembers(aMemNames);
1417 bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const
1419 ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName);
1420 if (!pDim)
1421 return false;
1423 return pDim->HasInvisibleMember();
1426 #if DEBUG_PIVOT_TABLE
1428 void ScDPSaveData::Dump() const
1430 DimsType::const_iterator itDim = aDimList.begin(), itDimEnd = aDimList.end();
1431 for (; itDim != itDimEnd; ++itDim)
1433 const ScDPSaveDimension& rDim = *itDim;
1434 rDim.Dump();
1438 #endif
1440 void ScDPSaveData::CheckDuplicateName(ScDPSaveDimension& rDim)
1442 const OUString aName = ScDPUtil::getSourceDimensionName(rDim.GetName());
1443 DupNameCountType::iterator it = maDupNameCounts.find(aName);
1444 if (it != maDupNameCounts.end())
1446 rDim.SetName(ScDPUtil::createDuplicateDimensionName(aName, ++it->second));
1447 rDim.SetDupFlag(true);
1449 else
1450 // New name.
1451 maDupNameCounts.insert(DupNameCountType::value_type(aName, 0));
1454 void ScDPSaveData::RemoveDuplicateNameCount(const OUString& rName)
1456 OUString aCoreName = rName;
1457 if (ScDPUtil::isDuplicateDimension(rName))
1458 aCoreName = ScDPUtil::getSourceDimensionName(rName);
1460 DupNameCountType::iterator it = maDupNameCounts.find(aCoreName);
1461 if (it == maDupNameCounts.end())
1462 return;
1464 if (!it->second)
1466 maDupNameCounts.erase(it);
1467 return;
1470 --it->second;
1471 return;
1474 ScDPSaveDimension* ScDPSaveData::AppendNewDimension(const OUString& rName, bool bDataLayout)
1476 if (ScDPUtil::isDuplicateDimension(rName))
1477 // This call is for original dimensions only.
1478 return NULL;
1480 ScDPSaveDimension* pNew = new ScDPSaveDimension(rName, bDataLayout);
1481 aDimList.push_back(pNew);
1482 if (!maDupNameCounts.count(rName))
1483 maDupNameCounts.insert(DupNameCountType::value_type(rName, 0));
1485 DimensionsChanged();
1486 return pNew;
1489 void ScDPSaveData::DimensionsChanged()
1491 mpDimOrder.reset();
1494 bool operator == (const ::com::sun::star::sheet::DataPilotFieldSortInfo &l, const ::com::sun::star::sheet::DataPilotFieldSortInfo &r )
1496 return l.Field == r.Field && l.IsAscending == r.IsAscending && l.Mode == r.Mode;
1498 bool operator == (const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &l, const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &r )
1500 return l.IsEnabled == r.IsEnabled &&
1501 l.ShowItemsMode == r.ShowItemsMode &&
1502 l.ItemCount == r.ItemCount &&
1503 l.DataField == r.DataField;
1505 bool operator == (const ::com::sun::star::sheet::DataPilotFieldReference &l, const ::com::sun::star::sheet::DataPilotFieldReference &r )
1507 return l.ReferenceType == r.ReferenceType &&
1508 l.ReferenceField == r.ReferenceField &&
1509 l.ReferenceItemType == r.ReferenceItemType &&
1510 l.ReferenceItemName == r.ReferenceItemName;
1513 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */