xref: /trunk/main/sc/source/core/data/dpsave.cxx (revision 3d762826)
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