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 "dptabsrc.hxx"
21 :
22 : #include <algorithm>
23 : #include <vector>
24 : #include <set>
25 : #include <boost/unordered_set.hpp>
26 : #include <boost/unordered_map.hpp>
27 :
28 : #include <rtl/math.hxx>
29 : #include <svl/itemprop.hxx>
30 : #include <svl/intitem.hxx>
31 : #include <vcl/svapp.hxx>
32 :
33 : #include "scitems.hxx"
34 : #include "document.hxx"
35 : #include "docpool.hxx"
36 : #include "patattr.hxx"
37 : #include "cell.hxx"
38 :
39 : #include "dptabres.hxx"
40 : #include "dptabdat.hxx"
41 : #include "global.hxx"
42 : #include "datauno.hxx" // ScDataUnoConversion
43 : #include "miscuno.hxx"
44 : #include "unonames.hxx"
45 : #include "dpitemdata.hxx"
46 : #include "dputil.hxx"
47 :
48 : #include <com/sun/star/beans/PropertyAttribute.hpp>
49 : #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
50 : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
51 : #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
52 : #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
53 : #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
54 : #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
55 : #include <com/sun/star/table/CellAddress.hpp>
56 :
57 : #include "comphelper/string.hxx"
58 : #include <unotools/collatorwrapper.hxx>
59 : #include <unotools/calendarwrapper.hxx>
60 : #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
61 :
62 : using namespace com::sun::star;
63 : using ::std::vector;
64 : using ::std::set;
65 : using ::com::sun::star::uno::Reference;
66 : using ::com::sun::star::uno::Sequence;
67 : using ::com::sun::star::uno::Any;
68 : using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
69 : using ::rtl::OUString;
70 :
71 : // -----------------------------------------------------------------------
72 :
73 : #define SC_MINCOUNT_LIMIT 1000000
74 :
75 : // -----------------------------------------------------------------------
76 :
77 0 : SC_SIMPLE_SERVICE_INFO( ScDPSource, "ScDPSource", "com.sun.star.sheet.DataPilotSource" )
78 0 : SC_SIMPLE_SERVICE_INFO( ScDPDimensions, "ScDPDimensions", "com.sun.star.sheet.DataPilotSourceDimensions" )
79 0 : SC_SIMPLE_SERVICE_INFO( ScDPDimension, "ScDPDimension", "com.sun.star.sheet.DataPilotSourceDimension" )
80 0 : SC_SIMPLE_SERVICE_INFO( ScDPHierarchies, "ScDPHierarchies", "com.sun.star.sheet.DataPilotSourceHierarcies" )
81 0 : SC_SIMPLE_SERVICE_INFO( ScDPHierarchy, "ScDPHierarchy", "com.sun.star.sheet.DataPilotSourceHierarcy" )
82 0 : SC_SIMPLE_SERVICE_INFO( ScDPLevels, "ScDPLevels", "com.sun.star.sheet.DataPilotSourceLevels" )
83 0 : SC_SIMPLE_SERVICE_INFO( ScDPLevel, "ScDPLevel", "com.sun.star.sheet.DataPilotSourceLevel" )
84 0 : SC_SIMPLE_SERVICE_INFO( ScDPMembers, "ScDPMembers", "com.sun.star.sheet.DataPilotSourceMembers" )
85 0 : SC_SIMPLE_SERVICE_INFO( ScDPMember, "ScDPMember", "com.sun.star.sheet.DataPilotSourceMember" )
86 :
87 : // -----------------------------------------------------------------------
88 :
89 : // property maps for PropertySetInfo
90 : // DataDescription / NumberFormat are internal
91 :
92 : // -----------------------------------------------------------------------
93 :
94 : //! move to a header?
95 158 : static sal_Bool lcl_GetBoolFromAny( const uno::Any& aAny )
96 : {
97 158 : if ( aAny.getValueTypeClass() == uno::TypeClass_BOOLEAN )
98 158 : return *(sal_Bool*)aAny.getValue();
99 0 : return false;
100 : }
101 :
102 263 : static void lcl_SetBoolInAny( uno::Any& rAny, sal_Bool bValue )
103 : {
104 263 : rAny.setValue( &bValue, getBooleanCppuType() );
105 263 : }
106 :
107 : // -----------------------------------------------------------------------
108 :
109 22 : ScDPSource::ScDPSource( ScDPTableData* pD ) :
110 : pData( pD ),
111 : pDimensions( NULL ),
112 : nColDimCount( 0 ),
113 : nRowDimCount( 0 ),
114 : nDataDimCount( 0 ),
115 : nPageDimCount( 0 ),
116 : bColumnGrand( true ), // default is true
117 : bRowGrand( true ),
118 : bIgnoreEmptyRows( false ),
119 : bRepeatIfEmpty( false ),
120 : nDupCount( 0 ),
121 : pResData( NULL ),
122 : pColResRoot( NULL ),
123 : pRowResRoot( NULL ),
124 : pColResults( NULL ),
125 : pRowResults( NULL ),
126 : bResultOverflow( false ),
127 : bPageFiltered( false ),
128 22 : mpGrandTotalName(NULL)
129 : {
130 22 : pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
131 22 : }
132 :
133 66 : ScDPSource::~ScDPSource()
134 : {
135 22 : if (pDimensions)
136 22 : pDimensions->release(); // ref-counted
137 :
138 : //! free lists
139 :
140 22 : delete[] pColResults;
141 22 : delete[] pRowResults;
142 :
143 22 : delete pColResRoot;
144 22 : delete pRowResRoot;
145 22 : delete pResData;
146 44 : }
147 :
148 26 : const ::rtl::OUString* ScDPSource::GetGrandTotalName() const
149 : {
150 26 : return mpGrandTotalName.get();
151 : }
152 :
153 256 : sal_uInt16 ScDPSource::GetOrientation(long nColumn)
154 : {
155 : long i;
156 310 : for (i=0; i<nColDimCount; i++)
157 70 : if (nColDims[i] == nColumn)
158 16 : return sheet::DataPilotFieldOrientation_COLUMN;
159 508 : for (i=0; i<nRowDimCount; i++)
160 418 : if (nRowDims[i] == nColumn)
161 150 : return sheet::DataPilotFieldOrientation_ROW;
162 154 : for (i=0; i<nDataDimCount; i++)
163 126 : if (nDataDims[i] == nColumn)
164 62 : return sheet::DataPilotFieldOrientation_DATA;
165 44 : for (i=0; i<nPageDimCount; i++)
166 24 : if (nPageDims[i] == nColumn)
167 8 : return sheet::DataPilotFieldOrientation_PAGE;
168 20 : return sheet::DataPilotFieldOrientation_HIDDEN;
169 : }
170 :
171 6 : long ScDPSource::GetDataDimensionCount()
172 : {
173 6 : return nDataDimCount;
174 : }
175 :
176 51 : ScDPDimension* ScDPSource::GetDataDimension(long nIndex)
177 : {
178 51 : if (nIndex < 0 || nIndex >= nDataDimCount)
179 0 : return NULL;
180 :
181 51 : long nDimIndex = nDataDims[nIndex];
182 51 : return GetDimensionsObject()->getByIndex(nDimIndex);
183 : }
184 :
185 16 : rtl::OUString ScDPSource::GetDataDimName(long nIndex)
186 : {
187 16 : rtl::OUString aRet;
188 16 : ScDPDimension* pDim = GetDataDimension(nIndex);
189 16 : if (pDim)
190 16 : aRet = pDim->getName();
191 16 : return aRet;
192 : }
193 :
194 103 : long ScDPSource::GetPosition(long nColumn)
195 : {
196 : long i;
197 124 : for (i=0; i<nColDimCount; i++)
198 28 : if (nColDims[i] == nColumn)
199 7 : return i;
200 204 : for (i=0; i<nRowDimCount; i++)
201 159 : if (nRowDims[i] == nColumn)
202 51 : return i;
203 77 : for (i=0; i<nDataDimCount; i++)
204 63 : if (nDataDims[i] == nColumn)
205 31 : return i;
206 22 : for (i=0; i<nPageDimCount; i++)
207 12 : if (nPageDims[i] == nColumn)
208 4 : return i;
209 10 : return 0;
210 : }
211 :
212 2146 : static sal_Bool lcl_TestSubTotal( sal_Bool& rAllowed, long nColumn, long* pArray, long nCount, ScDPSource* pSource )
213 : {
214 2587 : for (long i=0; i<nCount; i++)
215 1746 : if (pArray[i] == nColumn)
216 : {
217 : // no subtotals for data layout dim, no matter where
218 1305 : if ( pSource->IsDataLayoutDimension(nColumn) )
219 126 : rAllowed = false;
220 : else
221 : {
222 : // no subtotals if no other dim but data layout follows
223 1179 : long nNextIndex = i+1;
224 1179 : if ( nNextIndex < nCount && pSource->IsDataLayoutDimension(pArray[nNextIndex]) )
225 529 : ++nNextIndex;
226 1179 : if ( nNextIndex >= nCount )
227 961 : rAllowed = false;
228 : }
229 :
230 1305 : return sal_True; // found
231 : }
232 841 : return false;
233 : }
234 :
235 1305 : sal_Bool ScDPSource::SubTotalAllowed(long nColumn)
236 : {
237 : //! cache this at ScDPResultData
238 1305 : sal_Bool bAllowed = sal_True;
239 1305 : if ( lcl_TestSubTotal( bAllowed, nColumn, nColDims, nColDimCount, this ) )
240 464 : return bAllowed;
241 841 : if ( lcl_TestSubTotal( bAllowed, nColumn, nRowDims, nRowDimCount, this ) )
242 841 : return bAllowed;
243 0 : return bAllowed;
244 : }
245 :
246 808 : static void lcl_RemoveDim( long nRemove, long* pDims, long& rCount )
247 : {
248 939 : for (long i=0; i<rCount; i++)
249 131 : if ( pDims[i] == nRemove )
250 : {
251 0 : for (long j=i; j+1<rCount; j++)
252 0 : pDims[j] = pDims[j+1];
253 0 : --rCount;
254 808 : return;
255 : }
256 : }
257 :
258 202 : void ScDPSource::SetOrientation(long nColumn, sal_uInt16 nNew)
259 : {
260 : //! change to no-op if new orientation is equal to old?
261 :
262 : // remove from old list
263 202 : lcl_RemoveDim( nColumn, nColDims, nColDimCount );
264 202 : lcl_RemoveDim( nColumn, nRowDims, nRowDimCount );
265 202 : lcl_RemoveDim( nColumn, nDataDims, nDataDimCount );
266 202 : lcl_RemoveDim( nColumn, nPageDims, nPageDimCount );
267 :
268 : // add to new list
269 202 : switch (nNew)
270 : {
271 : case sheet::DataPilotFieldOrientation_COLUMN:
272 7 : nColDims[nColDimCount++] = nColumn;
273 7 : break;
274 : case sheet::DataPilotFieldOrientation_ROW:
275 51 : nRowDims[nRowDimCount++] = nColumn;
276 51 : break;
277 : case sheet::DataPilotFieldOrientation_DATA:
278 31 : nDataDims[nDataDimCount++] = nColumn;
279 31 : break;
280 : case sheet::DataPilotFieldOrientation_PAGE:
281 4 : nPageDims[nPageDimCount++] = nColumn;
282 4 : break;
283 : // DataPilot Migration - Cache&&Performance
284 : case sheet::DataPilotFieldOrientation_HIDDEN:
285 109 : break;
286 : default:
287 : OSL_FAIL( "ScDPSource::SetOrientation: unexpected orientation" );
288 0 : break;
289 : }
290 202 : }
291 :
292 2328 : sal_Bool ScDPSource::IsDataLayoutDimension(long nDim)
293 : {
294 2328 : return nDim == pData->GetColumnCount();
295 : }
296 :
297 50 : sal_uInt16 ScDPSource::GetDataLayoutOrientation()
298 : {
299 50 : return GetOrientation(pData->GetColumnCount());
300 : }
301 :
302 594 : sal_Bool ScDPSource::IsDateDimension(long nDim)
303 : {
304 594 : return pData->IsDateDimension(nDim);
305 : }
306 :
307 881 : ScDPDimensions* ScDPSource::GetDimensionsObject()
308 : {
309 881 : if (!pDimensions)
310 : {
311 25 : pDimensions = new ScDPDimensions(this);
312 25 : pDimensions->acquire(); // ref-counted
313 : }
314 881 : return pDimensions;
315 : }
316 :
317 86 : uno::Reference<container::XNameAccess> SAL_CALL ScDPSource::getDimensions() throw(uno::RuntimeException)
318 : {
319 86 : return GetDimensionsObject();
320 : }
321 :
322 5 : void ScDPSource::SetDupCount( long nNew )
323 : {
324 5 : nDupCount = nNew;
325 5 : }
326 :
327 2 : ScDPDimension* ScDPSource::AddDuplicated(long /* nSource */, const rtl::OUString& rNewName)
328 : {
329 : OSL_ENSURE( pDimensions, "AddDuplicated without dimensions?" );
330 :
331 : // re-use
332 :
333 2 : long nOldDimCount = pDimensions->getCount();
334 8 : for (long i=0; i<nOldDimCount; i++)
335 : {
336 6 : ScDPDimension* pDim = pDimensions->getByIndex(i);
337 6 : if (pDim && pDim->getName().equals(rNewName))
338 : {
339 : //! test if pDim is a duplicate of source
340 0 : return pDim;
341 : }
342 : }
343 :
344 2 : SetDupCount( nDupCount + 1 );
345 2 : pDimensions->CountChanged(); // uses nDupCount
346 :
347 2 : return pDimensions->getByIndex( pDimensions->getCount() - 1 );
348 : }
349 :
350 3419 : long ScDPSource::GetSourceDim(long nDim)
351 : {
352 : // original source dimension or data layout dimension?
353 3419 : if ( nDim <= pData->GetColumnCount() )
354 3403 : return nDim;
355 :
356 16 : if ( nDim < pDimensions->getCount() )
357 : {
358 16 : ScDPDimension* pDimObj = pDimensions->getByIndex( nDim );
359 16 : if ( pDimObj )
360 : {
361 16 : long nSource = pDimObj->GetSourceDim();
362 16 : if ( nSource >= 0 )
363 16 : return nSource;
364 : }
365 : }
366 :
367 : OSL_FAIL("GetSourceDim: wrong dim");
368 0 : return nDim;
369 : }
370 :
371 25 : uno::Sequence< uno::Sequence<sheet::DataResult> > SAL_CALL ScDPSource::getResults()
372 : throw(uno::RuntimeException)
373 : {
374 25 : CreateRes_Impl(); // create pColResRoot and pRowResRoot
375 :
376 25 : if ( bResultOverflow ) // set in CreateRes_Impl
377 : {
378 : // no results available
379 0 : throw uno::RuntimeException();
380 : }
381 :
382 25 : long nColCount = pColResRoot->GetSize(pResData->GetColStartMeasure());
383 25 : long nRowCount = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
384 :
385 : // allocate full sequence
386 : //! leave out empty rows???
387 :
388 25 : uno::Sequence< uno::Sequence<sheet::DataResult> > aSeq( nRowCount );
389 25 : uno::Sequence<sheet::DataResult>* pRowAry = aSeq.getArray();
390 153 : for (long nRow = 0; nRow < nRowCount; nRow++)
391 : {
392 128 : uno::Sequence<sheet::DataResult> aColSeq( nColCount );
393 : // use default values of DataResult
394 128 : pRowAry[nRow] = aColSeq;
395 128 : }
396 :
397 25 : long nSeqRow = 0;
398 25 : pRowResRoot->FillDataResults( pColResRoot, aSeq, nSeqRow, pResData->GetRowStartMeasure() );
399 :
400 25 : return aSeq;
401 : }
402 :
403 3 : void SAL_CALL ScDPSource::refresh() throw(uno::RuntimeException)
404 : {
405 3 : disposeData();
406 3 : }
407 :
408 0 : void SAL_CALL ScDPSource::addRefreshListener( const uno::Reference<util::XRefreshListener >& )
409 : throw(uno::RuntimeException)
410 : {
411 : OSL_FAIL("not implemented"); //! exception?
412 0 : }
413 :
414 0 : void SAL_CALL ScDPSource::removeRefreshListener( const uno::Reference<util::XRefreshListener >& )
415 : throw(uno::RuntimeException)
416 : {
417 : OSL_FAIL("not implemented"); //! exception?
418 0 : }
419 :
420 0 : Sequence< Sequence<Any> > SAL_CALL ScDPSource::getDrillDownData(const Sequence<sheet::DataPilotFieldFilter>& aFilters)
421 : throw (uno::RuntimeException)
422 : {
423 0 : long nColumnCount = GetData()->GetColumnCount();
424 :
425 0 : vector<ScDPFilteredCache::Criterion> aFilterCriteria;
426 0 : sal_Int32 nFilterCount = aFilters.getLength();
427 0 : for (sal_Int32 i = 0; i < nFilterCount; ++i)
428 : {
429 0 : const sheet::DataPilotFieldFilter& rFilter = aFilters[i];
430 0 : const rtl::OUString& aFieldName = rFilter.FieldName;
431 0 : for (long nCol = 0; nCol < nColumnCount; ++nCol)
432 : {
433 0 : if (aFieldName.equals(pData->getDimensionName(nCol)))
434 : {
435 0 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nCol );
436 0 : ScDPMembers* pMembers = pDim->GetHierarchiesObject()->getByIndex(0)->
437 0 : GetLevelsObject()->getByIndex(0)->GetMembersObject();
438 0 : sal_Int32 nIndex = pMembers->GetIndexFromName( rFilter.MatchValue );
439 0 : if ( nIndex >= 0 )
440 : {
441 0 : ScDPItemData aItem;
442 0 : pMembers->getByIndex(nIndex)->FillItemData( aItem );
443 0 : aFilterCriteria.push_back( ScDPFilteredCache::Criterion() );
444 0 : aFilterCriteria.back().mnFieldIndex = nCol;
445 0 : aFilterCriteria.back().mpFilter.reset(
446 0 : new ScDPFilteredCache::SingleFilter(aItem));
447 : }
448 : }
449 : }
450 : }
451 :
452 : // Take into account the visibilities of field members.
453 0 : ScDPResultVisibilityData aResVisData(this);
454 0 : pRowResRoot->FillVisibilityData(aResVisData);
455 0 : pColResRoot->FillVisibilityData(aResVisData);
456 0 : aResVisData.fillFieldFilters(aFilterCriteria);
457 :
458 0 : Sequence< Sequence<Any> > aTabData;
459 0 : boost::unordered_set<sal_Int32> aCatDims;
460 0 : GetCategoryDimensionIndices(aCatDims);
461 0 : pData->GetDrillDownData(aFilterCriteria, aCatDims, aTabData);
462 0 : return aTabData;
463 : }
464 :
465 25 : rtl::OUString ScDPSource::getDataDescription()
466 : {
467 25 : CreateRes_Impl(); // create pResData
468 :
469 25 : rtl::OUString aRet;
470 25 : if ( pResData->GetMeasureCount() == 1 )
471 : {
472 19 : bool bTotalResult = false;
473 19 : aRet = pResData->GetMeasureString(0, true, SUBTOTAL_FUNC_NONE, bTotalResult);
474 : }
475 :
476 : // empty for more than one measure
477 :
478 25 : return aRet;
479 : }
480 :
481 25 : void ScDPSource::setIgnoreEmptyRows(bool bSet)
482 : {
483 25 : bIgnoreEmptyRows = bSet;
484 25 : pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
485 25 : }
486 :
487 25 : void ScDPSource::setRepeatIfEmpty(bool bSet)
488 : {
489 25 : bRepeatIfEmpty = bSet;
490 25 : pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
491 25 : }
492 :
493 3 : void ScDPSource::disposeData()
494 : {
495 3 : if ( pResData )
496 : {
497 : // reset all data...
498 :
499 3 : DELETEZ(pColResRoot);
500 3 : DELETEZ(pRowResRoot);
501 3 : DELETEZ(pResData);
502 3 : delete[] pColResults;
503 3 : delete[] pRowResults;
504 3 : pColResults = NULL;
505 3 : pRowResults = NULL;
506 3 : aColLevelList.clear();
507 3 : aRowLevelList.clear();
508 : }
509 :
510 3 : if ( pDimensions )
511 : {
512 3 : pDimensions->release(); // ref-counted
513 3 : pDimensions = NULL; // settings have to be applied (from SaveData) again!
514 : }
515 3 : SetDupCount( 0 );
516 :
517 : //! Test ????
518 3 : nColDimCount = nRowDimCount = nDataDimCount = nPageDimCount = 0;
519 :
520 3 : pData->DisposeData(); // cached entries etc.
521 3 : bPageFiltered = false;
522 3 : bResultOverflow = false;
523 3 : }
524 :
525 50 : static long lcl_CountMinMembers(const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLevel, long nLevels )
526 : {
527 : // Calculate the product of the member count for those consecutive levels that
528 : // have the "show all" flag, one following level, and the data layout dimension.
529 :
530 50 : long nTotal = 1;
531 50 : long nDataCount = 1;
532 50 : sal_Bool bWasShowAll = sal_True;
533 50 : long nPos = nLevels;
534 139 : while ( nPos > 0 )
535 : {
536 39 : --nPos;
537 :
538 39 : if ( nPos+1 < nLevels && ppDim[nPos] == ppDim[nPos+1] )
539 : {
540 : OSL_FAIL("lcl_CountMinMembers: multiple levels from one dimension not implemented");
541 0 : return 0;
542 : }
543 :
544 39 : sal_Bool bDo = false;
545 39 : if ( ppDim[nPos]->getIsDataLayoutDimension() )
546 : {
547 : // data layout dim doesn't interfere with "show all" flags
548 6 : nDataCount = ppLevel[nPos]->GetMembersObject()->getCount();
549 6 : if ( nDataCount == 0 )
550 0 : nDataCount = 1;
551 : }
552 33 : else if ( bWasShowAll ) // "show all" set for all following levels?
553 : {
554 27 : bDo = sal_True;
555 27 : if ( !ppLevel[nPos]->getShowEmpty() )
556 : {
557 : // this level is counted, following ones are not
558 27 : bWasShowAll = false;
559 : }
560 : }
561 39 : if ( bDo )
562 : {
563 27 : long nThisCount = ppLevel[nPos]->GetMembersObject()->getMinMembers();
564 27 : if ( nThisCount == 0 )
565 : {
566 0 : nTotal = 1; // empty level -> start counting from here
567 : //! start with visible elements in this level?
568 : }
569 : else
570 : {
571 27 : if ( nTotal >= LONG_MAX / nThisCount )
572 0 : return LONG_MAX; // overflow
573 27 : nTotal *= nThisCount;
574 : }
575 : }
576 : }
577 :
578 : // always include data layout dim, even after restarting
579 50 : if ( nTotal >= LONG_MAX / nDataCount )
580 0 : return LONG_MAX; // overflow
581 50 : nTotal *= nDataCount;
582 :
583 50 : return nTotal;
584 : }
585 :
586 0 : static long lcl_GetIndexFromName( const rtl::OUString rName, const uno::Sequence<rtl::OUString>& rElements )
587 : {
588 0 : long nCount = rElements.getLength();
589 0 : const rtl::OUString* pArray = rElements.getConstArray();
590 0 : for (long nPos=0; nPos<nCount; nPos++)
591 0 : if (pArray[nPos] == rName)
592 0 : return nPos;
593 :
594 0 : return -1; // not found
595 : }
596 :
597 50 : void ScDPSource::FillCalcInfo(bool bIsRow, ScDPTableData::CalcInfo& rInfo, bool &rHasAutoShow)
598 : {
599 50 : long* nDims = bIsRow ? nRowDims : nColDims;
600 50 : long nDimCount = bIsRow ? nRowDimCount : nColDimCount;
601 :
602 108 : for (long i = 0; i < nDimCount; ++i)
603 : {
604 58 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nDims[i] );
605 58 : long nHierarchy = pDim->getUsedHierarchy();
606 58 : if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
607 0 : nHierarchy = 0;
608 58 : ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
609 58 : long nCount = pLevels->getCount();
610 :
611 : //! Test
612 58 : if ( pDim->getIsDataLayoutDimension() && nDataDimCount < 2 )
613 19 : nCount = 0;
614 : //! Test
615 :
616 97 : for (long j = 0; j < nCount; ++j)
617 : {
618 39 : ScDPLevel* pLevel = pLevels->getByIndex(j);
619 39 : pLevel->EvaluateSortOrder();
620 :
621 : // no layout flags for column fields, only for row fields
622 39 : pLevel->SetEnableLayout( bIsRow );
623 :
624 39 : if ( pLevel->GetAutoShow().IsEnabled )
625 0 : rHasAutoShow = sal_True;
626 :
627 39 : if (bIsRow)
628 : {
629 32 : rInfo.aRowLevelDims.push_back(nDims[i]);
630 32 : rInfo.aRowDims.push_back(pDim);
631 32 : rInfo.aRowLevels.push_back(pLevel);
632 : }
633 : else
634 : {
635 7 : rInfo.aColLevelDims.push_back(nDims[i]);
636 7 : rInfo.aColDims.push_back(pDim);
637 7 : rInfo.aColLevels.push_back(pLevel);
638 : }
639 :
640 39 : pLevel->GetMembersObject(); // initialize for groups
641 : }
642 : }
643 50 : }
644 :
645 2 : void ScDPSource::GetCategoryDimensionIndices(boost::unordered_set<sal_Int32>& rCatDims)
646 : {
647 2 : boost::unordered_set<sal_Int32> aCatDims;
648 2 : for (long i = 0; i < nColDimCount; ++i)
649 : {
650 0 : sal_Int32 nDim = static_cast<sal_Int32>(nColDims[i]);
651 0 : if (!IsDataLayoutDimension(nDim))
652 0 : aCatDims.insert(nDim);
653 : }
654 :
655 4 : for (long i = 0; i < nRowDimCount; ++i)
656 : {
657 2 : sal_Int32 nDim = static_cast<sal_Int32>(nRowDims[i]);
658 2 : if (!IsDataLayoutDimension(nDim))
659 0 : aCatDims.insert(nDim);
660 : }
661 :
662 4 : for (long i = 0; i < nPageDimCount; ++i)
663 : {
664 2 : sal_Int32 nDim = static_cast<sal_Int32>(nPageDims[i]);
665 2 : if (!IsDataLayoutDimension(nDim))
666 2 : aCatDims.insert(nDim);
667 : }
668 :
669 2 : rCatDims.swap(aCatDims);
670 2 : }
671 :
672 25 : void ScDPSource::FilterCacheByPageDimensions()
673 : {
674 : // #i117661# Repeated calls to ScDPFilteredCache::filterByPageDimension
675 : // are invalid because rows are only hidden, never shown again. If
676 : // FilterCacheByPageDimensions is called again, the cache table must
677 : // be re-initialized. Currently, CreateRes_Impl always uses a fresh cache
678 : // because ScDBDocFunc::DataPilotUpdate calls InvalidateData.
679 :
680 25 : if (bPageFiltered)
681 : {
682 : SAL_WARN( "sc.core","tried to apply page field filters several times");
683 :
684 0 : pData->DisposeData();
685 0 : pData->CreateCacheTable(); // re-initialize the cache table
686 0 : bPageFiltered = false;
687 : }
688 :
689 : // filter table by page dimensions.
690 25 : vector<ScDPFilteredCache::Criterion> aCriteria;
691 29 : for (long i = 0; i < nPageDimCount; ++i)
692 : {
693 4 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nPageDims[i]);
694 4 : long nField = pDim->GetDimension();
695 :
696 4 : ScDPMembers* pMems = pDim->GetHierarchiesObject()->getByIndex(0)->
697 4 : GetLevelsObject()->getByIndex(0)->GetMembersObject();
698 :
699 4 : long nMemCount = pMems->getCount();
700 4 : ScDPFilteredCache::Criterion aFilter;
701 4 : aFilter.mnFieldIndex = static_cast<sal_Int32>(nField);
702 4 : aFilter.mpFilter.reset(new ScDPFilteredCache::GroupFilter(/*rSharedString*/));
703 : ScDPFilteredCache::GroupFilter* pGrpFilter =
704 4 : static_cast<ScDPFilteredCache::GroupFilter*>(aFilter.mpFilter.get());
705 12 : for (long j = 0; j < nMemCount; ++j)
706 : {
707 8 : ScDPMember* pMem = pMems->getByIndex(j);
708 8 : if (pMem->isVisible())
709 : {
710 6 : ScDPItemData aData;
711 6 : pMem->FillItemData(aData);
712 6 : pGrpFilter->addMatchItem(aData);
713 : }
714 : }
715 4 : if (pGrpFilter->getMatchItemCount() < static_cast<size_t>(nMemCount))
716 : // there is at least one invisible item. Add this filter criterion to the mix.
717 2 : aCriteria.push_back(aFilter);
718 :
719 4 : if (!pDim || !pDim->HasSelectedPage())
720 4 : continue;
721 :
722 0 : const ScDPItemData& rData = pDim->GetSelectedData();
723 0 : aCriteria.push_back(ScDPFilteredCache::Criterion());
724 0 : ScDPFilteredCache::Criterion& r = aCriteria.back();
725 0 : r.mnFieldIndex = static_cast<sal_Int32>(nField);
726 0 : r.mpFilter.reset(new ScDPFilteredCache::SingleFilter(rData));
727 4 : }
728 25 : if (!aCriteria.empty())
729 : {
730 2 : boost::unordered_set<sal_Int32> aCatDims;
731 2 : GetCategoryDimensionIndices(aCatDims);
732 2 : pData->FilterCacheTable(aCriteria, aCatDims);
733 2 : bPageFiltered = true;
734 25 : }
735 25 : }
736 :
737 75 : void ScDPSource::CreateRes_Impl()
738 : {
739 75 : if (pResData)
740 : return;
741 :
742 25 : sal_uInt16 nDataOrient = GetDataLayoutOrientation();
743 25 : if ( nDataDimCount > 1 && ( nDataOrient != sheet::DataPilotFieldOrientation_COLUMN &&
744 : nDataOrient != sheet::DataPilotFieldOrientation_ROW ) )
745 : {
746 : // if more than one data dimension, data layout orientation must be set
747 0 : SetOrientation( pData->GetColumnCount(), sheet::DataPilotFieldOrientation_ROW );
748 0 : nDataOrient = sheet::DataPilotFieldOrientation_ROW;
749 : }
750 :
751 : // TODO: Aggreate pDataNames, pDataRefValues, nDataRefOrient, and
752 : // eDataFunctions into a structure and use vector instead of static
753 : // or pointer arrays.
754 25 : vector<rtl::OUString> aDataNames;
755 25 : sheet::DataPilotFieldReference* pDataRefValues = NULL;
756 : ScSubTotalFunc eDataFunctions[SC_DP_MAX_FIELDS];
757 : sal_uInt16 nDataRefOrient[SC_DP_MAX_FIELDS];
758 25 : if (nDataDimCount)
759 : {
760 25 : aDataNames.resize(nDataDimCount);
761 25 : pDataRefValues = new sheet::DataPilotFieldReference[nDataDimCount];
762 : }
763 :
764 25 : ScDPTableData::CalcInfo aInfo;
765 :
766 :
767 : // LateInit (initialize only those rows/children that are used) can be used unless
768 : // any data dimension needs reference values from column/row dimensions
769 25 : bool bLateInit = true;
770 :
771 : // Go through all data dimensions (i.e. fields) and build their meta data
772 : // so that they can be passed on to ScDPResultData instance later.
773 : // TODO: aggregate all of data dimension info into a structure.
774 : long i;
775 56 : for (i=0; i<nDataDimCount; i++)
776 : {
777 : // Get function for each data field.
778 31 : long nDimIndex = nDataDims[i];
779 31 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nDimIndex);
780 31 : sheet::GeneralFunction eUser = (sheet::GeneralFunction)pDim->getFunction();
781 31 : if (eUser == sheet::GeneralFunction_AUTO)
782 : {
783 : //! test for numeric data
784 0 : eUser = sheet::GeneralFunction_SUM;
785 : }
786 :
787 : // Map UNO's enum to internal enum ScSubTotalFunc.
788 31 : eDataFunctions[i] = ScDataUnoConversion::GeneralToSubTotal( eUser );
789 :
790 : // Get reference field/item information.
791 31 : pDataRefValues[i] = pDim->GetReferenceValue();
792 31 : nDataRefOrient[i] = sheet::DataPilotFieldOrientation_HIDDEN; // default if not used
793 31 : sal_Int32 eRefType = pDataRefValues[i].ReferenceType;
794 31 : if ( eRefType == sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE ||
795 : eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE ||
796 : eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE ||
797 : eRefType == sheet::DataPilotFieldReferenceType::RUNNING_TOTAL )
798 : {
799 0 : long nColumn = lcl_GetIndexFromName( pDataRefValues[i].ReferenceField,
800 0 : GetDimensionsObject()->getElementNames() );
801 0 : if ( nColumn >= 0 )
802 : {
803 0 : nDataRefOrient[i] = GetOrientation( nColumn );
804 : // need fully initialized results to find reference values
805 : // (both in column or row dimensions), so updated values or
806 : // differences to 0 can be displayed even for empty results.
807 0 : bLateInit = false;
808 : }
809 : }
810 :
811 31 : aDataNames[i] = pDim->getName();
812 :
813 : //! modify user visible strings as in ScDPResultData::GetMeasureString instead!
814 :
815 31 : aDataNames[i] = ScDPUtil::getSourceDimensionName(aDataNames[i]);
816 :
817 : //! if the name is overridden by user, a flag must be set
818 : //! so the user defined name replaces the function string and field name.
819 :
820 : //! the complete name (function and field) must be stored at the dimension
821 :
822 31 : long nSource = ((ScDPDimension*)pDim)->GetSourceDim();
823 31 : if (nSource >= 0)
824 2 : aInfo.aDataSrcCols.push_back(nSource);
825 : else
826 29 : aInfo.aDataSrcCols.push_back(nDimIndex);
827 : }
828 :
829 25 : pResData = new ScDPResultData( this );
830 25 : pResData->SetMeasureData( nDataDimCount, eDataFunctions, pDataRefValues, nDataRefOrient, aDataNames );
831 25 : pResData->SetDataLayoutOrientation(nDataOrient);
832 25 : pResData->SetLateInit( bLateInit );
833 :
834 25 : delete[] pDataRefValues;
835 :
836 25 : bool bHasAutoShow = false;
837 :
838 25 : ScDPInitState aInitState;
839 :
840 : // Page field selections restrict the members shown in related fields
841 : // (both in column and row fields). aInitState is filled with the page
842 : // field selections, they are kept across the data iterator loop.
843 :
844 29 : for (i=0; i<nPageDimCount; i++)
845 : {
846 4 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nPageDims[i] );
847 4 : if ( pDim->HasSelectedPage() )
848 0 : aInitState.AddMember( nPageDims[i], GetMemberId( nPageDims[i], pDim->GetSelectedData() ) );
849 : }
850 :
851 : // Show grand total columns only when the option is set *and* there is at
852 : // least one column field. Same for the grand total rows.
853 25 : sal_uInt16 nDataLayoutOrient = GetDataLayoutOrientation();
854 25 : long nColDimCount2 = nColDimCount - (nDataLayoutOrient == sheet::DataPilotFieldOrientation_COLUMN ? 1 : 0);
855 25 : long nRowDimCount2 = nRowDimCount - (nDataLayoutOrient == sheet::DataPilotFieldOrientation_ROW ? 1 : 0);
856 25 : bool bShowColGrand = bColumnGrand && nColDimCount2 > 0;
857 25 : bool bShowRowGrand = bRowGrand && nRowDimCount2 > 0;
858 25 : pColResRoot = new ScDPResultMember(pResData, bShowColGrand);
859 25 : pRowResRoot = new ScDPResultMember(pResData, bShowRowGrand);
860 :
861 25 : FillCalcInfo(false, aInfo, bHasAutoShow);
862 25 : long nColLevelCount = aInfo.aColLevels.size();
863 :
864 25 : pColResRoot->InitFrom( aInfo.aColDims, aInfo.aColLevels, 0, aInitState );
865 25 : pColResRoot->SetHasElements();
866 :
867 25 : FillCalcInfo(true, aInfo, bHasAutoShow);
868 25 : long nRowLevelCount = aInfo.aRowLevels.size();
869 :
870 25 : if ( nRowLevelCount > 0 )
871 : {
872 : // disable layout flags for the innermost row field (level)
873 25 : aInfo.aRowLevels[nRowLevelCount-1]->SetEnableLayout( false );
874 : }
875 :
876 25 : pRowResRoot->InitFrom( aInfo.aRowDims, aInfo.aRowLevels, 0, aInitState );
877 25 : pRowResRoot->SetHasElements();
878 :
879 : // initialize members object also for all page dimensions (needed for numeric groups)
880 29 : for (i=0; i<nPageDimCount; i++)
881 : {
882 4 : ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nPageDims[i] );
883 4 : long nHierarchy = pDim->getUsedHierarchy();
884 4 : if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
885 0 : nHierarchy = 0;
886 :
887 4 : ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
888 4 : long nCount = pLevels->getCount();
889 8 : for (long j=0; j<nCount; j++)
890 4 : pLevels->getByIndex(j)->GetMembersObject(); // initialize for groups
891 : }
892 :
893 : // pre-check: calculate minimum number of result columns / rows from
894 : // levels that have the "show all" flag set
895 :
896 25 : long nMinColMembers = lcl_CountMinMembers( aInfo.aColDims, aInfo.aColLevels, nColLevelCount );
897 25 : long nMinRowMembers = lcl_CountMinMembers( aInfo.aRowDims, aInfo.aRowLevels, nRowLevelCount );
898 :
899 25 : if ( nMinColMembers > MAXCOLCOUNT/*SC_MINCOUNT_LIMIT*/ || nMinRowMembers > SC_MINCOUNT_LIMIT )
900 : {
901 : // resulting table is too big -> abort before calculating
902 : // (this relies on late init, so no members are allocated in InitFrom above)
903 :
904 0 : bResultOverflow = true;
905 : return;
906 : }
907 :
908 25 : FilterCacheByPageDimensions();
909 :
910 25 : aInfo.aPageDims.reserve(nPageDimCount);
911 29 : for (i = 0; i < nPageDimCount; ++i)
912 4 : aInfo.aPageDims.push_back(nPageDims[i]);
913 :
914 25 : aInfo.pInitState = &aInitState;
915 25 : aInfo.pColRoot = pColResRoot;
916 25 : aInfo.pRowRoot = pRowResRoot;
917 25 : pData->CalcResults(aInfo, false);
918 :
919 25 : pColResRoot->CheckShowEmpty();
920 25 : pRowResRoot->CheckShowEmpty();
921 : // ----------------------------------------------------------------
922 : // With all data processed, calculate the final results:
923 :
924 : // UpdateDataResults calculates all original results from the collected values,
925 : // and stores them as reference values if needed.
926 25 : pRowResRoot->UpdateDataResults( pColResRoot, pResData->GetRowStartMeasure() );
927 :
928 25 : if ( bHasAutoShow ) // do the double calculation only if AutoShow is used
929 : {
930 : // Find the desired members and set bAutoHidden flag for the others
931 0 : pRowResRoot->DoAutoShow( pColResRoot );
932 :
933 : // Reset all results to empty, so they can be built again with data for the
934 : // desired members only.
935 0 : pColResRoot->ResetResults( sal_True );
936 0 : pRowResRoot->ResetResults( sal_True );
937 0 : pData->CalcResults(aInfo, true);
938 :
939 : // Call UpdateDataResults again, with the new (limited) values.
940 0 : pRowResRoot->UpdateDataResults( pColResRoot, pResData->GetRowStartMeasure() );
941 : }
942 :
943 : // SortMembers does the sorting by a result dimension, using the orginal results,
944 : // but not running totals etc.
945 25 : pRowResRoot->SortMembers( pColResRoot );
946 :
947 : // UpdateRunningTotals calculates running totals along column/row dimensions,
948 : // differences from other members (named or relative), and column/row percentages
949 : // or index values.
950 : // Running totals and relative differences need to be done using the sorted values.
951 : // Column/row percentages and index values must be done after sorting, because the
952 : // results may no longer be in the right order (row total for percentage of row is
953 : // always 1).
954 25 : ScDPRunningTotalState aRunning( pColResRoot, pRowResRoot );
955 25 : ScDPRowTotals aTotals;
956 25 : pRowResRoot->UpdateRunningTotals( pColResRoot, pResData->GetRowStartMeasure(), aRunning, aTotals );
957 : }
958 :
959 :
960 50 : void ScDPSource::FillLevelList( sal_uInt16 nOrientation, std::vector<ScDPLevel*> &rList )
961 : {
962 50 : rList.clear();
963 :
964 50 : long nDimCount = 0;
965 50 : long* pDimIndex = NULL;
966 50 : switch (nOrientation)
967 : {
968 : case sheet::DataPilotFieldOrientation_COLUMN:
969 25 : pDimIndex = nColDims;
970 25 : nDimCount = nColDimCount;
971 25 : break;
972 : case sheet::DataPilotFieldOrientation_ROW:
973 25 : pDimIndex = nRowDims;
974 25 : nDimCount = nRowDimCount;
975 25 : break;
976 : case sheet::DataPilotFieldOrientation_DATA:
977 0 : pDimIndex = nDataDims;
978 0 : nDimCount = nDataDimCount;
979 0 : break;
980 : case sheet::DataPilotFieldOrientation_PAGE:
981 0 : pDimIndex = nPageDims;
982 0 : nDimCount = nPageDimCount;
983 0 : break;
984 : default:
985 : OSL_FAIL( "ScDPSource::FillLevelList: unexpected orientation" );
986 0 : break;
987 : }
988 50 : if (!pDimIndex)
989 : {
990 : OSL_FAIL("invalid orientation");
991 50 : return;
992 : }
993 :
994 50 : ScDPDimensions* pDims = GetDimensionsObject();
995 108 : for (long nDim=0; nDim<nDimCount; nDim++)
996 : {
997 58 : ScDPDimension* pDim = pDims->getByIndex(pDimIndex[nDim]);
998 : OSL_ENSURE( pDim->getOrientation() == nOrientation, "orientations are wrong" );
999 :
1000 58 : ScDPHierarchies* pHiers = pDim->GetHierarchiesObject();
1001 58 : long nHierarchy = pDim->getUsedHierarchy();
1002 58 : if ( nHierarchy >= pHiers->getCount() )
1003 0 : nHierarchy = 0;
1004 58 : ScDPHierarchy* pHier = pHiers->getByIndex(nHierarchy);
1005 58 : ScDPLevels* pLevels = pHier->GetLevelsObject();
1006 58 : long nLevCount = pLevels->getCount();
1007 116 : for (long nLev=0; nLev<nLevCount; nLev++)
1008 : {
1009 58 : ScDPLevel* pLevel = pLevels->getByIndex(nLev);
1010 58 : rList.push_back(pLevel);
1011 : }
1012 : }
1013 : }
1014 :
1015 83 : void ScDPSource::FillMemberResults()
1016 : {
1017 83 : if ( !pColResults && !pRowResults )
1018 : {
1019 25 : CreateRes_Impl();
1020 :
1021 25 : if ( bResultOverflow ) // set in CreateRes_Impl
1022 : {
1023 : // no results available -> abort (leave empty)
1024 : // exception is thrown in ScDPSource::getResults
1025 83 : return;
1026 : }
1027 :
1028 25 : FillLevelList( sheet::DataPilotFieldOrientation_COLUMN, aColLevelList );
1029 25 : long nColLevelCount = aColLevelList.size();
1030 25 : if (nColLevelCount)
1031 : {
1032 7 : long nColDimSize = pColResRoot->GetSize(pResData->GetColStartMeasure());
1033 7 : pColResults = new uno::Sequence<sheet::MemberResult>[nColLevelCount];
1034 14 : for (long i=0; i<nColLevelCount; i++)
1035 7 : pColResults[i].realloc(nColDimSize);
1036 :
1037 7 : long nPos = 0;
1038 : pColResRoot->FillMemberResults( pColResults, nPos, pResData->GetColStartMeasure(),
1039 7 : sal_True, NULL, NULL );
1040 : }
1041 :
1042 25 : FillLevelList( sheet::DataPilotFieldOrientation_ROW, aRowLevelList );
1043 25 : long nRowLevelCount = aRowLevelList.size();
1044 25 : if (nRowLevelCount)
1045 : {
1046 25 : long nRowDimSize = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
1047 25 : pRowResults = new uno::Sequence<sheet::MemberResult>[nRowLevelCount];
1048 76 : for (long i=0; i<nRowLevelCount; i++)
1049 51 : pRowResults[i].realloc(nRowDimSize);
1050 :
1051 25 : long nPos = 0;
1052 : pRowResRoot->FillMemberResults( pRowResults, nPos, pResData->GetRowStartMeasure(),
1053 25 : sal_True, NULL, NULL );
1054 : }
1055 : }
1056 : }
1057 :
1058 83 : const uno::Sequence<sheet::MemberResult>* ScDPSource::GetMemberResults( ScDPLevel* pLevel )
1059 : {
1060 83 : FillMemberResults();
1061 :
1062 83 : long i = 0;
1063 83 : long nColCount = aColLevelList.size();
1064 102 : for (i=0; i<nColCount; i++)
1065 : {
1066 27 : ScDPLevel* pColLevel = aColLevelList[i];
1067 27 : if ( pColLevel == pLevel )
1068 8 : return pColResults+i;
1069 : }
1070 75 : long nRowCount = aRowLevelList.size();
1071 135 : for (i=0; i<nRowCount; i++)
1072 : {
1073 135 : ScDPLevel* pRowLevel = aRowLevelList[i];
1074 135 : if ( pRowLevel == pLevel )
1075 75 : return pRowResults+i;
1076 : }
1077 0 : return NULL;
1078 : }
1079 :
1080 : // XPropertySet
1081 :
1082 0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPSource::getPropertySetInfo()
1083 : throw(uno::RuntimeException)
1084 : {
1085 0 : SolarMutexGuard aGuard;
1086 : using beans::PropertyAttribute::READONLY;
1087 :
1088 : static SfxItemPropertyMapEntry aDPSourceMap_Impl[] =
1089 : {
1090 0 : {MAP_CHAR_LEN(SC_UNO_DP_COLGRAND), 0, &getBooleanCppuType(), 0, 0 },
1091 0 : {MAP_CHAR_LEN(SC_UNO_DP_DATADESC), 0, &getCppuType((rtl::OUString*)0), beans::PropertyAttribute::READONLY, 0 },
1092 0 : {MAP_CHAR_LEN(SC_UNO_DP_IGNOREEMPTY), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only
1093 0 : {MAP_CHAR_LEN(SC_UNO_DP_REPEATEMPTY), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only
1094 0 : {MAP_CHAR_LEN(SC_UNO_DP_ROWGRAND), 0, &getBooleanCppuType(), 0, 0 },
1095 0 : {MAP_CHAR_LEN(SC_UNO_DP_ROWFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
1096 0 : {MAP_CHAR_LEN(SC_UNO_DP_COLUMNFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
1097 0 : {MAP_CHAR_LEN(SC_UNO_DP_DATAFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
1098 0 : {MAP_CHAR_LEN(SC_UNO_DP_GRANDTOTAL_NAME), 0, &getCppuType(static_cast<OUString*>(0)), 0, 0 },
1099 : {0,0,0,0,0,0}
1100 0 : };
1101 : static uno::Reference<beans::XPropertySetInfo> aRef =
1102 0 : new SfxItemPropertySetInfo( aDPSourceMap_Impl );
1103 0 : return aRef;
1104 : }
1105 :
1106 100 : void SAL_CALL ScDPSource::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
1107 : throw(beans::UnknownPropertyException, beans::PropertyVetoException,
1108 : lang::IllegalArgumentException, lang::WrappedTargetException,
1109 : uno::RuntimeException)
1110 : {
1111 100 : if (aPropertyName.equalsAscii(SC_UNO_DP_COLGRAND))
1112 25 : bColumnGrand = lcl_GetBoolFromAny(aValue);
1113 75 : else if (aPropertyName.equalsAscii(SC_UNO_DP_ROWGRAND))
1114 25 : bRowGrand = lcl_GetBoolFromAny(aValue);
1115 50 : else if (aPropertyName.equalsAscii(SC_UNO_DP_IGNOREEMPTY))
1116 25 : setIgnoreEmptyRows( lcl_GetBoolFromAny( aValue ) );
1117 25 : else if (aPropertyName.equalsAscii(SC_UNO_DP_REPEATEMPTY))
1118 25 : setRepeatIfEmpty( lcl_GetBoolFromAny( aValue ) );
1119 0 : else if (aPropertyName.equalsAscii(SC_UNO_DP_GRANDTOTAL_NAME))
1120 : {
1121 0 : OUString aName;
1122 0 : if (aValue >>= aName)
1123 0 : mpGrandTotalName.reset(new OUString(aName));
1124 : }
1125 : else
1126 : {
1127 : OSL_FAIL("unknown property");
1128 : //! THROW( UnknownPropertyException() );
1129 : }
1130 100 : }
1131 :
1132 25 : uno::Any SAL_CALL ScDPSource::getPropertyValue( const rtl::OUString& aPropertyName )
1133 : throw(beans::UnknownPropertyException, lang::WrappedTargetException,
1134 : uno::RuntimeException)
1135 : {
1136 25 : uno::Any aRet;
1137 25 : if ( aPropertyName.equalsAscii( SC_UNO_DP_COLGRAND ) )
1138 0 : lcl_SetBoolInAny(aRet, bColumnGrand);
1139 25 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_ROWGRAND ) )
1140 0 : lcl_SetBoolInAny(aRet, bRowGrand);
1141 25 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_IGNOREEMPTY ) )
1142 0 : lcl_SetBoolInAny(aRet, bIgnoreEmptyRows);
1143 25 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_REPEATEMPTY ) )
1144 0 : lcl_SetBoolInAny(aRet, bRepeatIfEmpty);
1145 25 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_DATADESC ) ) // read-only
1146 25 : aRet <<= getDataDescription();
1147 0 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_ROWFIELDCOUNT ) ) // read-only
1148 0 : aRet <<= static_cast<sal_Int32>(nRowDimCount);
1149 0 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_COLUMNFIELDCOUNT ) ) // read-only
1150 0 : aRet <<= static_cast<sal_Int32>(nColDimCount);
1151 0 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_DATAFIELDCOUNT ) ) // read-only
1152 0 : aRet <<= static_cast<sal_Int32>(nDataDimCount);
1153 0 : else if (aPropertyName.equalsAscii(SC_UNO_DP_GRANDTOTAL_NAME))
1154 : {
1155 0 : if (mpGrandTotalName.get())
1156 0 : aRet <<= *mpGrandTotalName;
1157 : }
1158 : else
1159 : {
1160 : OSL_FAIL("unknown property");
1161 : //! THROW( UnknownPropertyException() );
1162 : }
1163 25 : return aRet;
1164 : }
1165 :
1166 0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPSource )
1167 :
1168 : // -----------------------------------------------------------------------
1169 :
1170 25 : ScDPDimensions::ScDPDimensions( ScDPSource* pSrc ) :
1171 : pSource( pSrc ),
1172 25 : ppDims( NULL )
1173 : {
1174 : //! hold pSource
1175 :
1176 : // include data layout dimension and duplicated dimensions
1177 25 : nDimCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
1178 25 : }
1179 :
1180 75 : ScDPDimensions::~ScDPDimensions()
1181 : {
1182 : //! release pSource
1183 :
1184 25 : if (ppDims)
1185 : {
1186 128 : for (long i=0; i<nDimCount; i++)
1187 103 : if ( ppDims[i] )
1188 103 : ppDims[i]->release(); // ref-counted
1189 25 : delete[] ppDims;
1190 : }
1191 50 : }
1192 :
1193 2 : void ScDPDimensions::CountChanged()
1194 : {
1195 : // include data layout dimension and duplicated dimensions
1196 2 : long nNewCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
1197 2 : if ( ppDims )
1198 : {
1199 : long i;
1200 2 : long nCopy = Min( nNewCount, nDimCount );
1201 2 : ScDPDimension** ppNew = new ScDPDimension*[nNewCount];
1202 :
1203 8 : for (i=0; i<nCopy; i++) // copy existing dims
1204 6 : ppNew[i] = ppDims[i];
1205 4 : for (i=nCopy; i<nNewCount; i++) // clear additional pointers
1206 2 : ppNew[i] = NULL;
1207 2 : for (i=nCopy; i<nDimCount; i++) // delete old dims if count is decreased
1208 0 : if ( ppDims[i] )
1209 0 : ppDims[i]->release(); // ref-counted
1210 :
1211 2 : delete[] ppDims;
1212 2 : ppDims = ppNew;
1213 : }
1214 2 : nDimCount = nNewCount;
1215 2 : }
1216 :
1217 : // very simple XNameAccess implementation using getCount/getByIndex
1218 :
1219 591 : uno::Any SAL_CALL ScDPDimensions::getByName( const rtl::OUString& aName )
1220 : throw(container::NoSuchElementException,
1221 : lang::WrappedTargetException, uno::RuntimeException)
1222 : {
1223 591 : long nCount = getCount();
1224 1440 : for (long i=0; i<nCount; i++)
1225 1440 : if ( getByIndex(i)->getName() == aName )
1226 : {
1227 591 : uno::Reference<container::XNamed> xNamed = getByIndex(i);
1228 591 : uno::Any aRet;
1229 591 : aRet <<= xNamed;
1230 1182 : return aRet;
1231 : }
1232 :
1233 0 : throw container::NoSuchElementException();
1234 : // return uno::Any();
1235 : }
1236 :
1237 86 : uno::Sequence<rtl::OUString> SAL_CALL ScDPDimensions::getElementNames() throw(uno::RuntimeException)
1238 : {
1239 86 : long nCount = getCount();
1240 86 : uno::Sequence<rtl::OUString> aSeq(nCount);
1241 86 : rtl::OUString* pArr = aSeq.getArray();
1242 434 : for (long i=0; i<nCount; i++)
1243 348 : pArr[i] = getByIndex(i)->getName();
1244 86 : return aSeq;
1245 : }
1246 :
1247 0 : sal_Bool SAL_CALL ScDPDimensions::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
1248 : {
1249 0 : long nCount = getCount();
1250 0 : for (long i=0; i<nCount; i++)
1251 0 : if ( getByIndex(i)->getName() == aName )
1252 0 : return sal_True;
1253 0 : return false;
1254 : }
1255 :
1256 0 : uno::Type SAL_CALL ScDPDimensions::getElementType() throw(uno::RuntimeException)
1257 : {
1258 0 : return getCppuType((uno::Reference<container::XNamed>*)0);
1259 : }
1260 :
1261 0 : sal_Bool SAL_CALL ScDPDimensions::hasElements() throw(uno::RuntimeException)
1262 : {
1263 0 : return ( getCount() > 0 );
1264 : }
1265 :
1266 : // end of XNameAccess implementation
1267 :
1268 697 : long ScDPDimensions::getCount() const
1269 : {
1270 : // in tabular data, every column of source data is a dimension
1271 :
1272 697 : return nDimCount;
1273 : }
1274 :
1275 3206 : ScDPDimension* ScDPDimensions::getByIndex(long nIndex) const
1276 : {
1277 3206 : if ( nIndex >= 0 && nIndex < nDimCount )
1278 : {
1279 3206 : if ( !ppDims )
1280 : {
1281 25 : ((ScDPDimensions*)this)->ppDims = new ScDPDimension*[nDimCount];
1282 126 : for (long i=0; i<nDimCount; i++)
1283 101 : ppDims[i] = NULL;
1284 : }
1285 3206 : if ( !ppDims[nIndex] )
1286 : {
1287 103 : ppDims[nIndex] = new ScDPDimension( pSource, nIndex );
1288 103 : ppDims[nIndex]->acquire(); // ref-counted
1289 : }
1290 :
1291 3206 : return ppDims[nIndex];
1292 : }
1293 :
1294 0 : return NULL; //! exception?
1295 : }
1296 :
1297 : // -----------------------------------------------------------------------
1298 :
1299 103 : ScDPDimension::ScDPDimension( ScDPSource* pSrc, long nD ) :
1300 : pSource( pSrc ),
1301 : nDim( nD ),
1302 : pHierarchies( NULL ),
1303 : nUsedHier( 0 ),
1304 : nFunction( SUBTOTAL_FUNC_SUM ), // sum is default
1305 : mpLayoutName(NULL),
1306 : mpSubtotalName(NULL),
1307 : nSourceDim( -1 ),
1308 : bHasSelectedPage( false ),
1309 : pSelectedData( NULL ),
1310 103 : mbHasHiddenMember(false)
1311 : {
1312 : //! hold pSource
1313 103 : }
1314 :
1315 309 : ScDPDimension::~ScDPDimension()
1316 : {
1317 : //! release pSource
1318 :
1319 103 : if ( pHierarchies )
1320 101 : pHierarchies->release(); // ref-counted
1321 :
1322 103 : delete pSelectedData;
1323 206 : }
1324 :
1325 396 : ScDPHierarchies* ScDPDimension::GetHierarchiesObject()
1326 : {
1327 396 : if (!pHierarchies)
1328 : {
1329 101 : pHierarchies = new ScDPHierarchies( pSource, nDim );
1330 101 : pHierarchies->acquire(); // ref-counted
1331 : }
1332 396 : return pHierarchies;
1333 : }
1334 :
1335 128 : const rtl::OUString* ScDPDimension::GetLayoutName() const
1336 : {
1337 128 : return mpLayoutName.get();
1338 : }
1339 :
1340 0 : const rtl::OUString* ScDPDimension::GetSubtotalName() const
1341 : {
1342 0 : return mpSubtotalName.get();
1343 : }
1344 :
1345 203 : uno::Reference<container::XNameAccess> SAL_CALL ScDPDimension::getHierarchies()
1346 : throw(uno::RuntimeException)
1347 : {
1348 203 : return GetHierarchiesObject();
1349 : }
1350 :
1351 2590 : ::rtl::OUString SAL_CALL ScDPDimension::getName() throw(uno::RuntimeException)
1352 : {
1353 2590 : if (!aName.isEmpty())
1354 26 : return aName;
1355 : else
1356 2564 : return pSource->GetData()->getDimensionName( nDim );
1357 : }
1358 :
1359 2 : void SAL_CALL ScDPDimension::setName( const ::rtl::OUString& rNewName ) throw(uno::RuntimeException)
1360 : {
1361 : // used after cloning
1362 2 : aName = rNewName;
1363 2 : }
1364 :
1365 206 : sal_uInt16 ScDPDimension::getOrientation() const
1366 : {
1367 206 : return pSource->GetOrientation( nDim );
1368 : }
1369 :
1370 202 : void ScDPDimension::setOrientation(sal_uInt16 nNew)
1371 : {
1372 202 : pSource->SetOrientation( nDim, nNew );
1373 202 : }
1374 :
1375 103 : long ScDPDimension::getPosition() const
1376 : {
1377 103 : return pSource->GetPosition( nDim );
1378 : }
1379 :
1380 359 : bool ScDPDimension::getIsDataLayoutDimension() const
1381 : {
1382 359 : return pSource->GetData()->getIsDataLayoutDimension( nDim );
1383 : }
1384 :
1385 62 : sal_uInt16 ScDPDimension::getFunction() const
1386 : {
1387 62 : return nFunction;
1388 : }
1389 :
1390 101 : void ScDPDimension::setFunction(sal_uInt16 nNew)
1391 : {
1392 101 : nFunction = nNew;
1393 101 : }
1394 :
1395 219 : long ScDPDimension::getUsedHierarchy() const
1396 : {
1397 219 : return nUsedHier;
1398 : }
1399 :
1400 70 : void ScDPDimension::setUsedHierarchy(long /* nNew */)
1401 : {
1402 : // #i52547# don't use the incomplete date hierarchy implementation - ignore the call
1403 70 : }
1404 :
1405 2 : ScDPDimension* ScDPDimension::CreateCloneObject()
1406 : {
1407 : OSL_ENSURE( nSourceDim < 0, "recursive duplicate - not implemented" );
1408 :
1409 : //! set new name here, or temporary name ???
1410 2 : rtl::OUString aNewName = aName;
1411 :
1412 2 : ScDPDimension* pNew = pSource->AddDuplicated( nDim, aNewName );
1413 :
1414 2 : pNew->aName = aNewName; //! here or in source?
1415 2 : pNew->nSourceDim = nDim; //! recursive?
1416 :
1417 2 : return pNew;
1418 : }
1419 :
1420 2 : uno::Reference<util::XCloneable> SAL_CALL ScDPDimension::createClone() throw(uno::RuntimeException)
1421 : {
1422 2 : return CreateCloneObject();
1423 : }
1424 :
1425 31 : const sheet::DataPilotFieldReference& ScDPDimension::GetReferenceValue() const
1426 : {
1427 31 : return aReferenceValue;
1428 : }
1429 :
1430 0 : const ScDPItemData& ScDPDimension::GetSelectedData()
1431 : {
1432 0 : if ( !pSelectedData )
1433 : {
1434 : // find the named member to initialize pSelectedData from it, with name and value
1435 :
1436 0 : long nLevel = 0;
1437 :
1438 0 : long nHierarchy = getUsedHierarchy();
1439 0 : if ( nHierarchy >= GetHierarchiesObject()->getCount() )
1440 0 : nHierarchy = 0;
1441 0 : ScDPLevels* pLevels = GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
1442 0 : long nLevCount = pLevels->getCount();
1443 0 : if ( nLevel < nLevCount )
1444 : {
1445 0 : ScDPMembers* pMembers = pLevels->getByIndex(nLevel)->GetMembersObject();
1446 :
1447 : //! merge with ScDPMembers::getByName
1448 0 : long nCount = pMembers->getCount();
1449 0 : for (long i=0; i<nCount && !pSelectedData; i++)
1450 : {
1451 0 : ScDPMember* pMember = pMembers->getByIndex(i);
1452 0 : if (aSelectedPage.equals(pMember->GetNameStr()))
1453 : {
1454 0 : pSelectedData = new ScDPItemData();
1455 0 : pMember->FillItemData( *pSelectedData );
1456 : }
1457 : }
1458 : }
1459 :
1460 0 : if ( !pSelectedData )
1461 0 : pSelectedData = new ScDPItemData(aSelectedPage); // default - name only
1462 : }
1463 :
1464 0 : return *pSelectedData;
1465 : }
1466 :
1467 : // XPropertySet
1468 :
1469 0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPDimension::getPropertySetInfo()
1470 : throw(uno::RuntimeException)
1471 : {
1472 0 : SolarMutexGuard aGuard;
1473 :
1474 : static SfxItemPropertyMapEntry aDPDimensionMap_Impl[] =
1475 : {
1476 0 : {MAP_CHAR_LEN(SC_UNO_DP_FILTER), 0, &getCppuType((uno::Sequence<sheet::TableFilterField>*)0), 0, 0 },
1477 0 : {MAP_CHAR_LEN(SC_UNO_DP_FLAGS), 0, &getCppuType((sal_Int32*)0), beans::PropertyAttribute::READONLY, 0 },
1478 0 : {MAP_CHAR_LEN(SC_UNO_DP_FUNCTION), 0, &getCppuType((sheet::GeneralFunction*)0), 0, 0 },
1479 0 : {MAP_CHAR_LEN(SC_UNO_DP_ISDATALAYOUT), 0, &getBooleanCppuType(), beans::PropertyAttribute::READONLY, 0 },
1480 0 : {MAP_CHAR_LEN(SC_UNO_DP_NUMBERFO), 0, &getCppuType((sal_Int32*)0), beans::PropertyAttribute::READONLY, 0 },
1481 0 : {MAP_CHAR_LEN(SC_UNO_DP_ORIENTATION), 0, &getCppuType((sheet::DataPilotFieldOrientation*)0), 0, 0 },
1482 0 : {MAP_CHAR_LEN(SC_UNO_DP_ORIGINAL), 0, &getCppuType((uno::Reference<container::XNamed>*)0), beans::PropertyAttribute::READONLY, 0 },
1483 0 : {MAP_CHAR_LEN(SC_UNO_DP_ORIGINAL_POS), 0, &getCppuType((sal_Int32*)0), 0, 0 },
1484 0 : {MAP_CHAR_LEN(SC_UNO_DP_POSITION), 0, &getCppuType((sal_Int32*)0), 0, 0 },
1485 0 : {MAP_CHAR_LEN(SC_UNO_DP_REFVALUE), 0, &getCppuType((sheet::DataPilotFieldReference*)0), 0, 0 },
1486 0 : {MAP_CHAR_LEN(SC_UNO_DP_USEDHIERARCHY), 0, &getCppuType((sal_Int32*)0), 0, 0 },
1487 0 : {MAP_CHAR_LEN(SC_UNO_DP_LAYOUTNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 },
1488 0 : {MAP_CHAR_LEN(SC_UNO_DP_FIELD_SUBTOTALNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 },
1489 0 : {MAP_CHAR_LEN(SC_UNO_DP_HAS_HIDDEN_MEMBER), 0, &getBooleanCppuType(), 0, 0 },
1490 : {0,0,0,0,0,0}
1491 0 : };
1492 : static uno::Reference<beans::XPropertySetInfo> aRef =
1493 0 : new SfxItemPropertySetInfo( aDPDimensionMap_Impl );
1494 0 : return aRef;
1495 : }
1496 :
1497 474 : void SAL_CALL ScDPDimension::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
1498 : throw(beans::UnknownPropertyException, beans::PropertyVetoException,
1499 : lang::IllegalArgumentException, lang::WrappedTargetException,
1500 : uno::RuntimeException)
1501 : {
1502 474 : if ( aPropertyName.equalsAscii( SC_UNO_DP_USEDHIERARCHY ) )
1503 : {
1504 70 : sal_Int32 nInt = 0;
1505 70 : if (aValue >>= nInt)
1506 70 : setUsedHierarchy( nInt );
1507 : }
1508 404 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_ORIENTATION ) )
1509 : {
1510 : sheet::DataPilotFieldOrientation eEnum;
1511 202 : if (aValue >>= eEnum)
1512 202 : setOrientation( sal::static_int_cast<sal_uInt16>(eEnum) );
1513 : }
1514 202 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_FUNCTION ) )
1515 : {
1516 : sheet::GeneralFunction eEnum;
1517 101 : if (aValue >>= eEnum)
1518 101 : setFunction( sal::static_int_cast<sal_uInt16>(eEnum) );
1519 : }
1520 101 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_REFVALUE ) )
1521 0 : aValue >>= aReferenceValue;
1522 101 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_FILTER ) )
1523 : {
1524 0 : sal_Bool bDone = false;
1525 0 : uno::Sequence<sheet::TableFilterField> aSeq;
1526 0 : if (aValue >>= aSeq)
1527 : {
1528 0 : sal_Int32 nLength = aSeq.getLength();
1529 0 : if ( nLength == 0 )
1530 : {
1531 0 : aSelectedPage = rtl::OUString();
1532 0 : bHasSelectedPage = false;
1533 0 : bDone = sal_True;
1534 : }
1535 0 : else if ( nLength == 1 )
1536 : {
1537 0 : const sheet::TableFilterField& rField = aSeq[0];
1538 0 : if ( rField.Field == 0 && rField.Operator == sheet::FilterOperator_EQUAL && !rField.IsNumeric )
1539 : {
1540 0 : aSelectedPage = rField.StringValue;
1541 0 : bHasSelectedPage = true;
1542 0 : bDone = sal_True;
1543 : }
1544 : }
1545 : }
1546 0 : if ( !bDone )
1547 : {
1548 : OSL_FAIL("Filter property is not a single string");
1549 0 : throw lang::IllegalArgumentException();
1550 : }
1551 0 : DELETEZ( pSelectedData ); // invalid after changing aSelectedPage
1552 : }
1553 101 : else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
1554 : {
1555 0 : OUString aTmpName;
1556 0 : if (aValue >>= aTmpName)
1557 0 : mpLayoutName.reset(new OUString(aTmpName));
1558 : }
1559 101 : else if (aPropertyName.equalsAscii(SC_UNO_DP_FIELD_SUBTOTALNAME))
1560 : {
1561 0 : OUString aTmpName;
1562 0 : if (aValue >>= aTmpName)
1563 0 : mpSubtotalName.reset(new OUString(aTmpName));
1564 : }
1565 101 : else if (aPropertyName.equalsAscii(SC_UNO_DP_HAS_HIDDEN_MEMBER))
1566 : {
1567 101 : sal_Bool b = false;
1568 101 : aValue >>= b;
1569 101 : mbHasHiddenMember = b;
1570 : }
1571 : else
1572 : {
1573 : OSL_FAIL("unknown property");
1574 : //! THROW( UnknownPropertyException() );
1575 : }
1576 474 : }
1577 :
1578 768 : uno::Any SAL_CALL ScDPDimension::getPropertyValue( const rtl::OUString& aPropertyName )
1579 : throw(beans::UnknownPropertyException, lang::WrappedTargetException,
1580 : uno::RuntimeException)
1581 : {
1582 768 : uno::Any aRet;
1583 768 : if ( aPropertyName.equalsAscii( SC_UNO_DP_POSITION ) )
1584 103 : aRet <<= (sal_Int32) getPosition();
1585 665 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_USEDHIERARCHY ) )
1586 99 : aRet <<= (sal_Int32) getUsedHierarchy();
1587 566 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_ORIENTATION ) )
1588 : {
1589 206 : sheet::DataPilotFieldOrientation eVal = (sheet::DataPilotFieldOrientation)getOrientation();
1590 206 : aRet <<= eVal;
1591 : }
1592 360 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_FUNCTION ) )
1593 : {
1594 0 : sheet::GeneralFunction eVal = (sheet::GeneralFunction)getFunction();
1595 0 : aRet <<= eVal;
1596 : }
1597 360 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_REFVALUE ) )
1598 0 : aRet <<= aReferenceValue;
1599 360 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_ISDATALAYOUT ) ) // read-only properties
1600 208 : lcl_SetBoolInAny( aRet, getIsDataLayoutDimension() );
1601 152 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_NUMBERFO ) )
1602 : {
1603 31 : sal_Int32 nFormat = 0;
1604 31 : sheet::GeneralFunction eFunc = (sheet::GeneralFunction)getFunction();
1605 : // #i63745# don't use source format for "count"
1606 31 : if ( eFunc != sheet::GeneralFunction_COUNT && eFunc != sheet::GeneralFunction_COUNTNUMS )
1607 29 : nFormat = pSource->GetData()->GetNumberFormat( ( nSourceDim >= 0 ) ? nSourceDim : nDim );
1608 :
1609 31 : switch ( aReferenceValue.ReferenceType )
1610 : {
1611 : case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE:
1612 : case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
1613 : case sheet::DataPilotFieldReferenceType::ROW_PERCENTAGE:
1614 : case sheet::DataPilotFieldReferenceType::COLUMN_PERCENTAGE:
1615 : case sheet::DataPilotFieldReferenceType::TOTAL_PERCENTAGE:
1616 0 : nFormat = pSource->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset)NF_PERCENT_DEC2 );
1617 0 : break;
1618 : case sheet::DataPilotFieldReferenceType::INDEX:
1619 0 : nFormat = pSource->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset)NF_NUMBER_SYSTEM );
1620 0 : break;
1621 : default:
1622 31 : break;
1623 : }
1624 :
1625 31 : aRet <<= nFormat;
1626 : }
1627 121 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_ORIGINAL ) )
1628 : {
1629 0 : uno::Reference<container::XNamed> xOriginal;
1630 0 : if (nSourceDim >= 0)
1631 0 : xOriginal = pSource->GetDimensionsObject()->getByIndex(nSourceDim);
1632 0 : aRet <<= xOriginal;
1633 : }
1634 121 : else if (aPropertyName.equalsAscii(SC_UNO_DP_ORIGINAL_POS))
1635 : {
1636 4 : sal_Int32 nPos = static_cast<sal_Int32>(nSourceDim);
1637 4 : aRet <<= nPos;
1638 : }
1639 117 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_FILTER ) )
1640 : {
1641 0 : if ( bHasSelectedPage )
1642 : {
1643 : // single filter field: first field equal to selected string
1644 : sheet::TableFilterField aField( sheet::FilterConnection_AND, 0,
1645 0 : sheet::FilterOperator_EQUAL, false, 0.0, aSelectedPage );
1646 0 : aRet <<= uno::Sequence<sheet::TableFilterField>( &aField, 1 );
1647 : }
1648 : else
1649 0 : aRet <<= uno::Sequence<sheet::TableFilterField>(0);
1650 : }
1651 117 : else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
1652 7 : aRet <<= mpLayoutName.get() ? *mpLayoutName : OUString(RTL_CONSTASCII_USTRINGPARAM(""));
1653 110 : else if (aPropertyName.equalsAscii(SC_UNO_DP_FIELD_SUBTOTALNAME))
1654 4 : aRet <<= mpSubtotalName.get() ? *mpSubtotalName : OUString(RTL_CONSTASCII_USTRINGPARAM(""));
1655 106 : else if (aPropertyName.equalsAscii(SC_UNO_DP_HAS_HIDDEN_MEMBER))
1656 103 : aRet <<= static_cast<sal_Bool>(mbHasHiddenMember);
1657 3 : else if (aPropertyName.equalsAscii(SC_UNO_DP_FLAGS))
1658 : {
1659 3 : sal_Int32 nFlags = 0; // tabular data: all orientations are possible
1660 3 : aRet <<= nFlags;
1661 : }
1662 : else
1663 : {
1664 : OSL_FAIL("unknown property");
1665 : //! THROW( UnknownPropertyException() );
1666 : }
1667 768 : return aRet;
1668 : }
1669 :
1670 0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPDimension )
1671 :
1672 : // -----------------------------------------------------------------------
1673 :
1674 101 : ScDPHierarchies::ScDPHierarchies( ScDPSource* pSrc, long nD ) :
1675 : pSource( pSrc ),
1676 : nDim( nD ),
1677 101 : ppHiers( NULL )
1678 : {
1679 : //! hold pSource
1680 :
1681 : // date columns have 3 hierarchies (flat/quarter/week), other columns only one
1682 :
1683 : // #i52547# don't offer the incomplete date hierarchy implementation
1684 101 : nHierCount = 1;
1685 101 : }
1686 :
1687 303 : ScDPHierarchies::~ScDPHierarchies()
1688 : {
1689 : //! release pSource
1690 :
1691 101 : if (ppHiers)
1692 : {
1693 202 : for (long i=0; i<nHierCount; i++)
1694 101 : if ( ppHiers[i] )
1695 101 : ppHiers[i]->release(); // ref-counted
1696 101 : delete[] ppHiers;
1697 : }
1698 202 : }
1699 :
1700 : // very simple XNameAccess implementation using getCount/getByIndex
1701 :
1702 200 : uno::Any SAL_CALL ScDPHierarchies::getByName( const rtl::OUString& aName )
1703 : throw(container::NoSuchElementException,
1704 : lang::WrappedTargetException, uno::RuntimeException)
1705 : {
1706 200 : long nCount = getCount();
1707 200 : for (long i=0; i<nCount; i++)
1708 200 : if ( getByIndex(i)->getName() == aName )
1709 : {
1710 200 : uno::Reference<container::XNamed> xNamed = getByIndex(i);
1711 200 : uno::Any aRet;
1712 200 : aRet <<= xNamed;
1713 400 : return aRet;
1714 : }
1715 :
1716 0 : throw container::NoSuchElementException();
1717 : }
1718 :
1719 203 : uno::Sequence<rtl::OUString> SAL_CALL ScDPHierarchies::getElementNames() throw(uno::RuntimeException)
1720 : {
1721 203 : long nCount = getCount();
1722 203 : uno::Sequence<rtl::OUString> aSeq(nCount);
1723 203 : rtl::OUString* pArr = aSeq.getArray();
1724 406 : for (long i=0; i<nCount; i++)
1725 203 : pArr[i] = getByIndex(i)->getName();
1726 203 : return aSeq;
1727 : }
1728 :
1729 0 : sal_Bool SAL_CALL ScDPHierarchies::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
1730 : {
1731 0 : long nCount = getCount();
1732 0 : for (long i=0; i<nCount; i++)
1733 0 : if ( getByIndex(i)->getName() == aName )
1734 0 : return sal_True;
1735 0 : return false;
1736 : }
1737 :
1738 0 : uno::Type SAL_CALL ScDPHierarchies::getElementType() throw(uno::RuntimeException)
1739 : {
1740 0 : return getCppuType((uno::Reference<container::XNamed>*)0);
1741 : }
1742 :
1743 0 : sal_Bool SAL_CALL ScDPHierarchies::hasElements() throw(uno::RuntimeException)
1744 : {
1745 0 : return ( getCount() > 0 );
1746 : }
1747 :
1748 : // end of XNameAccess implementation
1749 :
1750 523 : long ScDPHierarchies::getCount() const
1751 : {
1752 523 : return nHierCount;
1753 : }
1754 :
1755 734 : ScDPHierarchy* ScDPHierarchies::getByIndex(long nIndex) const
1756 : {
1757 : // pass hierarchy index to new object in case the implementation
1758 : // will be extended to more than one hierarchy
1759 :
1760 734 : if ( nIndex >= 0 && nIndex < nHierCount )
1761 : {
1762 734 : if ( !ppHiers )
1763 : {
1764 101 : ((ScDPHierarchies*)this)->ppHiers = new ScDPHierarchy*[nHierCount];
1765 202 : for (long i=0; i<nHierCount; i++)
1766 101 : ppHiers[i] = NULL;
1767 : }
1768 734 : if ( !ppHiers[nIndex] )
1769 : {
1770 101 : ppHiers[nIndex] = new ScDPHierarchy( pSource, nDim, nIndex );
1771 101 : ppHiers[nIndex]->acquire(); // ref-counted
1772 : }
1773 :
1774 734 : return ppHiers[nIndex];
1775 : }
1776 :
1777 0 : return NULL; //! exception?
1778 : }
1779 :
1780 : // -----------------------------------------------------------------------
1781 :
1782 101 : ScDPHierarchy::ScDPHierarchy( ScDPSource* pSrc, long nD, long nH ) :
1783 : pSource( pSrc ),
1784 : nDim( nD ),
1785 : nHier( nH ),
1786 101 : pLevels( NULL )
1787 : {
1788 : //! hold pSource
1789 101 : }
1790 :
1791 303 : ScDPHierarchy::~ScDPHierarchy()
1792 : {
1793 : //! release pSource
1794 :
1795 101 : if (pLevels)
1796 101 : pLevels->release(); // ref-counted
1797 202 : }
1798 :
1799 331 : ScDPLevels* ScDPHierarchy::GetLevelsObject()
1800 : {
1801 331 : if (!pLevels)
1802 : {
1803 101 : pLevels = new ScDPLevels( pSource, nDim, nHier );
1804 101 : pLevels->acquire(); // ref-counted
1805 : }
1806 331 : return pLevels;
1807 : }
1808 :
1809 200 : uno::Reference<container::XNameAccess> SAL_CALL ScDPHierarchy::getLevels()
1810 : throw(uno::RuntimeException)
1811 : {
1812 200 : return GetLevelsObject();
1813 : }
1814 :
1815 403 : ::rtl::OUString SAL_CALL ScDPHierarchy::getName() throw(uno::RuntimeException)
1816 : {
1817 403 : rtl::OUString aRet; //! globstr-ID !!!!
1818 403 : switch (nHier)
1819 : {
1820 : case SC_DAPI_HIERARCHY_FLAT:
1821 403 : aRet = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("flat"));
1822 403 : break; //! name ???????
1823 : case SC_DAPI_HIERARCHY_QUARTER:
1824 0 : aRet = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Quarter"));
1825 0 : break; //! name ???????
1826 : case SC_DAPI_HIERARCHY_WEEK:
1827 0 : aRet = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Week"));
1828 0 : break; //! name ???????
1829 : default:
1830 : OSL_FAIL( "ScDPHierarchy::getName: unexpected hierarchy" );
1831 0 : break;
1832 : }
1833 403 : return aRet;
1834 : }
1835 :
1836 0 : void SAL_CALL ScDPHierarchy::setName( const ::rtl::OUString& /* rNewName */ ) throw(uno::RuntimeException)
1837 : {
1838 : OSL_FAIL("not implemented"); //! exception?
1839 0 : }
1840 :
1841 : // -----------------------------------------------------------------------
1842 :
1843 101 : ScDPLevels::ScDPLevels( ScDPSource* pSrc, long nD, long nH ) :
1844 : pSource( pSrc ),
1845 : nDim( nD ),
1846 : nHier( nH ),
1847 101 : ppLevs( NULL )
1848 : {
1849 : //! hold pSource
1850 :
1851 : // text columns have only one level
1852 :
1853 101 : long nSrcDim = pSource->GetSourceDim( nDim );
1854 101 : if ( pSource->IsDateDimension( nSrcDim ) )
1855 : {
1856 8 : switch ( nHier )
1857 : {
1858 8 : case SC_DAPI_HIERARCHY_FLAT: nLevCount = SC_DAPI_FLAT_LEVELS; break;
1859 0 : case SC_DAPI_HIERARCHY_QUARTER: nLevCount = SC_DAPI_QUARTER_LEVELS; break;
1860 0 : case SC_DAPI_HIERARCHY_WEEK: nLevCount = SC_DAPI_WEEK_LEVELS; break;
1861 : default:
1862 : OSL_FAIL("wrong hierarchy");
1863 0 : nLevCount = 0;
1864 : }
1865 : }
1866 : else
1867 93 : nLevCount = 1;
1868 101 : }
1869 :
1870 303 : ScDPLevels::~ScDPLevels()
1871 : {
1872 : //! release pSource
1873 :
1874 101 : if (ppLevs)
1875 : {
1876 202 : for (long i=0; i<nLevCount; i++)
1877 101 : if ( ppLevs[i] )
1878 101 : ppLevs[i]->release(); // ref-counted
1879 101 : delete[] ppLevs;
1880 : }
1881 202 : }
1882 :
1883 : // very simple XNameAccess implementation using getCount/getByIndex
1884 :
1885 200 : uno::Any SAL_CALL ScDPLevels::getByName( const rtl::OUString& aName )
1886 : throw(container::NoSuchElementException,
1887 : lang::WrappedTargetException, uno::RuntimeException)
1888 : {
1889 200 : long nCount = getCount();
1890 200 : for (long i=0; i<nCount; i++)
1891 200 : if ( getByIndex(i)->getName() == aName )
1892 : {
1893 200 : uno::Reference<container::XNamed> xNamed = getByIndex(i);
1894 200 : uno::Any aRet;
1895 200 : aRet <<= xNamed;
1896 400 : return aRet;
1897 : }
1898 :
1899 0 : throw container::NoSuchElementException();
1900 : }
1901 :
1902 200 : uno::Sequence<rtl::OUString> SAL_CALL ScDPLevels::getElementNames() throw(uno::RuntimeException)
1903 : {
1904 200 : long nCount = getCount();
1905 200 : uno::Sequence<rtl::OUString> aSeq(nCount);
1906 200 : rtl::OUString* pArr = aSeq.getArray();
1907 400 : for (long i=0; i<nCount; i++)
1908 200 : pArr[i] = getByIndex(i)->getName();
1909 200 : return aSeq;
1910 : }
1911 :
1912 0 : sal_Bool SAL_CALL ScDPLevels::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
1913 : {
1914 0 : long nCount = getCount();
1915 0 : for (long i=0; i<nCount; i++)
1916 0 : if ( getByIndex(i)->getName() == aName )
1917 0 : return sal_True;
1918 0 : return false;
1919 : }
1920 :
1921 0 : uno::Type SAL_CALL ScDPLevels::getElementType() throw(uno::RuntimeException)
1922 : {
1923 0 : return getCppuType((uno::Reference<container::XNamed>*)0);
1924 : }
1925 :
1926 0 : sal_Bool SAL_CALL ScDPLevels::hasElements() throw(uno::RuntimeException)
1927 : {
1928 0 : return ( getCount() > 0 );
1929 : }
1930 :
1931 : // end of XNameAccess implementation
1932 :
1933 520 : long ScDPLevels::getCount() const
1934 : {
1935 520 : return nLevCount;
1936 : }
1937 :
1938 712 : ScDPLevel* ScDPLevels::getByIndex(long nIndex) const
1939 : {
1940 712 : if ( nIndex >= 0 && nIndex < nLevCount )
1941 : {
1942 712 : if ( !ppLevs )
1943 : {
1944 101 : ((ScDPLevels*)this)->ppLevs = new ScDPLevel*[nLevCount];
1945 202 : for (long i=0; i<nLevCount; i++)
1946 101 : ppLevs[i] = NULL;
1947 : }
1948 712 : if ( !ppLevs[nIndex] )
1949 : {
1950 101 : ppLevs[nIndex] = new ScDPLevel( pSource, nDim, nHier, nIndex );
1951 101 : ppLevs[nIndex]->acquire(); // ref-counted
1952 : }
1953 :
1954 712 : return ppLevs[nIndex];
1955 : }
1956 :
1957 0 : return NULL; //! exception?
1958 : }
1959 :
1960 : // -----------------------------------------------------------------------
1961 :
1962 : class ScDPGlobalMembersOrder
1963 : {
1964 : ScDPLevel& rLevel;
1965 : sal_Bool bAscending;
1966 :
1967 : public:
1968 46 : ScDPGlobalMembersOrder( ScDPLevel& rLev, sal_Bool bAsc ) :
1969 : rLevel(rLev),
1970 46 : bAscending(bAsc)
1971 46 : {}
1972 377 : ~ScDPGlobalMembersOrder() {}
1973 :
1974 : sal_Bool operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const;
1975 : };
1976 :
1977 307 : sal_Bool ScDPGlobalMembersOrder::operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const
1978 : {
1979 307 : sal_Int32 nCompare = 0;
1980 : // seems that some ::std::sort() implementations pass the same index twice
1981 307 : if( nIndex1 != nIndex2 )
1982 : {
1983 307 : ScDPMembers* pMembers = rLevel.GetMembersObject();
1984 307 : ScDPMember* pMember1 = pMembers->getByIndex(nIndex1);
1985 307 : ScDPMember* pMember2 = pMembers->getByIndex(nIndex2);
1986 307 : nCompare = pMember1->Compare( *pMember2 );
1987 : }
1988 307 : return bAscending ? (nCompare < 0) : (nCompare > 0);
1989 : }
1990 :
1991 : // -----------------------------------------------------------------------
1992 :
1993 101 : ScDPLevel::ScDPLevel( ScDPSource* pSrc, long nD, long nH, long nL ) :
1994 : pSource( pSrc ),
1995 : nDim( nD ),
1996 : nHier( nH ),
1997 : nLev( nL ),
1998 : pMembers( NULL ),
1999 101 : aSortInfo( EMPTY_STRING, sal_True, sheet::DataPilotFieldSortMode::NAME ), // default: sort by name
2000 : nSortMeasure( 0 ),
2001 : nAutoMeasure( 0 ),
2002 : bShowEmpty( false ),
2003 202 : bEnableLayout( false )
2004 : {
2005 : //! hold pSource
2006 : // aSubTotals is empty
2007 101 : }
2008 :
2009 303 : ScDPLevel::~ScDPLevel()
2010 : {
2011 : //! release pSource
2012 :
2013 101 : if ( pMembers )
2014 56 : pMembers->release(); // ref-counted
2015 202 : }
2016 :
2017 46 : void ScDPLevel::EvaluateSortOrder()
2018 : {
2019 46 : switch (aSortInfo.Mode)
2020 : {
2021 : case sheet::DataPilotFieldSortMode::DATA:
2022 : {
2023 : // find index of measure (index among data dimensions)
2024 :
2025 0 : long nMeasureCount = pSource->GetDataDimensionCount();
2026 0 : for (long nMeasure=0; nMeasure<nMeasureCount; nMeasure++)
2027 : {
2028 0 : if (pSource->GetDataDimName(nMeasure).equals(aSortInfo.Field))
2029 : {
2030 0 : nSortMeasure = nMeasure;
2031 0 : break;
2032 : }
2033 : }
2034 :
2035 : //! error if not found?
2036 : }
2037 0 : break;
2038 : case sheet::DataPilotFieldSortMode::MANUAL:
2039 : case sheet::DataPilotFieldSortMode::NAME:
2040 : {
2041 46 : ScDPMembers* pLocalMembers = GetMembersObject();
2042 46 : long nCount = pLocalMembers->getCount();
2043 :
2044 46 : aGlobalOrder.resize( nCount );
2045 248 : for (long nPos=0; nPos<nCount; nPos++)
2046 202 : aGlobalOrder[nPos] = nPos;
2047 :
2048 : // allow manual or name (manual is always ascending)
2049 46 : sal_Bool bAscending = ( aSortInfo.Mode == sheet::DataPilotFieldSortMode::MANUAL || aSortInfo.IsAscending );
2050 46 : ScDPGlobalMembersOrder aComp( *this, bAscending );
2051 46 : ::std::sort( aGlobalOrder.begin(), aGlobalOrder.end(), aComp );
2052 : }
2053 46 : break;
2054 : }
2055 :
2056 46 : if ( aAutoShowInfo.IsEnabled )
2057 : {
2058 : // find index of measure (index among data dimensions)
2059 :
2060 0 : long nMeasureCount = pSource->GetDataDimensionCount();
2061 0 : for (long nMeasure=0; nMeasure<nMeasureCount; nMeasure++)
2062 : {
2063 0 : if (pSource->GetDataDimName(nMeasure).equals(aAutoShowInfo.DataField))
2064 : {
2065 0 : nAutoMeasure = nMeasure;
2066 0 : break;
2067 : }
2068 : }
2069 :
2070 : //! error if not found?
2071 : }
2072 46 : }
2073 :
2074 64 : void ScDPLevel::SetEnableLayout(bool bSet)
2075 : {
2076 64 : bEnableLayout = bSet;
2077 64 : }
2078 :
2079 523 : ScDPMembers* ScDPLevel::GetMembersObject()
2080 : {
2081 523 : if (!pMembers)
2082 : {
2083 56 : pMembers = new ScDPMembers( pSource, nDim, nHier, nLev );
2084 56 : pMembers->acquire(); // ref-counted
2085 : }
2086 523 : return pMembers;
2087 : }
2088 :
2089 23 : uno::Reference<container::XNameAccess> SAL_CALL ScDPLevel::getMembers() throw(uno::RuntimeException)
2090 : {
2091 23 : return GetMembersObject();
2092 : }
2093 :
2094 83 : uno::Sequence<sheet::MemberResult> SAL_CALL ScDPLevel::getResults() throw(uno::RuntimeException)
2095 : {
2096 83 : const uno::Sequence<sheet::MemberResult>* pRes = pSource->GetMemberResults( this );
2097 83 : if (pRes)
2098 83 : return *pRes;
2099 :
2100 0 : return uno::Sequence<sheet::MemberResult>(0); //! Error?
2101 : }
2102 :
2103 493 : ::rtl::OUString SAL_CALL ScDPLevel::getName() throw(uno::RuntimeException)
2104 : {
2105 493 : long nSrcDim = pSource->GetSourceDim( nDim );
2106 493 : if ( pSource->IsDateDimension( nSrcDim ) )
2107 : {
2108 40 : rtl::OUString aRet; //! globstr-ID !!!!
2109 :
2110 40 : if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
2111 : {
2112 0 : switch ( nLev )
2113 : {
2114 : case SC_DAPI_LEVEL_YEAR:
2115 0 : aRet = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Year"));
2116 0 : break;
2117 : case SC_DAPI_LEVEL_QUARTER:
2118 0 : aRet = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Quarter"));
2119 0 : break;
2120 : case SC_DAPI_LEVEL_MONTH:
2121 0 : aRet = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Month"));
2122 0 : break;
2123 : case SC_DAPI_LEVEL_DAY:
2124 0 : aRet = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Day"));
2125 0 : break;
2126 : default:
2127 : OSL_FAIL( "ScDPLevel::getName: unexpected level" );
2128 0 : break;
2129 : }
2130 : }
2131 40 : else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
2132 : {
2133 0 : switch ( nLev )
2134 : {
2135 : case SC_DAPI_LEVEL_YEAR:
2136 0 : aRet = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Year"));
2137 0 : break;
2138 : case SC_DAPI_LEVEL_WEEK:
2139 0 : aRet = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Week"));
2140 0 : break;
2141 : case SC_DAPI_LEVEL_WEEKDAY:
2142 0 : aRet = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Weekday"));
2143 0 : break;
2144 : default:
2145 : OSL_FAIL( "ScDPLevel::getName: unexpected level" );
2146 0 : break;
2147 : }
2148 : }
2149 40 : if (!aRet.isEmpty())
2150 0 : return aRet;
2151 : }
2152 :
2153 493 : ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
2154 493 : if (!pDim)
2155 0 : return rtl::OUString();
2156 :
2157 493 : return pDim->getName();
2158 : }
2159 :
2160 0 : void SAL_CALL ScDPLevel::setName( const ::rtl::OUString& /* rNewName */ ) throw(uno::RuntimeException)
2161 : {
2162 : OSL_FAIL("not implemented"); //! exception?
2163 0 : }
2164 :
2165 1305 : uno::Sequence<sheet::GeneralFunction> ScDPLevel::getSubTotals() const
2166 : {
2167 : //! separate functions for settings and evaluation?
2168 :
2169 1305 : long nSrcDim = pSource->GetSourceDim( nDim );
2170 1305 : if ( !pSource->SubTotalAllowed( nSrcDim ) )
2171 1087 : return uno::Sequence<sheet::GeneralFunction>(0);
2172 :
2173 218 : return aSubTotals;
2174 : }
2175 :
2176 304 : bool ScDPLevel::getShowEmpty() const
2177 : {
2178 304 : return bShowEmpty;
2179 : }
2180 :
2181 : // XPropertySet
2182 :
2183 0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPLevel::getPropertySetInfo()
2184 : throw(uno::RuntimeException)
2185 : {
2186 0 : SolarMutexGuard aGuard;
2187 :
2188 : static SfxItemPropertyMapEntry aDPLevelMap_Impl[] =
2189 : {
2190 : //! change type of AutoShow/Layout/Sorting to API struct when available
2191 0 : {MAP_CHAR_LEN(SC_UNO_DP_AUTOSHOW), 0, &getCppuType((sheet::DataPilotFieldAutoShowInfo*)0), 0, 0 },
2192 0 : {MAP_CHAR_LEN(SC_UNO_DP_LAYOUT), 0, &getCppuType((sheet::DataPilotFieldLayoutInfo*)0), 0, 0 },
2193 0 : {MAP_CHAR_LEN(SC_UNO_DP_SHOWEMPTY), 0, &getBooleanCppuType(), 0, 0 },
2194 0 : {MAP_CHAR_LEN(SC_UNO_DP_SORTING), 0, &getCppuType((sheet::DataPilotFieldSortInfo*)0), 0, 0 },
2195 0 : {MAP_CHAR_LEN(SC_UNO_DP_SUBTOTAL), 0, &getCppuType((uno::Sequence<sheet::GeneralFunction>*)0), 0, 0 },
2196 : {0,0,0,0,0,0}
2197 0 : };
2198 : static uno::Reference<beans::XPropertySetInfo> aRef =
2199 0 : new SfxItemPropertySetInfo( aDPLevelMap_Impl );
2200 0 : return aRef;
2201 : }
2202 :
2203 142 : void SAL_CALL ScDPLevel::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
2204 : throw(beans::UnknownPropertyException, beans::PropertyVetoException,
2205 : lang::IllegalArgumentException, lang::WrappedTargetException,
2206 : uno::RuntimeException)
2207 : {
2208 142 : if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWEMPTY ) )
2209 25 : bShowEmpty = lcl_GetBoolFromAny(aValue);
2210 117 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_SUBTOTAL ) )
2211 0 : aValue >>= aSubTotals;
2212 117 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_SORTING ) )
2213 39 : aValue >>= aSortInfo;
2214 78 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_AUTOSHOW ) )
2215 39 : aValue >>= aAutoShowInfo;
2216 39 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_LAYOUT ) )
2217 39 : aValue >>= aLayoutInfo;
2218 : else
2219 : {
2220 : OSL_FAIL("unknown property");
2221 : }
2222 142 : }
2223 :
2224 105 : uno::Any SAL_CALL ScDPLevel::getPropertyValue( const rtl::OUString& aPropertyName )
2225 : throw(beans::UnknownPropertyException, lang::WrappedTargetException,
2226 : uno::RuntimeException)
2227 : {
2228 105 : uno::Any aRet;
2229 105 : if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWEMPTY ) )
2230 3 : lcl_SetBoolInAny(aRet, bShowEmpty);
2231 102 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_SUBTOTAL ) )
2232 : {
2233 0 : uno::Sequence<sheet::GeneralFunction> aSeq = getSubTotals(); //! avoid extra copy?
2234 0 : aRet <<= aSeq;
2235 : }
2236 102 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_SORTING ) )
2237 3 : aRet <<= aSortInfo;
2238 99 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_AUTOSHOW ) )
2239 3 : aRet <<= aAutoShowInfo;
2240 96 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_LAYOUT ) )
2241 3 : aRet <<= aLayoutInfo;
2242 93 : else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
2243 : {
2244 : // read only property
2245 93 : long nSrcDim = pSource->GetSourceDim(nDim);
2246 93 : ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
2247 93 : if (!pDim)
2248 0 : return aRet;
2249 :
2250 93 : const OUString* pLayoutName = pDim->GetLayoutName();
2251 93 : if (!pLayoutName)
2252 93 : return aRet;
2253 :
2254 0 : aRet <<= *pLayoutName;
2255 : }
2256 : else
2257 : {
2258 : OSL_FAIL("unknown property");
2259 : }
2260 12 : return aRet;
2261 : }
2262 :
2263 0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPLevel )
2264 :
2265 : // -----------------------------------------------------------------------
2266 :
2267 56 : ScDPMembers::ScDPMembers( ScDPSource* pSrc, long nD, long nH, long nL ) :
2268 : pSource( pSrc ),
2269 : nDim( nD ),
2270 : nHier( nH ),
2271 56 : nLev( nL )
2272 : {
2273 : //! hold pSource
2274 :
2275 56 : long nSrcDim = pSource->GetSourceDim( nDim );
2276 56 : if ( pSource->IsDataLayoutDimension(nSrcDim) )
2277 6 : nMbrCount = pSource->GetDataDimensionCount();
2278 50 : else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
2279 : {
2280 0 : nMbrCount = 0;
2281 0 : if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
2282 : {
2283 0 : switch (nLev)
2284 : {
2285 : case SC_DAPI_LEVEL_YEAR:
2286 : {
2287 0 : const ScDPItemData* pLastNumData = NULL;
2288 0 : for ( SCROW n = 0 ;n <GetSrcItemsCount() ; n-- )
2289 : {
2290 0 : const ScDPItemData* pData = GetSrcItemDataByIndex( n );
2291 0 : if ( pData && pData->HasStringData() )
2292 0 : break;
2293 : else
2294 0 : pLastNumData = pData;
2295 : }
2296 :
2297 0 : if ( pLastNumData )
2298 : {
2299 0 : const ScDPItemData* pFirstData = GetSrcItemDataByIndex( 0 );
2300 0 : double fFirstVal = pFirstData->GetValue();
2301 0 : double fLastVal = pLastNumData->GetValue();
2302 :
2303 : long nFirstYear = pSource->GetData()->GetDatePart(
2304 0 : (long)::rtl::math::approxFloor( fFirstVal ),
2305 0 : nHier, nLev );
2306 : long nLastYear = pSource->GetData()->GetDatePart(
2307 0 : (long)::rtl::math::approxFloor( fLastVal ),
2308 0 : nHier, nLev );
2309 :
2310 0 : nMbrCount = nLastYear + 1 - nFirstYear;
2311 : }
2312 : else
2313 0 : nMbrCount = 0; // no values
2314 : }
2315 0 : break;
2316 0 : case SC_DAPI_LEVEL_QUARTER: nMbrCount = 4; break;
2317 0 : case SC_DAPI_LEVEL_MONTH: nMbrCount = 12; break;
2318 0 : case SC_DAPI_LEVEL_DAY: nMbrCount = 31; break;
2319 : default:
2320 : OSL_FAIL( "ScDPMembers::ScDPMembers: unexpected level" );
2321 0 : break;
2322 : }
2323 : }
2324 0 : else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
2325 : {
2326 0 : switch (nLev)
2327 : {
2328 0 : case SC_DAPI_LEVEL_YEAR: nMbrCount = 1; break; //! get years from source
2329 0 : case SC_DAPI_LEVEL_WEEK: nMbrCount = 53; break;
2330 0 : case SC_DAPI_LEVEL_WEEKDAY: nMbrCount = 7; break;
2331 : default:
2332 : OSL_FAIL( "ScDPMembers::ScDPMembers: unexpected level" );
2333 0 : break;
2334 : }
2335 : }
2336 : }
2337 : else
2338 50 : nMbrCount = pSource->GetData()->GetMembersCount( nSrcDim );
2339 56 : }
2340 :
2341 112 : ScDPMembers::~ScDPMembers()
2342 : {
2343 112 : }
2344 :
2345 : // XNameAccess implementation using getCount/getByIndex
2346 :
2347 114 : sal_Int32 ScDPMembers::GetIndexFromName( const ::rtl::OUString& rName ) const
2348 : {
2349 114 : if ( aHashMap.empty() )
2350 : {
2351 : // store the index for each name
2352 :
2353 19 : sal_Int32 nCount = getCount();
2354 69 : for (sal_Int32 i=0; i<nCount; i++)
2355 50 : aHashMap[ getByIndex(i)->getName() ] = i;
2356 : }
2357 :
2358 114 : ScDPMembersHashMap::const_iterator aIter = aHashMap.find( rName );
2359 114 : if ( aIter != aHashMap.end() )
2360 104 : return aIter->second; // found index
2361 : else
2362 10 : return -1; // not found
2363 : }
2364 :
2365 71 : uno::Any SAL_CALL ScDPMembers::getByName( const rtl::OUString& aName )
2366 : throw(container::NoSuchElementException,
2367 : lang::WrappedTargetException, uno::RuntimeException)
2368 : {
2369 71 : sal_Int32 nIndex = GetIndexFromName( aName );
2370 71 : if ( nIndex >= 0 )
2371 : {
2372 71 : uno::Reference<container::XNamed> xNamed = getByIndex(nIndex);
2373 71 : uno::Any aRet;
2374 71 : aRet <<= xNamed;
2375 142 : return aRet;
2376 : }
2377 :
2378 0 : throw container::NoSuchElementException();
2379 : }
2380 :
2381 7 : uno::Sequence<rtl::OUString> SAL_CALL ScDPMembers::getElementNames() throw(uno::RuntimeException)
2382 : {
2383 : // Return list of names in sorted order,
2384 : // so it's displayed in that order in the field options dialog.
2385 : // Sorting is done at the level object (parent of this).
2386 :
2387 7 : ScDPLevel* pLevel = pSource->GetDimensionsObject()->getByIndex(nDim)->
2388 7 : GetHierarchiesObject()->getByIndex(nHier)->GetLevelsObject()->getByIndex(nLev);
2389 7 : pLevel->EvaluateSortOrder();
2390 7 : const std::vector<sal_Int32>& rGlobalOrder = pLevel->GetGlobalOrder();
2391 7 : bool bSort = !rGlobalOrder.empty();
2392 :
2393 7 : long nCount = getCount();
2394 7 : uno::Sequence<rtl::OUString> aSeq(nCount);
2395 7 : rtl::OUString* pArr = aSeq.getArray();
2396 37 : for (long i=0; i<nCount; i++)
2397 30 : pArr[i] = getByIndex(bSort ? rGlobalOrder[i] : i)->getName();
2398 7 : return aSeq;
2399 : }
2400 :
2401 43 : sal_Bool SAL_CALL ScDPMembers::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
2402 : {
2403 43 : return ( GetIndexFromName( aName ) >= 0 );
2404 : }
2405 :
2406 0 : uno::Type SAL_CALL ScDPMembers::getElementType() throw(uno::RuntimeException)
2407 : {
2408 0 : return getCppuType((uno::Reference<container::XNamed>*)0);
2409 : }
2410 :
2411 0 : sal_Bool SAL_CALL ScDPMembers::hasElements() throw(uno::RuntimeException)
2412 : {
2413 0 : return ( getCount() > 0 );
2414 : }
2415 :
2416 : // end of XNameAccess implementation
2417 :
2418 149 : long ScDPMembers::getCount() const
2419 : {
2420 149 : return nMbrCount;
2421 : }
2422 :
2423 27 : long ScDPMembers::getMinMembers() const
2424 : {
2425 : // used in lcl_CountMinMembers
2426 :
2427 27 : long nVisCount = 0;
2428 27 : if (!maMembers.empty())
2429 : {
2430 25 : MembersType::const_iterator it = maMembers.begin(), itEnd = maMembers.end();
2431 155 : for (; it != itEnd; ++it)
2432 : {
2433 : // count only visible with details (default is true for both)
2434 130 : const rtl::Reference<ScDPMember>& pMbr = *it;
2435 130 : if (!pMbr.get() || (pMbr->isVisible() && pMbr->getShowDetails()))
2436 130 : ++nVisCount;
2437 : }
2438 : }
2439 : else
2440 2 : nVisCount = nMbrCount; // default for all
2441 :
2442 27 : return nVisCount;
2443 : }
2444 :
2445 1053 : ScDPMember* ScDPMembers::getByIndex(long nIndex) const
2446 : {
2447 : // result of GetColumnEntries must not change between ScDPMembers ctor
2448 : // and all calls to getByIndex
2449 :
2450 1053 : if ( nIndex >= 0 && nIndex < nMbrCount )
2451 : {
2452 1053 : if (maMembers.empty())
2453 56 : maMembers.resize(nMbrCount);
2454 :
2455 1053 : if (!maMembers[nIndex].get())
2456 : {
2457 216 : rtl::Reference<ScDPMember> pNew;
2458 216 : long nSrcDim = pSource->GetSourceDim( nDim );
2459 216 : if ( pSource->IsDataLayoutDimension(nSrcDim) )
2460 : {
2461 : // empty name (never shown, not used for lookup)
2462 12 : pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, 0));
2463 : }
2464 204 : else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
2465 : {
2466 0 : sal_Int32 nGroupBy = 0;
2467 0 : sal_Int32 nVal = 0;
2468 0 : rtl::OUString aName;
2469 :
2470 0 : if ( nLev == SC_DAPI_LEVEL_YEAR ) // YEAR is in both hierarchies
2471 : {
2472 : //! cache year range here!
2473 :
2474 0 : double fFirstVal = pSource->GetData()->GetMemberByIndex( nSrcDim, 0 )->GetValue();
2475 : long nFirstYear = pSource->GetData()->GetDatePart(
2476 0 : (long)::rtl::math::approxFloor( fFirstVal ),
2477 0 : nHier, nLev );
2478 :
2479 0 : nVal = nFirstYear + nIndex;
2480 : }
2481 0 : else if ( nHier == SC_DAPI_HIERARCHY_WEEK && nLev == SC_DAPI_LEVEL_WEEKDAY )
2482 : {
2483 0 : nVal = nIndex; // DayOfWeek is 0-based
2484 : aName = ScGlobal::GetCalendar()->getDisplayName(
2485 : ::com::sun::star::i18n::CalendarDisplayIndex::DAY,
2486 0 : sal::static_int_cast<sal_Int16>(nVal), 0 );
2487 : }
2488 0 : else if ( nHier == SC_DAPI_HIERARCHY_QUARTER && nLev == SC_DAPI_LEVEL_MONTH )
2489 : {
2490 0 : nVal = nIndex; // Month is 0-based
2491 : aName = ScGlobal::GetCalendar()->getDisplayName(
2492 : ::com::sun::star::i18n::CalendarDisplayIndex::MONTH,
2493 0 : sal::static_int_cast<sal_Int16>(nVal), 0 );
2494 : }
2495 : else
2496 0 : nVal = nIndex + 1; // Quarter, Day, Week are 1-based
2497 :
2498 0 : switch (nLev)
2499 : {
2500 : case SC_DAPI_LEVEL_YEAR:
2501 0 : nGroupBy = sheet::DataPilotFieldGroupBy::YEARS;
2502 0 : break;
2503 : case SC_DAPI_LEVEL_QUARTER:
2504 : case SC_DAPI_LEVEL_WEEK:
2505 0 : nGroupBy = sheet::DataPilotFieldGroupBy::QUARTERS;
2506 0 : break;
2507 : case SC_DAPI_LEVEL_MONTH:
2508 : case SC_DAPI_LEVEL_WEEKDAY:
2509 0 : nGroupBy = sheet::DataPilotFieldGroupBy::MONTHS;
2510 0 : break;
2511 : case SC_DAPI_LEVEL_DAY:
2512 0 : nGroupBy = sheet::DataPilotFieldGroupBy::DAYS;
2513 0 : break;
2514 : default:
2515 : ;
2516 : }
2517 0 : if (aName.isEmpty())
2518 0 : aName = rtl::OUString::valueOf(nVal);
2519 :
2520 0 : ScDPItemData aData(nGroupBy, nVal);
2521 0 : SCROW nId = pSource->GetCache()->GetIdByItemData(nDim, aData);
2522 0 : pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, nId));
2523 : }
2524 : else
2525 : {
2526 204 : const std::vector<SCROW>& memberIndexs = pSource->GetData()->GetColumnEntries(nSrcDim);
2527 204 : pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, memberIndexs[nIndex]));
2528 : }
2529 216 : maMembers[nIndex] = pNew;
2530 : }
2531 :
2532 1053 : return maMembers[nIndex].get();
2533 : }
2534 :
2535 0 : return NULL; //! exception?
2536 : }
2537 :
2538 : // -----------------------------------------------------------------------
2539 :
2540 216 : ScDPMember::ScDPMember(
2541 : ScDPSource* pSrc, long nD, long nH, long nL, SCROW nIndex) :
2542 : pSource( pSrc ),
2543 : nDim( nD ),
2544 : nHier( nH ),
2545 : nLev( nL ),
2546 : mnDataId( nIndex ),
2547 : mpLayoutName(NULL),
2548 : nPosition( -1 ),
2549 : bVisible( true ),
2550 216 : bShowDet( true )
2551 : {
2552 : //! hold pSource
2553 216 : }
2554 :
2555 432 : ScDPMember::~ScDPMember()
2556 : {
2557 : //! release pSource
2558 432 : }
2559 :
2560 852 : bool ScDPMember::IsNamedItem(SCROW nIndex) const
2561 : {
2562 852 : long nSrcDim = pSource->GetSourceDim( nDim );
2563 852 : if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
2564 : {
2565 0 : const ScDPItemData* pData = pSource->GetCache()->GetItemDataById(nDim, nIndex);
2566 0 : if (pData->IsValue())
2567 : {
2568 : long nComp = pSource->GetData()->GetDatePart(
2569 0 : (long)::rtl::math::approxFloor( pData->GetValue() ),
2570 0 : nHier, nLev );
2571 : // fValue is converted from integer, so simple comparison works
2572 0 : const ScDPItemData* pData2 = GetItemData();
2573 0 : return pData2 && nComp == pData2->GetValue();
2574 : }
2575 : }
2576 :
2577 852 : return nIndex == mnDataId;
2578 : }
2579 :
2580 307 : sal_Int32 ScDPMember::Compare( const ScDPMember& rOther ) const
2581 : {
2582 307 : if ( nPosition >= 0 )
2583 : {
2584 1 : if ( rOther.nPosition >= 0 )
2585 : {
2586 : OSL_ENSURE( nPosition != rOther.nPosition, "same position for two members" );
2587 0 : return ( nPosition < rOther.nPosition ) ? -1 : 1;
2588 : }
2589 : else
2590 : {
2591 : // only this has a position - members with specified positions come before those without
2592 1 : return -1;
2593 : }
2594 : }
2595 306 : else if ( rOther.nPosition >= 0 )
2596 : {
2597 : // only rOther has a position
2598 3 : return 1;
2599 : }
2600 :
2601 : // no positions set - compare names
2602 303 : return pSource->GetData()->Compare( pSource->GetSourceDim(nDim),mnDataId,rOther.GetItemDataId());
2603 : }
2604 :
2605 189 : void ScDPMember::FillItemData( ScDPItemData& rData ) const
2606 : {
2607 : //! handle date hierarchy...
2608 :
2609 189 : const ScDPItemData* pData = GetItemData();
2610 189 : rData = (pData ? *pData : ScDPItemData());
2611 189 : }
2612 :
2613 145 : const OUString* ScDPMember::GetLayoutName() const
2614 : {
2615 145 : return mpLayoutName.get();
2616 : }
2617 :
2618 0 : long ScDPMember::GetDim() const
2619 : {
2620 0 : return nDim;
2621 : }
2622 :
2623 102 : rtl::OUString ScDPMember::GetNameStr() const
2624 : {
2625 102 : const ScDPItemData* pData = GetItemData();
2626 102 : if (pData)
2627 102 : return pSource->GetData()->GetFormattedString(nDim, *pData);
2628 0 : return rtl::OUString();
2629 : }
2630 :
2631 102 : ::rtl::OUString SAL_CALL ScDPMember::getName() throw(uno::RuntimeException)
2632 : {
2633 102 : return GetNameStr();
2634 : }
2635 :
2636 0 : void SAL_CALL ScDPMember::setName( const ::rtl::OUString& /* rNewName */ ) throw(uno::RuntimeException)
2637 : {
2638 : OSL_FAIL("not implemented"); //! exception?
2639 0 : }
2640 :
2641 2400 : bool ScDPMember::isVisible() const
2642 : {
2643 2400 : return bVisible;
2644 : }
2645 :
2646 346 : bool ScDPMember::getShowDetails() const
2647 : {
2648 346 : return bShowDet;
2649 : }
2650 :
2651 : // XPropertySet
2652 :
2653 0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPMember::getPropertySetInfo()
2654 : throw(uno::RuntimeException)
2655 : {
2656 0 : SolarMutexGuard aGuard;
2657 :
2658 : static SfxItemPropertyMapEntry aDPMemberMap_Impl[] =
2659 : {
2660 0 : {MAP_CHAR_LEN(SC_UNO_DP_ISVISIBLE), 0, &getBooleanCppuType(), 0, 0 },
2661 0 : {MAP_CHAR_LEN(SC_UNO_DP_POSITION), 0, &getCppuType((sal_Int32*)0), 0, 0 },
2662 0 : {MAP_CHAR_LEN(SC_UNO_DP_SHOWDETAILS), 0, &getBooleanCppuType(), 0, 0 },
2663 0 : {MAP_CHAR_LEN(SC_UNO_DP_LAYOUTNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 },
2664 : {0,0,0,0,0,0}
2665 0 : };
2666 : static uno::Reference<beans::XPropertySetInfo> aRef =
2667 0 : new SfxItemPropertySetInfo( aDPMemberMap_Impl );
2668 0 : return aRef;
2669 : }
2670 :
2671 40 : void SAL_CALL ScDPMember::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
2672 : throw(beans::UnknownPropertyException, beans::PropertyVetoException,
2673 : lang::IllegalArgumentException, lang::WrappedTargetException,
2674 : uno::RuntimeException)
2675 : {
2676 40 : if ( aPropertyName.equalsAscii( SC_UNO_DP_ISVISIBLE ) )
2677 33 : bVisible = lcl_GetBoolFromAny(aValue);
2678 7 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWDETAILS ) )
2679 0 : bShowDet = lcl_GetBoolFromAny(aValue);
2680 7 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_POSITION ) )
2681 7 : aValue >>= nPosition;
2682 0 : else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
2683 : {
2684 0 : rtl::OUString aName;
2685 0 : if (aValue >>= aName)
2686 0 : mpLayoutName.reset(new rtl::OUString(aName));
2687 : }
2688 : else
2689 : {
2690 : OSL_FAIL("unknown property");
2691 : }
2692 40 : }
2693 :
2694 82 : uno::Any SAL_CALL ScDPMember::getPropertyValue( const rtl::OUString& aPropertyName )
2695 : throw(beans::UnknownPropertyException, lang::WrappedTargetException,
2696 : uno::RuntimeException)
2697 : {
2698 82 : uno::Any aRet;
2699 82 : if ( aPropertyName.equalsAscii( SC_UNO_DP_ISVISIBLE ) )
2700 30 : lcl_SetBoolInAny(aRet, bVisible);
2701 52 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWDETAILS ) )
2702 22 : lcl_SetBoolInAny(aRet, bShowDet);
2703 30 : else if ( aPropertyName.equalsAscii( SC_UNO_DP_POSITION ) )
2704 0 : aRet <<= nPosition;
2705 30 : else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
2706 30 : aRet <<= mpLayoutName.get() ? *mpLayoutName : rtl::OUString();
2707 : else
2708 : {
2709 : OSL_FAIL("unknown property");
2710 : }
2711 82 : return aRet;
2712 : }
2713 :
2714 0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPMember )
2715 :
2716 :
2717 0 : const ScDPCache* ScDPSource::GetCache()
2718 : {
2719 : OSL_ENSURE( GetData() , "empty ScDPTableData pointer");
2720 0 : return ( GetData()!=NULL) ? GetData()->GetCacheTable().getCache() : NULL ;
2721 : }
2722 :
2723 291 : const ScDPItemData* ScDPMember::GetItemData() const
2724 : {
2725 291 : const ScDPItemData* pData = pSource->GetItemDataById(nDim, mnDataId);
2726 : SAL_WARN_IF( !pData, "sc", "ScDPMember::GetItemData: what data? nDim " << nDim << ", mnDataId " << mnDataId);
2727 291 : return pData;
2728 : }
2729 :
2730 341 : const ScDPItemData* ScDPSource::GetItemDataById(long nDim, long nId)
2731 : {
2732 341 : return GetData()->GetMemberById(nDim, nId);
2733 : }
2734 :
2735 0 : SCROW ScDPSource::GetMemberId(long nDim, const ScDPItemData& rData)
2736 : {
2737 0 : return GetCache()->GetIdByItemData(nDim, rData);
2738 : }
2739 :
2740 0 : const ScDPItemData* ScDPMembers::GetSrcItemDataByIndex(SCROW nIndex)
2741 : {
2742 0 : const std::vector< SCROW >& memberIds = pSource->GetData()->GetColumnEntries( nDim );
2743 0 : if ( nIndex >= (long )(memberIds.size()) || nIndex < 0 )
2744 0 : return NULL;
2745 0 : SCROW nId = memberIds[ nIndex ];
2746 0 : return pSource->GetItemDataById( nDim, nId );
2747 : }
2748 :
2749 0 : SCROW ScDPMembers::GetSrcItemsCount()
2750 : {
2751 0 : return pSource->GetData()->GetColumnEntries(nDim).size();
2752 15 : }
2753 :
2754 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|