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