LCOV - code coverage report
Current view: top level - sc/source/core/data - dpsave.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 751 0.0 %
Date: 2014-04-14 Functions: 0 94 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "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"
      28             : 
      29             : #include <sal/types.h>
      30             : #include "comphelper/string.hxx"
      31             : 
      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>
      45             : 
      46             : #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
      47             : #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
      48             : 
      49             : #include <boost/unordered_map.hpp>
      50             : #include <boost/unordered_set.hpp>
      51             : 
      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;
      57             : 
      58             : #define SC_DPSAVEMODE_DONTKNOW 2
      59             : 
      60           0 : static void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp,
      61             :                             const OUString& rName, sal_Bool bValue )
      62             : {
      63             :     //! move to ScUnoHelpFunctions?
      64             : 
      65           0 :     xProp->setPropertyValue( rName, uno::Any( &bValue, getBooleanCppuType() ) );
      66           0 : }
      67             : 
      68           0 : ScDPSaveMember::ScDPSaveMember(const OUString& rName) :
      69             :     aName( rName ),
      70             :     mpLayoutName(NULL),
      71             :     nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
      72           0 :     nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
      73             : {
      74           0 : }
      75             : 
      76           0 : ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
      77             :     aName( r.aName ),
      78             :     mpLayoutName(NULL),
      79             :     nVisibleMode( r.nVisibleMode ),
      80           0 :     nShowDetailsMode( r.nShowDetailsMode )
      81             : {
      82           0 :     if (r.mpLayoutName)
      83           0 :         mpLayoutName.reset(new OUString(*r.mpLayoutName));
      84           0 : }
      85             : 
      86           0 : ScDPSaveMember::~ScDPSaveMember()
      87             : {
      88           0 : }
      89             : 
      90           0 : bool ScDPSaveMember::operator== ( const ScDPSaveMember& r ) const
      91             : {
      92           0 :     if ( aName            != r.aName           ||
      93           0 :          nVisibleMode     != r.nVisibleMode    ||
      94           0 :          nShowDetailsMode != r.nShowDetailsMode )
      95           0 :         return false;
      96             : 
      97           0 :     return true;
      98             : }
      99             : 
     100           0 : bool ScDPSaveMember::HasIsVisible() const
     101             : {
     102           0 :     return nVisibleMode != SC_DPSAVEMODE_DONTKNOW;
     103             : }
     104             : 
     105           0 : void ScDPSaveMember::SetIsVisible(bool bSet)
     106             : {
     107           0 :     nVisibleMode = sal_uInt16(bSet);
     108           0 : }
     109             : 
     110           0 : bool ScDPSaveMember::HasShowDetails() const
     111             : {
     112           0 :     return nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW;
     113             : }
     114             : 
     115           0 : void ScDPSaveMember::SetShowDetails(bool bSet)
     116             : {
     117           0 :     nShowDetailsMode = sal_uInt16(bSet);
     118           0 : }
     119             : 
     120           0 : void ScDPSaveMember::SetName( const OUString& rNew )
     121             : {
     122             :     // Used only if the source member was renamed (groups).
     123             :     // For UI renaming of members, a layout name must be used.
     124             : 
     125           0 :     aName = rNew;
     126           0 : }
     127             : 
     128           0 : void ScDPSaveMember::SetLayoutName( const OUString& rName )
     129             : {
     130           0 :     mpLayoutName.reset(new OUString(rName));
     131           0 : }
     132             : 
     133           0 : const OUString* ScDPSaveMember::GetLayoutName() const
     134             : {
     135           0 :     return mpLayoutName.get();
     136             : }
     137             : 
     138           0 : void ScDPSaveMember::RemoveLayoutName()
     139             : {
     140           0 :     mpLayoutName.reset();
     141           0 : }
     142             : 
     143           0 : void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
     144             : {
     145           0 :     uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
     146             :     OSL_ENSURE( xMembProp.is(), "no properties at member" );
     147           0 :     if ( xMembProp.is() )
     148             :     {
     149             :         // exceptions are caught at ScDPSaveData::WriteToSource
     150             : 
     151           0 :         if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW )
     152             :             lcl_SetBoolProperty( xMembProp,
     153           0 :                     OUString(SC_UNO_DP_ISVISIBLE), (bool)nVisibleMode );
     154             : 
     155           0 :         if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW )
     156             :             lcl_SetBoolProperty( xMembProp,
     157           0 :                     OUString(SC_UNO_DP_SHOWDETAILS), (bool)nShowDetailsMode );
     158             : 
     159           0 :         if (mpLayoutName)
     160           0 :             ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_DP_LAYOUTNAME, *mpLayoutName);
     161             : 
     162           0 :         if ( nPosition >= 0 )
     163           0 :             ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_DP_POSITION, nPosition);
     164           0 :     }
     165           0 : }
     166             : 
     167             : #if DEBUG_PIVOT_TABLE
     168             : 
     169             : void ScDPSaveMember::Dump(int nIndent) const
     170             : {
     171             :     std::string aIndent(nIndent*4, ' ');
     172             :     cout << aIndent << "* member name: '" << aName << "'" << endl;
     173             : 
     174             :     cout << aIndent << "    + layout name: ";
     175             :     if (mpLayoutName)
     176             :         cout << "'" << *mpLayoutName << "'";
     177             :     else
     178             :         cout << "(none)";
     179             :     cout << endl;
     180             : 
     181             :     cout << aIndent << "    + visibility: ";
     182             :     if (nVisibleMode == SC_DPSAVEMODE_DONTKNOW)
     183             :         cout << "(unknown)";
     184             :     else
     185             :         cout << (nVisibleMode ? "visible" : "hidden");
     186             :     cout << endl;
     187             : }
     188             : 
     189             : #endif
     190             : 
     191           0 : 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           0 :     pLayoutInfo( NULL )
     208             : {
     209           0 : }
     210             : 
     211           0 : 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           0 :     pSubTotalFuncs( NULL )
     224             : {
     225           0 :     if ( nSubTotalCount && r.pSubTotalFuncs )
     226             :     {
     227           0 :         pSubTotalFuncs = new sal_uInt16[nSubTotalCount];
     228           0 :         for (long nSub=0; nSub<nSubTotalCount; nSub++)
     229           0 :             pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub];
     230             :     }
     231             : 
     232           0 :     for (MemberList::const_iterator i=r.maMemberList.begin(); i != r.maMemberList.end() ; ++i)
     233             :     {
     234           0 :         const OUString& rName =  (*i)->GetName();
     235           0 :         ScDPSaveMember* pNew = new ScDPSaveMember( **i );
     236           0 :         maMemberHash[rName] = pNew;
     237           0 :         maMemberList.push_back( pNew );
     238             :     }
     239           0 :     if (r.pReferenceValue)
     240           0 :         pReferenceValue = new sheet::DataPilotFieldReference( *(r.pReferenceValue) );
     241             :     else
     242           0 :         pReferenceValue = NULL;
     243           0 :     if (r.pSortInfo)
     244           0 :         pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) );
     245             :     else
     246           0 :         pSortInfo = NULL;
     247           0 :     if (r.pAutoShowInfo)
     248           0 :         pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) );
     249             :     else
     250           0 :         pAutoShowInfo = NULL;
     251           0 :     if (r.pLayoutInfo)
     252           0 :         pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
     253             :     else
     254           0 :         pLayoutInfo = NULL;
     255           0 :     if (r.mpLayoutName)
     256           0 :         mpLayoutName.reset(new OUString(*r.mpLayoutName));
     257           0 :     if (r.mpSubtotalName)
     258           0 :         mpSubtotalName.reset(new OUString(*r.mpSubtotalName));
     259           0 : }
     260             : 
     261           0 : ScDPSaveDimension::~ScDPSaveDimension()
     262             : {
     263           0 :     for (MemberHash::const_iterator i=maMemberHash.begin(); i != maMemberHash.end() ; ++i)
     264           0 :         delete i->second;
     265           0 :     delete pReferenceValue;
     266           0 :     delete pSortInfo;
     267           0 :     delete pAutoShowInfo;
     268           0 :     delete pLayoutInfo;
     269           0 :     delete [] pSubTotalFuncs;
     270           0 : }
     271             : 
     272           0 : bool ScDPSaveDimension::operator== ( const ScDPSaveDimension& r ) const
     273             : {
     274           0 :     if ( aName            != r.aName            ||
     275           0 :          bIsDataLayout    != r.bIsDataLayout    ||
     276           0 :          bDupFlag         != r.bDupFlag         ||
     277           0 :          nOrientation     != r.nOrientation     ||
     278           0 :          nFunction        != r.nFunction        ||
     279           0 :          nUsedHierarchy   != r.nUsedHierarchy   ||
     280           0 :          nShowEmptyMode   != r.nShowEmptyMode   ||
     281           0 :          bSubTotalDefault != r.bSubTotalDefault ||
     282           0 :          nSubTotalCount   != r.nSubTotalCount    )
     283           0 :         return false;
     284             : 
     285           0 :     if ( nSubTotalCount && ( !pSubTotalFuncs || !r.pSubTotalFuncs ) ) // should not happen
     286           0 :         return false;
     287             : 
     288             :     long i;
     289           0 :     for (i=0; i<nSubTotalCount; i++)
     290           0 :         if ( pSubTotalFuncs[i] != r.pSubTotalFuncs[i] )
     291           0 :             return false;
     292             : 
     293           0 :     if (maMemberHash.size() != r.maMemberHash.size() )
     294           0 :         return false;
     295             : 
     296           0 :     MemberList::const_iterator a=maMemberList.begin();
     297           0 :     MemberList::const_iterator b=r.maMemberList.begin();
     298           0 :     for (; a != maMemberList.end() ; ++a, ++b)
     299           0 :         if (!(**a == **b))
     300           0 :             return false;
     301             : 
     302           0 :     if( pReferenceValue && r.pReferenceValue )
     303             :     {
     304           0 :         if ( !(*pReferenceValue == *r.pReferenceValue) )
     305             :         {
     306           0 :             return false;
     307             :         }
     308             :     }
     309           0 :     else if ( pReferenceValue || r.pReferenceValue )
     310             :     {
     311           0 :         return false;
     312             :     }
     313           0 :     if( this->pSortInfo && r.pSortInfo )
     314             :     {
     315           0 :         if ( !(*this->pSortInfo == *r.pSortInfo) )
     316             :         {
     317           0 :             return false;
     318             :         }
     319             :     }
     320           0 :     else if ( this->pSortInfo || r.pSortInfo )
     321             :     {
     322           0 :         return false;
     323             :     }
     324           0 :     if( this->pAutoShowInfo && r.pAutoShowInfo )
     325             :     {
     326           0 :         if ( !(*this->pAutoShowInfo == *r.pAutoShowInfo) )
     327             :         {
     328           0 :             return false;
     329             :         }
     330             :     }
     331           0 :     else if ( this->pAutoShowInfo || r.pAutoShowInfo )
     332             :     {
     333           0 :         return false;
     334             :     }
     335             : 
     336           0 :     return true;
     337             : }
     338             : 
     339           0 : void ScDPSaveDimension::AddMember(ScDPSaveMember* pMember)
     340             : {
     341           0 :     const OUString & rName = pMember->GetName();
     342           0 :     MemberHash::iterator aExisting = maMemberHash.find( rName );
     343           0 :     if ( aExisting == maMemberHash.end() )
     344             :     {
     345           0 :         std::pair< const OUString, ScDPSaveMember *> key( rName, pMember );
     346           0 :         maMemberHash.insert ( key );
     347             :     }
     348             :     else
     349             :     {
     350           0 :         maMemberList.remove( aExisting->second );
     351           0 :         delete aExisting->second;
     352           0 :         aExisting->second = pMember;
     353             :     }
     354           0 :     maMemberList.push_back( pMember );
     355           0 : }
     356             : 
     357           0 : void ScDPSaveDimension::SetName( const OUString& rNew )
     358             : {
     359             :     // Used only if the source dim was renamed (groups).
     360             :     // For UI renaming of dimensions, the layout name must be used.
     361             : 
     362           0 :     aName = rNew;
     363           0 : }
     364             : 
     365           0 : void ScDPSaveDimension::SetOrientation(sal_uInt16 nNew)
     366             : {
     367           0 :     nOrientation = nNew;
     368           0 : }
     369             : 
     370           0 : void ScDPSaveDimension::SetSubTotals(long nCount, const sal_uInt16* pFuncs)
     371             : {
     372           0 :     if (pSubTotalFuncs)
     373           0 :         delete [] pSubTotalFuncs;
     374           0 :     nSubTotalCount = nCount;
     375           0 :     if ( nCount && pFuncs )
     376             :     {
     377           0 :         pSubTotalFuncs = new sal_uInt16[nCount];
     378           0 :         for (long i=0; i<nCount; i++)
     379           0 :             pSubTotalFuncs[i] = pFuncs[i];
     380             :     }
     381             :     else
     382           0 :         pSubTotalFuncs = NULL;
     383             : 
     384           0 :     bSubTotalDefault = false;
     385           0 : }
     386             : 
     387           0 : bool ScDPSaveDimension::HasShowEmpty() const
     388             : {
     389           0 :     return nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW;
     390             : }
     391             : 
     392           0 : void ScDPSaveDimension::SetShowEmpty(bool bSet)
     393             : {
     394           0 :     nShowEmptyMode = sal_uInt16(bSet);
     395           0 : }
     396             : 
     397           0 : void ScDPSaveDimension::SetFunction(sal_uInt16 nNew)
     398             : {
     399           0 :     nFunction = nNew;
     400           0 : }
     401             : 
     402           0 : void ScDPSaveDimension::SetUsedHierarchy(long nNew)
     403             : {
     404           0 :     nUsedHierarchy = nNew;
     405           0 : }
     406             : 
     407           0 : void ScDPSaveDimension::SetSubtotalName(const OUString& rName)
     408             : {
     409           0 :     mpSubtotalName.reset(new OUString(rName));
     410           0 : }
     411             : 
     412           0 : const OUString* ScDPSaveDimension::GetSubtotalName() const
     413             : {
     414           0 :     return mpSubtotalName.get();
     415             : }
     416             : 
     417           0 : void ScDPSaveDimension::RemoveSubtotalName()
     418             : {
     419           0 :     mpSubtotalName.reset();
     420           0 : }
     421             : 
     422           0 : bool ScDPSaveDimension::IsMemberNameInUse(const OUString& rName) const
     423             : {
     424           0 :     MemberList::const_iterator itr = maMemberList.begin(), itrEnd = maMemberList.end();
     425           0 :     for (; itr != itrEnd; ++itr)
     426             :     {
     427           0 :         const ScDPSaveMember* pMem = *itr;
     428           0 :         if (rName.equalsIgnoreAsciiCase(pMem->GetName()))
     429           0 :             return true;
     430             : 
     431           0 :         const OUString* pLayoutName = pMem->GetLayoutName();
     432           0 :         if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName))
     433           0 :             return true;
     434             :     }
     435           0 :     return false;
     436             : }
     437             : 
     438           0 : void ScDPSaveDimension::SetLayoutName(const OUString& rName)
     439             : {
     440           0 :     mpLayoutName.reset(new OUString(rName));
     441           0 : }
     442             : 
     443           0 : const OUString* ScDPSaveDimension::GetLayoutName() const
     444             : {
     445           0 :     return mpLayoutName.get();
     446             : }
     447             : 
     448           0 : void ScDPSaveDimension::RemoveLayoutName()
     449             : {
     450           0 :     mpLayoutName.reset();
     451           0 : }
     452             : 
     453           0 : void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
     454             : {
     455           0 :     delete pReferenceValue;
     456           0 :     if (pNew)
     457           0 :         pReferenceValue = new sheet::DataPilotFieldReference(*pNew);
     458             :     else
     459           0 :         pReferenceValue = NULL;
     460           0 : }
     461             : 
     462           0 : void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew)
     463             : {
     464           0 :     delete pSortInfo;
     465           0 :     if (pNew)
     466           0 :         pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew);
     467             :     else
     468           0 :         pSortInfo = NULL;
     469           0 : }
     470             : 
     471           0 : void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew)
     472             : {
     473           0 :     delete pAutoShowInfo;
     474           0 :     if (pNew)
     475           0 :         pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew);
     476             :     else
     477           0 :         pAutoShowInfo = NULL;
     478           0 : }
     479             : 
     480           0 : void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew)
     481             : {
     482           0 :     delete pLayoutInfo;
     483           0 :     if (pNew)
     484           0 :         pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew);
     485             :     else
     486           0 :         pLayoutInfo = NULL;
     487           0 : }
     488             : 
     489           0 : void ScDPSaveDimension::SetCurrentPage( const OUString* pPage )
     490             : {
     491             :     // We use member's visibility attribute to filter by page dimension.
     492             : 
     493             :     // pPage == NULL -> all members visible.
     494           0 :     MemberList::iterator it = maMemberList.begin(), itEnd = maMemberList.end();
     495           0 :     for (; it != itEnd; ++it)
     496             :     {
     497           0 :         ScDPSaveMember* pMem = *it;
     498           0 :         bool bVisible = !pPage || pMem->GetName() == *pPage;
     499           0 :         pMem->SetIsVisible(bVisible);
     500             :     }
     501           0 : }
     502             : 
     503           0 : ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const OUString& rName)
     504             : {
     505           0 :     MemberHash::const_iterator res = maMemberHash.find (rName);
     506           0 :     if (res != maMemberHash.end())
     507           0 :         return res->second;
     508           0 :     return NULL;
     509             : }
     510             : 
     511           0 : ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const OUString& rName)
     512             : {
     513           0 :     MemberHash::const_iterator res = maMemberHash.find (rName);
     514           0 :     if (res != maMemberHash.end())
     515           0 :         return res->second;
     516             : 
     517           0 :     ScDPSaveMember* pNew = new ScDPSaveMember( rName );
     518           0 :     maMemberHash[rName] = pNew;
     519           0 :     maMemberList.push_back( pNew );
     520           0 :     return pNew;
     521             : }
     522             : 
     523           0 : void ScDPSaveDimension::SetMemberPosition( const OUString& rName, sal_Int32 nNewPos )
     524             : {
     525           0 :     ScDPSaveMember* pMember = GetMemberByName( rName ); // make sure it exists and is in the hash
     526             : 
     527           0 :     maMemberList.remove( pMember );
     528             : 
     529           0 :     MemberList::iterator aIter = maMemberList.begin();
     530           0 :     for (sal_Int32 i=0; i<nNewPos && aIter != maMemberList.end(); i++)
     531           0 :         ++aIter;
     532           0 :     maMemberList.insert( aIter, pMember );
     533           0 : }
     534             : 
     535           0 : void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim )
     536             : {
     537           0 :     uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
     538             :     OSL_ENSURE( xDimProp.is(), "no properties at dimension" );
     539           0 :     if ( xDimProp.is() )
     540             :     {
     541             :         // exceptions are caught at ScDPSaveData::WriteToSource
     542           0 :         uno::Any aAny;
     543             : 
     544           0 :         sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
     545           0 :         aAny <<= eOrient;
     546           0 :         xDimProp->setPropertyValue( OUString(SC_UNO_DP_ORIENTATION), aAny );
     547             : 
     548           0 :         sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
     549           0 :         aAny <<= eFunc;
     550           0 :         xDimProp->setPropertyValue( OUString(SC_UNO_DP_FUNCTION), aAny );
     551             : 
     552           0 :         if ( nUsedHierarchy >= 0 )
     553             :         {
     554           0 :             aAny <<= (sal_Int32)nUsedHierarchy;
     555           0 :             xDimProp->setPropertyValue( OUString(SC_UNO_DP_USEDHIERARCHY), aAny );
     556             :         }
     557             : 
     558           0 :         if ( pReferenceValue )
     559             :         {
     560           0 :             aAny <<= *pReferenceValue;
     561           0 :             xDimProp->setPropertyValue( OUString(SC_UNO_DP_REFVALUE), aAny );
     562             :         }
     563             : 
     564           0 :         if (mpLayoutName)
     565           0 :             ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_LAYOUTNAME, *mpLayoutName);
     566             : 
     567           0 :         const OUString* pSubTotalName = GetSubtotalName();
     568           0 :         if (pSubTotalName)
     569             :             // Custom subtotal name, with '?' being replaced by the visible field name later.
     570           0 :             ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_FIELD_SUBTOTALNAME, *pSubTotalName);
     571             :     }
     572             : 
     573             :     // Level loop outside of maMemberList loop
     574             :     // because SubTotals have to be set independently of known members
     575             : 
     576           0 :     long nCount = maMemberHash.size();
     577             : 
     578           0 :     long nHierCount = 0;
     579           0 :     uno::Reference<container::XIndexAccess> xHiers;
     580           0 :     uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
     581           0 :     if ( xHierSupp.is() )
     582             :     {
     583           0 :         uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
     584           0 :         xHiers = new ScNameToIndexAccess( xHiersName );
     585           0 :         nHierCount = xHiers->getCount();
     586             :     }
     587             : 
     588           0 :     bool bHasHiddenMember = false;
     589             : 
     590           0 :     for (long nHier=0; nHier<nHierCount; nHier++)
     591             :     {
     592           0 :         uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
     593             : 
     594           0 :         long nLevCount = 0;
     595           0 :         uno::Reference<container::XIndexAccess> xLevels;
     596           0 :         uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
     597           0 :         if ( xLevSupp.is() )
     598             :         {
     599           0 :             uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
     600           0 :             xLevels = new ScNameToIndexAccess( xLevelsName );
     601           0 :             nLevCount = xLevels->getCount();
     602             :         }
     603             : 
     604           0 :         for (long nLev=0; nLev<nLevCount; nLev++)
     605             :         {
     606           0 :             uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) );
     607           0 :             uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
     608             :             OSL_ENSURE( xLevProp.is(), "no properties at level" );
     609           0 :             if ( xLevProp.is() )
     610             :             {
     611           0 :                 uno::Any aAny;
     612           0 :                 if ( !bSubTotalDefault )
     613             :                 {
     614           0 :                     if ( !pSubTotalFuncs )
     615           0 :                         nSubTotalCount = 0;
     616             : 
     617           0 :                     uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount);
     618           0 :                     sheet::GeneralFunction* pArray = aSeq.getArray();
     619           0 :                     for (long i=0; i<nSubTotalCount; i++)
     620           0 :                         pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i];
     621           0 :                     aAny <<= aSeq;
     622           0 :                     xLevProp->setPropertyValue( OUString(SC_UNO_DP_SUBTOTAL), aAny );
     623             :                 }
     624           0 :                 if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW )
     625             :                     lcl_SetBoolProperty( xLevProp,
     626           0 :                         OUString(SC_UNO_DP_SHOWEMPTY), (bool)nShowEmptyMode );
     627             : 
     628           0 :                 if ( pSortInfo )
     629           0 :                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_SORTING, *pSortInfo);
     630             : 
     631           0 :                 if ( pAutoShowInfo )
     632           0 :                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_AUTOSHOW, *pAutoShowInfo);
     633             : 
     634           0 :                 if ( pLayoutInfo )
     635           0 :                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_LAYOUT, *pLayoutInfo);
     636             : 
     637             :                 // exceptions are caught at ScDPSaveData::WriteToSource
     638             :             }
     639             : 
     640           0 :             if ( nCount > 0 )
     641             :             {
     642           0 :                 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
     643           0 :                 if ( xMembSupp.is() )
     644             :                 {
     645           0 :                     uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
     646           0 :                     if ( xMembers.is() )
     647             :                     {
     648           0 :                         sal_Int32 nPosition = -1; // set position only in manual mode
     649           0 :                         if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL )
     650           0 :                             nPosition = 0;
     651             : 
     652           0 :                         for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; ++i)
     653             :                         {
     654           0 :                             ScDPSaveMember* pMember = *i;
     655           0 :                             if (!pMember->GetIsVisible())
     656           0 :                                 bHasHiddenMember = true;
     657           0 :                             OUString aMemberName = pMember->GetName();
     658           0 :                             if ( xMembers->hasByName( aMemberName ) )
     659             :                             {
     660             :                                 uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
     661           0 :                                     xMembers->getByName( aMemberName ) );
     662           0 :                                 pMember->WriteToSource( xMemberInt, nPosition );
     663             : 
     664           0 :                                 if ( nPosition >= 0 )
     665           0 :                                     ++nPosition; // increase if initialized
     666             :                             }
     667             :                             // missing member is no error
     668           0 :                         }
     669           0 :                     }
     670           0 :                 }
     671             :             }
     672           0 :         }
     673           0 :     }
     674             : 
     675           0 :     if (xDimProp.is())
     676           0 :         ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_HAS_HIDDEN_MEMBER, bHasHiddenMember);
     677           0 : }
     678             : 
     679           0 : void ScDPSaveDimension::UpdateMemberVisibility(const boost::unordered_map<OUString, bool, OUStringHash>& rData)
     680             : {
     681             :     typedef boost::unordered_map<OUString, bool, OUStringHash> DataMap;
     682           0 :     MemberList::iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
     683           0 :     for (; itrMem != itrMemEnd; ++itrMem)
     684             :     {
     685           0 :         ScDPSaveMember* pMem = *itrMem;
     686           0 :         const OUString& rMemName = pMem->GetName();
     687           0 :         DataMap::const_iterator itr = rData.find(rMemName);
     688           0 :         if (itr != rData.end())
     689           0 :             pMem->SetIsVisible(itr->second);
     690             :     }
     691           0 : }
     692             : 
     693           0 : bool ScDPSaveDimension::HasInvisibleMember() const
     694             : {
     695           0 :     MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
     696           0 :     for (; itrMem != itrMemEnd; ++itrMem)
     697             :     {
     698           0 :         const ScDPSaveMember* pMem = *itrMem;
     699           0 :         if (!pMem->GetIsVisible())
     700           0 :             return true;
     701             :     }
     702           0 :     return false;
     703             : }
     704             : 
     705           0 : void ScDPSaveDimension::RemoveObsoleteMembers(const MemberSetType& rMembers)
     706             : {
     707           0 :     maMemberHash.clear();
     708           0 :     MemberList aNew;
     709           0 :     MemberList::iterator it = maMemberList.begin(), itEnd = maMemberList.end();
     710           0 :     for (; it != itEnd; ++it)
     711             :     {
     712           0 :         ScDPSaveMember* pMem = *it;
     713           0 :         if (rMembers.count(pMem->GetName()))
     714             :         {
     715             :             // This member still exists.
     716           0 :             maMemberHash.insert(MemberHash::value_type(pMem->GetName(), pMem));
     717           0 :             aNew.push_back(pMem);
     718             :         }
     719             :         else
     720             :         {
     721             :             // This member no longer exists.
     722           0 :             delete pMem;
     723             :         }
     724             :     }
     725             : 
     726           0 :     maMemberList.swap(aNew);
     727           0 : }
     728             : 
     729             : #if DEBUG_PIVOT_TABLE
     730             : 
     731             : void ScDPSaveDimension::Dump(int nIndent) const
     732             : {
     733             :     static const char* pOrientNames[] = { "hidden", "column", "row", "page", "data" };
     734             :     std::string aIndent(nIndent*4, ' ');
     735             : 
     736             :     cout << aIndent << "* dimension name: '" << aName << "'" << endl;
     737             : 
     738             :     cout << aIndent << "    + orientation: ";
     739             :     if (nOrientation <= 4)
     740             :         cout << pOrientNames[nOrientation];
     741             :     else
     742             :         cout << "(invalid)";
     743             :     cout << endl;
     744             : 
     745             :     cout << aIndent << "    + layout name: ";
     746             :     if (mpLayoutName)
     747             :         cout << "'" << *mpLayoutName << "'";
     748             :     else
     749             :         cout << "(none)";
     750             :     cout << endl;
     751             : 
     752             :     cout << aIndent << "    + subtotal name: ";
     753             :     if (mpSubtotalName)
     754             :         cout << "'" << *mpSubtotalName << "'";
     755             :     else
     756             :         cout << "(none)";
     757             :     cout << endl;
     758             : 
     759             :     cout << aIndent << "    + is data layout: " << (bIsDataLayout ? "yes" : "no") << endl;
     760             :     cout << aIndent << "    + is duplicate: " << (bDupFlag ? "yes" : "no") << endl;
     761             : 
     762             :     MemberList::const_iterator itMem = maMemberList.begin(), itMemEnd = maMemberList.end();
     763             :     for (; itMem != itMemEnd; ++itMem)
     764             :     {
     765             :         ScDPSaveMember* pMem = *itMem;
     766             :         pMem->Dump(nIndent+1);
     767             :     }
     768             : 
     769             :     cout << endl; // blank line
     770             : }
     771             : 
     772             : #endif
     773             : 
     774           0 : 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           0 :     mpGrandTotalName(NULL)
     784             : {
     785           0 : }
     786             : 
     787           0 : 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           0 :     mpDimOrder(NULL)
     797             : {
     798           0 :     if ( r.pDimensionData )
     799           0 :         pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
     800             :     else
     801           0 :         pDimensionData = NULL;
     802             : 
     803           0 :     aDimList = r.aDimList.clone();
     804             : 
     805           0 :     if (r.mpGrandTotalName)
     806           0 :         mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
     807           0 : }
     808             : 
     809           0 : ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
     810             : {
     811           0 :     if ( &r != this )
     812             :     {
     813           0 :         this->~ScDPSaveData();
     814           0 :         new( this ) ScDPSaveData ( r );
     815             :     }
     816           0 :     return *this;
     817             : }
     818             : 
     819           0 : bool ScDPSaveData::operator== ( const ScDPSaveData& r ) const
     820             : {
     821           0 :     if ( nColumnGrandMode != r.nColumnGrandMode ||
     822           0 :          nRowGrandMode    != r.nRowGrandMode    ||
     823           0 :          nIgnoreEmptyMode != r.nIgnoreEmptyMode ||
     824           0 :          nRepeatEmptyMode != r.nRepeatEmptyMode ||
     825           0 :          bFilterButton    != r.bFilterButton    ||
     826           0 :          bDrillDown       != r.bDrillDown       ||
     827           0 :          mbDimensionMembersBuilt != r.mbDimensionMembersBuilt)
     828           0 :         return false;
     829             : 
     830           0 :     if ( pDimensionData || r.pDimensionData )
     831           0 :         if ( !pDimensionData || !r.pDimensionData || !( *pDimensionData == *r.pDimensionData ) )
     832           0 :             return false;
     833             : 
     834           0 :     if ( aDimList.size() != r.aDimList.size() )
     835           0 :         return false;
     836             : 
     837           0 :     if (aDimList != r.aDimList)
     838           0 :         return false;
     839             : 
     840           0 :     if (mpGrandTotalName)
     841             :     {
     842           0 :         if (!r.mpGrandTotalName)
     843           0 :             return false;
     844           0 :         if (!mpGrandTotalName->equals(*r.mpGrandTotalName))
     845           0 :             return false;
     846             :     }
     847           0 :     else if (r.mpGrandTotalName)
     848           0 :         return false;
     849             : 
     850           0 :     return true;
     851             : }
     852             : 
     853           0 : ScDPSaveData::~ScDPSaveData()
     854             : {
     855           0 :     delete pDimensionData;
     856           0 : }
     857             : 
     858           0 : void ScDPSaveData::SetGrandTotalName(const OUString& rName)
     859             : {
     860           0 :     mpGrandTotalName.reset(new OUString(rName));
     861           0 : }
     862             : 
     863           0 : const OUString* ScDPSaveData::GetGrandTotalName() const
     864             : {
     865           0 :     return mpGrandTotalName.get();
     866             : }
     867             : 
     868           0 : const ScDPSaveData::DimsType& ScDPSaveData::GetDimensions() const
     869             : {
     870           0 :     return aDimList;
     871             : }
     872             : 
     873             : namespace {
     874             : 
     875             : class DimOrderInserter : std::unary_function<const ScDPSaveDimension*, void>
     876             : {
     877             :     ScDPSaveData::DimOrderType& mrNames;
     878             : public:
     879           0 :     DimOrderInserter(ScDPSaveData::DimOrderType& rNames) : mrNames(rNames) {}
     880             : 
     881           0 :     void operator() (const ScDPSaveDimension* pDim)
     882             :     {
     883           0 :         size_t nRank = mrNames.size();
     884             :         mrNames.insert(
     885           0 :             ScDPSaveData::DimOrderType::value_type(pDim->GetName(), nRank));
     886           0 :     }
     887             : };
     888             : 
     889             : }
     890             : 
     891           0 : const ScDPSaveData::DimOrderType& ScDPSaveData::GetDimensionSortOrder() const
     892             : {
     893           0 :     if (!mpDimOrder)
     894             :     {
     895           0 :         mpDimOrder.reset(new DimOrderType);
     896           0 :         std::vector<const ScDPSaveDimension*> aRowDims, aColDims;
     897           0 :         GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aRowDims);
     898           0 :         GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aColDims);
     899             : 
     900           0 :         std::for_each(aRowDims.begin(), aRowDims.end(), DimOrderInserter(*mpDimOrder));
     901           0 :         std::for_each(aColDims.begin(), aColDims.end(), DimOrderInserter(*mpDimOrder));
     902             :     }
     903           0 :     return *mpDimOrder;
     904             : }
     905             : 
     906           0 : void ScDPSaveData::GetAllDimensionsByOrientation(
     907             :     sheet::DataPilotFieldOrientation eOrientation, std::vector<const ScDPSaveDimension*>& rDims) const
     908             : {
     909           0 :     std::vector<const ScDPSaveDimension*> aDims;
     910           0 :     DimsType::const_iterator it = aDimList.begin(), itEnd = aDimList.end();
     911           0 :     for (; it != itEnd; ++it)
     912             :     {
     913           0 :         const ScDPSaveDimension& rDim = *it;
     914           0 :         if (rDim.GetOrientation() != static_cast<sal_uInt16>(eOrientation))
     915           0 :             continue;
     916             : 
     917           0 :         aDims.push_back(&rDim);
     918             :     }
     919             : 
     920           0 :     rDims.swap(aDims);
     921           0 : }
     922             : 
     923           0 : void ScDPSaveData::AddDimension(ScDPSaveDimension* pDim)
     924             : {
     925           0 :     if (!pDim)
     926           0 :         return;
     927             : 
     928           0 :     CheckDuplicateName(*pDim);
     929           0 :     aDimList.push_back(pDim);
     930             : 
     931           0 :     DimensionsChanged();
     932             : }
     933             : 
     934           0 : ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const OUString& rName)
     935             : {
     936           0 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
     937           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
     938             :     {
     939           0 :         if (iter->GetName() == rName && !iter->IsDataLayout() )
     940           0 :             return const_cast<ScDPSaveDimension*>(&(*iter));
     941             :     }
     942             : 
     943           0 :     return AppendNewDimension(rName, false);
     944             : }
     945             : 
     946           0 : ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const OUString& rName) const
     947             : {
     948           0 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
     949           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
     950             :     {
     951           0 :         if (iter->GetName() == rName && !iter->IsDataLayout() )
     952           0 :             return const_cast<ScDPSaveDimension*>(&(*iter));
     953             :     }
     954           0 :     return NULL; // don't create new
     955             : }
     956             : 
     957           0 : ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const OUString& rName)
     958             : {
     959           0 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
     960           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
     961             :     {
     962           0 :         if (iter->GetName() == rName && !iter->IsDataLayout() )
     963           0 :             return DuplicateDimension(rName);
     964             :     }
     965             : 
     966           0 :     return AppendNewDimension(rName, false);
     967             : }
     968             : 
     969           0 : ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
     970             : {
     971           0 :     ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
     972           0 :     if (pDim)
     973           0 :         return pDim;
     974             : 
     975           0 :     return AppendNewDimension(OUString(), true);
     976             : }
     977             : 
     978           0 : ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const
     979             : {
     980           0 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
     981           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
     982             :     {
     983           0 :         if ( iter->IsDataLayout() )
     984           0 :             return const_cast<ScDPSaveDimension*>(&(*iter));
     985             :     }
     986           0 :     return NULL;
     987             : }
     988             : 
     989           0 : ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const OUString& rName)
     990             : {
     991             :     // always insert new
     992             : 
     993           0 :     ScDPSaveDimension* pOld = GetExistingDimensionByName(rName);
     994           0 :     if (!pOld)
     995           0 :         return NULL;
     996             : 
     997           0 :     ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld );
     998           0 :     AddDimension(pNew);
     999           0 :     return pNew;
    1000             : }
    1001             : 
    1002           0 : void ScDPSaveData::RemoveDimensionByName(const OUString& rName)
    1003             : {
    1004           0 :     boost::ptr_vector<ScDPSaveDimension>::iterator iter;
    1005           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
    1006             :     {
    1007           0 :         if (iter->GetName() != rName || iter->IsDataLayout())
    1008           0 :             continue;
    1009             : 
    1010           0 :         aDimList.erase(iter);
    1011           0 :         RemoveDuplicateNameCount(rName);
    1012           0 :         DimensionsChanged();
    1013           0 :         return;
    1014             :     }
    1015             : }
    1016             : 
    1017           0 : ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rDim )
    1018             : {
    1019           0 :     ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim );
    1020           0 :     AddDimension(pNew);
    1021           0 :     return *pNew;
    1022             : }
    1023             : 
    1024           0 : ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(sal_uInt16 nOrientation)
    1025             : {
    1026             :     // return the innermost dimension for the given orientation,
    1027             :     // excluding data layout dimension
    1028             : 
    1029           0 :     boost::ptr_vector<ScDPSaveDimension>::const_reverse_iterator iter;
    1030           0 :     for (iter = aDimList.rbegin(); iter != aDimList.rend(); ++iter)
    1031             :     {
    1032           0 :         if (iter->GetOrientation() == nOrientation && !iter->IsDataLayout())
    1033           0 :             return const_cast<ScDPSaveDimension*>(&(*iter));
    1034             :     }
    1035             : 
    1036           0 :     return NULL;
    1037             : }
    1038             : 
    1039           0 : ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)
    1040             : {
    1041           0 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
    1042           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
    1043             :     {
    1044           0 :         if (iter->GetOrientation() == eOrientation && !iter->IsDataLayout())
    1045           0 :             return const_cast<ScDPSaveDimension*>(&(*iter));
    1046             :     }
    1047           0 :     return NULL;
    1048             : }
    1049             : 
    1050           0 : long ScDPSaveData::GetDataDimensionCount() const
    1051             : {
    1052           0 :     long nDataCount = 0;
    1053             : 
    1054           0 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
    1055           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
    1056             :     {
    1057           0 :         if (iter->GetOrientation() == sheet::DataPilotFieldOrientation_DATA)
    1058           0 :             ++nDataCount;
    1059             :     }
    1060             : 
    1061           0 :     return nDataCount;
    1062             : }
    1063             : 
    1064           0 : void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
    1065             : {
    1066             :     // position (nNew) is counted within dimensions of the same orientation
    1067             : 
    1068           0 :     sal_uInt16 nOrient = pDim->GetOrientation();
    1069             : 
    1070           0 :     boost::ptr_vector<ScDPSaveDimension>::iterator it;
    1071           0 :     for ( it = aDimList.begin(); it != aDimList.end(); ++it)
    1072             :     {
    1073           0 :         if (pDim == &(*it))
    1074             :         {
    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           0 :             aDimList.release(it).release();
    1079           0 :             break;
    1080             :         }
    1081             :     }
    1082             : 
    1083           0 :     boost::ptr_vector<ScDPSaveDimension>::iterator iterInsert = aDimList.begin();
    1084           0 :     while ( nNew > 0 && iterInsert != aDimList.end())
    1085             :     {
    1086           0 :         if (iterInsert->GetOrientation() == nOrient )
    1087           0 :             --nNew;
    1088             : 
    1089           0 :         ++iterInsert;
    1090             :     }
    1091             : 
    1092           0 :     aDimList.insert(iterInsert,pDim);
    1093           0 :     DimensionsChanged();
    1094           0 : }
    1095             : 
    1096           0 : void ScDPSaveData::SetColumnGrand(bool bSet)
    1097             : {
    1098           0 :     nColumnGrandMode = sal_uInt16(bSet);
    1099           0 : }
    1100             : 
    1101           0 : void ScDPSaveData::SetRowGrand(bool bSet)
    1102             : {
    1103           0 :     nRowGrandMode = sal_uInt16(bSet);
    1104           0 : }
    1105             : 
    1106           0 : void ScDPSaveData::SetIgnoreEmptyRows(bool bSet)
    1107             : {
    1108           0 :     nIgnoreEmptyMode = sal_uInt16(bSet);
    1109           0 : }
    1110             : 
    1111           0 : void ScDPSaveData::SetRepeatIfEmpty(bool bSet)
    1112             : {
    1113           0 :     nRepeatEmptyMode = sal_uInt16(bSet);
    1114           0 : }
    1115             : 
    1116           0 : void ScDPSaveData::SetFilterButton(bool bSet)
    1117             : {
    1118           0 :     bFilterButton = bSet;
    1119           0 : }
    1120             : 
    1121           0 : void ScDPSaveData::SetDrillDown(bool bSet)
    1122             : {
    1123           0 :     bDrillDown = bSet;
    1124           0 : }
    1125             : 
    1126           0 : static void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
    1127             : {
    1128           0 :     sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN;
    1129             : 
    1130           0 :     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    1131           0 :     uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
    1132           0 :     long nIntCount = xIntDims->getCount();
    1133           0 :     for (long nIntDim=0; nIntDim<nIntCount; nIntDim++)
    1134             :     {
    1135           0 :         uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
    1136           0 :         uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
    1137           0 :         if (xDimProp.is())
    1138             :         {
    1139           0 :             uno::Any aAny;
    1140           0 :             aAny <<= eOrient;
    1141           0 :             xDimProp->setPropertyValue( OUString(SC_UNO_DP_ORIENTATION), aAny );
    1142             :         }
    1143           0 :     }
    1144           0 : }
    1145             : 
    1146           0 : void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
    1147             : {
    1148           0 :     if (!xSource.is())
    1149           0 :         return;
    1150             : 
    1151             :     // source options must be first!
    1152             : 
    1153           0 :     uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
    1154             :     OSL_ENSURE( xSourceProp.is(), "no properties at source" );
    1155           0 :     if ( xSourceProp.is() )
    1156             :     {
    1157             :         // source options are not available for external sources
    1158             :         //! use XPropertySetInfo to test for availability?
    1159             : 
    1160             :         try
    1161             :         {
    1162           0 :             if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW )
    1163             :                 lcl_SetBoolProperty( xSourceProp,
    1164           0 :                     OUString(SC_UNO_DP_IGNOREEMPTY), (bool)nIgnoreEmptyMode );
    1165           0 :             if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
    1166             :                 lcl_SetBoolProperty( xSourceProp,
    1167           0 :                     OUString(SC_UNO_DP_REPEATEMPTY), (bool)nRepeatEmptyMode );
    1168             :         }
    1169           0 :         catch(uno::Exception&)
    1170             :         {
    1171             :             // no error
    1172             :         }
    1173             : 
    1174           0 :         const OUString* pGrandTotalName = GetGrandTotalName();
    1175           0 :         if (pGrandTotalName)
    1176           0 :             ScUnoHelpFunctions::SetOptionalPropertyValue(xSourceProp, SC_UNO_DP_GRANDTOTAL_NAME, *pGrandTotalName);
    1177             :     }
    1178             : 
    1179             :     // exceptions in the other calls are errors
    1180             :     try
    1181             :     {
    1182             :         // reset all orientations
    1183             :         //! "forgetSettings" or similar at source ?????
    1184             :         //! reset all duplicated dimensions, or reuse them below !!!
    1185             :         OSL_FAIL( "ScDPSaveData::WriteToSource" );
    1186             : 
    1187           0 :         lcl_ResetOrient( xSource );
    1188             : 
    1189           0 :         uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    1190           0 :         uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
    1191           0 :         long nIntCount = xIntDims->getCount();
    1192             : 
    1193           0 :         boost::ptr_vector<ScDPSaveDimension>::iterator iter = aDimList.begin();
    1194           0 :         for (long i = 0; iter != aDimList.end(); ++iter, ++i)
    1195             :         {
    1196           0 :             OUString aName = iter->GetName();
    1197           0 :             OUString aCoreName = ScDPUtil::getSourceDimensionName(aName);
    1198             : 
    1199             :             OSL_TRACE( "%s", aName.getStr() );
    1200             : 
    1201           0 :             bool bData = iter->IsDataLayout();
    1202             : 
    1203             :             //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
    1204             : 
    1205           0 :             bool bFound = false;
    1206           0 :             for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
    1207             :             {
    1208           0 :                 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
    1209           0 :                 if ( bData )
    1210             :                 {
    1211           0 :                     uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
    1212           0 :                     if ( xDimProp.is() )
    1213             :                     {
    1214             :                         bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
    1215           0 :                                     OUString(SC_UNO_DP_ISDATALAYOUT) );
    1216             :                         //! error checking -- is "IsDataLayoutDimension" property required??
    1217           0 :                     }
    1218             :                 }
    1219             :                 else
    1220             :                 {
    1221           0 :                     uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
    1222           0 :                     if (xDimName.is() && xDimName->getName() == aCoreName)
    1223           0 :                         bFound = true;
    1224             :                 }
    1225             : 
    1226           0 :                 if (bFound)
    1227             :                 {
    1228           0 :                     if (iter->GetDupFlag())
    1229             :                     {
    1230           0 :                         uno::Reference<util::XCloneable> xCloneable(xIntDim, uno::UNO_QUERY);
    1231             :                         OSL_ENSURE(xCloneable.is(), "cannot clone dimension");
    1232           0 :                         if (xCloneable.is())
    1233             :                         {
    1234           0 :                             uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
    1235           0 :                             uno::Reference<container::XNamed> xNewName(xNew, uno::UNO_QUERY);
    1236           0 :                             if (xNewName.is())
    1237             :                             {
    1238           0 :                                 xNewName->setName(aName);
    1239           0 :                                 iter->WriteToSource(xNew);
    1240           0 :                             }
    1241           0 :                         }
    1242             :                     }
    1243             :                     else
    1244           0 :                         iter->WriteToSource( xIntDim );
    1245             :                 }
    1246           0 :             }
    1247             :             OSL_ENSURE(bFound, "WriteToSource: Dimension not found");
    1248           0 :         }
    1249             : 
    1250           0 :         if ( xSourceProp.is() )
    1251             :         {
    1252           0 :             if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW )
    1253             :                 lcl_SetBoolProperty( xSourceProp,
    1254           0 :                     OUString(SC_UNO_DP_COLGRAND), (bool)nColumnGrandMode );
    1255           0 :             if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW )
    1256             :                 lcl_SetBoolProperty( xSourceProp,
    1257           0 :                     OUString(SC_UNO_DP_ROWGRAND), (bool)nRowGrandMode );
    1258           0 :         }
    1259             :     }
    1260           0 :     catch(uno::Exception&)
    1261             :     {
    1262             :         OSL_FAIL("exception in WriteToSource");
    1263           0 :     }
    1264             : }
    1265             : 
    1266           0 : bool ScDPSaveData::IsEmpty() const
    1267             : {
    1268           0 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
    1269           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
    1270             :     {
    1271           0 :         if (iter->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !iter->IsDataLayout())
    1272           0 :             return false;
    1273             :     }
    1274           0 :     return true; // no entries that are not hidden
    1275             : }
    1276             : 
    1277           0 : void ScDPSaveData::RemoveAllGroupDimensions( const OUString& rSrcDimName, std::vector<OUString>* pDeletedNames )
    1278             : {
    1279           0 :     if (!pDimensionData)
    1280             :         // No group dimensions exist.  Nothing to do.
    1281           0 :         return;
    1282             : 
    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           0 :     pDimensionData->RemoveNumGroupDimension(rSrcDimName);
    1287             : 
    1288             :     // Remove named group dimension(s). Dimensions have to be removed from
    1289             :     // dimension save data and from save data too.
    1290           0 :     const ScDPSaveGroupDimension* pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
    1291           0 :     while ( pExistingGroup )
    1292             :     {
    1293           0 :         OUString aGroupDimName = pExistingGroup->GetGroupDimName();
    1294           0 :         pDimensionData->RemoveGroupDimension(aGroupDimName);     // pExistingGroup is deleted
    1295             : 
    1296             :         // also remove SaveData settings for the dimension that no longer exists
    1297           0 :         RemoveDimensionByName(aGroupDimName);
    1298             : 
    1299           0 :         if (pDeletedNames)
    1300           0 :             pDeletedNames->push_back(aGroupDimName);
    1301             : 
    1302             :         // see if there are more group dimensions
    1303           0 :         pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
    1304             : 
    1305           0 :         if ( pExistingGroup && pExistingGroup->GetGroupDimName() == aGroupDimName )
    1306             :         {
    1307             :             // still get the same group dimension?
    1308             :             OSL_FAIL("couldn't remove group dimension");
    1309           0 :             pExistingGroup = NULL;      // avoid endless loop
    1310             :         }
    1311           0 :     }
    1312             : }
    1313             : 
    1314           0 : ScDPDimensionSaveData* ScDPSaveData::GetDimensionData()
    1315             : {
    1316           0 :     if (!pDimensionData)
    1317           0 :         pDimensionData = new ScDPDimensionSaveData;
    1318           0 :     return pDimensionData;
    1319             : }
    1320             : 
    1321           0 : void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew )
    1322             : {
    1323           0 :     delete pDimensionData;
    1324           0 :     if ( pNew )
    1325           0 :         pDimensionData = new ScDPDimensionSaveData( *pNew );
    1326             :     else
    1327           0 :         pDimensionData = NULL;
    1328           0 : }
    1329             : 
    1330           0 : void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
    1331             : {
    1332           0 :     if (mbDimensionMembersBuilt)
    1333           0 :         return;
    1334             : 
    1335             :     // First, build a dimension name-to-index map.
    1336             :     typedef boost::unordered_map<OUString, long, OUStringHash> NameIndexMap;
    1337           0 :     NameIndexMap aMap;
    1338           0 :     long nColCount = pData->GetColumnCount();
    1339           0 :     for (long i = 0; i < nColCount; ++i)
    1340           0 :         aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i));
    1341             : 
    1342           0 :     NameIndexMap::const_iterator itrEnd = aMap.end();
    1343             : 
    1344           0 :     boost::ptr_vector<ScDPSaveDimension>::iterator iter;
    1345           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
    1346             :     {
    1347           0 :         const OUString& rDimName = iter->GetName();
    1348           0 :         if (rDimName.isEmpty())
    1349             :             // empty dimension name. It must be data layout.
    1350           0 :             continue;
    1351             : 
    1352           0 :         NameIndexMap::const_iterator itr = aMap.find(rDimName);
    1353           0 :         if (itr == itrEnd)
    1354             :             // dimension name not in the data. This should never happen!
    1355           0 :             continue;
    1356             : 
    1357           0 :         long nDimIndex = itr->second;
    1358           0 :         const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
    1359           0 :         size_t mMemberCount = rMembers.size();
    1360           0 :         for (size_t j = 0; j < mMemberCount; ++j)
    1361             :         {
    1362           0 :             const ScDPItemData* pMemberData = pData->GetMemberById( nDimIndex, rMembers[j] );
    1363           0 :             OUString aMemName = pData->GetFormattedString(nDimIndex, *pMemberData);
    1364           0 :             if (iter->GetExistingMemberByName(aMemName))
    1365             :                 // this member instance already exists. nothing to do.
    1366           0 :                 continue;
    1367             : 
    1368           0 :             auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName));
    1369           0 :             pNewMember->SetIsVisible(true);
    1370           0 :             iter->AddMember(pNewMember.release());
    1371           0 :         }
    1372             :     }
    1373             : 
    1374           0 :     mbDimensionMembersBuilt = true;
    1375             : }
    1376             : 
    1377           0 : void ScDPSaveData::SyncAllDimensionMembers(ScDPTableData* pData)
    1378             : {
    1379             :     typedef boost::unordered_map<OUString, long, OUStringHash> NameIndexMap;
    1380             : 
    1381             :     // First, build a dimension name-to-index map.
    1382           0 :     NameIndexMap aMap;
    1383           0 :     long nColCount = pData->GetColumnCount();
    1384           0 :     for (long i = 0; i < nColCount; ++i)
    1385           0 :         aMap.insert(NameIndexMap::value_type(pData->getDimensionName(i), i));
    1386             : 
    1387           0 :     NameIndexMap::const_iterator itMapEnd = aMap.end();
    1388             : 
    1389           0 :     DimsType::iterator it = aDimList.begin(), itEnd = aDimList.end();
    1390           0 :     for (it = aDimList.begin(); it != itEnd; ++it)
    1391             :     {
    1392           0 :         const OUString& rDimName = it->GetName();
    1393           0 :         if (rDimName.isEmpty())
    1394             :             // empty dimension name. It must be data layout.
    1395           0 :             continue;
    1396             : 
    1397           0 :         NameIndexMap::const_iterator itMap = aMap.find(rDimName);
    1398           0 :         if (itMap == itMapEnd)
    1399             :             // dimension name not in the data. This should never happen!
    1400           0 :             continue;
    1401             : 
    1402           0 :         ScDPSaveDimension::MemberSetType aMemNames;
    1403           0 :         long nDimIndex = itMap->second;
    1404           0 :         const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
    1405           0 :         size_t nMemberCount = rMembers.size();
    1406           0 :         for (size_t j = 0; j < nMemberCount; ++j)
    1407             :         {
    1408           0 :             const ScDPItemData* pMemberData = pData->GetMemberById(nDimIndex, rMembers[j]);
    1409           0 :             OUString aMemName = pData->GetFormattedString(nDimIndex, *pMemberData);
    1410           0 :             aMemNames.insert(aMemName);
    1411           0 :         }
    1412             : 
    1413           0 :         it->RemoveObsoleteMembers(aMemNames);
    1414           0 :     }
    1415           0 : }
    1416             : 
    1417           0 : bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const
    1418             : {
    1419           0 :     ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName);
    1420           0 :     if (!pDim)
    1421           0 :         return false;
    1422             : 
    1423           0 :     return pDim->HasInvisibleMember();
    1424             : }
    1425             : 
    1426             : #if DEBUG_PIVOT_TABLE
    1427             : 
    1428             : void ScDPSaveData::Dump() const
    1429             : {
    1430             :     DimsType::const_iterator itDim = aDimList.begin(), itDimEnd = aDimList.end();
    1431             :     for (; itDim != itDimEnd; ++itDim)
    1432             :     {
    1433             :         const ScDPSaveDimension& rDim = *itDim;
    1434             :         rDim.Dump();
    1435             :     }
    1436             : }
    1437             : 
    1438             : #endif
    1439             : 
    1440           0 : void ScDPSaveData::CheckDuplicateName(ScDPSaveDimension& rDim)
    1441             : {
    1442           0 :     const OUString aName = ScDPUtil::getSourceDimensionName(rDim.GetName());
    1443           0 :     DupNameCountType::iterator it = maDupNameCounts.find(aName);
    1444           0 :     if (it != maDupNameCounts.end())
    1445             :     {
    1446           0 :         rDim.SetName(ScDPUtil::createDuplicateDimensionName(aName, ++it->second));
    1447           0 :         rDim.SetDupFlag(true);
    1448             :     }
    1449             :     else
    1450             :         // New name.
    1451           0 :         maDupNameCounts.insert(DupNameCountType::value_type(aName, 0));
    1452           0 : }
    1453             : 
    1454           0 : void ScDPSaveData::RemoveDuplicateNameCount(const OUString& rName)
    1455             : {
    1456           0 :     OUString aCoreName = rName;
    1457           0 :     if (ScDPUtil::isDuplicateDimension(rName))
    1458           0 :         aCoreName = ScDPUtil::getSourceDimensionName(rName);
    1459             : 
    1460           0 :     DupNameCountType::iterator it = maDupNameCounts.find(aCoreName);
    1461           0 :     if (it == maDupNameCounts.end())
    1462           0 :         return;
    1463             : 
    1464           0 :     if (!it->second)
    1465             :     {
    1466           0 :         maDupNameCounts.erase(it);
    1467           0 :         return;
    1468             :     }
    1469             : 
    1470           0 :     --it->second;
    1471           0 :     return;
    1472             : }
    1473             : 
    1474           0 : ScDPSaveDimension* ScDPSaveData::AppendNewDimension(const OUString& rName, bool bDataLayout)
    1475             : {
    1476           0 :     if (ScDPUtil::isDuplicateDimension(rName))
    1477             :         // This call is for original dimensions only.
    1478           0 :         return NULL;
    1479             : 
    1480           0 :     ScDPSaveDimension* pNew = new ScDPSaveDimension(rName, bDataLayout);
    1481           0 :     aDimList.push_back(pNew);
    1482           0 :     if (!maDupNameCounts.count(rName))
    1483           0 :         maDupNameCounts.insert(DupNameCountType::value_type(rName, 0));
    1484             : 
    1485           0 :     DimensionsChanged();
    1486           0 :     return pNew;
    1487             : }
    1488             : 
    1489           0 : void ScDPSaveData::DimensionsChanged()
    1490             : {
    1491           0 :     mpDimOrder.reset();
    1492           0 : }
    1493             : 
    1494           0 : bool operator == (const ::com::sun::star::sheet::DataPilotFieldSortInfo &l, const ::com::sun::star::sheet::DataPilotFieldSortInfo &r )
    1495             : {
    1496           0 :     return l.Field == r.Field && l.IsAscending == r.IsAscending && l.Mode == r.Mode;
    1497             : }
    1498           0 : bool operator == (const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &l, const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &r )
    1499             : {
    1500           0 :     return l.IsEnabled == r.IsEnabled &&
    1501           0 :         l.ShowItemsMode == r.ShowItemsMode &&
    1502           0 :         l.ItemCount == r.ItemCount &&
    1503           0 :         l.DataField == r.DataField;
    1504             : }
    1505           0 : bool operator == (const ::com::sun::star::sheet::DataPilotFieldReference &l, const ::com::sun::star::sheet::DataPilotFieldReference &r )
    1506             : {
    1507           0 :     return l.ReferenceType == r.ReferenceType &&
    1508           0 :         l.ReferenceField == r.ReferenceField &&
    1509           0 :         l.ReferenceItemType == r.ReferenceItemType &&
    1510           0 :         l.ReferenceItemName == r.ReferenceItemName;
    1511           0 : }
    1512             : 
    1513             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10