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 158 : 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 158 : xProp->setPropertyValue( rName, uno::Any( &bValue, getBooleanCppuType() ) );
71 158 : }
72 :
73 33 : ScDPSaveMember::ScDPSaveMember(const ::rtl::OUString& rName) :
74 : aName( rName ),
75 : mpLayoutName(NULL),
76 : nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
77 33 : nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
78 : {
79 33 : }
80 :
81 60 : ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
82 : aName( r.aName ),
83 : mpLayoutName(NULL),
84 : nVisibleMode( r.nVisibleMode ),
85 60 : nShowDetailsMode( r.nShowDetailsMode )
86 : {
87 60 : if (r.mpLayoutName)
88 0 : mpLayoutName.reset(new OUString(*r.mpLayoutName));
89 60 : }
90 :
91 75 : ScDPSaveMember::~ScDPSaveMember()
92 : {
93 75 : }
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 37 : void ScDPSaveMember::SetIsVisible(bool bSet)
111 : {
112 37 : nVisibleMode = bSet;
113 37 : }
114 :
115 0 : bool ScDPSaveMember::HasShowDetails() const
116 : {
117 0 : return nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW;
118 : }
119 :
120 18 : void ScDPSaveMember::SetShowDetails(bool bSet)
121 : {
122 18 : nShowDetailsMode = bSet;
123 18 : }
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 33 : void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
149 : {
150 33 : uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
151 : OSL_ENSURE( xMembProp.is(), "no properties at member" );
152 33 : if ( xMembProp.is() )
153 : {
154 : // exceptions are caught at ScDPSaveData::WriteToSource
155 :
156 33 : if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW )
157 : lcl_SetBoolProperty( xMembProp,
158 33 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_ISVISIBLE)), (bool)nVisibleMode );
159 :
160 33 : if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW )
161 : lcl_SetBoolProperty( xMembProp,
162 0 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_SHOWDETAILS)), (bool)nShowDetailsMode );
163 :
164 33 : if (mpLayoutName)
165 0 : ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_DP_LAYOUTNAME, *mpLayoutName);
166 :
167 33 : if ( nPosition >= 0 )
168 7 : ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_DP_POSITION, nPosition);
169 33 : }
170 33 : }
171 :
172 61 : 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 61 : pLayoutInfo( NULL )
189 : {
190 61 : }
191 :
192 82 : 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 82 : pSubTotalFuncs( NULL )
205 : {
206 82 : if ( nSubTotalCount && r.pSubTotalFuncs )
207 : {
208 0 : pSubTotalFuncs = new sal_uInt16[nSubTotalCount];
209 0 : for (long nSub=0; nSub<nSubTotalCount; nSub++)
210 0 : pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub];
211 : }
212 :
213 142 : for (MemberList::const_iterator i=r.maMemberList.begin(); i != r.maMemberList.end() ; ++i)
214 : {
215 60 : const ::rtl::OUString& rName = (*i)->GetName();
216 60 : ScDPSaveMember* pNew = new ScDPSaveMember( **i );
217 60 : maMemberHash[rName] = pNew;
218 60 : maMemberList.push_back( pNew );
219 : }
220 82 : if (r.pReferenceValue)
221 0 : pReferenceValue = new sheet::DataPilotFieldReference( *(r.pReferenceValue) );
222 : else
223 82 : pReferenceValue = NULL;
224 82 : if (r.pSortInfo)
225 39 : pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) );
226 : else
227 43 : pSortInfo = NULL;
228 82 : if (r.pAutoShowInfo)
229 39 : pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) );
230 : else
231 43 : pAutoShowInfo = NULL;
232 82 : if (r.pLayoutInfo)
233 39 : pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
234 : else
235 43 : pLayoutInfo = NULL;
236 82 : if (r.mpLayoutName)
237 0 : mpLayoutName.reset(new OUString(*r.mpLayoutName));
238 82 : if (r.mpSubtotalName)
239 0 : mpSubtotalName.reset(new OUString(*r.mpSubtotalName));
240 82 : }
241 :
242 270 : ScDPSaveDimension::~ScDPSaveDimension()
243 : {
244 210 : for (MemberHash::const_iterator i=maMemberHash.begin(); i != maMemberHash.end() ; ++i)
245 75 : delete i->second;
246 135 : delete pReferenceValue;
247 135 : delete pSortInfo;
248 135 : delete pAutoShowInfo;
249 135 : delete pLayoutInfo;
250 135 : delete [] pSubTotalFuncs;
251 135 : }
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 32 : void ScDPSaveDimension::AddMember(ScDPSaveMember* pMember)
321 : {
322 32 : const ::rtl::OUString & rName = pMember->GetName();
323 32 : MemberHash::iterator aExisting = maMemberHash.find( rName );
324 32 : if ( aExisting == maMemberHash.end() )
325 : {
326 32 : std::pair< const ::rtl::OUString, ScDPSaveMember *> key( rName, pMember );
327 32 : 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 32 : maMemberList.push_back( pMember );
336 32 : }
337 :
338 1 : 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 1 : aName = rNew;
344 1 : }
345 :
346 63 : void ScDPSaveDimension::SetOrientation(sal_uInt16 nNew)
347 : {
348 63 : nOrientation = nNew;
349 63 : }
350 :
351 0 : void ScDPSaveDimension::SetSubTotals(long nCount, const sal_uInt16* pFuncs)
352 : {
353 0 : if (pSubTotalFuncs)
354 0 : delete [] pSubTotalFuncs;
355 0 : nSubTotalCount = nCount;
356 0 : if ( nCount && pFuncs )
357 : {
358 0 : pSubTotalFuncs = new sal_uInt16[nCount];
359 0 : for (long i=0; i<nCount; i++)
360 0 : pSubTotalFuncs[i] = pFuncs[i];
361 : }
362 : else
363 0 : pSubTotalFuncs = NULL;
364 :
365 0 : bSubTotalDefault = false;
366 0 : }
367 :
368 0 : bool ScDPSaveDimension::HasShowEmpty() const
369 : {
370 0 : return nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW;
371 : }
372 :
373 22 : void ScDPSaveDimension::SetShowEmpty(bool bSet)
374 : {
375 22 : nShowEmptyMode = bSet;
376 22 : }
377 :
378 24 : void ScDPSaveDimension::SetFunction(sal_uInt16 nNew)
379 : {
380 24 : nFunction = nNew;
381 24 : }
382 :
383 45 : void ScDPSaveDimension::SetUsedHierarchy(long nNew)
384 : {
385 45 : nUsedHierarchy = nNew;
386 45 : }
387 :
388 0 : void ScDPSaveDimension::SetSubtotalName(const OUString& rName)
389 : {
390 0 : mpSubtotalName.reset(new OUString(rName));
391 0 : }
392 :
393 101 : const OUString* ScDPSaveDimension::GetSubtotalName() const
394 : {
395 101 : 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 0 : const OUString* ScDPSaveDimension::GetLayoutName() const
425 : {
426 0 : return mpLayoutName.get();
427 : }
428 :
429 0 : void ScDPSaveDimension::RemoveLayoutName()
430 : {
431 0 : mpLayoutName.reset(NULL);
432 0 : }
433 :
434 16 : void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
435 : {
436 16 : delete pReferenceValue;
437 16 : if (pNew)
438 0 : pReferenceValue = new sheet::DataPilotFieldReference(*pNew);
439 : else
440 16 : pReferenceValue = NULL;
441 16 : }
442 :
443 28 : void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew)
444 : {
445 28 : delete pSortInfo;
446 28 : if (pNew)
447 28 : pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew);
448 : else
449 0 : pSortInfo = NULL;
450 28 : }
451 :
452 28 : void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew)
453 : {
454 28 : delete pAutoShowInfo;
455 28 : if (pNew)
456 28 : pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew);
457 : else
458 0 : pAutoShowInfo = NULL;
459 28 : }
460 :
461 28 : void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew)
462 : {
463 28 : delete pLayoutInfo;
464 28 : if (pNew)
465 28 : pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew);
466 : else
467 0 : pLayoutInfo = NULL;
468 28 : }
469 :
470 2 : 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 2 : MemberList::iterator it = maMemberList.begin(), itEnd = maMemberList.end();
476 6 : for (; it != itEnd; ++it)
477 : {
478 4 : ScDPSaveMember* pMem = *it;
479 4 : bool bVisible = !pPage || pMem->GetName() == *pPage;
480 4 : pMem->SetIsVisible(bVisible);
481 : }
482 2 : }
483 :
484 14 : ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const ::rtl::OUString& rName)
485 : {
486 14 : MemberHash::const_iterator res = maMemberHash.find (rName);
487 14 : if (res != maMemberHash.end())
488 0 : return res->second;
489 14 : return NULL;
490 : }
491 :
492 1 : ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const ::rtl::OUString& rName)
493 : {
494 1 : MemberHash::const_iterator res = maMemberHash.find (rName);
495 1 : if (res != maMemberHash.end())
496 0 : return res->second;
497 :
498 1 : ScDPSaveMember* pNew = new ScDPSaveMember( rName );
499 1 : maMemberHash[rName] = pNew;
500 1 : maMemberList.push_back( pNew );
501 1 : 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 101 : void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim )
517 : {
518 101 : uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
519 : OSL_ENSURE( xDimProp.is(), "no properties at dimension" );
520 101 : if ( xDimProp.is() )
521 : {
522 : // exceptions are caught at ScDPSaveData::WriteToSource
523 101 : uno::Any aAny;
524 :
525 101 : sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
526 101 : aAny <<= eOrient;
527 101 : xDimProp->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_ORIENTATION)), aAny );
528 :
529 101 : sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
530 101 : aAny <<= eFunc;
531 101 : xDimProp->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_FUNCTION)), aAny );
532 :
533 101 : if ( nUsedHierarchy >= 0 )
534 : {
535 70 : aAny <<= (sal_Int32)nUsedHierarchy;
536 70 : xDimProp->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_USEDHIERARCHY)), aAny );
537 : }
538 :
539 101 : if ( pReferenceValue )
540 : {
541 0 : aAny <<= *pReferenceValue;
542 0 : xDimProp->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_REFVALUE)), aAny );
543 : }
544 :
545 101 : if (mpLayoutName)
546 0 : ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_LAYOUTNAME, *mpLayoutName);
547 :
548 101 : const OUString* pSubTotalName = GetSubtotalName();
549 101 : 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 101 : long nCount = maMemberHash.size();
558 :
559 101 : long nHierCount = 0;
560 101 : uno::Reference<container::XIndexAccess> xHiers;
561 101 : uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
562 101 : if ( xHierSupp.is() )
563 : {
564 101 : uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
565 101 : xHiers = new ScNameToIndexAccess( xHiersName );
566 101 : nHierCount = xHiers->getCount();
567 : }
568 :
569 101 : bool bHasHiddenMember = false;
570 :
571 202 : for (long nHier=0; nHier<nHierCount; nHier++)
572 : {
573 101 : uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
574 :
575 101 : long nLevCount = 0;
576 101 : uno::Reference<container::XIndexAccess> xLevels;
577 101 : uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
578 101 : if ( xLevSupp.is() )
579 : {
580 101 : uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
581 101 : xLevels = new ScNameToIndexAccess( xLevelsName );
582 101 : nLevCount = xLevels->getCount();
583 : }
584 :
585 202 : for (long nLev=0; nLev<nLevCount; nLev++)
586 : {
587 101 : uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) );
588 101 : uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
589 : OSL_ENSURE( xLevProp.is(), "no properties at level" );
590 101 : if ( xLevProp.is() )
591 : {
592 101 : uno::Any aAny;
593 101 : if ( !bSubTotalDefault )
594 : {
595 0 : if ( !pSubTotalFuncs )
596 0 : nSubTotalCount = 0;
597 :
598 0 : uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount);
599 0 : sheet::GeneralFunction* pArray = aSeq.getArray();
600 0 : for (long i=0; i<nSubTotalCount; i++)
601 0 : pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i];
602 0 : aAny <<= aSeq;
603 0 : xLevProp->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_SUBTOTAL)), aAny );
604 : }
605 101 : if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW )
606 : lcl_SetBoolProperty( xLevProp,
607 25 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_SHOWEMPTY)), (bool)nShowEmptyMode );
608 :
609 101 : if ( pSortInfo )
610 39 : ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_SORTING, *pSortInfo);
611 :
612 101 : if ( pAutoShowInfo )
613 39 : ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_AUTOSHOW, *pAutoShowInfo);
614 :
615 101 : if ( pLayoutInfo )
616 39 : ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_DP_LAYOUT, *pLayoutInfo);
617 :
618 : // exceptions are caught at ScDPSaveData::WriteToSource
619 : }
620 :
621 101 : if ( nCount > 0 )
622 : {
623 16 : uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
624 16 : if ( xMembSupp.is() )
625 : {
626 16 : uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
627 16 : if ( xMembers.is() )
628 : {
629 16 : sal_Int32 nPosition = -1; // set position only in manual mode
630 16 : if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL )
631 7 : nPosition = 0;
632 :
633 59 : for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; ++i)
634 : {
635 43 : ScDPSaveMember* pMember = *i;
636 43 : if (!pMember->GetIsVisible())
637 3 : bHasHiddenMember = true;
638 43 : rtl::OUString aMemberName = pMember->GetName();
639 43 : if ( xMembers->hasByName( aMemberName ) )
640 : {
641 : uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
642 33 : xMembers->getByName( aMemberName ) );
643 33 : pMember->WriteToSource( xMemberInt, nPosition );
644 :
645 33 : if ( nPosition >= 0 )
646 7 : ++nPosition; // increase if initialized
647 : }
648 : // missing member is no error
649 43 : }
650 16 : }
651 16 : }
652 : }
653 101 : }
654 101 : }
655 :
656 101 : if (xDimProp.is())
657 101 : ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_DP_HAS_HIDDEN_MEMBER, bHasHiddenMember);
658 101 : }
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 6 : bool ScDPSaveDimension::HasInvisibleMember() const
675 : {
676 6 : MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
677 14 : for (; itrMem != itrMemEnd; ++itrMem)
678 : {
679 8 : const ScDPSaveMember* pMem = *itrMem;
680 8 : if (!pMem->GetIsVisible())
681 0 : return true;
682 : }
683 6 : return false;
684 : }
685 :
686 0 : void ScDPSaveDimension::RemoveObsoleteMembers(const MemberSetType& rMembers)
687 : {
688 0 : maMemberHash.clear();
689 0 : MemberList aNew;
690 0 : MemberList::iterator it = maMemberList.begin(), itEnd = maMemberList.end();
691 0 : 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 0 : maMemberList.swap(aNew);
708 0 : }
709 :
710 20 : 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 20 : mpGrandTotalName(NULL)
720 : {
721 20 : }
722 :
723 19 : 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 19 : mpGrandTotalName(NULL)
732 : {
733 19 : if ( r.pDimensionData )
734 0 : pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
735 : else
736 19 : pDimensionData = NULL;
737 :
738 19 : aDimList = r.aDimList.clone();
739 :
740 19 : if (r.mpGrandTotalName)
741 0 : mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
742 19 : }
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 66 : ScDPSaveData::~ScDPSaveData()
789 : {
790 33 : delete pDimensionData;
791 33 : }
792 :
793 0 : void ScDPSaveData::SetGrandTotalName(const OUString& rName)
794 : {
795 0 : mpGrandTotalName.reset(new OUString(rName));
796 0 : }
797 :
798 25 : const OUString* ScDPSaveData::GetGrandTotalName() const
799 : {
800 25 : return mpGrandTotalName.get();
801 : }
802 :
803 0 : const ScDPSaveData::DimsType& ScDPSaveData::GetDimensions() const
804 : {
805 0 : return aDimList;
806 : }
807 :
808 7 : void ScDPSaveData::GetAllDimensionsByOrientation(
809 : sheet::DataPilotFieldOrientation eOrientation, std::vector<const ScDPSaveDimension*>& rDims) const
810 : {
811 7 : std::vector<const ScDPSaveDimension*> aDims;
812 7 : DimsType::const_iterator it = aDimList.begin(), itEnd = aDimList.end();
813 63 : for (; it != itEnd; ++it)
814 : {
815 56 : const ScDPSaveDimension& rDim = *it;
816 56 : if (rDim.GetOrientation() != static_cast<sal_uInt16>(eOrientation))
817 41 : continue;
818 :
819 15 : aDims.push_back(&rDim);
820 : }
821 :
822 7 : rDims.swap(aDims);
823 7 : }
824 :
825 9 : void ScDPSaveData::AddDimension(ScDPSaveDimension* pDim)
826 : {
827 9 : if (!pDim)
828 9 : return;
829 :
830 9 : CheckDuplicateName(*pDim);
831 9 : aDimList.push_back(pDim);
832 : }
833 :
834 5 : ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const ::rtl::OUString& rName)
835 : {
836 5 : boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
837 17 : for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
838 : {
839 14 : if (iter->GetName() == rName && !iter->IsDataLayout() )
840 2 : return const_cast<ScDPSaveDimension*>(&(*iter));
841 : }
842 :
843 3 : return AppendNewDimension(rName, false);
844 : }
845 :
846 8 : ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const ::rtl::OUString& rName) const
847 : {
848 8 : boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
849 31 : for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
850 : {
851 24 : if (iter->GetName() == rName && !iter->IsDataLayout() )
852 1 : return const_cast<ScDPSaveDimension*>(&(*iter));
853 : }
854 7 : return NULL; // don't create new
855 : }
856 :
857 37 : ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const ::rtl::OUString& rName)
858 : {
859 37 : boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
860 71 : for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
861 : {
862 35 : if (iter->GetName() == rName && !iter->IsDataLayout() )
863 1 : return DuplicateDimension(rName);
864 : }
865 :
866 36 : return AppendNewDimension(rName, false);
867 : }
868 :
869 15 : ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
870 : {
871 15 : ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
872 15 : if (pDim)
873 1 : return pDim;
874 :
875 14 : return AppendNewDimension(rtl::OUString(), true);
876 : }
877 :
878 16 : ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const
879 : {
880 16 : boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
881 62 : for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
882 : {
883 48 : if ( iter->IsDataLayout() )
884 2 : return const_cast<ScDPSaveDimension*>(&(*iter));
885 : }
886 14 : return NULL;
887 : }
888 :
889 1 : ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const ::rtl::OUString& rName)
890 : {
891 : // always insert new
892 :
893 1 : ScDPSaveDimension* pOld = GetExistingDimensionByName(rName);
894 1 : if (!pOld)
895 0 : return NULL;
896 :
897 1 : ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld );
898 1 : AddDimension(pNew);
899 1 : return pNew;
900 : }
901 :
902 2 : void ScDPSaveData::RemoveDimensionByName(const ::rtl::OUString& rName)
903 : {
904 2 : boost::ptr_vector<ScDPSaveDimension>::iterator iter;
905 6 : for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
906 : {
907 3 : if (iter->GetName() != rName || iter->IsDataLayout())
908 1 : continue;
909 :
910 2 : aDimList.erase(iter);
911 2 : RemoveDuplicateNameCount(rName);
912 2 : 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 3 : void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
964 : {
965 : // position (nNew) is counted within dimensions of the same orientation
966 :
967 3 : sal_uInt16 nOrient = pDim->GetOrientation();
968 :
969 3 : boost::ptr_vector<ScDPSaveDimension>::iterator it;
970 13 : for ( it = aDimList.begin(); it != aDimList.end(); ++it)
971 : {
972 13 : 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 3 : aDimList.release(it).release();
978 3 : break;
979 : }
980 : }
981 :
982 3 : boost::ptr_vector<ScDPSaveDimension>::iterator iterInsert = aDimList.begin();
983 6 : while ( nNew > 0 && iterInsert != aDimList.end())
984 : {
985 0 : if (iterInsert->GetOrientation() == nOrient )
986 0 : --nNew;
987 :
988 0 : ++iterInsert;
989 : }
990 :
991 3 : aDimList.insert(iterInsert,pDim);
992 3 : }
993 :
994 15 : void ScDPSaveData::SetColumnGrand(bool bSet)
995 : {
996 15 : nColumnGrandMode = bSet;
997 15 : }
998 :
999 15 : void ScDPSaveData::SetRowGrand(bool bSet)
1000 : {
1001 15 : nRowGrandMode = bSet;
1002 15 : }
1003 :
1004 16 : void ScDPSaveData::SetIgnoreEmptyRows(bool bSet)
1005 : {
1006 16 : nIgnoreEmptyMode = bSet;
1007 16 : }
1008 :
1009 15 : void ScDPSaveData::SetRepeatIfEmpty(bool bSet)
1010 : {
1011 15 : nRepeatEmptyMode = bSet;
1012 15 : }
1013 :
1014 15 : void ScDPSaveData::SetFilterButton(bool bSet)
1015 : {
1016 15 : bFilterButton = bSet;
1017 15 : }
1018 :
1019 15 : void ScDPSaveData::SetDrillDown(bool bSet)
1020 : {
1021 15 : bDrillDown = bSet;
1022 15 : }
1023 :
1024 25 : static void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1025 : {
1026 25 : sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN;
1027 :
1028 25 : uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1029 25 : uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1030 25 : long nIntCount = xIntDims->getCount();
1031 126 : for (long nIntDim=0; nIntDim<nIntCount; nIntDim++)
1032 : {
1033 101 : uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1034 101 : uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1035 101 : if (xDimProp.is())
1036 : {
1037 101 : uno::Any aAny;
1038 101 : aAny <<= eOrient;
1039 101 : xDimProp->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_ORIENTATION)), aAny );
1040 : }
1041 126 : }
1042 25 : }
1043 :
1044 25 : void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1045 : {
1046 25 : if (!xSource.is())
1047 25 : return;
1048 :
1049 : // source options must be first!
1050 :
1051 25 : uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
1052 : OSL_ENSURE( xSourceProp.is(), "no properties at source" );
1053 25 : 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 25 : if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1061 : lcl_SetBoolProperty( xSourceProp,
1062 25 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_IGNOREEMPTY)), (bool)nIgnoreEmptyMode );
1063 25 : if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1064 : lcl_SetBoolProperty( xSourceProp,
1065 25 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_REPEATEMPTY)), (bool)nRepeatEmptyMode );
1066 : }
1067 0 : catch(uno::Exception&)
1068 : {
1069 : // no error
1070 : }
1071 :
1072 25 : const OUString* pGrandTotalName = GetGrandTotalName();
1073 25 : 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 25 : lcl_ResetOrient( xSource );
1086 :
1087 25 : uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1088 25 : uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1089 25 : long nIntCount = xIntDims->getCount();
1090 :
1091 25 : boost::ptr_vector<ScDPSaveDimension>::iterator iter = aDimList.begin();
1092 126 : for (long i = 0; iter != aDimList.end(); ++iter, ++i)
1093 : {
1094 101 : rtl::OUString aName = iter->GetName();
1095 101 : rtl::OUString aCoreName = ScDPUtil::getSourceDimensionName(aName);
1096 :
1097 : OSL_TRACE( "%s", aName.getStr() );
1098 :
1099 101 : bool bData = iter->IsDataLayout();
1100 :
1101 : //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
1102 :
1103 101 : bool bFound = false;
1104 369 : for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1105 : {
1106 268 : uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1107 268 : if ( bData )
1108 : {
1109 101 : uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1110 101 : if ( xDimProp.is() )
1111 : {
1112 : bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
1113 101 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_ISDATALAYOUT)) );
1114 : //! error checking -- is "IsDataLayoutDimension" property required??
1115 101 : }
1116 : }
1117 : else
1118 : {
1119 167 : uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1120 167 : if (xDimName.is() && xDimName->getName() == aCoreName)
1121 76 : bFound = true;
1122 : }
1123 :
1124 268 : if (bFound)
1125 : {
1126 101 : if (iter->GetDupFlag())
1127 : {
1128 2 : uno::Reference<util::XCloneable> xCloneable(xIntDim, uno::UNO_QUERY);
1129 : OSL_ENSURE(xCloneable.is(), "cannot clone dimension");
1130 2 : if (xCloneable.is())
1131 : {
1132 2 : uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
1133 2 : uno::Reference<container::XNamed> xNewName(xNew, uno::UNO_QUERY);
1134 2 : if (xNewName.is())
1135 : {
1136 2 : xNewName->setName(aName);
1137 2 : iter->WriteToSource(xNew);
1138 2 : }
1139 2 : }
1140 : }
1141 : else
1142 99 : iter->WriteToSource( xIntDim );
1143 : }
1144 268 : }
1145 : OSL_ENSURE(bFound, "WriteToSource: Dimension not found");
1146 101 : }
1147 :
1148 25 : if ( xSourceProp.is() )
1149 : {
1150 25 : if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW )
1151 : lcl_SetBoolProperty( xSourceProp,
1152 25 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_COLGRAND)), (bool)nColumnGrandMode );
1153 25 : if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW )
1154 : lcl_SetBoolProperty( xSourceProp,
1155 25 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DP_ROWGRAND)), (bool)nRowGrandMode );
1156 25 : }
1157 : }
1158 0 : catch(uno::Exception&)
1159 : {
1160 : OSL_FAIL("exception in WriteToSource");
1161 25 : }
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 1 : void ScDPSaveData::RemoveAllGroupDimensions( const OUString& rSrcDimName, std::vector<OUString>* pDeletedNames )
1176 : {
1177 1 : if (!pDimensionData)
1178 : // No group dimensions exist. Nothing to do.
1179 1 : 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 1 : 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 1 : const ScDPSaveGroupDimension* pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
1189 4 : while ( pExistingGroup )
1190 : {
1191 2 : rtl::OUString aGroupDimName = pExistingGroup->GetGroupDimName();
1192 2 : pDimensionData->RemoveGroupDimension(aGroupDimName); // pExistingGroup is deleted
1193 :
1194 : // also remove SaveData settings for the dimension that no longer exists
1195 2 : RemoveDimensionByName(aGroupDimName);
1196 :
1197 2 : if (pDeletedNames)
1198 0 : pDeletedNames->push_back(aGroupDimName);
1199 :
1200 : // see if there are more group dimensions
1201 2 : pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
1202 :
1203 2 : 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 2 : }
1210 : }
1211 :
1212 4 : ScDPDimensionSaveData* ScDPSaveData::GetDimensionData()
1213 : {
1214 4 : if (!pDimensionData)
1215 3 : pDimensionData = new ScDPDimensionSaveData;
1216 4 : 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 1 : void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
1229 : {
1230 1 : if (mbDimensionMembersBuilt)
1231 1 : return;
1232 :
1233 : // First, build a dimension name-to-index map.
1234 : typedef boost::unordered_map<OUString, long, ::rtl::OUStringHash> NameIndexMap;
1235 1 : NameIndexMap aMap;
1236 1 : long nColCount = pData->GetColumnCount();
1237 6 : for (long i = 0; i < nColCount; ++i)
1238 5 : aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i));
1239 :
1240 1 : NameIndexMap::const_iterator itrEnd = aMap.end();
1241 :
1242 1 : boost::ptr_vector<ScDPSaveDimension>::iterator iter;
1243 7 : for (iter = aDimList.begin(); iter != aDimList.end(); ++iter)
1244 : {
1245 6 : const ::rtl::OUString& rDimName = iter->GetName();
1246 6 : if (rDimName.isEmpty())
1247 : // empty dimension name. It must be data layout.
1248 1 : continue;
1249 :
1250 5 : NameIndexMap::const_iterator itr = aMap.find(rDimName);
1251 5 : if (itr == itrEnd)
1252 : // dimension name not in the data. This should never happen!
1253 0 : continue;
1254 :
1255 5 : long nDimIndex = itr->second;
1256 5 : const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
1257 5 : size_t mMemberCount = rMembers.size();
1258 19 : for (size_t j = 0; j < mMemberCount; ++j)
1259 : {
1260 14 : const ScDPItemData* pMemberData = pData->GetMemberById( nDimIndex, rMembers[j] );
1261 14 : rtl::OUString aMemName = pData->GetFormattedString(nDimIndex, *pMemberData);
1262 14 : if (iter->GetExistingMemberByName(aMemName))
1263 : // this member instance already exists. nothing to do.
1264 0 : continue;
1265 :
1266 14 : auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName));
1267 14 : pNewMember->SetIsVisible(true);
1268 14 : iter->AddMember(pNewMember.release());
1269 14 : }
1270 : }
1271 :
1272 1 : mbDimensionMembersBuilt = true;
1273 : }
1274 :
1275 0 : 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 0 : NameIndexMap aMap;
1281 0 : long nColCount = pData->GetColumnCount();
1282 0 : for (long i = 0; i < nColCount; ++i)
1283 0 : aMap.insert(NameIndexMap::value_type(pData->getDimensionName(i), i));
1284 :
1285 0 : NameIndexMap::const_iterator itMapEnd = aMap.end();
1286 :
1287 0 : DimsType::iterator it = aDimList.begin(), itEnd = aDimList.end();
1288 0 : for (it = aDimList.begin(); it != itEnd; ++it)
1289 : {
1290 0 : const ::rtl::OUString& rDimName = it->GetName();
1291 0 : if (rDimName.isEmpty())
1292 : // empty dimension name. It must be data layout.
1293 0 : continue;
1294 :
1295 0 : NameIndexMap::const_iterator itMap = aMap.find(rDimName);
1296 0 : if (itMap == itMapEnd)
1297 : // dimension name not in the data. This should never happen!
1298 0 : continue;
1299 :
1300 0 : ScDPSaveDimension::MemberSetType aMemNames;
1301 0 : long nDimIndex = itMap->second;
1302 0 : const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
1303 0 : size_t nMemberCount = rMembers.size();
1304 0 : for (size_t j = 0; j < nMemberCount; ++j)
1305 : {
1306 0 : const ScDPItemData* pMemberData = pData->GetMemberById(nDimIndex, rMembers[j]);
1307 0 : rtl::OUString aMemName = pData->GetFormattedString(nDimIndex, *pMemberData);
1308 0 : aMemNames.insert(aMemName);
1309 0 : }
1310 :
1311 0 : it->RemoveObsoleteMembers(aMemNames);
1312 0 : }
1313 0 : }
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 9 : void ScDPSaveData::CheckDuplicateName(ScDPSaveDimension& rDim)
1325 : {
1326 9 : const rtl::OUString aName = ScDPUtil::getSourceDimensionName(rDim.GetName());
1327 9 : DupNameCountType::iterator it = maDupNameCounts.find(aName);
1328 9 : if (it != maDupNameCounts.end())
1329 : {
1330 1 : rDim.SetName(ScDPUtil::createDuplicateDimensionName(aName, ++it->second));
1331 1 : rDim.SetDupFlag(true);
1332 : }
1333 : else
1334 : // New name.
1335 8 : maDupNameCounts.insert(DupNameCountType::value_type(aName, 0));
1336 9 : }
1337 :
1338 2 : void ScDPSaveData::RemoveDuplicateNameCount(const rtl::OUString& rName)
1339 : {
1340 2 : rtl::OUString aCoreName = rName;
1341 2 : if (ScDPUtil::isDuplicateDimension(rName))
1342 0 : aCoreName = ScDPUtil::getSourceDimensionName(rName);
1343 :
1344 2 : DupNameCountType::iterator it = maDupNameCounts.find(aCoreName);
1345 2 : if (it == maDupNameCounts.end())
1346 : return;
1347 :
1348 2 : if (!it->second)
1349 : {
1350 2 : maDupNameCounts.erase(it);
1351 : return;
1352 : }
1353 :
1354 0 : --it->second;
1355 2 : return;
1356 : }
1357 :
1358 53 : ScDPSaveDimension* ScDPSaveData::AppendNewDimension(const rtl::OUString& rName, bool bDataLayout)
1359 : {
1360 53 : if (ScDPUtil::isDuplicateDimension(rName))
1361 : // This call is for original dimensions only.
1362 0 : return NULL;
1363 :
1364 53 : ScDPSaveDimension* pNew = new ScDPSaveDimension(rName, bDataLayout);
1365 53 : aDimList.push_back(pNew);
1366 53 : if (!maDupNameCounts.count(rName))
1367 53 : maDupNameCounts.insert(DupNameCountType::value_type(rName, 0));
1368 :
1369 53 : 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 15 : }
1390 :
1391 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|