xref: /AOO41X/main/sc/source/core/data/dpsave.cxx (revision 3d7628264b67541a59f8a1d4df8ea02ab31c33a6)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 
31 #include "dpsave.hxx"
32 #include "dpdimsave.hxx"
33 #include "dpobject.hxx"     // GetMemberNames used in BuildAllDimensionMembersFromSource
34 #include "miscuno.hxx"
35 #include "scerrors.hxx"
36 #include "unonames.hxx"
37 #include "global.hxx"
38 
39 #include <tools/debug.hxx>
40 
41 #include <com/sun/star/sheet/GeneralFunction.hpp>
42 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
43 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
44 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
45 #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
46 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
47 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
48 #include <com/sun/star/sheet/TableFilterField.hpp>
49 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
50 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
51 #include <com/sun/star/sheet/XMembersSupplier.hpp>
52 #include <com/sun/star/container/XNamed.hpp>
53 #include <com/sun/star/util/XCloneable.hpp>
54 // Wang Xu Ming -- 2009-8-17
55 // DataPilot Migration - Cache&&Performance
56 #include "dptabsrc.hxx"
57 #include "dpglobal.hxx"
58 using namespace ScDPGlobal;
59 #ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDREFERENCETYPE_HPP_
60 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
61 #endif
62 #ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDREFERENCEITEMTYPE_HPP_
63 #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
64 #endif
65 using namespace com::sun::star::sheet;
66 // End Comments
67 
68 #include <hash_map>
69 
70 using namespace com::sun::star;
71 using ::com::sun::star::uno::Reference;
72 using ::com::sun::star::uno::Any;
73 using ::rtl::OUString;
74 using ::rtl::OUStringHash;
75 using ::std::hash_map;
76 using ::std::auto_ptr;
77 
78 // -----------------------------------------------------------------------
79 
80 #define SC_DPSAVEMODE_NO        0
81 #define SC_DPSAVEMODE_YES       1
82 #define SC_DPSAVEMODE_DONTKNOW  2
83 
84 // -----------------------------------------------------------------------
85 
lcl_SetBoolProperty(const uno::Reference<beans::XPropertySet> & xProp,const rtl::OUString & rName,sal_Bool bValue)86 void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp,
87                             const rtl::OUString& rName, sal_Bool bValue )
88 {
89     //! move to ScUnoHelpFunctions?
90 
91     xProp->setPropertyValue( rName, uno::Any( &bValue, getBooleanCppuType() ) );
92 }
93 
94 // -----------------------------------------------------------------------
95 
ScDPSaveMember(const String & rName)96 ScDPSaveMember::ScDPSaveMember(const String& rName) :
97     aName( rName ),
98     mpLayoutName(NULL),
99     nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
100     nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
101 {
102 }
103 
ScDPSaveMember(const ScDPSaveMember & r)104 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
105     aName( r.aName ),
106     mpLayoutName(NULL),
107     nVisibleMode( r.nVisibleMode ),
108     nShowDetailsMode( r.nShowDetailsMode )
109 {
110     if (r.mpLayoutName.get())
111         mpLayoutName.reset(new OUString(*r.mpLayoutName));
112 }
113 
~ScDPSaveMember()114 ScDPSaveMember::~ScDPSaveMember()
115 {
116 }
117 
operator ==(const ScDPSaveMember & r) const118 sal_Bool ScDPSaveMember::operator== ( const ScDPSaveMember& r ) const
119 {
120     if ( aName            != r.aName            ||
121          nVisibleMode     != r.nVisibleMode     ||
122          nShowDetailsMode != r.nShowDetailsMode )
123         return sal_False;
124 
125     return sal_True;
126 }
127 
HasIsVisible() const128 sal_Bool ScDPSaveMember::HasIsVisible() const
129 {
130     return nVisibleMode != SC_DPSAVEMODE_DONTKNOW;
131 }
132 
SetIsVisible(sal_Bool bSet)133 void ScDPSaveMember::SetIsVisible(sal_Bool bSet)
134 {
135     nVisibleMode = bSet;
136 }
137 
HasShowDetails() const138 sal_Bool ScDPSaveMember::HasShowDetails() const
139 {
140     return nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW;
141 }
142 
SetShowDetails(sal_Bool bSet)143 void ScDPSaveMember::SetShowDetails(sal_Bool bSet)
144 {
145     nShowDetailsMode = bSet;
146 }
147 
SetName(const String & rNew)148 void ScDPSaveMember::SetName( const String& rNew )
149 {
150     // Used only if the source member was renamed (groups).
151     // For UI renaming of members, a layout name must be used.
152 
153     aName = rNew;
154 }
155 
SetLayoutName(const OUString & rName)156 void ScDPSaveMember::SetLayoutName( const OUString& rName )
157 {
158     mpLayoutName.reset(new OUString(rName));
159 }
160 
GetLayoutName() const161 const OUString* ScDPSaveMember::GetLayoutName() const
162 {
163     return mpLayoutName.get();
164 }
165 
RemoveLayoutName()166 void ScDPSaveMember::RemoveLayoutName()
167 {
168     mpLayoutName.reset();
169 }
170 
WriteToSource(const uno::Reference<uno::XInterface> & xMember,sal_Int32 nPosition)171 void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
172 {
173     uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
174     DBG_ASSERT( xMembProp.is(), "no properties at member" );
175     if ( xMembProp.is() )
176     {
177         // exceptions are caught at ScDPSaveData::WriteToSource
178 
179         if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW )
180             lcl_SetBoolProperty( xMembProp,
181                     rtl::OUString::createFromAscii(DP_PROP_ISVISIBLE), (sal_Bool)nVisibleMode );
182 
183         if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW )
184             lcl_SetBoolProperty( xMembProp,
185                     rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS), (sal_Bool)nShowDetailsMode );
186 
187         if (mpLayoutName.get())
188             ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_LAYOUTNAME, *mpLayoutName);
189 
190         if ( nPosition >= 0 )
191             ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, DP_PROP_POSITION, nPosition);
192     }
193 }
194 
195 // -----------------------------------------------------------------------
196 
ScDPSaveDimension(const String & rName,sal_Bool bDataLayout)197 ScDPSaveDimension::ScDPSaveDimension(const String& rName, sal_Bool bDataLayout) :
198     aName( rName ),
199     pSelectedPage( NULL ),
200     mpLayoutName(NULL),
201     mpSubtotalName(NULL),
202     bIsDataLayout( bDataLayout ),
203     bDupFlag( sal_False ),
204     nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ),
205     nFunction( sheet::GeneralFunction_AUTO ),
206     nUsedHierarchy( -1 ),
207     nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
208     bSubTotalDefault( sal_True ),
209     nSubTotalCount( 0 ),
210     pSubTotalFuncs( NULL ),
211     pReferenceValue( NULL ),
212     pSortInfo( NULL ),
213     pAutoShowInfo( NULL ),
214     pLayoutInfo( NULL )
215 {
216 }
217 
ScDPSaveDimension(const ScDPSaveDimension & r)218 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
219     aName( r.aName ),
220     mpLayoutName(NULL),
221     mpSubtotalName(NULL),
222     bIsDataLayout( r.bIsDataLayout ),
223     bDupFlag( r.bDupFlag ),
224     nOrientation( r.nOrientation ),
225     nFunction( r.nFunction ),
226     nUsedHierarchy( r.nUsedHierarchy ),
227     nShowEmptyMode( r.nShowEmptyMode ),
228     bSubTotalDefault( r.bSubTotalDefault ),
229     nSubTotalCount( r.nSubTotalCount ),
230     pSubTotalFuncs( NULL )
231 {
232     if ( nSubTotalCount && r.pSubTotalFuncs )
233     {
234         pSubTotalFuncs = new sal_uInt16[nSubTotalCount];
235         for (long nSub=0; nSub<nSubTotalCount; nSub++)
236             pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub];
237     }
238 
239     for (MemberList::const_iterator i=r.maMemberList.begin(); i != r.maMemberList.end() ; i++)
240     {
241         const String& rName =  (*i)->GetName();
242         ScDPSaveMember* pNew = new ScDPSaveMember( **i );
243         maMemberHash[rName] = pNew;
244         maMemberList.push_back( pNew );
245     }
246     if (r.pReferenceValue)
247         pReferenceValue = new sheet::DataPilotFieldReference( *(r.pReferenceValue) );
248     else
249         pReferenceValue = NULL;
250     if (r.pSortInfo)
251         pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) );
252     else
253         pSortInfo = NULL;
254     if (r.pAutoShowInfo)
255         pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) );
256     else
257         pAutoShowInfo = NULL;
258     if (r.pLayoutInfo)
259         pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
260     else
261         pLayoutInfo = NULL;
262     if (r.pSelectedPage)
263         pSelectedPage = new String( *(r.pSelectedPage) );
264     else
265         pSelectedPage = NULL;
266     if (r.mpLayoutName.get())
267         mpLayoutName.reset(new OUString(*r.mpLayoutName));
268     if (r.mpSubtotalName.get())
269         mpSubtotalName.reset(new OUString(*r.mpSubtotalName));
270 }
271 
~ScDPSaveDimension()272 ScDPSaveDimension::~ScDPSaveDimension()
273 {
274     for (MemberHash::const_iterator i=maMemberHash.begin(); i != maMemberHash.end() ; i++)
275         delete i->second;
276     delete pReferenceValue;
277     delete pSortInfo;
278     delete pAutoShowInfo;
279     delete pLayoutInfo;
280     delete pSelectedPage;
281     delete [] pSubTotalFuncs;
282 }
283 
operator ==(const ScDPSaveDimension & r) const284 sal_Bool ScDPSaveDimension::operator== ( const ScDPSaveDimension& r ) const
285 {
286     if ( aName            != r.aName            ||
287          bIsDataLayout    != r.bIsDataLayout    ||
288          bDupFlag         != r.bDupFlag         ||
289          nOrientation     != r.nOrientation     ||
290          nFunction        != r.nFunction        ||
291          nUsedHierarchy   != r.nUsedHierarchy   ||
292          nShowEmptyMode   != r.nShowEmptyMode   ||
293          bSubTotalDefault != r.bSubTotalDefault ||
294          nSubTotalCount   != r.nSubTotalCount )
295         return sal_False;
296 
297     if ( nSubTotalCount && ( !pSubTotalFuncs || !r.pSubTotalFuncs ) )   // should not happen
298         return sal_False;
299 
300     long i;
301     for (i=0; i<nSubTotalCount; i++)
302         if ( pSubTotalFuncs[i] != r.pSubTotalFuncs[i] )
303             return sal_False;
304 
305     if (maMemberHash.size() != r.maMemberHash.size() )
306         return sal_False;
307 
308     MemberList::const_iterator a=maMemberList.begin();
309     MemberList::const_iterator b=r.maMemberList.begin();
310     for (; a != maMemberList.end() ; ++a, ++b)
311         if (!(**a == **b))
312             return sal_False;
313 
314     if ( this->HasCurrentPage() && r.HasCurrentPage() )
315     {
316         if ( this->GetCurrentPage() != r.GetCurrentPage() )
317         {
318             return sal_False;
319         }
320     }
321     else if ( this->HasCurrentPage() || r.HasCurrentPage() )
322     {
323         return sal_False;
324     }
325     if( pReferenceValue && r.pReferenceValue )
326     {
327         if ( !(*pReferenceValue == *r.pReferenceValue) )
328         {
329             return sal_False;
330         }
331     }
332     else if ( pReferenceValue || r.pReferenceValue )
333     {
334         return sal_False;
335     }
336     if( this->pSortInfo && r.pSortInfo )
337     {
338         if ( !(*this->pSortInfo == *r.pSortInfo) )
339         {
340             return sal_False;
341         }
342     }
343     else if ( this->pSortInfo || r.pSortInfo )
344     {
345         return sal_False;
346     }
347     if( this->pAutoShowInfo && r.pAutoShowInfo )
348     {
349         if ( !(*this->pAutoShowInfo == *r.pAutoShowInfo) )
350         {
351             return sal_False;
352         }
353     }
354     else if ( this->pAutoShowInfo || r.pAutoShowInfo )
355     {
356         return sal_False;
357     }
358 
359     return sal_True;
360 }
361 
AddMember(ScDPSaveMember * pMember)362 void ScDPSaveDimension::AddMember(ScDPSaveMember* pMember)
363 {
364     const String & rName =  pMember->GetName();
365     MemberHash::iterator aExisting = maMemberHash.find( rName );
366     if ( aExisting == maMemberHash.end() )
367     {
368         std::pair< const String, ScDPSaveMember *> key( rName, pMember );
369         maMemberHash.insert ( key );
370     }
371     else
372     {
373         maMemberList.remove( aExisting->second );
374         delete aExisting->second;
375         aExisting->second = pMember;
376     }
377     maMemberList.push_back( pMember );
378 }
379 
SetName(const String & rNew)380 void ScDPSaveDimension::SetName( const String& rNew )
381 {
382     // Used only if the source dim was renamed (groups).
383     // For UI renaming of dimensions, the layout name must be used.
384 
385     aName = rNew;
386 }
387 
SetOrientation(sal_uInt16 nNew)388 void ScDPSaveDimension::SetOrientation(sal_uInt16 nNew)
389 {
390     nOrientation = nNew;
391 }
392 
SetSubTotals(long nCount,const sal_uInt16 * pFuncs)393 void ScDPSaveDimension::SetSubTotals(long nCount, const sal_uInt16* pFuncs)
394 {
395     if (pSubTotalFuncs)
396         delete [] pSubTotalFuncs;
397     nSubTotalCount = nCount;
398     if ( nCount && pFuncs )
399     {
400         pSubTotalFuncs = new sal_uInt16[nCount];
401         for (long i=0; i<nCount; i++)
402             pSubTotalFuncs[i] = pFuncs[i];
403     }
404     else
405         pSubTotalFuncs = NULL;
406 
407     bSubTotalDefault = sal_False;
408 }
409 
HasShowEmpty() const410 bool ScDPSaveDimension::HasShowEmpty() const
411 {
412     return nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW;
413 }
414 
SetShowEmpty(sal_Bool bSet)415 void ScDPSaveDimension::SetShowEmpty(sal_Bool bSet)
416 {
417     nShowEmptyMode = bSet;
418 }
419 
SetFunction(sal_uInt16 nNew)420 void ScDPSaveDimension::SetFunction(sal_uInt16 nNew)
421 {
422     nFunction = nNew;
423 }
424 
SetUsedHierarchy(long nNew)425 void ScDPSaveDimension::SetUsedHierarchy(long nNew)
426 {
427     nUsedHierarchy = nNew;
428 }
429 
SetSubtotalName(const OUString & rName)430 void ScDPSaveDimension::SetSubtotalName(const OUString& rName)
431 {
432     mpSubtotalName.reset(new OUString(rName));
433 }
434 
GetSubtotalName() const435 const OUString* ScDPSaveDimension::GetSubtotalName() const
436 {
437     return mpSubtotalName.get();
438 }
439 
IsMemberNameInUse(const OUString & rName) const440 bool ScDPSaveDimension::IsMemberNameInUse(const OUString& rName) const
441 {
442     MemberList::const_iterator itr = maMemberList.begin(), itrEnd = maMemberList.end();
443     for (; itr != itrEnd; ++itr)
444     {
445         const ScDPSaveMember* pMem = *itr;
446         if (rName.equalsIgnoreAsciiCase(pMem->GetName()))
447             return true;
448 
449         const OUString* pLayoutName = pMem->GetLayoutName();
450         if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName))
451             return true;
452     }
453     return false;
454 }
455 
SetLayoutName(const OUString & rName)456 void ScDPSaveDimension::SetLayoutName(const OUString& rName)
457 {
458     mpLayoutName.reset(new OUString(rName));
459 }
460 
GetLayoutName() const461 const OUString* ScDPSaveDimension::GetLayoutName() const
462 {
463     return mpLayoutName.get();
464 }
465 
RemoveLayoutName()466 void ScDPSaveDimension::RemoveLayoutName()
467 {
468     mpLayoutName.reset();
469 }
470 
SetReferenceValue(const sheet::DataPilotFieldReference * pNew)471 void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
472 {
473     delete pReferenceValue;
474     if (pNew)
475         pReferenceValue = new sheet::DataPilotFieldReference(*pNew);
476     else
477         pReferenceValue = NULL;
478 }
479 
SetSortInfo(const sheet::DataPilotFieldSortInfo * pNew)480 void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew)
481 {
482     delete pSortInfo;
483     if (pNew)
484         pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew);
485     else
486         pSortInfo = NULL;
487 }
488 
SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo * pNew)489 void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew)
490 {
491     delete pAutoShowInfo;
492     if (pNew)
493         pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew);
494     else
495         pAutoShowInfo = NULL;
496 }
497 
SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo * pNew)498 void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew)
499 {
500     delete pLayoutInfo;
501     if (pNew)
502         pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew);
503     else
504         pLayoutInfo = NULL;
505 }
506 
SetCurrentPage(const String * pPage)507 void ScDPSaveDimension::SetCurrentPage( const String* pPage )
508 {
509     delete pSelectedPage;
510     if (pPage)
511         pSelectedPage = new String( *pPage );
512     else
513         pSelectedPage = NULL;
514 }
515 
HasCurrentPage() const516 sal_Bool ScDPSaveDimension::HasCurrentPage() const
517 {
518     return ( pSelectedPage != NULL );
519 }
520 
GetCurrentPage() const521 const String& ScDPSaveDimension::GetCurrentPage() const
522 {
523     if (pSelectedPage)
524         return *pSelectedPage;
525     return EMPTY_STRING;
526 }
527 
GetExistingMemberByName(const String & rName)528 ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const String& rName)
529 {
530     MemberHash::const_iterator res = maMemberHash.find (rName);
531     if (res != maMemberHash.end())
532         return res->second;
533     return NULL;
534 }
535 
536 
GetMemberByName(const String & rName)537 ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const String& rName)
538 {
539     MemberHash::const_iterator res = maMemberHash.find (rName);
540     if (res != maMemberHash.end())
541         return res->second;
542 
543     ScDPSaveMember* pNew = new ScDPSaveMember( rName );
544     maMemberHash[rName] = pNew;
545     maMemberList.push_back( pNew );
546     return pNew;
547 }
548 
SetMemberPosition(const String & rName,sal_Int32 nNewPos)549 void ScDPSaveDimension::SetMemberPosition( const String& rName, sal_Int32 nNewPos )
550 {
551     ScDPSaveMember* pMember = GetMemberByName( rName );     // make sure it exists and is in the hash
552 
553     maMemberList.remove( pMember );
554 
555     MemberList::iterator aIter = maMemberList.begin();
556     for (sal_Int32 i=0; i<nNewPos && aIter != maMemberList.end(); i++)
557         ++aIter;
558     maMemberList.insert( aIter, pMember );
559 }
560 
WriteToSource(const uno::Reference<uno::XInterface> & xDim)561 void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim )
562 {
563     uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
564     DBG_ASSERT( xDimProp.is(), "no properties at dimension" );
565     if ( xDimProp.is() )
566     {
567         // exceptions are caught at ScDPSaveData::WriteToSource
568         uno::Any aAny;
569 
570         sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
571         aAny <<= eOrient;
572         xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
573 
574         sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
575         aAny <<= eFunc;
576         xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FUNCTION), aAny );
577 
578         if ( nUsedHierarchy >= 0 )
579         {
580             aAny <<= (sal_Int32)nUsedHierarchy;
581             xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY), aAny );
582         }
583 
584         if ( pReferenceValue )
585         {
586             aAny <<= *pReferenceValue;
587             xDimProp->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_REFVALUE), aAny );
588         }
589 
590         uno::Sequence<sheet::TableFilterField> aFilter;
591         // set the selected page field only if the dimension is used as page dimension
592         if ( pSelectedPage && nOrientation == sheet::DataPilotFieldOrientation_PAGE )
593         {
594             // single filter field: first field equal to selected string
595             sheet::TableFilterField aField( sheet::FilterConnection_AND, 0,
596                     sheet::FilterOperator_EQUAL, sal_False, 0.0, *pSelectedPage );
597             aFilter = uno::Sequence<sheet::TableFilterField>( &aField, 1 );
598         }
599         // else keep empty sequence
600 
601         ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, DP_PROP_FILTER, aFilter);
602         if (mpLayoutName.get())
603             ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_LAYOUTNAME, *mpLayoutName);
604 
605         const OUString* pSubTotalName = GetSubtotalName();
606         if (pSubTotalName)
607             // Custom subtotal name, with '?' being replaced by the visible field name later.
608             ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_FIELD_SUBTOTALNAME, *pSubTotalName);
609     }
610 
611     //  Level loop outside of maMemberList loop
612     //  because SubTotals have to be set independently of known members
613 
614     long nCount = maMemberHash.size();
615 
616     long nHierCount = 0;
617     uno::Reference<container::XIndexAccess> xHiers;
618     uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
619     if ( xHierSupp.is() )
620     {
621         uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
622         xHiers = new ScNameToIndexAccess( xHiersName );
623         nHierCount = xHiers->getCount();
624     }
625 
626     sal_Bool bHasHiddenMember = false;
627 
628     for (long nHier=0; nHier<nHierCount; nHier++)
629     {
630         uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
631 
632         long nLevCount = 0;
633         uno::Reference<container::XIndexAccess> xLevels;
634         uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
635         if ( xLevSupp.is() )
636         {
637             uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
638             xLevels = new ScNameToIndexAccess( xLevelsName );
639             nLevCount = xLevels->getCount();
640         }
641 
642         for (long nLev=0; nLev<nLevCount; nLev++)
643         {
644             uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) );
645             uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
646             DBG_ASSERT( xLevProp.is(), "no properties at level" );
647             if ( xLevProp.is() )
648             {
649                 uno::Any aAny;
650                 if ( !bSubTotalDefault )
651                 {
652                     if ( !pSubTotalFuncs )
653                         nSubTotalCount = 0;
654 
655                     uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount);
656                     sheet::GeneralFunction* pArray = aSeq.getArray();
657                     for (long i=0; i<nSubTotalCount; i++)
658                         pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i];
659                     aAny <<= aSeq;
660                     xLevProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_SUBTOTALS), aAny );
661                 }
662                 if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW )
663                     lcl_SetBoolProperty( xLevProp,
664                         rtl::OUString::createFromAscii(DP_PROP_SHOWEMPTY), (sal_Bool)nShowEmptyMode );
665 
666                 if ( pSortInfo )
667                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_SORTING, *pSortInfo);
668 
669                 if ( pAutoShowInfo )
670                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_AUTOSHOW, *pAutoShowInfo);
671 
672                 if ( pLayoutInfo )
673                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_LAYOUT, *pLayoutInfo);
674 
675                 // exceptions are caught at ScDPSaveData::WriteToSource
676             }
677 
678             if ( nCount > 0 )
679             {
680                 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
681                 if ( xMembSupp.is() )
682                 {
683                     uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
684                     if ( xMembers.is() )
685                     {
686                         sal_Int32 nPosition = -1;           // set position only in manual mode
687                         if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL )
688                             nPosition = 0;
689 
690                         for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; i++)
691                         {
692                             ScDPSaveMember* pMember = *i;
693                             if (!pMember->GetIsVisible())
694                                 bHasHiddenMember = true;
695                             rtl::OUString aMemberName = pMember->GetName();
696                             if ( xMembers->hasByName( aMemberName ) )
697                             {
698                                 uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
699                                     xMembers->getByName( aMemberName ) );
700                                 pMember->WriteToSource( xMemberInt, nPosition );
701 
702                                 if ( nPosition >= 0 )
703                                     ++nPosition;            // increase if initialized
704                             }
705                             // missing member is no error
706                         }
707                     }
708                 }
709             }
710         }
711     }
712 
713     if (xDimProp.is())
714         ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_HAS_HIDDEN_MEMBER, bHasHiddenMember);
715 }
716 
UpdateMemberVisibility(const hash_map<OUString,bool,OUStringHash> & rData)717 void ScDPSaveDimension::UpdateMemberVisibility(const hash_map<OUString, bool, OUStringHash>& rData)
718 {
719     typedef hash_map<OUString, bool, OUStringHash> DataMap;
720     MemberList::iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
721     for (; itrMem != itrMemEnd; ++itrMem)
722     {
723         ScDPSaveMember* pMem = *itrMem;
724         const String& rMemName = pMem->GetName();
725         DataMap::const_iterator itr = rData.find(rMemName);
726         if (itr != rData.end())
727             pMem->SetIsVisible(itr->second);
728     }
729 }
730 
HasInvisibleMember() const731 bool ScDPSaveDimension::HasInvisibleMember() const
732 {
733     MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
734     for (; itrMem != itrMemEnd; ++itrMem)
735     {
736         const ScDPSaveMember* pMem = *itrMem;
737         if (!pMem->GetIsVisible())
738             return true;
739     }
740     return false;
741 }
742 
743 // -----------------------------------------------------------------------
744 
ScDPSaveData()745 ScDPSaveData::ScDPSaveData() :
746     pDimensionData( NULL ),
747     nColumnGrandMode( SC_DPSAVEMODE_DONTKNOW ),
748     nRowGrandMode( SC_DPSAVEMODE_DONTKNOW ),
749     nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
750     nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
751     bFilterButton( sal_True ),
752     bDrillDown( sal_True ),
753     // Wang Xu Ming -- 2009-8-17
754     // DataPilot Migration - Cache&&Performance
755     mnCacheId( -1),
756     // End Comments
757     mbDimensionMembersBuilt(false),
758     mpGrandTotalName(NULL)
759 {
760 }
761 
ScDPSaveData(const ScDPSaveData & r)762 ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
763     nColumnGrandMode( r.nColumnGrandMode ),
764     nRowGrandMode( r.nRowGrandMode ),
765     nIgnoreEmptyMode( r.nIgnoreEmptyMode ),
766     nRepeatEmptyMode( r.nRepeatEmptyMode ),
767     bFilterButton( r.bFilterButton ),
768     bDrillDown( r.bDrillDown ),
769     // Wang Xu Ming -- 2009-8-17
770     // DataPilot Migration - Cache&&Performance
771     mnCacheId(  r.mnCacheId ),
772     // End Comments
773     mbDimensionMembersBuilt(r.mbDimensionMembersBuilt),
774     mpGrandTotalName(NULL)
775 {
776     if ( r.pDimensionData )
777         pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
778     else
779         pDimensionData = NULL;
780 
781     long nCount = r.aDimList.Count();
782     for (long i=0; i<nCount; i++)
783     {
784         ScDPSaveDimension* pNew = new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) );
785         aDimList.Insert( pNew, LIST_APPEND );
786     }
787 
788     if (r.mpGrandTotalName.get())
789         mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
790 }
791 
operator =(const ScDPSaveData & r)792 ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
793 {
794     if ( &r != this )
795     {
796         // Wang Xu Ming -- 2009-8-17
797         // DataPilot Migration - Cache&&Performance
798         this->~ScDPSaveData();
799         new( this ) ScDPSaveData ( r );
800         // End Comments
801     }
802     return *this;
803 }
804 
operator ==(const ScDPSaveData & r) const805 sal_Bool ScDPSaveData::operator== ( const ScDPSaveData& r ) const
806 {
807     if ( nColumnGrandMode != r.nColumnGrandMode ||
808          nRowGrandMode    != r.nRowGrandMode    ||
809          nIgnoreEmptyMode != r.nIgnoreEmptyMode ||
810          nRepeatEmptyMode != r.nRepeatEmptyMode ||
811          bFilterButton    != r.bFilterButton    ||
812          mnCacheId        != r.mnCacheId ||/// Wang Xu Ming -- 2009-6-18 DataPilot Migration
813          bDrillDown       != r.bDrillDown ||
814          mbDimensionMembersBuilt != r.mbDimensionMembersBuilt)
815         return sal_False;
816 
817     if ( pDimensionData || r.pDimensionData )
818         if ( !pDimensionData || !r.pDimensionData || !( *pDimensionData == *r.pDimensionData ) )
819             return sal_False;
820 
821     sal_uLong nCount = aDimList.Count();
822     if ( nCount != r.aDimList.Count() )
823         return sal_False;
824 
825     for (sal_uLong i=0; i<nCount; i++)
826         if ( !( *(ScDPSaveDimension*)aDimList.GetObject(i) ==
827                 *(ScDPSaveDimension*)r.aDimList.GetObject(i) ) )
828             return sal_False;
829 
830     if (mpGrandTotalName.get())
831     {
832         if (!r.mpGrandTotalName.get())
833             return false;
834         if (!mpGrandTotalName->equals(*r.mpGrandTotalName))
835             return false;
836     }
837     else if (r.mpGrandTotalName.get())
838         return false;
839 
840     return sal_True;
841 }
842 
~ScDPSaveData()843 ScDPSaveData::~ScDPSaveData()
844 {
845     long nCount = aDimList.Count();
846     for (long i=0; i<nCount; i++)
847         delete (ScDPSaveDimension*)aDimList.GetObject(i);
848     aDimList.Clear();
849 
850     delete pDimensionData;
851 }
852 
SetGrandTotalName(const OUString & rName)853 void ScDPSaveData::SetGrandTotalName(const OUString& rName)
854 {
855     mpGrandTotalName.reset(new OUString(rName));
856 }
857 
GetGrandTotalName() const858 const OUString* ScDPSaveData::GetGrandTotalName() const
859 {
860     return mpGrandTotalName.get();
861 }
862 
GetDimensionByName(const String & rName)863 ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const String& rName)
864 {
865     long nCount = aDimList.Count();
866     for (long i=0; i<nCount; i++)
867     {
868         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
869         if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
870             return pDim;
871     }
872     ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, sal_False );
873     aDimList.Insert( pNew, LIST_APPEND );
874     mbDimensionMembersBuilt = false;        // BuildAllDimensionMembers only handles existing entries in aDimList
875     return pNew;
876 }
877 
GetExistingDimensionByName(const String & rName) const878 ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const String& rName) const
879 {
880     long nCount = aDimList.Count();
881     for (long i=0; i<nCount; i++)
882     {
883         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
884         if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
885             return pDim;
886     }
887     return NULL;        // don't create new
888 }
889 
GetNewDimensionByName(const String & rName)890 ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const String& rName)
891 {
892     long nCount = aDimList.Count();
893     for (long i=0; i<nCount; i++)
894     {
895         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
896         if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
897             return DuplicateDimension(rName);
898     }
899     ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, sal_False );
900     aDimList.Insert( pNew, LIST_APPEND );
901     mbDimensionMembersBuilt = false;        // BuildAllDimensionMembers only handles existing entries in aDimList
902     return pNew;
903 }
904 
GetDataLayoutDimension()905 ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
906 {
907     ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
908     if (pDim)
909         return pDim;
910 
911     ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), sal_True );
912     aDimList.Insert( pNew, LIST_APPEND );
913     mbDimensionMembersBuilt = false;        // BuildAllDimensionMembers only handles existing entries in aDimList
914     return pNew;
915 }
916 
GetExistingDataLayoutDimension() const917 ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const
918 {
919     long nCount = aDimList.Count();
920     for (long i=0; i<nCount; i++)
921     {
922         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
923         if ( pDim->IsDataLayout() )
924             return pDim;
925     }
926     return NULL;
927 }
928 
DuplicateDimension(const String & rName)929 ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const String& rName)
930 {
931     //  always insert new
932     //! check if dimension is there?
933 
934     ScDPSaveDimension* pOld = GetDimensionByName( rName );
935     ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld );
936     pNew->SetDupFlag( sal_True );
937     aDimList.Insert( pNew, LIST_APPEND );
938     mbDimensionMembersBuilt = false;        // BuildAllDimensionMembers only handles existing entries in aDimList
939     return pNew;
940 }
941 
RemoveDimensionByName(const String & rName)942 void ScDPSaveData::RemoveDimensionByName(const String& rName)
943 {
944     long nCount = aDimList.Count();
945     for (long i=0; i<nCount; i++)
946     {
947         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
948         if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
949         {
950             delete pDim;
951             aDimList.Remove(i);
952             break;
953         }
954     }
955 }
956 
DuplicateDimension(const ScDPSaveDimension & rDim)957 ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rDim )
958 {
959     ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim );
960     pNew->SetDupFlag( sal_True );
961     aDimList.Insert( pNew, LIST_APPEND );
962     mbDimensionMembersBuilt = false;        // BuildAllDimensionMembers only handles existing entries in aDimList
963     return *pNew;
964 }
965 
GetInnermostDimension(sal_uInt16 nOrientation)966 ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(sal_uInt16 nOrientation)
967 {
968     //  return the innermost dimension for the given orientation,
969     //  excluding data layout dimension
970 
971     ScDPSaveDimension* pInner = NULL;
972     long nCount = aDimList.Count();
973     for (long i=0; i<nCount; i++)
974     {
975         ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
976         if ( pDim->GetOrientation() == nOrientation && !pDim->IsDataLayout() )
977             pInner = pDim;
978     }
979     return pInner;      // the last matching one
980 }
981 
GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)982 ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)
983 {
984     long nCount = aDimList.Count();
985     for (long i = 0; i < nCount; ++i)
986     {
987         ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
988         if (pDim->GetOrientation() == eOrientation && !pDim->IsDataLayout())
989             return pDim;
990     }
991     return NULL;
992 }
993 
GetDataDimensionCount() const994 long ScDPSaveData::GetDataDimensionCount() const
995 {
996     long nDataCount = 0;
997 
998     long nCount = aDimList.Count();
999     for (long i=0; i<nCount; i++)
1000     {
1001         const ScDPSaveDimension* pDim = static_cast<const ScDPSaveDimension*>(aDimList.GetObject(i));
1002         if ( pDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA )
1003             ++nDataCount;
1004     }
1005 
1006     return nDataCount;
1007 }
1008 
SetPosition(ScDPSaveDimension * pDim,long nNew)1009 void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
1010 {
1011     //  position (nNew) is counted within dimensions of the same orientation
1012 
1013     sal_uInt16 nOrient = pDim->GetOrientation();
1014 
1015     aDimList.Remove( pDim );
1016     sal_uLong nCount = aDimList.Count();        // after remove
1017 
1018     sal_uLong nInsPos = 0;
1019     while ( nNew > 0 && nInsPos < nCount )
1020     {
1021         if ( ((ScDPSaveDimension*)aDimList.GetObject(nInsPos))->GetOrientation() == nOrient )
1022             --nNew;
1023         ++nInsPos;
1024     }
1025 
1026     aDimList.Insert( pDim, nInsPos );
1027 }
1028 
SetColumnGrand(sal_Bool bSet)1029 void ScDPSaveData::SetColumnGrand(sal_Bool bSet)
1030 {
1031     nColumnGrandMode = bSet;
1032 }
1033 
SetRowGrand(sal_Bool bSet)1034 void ScDPSaveData::SetRowGrand(sal_Bool bSet)
1035 {
1036     nRowGrandMode = bSet;
1037 }
1038 
SetIgnoreEmptyRows(sal_Bool bSet)1039 void ScDPSaveData::SetIgnoreEmptyRows(sal_Bool bSet)
1040 {
1041     nIgnoreEmptyMode = bSet;
1042 }
1043 
SetRepeatIfEmpty(sal_Bool bSet)1044 void ScDPSaveData::SetRepeatIfEmpty(sal_Bool bSet)
1045 {
1046     nRepeatEmptyMode = bSet;
1047 }
1048 
SetFilterButton(sal_Bool bSet)1049 void ScDPSaveData::SetFilterButton(sal_Bool bSet)
1050 {
1051     bFilterButton = bSet;
1052 }
1053 
SetDrillDown(sal_Bool bSet)1054 void ScDPSaveData::SetDrillDown(sal_Bool bSet)
1055 {
1056     bDrillDown = bSet;
1057 }
1058 
lcl_ResetOrient(const uno::Reference<sheet::XDimensionsSupplier> & xSource)1059 void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1060 {
1061     sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN;
1062 
1063     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1064     uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1065     long nIntCount = xIntDims->getCount();
1066     for (long nIntDim=0; nIntDim<nIntCount; nIntDim++)
1067     {
1068         uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1069         uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1070         if (xDimProp.is())
1071         {
1072             uno::Any aAny;
1073             aAny <<= eOrient;
1074             xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
1075         }
1076     }
1077 }
1078 
WriteToSource(const uno::Reference<sheet::XDimensionsSupplier> & xSource)1079 void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1080 {
1081     if (!xSource.is())
1082         return;
1083 
1084     //  source options must be first!
1085 
1086     uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
1087     DBG_ASSERT( xSourceProp.is(), "no properties at source" );
1088     if ( xSourceProp.is() )
1089     {
1090         //  source options are not available for external sources
1091         //! use XPropertySetInfo to test for availability?
1092 
1093         try
1094         {
1095             if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1096                 lcl_SetBoolProperty( xSourceProp,
1097                     rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY), (sal_Bool)nIgnoreEmptyMode );
1098             if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1099                 lcl_SetBoolProperty( xSourceProp,
1100                     rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY), (sal_Bool)nRepeatEmptyMode );
1101         }
1102         catch(uno::Exception&)
1103         {
1104             // no error
1105         }
1106 
1107         const OUString* pGrandTotalName = GetGrandTotalName();
1108         if (pGrandTotalName)
1109             ScUnoHelpFunctions::SetOptionalPropertyValue(xSourceProp, SC_UNO_GRANDTOTAL_NAME, *pGrandTotalName);
1110     }
1111 
1112     // exceptions in the other calls are errors
1113     try
1114     {
1115         //  reset all orientations
1116         //! "forgetSettings" or similar at source ?????
1117         //! reset all duplicated dimensions, or reuse them below !!!
1118         DBG_TRACE( "ScDPSaveData::WriteToSource" );
1119 
1120         lcl_ResetOrient( xSource );
1121 
1122         long nCount = aDimList.Count();
1123         for (long i=0; i<nCount; i++)
1124         {
1125             ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1126             rtl::OUString aName = pDim->GetName();
1127 
1128             DBG_TRACESTR(pDim->GetName());
1129 
1130             sal_Bool bData = pDim->IsDataLayout();
1131 
1132             //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
1133 
1134             uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1135             uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1136             long nIntCount = xIntDims->getCount();
1137             sal_Bool bFound = sal_False;
1138             for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1139             {
1140                 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1141                 if ( bData )
1142                 {
1143                     uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1144                     if ( xDimProp.is() )
1145                     {
1146                         bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
1147                                     rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
1148                         //! error checking -- is "IsDataLayoutDimension" property required??
1149                     }
1150                 }
1151                 else
1152                 {
1153                     uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1154                     if ( xDimName.is() && xDimName->getName() == aName )
1155                         bFound = sal_True;
1156                 }
1157 
1158                 if ( bFound )
1159                 {
1160                     if ( pDim->GetDupFlag() )
1161                     {
1162                         String aNewName = pDim->GetName();
1163 
1164                         // different name for each duplication of a (real) dimension...
1165                         for (long j=0; j<=i; j++)   //! Test !!!!!!
1166                             aNewName += '*';        //! modify name at creation of SaveDimension
1167 
1168                         uno::Reference<util::XCloneable> xCloneable( xIntDim, uno::UNO_QUERY );
1169                         DBG_ASSERT( xCloneable.is(), "cannot clone dimension" );
1170                         if (xCloneable.is())
1171                         {
1172                             uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
1173                             uno::Reference<container::XNamed> xNewName( xNew, uno::UNO_QUERY );
1174                             if (xNewName.is())
1175                             {
1176                                 xNewName->setName( aNewName );
1177                                 pDim->WriteToSource( xNew );
1178                             }
1179                         }
1180                     }
1181                     else
1182                         pDim->WriteToSource( xIntDim );
1183                 }
1184             }
1185             DBG_ASSERT(bFound, "WriteToSource: Dimension not found");
1186         }
1187 
1188         if ( xSourceProp.is() )
1189         {
1190             if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW )
1191                 lcl_SetBoolProperty( xSourceProp,
1192                     rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND), (sal_Bool)nColumnGrandMode );
1193             if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW )
1194                 lcl_SetBoolProperty( xSourceProp,
1195                     rtl::OUString::createFromAscii(DP_PROP_ROWGRAND), (sal_Bool)nRowGrandMode );
1196         }
1197     }
1198     catch(uno::Exception&)
1199     {
1200         DBG_ERROR("exception in WriteToSource");
1201     }
1202 }
1203 
IsEmpty() const1204 sal_Bool ScDPSaveData::IsEmpty() const
1205 {
1206     long nCount = aDimList.Count();
1207     for (long i=0; i<nCount; i++)
1208     {
1209         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1210         if ( pDim->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !pDim->IsDataLayout() )
1211             return sal_False;
1212     }
1213     return sal_True;    // no entries that are not hidden
1214 }
1215 
GetDimensionData()1216 ScDPDimensionSaveData* ScDPSaveData::GetDimensionData()
1217 {
1218     if (!pDimensionData)
1219         pDimensionData = new ScDPDimensionSaveData;
1220     return pDimensionData;
1221 }
1222 
SetDimensionData(const ScDPDimensionSaveData * pNew)1223 void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew )
1224 {
1225     delete pDimensionData;
1226     if ( pNew )
1227         pDimensionData = new ScDPDimensionSaveData( *pNew );
1228     else
1229         pDimensionData = NULL;
1230 }
1231 
BuildAllDimensionMembers(ScDPTableData * pData)1232 void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
1233 {
1234     if (mbDimensionMembersBuilt)
1235         return;
1236 
1237     // First, build a dimension name-to-index map.
1238     typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap;
1239     NameIndexMap aMap;
1240     long nColCount = pData->GetColumnCount();
1241     for (long i = 0; i < nColCount; ++i)
1242         aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i));
1243 
1244     NameIndexMap::const_iterator itrEnd = aMap.end();
1245 
1246     sal_uInt32 n = aDimList.Count();
1247     for (sal_uInt32 i = 0; i < n; ++i)
1248     {
1249         ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1250         const String& rDimName = pDim->GetName();
1251         if (!rDimName.Len())
1252             // empty dimension name.  It must be data layout.
1253             continue;
1254 
1255         NameIndexMap::const_iterator itr = aMap.find(rDimName);
1256         if (itr == itrEnd)
1257             // dimension name not in the data.  This should never happen!
1258             continue;
1259 
1260         long nDimIndex = itr->second;
1261         const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
1262         size_t mMemberCount = rMembers.size();
1263         for (size_t j = 0; j < mMemberCount; ++j)
1264         {
1265             const ScDPItemData* pMemberData = pData->GetMemberById( nDimIndex, rMembers[j] );
1266             String aMemName = pMemberData->GetString();
1267             if (pDim->GetExistingMemberByName(aMemName))
1268                 // this member instance already exists.  nothing to do.
1269                 continue;
1270 
1271             auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName));
1272             pNewMember->SetIsVisible(true);
1273             pDim->AddMember(pNewMember.release());
1274         }
1275     }
1276 
1277     mbDimensionMembersBuilt = true;
1278 }
1279 
BuildAllDimensionMembersFromSource(ScDPObject * pDPObj)1280 void ScDPSaveData::BuildAllDimensionMembersFromSource( ScDPObject* pDPObj )
1281 {
1282     // Initialize all members like BuildAllDimensionMembers, but access only the DataPilotSource, not the table data.
1283     // This could also replace BuildAllDimensionMembers, but the performance implications still have to be checked.
1284     // ScDPObject is used for the helper method GetMemberNames.
1285 
1286     if (mbDimensionMembersBuilt)
1287         return;
1288 
1289     uno::Reference<sheet::XDimensionsSupplier> xSource = pDPObj->GetSource();
1290     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1291     // GetMemberNames uses the dimension index from getElementNames
1292     uno::Sequence<OUString> aDimNames = xDimsName->getElementNames();
1293 
1294     // First, build a dimension name-to-index map.
1295     typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap;
1296     NameIndexMap aMap;
1297     long nColCount = aDimNames.getLength();
1298     for (long i = 0; i < nColCount; ++i)
1299         aMap.insert( NameIndexMap::value_type(aDimNames[i], i) );
1300 
1301     NameIndexMap::const_iterator itrEnd = aMap.end();
1302 
1303     sal_uInt32 n = aDimList.Count();
1304     for (sal_uInt32 i = 0; i < n; ++i)
1305     {
1306         ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1307         const String& rDimName = pDim->GetName();
1308         if (!rDimName.Len())
1309             // empty dimension name.  It must be data layout.
1310             continue;
1311 
1312         NameIndexMap::const_iterator itr = aMap.find(rDimName);
1313         if (itr == itrEnd)
1314             // dimension name not in the data.  This should never happen!
1315             continue;
1316 
1317         long nDimIndex = itr->second;
1318         uno::Sequence<OUString> aMemberNames;
1319         pDPObj->GetMemberNames( nDimIndex, aMemberNames );
1320         sal_Int32 nMemberCount = aMemberNames.getLength();
1321         for (sal_Int32 j = 0; j < nMemberCount; ++j)
1322         {
1323             String aMemName = aMemberNames[j];
1324             if (pDim->GetExistingMemberByName(aMemName))
1325                 // this member instance already exists.  nothing to do.
1326                 continue;
1327 
1328             auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName));
1329             pNewMember->SetIsVisible(true);
1330             pDim->AddMember(pNewMember.release());
1331         }
1332     }
1333 
1334     mbDimensionMembersBuilt = true;
1335 }
1336 
HasInvisibleMember(const OUString & rDimName) const1337 bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const
1338 {
1339     ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName);
1340     if (!pDim)
1341         return false;
1342 
1343     return pDim->HasInvisibleMember();
1344 }
1345 
Refresh(const uno::Reference<sheet::XDimensionsSupplier> & xSource)1346 void ScDPSaveData::Refresh( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1347 {
1348     try
1349     {
1350         long nCount = aDimList.Count();
1351         std::list<String> deletedDims;
1352         for (long i=nCount-1; i >=0 ; i--)
1353         {
1354             ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1355 
1356             rtl::OUString aName = pDim->GetName();
1357             if ( pDim->IsDataLayout() )
1358                 continue;
1359 
1360             uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1361             uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1362             long nIntCount = xIntDims->getCount();
1363             sal_Bool bFound = sal_False;
1364             for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1365             {
1366                 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1367                 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1368                 if ( xDimName.is() && xDimName->getName() == aName )
1369                     bFound = sal_True;
1370             }
1371             if ( !bFound )
1372             {
1373                 deletedDims.push_back( aName );
1374                 aDimList.Remove(i);
1375                 DBG_TRACE( "\n Remove dim: \t" );
1376                 DBG_TRACESTR(  String( aName ) );
1377             }
1378 
1379         }
1380 
1381         nCount = aDimList.Count();
1382         for (long  i=nCount-1; i >=0 ; i--) //check every dimension ??
1383         {
1384             ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1385 
1386             rtl::OUString aName = pDim->GetName();
1387             if ( pDim->IsDataLayout() )
1388                 continue;
1389             pDim->Refresh( xSource, deletedDims );
1390 
1391         }
1392 
1393         mbDimensionMembersBuilt = false;    // there may be new members
1394     }
1395     catch(uno::Exception&)
1396     {
1397         DBG_ERROR("error in ScDPSaveData::Refresh");
1398     }
1399 
1400 }
Refresh(const com::sun::star::uno::Reference<com::sun::star::sheet::XDimensionsSupplier> & xSource,const std::list<String> & deletedDims)1401 void ScDPSaveDimension::Refresh( const com::sun::star::uno::Reference<
1402                                 com::sun::star::sheet::XDimensionsSupplier>& xSource ,
1403                                 const std::list<String>& deletedDims)
1404 {
1405     if ( xSource.is() )
1406     {
1407         ScDPSource* pTabSource = static_cast<ScDPSource*>( xSource.get() );
1408         ScDPTableDataCache*  pCache = pTabSource->GetCache();
1409         if ( pCache->GetId() == -1 )
1410             return;
1411 
1412         SCCOL nSrcDim = pCache->GetDimensionIndex( GetName() );
1413 
1414         if ( nSrcDim == -1 )
1415             return;
1416         if ( pSelectedPage )
1417         {//check pSelected page
1418             DBG_TRACESTR( (*pSelectedPage) );
1419             if ( pCache->GetIdByItemData( nSrcDim, *pSelectedPage ) == -1 )
1420             {
1421                 delete pSelectedPage;
1422                 pSelectedPage = NULL;
1423             }
1424 
1425         };
1426 
1427         if ( pReferenceValue && pReferenceValue->ReferenceItemType == DataPilotFieldReferenceItemType::NAMED )
1428         {//check pReferenceValue
1429 #ifdef DEBUG
1430             switch( pReferenceValue->ReferenceType)
1431             {
1432             case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE: //both
1433                 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE \n" );
1434                 break;
1435             case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE: //both
1436                 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE \n" );
1437                 break;
1438             case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE: //both
1439                 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE \n" );
1440                 break;
1441             case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL:
1442                 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::RUNNING_TOTAL \n" ); //enable name
1443                 break;
1444             }
1445 #endif
1446             switch( pReferenceValue->ReferenceType)
1447             {
1448             case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE:
1449             case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE:
1450             case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
1451             case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL:
1452                 {
1453                     if( pReferenceValue->ReferenceItemType == DataPilotFieldReferenceItemType::NAMED  )
1454                     {
1455                         const String& sReferenceFieldName = pReferenceValue->ReferenceField;
1456                         DBG_TRACESTR( sReferenceFieldName );
1457                         SCCOL nRefDim = pCache->GetDimensionIndex( sReferenceFieldName );
1458                         bool bValid = true;
1459                         if ( nRefDim == -1 )
1460                             bValid = false;
1461                         else if ( pReferenceValue->ReferenceType != sheet::DataPilotFieldReferenceType::RUNNING_TOTAL )
1462                         { //running total has not reference item
1463                             const String& sReferenceItemName = pReferenceValue->ReferenceItemName;
1464                             DBG_TRACESTR( sReferenceItemName );
1465                             if ( pCache->GetIdByItemData( nRefDim, sReferenceItemName ) == -1 )
1466                                 bValid = false;
1467                         }
1468                         if ( !bValid )
1469                         {
1470                             delete pReferenceValue;
1471                             pReferenceValue = NULL;
1472                         }
1473                     }
1474                 }
1475                 break;
1476             }
1477 
1478         };
1479 
1480         if ( pSortInfo )
1481         { //check sortinfo
1482             if ( pSortInfo->Mode == DataPilotFieldSortMode::DATA )
1483             {
1484                 DBG_TRACE( "\n DataPilotFieldSortMode::DATA \n" );
1485                 const String& sFieldDimName = pSortInfo->Field;
1486                 std::list<String>::const_iterator iter = std::find( deletedDims.begin(), deletedDims.end(), sFieldDimName );
1487                 if ( iter != deletedDims.end() && pCache->GetDimensionIndex( sFieldDimName ) == -1  )
1488                 {
1489                     pSortInfo->Mode = DataPilotFieldSortMode::MANUAL;
1490                     pSortInfo->Field = GetName();
1491                 }
1492             }
1493 
1494         };
1495 
1496         if ( pAutoShowInfo )
1497         { //check autoshow
1498             const String& sFieldDimName = pAutoShowInfo->DataField;
1499             std::list<String>::const_iterator iter = std::find( deletedDims.begin(), deletedDims.end(), sFieldDimName );
1500             if ( iter != deletedDims.end() && pCache->GetDimensionIndex( sFieldDimName ) == -1  )
1501             {
1502                 delete pAutoShowInfo;
1503                 pAutoShowInfo = NULL;
1504             }
1505 
1506         };
1507 
1508         //remove unused members
1509         for (MemberList::iterator i=maMemberList.begin(); i != maMemberList.end() ; )
1510         {
1511             rtl::OUString aMemberName = (*i)->GetName();
1512             if ( pCache->GetIdByItemData( nSrcDim, aMemberName ) == -1 )
1513                 i = maMemberList.erase( i );
1514             else
1515                 i++;
1516         }
1517     }
1518 }
1519 // End Comments
operator ==(const::com::sun::star::sheet::DataPilotFieldSortInfo & l,const::com::sun::star::sheet::DataPilotFieldSortInfo & r)1520 bool operator == (const ::com::sun::star::sheet::DataPilotFieldSortInfo &l, const ::com::sun::star::sheet::DataPilotFieldSortInfo &r )
1521 {
1522     return l.Field == r.Field && l.IsAscending == r.IsAscending && l.Mode == r.Mode;
1523 }
operator ==(const::com::sun::star::sheet::DataPilotFieldAutoShowInfo & l,const::com::sun::star::sheet::DataPilotFieldAutoShowInfo & r)1524 bool operator == (const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &l, const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &r )
1525 {
1526     return l.IsEnabled == r.IsEnabled &&
1527         l.ShowItemsMode == r.ShowItemsMode &&
1528         l.ItemCount == r.ItemCount &&
1529         l.DataField == r.DataField;
1530 }
operator ==(const::com::sun::star::sheet::DataPilotFieldReference & l,const::com::sun::star::sheet::DataPilotFieldReference & r)1531 bool operator == (const ::com::sun::star::sheet::DataPilotFieldReference &l, const ::com::sun::star::sheet::DataPilotFieldReference &r )
1532 {
1533     return l.ReferenceType == r.ReferenceType &&
1534         l.ReferenceField == r.ReferenceField &&
1535         l.ReferenceItemType == r.ReferenceItemType &&
1536         l.ReferenceItemName == r.ReferenceItemName;
1537 }
1538 
1539