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