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