LCOV - code coverage report
Current view: top level - sc/source/core/data - dpsave.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 558 749 74.5 %
Date: 2014-11-03 Functions: 69 93 74.2 %
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::unique_ptr;
      57             : 
      58             : #define SC_DPSAVEMODE_DONTKNOW 2
      59             : 
      60        2278 : static void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp,
      61             :                             const OUString& rName, bool bValue )
      62             : {
      63             :     //! move to ScUnoHelpFunctions?
      64             : 
      65        2278 :     xProp->setPropertyValue( rName, uno::Any( &bValue, getBooleanCppuType() ) );
      66        2278 : }
      67             : 
      68        7464 : ScDPSaveMember::ScDPSaveMember(const OUString& rName) :
      69             :     aName( rName ),
      70             :     mpLayoutName(NULL),
      71             :     nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
      72        7464 :     nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
      73             : {
      74        7464 : }
      75             : 
      76        7072 : ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
      77             :     aName( r.aName ),
      78             :     mpLayoutName(NULL),
      79             :     nVisibleMode( r.nVisibleMode ),
      80        7072 :     nShowDetailsMode( r.nShowDetailsMode )
      81             : {
      82        7072 :     if (r.mpLayoutName)
      83           0 :         mpLayoutName.reset(new OUString(*r.mpLayoutName));
      84        7072 : }
      85             : 
      86       14536 : ScDPSaveMember::~ScDPSaveMember()
      87             : {
      88       14536 : }
      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          14 : bool ScDPSaveMember::HasIsVisible() const
     101             : {
     102          14 :     return nVisibleMode != SC_DPSAVEMODE_DONTKNOW;
     103             : }
     104             : 
     105        7540 : void ScDPSaveMember::SetIsVisible(bool bSet)
     106             : {
     107        7540 :     nVisibleMode = sal_uInt16(bSet);
     108        7540 : }
     109             : 
     110          12 : bool ScDPSaveMember::HasShowDetails() const
     111             : {
     112          12 :     return nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW;
     113             : }
     114             : 
     115        5882 : void ScDPSaveMember::SetShowDetails(bool bSet)
     116             : {
     117        5882 :     nShowDetailsMode = sal_uInt16(bSet);
     118        5882 : }
     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         552 : void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
     144             : {
     145         552 :     uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
     146             :     OSL_ENSURE( xMembProp.is(), "no properties at member" );
     147         552 :     if ( xMembProp.is() )
     148             :     {
     149             :         // exceptions are caught at ScDPSaveData::WriteToSource
     150             : 
     151         552 :         if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW )
     152             :             lcl_SetBoolProperty( xMembProp,
     153         552 :                     OUString(SC_UNO_DP_ISVISIBLE), (bool)nVisibleMode );
     154             : 
     155         552 :         if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW )
     156             :             lcl_SetBoolProperty( xMembProp,
     157         470 :                     OUString(SC_UNO_DP_SHOWDETAILS), (bool)nShowDetailsMode );
     158             : 
     159         552 :         if (mpLayoutName)
     160           0 :             ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_DP_LAYOUTNAME, *mpLayoutName);
     161             : 
     162         552 :         if ( nPosition >= 0 )
     163         154 :             ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_DP_POSITION, nPosition);
     164         552 :     }
     165         552 : }
     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         386 : 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         386 :     pLayoutInfo( NULL )
     208             : {
     209         386 : }
     210             : 
     211        1136 : 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        1136 :     pSubTotalFuncs( NULL )
     224             : {
     225        1136 :     if ( nSubTotalCount && r.pSubTotalFuncs )
     226             :     {
     227         272 :         pSubTotalFuncs = new sal_uInt16[nSubTotalCount];
     228         544 :         for (long nSub=0; nSub<nSubTotalCount; nSub++)
     229         272 :             pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub];
     230             :     }
     231             : 
     232        8208 :     for (MemberList::const_iterator i=r.maMemberList.begin(); i != r.maMemberList.end() ; ++i)
     233             :     {
     234        7072 :         const OUString& rName =  (*i)->GetName();
     235        7072 :         ScDPSaveMember* pNew = new ScDPSaveMember( **i );
     236        7072 :         maMemberHash[rName] = pNew;
     237        7072 :         maMemberList.push_back( pNew );
     238             :     }
     239        1136 :     if (r.pReferenceValue)
     240          18 :         pReferenceValue = new sheet::DataPilotFieldReference( *(r.pReferenceValue) );
     241             :     else
     242        1118 :         pReferenceValue = NULL;
     243        1136 :     if (r.pSortInfo)
     244         376 :         pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) );
     245             :     else
     246         760 :         pSortInfo = NULL;
     247        1136 :     if (r.pAutoShowInfo)
     248         344 :         pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) );
     249             :     else
     250         792 :         pAutoShowInfo = NULL;
     251        1136 :     if (r.pLayoutInfo)
     252         388 :         pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
     253             :     else
     254         748 :         pLayoutInfo = NULL;
     255        1136 :     if (r.mpLayoutName)
     256           4 :         mpLayoutName.reset(new OUString(*r.mpLayoutName));
     257        1136 :     if (r.mpSubtotalName)
     258           0 :         mpSubtotalName.reset(new OUString(*r.mpSubtotalName));
     259        1136 : }
     260             : 
     261        3032 : ScDPSaveDimension::~ScDPSaveDimension()
     262             : {
     263       16052 :     for (MemberHash::const_iterator i=maMemberHash.begin(); i != maMemberHash.end() ; ++i)
     264       14536 :         delete i->second;
     265        1516 :     delete pReferenceValue;
     266        1516 :     delete pSortInfo;
     267        1516 :     delete pAutoShowInfo;
     268        1516 :     delete pLayoutInfo;
     269        1516 :     delete [] pSubTotalFuncs;
     270        1516 : }
     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        7416 : void ScDPSaveDimension::AddMember(ScDPSaveMember* pMember)
     340             : {
     341        7416 :     const OUString & rName = pMember->GetName();
     342        7416 :     MemberHash::iterator aExisting = maMemberHash.find( rName );
     343        7416 :     if ( aExisting == maMemberHash.end() )
     344             :     {
     345        7416 :         std::pair< const OUString, ScDPSaveMember *> key( rName, pMember );
     346        7416 :         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        7416 :     maMemberList.push_back( pMember );
     355        7416 : }
     356             : 
     357           8 : 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           8 :     aName = rNew;
     363           8 : }
     364             : 
     365         386 : void ScDPSaveDimension::SetOrientation(sal_uInt16 nNew)
     366             : {
     367         386 :     nOrientation = nNew;
     368         386 : }
     369             : 
     370          90 : void ScDPSaveDimension::SetSubTotals(long nCount, const sal_uInt16* pFuncs)
     371             : {
     372          90 :     if (pSubTotalFuncs)
     373           6 :         delete [] pSubTotalFuncs;
     374          90 :     nSubTotalCount = nCount;
     375          90 :     if ( nCount && pFuncs )
     376             :     {
     377          88 :         pSubTotalFuncs = new sal_uInt16[nCount];
     378         176 :         for (long i=0; i<nCount; i++)
     379         176 :             pSubTotalFuncs[i] = pFuncs[i];
     380             :     }
     381             :     else
     382           2 :         pSubTotalFuncs = NULL;
     383             : 
     384          90 :     bSubTotalDefault = false;
     385          90 : }
     386             : 
     387           0 : bool ScDPSaveDimension::HasShowEmpty() const
     388             : {
     389           0 :     return nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW;
     390             : }
     391             : 
     392         163 : void ScDPSaveDimension::SetShowEmpty(bool bSet)
     393             : {
     394         163 :     nShowEmptyMode = sal_uInt16(bSet);
     395         163 : }
     396             : 
     397         136 : void ScDPSaveDimension::SetFunction(sal_uInt16 nNew)
     398             : {
     399         136 :     nFunction = nNew;
     400         136 : }
     401             : 
     402         174 : void ScDPSaveDimension::SetUsedHierarchy(long nNew)
     403             : {
     404         174 :     nUsedHierarchy = nNew;
     405         174 : }
     406             : 
     407           0 : void ScDPSaveDimension::SetSubtotalName(const OUString& rName)
     408             : {
     409           0 :     mpSubtotalName.reset(new OUString(rName));
     410           0 : }
     411             : 
     412         648 : const OUString* ScDPSaveDimension::GetSubtotalName() const
     413             : {
     414         648 :     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          12 : void ScDPSaveDimension::SetLayoutName(const OUString& rName)
     439             : {
     440          12 :     mpLayoutName.reset(new OUString(rName));
     441          12 : }
     442             : 
     443         232 : const OUString* ScDPSaveDimension::GetLayoutName() const
     444             : {
     445         232 :     return mpLayoutName.get();
     446             : }
     447             : 
     448           0 : void ScDPSaveDimension::RemoveLayoutName()
     449             : {
     450           0 :     mpLayoutName.reset();
     451           0 : }
     452             : 
     453          60 : void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
     454             : {
     455          60 :     delete pReferenceValue;
     456          60 :     if (pNew)
     457          14 :         pReferenceValue = new sheet::DataPilotFieldReference(*pNew);
     458             :     else
     459          46 :         pReferenceValue = NULL;
     460          60 : }
     461             : 
     462         164 : void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew)
     463             : {
     464         164 :     delete pSortInfo;
     465         164 :     if (pNew)
     466         162 :         pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew);
     467             :     else
     468           2 :         pSortInfo = NULL;
     469         164 : }
     470             : 
     471         116 : void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew)
     472             : {
     473         116 :     delete pAutoShowInfo;
     474         116 :     if (pNew)
     475         114 :         pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew);
     476             :     else
     477           2 :         pAutoShowInfo = NULL;
     478         116 : }
     479             : 
     480         164 : void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew)
     481             : {
     482         164 :     delete pLayoutInfo;
     483         164 :     if (pNew)
     484         162 :         pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew);
     485             :     else
     486           2 :         pLayoutInfo = NULL;
     487         164 : }
     488             : 
     489          18 : 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          18 :     MemberList::iterator it = maMemberList.begin(), itEnd = maMemberList.end();
     495          90 :     for (; it != itEnd; ++it)
     496             :     {
     497          72 :         ScDPSaveMember* pMem = *it;
     498          72 :         bool bVisible = !pPage || pMem->GetName() == *pPage;
     499          72 :         pMem->SetIsVisible(bVisible);
     500             :     }
     501          18 : }
     502             : 
     503        1806 : ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const OUString& rName)
     504             : {
     505        1806 :     MemberHash::const_iterator res = maMemberHash.find (rName);
     506        1806 :     if (res != maMemberHash.end())
     507         220 :         return res->second;
     508        1586 :     return NULL;
     509             : }
     510             : 
     511          60 : ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const OUString& rName)
     512             : {
     513          60 :     MemberHash::const_iterator res = maMemberHash.find (rName);
     514          60 :     if (res != maMemberHash.end())
     515          12 :         return res->second;
     516             : 
     517          48 :     ScDPSaveMember* pNew = new ScDPSaveMember( rName );
     518          48 :     maMemberHash[rName] = pNew;
     519          48 :     maMemberList.push_back( pNew );
     520          48 :     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         648 : void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim )
     536             : {
     537         648 :     uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
     538             :     OSL_ENSURE( xDimProp.is(), "no properties at dimension" );
     539         648 :     if ( xDimProp.is() )
     540             :     {
     541             :         // exceptions are caught at ScDPSaveData::WriteToSource
     542         648 :         uno::Any aAny;
     543             : 
     544         648 :         sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
     545         648 :         aAny <<= eOrient;
     546         648 :         xDimProp->setPropertyValue( OUString(SC_UNO_DP_ORIENTATION), aAny );
     547             : 
     548         648 :         sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
     549         648 :         aAny <<= eFunc;
     550         648 :         xDimProp->setPropertyValue( OUString(SC_UNO_DP_FUNCTION), aAny );
     551             : 
     552         648 :         if ( nUsedHierarchy >= 0 )
     553             :         {
     554         272 :             aAny <<= (sal_Int32)nUsedHierarchy;
     555         272 :             xDimProp->setPropertyValue( OUString(SC_UNO_DP_USEDHIERARCHY), aAny );
     556             :         }
     557             : 
     558         648 :         if ( pReferenceValue )
     559             :         {
     560          14 :             aAny <<= *pReferenceValue;
     561          14 :             xDimProp->setPropertyValue( OUString(SC_UNO_DP_REFVALUE), aAny );
     562             :         }
     563             : 
     564         648 :         if (mpLayoutName)
     565           4 :             ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_LAYOUTNAME, *mpLayoutName);
     566             : 
     567         648 :         const OUString* pSubTotalName = GetSubtotalName();
     568         648 :         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         648 :     long nCount = maMemberHash.size();
     577             : 
     578         648 :     long nHierCount = 0;
     579        1296 :     uno::Reference<container::XIndexAccess> xHiers;
     580        1296 :     uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
     581         648 :     if ( xHierSupp.is() )
     582             :     {
     583         648 :         uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
     584         648 :         xHiers = new ScNameToIndexAccess( xHiersName );
     585         648 :         nHierCount = xHiers->getCount();
     586             :     }
     587             : 
     588         648 :     bool bHasHiddenMember = false;
     589             : 
     590        1296 :     for (long nHier=0; nHier<nHierCount; nHier++)
     591             :     {
     592         648 :         uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
     593             : 
     594         648 :         long nLevCount = 0;
     595        1296 :         uno::Reference<container::XIndexAccess> xLevels;
     596        1296 :         uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
     597         648 :         if ( xLevSupp.is() )
     598             :         {
     599         648 :             uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
     600         648 :             xLevels = new ScNameToIndexAccess( xLevelsName );
     601         648 :             nLevCount = xLevels->getCount();
     602             :         }
     603             : 
     604        1296 :         for (long nLev=0; nLev<nLevCount; nLev++)
     605             :         {
     606         648 :             uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) );
     607        1296 :             uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
     608             :             OSL_ENSURE( xLevProp.is(), "no properties at level" );
     609         648 :             if ( xLevProp.is() )
     610             :             {
     611         648 :                 uno::Any aAny;
     612         648 :                 if ( !bSubTotalDefault )
     613             :                 {
     614         138 :                     if ( !pSubTotalFuncs )
     615           0 :                         nSubTotalCount = 0;
     616             : 
     617         138 :                     uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount);
     618         138 :                     sheet::GeneralFunction* pArray = aSeq.getArray();
     619         276 :                     for (long i=0; i<nSubTotalCount; i++)
     620         138 :                         pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i];
     621         138 :                     aAny <<= aSeq;
     622         138 :                     xLevProp->setPropertyValue( OUString(SC_UNO_DP_SUBTOTAL), aAny );
     623             :                 }
     624         648 :                 if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW )
     625             :                     lcl_SetBoolProperty( xLevProp,
     626         236 :                         OUString(SC_UNO_DP_SHOWEMPTY), (bool)nShowEmptyMode );
     627             : 
     628         648 :                 if ( pSortInfo )
     629         226 :                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_SORTING, *pSortInfo);
     630             : 
     631         648 :                 if ( pAutoShowInfo )
     632         182 :                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_AUTOSHOW, *pAutoShowInfo);
     633             : 
     634         648 :                 if ( pLayoutInfo )
     635         230 :                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_LAYOUT, *pLayoutInfo);
     636             : 
     637             :                 // exceptions are caught at ScDPSaveData::WriteToSource
     638             :             }
     639             : 
     640         648 :             if ( nCount > 0 )
     641             :             {
     642         134 :                 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
     643         134 :                 if ( xMembSupp.is() )
     644             :                 {
     645         134 :                     uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
     646         134 :                     if ( xMembers.is() )
     647             :                     {
     648         134 :                         sal_Int32 nPosition = -1; // set position only in manual mode
     649         134 :                         if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL )
     650          48 :                             nPosition = 0;
     651             : 
     652         708 :                         for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; ++i)
     653             :                         {
     654         574 :                             ScDPSaveMember* pMember = *i;
     655         574 :                             if (!pMember->GetIsVisible())
     656          18 :                                 bHasHiddenMember = true;
     657         574 :                             OUString aMemberName = pMember->GetName();
     658         574 :                             if ( xMembers->hasByName( aMemberName ) )
     659             :                             {
     660             :                                 uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
     661         552 :                                     xMembers->getByName( aMemberName ) );
     662         552 :                                 pMember->WriteToSource( xMemberInt, nPosition );
     663             : 
     664         552 :                                 if ( nPosition >= 0 )
     665         154 :                                     ++nPosition; // increase if initialized
     666             :                             }
     667             :                             // missing member is no error
     668         574 :                         }
     669         134 :                     }
     670         134 :                 }
     671             :             }
     672         648 :         }
     673         648 :     }
     674             : 
     675         648 :     if (xDimProp.is())
     676        1296 :         ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_HAS_HIDDEN_MEMBER, bHasHiddenMember);
     677         648 : }
     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          56 : bool ScDPSaveDimension::HasInvisibleMember() const
     694             : {
     695          56 :     MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
     696        5022 :     for (; itrMem != itrMemEnd; ++itrMem)
     697             :     {
     698        4970 :         const ScDPSaveMember* pMem = *itrMem;
     699        4970 :         if (!pMem->GetIsVisible())
     700           4 :             return true;
     701             :     }
     702          52 :     return false;
     703             : }
     704             : 
     705         330 : void ScDPSaveDimension::RemoveObsoleteMembers(const MemberSetType& rMembers)
     706             : {
     707         330 :     maMemberHash.clear();
     708         330 :     MemberList aNew;
     709         330 :     MemberList::iterator it = maMemberList.begin(), itEnd = maMemberList.end();
     710         720 :     for (; it != itEnd; ++it)
     711             :     {
     712         390 :         ScDPSaveMember* pMem = *it;
     713         390 :         if (rMembers.count(pMem->GetName()))
     714             :         {
     715             :             // This member still exists.
     716         390 :             maMemberHash.insert(MemberHash::value_type(pMem->GetName(), pMem));
     717         390 :             aNew.push_back(pMem);
     718             :         }
     719             :         else
     720             :         {
     721             :             // This member no longer exists.
     722           0 :             delete pMem;
     723             :         }
     724             :     }
     725             : 
     726         330 :     maMemberList.swap(aNew);
     727         330 : }
     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         172 : 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         172 :     mpGrandTotalName(NULL)
     784             : {
     785         172 : }
     786             : 
     787         424 : 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         424 :     mpDimOrder(NULL)
     797             : {
     798         424 :     if ( r.pDimensionData )
     799          20 :         pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
     800             :     else
     801         404 :         pDimensionData = NULL;
     802             : 
     803         424 :     aDimList = r.aDimList.clone();
     804             : 
     805         424 :     if (r.mpGrandTotalName)
     806           0 :         mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
     807         424 : }
     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        1072 : ScDPSaveData::~ScDPSaveData()
     854             : {
     855         536 :     delete pDimensionData;
     856         536 : }
     857             : 
     858           0 : void ScDPSaveData::SetGrandTotalName(const OUString& rName)
     859             : {
     860           0 :     mpGrandTotalName.reset(new OUString(rName));
     861           0 : }
     862             : 
     863         256 : const OUString* ScDPSaveData::GetGrandTotalName() const
     864             : {
     865         256 :     return mpGrandTotalName.get();
     866             : }
     867             : 
     868             : namespace {
     869             : 
     870             : class DimOrderInserter : std::unary_function<const ScDPSaveDimension*, void>
     871             : {
     872             :     ScDPSaveData::DimOrderType& mrNames;
     873             : public:
     874          16 :     DimOrderInserter(ScDPSaveData::DimOrderType& rNames) : mrNames(rNames) {}
     875             : 
     876          18 :     void operator() (const ScDPSaveDimension* pDim)
     877             :     {
     878          18 :         size_t nRank = mrNames.size();
     879             :         mrNames.insert(
     880          18 :             ScDPSaveData::DimOrderType::value_type(pDim->GetName(), nRank));
     881          18 :     }
     882             : };
     883             : 
     884             : }
     885             : 
     886          62 : const ScDPSaveData::DimOrderType& ScDPSaveData::GetDimensionSortOrder() const
     887             : {
     888          62 :     if (!mpDimOrder)
     889             :     {
     890           8 :         mpDimOrder.reset(new DimOrderType);
     891          16 :         std::vector<const ScDPSaveDimension*> aRowDims, aColDims;
     892           8 :         GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aRowDims);
     893           8 :         GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aColDims);
     894             : 
     895           8 :         std::for_each(aRowDims.begin(), aRowDims.end(), DimOrderInserter(*mpDimOrder));
     896          16 :         std::for_each(aColDims.begin(), aColDims.end(), DimOrderInserter(*mpDimOrder));
     897             :     }
     898          62 :     return *mpDimOrder;
     899             : }
     900             : 
     901         160 : void ScDPSaveData::GetAllDimensionsByOrientation(
     902             :     sheet::DataPilotFieldOrientation eOrientation, std::vector<const ScDPSaveDimension*>& rDims) const
     903             : {
     904         160 :     std::vector<const ScDPSaveDimension*> aDims;
     905         160 :     DimsType::const_iterator it = aDimList.begin(), itEnd = aDimList.end();
     906         978 :     for (; it != itEnd; ++it)
     907             :     {
     908         818 :         const ScDPSaveDimension& rDim = *it;
     909         818 :         if (rDim.GetOrientation() != static_cast<sal_uInt16>(eOrientation))
     910         606 :             continue;
     911             : 
     912         212 :         aDims.push_back(&rDim);
     913             :     }
     914             : 
     915         160 :     rDims.swap(aDims);
     916         160 : }
     917             : 
     918          84 : void ScDPSaveData::AddDimension(ScDPSaveDimension* pDim)
     919             : {
     920          84 :     if (!pDim)
     921          84 :         return;
     922             : 
     923          84 :     CheckDuplicateName(*pDim);
     924          84 :     aDimList.push_back(pDim);
     925             : 
     926          84 :     DimensionsChanged();
     927             : }
     928             : 
     929         860 : ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const OUString& rName)
     930             : {
     931         860 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
     932        2714 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
     933             :     {
     934        2552 :         if (iter->GetName() == rName && !iter->IsDataLayout() )
     935         698 :             return const_cast<ScDPSaveDimension*>(&(*iter));
     936             :     }
     937             : 
     938         162 :     return AppendNewDimension(rName, false);
     939             : }
     940             : 
     941         104 : ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const OUString& rName) const
     942             : {
     943         104 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
     944         372 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
     945             :     {
     946         306 :         if (iter->GetName() == rName && !iter->IsDataLayout() )
     947          38 :             return const_cast<ScDPSaveDimension*>(&(*iter));
     948             :     }
     949          66 :     return NULL; // don't create new
     950             : }
     951             : 
     952         104 : ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const OUString& rName)
     953             : {
     954         104 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
     955         194 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
     956             :     {
     957          94 :         if (iter->GetName() == rName && !iter->IsDataLayout() )
     958           4 :             return DuplicateDimension(rName);
     959             :     }
     960             : 
     961         100 :     return AppendNewDimension(rName, false);
     962             : }
     963             : 
     964          54 : ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
     965             : {
     966          54 :     ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
     967          54 :     if (pDim)
     968           6 :         return pDim;
     969             : 
     970          48 :     return AppendNewDimension(OUString(), true);
     971             : }
     972             : 
     973          56 : ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const
     974             : {
     975          56 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
     976         214 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
     977             :     {
     978         166 :         if ( iter->IsDataLayout() )
     979           8 :             return const_cast<ScDPSaveDimension*>(&(*iter));
     980             :     }
     981          48 :     return NULL;
     982             : }
     983             : 
     984           4 : ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const OUString& rName)
     985             : {
     986             :     // always insert new
     987             : 
     988           4 :     ScDPSaveDimension* pOld = GetExistingDimensionByName(rName);
     989           4 :     if (!pOld)
     990           0 :         return NULL;
     991             : 
     992           4 :     ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld );
     993           4 :     AddDimension(pNew);
     994           4 :     return pNew;
     995             : }
     996             : 
     997           4 : void ScDPSaveData::RemoveDimensionByName(const OUString& rName)
     998             : {
     999           4 :     boost::ptr_vector<ScDPSaveDimension>::iterator iter;
    1000           6 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
    1001             :     {
    1002           6 :         if (iter->GetName() != rName || iter->IsDataLayout())
    1003           2 :             continue;
    1004             : 
    1005           4 :         aDimList.erase(iter);
    1006           4 :         RemoveDuplicateNameCount(rName);
    1007           4 :         DimensionsChanged();
    1008           8 :         return;
    1009             :     }
    1010             : }
    1011             : 
    1012           4 : ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rDim )
    1013             : {
    1014           4 :     ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim );
    1015           4 :     AddDimension(pNew);
    1016           4 :     return *pNew;
    1017             : }
    1018             : 
    1019           0 : ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(sal_uInt16 nOrientation)
    1020             : {
    1021             :     // return the innermost dimension for the given orientation,
    1022             :     // excluding data layout dimension
    1023             : 
    1024           0 :     boost::ptr_vector<ScDPSaveDimension>::const_reverse_iterator iter;
    1025           0 :     for (iter = aDimList.rbegin(); iter != aDimList.rend(); ++iter)
    1026             :     {
    1027           0 :         if (iter->GetOrientation() == nOrientation && !iter->IsDataLayout())
    1028           0 :             return const_cast<ScDPSaveDimension*>(&(*iter));
    1029             :     }
    1030             : 
    1031           0 :     return NULL;
    1032             : }
    1033             : 
    1034           0 : ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)
    1035             : {
    1036           0 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
    1037           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
    1038             :     {
    1039           0 :         if (iter->GetOrientation() == eOrientation && !iter->IsDataLayout())
    1040           0 :             return const_cast<ScDPSaveDimension*>(&(*iter));
    1041             :     }
    1042           0 :     return NULL;
    1043             : }
    1044             : 
    1045           0 : long ScDPSaveData::GetDataDimensionCount() const
    1046             : {
    1047           0 :     long nDataCount = 0;
    1048             : 
    1049           0 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
    1050           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
    1051             :     {
    1052           0 :         if (iter->GetOrientation() == sheet::DataPilotFieldOrientation_DATA)
    1053           0 :             ++nDataCount;
    1054             :     }
    1055             : 
    1056           0 :     return nDataCount;
    1057             : }
    1058             : 
    1059         164 : void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
    1060             : {
    1061             :     // position (nNew) is counted within dimensions of the same orientation
    1062             : 
    1063         164 :     sal_uInt16 nOrient = pDim->GetOrientation();
    1064             : 
    1065         164 :     boost::ptr_vector<ScDPSaveDimension>::iterator it;
    1066         466 :     for ( it = aDimList.begin(); it != aDimList.end(); ++it)
    1067             :     {
    1068         466 :         if (pDim == &(*it))
    1069             :         {
    1070             :             // Tell ptr_vector to give up ownership of this element.  Don't
    1071             :             // delete this instance as it is re-inserted into the container
    1072             :             // later.
    1073         164 :             aDimList.release(it).release();
    1074         164 :             break;
    1075             :         }
    1076             :     }
    1077             : 
    1078         164 :     boost::ptr_vector<ScDPSaveDimension>::iterator iterInsert = aDimList.begin();
    1079         718 :     while ( nNew > 0 && iterInsert != aDimList.end())
    1080             :     {
    1081         390 :         if (iterInsert->GetOrientation() == nOrient )
    1082          12 :             --nNew;
    1083             : 
    1084         390 :         ++iterInsert;
    1085             :     }
    1086             : 
    1087         164 :     aDimList.insert(iterInsert,pDim);
    1088         164 :     DimensionsChanged();
    1089         164 : }
    1090             : 
    1091         104 : void ScDPSaveData::SetColumnGrand(bool bSet)
    1092             : {
    1093         104 :     nColumnGrandMode = sal_uInt16(bSet);
    1094         104 : }
    1095             : 
    1096         104 : void ScDPSaveData::SetRowGrand(bool bSet)
    1097             : {
    1098         104 :     nRowGrandMode = sal_uInt16(bSet);
    1099         104 : }
    1100             : 
    1101          96 : void ScDPSaveData::SetIgnoreEmptyRows(bool bSet)
    1102             : {
    1103          96 :     nIgnoreEmptyMode = sal_uInt16(bSet);
    1104          96 : }
    1105             : 
    1106          94 : void ScDPSaveData::SetRepeatIfEmpty(bool bSet)
    1107             : {
    1108          94 :     nRepeatEmptyMode = sal_uInt16(bSet);
    1109          94 : }
    1110             : 
    1111          62 : void ScDPSaveData::SetFilterButton(bool bSet)
    1112             : {
    1113          62 :     bFilterButton = bSet;
    1114          62 : }
    1115             : 
    1116          62 : void ScDPSaveData::SetDrillDown(bool bSet)
    1117             : {
    1118          62 :     bDrillDown = bSet;
    1119          62 : }
    1120             : 
    1121         256 : static void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
    1122             : {
    1123         256 :     sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN;
    1124             : 
    1125         256 :     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    1126         512 :     uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
    1127         256 :     long nIntCount = xIntDims->getCount();
    1128        1426 :     for (long nIntDim=0; nIntDim<nIntCount; nIntDim++)
    1129             :     {
    1130        1170 :         uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
    1131        2340 :         uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
    1132        1170 :         if (xDimProp.is())
    1133             :         {
    1134        1170 :             uno::Any aAny;
    1135        1170 :             aAny <<= eOrient;
    1136        1170 :             xDimProp->setPropertyValue( OUString(SC_UNO_DP_ORIENTATION), aAny );
    1137             :         }
    1138        1426 :     }
    1139         256 : }
    1140             : 
    1141         256 : void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
    1142             : {
    1143         256 :     if (!xSource.is())
    1144         256 :         return;
    1145             : 
    1146             :     // source options must be first!
    1147             : 
    1148         256 :     uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
    1149             :     OSL_ENSURE( xSourceProp.is(), "no properties at source" );
    1150         256 :     if ( xSourceProp.is() )
    1151             :     {
    1152             :         // source options are not available for external sources
    1153             :         //! use XPropertySetInfo to test for availability?
    1154             : 
    1155             :         try
    1156             :         {
    1157         256 :             if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW )
    1158             :                 lcl_SetBoolProperty( xSourceProp,
    1159         254 :                     OUString(SC_UNO_DP_IGNOREEMPTY), (bool)nIgnoreEmptyMode );
    1160         256 :             if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
    1161             :                 lcl_SetBoolProperty( xSourceProp,
    1162         254 :                     OUString(SC_UNO_DP_REPEATEMPTY), (bool)nRepeatEmptyMode );
    1163             :         }
    1164           0 :         catch(uno::Exception&)
    1165             :         {
    1166             :             // no error
    1167             :         }
    1168             : 
    1169         256 :         const OUString* pGrandTotalName = GetGrandTotalName();
    1170         256 :         if (pGrandTotalName)
    1171           0 :             ScUnoHelpFunctions::SetOptionalPropertyValue(xSourceProp, SC_UNO_DP_GRANDTOTAL_NAME, *pGrandTotalName);
    1172             :     }
    1173             : 
    1174             :     // exceptions in the other calls are errors
    1175             :     try
    1176             :     {
    1177             :         // reset all orientations
    1178             :         //! "forgetSettings" or similar at source ?????
    1179             :         //! reset all duplicated dimensions, or reuse them below !!!
    1180             :         OSL_FAIL( "ScDPSaveData::WriteToSource" );
    1181             : 
    1182         256 :         lcl_ResetOrient( xSource );
    1183             : 
    1184         256 :         uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
    1185         512 :         uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
    1186         256 :         long nIntCount = xIntDims->getCount();
    1187             : 
    1188         256 :         boost::ptr_vector<ScDPSaveDimension>::iterator iter = aDimList.begin();
    1189         906 :         for (long i = 0; iter != aDimList.end(); ++iter, ++i)
    1190             :         {
    1191         650 :             OUString aName = iter->GetName();
    1192        1300 :             OUString aCoreName = ScDPUtil::getSourceDimensionName(aName);
    1193             : 
    1194             :             OSL_TRACE( "%s", aName.getStr() );
    1195             : 
    1196         650 :             bool bData = iter->IsDataLayout();
    1197             : 
    1198             :             //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
    1199             : 
    1200         650 :             bool bFound = false;
    1201        2520 :             for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
    1202             :             {
    1203        1870 :                 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
    1204        1870 :                 if ( bData )
    1205             :                 {
    1206         418 :                     uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
    1207         418 :                     if ( xDimProp.is() )
    1208             :                     {
    1209             :                         bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
    1210         418 :                                     OUString(SC_UNO_DP_ISDATALAYOUT) );
    1211             :                         //! error checking -- is "IsDataLayoutDimension" property required??
    1212         418 :                     }
    1213             :                 }
    1214             :                 else
    1215             :                 {
    1216        1452 :                     uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
    1217        1452 :                     if (xDimName.is() && xDimName->getName() == aCoreName)
    1218         548 :                         bFound = true;
    1219             :                 }
    1220             : 
    1221        1870 :                 if (bFound)
    1222             :                 {
    1223         648 :                     if (iter->GetDupFlag())
    1224             :                     {
    1225          10 :                         uno::Reference<util::XCloneable> xCloneable(xIntDim, uno::UNO_QUERY);
    1226             :                         OSL_ENSURE(xCloneable.is(), "cannot clone dimension");
    1227          10 :                         if (xCloneable.is())
    1228             :                         {
    1229          10 :                             uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
    1230          20 :                             uno::Reference<container::XNamed> xNewName(xNew, uno::UNO_QUERY);
    1231          10 :                             if (xNewName.is())
    1232             :                             {
    1233          10 :                                 xNewName->setName(aName);
    1234          10 :                                 iter->WriteToSource(xNew);
    1235          10 :                             }
    1236          10 :                         }
    1237             :                     }
    1238             :                     else
    1239         638 :                         iter->WriteToSource( xIntDim );
    1240             :                 }
    1241        1870 :             }
    1242             :             OSL_ENSURE(bFound, "WriteToSource: Dimension not found");
    1243         650 :         }
    1244             : 
    1245         256 :         if ( xSourceProp.is() )
    1246             :         {
    1247         256 :             if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW )
    1248             :                 lcl_SetBoolProperty( xSourceProp,
    1249         256 :                     OUString(SC_UNO_DP_COLGRAND), (bool)nColumnGrandMode );
    1250         256 :             if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW )
    1251             :                 lcl_SetBoolProperty( xSourceProp,
    1252         256 :                     OUString(SC_UNO_DP_ROWGRAND), (bool)nRowGrandMode );
    1253         256 :         }
    1254             :     }
    1255           0 :     catch(uno::Exception&)
    1256             :     {
    1257             :         OSL_FAIL("exception in WriteToSource");
    1258         256 :     }
    1259             : }
    1260             : 
    1261           0 : bool ScDPSaveData::IsEmpty() const
    1262             : {
    1263           0 :     boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
    1264           0 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
    1265             :     {
    1266           0 :         if (iter->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !iter->IsDataLayout())
    1267           0 :             return false;
    1268             :     }
    1269           0 :     return true; // no entries that are not hidden
    1270             : }
    1271             : 
    1272           2 : void ScDPSaveData::RemoveAllGroupDimensions( const OUString& rSrcDimName, std::vector<OUString>* pDeletedNames )
    1273             : {
    1274           2 :     if (!pDimensionData)
    1275             :         // No group dimensions exist.  Nothing to do.
    1276           2 :         return;
    1277             : 
    1278             :     // Remove numeric group dimension (exists once at most). No need to delete
    1279             :     // anything in save data (grouping was done inplace in an existing base
    1280             :     // dimension).
    1281           2 :     pDimensionData->RemoveNumGroupDimension(rSrcDimName);
    1282             : 
    1283             :     // Remove named group dimension(s). Dimensions have to be removed from
    1284             :     // dimension save data and from save data too.
    1285           2 :     const ScDPSaveGroupDimension* pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
    1286           8 :     while ( pExistingGroup )
    1287             :     {
    1288           4 :         OUString aGroupDimName = pExistingGroup->GetGroupDimName();
    1289           4 :         pDimensionData->RemoveGroupDimension(aGroupDimName);     // pExistingGroup is deleted
    1290             : 
    1291             :         // also remove SaveData settings for the dimension that no longer exists
    1292           4 :         RemoveDimensionByName(aGroupDimName);
    1293             : 
    1294           4 :         if (pDeletedNames)
    1295           0 :             pDeletedNames->push_back(aGroupDimName);
    1296             : 
    1297             :         // see if there are more group dimensions
    1298           4 :         pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
    1299             : 
    1300           4 :         if ( pExistingGroup && pExistingGroup->GetGroupDimName() == aGroupDimName )
    1301             :         {
    1302             :             // still get the same group dimension?
    1303             :             OSL_FAIL("couldn't remove group dimension");
    1304           0 :             pExistingGroup = NULL;      // avoid endless loop
    1305             :         }
    1306           4 :     }
    1307             : }
    1308             : 
    1309          16 : ScDPDimensionSaveData* ScDPSaveData::GetDimensionData()
    1310             : {
    1311          16 :     if (!pDimensionData)
    1312          14 :         pDimensionData = new ScDPDimensionSaveData;
    1313          16 :     return pDimensionData;
    1314             : }
    1315             : 
    1316           4 : void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew )
    1317             : {
    1318           4 :     delete pDimensionData;
    1319           4 :     if ( pNew )
    1320           4 :         pDimensionData = new ScDPDimensionSaveData( *pNew );
    1321             :     else
    1322           0 :         pDimensionData = NULL;
    1323           4 : }
    1324             : 
    1325           8 : void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
    1326             : {
    1327           8 :     if (mbDimensionMembersBuilt)
    1328           8 :         return;
    1329             : 
    1330             :     // First, build a dimension name-to-index map.
    1331             :     typedef boost::unordered_map<OUString, long, OUStringHash> NameIndexMap;
    1332           8 :     NameIndexMap aMap;
    1333           8 :     long nColCount = pData->GetColumnCount();
    1334          62 :     for (long i = 0; i < nColCount; ++i)
    1335          54 :         aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i));
    1336             : 
    1337           8 :     NameIndexMap::const_iterator itrEnd = aMap.end();
    1338             : 
    1339           8 :     boost::ptr_vector<ScDPSaveDimension>::iterator iter;
    1340          58 :     for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
    1341             :     {
    1342          50 :         const OUString& rDimName = iter->GetName();
    1343          50 :         if (rDimName.isEmpty())
    1344             :             // empty dimension name. It must be data layout.
    1345          16 :             continue;
    1346             : 
    1347          42 :         NameIndexMap::const_iterator itr = aMap.find(rDimName);
    1348          42 :         if (itr == itrEnd)
    1349             :             // dimension name not in the data. This should never happen!
    1350           0 :             continue;
    1351             : 
    1352          42 :         long nDimIndex = itr->second;
    1353          42 :         const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
    1354          42 :         size_t mMemberCount = rMembers.size();
    1355        1818 :         for (size_t j = 0; j < mMemberCount; ++j)
    1356             :         {
    1357        1776 :             const ScDPItemData* pMemberData = pData->GetMemberById( nDimIndex, rMembers[j] );
    1358        1776 :             OUString aMemName = pData->GetFormattedString(nDimIndex, *pMemberData);
    1359        1776 :             if (iter->GetExistingMemberByName(aMemName))
    1360             :                 // this member instance already exists. nothing to do.
    1361         192 :                 continue;
    1362             : 
    1363        3168 :             unique_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName));
    1364        1584 :             pNewMember->SetIsVisible(true);
    1365        1584 :             iter->AddMember(pNewMember.release());
    1366        1584 :         }
    1367             :     }
    1368             : 
    1369           8 :     mbDimensionMembersBuilt = true;
    1370             : }
    1371             : 
    1372         102 : void ScDPSaveData::SyncAllDimensionMembers(ScDPTableData* pData)
    1373             : {
    1374             :     typedef boost::unordered_map<OUString, long, OUStringHash> NameIndexMap;
    1375             : 
    1376             :     // First, build a dimension name-to-index map.
    1377         102 :     NameIndexMap aMap;
    1378         102 :     long nColCount = pData->GetColumnCount();
    1379         614 :     for (long i = 0; i < nColCount; ++i)
    1380         512 :         aMap.insert(NameIndexMap::value_type(pData->getDimensionName(i), i));
    1381             : 
    1382         102 :     NameIndexMap::const_iterator itMapEnd = aMap.end();
    1383             : 
    1384         102 :     DimsType::iterator it = aDimList.begin(), itEnd = aDimList.end();
    1385         462 :     for (it = aDimList.begin(); it != itEnd; ++it)
    1386             :     {
    1387         360 :         const OUString& rDimName = it->GetName();
    1388         360 :         if (rDimName.isEmpty())
    1389             :             // empty dimension name. It must be data layout.
    1390          54 :             continue;
    1391             : 
    1392         336 :         NameIndexMap::const_iterator itMap = aMap.find(rDimName);
    1393         336 :         if (itMap == itMapEnd)
    1394             :             // dimension name not in the data. This should never happen!
    1395           6 :             continue;
    1396             : 
    1397         330 :         ScDPSaveDimension::MemberSetType aMemNames;
    1398         330 :         long nDimIndex = itMap->second;
    1399         330 :         const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
    1400         330 :         size_t nMemberCount = rMembers.size();
    1401        1808 :         for (size_t j = 0; j < nMemberCount; ++j)
    1402             :         {
    1403        1478 :             const ScDPItemData* pMemberData = pData->GetMemberById(nDimIndex, rMembers[j]);
    1404        1478 :             OUString aMemName = pData->GetFormattedString(nDimIndex, *pMemberData);
    1405        1478 :             aMemNames.insert(aMemName);
    1406        1478 :         }
    1407             : 
    1408         330 :         it->RemoveObsoleteMembers(aMemNames);
    1409         432 :     }
    1410         102 : }
    1411             : 
    1412           0 : bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const
    1413             : {
    1414           0 :     ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName);
    1415           0 :     if (!pDim)
    1416           0 :         return false;
    1417             : 
    1418           0 :     return pDim->HasInvisibleMember();
    1419             : }
    1420             : 
    1421             : #if DEBUG_PIVOT_TABLE
    1422             : 
    1423             : void ScDPSaveData::Dump() const
    1424             : {
    1425             :     DimsType::const_iterator itDim = aDimList.begin(), itDimEnd = aDimList.end();
    1426             :     for (; itDim != itDimEnd; ++itDim)
    1427             :     {
    1428             :         const ScDPSaveDimension& rDim = *itDim;
    1429             :         rDim.Dump();
    1430             :     }
    1431             : }
    1432             : 
    1433             : #endif
    1434             : 
    1435          84 : void ScDPSaveData::CheckDuplicateName(ScDPSaveDimension& rDim)
    1436             : {
    1437          84 :     const OUString aName = ScDPUtil::getSourceDimensionName(rDim.GetName());
    1438          84 :     DupNameCountType::iterator it = maDupNameCounts.find(aName);
    1439          84 :     if (it != maDupNameCounts.end())
    1440             :     {
    1441           8 :         rDim.SetName(ScDPUtil::createDuplicateDimensionName(aName, ++it->second));
    1442           8 :         rDim.SetDupFlag(true);
    1443             :     }
    1444             :     else
    1445             :         // New name.
    1446          76 :         maDupNameCounts.insert(DupNameCountType::value_type(aName, 0));
    1447          84 : }
    1448             : 
    1449           4 : void ScDPSaveData::RemoveDuplicateNameCount(const OUString& rName)
    1450             : {
    1451           4 :     OUString aCoreName = rName;
    1452           4 :     if (ScDPUtil::isDuplicateDimension(rName))
    1453           0 :         aCoreName = ScDPUtil::getSourceDimensionName(rName);
    1454             : 
    1455           4 :     DupNameCountType::iterator it = maDupNameCounts.find(aCoreName);
    1456           4 :     if (it == maDupNameCounts.end())
    1457           0 :         return;
    1458             : 
    1459           4 :     if (!it->second)
    1460             :     {
    1461           4 :         maDupNameCounts.erase(it);
    1462           4 :         return;
    1463             :     }
    1464             : 
    1465           0 :     --it->second;
    1466           0 :     return;
    1467             : }
    1468             : 
    1469         310 : ScDPSaveDimension* ScDPSaveData::AppendNewDimension(const OUString& rName, bool bDataLayout)
    1470             : {
    1471         310 :     if (ScDPUtil::isDuplicateDimension(rName))
    1472             :         // This call is for original dimensions only.
    1473           0 :         return NULL;
    1474             : 
    1475         310 :     ScDPSaveDimension* pNew = new ScDPSaveDimension(rName, bDataLayout);
    1476         310 :     aDimList.push_back(pNew);
    1477         310 :     if (!maDupNameCounts.count(rName))
    1478         310 :         maDupNameCounts.insert(DupNameCountType::value_type(rName, 0));
    1479             : 
    1480         310 :     DimensionsChanged();
    1481         310 :     return pNew;
    1482             : }
    1483             : 
    1484         562 : void ScDPSaveData::DimensionsChanged()
    1485             : {
    1486         562 :     mpDimOrder.reset();
    1487         562 : }
    1488             : 
    1489           0 : bool operator == (const ::com::sun::star::sheet::DataPilotFieldSortInfo &l, const ::com::sun::star::sheet::DataPilotFieldSortInfo &r )
    1490             : {
    1491           0 :     return l.Field == r.Field && l.IsAscending == r.IsAscending && l.Mode == r.Mode;
    1492             : }
    1493           0 : bool operator == (const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &l, const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &r )
    1494             : {
    1495           0 :     return l.IsEnabled == r.IsEnabled &&
    1496           0 :         l.ShowItemsMode == r.ShowItemsMode &&
    1497           0 :         l.ItemCount == r.ItemCount &&
    1498           0 :         l.DataField == r.DataField;
    1499             : }
    1500           0 : bool operator == (const ::com::sun::star::sheet::DataPilotFieldReference &l, const ::com::sun::star::sheet::DataPilotFieldReference &r )
    1501             : {
    1502           0 :     return l.ReferenceType == r.ReferenceType &&
    1503           0 :         l.ReferenceField == r.ReferenceField &&
    1504           0 :         l.ReferenceItemType == r.ReferenceItemType &&
    1505           0 :         l.ReferenceItemName == r.ReferenceItemName;
    1506         228 : }
    1507             : 
    1508             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10