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