1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27 #include <algorithm>
28 #include <svl/smplhint.hxx>
29 #include <rtl/uuid.h>
30
31 #include "dapiuno.hxx"
32 #include "datauno.hxx"
33 #include "miscuno.hxx"
34 #include "convuno.hxx"
35 #include "docsh.hxx"
36 #include "tabvwsh.hxx"
37 #include "pivot.hxx"
38 #include "rangeutl.hxx"
39 #include "unoguard.hxx"
40 #include "dpobject.hxx"
41 #include "dpshttab.hxx"
42 #include "dpsdbtab.hxx"
43 #include "dpsave.hxx"
44 #include "dbdocfun.hxx"
45 #include "unonames.hxx"
46 #include "dpgroup.hxx"
47 #include "dpdimsave.hxx"
48 #include "hints.hxx"
49
50 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
51 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
52 #include <com/sun/star/sheet/XMembersSupplier.hpp>
53 #include <com/sun/star/beans/PropertyAttribute.hpp>
54 #include <com/sun/star/sheet/DataImportMode.hpp>
55 #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
56 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
57 #include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
58 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
59
60 #include <comphelper/extract.hxx>
61 #include <comphelper/sequence.hxx>
62
63 using namespace com::sun::star;
64 using namespace com::sun::star::sheet;
65
66 using ::rtl::OUString;
67
68 using ::com::sun::star::uno::Any;
69 using ::com::sun::star::uno::Exception;
70 using ::com::sun::star::uno::Reference;
71 using ::com::sun::star::uno::RuntimeException;
72 using ::com::sun::star::uno::Sequence;
73 using ::com::sun::star::uno::UNO_QUERY;
74 using ::com::sun::star::uno::UNO_QUERY_THROW;
75
76 using ::com::sun::star::container::ElementExistException;
77 using ::com::sun::star::container::NoSuchElementException;
78 using ::com::sun::star::container::XEnumeration;
79 using ::com::sun::star::container::XIndexAccess;
80 using ::com::sun::star::container::XNameAccess;
81 using ::com::sun::star::container::XNamed;
82
83 using ::com::sun::star::beans::PropertyVetoException;
84 using ::com::sun::star::beans::UnknownPropertyException;
85 using ::com::sun::star::beans::XPropertyChangeListener;
86 using ::com::sun::star::beans::XPropertySet;
87 using ::com::sun::star::beans::XPropertySetInfo;
88 using ::com::sun::star::beans::XVetoableChangeListener;
89
90 using ::com::sun::star::lang::IllegalArgumentException;
91 using ::com::sun::star::lang::IndexOutOfBoundsException;
92 using ::com::sun::star::lang::WrappedTargetException;
93
94 using ::com::sun::star::table::CellAddress;
95 using ::com::sun::star::table::CellRangeAddress;
96
97 // ============================================================================
98
99 namespace {
100
lcl_GetDataPilotDescriptorBaseMap()101 const SfxItemPropertyMapEntry* lcl_GetDataPilotDescriptorBaseMap()
102 {
103 static SfxItemPropertyMapEntry aDataPilotDescriptorBaseMap_Impl[] =
104 {
105 {MAP_CHAR_LEN(SC_UNO_COLGRAND), 0, &getBooleanCppuType(), 0, 0 },
106 {MAP_CHAR_LEN(SC_UNO_DRILLDOWN), 0, &getBooleanCppuType(), 0, 0 },
107 {MAP_CHAR_LEN(SC_UNO_GRANDTOTAL_NAME),0,&getCppuType((rtl::OUString*)0), beans::PropertyAttribute::MAYBEVOID, 0 },
108 {MAP_CHAR_LEN(SC_UNO_IGNEMPROWS), 0, &getBooleanCppuType(), 0, 0 },
109 {MAP_CHAR_LEN(SC_UNO_IMPORTDESC), 0, &getCppuType((uno::Sequence<beans::PropertyValue>*)0), 0, 0 },
110 {MAP_CHAR_LEN(SC_UNO_RPTEMPTY), 0, &getBooleanCppuType(), 0, 0 },
111 {MAP_CHAR_LEN(SC_UNO_ROWGRAND), 0, &getBooleanCppuType(), 0, 0 },
112 {MAP_CHAR_LEN(SC_UNO_SERVICEARG), 0, &getCppuType((uno::Sequence<beans::PropertyValue>*)0), 0, 0 },
113 {MAP_CHAR_LEN(SC_UNO_SHOWFILT), 0, &getBooleanCppuType(), 0, 0 },
114 {MAP_CHAR_LEN(SC_UNO_SOURCESERV), 0, &getCppuType((rtl::OUString*)0), 0, 0 },
115 {0,0,0,0,0,0}
116 };
117 return aDataPilotDescriptorBaseMap_Impl;
118 }
119
120 // ----------------------------------------------------------------------------
121
lcl_GetDataPilotFieldMap()122 const SfxItemPropertyMapEntry* lcl_GetDataPilotFieldMap()
123 {
124 using namespace ::com::sun::star::beans::PropertyAttribute;
125 static SfxItemPropertyMapEntry aDataPilotFieldMap_Impl[] =
126 {
127 {MAP_CHAR_LEN(SC_UNONAME_AUTOSHOW), 0, &getCppuType((DataPilotFieldAutoShowInfo*)0), MAYBEVOID, 0 },
128 {MAP_CHAR_LEN(SC_UNONAME_FUNCTION), 0, &getCppuType((GeneralFunction*)0), 0, 0 },
129 {MAP_CHAR_LEN(SC_UNONAME_GROUPINFO), 0, &getCppuType((DataPilotFieldGroupInfo*)0), MAYBEVOID, 0 },
130 {MAP_CHAR_LEN(SC_UNONAME_HASAUTOSHOW), 0, &getBooleanCppuType(), 0, 0 },
131 {MAP_CHAR_LEN(SC_UNONAME_HASLAYOUTINFO),0, &getBooleanCppuType(), 0, 0 },
132 {MAP_CHAR_LEN(SC_UNONAME_HASREFERENCE), 0, &getBooleanCppuType(), 0, 0 },
133 {MAP_CHAR_LEN(SC_UNONAME_HASSORTINFO), 0, &getBooleanCppuType(), 0, 0 },
134 {MAP_CHAR_LEN(SC_UNONAME_ISGROUP), 0, &getBooleanCppuType(), 0, 0 },
135 {MAP_CHAR_LEN(SC_UNONAME_LAYOUTINFO), 0, &getCppuType((DataPilotFieldLayoutInfo*)0), MAYBEVOID, 0 },
136 {MAP_CHAR_LEN(SC_UNONAME_ORIENT), 0, &getCppuType((DataPilotFieldOrientation*)0), MAYBEVOID, 0 },
137 {MAP_CHAR_LEN(SC_UNONAME_REFERENCE), 0, &getCppuType((DataPilotFieldReference*)0), MAYBEVOID, 0 },
138 {MAP_CHAR_LEN(SC_UNONAME_SELPAGE), 0, &getCppuType((OUString*)0), 0, 0 },
139 {MAP_CHAR_LEN(SC_UNONAME_SHOWEMPTY), 0, &getBooleanCppuType(), 0, 0 },
140 {MAP_CHAR_LEN(SC_UNONAME_SORTINFO), 0, &getCppuType((DataPilotFieldSortInfo*)0), MAYBEVOID, 0 },
141 {MAP_CHAR_LEN(SC_UNONAME_SUBTOTALS), 0, &getCppuType((Sequence<GeneralFunction>*)0), 0, 0 },
142 {MAP_CHAR_LEN(SC_UNONAME_USESELPAGE), 0, &getBooleanCppuType(), 0, 0 },
143 {0,0,0,0,0,0}
144 };
145 return aDataPilotFieldMap_Impl;
146 }
147
148 // ----------------------------------------------------------------------------
149
lcl_GetDataPilotItemMap()150 const SfxItemPropertyMapEntry* lcl_GetDataPilotItemMap()
151 {
152 static SfxItemPropertyMapEntry aDataPilotItemMap_Impl[] =
153 {
154 {MAP_CHAR_LEN(SC_UNONAME_ISHIDDEN), 0, &getBooleanCppuType(), 0, 0 },
155 {MAP_CHAR_LEN(SC_UNONAME_POS), 0, &getCppuType((sal_Int32*)0), 0, 0 },
156 {MAP_CHAR_LEN(SC_UNONAME_SHOWDETAIL), 0, &getBooleanCppuType(), 0, 0 },
157 {0,0,0,0,0,0}
158 };
159 return aDataPilotItemMap_Impl;
160 }
161
162 // ----------------------------------------------------------------------------
163
lclCheckValidDouble(double fValue,sal_Bool bAuto)164 inline bool lclCheckValidDouble( double fValue, sal_Bool bAuto )
165 {
166 return bAuto || ::rtl::math::isFinite( fValue );
167 }
168
lclCheckMinMaxStep(const DataPilotFieldGroupInfo & rInfo)169 bool lclCheckMinMaxStep( const DataPilotFieldGroupInfo& rInfo )
170 {
171 return
172 lclCheckValidDouble( rInfo.Start, rInfo.HasAutoStart ) &&
173 lclCheckValidDouble( rInfo.End, rInfo.HasAutoEnd ) &&
174 (rInfo.HasAutoStart || rInfo.HasAutoEnd || (rInfo.Start <= rInfo.End)) &&
175 lclCheckValidDouble( rInfo.Step, sal_False ) &&
176 (0.0 <= rInfo.Step);
177 }
178
179 } // namespace
180
181 // ============================================================================
182
183 SC_SIMPLE_SERVICE_INFO( ScDataPilotDescriptor, "ScDataPilotDescriptor", "stardiv::one::sheet::DataPilotDescriptor" )
184 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldObj, "ScDataPilotFieldObj", "com.sun.star.sheet.DataPilotField" )
185 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldsObj, "ScDataPilotFieldsObj", "com.sun.star.sheet.DataPilotFields" )
186 SC_SIMPLE_SERVICE_INFO( ScDataPilotTableObj, "ScDataPilotTableObj", "com.sun.star.sheet.DataPilotTable" )
187 SC_SIMPLE_SERVICE_INFO( ScDataPilotTablesObj, "ScDataPilotTablesObj", "com.sun.star.sheet.DataPilotTables" )
188 SC_SIMPLE_SERVICE_INFO( ScDataPilotItemsObj, "ScDataPilotItemsObj", "com.sun.star.sheet.DataPilotItems" )
189 SC_SIMPLE_SERVICE_INFO( ScDataPilotItemObj, "ScDataPilotItemObj", "com.sun.star.sheet.DataPilotItem" )
190
191 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupsObj, "ScDataPilotFieldGroupsObj", "com.sun.star.sheet.DataPilotFieldGroups" )
192 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupObj, "ScDataPilotFieldGroupObj", "com.sun.star.sheet.DataPilotFieldGroup" )
193 SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupItemObj, "ScDataPilotFieldGroupItemObj", "com.sun.star.sheet.DataPilotFieldGroupItem" )
194
195 //------------------------------------------------------------------------
196
197 // name that is used in the API for the data layout field
198 #define SC_DATALAYOUT_NAME "Data"
199
200 //------------------------------------------------------------------------
201
FirstFunc(sal_uInt16 nBits)202 GeneralFunction ScDataPilotConversion::FirstFunc( sal_uInt16 nBits )
203 {
204 if ( nBits & PIVOT_FUNC_SUM ) return GeneralFunction_SUM;
205 if ( nBits & PIVOT_FUNC_COUNT ) return GeneralFunction_COUNT;
206 if ( nBits & PIVOT_FUNC_AVERAGE ) return GeneralFunction_AVERAGE;
207 if ( nBits & PIVOT_FUNC_MAX ) return GeneralFunction_MAX;
208 if ( nBits & PIVOT_FUNC_MIN ) return GeneralFunction_MIN;
209 if ( nBits & PIVOT_FUNC_PRODUCT ) return GeneralFunction_PRODUCT;
210 if ( nBits & PIVOT_FUNC_COUNT_NUM ) return GeneralFunction_COUNTNUMS;
211 if ( nBits & PIVOT_FUNC_STD_DEV ) return GeneralFunction_STDEV;
212 if ( nBits & PIVOT_FUNC_STD_DEVP ) return GeneralFunction_STDEVP;
213 if ( nBits & PIVOT_FUNC_STD_VAR ) return GeneralFunction_VAR;
214 if ( nBits & PIVOT_FUNC_STD_VARP ) return GeneralFunction_VARP;
215 if ( nBits & PIVOT_FUNC_AUTO ) return GeneralFunction_AUTO;
216 return GeneralFunction_NONE;
217 }
218
FunctionBit(GeneralFunction eFunc)219 sal_uInt16 ScDataPilotConversion::FunctionBit( GeneralFunction eFunc )
220 {
221 sal_uInt16 nRet = PIVOT_FUNC_NONE; // 0
222 switch (eFunc)
223 {
224 case GeneralFunction_SUM: nRet = PIVOT_FUNC_SUM; break;
225 case GeneralFunction_COUNT: nRet = PIVOT_FUNC_COUNT; break;
226 case GeneralFunction_AVERAGE: nRet = PIVOT_FUNC_AVERAGE; break;
227 case GeneralFunction_MAX: nRet = PIVOT_FUNC_MAX; break;
228 case GeneralFunction_MIN: nRet = PIVOT_FUNC_MIN; break;
229 case GeneralFunction_PRODUCT: nRet = PIVOT_FUNC_PRODUCT; break;
230 case GeneralFunction_COUNTNUMS: nRet = PIVOT_FUNC_COUNT_NUM; break;
231 case GeneralFunction_STDEV: nRet = PIVOT_FUNC_STD_DEV; break;
232 case GeneralFunction_STDEVP: nRet = PIVOT_FUNC_STD_DEVP; break;
233 case GeneralFunction_VAR: nRet = PIVOT_FUNC_STD_VAR; break;
234 case GeneralFunction_VARP: nRet = PIVOT_FUNC_STD_VARP; break;
235 case GeneralFunction_AUTO: nRet = PIVOT_FUNC_AUTO; break;
236 default:
237 {
238 // added to avoid warnings
239 }
240 }
241 return nRet;
242 }
243
FillGroupInfo(DataPilotFieldGroupInfo & rInfo,const ScDPNumGroupInfo & rGroupInfo)244 void ScDataPilotConversion::FillGroupInfo( DataPilotFieldGroupInfo& rInfo, const ScDPNumGroupInfo& rGroupInfo )
245 {
246 rInfo.HasDateValues = rGroupInfo.DateValues;
247 rInfo.HasAutoStart = rGroupInfo.AutoStart;
248 rInfo.Start = rGroupInfo.Start;
249 rInfo.HasAutoEnd = rGroupInfo.AutoEnd;
250 rInfo.End = rGroupInfo.End;
251 rInfo.Step = rGroupInfo.Step;
252 }
253
254 //------------------------------------------------------------------------
255
lcl_GetDPObject(ScDocShell * pDocShell,SCTAB nTab,const String & rName)256 ScDPObject* lcl_GetDPObject( ScDocShell* pDocShell, SCTAB nTab, const String& rName )
257 {
258 if (pDocShell)
259 {
260 ScDocument* pDoc = pDocShell->GetDocument();
261 ScDPCollection* pColl = pDoc->GetDPCollection();
262 if ( pColl )
263 {
264 sal_uInt16 nCount = pColl->GetCount();
265 for (sal_uInt16 i=0; i<nCount; i++)
266 {
267 ScDPObject* pDPObj = (*pColl)[i];
268 if ( pDPObj->GetOutRange().aStart.Tab() == nTab &&
269 pDPObj->GetName() == rName )
270 return pDPObj;
271 }
272 }
273 }
274 return NULL; // nicht gefunden
275 }
276
lcl_CreatePivotName(ScDocShell * pDocShell)277 String lcl_CreatePivotName( ScDocShell* pDocShell )
278 {
279 if (pDocShell)
280 {
281 ScDocument* pDoc = pDocShell->GetDocument();
282 ScDPCollection* pColl = pDoc->GetDPCollection();
283 if ( pColl )
284 return pColl->CreateNewName();
285 }
286 return String(); // sollte nicht vorkommen
287 }
288
lcl_GetObjectIndex(ScDPObject * pDPObj,const ScFieldIdentifier & rFieldId)289 sal_Int32 lcl_GetObjectIndex( ScDPObject* pDPObj, const ScFieldIdentifier& rFieldId )
290 {
291 // used for items - nRepeat in identifier can be ignored
292 if ( pDPObj )
293 {
294 sal_Int32 nCount = pDPObj->GetDimCount();
295 for ( sal_Int32 nDim = 0; nDim < nCount; ++nDim )
296 {
297 sal_Bool bIsDataLayout = sal_False;
298 OUString aDimName( pDPObj->GetDimName( nDim, bIsDataLayout ) );
299 if ( rFieldId.mbDataLayout ? bIsDataLayout : (aDimName == rFieldId.maFieldName) )
300 return nDim;
301 }
302 }
303 return -1; // none
304 }
305
306 //------------------------------------------------------------------------
307
ScDataPilotTablesObj(ScDocShell * pDocSh,SCTAB nT)308 ScDataPilotTablesObj::ScDataPilotTablesObj(ScDocShell* pDocSh, SCTAB nT) :
309 pDocShell( pDocSh ),
310 nTab( nT )
311 {
312 pDocShell->GetDocument()->AddUnoObject(*this);
313 }
314
~ScDataPilotTablesObj()315 ScDataPilotTablesObj::~ScDataPilotTablesObj()
316 {
317 if (pDocShell)
318 pDocShell->GetDocument()->RemoveUnoObject(*this);
319 }
320
Notify(SfxBroadcaster &,const SfxHint & rHint)321 void ScDataPilotTablesObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
322 {
323 //! Referenz-Update
324
325 if ( rHint.ISA( SfxSimpleHint ) &&
326 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
327 {
328 pDocShell = NULL; // ungueltig geworden
329 }
330 }
331
332 // XDataPilotTables
333
GetObjectByIndex_Impl(sal_Int32 nIndex)334 ScDataPilotTableObj* ScDataPilotTablesObj::GetObjectByIndex_Impl( sal_Int32 nIndex )
335 {
336 if (pDocShell)
337 {
338 ScDocument* pDoc = pDocShell->GetDocument();
339 ScDPCollection* pColl = pDoc->GetDPCollection();
340 if ( pColl )
341 {
342 // count tables on this sheet
343 sal_Int32 nFound = 0;
344 sal_uInt16 nCount = pColl->GetCount();
345 for (sal_uInt16 i=0; i<nCount; i++)
346 {
347 ScDPObject* pDPObj = (*pColl)[i];
348 if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
349 {
350 if ( nFound == nIndex )
351 {
352 String aName = pDPObj->GetName();
353 return new ScDataPilotTableObj( pDocShell, nTab, aName );
354 }
355 ++nFound;
356 }
357 }
358 }
359 }
360 return NULL;
361 }
362
GetObjectByName_Impl(const OUString & rName)363 ScDataPilotTableObj* ScDataPilotTablesObj::GetObjectByName_Impl(const OUString& rName)
364 {
365 if (hasByName(rName))
366 return new ScDataPilotTableObj( pDocShell, nTab, rName );
367 return 0;
368 }
369
createDataPilotDescriptor()370 Reference<XDataPilotDescriptor> SAL_CALL ScDataPilotTablesObj::createDataPilotDescriptor()
371 {
372 ScUnoGuard aGuard;
373 if (pDocShell)
374 return new ScDataPilotDescriptor(pDocShell);
375 return NULL;
376 }
377
lcl_IsDuplicated(const Reference<XPropertySet> xDimProps)378 bool lcl_IsDuplicated( const Reference<XPropertySet> xDimProps )
379 {
380 try
381 {
382 Any aAny = xDimProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_ORIGINAL ) ) );
383 Reference< XNamed > xOriginal( aAny, UNO_QUERY );
384 return xOriginal.is();
385 }
386 catch( Exception& )
387 {
388 }
389 return false;
390 }
391
lcl_GetOriginalName(const Reference<XNamed> xDim)392 OUString lcl_GetOriginalName( const Reference< XNamed > xDim )
393 {
394 Reference< XNamed > xOriginal;
395
396 Reference< XPropertySet > xDimProps( xDim, UNO_QUERY );
397 if ( xDimProps.is() )
398 {
399 try
400 {
401 Any aAny = xDimProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ORIGINAL)));
402 aAny >>= xOriginal;
403 }
404 catch( Exception& )
405 {
406 }
407 }
408
409 if ( !xOriginal.is() )
410 xOriginal = xDim;
411
412 return xOriginal->getName();
413 }
414
insertNewByName(const OUString & aNewName,const CellAddress & aOutputAddress,const Reference<XDataPilotDescriptor> & xDescriptor)415 void SAL_CALL ScDataPilotTablesObj::insertNewByName( const OUString& aNewName,
416 const CellAddress& aOutputAddress,
417 const Reference<XDataPilotDescriptor>& xDescriptor )
418 {
419 ScUnoGuard aGuard;
420 if (!xDescriptor.is()) return;
421
422 // inserting with already existing name?
423 if ( aNewName.getLength() && hasByName( aNewName ) )
424 throw RuntimeException(); // no other exceptions specified
425
426 sal_Bool bDone = sal_False;
427 ScDataPilotDescriptorBase* pImp = ScDataPilotDescriptorBase::getImplementation( xDescriptor );
428 if ( pDocShell && pImp )
429 {
430 ScDPObject* pNewObj = pImp->GetDPObject();
431
432 if (pNewObj)
433 {
434 ScRange aOutputRange((SCCOL)aOutputAddress.Column, (SCROW)aOutputAddress.Row, (SCTAB)aOutputAddress.Sheet,
435 (SCCOL)aOutputAddress.Column, (SCROW)aOutputAddress.Row, (SCTAB)aOutputAddress.Sheet);
436 pNewObj->SetOutRange(aOutputRange);
437 String aName = aNewName;
438 if (!aName.Len())
439 aName = lcl_CreatePivotName( pDocShell );
440 pNewObj->SetName(aName);
441 String aTag = xDescriptor->getTag();
442 pNewObj->SetTag(aTag);
443
444 // todo: handle double fields (for more information see ScDPObject
445
446 ScDBDocFunc aFunc(*pDocShell);
447 bDone = aFunc.DataPilotUpdate( NULL, pNewObj, sal_True, sal_True );
448 }
449 }
450
451 if (!bDone)
452 throw RuntimeException(); // no other exceptions specified
453 }
454
removeByName(const OUString & aName)455 void SAL_CALL ScDataPilotTablesObj::removeByName( const OUString& aName )
456 {
457 ScUnoGuard aGuard;
458 String aNameStr(aName);
459 ScDPObject* pDPObj = lcl_GetDPObject( pDocShell, nTab, aNameStr );
460 if (pDPObj && pDocShell)
461 {
462 ScDBDocFunc aFunc(*pDocShell);
463 aFunc.DataPilotUpdate( pDPObj, NULL, sal_True, sal_True ); // remove - incl. undo etc.
464 }
465 else
466 throw RuntimeException(); // no other exceptions specified
467 }
468
469 // XEnumerationAccess
470
createEnumeration()471 Reference< XEnumeration > SAL_CALL ScDataPilotTablesObj::createEnumeration()
472 {
473 ScUnoGuard aGuard;
474 return new ScIndexEnumeration(this, OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DataPilotTablesEnumeration")));
475 }
476
477 // XIndexAccess
478
getCount()479 sal_Int32 SAL_CALL ScDataPilotTablesObj::getCount()
480 {
481 ScUnoGuard aGuard;
482 if ( pDocShell )
483 {
484 ScDocument* pDoc = pDocShell->GetDocument();
485 ScDPCollection* pColl = pDoc->GetDPCollection();
486 if ( pColl )
487 {
488 // count tables on this sheet
489
490 sal_uInt16 nFound = 0;
491 sal_uInt16 nCount = pColl->GetCount();
492 for (sal_uInt16 i=0; i<nCount; i++)
493 {
494 ScDPObject* pDPObj = (*pColl)[i];
495 if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
496 ++nFound;
497 }
498 return nFound;
499 }
500 }
501
502 return 0;
503 }
504
getByIndex(sal_Int32 nIndex)505 Any SAL_CALL ScDataPilotTablesObj::getByIndex( sal_Int32 nIndex )
506 {
507 ScUnoGuard aGuard;
508 Reference<XDataPilotTable2> xTable(GetObjectByIndex_Impl(nIndex));
509 if (!xTable.is())
510 throw IndexOutOfBoundsException();
511 return Any( xTable );
512 }
513
getElementType()514 uno::Type SAL_CALL ScDataPilotTablesObj::getElementType()
515 {
516 ScUnoGuard aGuard;
517 return getCppuType((Reference<XDataPilotTable2>*)0);
518 }
519
hasElements()520 sal_Bool SAL_CALL ScDataPilotTablesObj::hasElements()
521 {
522 ScUnoGuard aGuard;
523 return ( getCount() != 0 );
524 }
525
526 // XNameAccess
527
getByName(const OUString & aName)528 Any SAL_CALL ScDataPilotTablesObj::getByName( const OUString& aName )
529 {
530 ScUnoGuard aGuard;
531 Reference<XDataPilotTable2> xTable(GetObjectByName_Impl(aName));
532 if (!xTable.is())
533 throw NoSuchElementException();
534 return Any( xTable );
535 }
536
getElementNames()537 Sequence<OUString> SAL_CALL ScDataPilotTablesObj::getElementNames()
538 {
539 ScUnoGuard aGuard;
540 if (pDocShell)
541 {
542 ScDocument* pDoc = pDocShell->GetDocument();
543 ScDPCollection* pColl = pDoc->GetDPCollection();
544 if ( pColl )
545 {
546 // count tables on this sheet
547
548 sal_uInt16 nFound = 0;
549 sal_uInt16 nCount = pColl->GetCount();
550 sal_uInt16 i;
551 for (i=0; i<nCount; i++)
552 {
553 ScDPObject* pDPObj = (*pColl)[i];
554 if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
555 ++nFound;
556 }
557
558 sal_uInt16 nPos = 0;
559 Sequence<OUString> aSeq(nFound);
560 OUString* pAry = aSeq.getArray();
561 for (i=0; i<nCount; i++)
562 {
563 ScDPObject* pDPObj = (*pColl)[i];
564 if ( pDPObj->GetOutRange().aStart.Tab() == nTab )
565 pAry[nPos++] = pDPObj->GetName();
566 }
567
568 return aSeq;
569 }
570 }
571 return Sequence<OUString>(0);
572 }
573
hasByName(const OUString & aName)574 sal_Bool SAL_CALL ScDataPilotTablesObj::hasByName( const OUString& aName )
575 {
576 ScUnoGuard aGuard;
577 if (pDocShell)
578 {
579 ScDocument* pDoc = pDocShell->GetDocument();
580 ScDPCollection* pColl = pDoc->GetDPCollection();
581 if ( pColl )
582 {
583 String aNamStr(aName);
584 sal_uInt16 nCount = pColl->GetCount();
585 for (sal_uInt16 i=0; i<nCount; i++)
586 {
587 ScDPObject* pDPObj = (*pColl)[i];
588 if ( pDPObj->GetOutRange().aStart.Tab() == nTab &&
589 pDPObj->GetName() == aNamStr )
590 return sal_True;
591 }
592 }
593 }
594 return sal_False;
595 }
596
597 //------------------------------------------------------------------------
598
ScDataPilotDescriptorBase(ScDocShell * pDocSh)599 ScDataPilotDescriptorBase::ScDataPilotDescriptorBase(ScDocShell* pDocSh) :
600 maPropSet( lcl_GetDataPilotDescriptorBaseMap() ),
601 pDocShell( pDocSh )
602 {
603 pDocShell->GetDocument()->AddUnoObject(*this);
604 }
605
~ScDataPilotDescriptorBase()606 ScDataPilotDescriptorBase::~ScDataPilotDescriptorBase()
607 {
608 if (pDocShell)
609 pDocShell->GetDocument()->RemoveUnoObject(*this);
610 }
611
queryInterface(const uno::Type & rType)612 Any SAL_CALL ScDataPilotDescriptorBase::queryInterface( const uno::Type& rType )
613 {
614 SC_QUERYINTERFACE( XDataPilotDescriptor )
615 SC_QUERYINTERFACE( XPropertySet )
616 SC_QUERYINTERFACE( XDataPilotDataLayoutFieldSupplier )
617 SC_QUERYINTERFACE( XNamed ) // base of XDataPilotDescriptor
618 SC_QUERYINTERFACE( lang::XUnoTunnel )
619 SC_QUERYINTERFACE( lang::XTypeProvider )
620 SC_QUERYINTERFACE( lang::XServiceInfo )
621
622 return OWeakObject::queryInterface( rType );
623 }
624
acquire()625 void SAL_CALL ScDataPilotDescriptorBase::acquire() throw()
626 {
627 OWeakObject::acquire();
628 }
629
release()630 void SAL_CALL ScDataPilotDescriptorBase::release() throw()
631 {
632 OWeakObject::release();
633 }
634
getTypes()635 Sequence< uno::Type > SAL_CALL ScDataPilotDescriptorBase::getTypes()
636 {
637 static Sequence< uno::Type > aTypes;
638 if ( aTypes.getLength() == 0 )
639 {
640 aTypes.realloc( 6 );
641 uno::Type* pPtr = aTypes.getArray();
642 pPtr[ 0 ] = getCppuType( (const Reference< XDataPilotDescriptor >*)0 );
643 pPtr[ 1 ] = getCppuType( (const Reference< XPropertySet >*)0 );
644 pPtr[ 2 ] = getCppuType( (const Reference< XDataPilotDataLayoutFieldSupplier >*)0 );
645 pPtr[ 3 ] = getCppuType( (const Reference< lang::XUnoTunnel >*)0 );
646 pPtr[ 4 ] = getCppuType( (const Reference< lang::XTypeProvider >*)0 );
647 pPtr[ 5 ] = getCppuType( (const Reference< lang::XServiceInfo >*)0 );
648 }
649 return aTypes;
650 }
651
getImplementationId()652 Sequence<sal_Int8> SAL_CALL ScDataPilotDescriptorBase::getImplementationId()
653 {
654 static Sequence< sal_Int8 > aId;
655 if( aId.getLength() == 0 )
656 {
657 aId.realloc( 16 );
658 rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True );
659 }
660 return aId;
661 }
662
Notify(SfxBroadcaster &,const SfxHint & rHint)663 void ScDataPilotDescriptorBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
664 {
665 //! Referenz-Update?
666
667 if ( rHint.ISA( SfxSimpleHint ) &&
668 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
669 {
670 pDocShell = NULL; // ungueltig geworden
671 }
672 }
673
674 // XDataPilotDescriptor
675
getSourceRange()676 CellRangeAddress SAL_CALL ScDataPilotDescriptorBase::getSourceRange()
677 {
678 ScUnoGuard aGuard;
679
680 ScDPObject* pDPObject(GetDPObject());
681 if (!pDPObject)
682 throw RuntimeException();
683
684 CellRangeAddress aRet;
685 if (pDPObject->IsSheetData())
686 ScUnoConversion::FillApiRange( aRet, pDPObject->GetSheetDesc()->aSourceRange );
687 return aRet;
688 }
689
setSourceRange(const CellRangeAddress & aSourceRange)690 void SAL_CALL ScDataPilotDescriptorBase::setSourceRange( const CellRangeAddress& aSourceRange )
691 {
692 ScUnoGuard aGuard;
693
694 ScDPObject* pDPObject = GetDPObject();
695 if (!pDPObject)
696 throw RuntimeException();
697
698 ScSheetSourceDesc aSheetDesc;
699 if (pDPObject->IsSheetData())
700 aSheetDesc = *pDPObject->GetSheetDesc();
701 ScUnoConversion::FillScRange( aSheetDesc.aSourceRange, aSourceRange );
702 pDPObject->SetSheetDesc( aSheetDesc );
703 SetDPObject( pDPObject );
704 }
705
getFilterDescriptor()706 Reference<XSheetFilterDescriptor> SAL_CALL ScDataPilotDescriptorBase::getFilterDescriptor()
707 {
708 ScUnoGuard aGuard;
709 return new ScDataPilotFilterDescriptor( pDocShell, this );
710 }
711
getDataPilotFields()712 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getDataPilotFields()
713 {
714 ScUnoGuard aGuard;
715 return new ScDataPilotFieldsObj( *this );
716 }
717
getColumnFields()718 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getColumnFields()
719 {
720 ScUnoGuard aGuard;
721 return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_COLUMN );
722 }
723
getRowFields()724 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getRowFields()
725 {
726 ScUnoGuard aGuard;
727 return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_ROW );
728 }
729
getPageFields()730 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getPageFields()
731 {
732 ScUnoGuard aGuard;
733 return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_PAGE );
734 }
735
getDataFields()736 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getDataFields()
737 {
738 ScUnoGuard aGuard;
739 return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_DATA );
740 }
741
getHiddenFields()742 Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getHiddenFields()
743 {
744 ScUnoGuard aGuard;
745 return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_HIDDEN );
746 }
747
748 // XPropertySet
getPropertySetInfo()749 Reference< XPropertySetInfo > SAL_CALL ScDataPilotDescriptorBase::getPropertySetInfo( )
750 {
751 ScUnoGuard aGuard;
752 static Reference<XPropertySetInfo> aRef =
753 new SfxItemPropertySetInfo( maPropSet.getPropertyMap() );
754 return aRef;
755 }
756
setPropertyValue(const OUString & aPropertyName,const Any & aValue)757 void SAL_CALL ScDataPilotDescriptorBase::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
758 {
759 ScUnoGuard aGuard;
760 ScDPObject* pDPObject = GetDPObject();
761 if (pDPObject)
762 {
763 ScDPSaveData* pOldData = pDPObject->GetSaveData();
764 DBG_ASSERT(pOldData, "Here should be a SaveData");
765 if ( pOldData )
766 {
767 ScDPSaveData aNewData( *pOldData );
768
769 String aNameString = aPropertyName;
770 if ( aNameString.EqualsAscii( SC_UNO_COLGRAND ) )
771 {
772 aNewData.SetColumnGrand(::cppu::any2bool( aValue ));
773 }
774 else if ( aNameString.EqualsAscii( SC_UNO_IGNEMPROWS ) )
775 {
776 aNewData.SetIgnoreEmptyRows(::cppu::any2bool( aValue ));
777 }
778 else if ( aNameString.EqualsAscii( SC_UNO_RPTEMPTY ) )
779 {
780 aNewData.SetRepeatIfEmpty(::cppu::any2bool( aValue ));
781 }
782 else if ( aNameString.EqualsAscii( SC_UNO_ROWGRAND ) )
783 {
784 aNewData.SetRowGrand(::cppu::any2bool( aValue ));
785 }
786 else if ( aNameString.EqualsAscii( SC_UNO_SHOWFILT ) )
787 {
788 aNewData.SetFilterButton(::cppu::any2bool( aValue ));
789 }
790 else if ( aNameString.EqualsAscii( SC_UNO_DRILLDOWN ) )
791 {
792 aNewData.SetDrillDown(::cppu::any2bool( aValue ));
793 }
794 else if ( aNameString.EqualsAscii( SC_UNO_GRANDTOTAL_NAME ) )
795 {
796 rtl::OUString aStrVal;
797 if ( aValue >>= aStrVal )
798 aNewData.SetGrandTotalName(aStrVal);
799 }
800 else if ( aNameString.EqualsAscii( SC_UNO_IMPORTDESC ) )
801 {
802 uno::Sequence<beans::PropertyValue> aArgSeq;
803 if ( aValue >>= aArgSeq )
804 {
805 ScImportSourceDesc aImportDesc;
806
807 const ScImportSourceDesc* pOldDesc = pDPObject->GetImportSourceDesc();
808 if (pOldDesc)
809 aImportDesc = *pOldDesc;
810
811 ScImportParam aParam;
812 ScImportDescriptor::FillImportParam( aParam, aArgSeq );
813
814 sal_uInt16 nNewType = sheet::DataImportMode_NONE;
815 if ( aParam.bImport )
816 {
817 if ( aParam.bSql )
818 nNewType = sheet::DataImportMode_SQL;
819 else if ( aParam.nType == ScDbQuery )
820 nNewType = sheet::DataImportMode_QUERY;
821 else
822 nNewType = sheet::DataImportMode_TABLE;
823 }
824 aImportDesc.nType = nNewType;
825 aImportDesc.aDBName = aParam.aDBName;
826 aImportDesc.aObject = aParam.aStatement;
827 aImportDesc.bNative = aParam.bNative;
828
829 pDPObject->SetImportDesc( aImportDesc );
830 }
831 }
832 else if ( aNameString.EqualsAscii( SC_UNO_SOURCESERV ) )
833 {
834 rtl::OUString aStrVal;
835 if ( aValue >>= aStrVal )
836 {
837 String aEmpty;
838 ScDPServiceDesc aServiceDesc(aEmpty, aEmpty, aEmpty, aEmpty, aEmpty);
839
840 const ScDPServiceDesc* pOldDesc = pDPObject->GetDPServiceDesc();
841 if (pOldDesc)
842 aServiceDesc = *pOldDesc;
843
844 aServiceDesc.aServiceName = aStrVal;
845
846 pDPObject->SetServiceData( aServiceDesc );
847 }
848 }
849 else if ( aNameString.EqualsAscii( SC_UNO_SERVICEARG ) )
850 {
851 uno::Sequence<beans::PropertyValue> aArgSeq;
852 if ( aValue >>= aArgSeq )
853 {
854 String aEmpty;
855 ScDPServiceDesc aServiceDesc(aEmpty, aEmpty, aEmpty, aEmpty, aEmpty);
856
857 const ScDPServiceDesc* pOldDesc = pDPObject->GetDPServiceDesc();
858 if (pOldDesc)
859 aServiceDesc = *pOldDesc;
860
861 rtl::OUString aStrVal;
862 sal_Int32 nArgs = aArgSeq.getLength();
863 for (sal_Int32 nArgPos=0; nArgPos<nArgs; ++nArgPos)
864 {
865 const beans::PropertyValue& rProp = aArgSeq[nArgPos];
866 String aPropName(rProp.Name);
867
868 if (aPropName.EqualsAscii( SC_UNO_SOURCENAME ))
869 {
870 if ( rProp.Value >>= aStrVal )
871 aServiceDesc.aParSource = aStrVal;
872 }
873 else if (aPropName.EqualsAscii( SC_UNO_OBJECTNAME ))
874 {
875 if ( rProp.Value >>= aStrVal )
876 aServiceDesc.aParName = aStrVal;
877 }
878 else if (aPropName.EqualsAscii( SC_UNO_USERNAME ))
879 {
880 if ( rProp.Value >>= aStrVal )
881 aServiceDesc.aParUser = aStrVal;
882 }
883 else if (aPropName.EqualsAscii( SC_UNO_PASSWORD ))
884 {
885 if ( rProp.Value >>= aStrVal )
886 aServiceDesc.aParPass = aStrVal;
887 }
888 }
889
890 pDPObject->SetServiceData( aServiceDesc );
891 }
892 }
893 else
894 throw UnknownPropertyException();
895
896 pDPObject->SetSaveData( aNewData );
897 }
898
899 SetDPObject(pDPObject);
900 }
901 }
902
getPropertyValue(const OUString & aPropertyName)903 Any SAL_CALL ScDataPilotDescriptorBase::getPropertyValue( const OUString& aPropertyName )
904 {
905 ScUnoGuard aGuard;
906 Any aRet;
907
908 ScDPObject* pDPObject(GetDPObject());
909 if (pDPObject)
910 {
911 ScDPSaveData* pOldData = pDPObject->GetSaveData();
912 DBG_ASSERT(pOldData, "Here should be a SaveData");
913 if ( pOldData )
914 {
915 ScDPSaveData aNewData( *pOldData );
916
917 String aNameString = aPropertyName;
918 if ( aNameString.EqualsAscii( SC_UNO_COLGRAND ) )
919 {
920 aRet = ::cppu::bool2any( aNewData.GetColumnGrand() );
921 }
922 else if ( aNameString.EqualsAscii( SC_UNO_IGNEMPROWS ) )
923 {
924 aRet = ::cppu::bool2any( aNewData.GetIgnoreEmptyRows() );
925 }
926 else if ( aNameString.EqualsAscii( SC_UNO_RPTEMPTY ) )
927 {
928 aRet = ::cppu::bool2any( aNewData.GetRepeatIfEmpty() );
929 }
930 else if ( aNameString.EqualsAscii( SC_UNO_ROWGRAND ) )
931 {
932 aRet = ::cppu::bool2any( aNewData.GetRowGrand() );
933 }
934 else if ( aNameString.EqualsAscii( SC_UNO_SHOWFILT ) )
935 {
936 aRet = ::cppu::bool2any( aNewData.GetFilterButton() );
937 }
938 else if ( aNameString.EqualsAscii( SC_UNO_DRILLDOWN ) )
939 {
940 aRet = ::cppu::bool2any( aNewData.GetDrillDown() );
941 }
942 else if ( aNameString.EqualsAscii( SC_UNO_GRANDTOTAL_NAME ) )
943 {
944 const rtl::OUString* pGrandTotalName = aNewData.GetGrandTotalName();
945 if (pGrandTotalName)
946 aRet <<= *pGrandTotalName; // same behavior as in ScDPSource
947 }
948 else if ( aNameString.EqualsAscii( SC_UNO_IMPORTDESC ) )
949 {
950 const ScImportSourceDesc* pImportDesc = pDPObject->GetImportSourceDesc();
951 if ( pImportDesc )
952 {
953 // fill ScImportParam so ScImportDescriptor::FillProperties can be used
954 ScImportParam aParam;
955 aParam.bImport = ( pImportDesc->nType != sheet::DataImportMode_NONE );
956 aParam.aDBName = pImportDesc->aDBName;
957 aParam.aStatement = pImportDesc->aObject;
958 aParam.bNative = pImportDesc->bNative;
959 aParam.bSql = ( pImportDesc->nType == sheet::DataImportMode_SQL );
960 aParam.nType = static_cast<sal_uInt8>(( pImportDesc->nType == sheet::DataImportMode_QUERY ) ? ScDbQuery : ScDbTable);
961
962 uno::Sequence<beans::PropertyValue> aSeq( ScImportDescriptor::GetPropertyCount() );
963 ScImportDescriptor::FillProperties( aSeq, aParam );
964 aRet <<= aSeq;
965 }
966 else
967 {
968 // empty sequence
969 uno::Sequence<beans::PropertyValue> aEmpty(0);
970 aRet <<= aEmpty;
971 }
972 }
973 else if ( aNameString.EqualsAscii( SC_UNO_SOURCESERV ) )
974 {
975 rtl::OUString aServiceName;
976 const ScDPServiceDesc* pServiceDesc = pDPObject->GetDPServiceDesc();
977 if (pServiceDesc)
978 aServiceName = pServiceDesc->aServiceName;
979 aRet <<= aServiceName; // empty string if no ServiceDesc set
980 }
981 else if ( aNameString.EqualsAscii( SC_UNO_SERVICEARG ) )
982 {
983 const ScDPServiceDesc* pServiceDesc = pDPObject->GetDPServiceDesc();
984 if (pServiceDesc)
985 {
986 uno::Sequence<beans::PropertyValue> aSeq( 4 );
987 beans::PropertyValue* pArray = aSeq.getArray();
988 pArray[0].Name = rtl::OUString::createFromAscii( SC_UNO_SOURCENAME );
989 pArray[0].Value <<= rtl::OUString( pServiceDesc->aParSource );
990 pArray[1].Name = rtl::OUString::createFromAscii( SC_UNO_OBJECTNAME );
991 pArray[1].Value <<= rtl::OUString( pServiceDesc->aParName );
992 pArray[2].Name = rtl::OUString::createFromAscii( SC_UNO_USERNAME );
993 pArray[2].Value <<= rtl::OUString( pServiceDesc->aParUser );
994 pArray[3].Name = rtl::OUString::createFromAscii( SC_UNO_PASSWORD );
995 pArray[3].Value <<= rtl::OUString( pServiceDesc->aParPass );
996 aRet <<= aSeq;
997 }
998 else
999 {
1000 // empty sequence
1001 uno::Sequence<beans::PropertyValue> aEmpty(0);
1002 aRet <<= aEmpty;
1003 }
1004 }
1005 else
1006 throw UnknownPropertyException();
1007 }
1008 }
1009
1010 return aRet;
1011 }
1012
addPropertyChangeListener(const OUString &,const Reference<XPropertyChangeListener> &)1013 void SAL_CALL ScDataPilotDescriptorBase::addPropertyChangeListener(
1014 const OUString& /* aPropertyName */, const Reference<XPropertyChangeListener >& /* xListener */ )
1015 {
1016 }
1017
removePropertyChangeListener(const OUString &,const Reference<XPropertyChangeListener> &)1018 void SAL_CALL ScDataPilotDescriptorBase::removePropertyChangeListener(
1019 const OUString& /* aPropertyName */, const Reference<XPropertyChangeListener >& /* aListener */ )
1020 {
1021 }
1022
addVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)1023 void SAL_CALL ScDataPilotDescriptorBase::addVetoableChangeListener(
1024 const OUString& /* PropertyName */, const Reference<XVetoableChangeListener >& /* aListener */ )
1025 {
1026 }
1027
removeVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)1028 void SAL_CALL ScDataPilotDescriptorBase::removeVetoableChangeListener(
1029 const OUString& /* PropertyName */, const Reference<XVetoableChangeListener >& /* aListener */ )
1030 {
1031 }
1032
1033 // XDataPilotDataLayoutFieldSupplier
1034
getDataLayoutField()1035 Reference< XDataPilotField > SAL_CALL ScDataPilotDescriptorBase::getDataLayoutField()
1036 {
1037 ScUnoGuard aGuard;
1038 if( ScDPObject* pDPObject = GetDPObject() )
1039 {
1040 if( ScDPSaveData* pSaveData = pDPObject->GetSaveData() )
1041 {
1042 if( /*ScDPSaveDimension* pDataDim =*/ pSaveData->GetDataLayoutDimension() )
1043 {
1044 ScFieldIdentifier aFieldId( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_DATALAYOUT_NAME ) ), 0, true );
1045 return new ScDataPilotFieldObj( *this, aFieldId );
1046 }
1047 }
1048 }
1049 return 0;
1050 }
1051
1052 // XUnoTunnel
1053
getSomething(const Sequence<sal_Int8> & rId)1054 sal_Int64 SAL_CALL ScDataPilotDescriptorBase::getSomething(
1055 const Sequence<sal_Int8 >& rId )
1056 {
1057 if ( rId.getLength() == 16 &&
1058 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
1059 rId.getConstArray(), 16 ) )
1060 {
1061 return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
1062 }
1063 return 0;
1064 }
1065
1066 // static
getUnoTunnelId()1067 const Sequence<sal_Int8>& ScDataPilotDescriptorBase::getUnoTunnelId()
1068 {
1069 static Sequence<sal_Int8> * pSeq = 0;
1070 if( !pSeq )
1071 {
1072 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
1073 if( !pSeq )
1074 {
1075 static Sequence< sal_Int8 > aSeq( 16 );
1076 rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
1077 pSeq = &aSeq;
1078 }
1079 }
1080 return *pSeq;
1081 }
1082
1083 // static
getImplementation(const Reference<XDataPilotDescriptor> xObj)1084 ScDataPilotDescriptorBase* ScDataPilotDescriptorBase::getImplementation(
1085 const Reference<XDataPilotDescriptor> xObj )
1086 {
1087 ScDataPilotDescriptorBase* pRet = NULL;
1088 Reference<lang::XUnoTunnel> xUT( xObj, UNO_QUERY );
1089 if (xUT.is())
1090 pRet = reinterpret_cast<ScDataPilotDescriptorBase*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
1091 return pRet;
1092 }
1093
1094 //------------------------------------------------------------------------
1095
ScDataPilotTableObj(ScDocShell * pDocSh,SCTAB nT,const String & rN)1096 ScDataPilotTableObj::ScDataPilotTableObj(ScDocShell* pDocSh, SCTAB nT, const String& rN) :
1097 ScDataPilotDescriptorBase( pDocSh ),
1098 nTab( nT ),
1099 aName( rN ),
1100 aModifyListeners( 0 )
1101 {
1102 }
1103
~ScDataPilotTableObj()1104 ScDataPilotTableObj::~ScDataPilotTableObj()
1105 {
1106 }
1107
queryInterface(const uno::Type & rType)1108 Any SAL_CALL ScDataPilotTableObj::queryInterface( const uno::Type& rType )
1109 {
1110 // since we manually do resolve the query for XDataPilotTable2
1111 // we also need to do the same for XDataPilotTable
1112 SC_QUERYINTERFACE( XDataPilotTable )
1113 SC_QUERYINTERFACE( XDataPilotTable2 )
1114 SC_QUERYINTERFACE( XModifyBroadcaster )
1115
1116 return ScDataPilotDescriptorBase::queryInterface( rType );
1117 }
1118
acquire()1119 void SAL_CALL ScDataPilotTableObj::acquire() throw()
1120 {
1121 ScDataPilotDescriptorBase::acquire();
1122 }
1123
release()1124 void SAL_CALL ScDataPilotTableObj::release() throw()
1125 {
1126 ScDataPilotDescriptorBase::release();
1127 }
1128
getTypes()1129 Sequence< uno::Type > SAL_CALL ScDataPilotTableObj::getTypes()
1130 {
1131 static Sequence< uno::Type > aTypes;
1132 if ( aTypes.getLength() == 0 )
1133 {
1134 Sequence< uno::Type > aParentTypes = ScDataPilotDescriptorBase::getTypes();
1135 sal_Int32 nParentLen = aParentTypes.getLength();
1136 const uno::Type* pParentPtr = aParentTypes.getConstArray();
1137
1138 aTypes.realloc( nParentLen + 2 );
1139 uno::Type* pPtr = aTypes.getArray();
1140 for (sal_Int32 i = 0; i < nParentLen; ++i)
1141 pPtr[ i ] = pParentPtr[ i ]; // parent types first
1142
1143 pPtr[ nParentLen ] = getCppuType( (const Reference< XDataPilotTable2 >*)0 );
1144 pPtr[ nParentLen+1 ] = getCppuType( (const Reference< XModifyBroadcaster >*)0 );
1145 }
1146 return aTypes;
1147 }
1148
getImplementationId()1149 Sequence<sal_Int8> SAL_CALL ScDataPilotTableObj::getImplementationId()
1150 {
1151 static Sequence< sal_Int8 > aId;
1152 if( aId.getLength() == 0 )
1153 {
1154 aId.realloc( 16 );
1155 rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True );
1156 }
1157 return aId;
1158 }
1159
1160 // ---
GetDPObject() const1161 ScDPObject* ScDataPilotTableObj::GetDPObject() const
1162 {
1163 return lcl_GetDPObject(GetDocShell(), nTab, aName);
1164 }
1165
SetDPObject(ScDPObject * pDPObject)1166 void ScDataPilotTableObj::SetDPObject( ScDPObject* pDPObject )
1167 {
1168 ScDocShell* pDocSh = GetDocShell();
1169 ScDPObject* pDPObj = lcl_GetDPObject(pDocSh, nTab, aName);
1170 if ( pDPObj && pDocSh )
1171 {
1172 ScDBDocFunc aFunc(*pDocSh);
1173 aFunc.DataPilotUpdate( pDPObj, pDPObject, sal_True, sal_True );
1174 }
1175 }
1176
1177 // "rest of XDataPilotDescriptor"
1178
getName()1179 OUString SAL_CALL ScDataPilotTableObj::getName()
1180 {
1181 ScUnoGuard aGuard;
1182 ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName);
1183 if (pDPObj)
1184 return pDPObj->GetName();
1185 return OUString();
1186 }
1187
setName(const OUString & aNewName)1188 void SAL_CALL ScDataPilotTableObj::setName( const OUString& aNewName )
1189 {
1190 ScUnoGuard aGuard;
1191 ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName);
1192 if (pDPObj)
1193 {
1194 //! test for existing names !!!
1195
1196 String aString(aNewName);
1197 pDPObj->SetName( aString ); //! Undo - DBDocFunc ???
1198 aName = aString;
1199
1200 // DataPilotUpdate would do too much (output table is not changed)
1201 GetDocShell()->SetDocumentModified();
1202 }
1203 }
1204
getTag()1205 OUString SAL_CALL ScDataPilotTableObj::getTag()
1206 {
1207 ScUnoGuard aGuard;
1208 ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName);
1209 if (pDPObj)
1210 return pDPObj->GetTag();
1211 return OUString();
1212 }
1213
setTag(const OUString & aNewTag)1214 void SAL_CALL ScDataPilotTableObj::setTag( const OUString& aNewTag )
1215 {
1216 ScUnoGuard aGuard;
1217 ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName);
1218 if (pDPObj)
1219 {
1220 String aString(aNewTag);
1221 pDPObj->SetTag( aString ); //! Undo - DBDocFunc ???
1222
1223 // DataPilotUpdate would do too much (output table is not changed)
1224 GetDocShell()->SetDocumentModified();
1225 }
1226 }
1227
1228 // XDataPilotTable
1229
getOutputRange()1230 CellRangeAddress SAL_CALL ScDataPilotTableObj::getOutputRange()
1231 {
1232 ScUnoGuard aGuard;
1233 CellRangeAddress aRet;
1234 ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName);
1235 if (pDPObj)
1236 {
1237 ScRange aRange(pDPObj->GetOutRange());
1238 aRet.Sheet = aRange.aStart.Tab();
1239 aRet.StartColumn = aRange.aStart.Col();
1240 aRet.StartRow = aRange.aStart.Row();
1241 aRet.EndColumn = aRange.aEnd.Col();
1242 aRet.EndRow = aRange.aEnd.Row();
1243 }
1244 return aRet;
1245 }
1246
1247 sal_uLong RefreshDPObject( ScDPObject *pDPObj, ScDocument *pDoc, ScDocShell *pDocSh, sal_Bool bRecord, sal_Bool bApi );
1248
refresh()1249 void SAL_CALL ScDataPilotTableObj::refresh()
1250 {
1251 ScUnoGuard aGuard;
1252 if( ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName) )
1253 RefreshDPObject( pDPObj, NULL, GetDocShell(), sal_True, sal_True );
1254 //if (pDPObj)
1255 //{
1256 // ScDPObject* pNew = new ScDPObject(*pDPObj);
1257 // ScDBDocFunc aFunc(*GetDocShell());
1258 // aFunc.DataPilotUpdate( pDPObj, pNew, sal_True, sal_True );
1259 // delete pNew; // DataPilotUpdate copies settings from "new" object
1260 //}
1261
1262 }
1263
getDrillDownData(const CellAddress & aAddr)1264 Sequence< Sequence<Any> > SAL_CALL ScDataPilotTableObj::getDrillDownData(const CellAddress& aAddr)
1265 {
1266 ScUnoGuard aGuard;
1267 Sequence< Sequence<Any> > aTabData;
1268 ScAddress aAddr2(static_cast<SCCOL>(aAddr.Column), static_cast<SCROW>(aAddr.Row), aAddr.Sheet);
1269 ScDPObject* pObj = GetDPObject();
1270 if (!pObj)
1271 throw RuntimeException();
1272
1273 pObj->GetDrillDownData(aAddr2, aTabData);
1274 return aTabData;
1275 }
1276
getPositionData(const CellAddress & aAddr)1277 DataPilotTablePositionData SAL_CALL ScDataPilotTableObj::getPositionData(const CellAddress& aAddr)
1278 {
1279 ScUnoGuard aGuard;
1280 DataPilotTablePositionData aPosData;
1281 ScAddress aAddr2(static_cast<SCCOL>(aAddr.Column), static_cast<SCROW>(aAddr.Row), aAddr.Sheet);
1282 ScDPObject* pObj = GetDPObject();
1283 if (!pObj)
1284 throw RuntimeException();
1285
1286 pObj->GetPositionData(aAddr2, aPosData);
1287 return aPosData;
1288 }
1289
insertDrillDownSheet(const CellAddress & aAddr)1290 void SAL_CALL ScDataPilotTableObj::insertDrillDownSheet(const CellAddress& aAddr)
1291 {
1292 ScUnoGuard aGuard;
1293 ScDPObject* pDPObj = GetDPObject();
1294 if (!pDPObj)
1295 throw RuntimeException();
1296
1297 Sequence<DataPilotFieldFilter> aFilters;
1298 pDPObj->GetDataFieldPositionData(
1299 ScAddress(static_cast<SCCOL>(aAddr.Column), static_cast<SCROW>(aAddr.Row), aAddr.Sheet), aFilters);
1300 GetDocShell()->GetBestViewShell()->ShowDataPilotSourceData(*pDPObj, aFilters);
1301 }
1302
getOutputRangeByType(sal_Int32 nType)1303 CellRangeAddress SAL_CALL ScDataPilotTableObj::getOutputRangeByType( sal_Int32 nType )
1304 {
1305 ScUnoGuard aGuard;
1306 if (nType < 0 || nType > DataPilotOutputRangeType::RESULT)
1307 throw IllegalArgumentException();
1308
1309 CellRangeAddress aRet;
1310 if (ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName))
1311 ScUnoConversion::FillApiRange( aRet, pDPObj->GetOutputRangeByType( nType ) );
1312 return aRet;
1313 }
1314
addModifyListener(const uno::Reference<util::XModifyListener> & aListener)1315 void SAL_CALL ScDataPilotTableObj::addModifyListener( const uno::Reference<util::XModifyListener>& aListener )
1316 {
1317 ScUnoGuard aGuard;
1318
1319 uno::Reference<util::XModifyListener> *pObj = new uno::Reference<util::XModifyListener>( aListener );
1320 aModifyListeners.Insert( pObj, aModifyListeners.Count() );
1321
1322 if ( aModifyListeners.Count() == 1 )
1323 {
1324 acquire(); // don't lose this object (one ref for all listeners)
1325 }
1326 }
1327
removeModifyListener(const uno::Reference<util::XModifyListener> & aListener)1328 void SAL_CALL ScDataPilotTableObj::removeModifyListener( const uno::Reference<util::XModifyListener>& aListener )
1329 {
1330 ScUnoGuard aGuard;
1331
1332 acquire(); // in case the listeners have the last ref - released below
1333
1334 sal_uInt16 nCount = aModifyListeners.Count();
1335 for ( sal_uInt16 n=nCount; n--; )
1336 {
1337 uno::Reference<util::XModifyListener> *pObj = aModifyListeners[n];
1338 if ( *pObj == aListener )
1339 {
1340 aModifyListeners.DeleteAndDestroy( n );
1341
1342 if ( aModifyListeners.Count() == 0 )
1343 {
1344 release(); // release the ref for the listeners
1345 }
1346
1347 break;
1348 }
1349 }
1350
1351 release(); // might delete this object
1352 }
1353
Notify(SfxBroadcaster & rBC,const SfxHint & rHint)1354 void ScDataPilotTableObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1355 {
1356 if ( rHint.ISA(ScDataPilotModifiedHint) &&
1357 static_cast<const ScDataPilotModifiedHint&>(rHint).GetName() == aName )
1358 {
1359 Refreshed_Impl();
1360 }
1361 else if ( rHint.ISA( ScUpdateRefHint ) )
1362 {
1363 ScRange aRange( 0, 0, nTab );
1364 ScRangeList aRanges;
1365 aRanges.Append( aRange );
1366 const ScUpdateRefHint& rRef = static_cast< const ScUpdateRefHint& >( rHint );
1367 if ( aRanges.UpdateReference( rRef.GetMode(), GetDocShell()->GetDocument(), rRef.GetRange(),
1368 rRef.GetDx(), rRef.GetDy(), rRef.GetDz() ) &&
1369 aRanges.Count() == 1 )
1370 {
1371 const ScRange* pRange = aRanges.GetObject( 0 );
1372 if ( pRange )
1373 {
1374 nTab = pRange->aStart.Tab();
1375 }
1376 }
1377 }
1378
1379 ScDataPilotDescriptorBase::Notify( rBC, rHint );
1380 }
1381
Refreshed_Impl()1382 void ScDataPilotTableObj::Refreshed_Impl()
1383 {
1384 lang::EventObject aEvent;
1385 aEvent.Source.set((cppu::OWeakObject*)this);
1386
1387 // the EventObject holds a Ref to this object until after the listener calls
1388
1389 ScDocument* pDoc = GetDocShell()->GetDocument();
1390 for ( sal_uInt16 n=0; n<aModifyListeners.Count(); n++ )
1391 pDoc->AddUnoListenerCall( *aModifyListeners[n], aEvent );
1392 }
1393
1394 // ============================================================================
1395
ScDataPilotDescriptor(ScDocShell * pDocSh)1396 ScDataPilotDescriptor::ScDataPilotDescriptor(ScDocShell* pDocSh) :
1397 ScDataPilotDescriptorBase( pDocSh ),
1398 mpDPObject(new ScDPObject(pDocSh ? pDocSh->GetDocument() : NULL) )
1399 {
1400 mpDPObject->SetAlive(sal_True);
1401 ScDPSaveData aSaveData;
1402 // set defaults like in ScPivotParam constructor
1403 aSaveData.SetColumnGrand( sal_True );
1404 aSaveData.SetRowGrand( sal_True );
1405 aSaveData.SetIgnoreEmptyRows( sal_False );
1406 aSaveData.SetRepeatIfEmpty( sal_False );
1407 mpDPObject->SetSaveData(aSaveData);
1408 ScSheetSourceDesc aSheetDesc;
1409 mpDPObject->SetSheetDesc(aSheetDesc);
1410 mpDPObject->GetSource();
1411 }
1412
~ScDataPilotDescriptor()1413 ScDataPilotDescriptor::~ScDataPilotDescriptor()
1414 {
1415 delete mpDPObject;
1416 }
1417
GetDPObject() const1418 ScDPObject* ScDataPilotDescriptor::GetDPObject() const
1419 {
1420 return mpDPObject;
1421 }
1422
SetDPObject(ScDPObject * pDPObject)1423 void ScDataPilotDescriptor::SetDPObject( ScDPObject* pDPObject )
1424 {
1425 if (mpDPObject != pDPObject)
1426 {
1427 delete mpDPObject;
1428 mpDPObject = pDPObject;
1429 DBG_ERROR("replace DPObject should not happen");
1430 }
1431 }
1432
1433 // "rest of XDataPilotDescriptor"
1434
getName()1435 OUString SAL_CALL ScDataPilotDescriptor::getName()
1436 {
1437 ScUnoGuard aGuard;
1438 return mpDPObject->GetName();
1439 }
1440
setName(const OUString & aNewName)1441 void SAL_CALL ScDataPilotDescriptor::setName( const OUString& aNewName )
1442 {
1443 ScUnoGuard aGuard;
1444 mpDPObject->SetName( aNewName );
1445 }
1446
getTag()1447 OUString SAL_CALL ScDataPilotDescriptor::getTag()
1448 {
1449 ScUnoGuard aGuard;
1450 return mpDPObject->GetTag();
1451 }
1452
setTag(const OUString & aNewTag)1453 void SAL_CALL ScDataPilotDescriptor::setTag( const OUString& aNewTag )
1454 {
1455 ScUnoGuard aGuard;
1456 mpDPObject->SetTag( aNewTag );
1457 }
1458
1459 // ============================================================================
1460
ScDataPilotChildObjBase(ScDataPilotDescriptorBase & rParent)1461 ScDataPilotChildObjBase::ScDataPilotChildObjBase( ScDataPilotDescriptorBase& rParent ) :
1462 mrParent( rParent )
1463 {
1464 mrParent.acquire();
1465 }
1466
ScDataPilotChildObjBase(ScDataPilotDescriptorBase & rParent,const ScFieldIdentifier & rFieldId)1467 ScDataPilotChildObjBase::ScDataPilotChildObjBase( ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId ) :
1468 mrParent( rParent ),
1469 maFieldId( rFieldId )
1470 {
1471 mrParent.acquire();
1472 }
1473
~ScDataPilotChildObjBase()1474 ScDataPilotChildObjBase::~ScDataPilotChildObjBase()
1475 {
1476 mrParent.release();
1477 }
1478
GetDPObject() const1479 ScDPObject* ScDataPilotChildObjBase::GetDPObject() const
1480 {
1481 return mrParent.GetDPObject();
1482 }
1483
SetDPObject(ScDPObject * pDPObject)1484 void ScDataPilotChildObjBase::SetDPObject( ScDPObject* pDPObject )
1485 {
1486 mrParent.SetDPObject( pDPObject );
1487 }
1488
GetDPDimension(ScDPObject ** ppDPObject) const1489 ScDPSaveDimension* ScDataPilotChildObjBase::GetDPDimension( ScDPObject** ppDPObject ) const
1490 {
1491 if( ScDPObject* pDPObj = GetDPObject() )
1492 {
1493 if( ppDPObject ) *ppDPObject = pDPObj;
1494 if( ScDPSaveData* pSaveData = pDPObj->GetSaveData() )
1495 {
1496 if( maFieldId.mbDataLayout )
1497 return pSaveData->GetDataLayoutDimension();
1498
1499 if( maFieldId.mnFieldIdx == 0 )
1500 return pSaveData->GetDimensionByName( maFieldId.maFieldName );
1501
1502 // find dimension with specified index (search in duplicated dimensions)
1503 String aFieldName = maFieldId.maFieldName; // needed for comparison
1504 const List& rDimensions = pSaveData->GetDimensions();
1505 sal_uLong nDimCount = rDimensions.Count();
1506 sal_Int32 nFoundIdx = 0;
1507 for( sal_uLong nDim = 0; nDim < nDimCount; ++nDim )
1508 {
1509 ScDPSaveDimension* pDim = static_cast< ScDPSaveDimension* >( rDimensions.GetObject( nDim ) );
1510 if( !pDim->IsDataLayout() && (pDim->GetName() == aFieldName) )
1511 {
1512 if( nFoundIdx == maFieldId.mnFieldIdx )
1513 return pDim;
1514 ++nFoundIdx;
1515 }
1516 }
1517 }
1518 }
1519 return 0;
1520 }
1521
GetMemberCount() const1522 sal_Int32 ScDataPilotChildObjBase::GetMemberCount() const
1523 {
1524 sal_Int32 nRet = 0;
1525 Reference<XNameAccess> xMembersNA = GetMembers();
1526 if (xMembersNA.is())
1527 {
1528 Reference< XIndexAccess > xMembersIA( new ScNameToIndexAccess( xMembersNA ) );
1529 nRet = xMembersIA->getCount();
1530 }
1531 return nRet;
1532 }
1533
GetMembers() const1534 Reference< XNameAccess > ScDataPilotChildObjBase::GetMembers() const
1535 {
1536 Reference< XNameAccess > xMembersNA;
1537 if( ScDPObject* pDPObj = GetDPObject() )
1538 pDPObj->GetMembersNA( lcl_GetObjectIndex( pDPObj, maFieldId ), xMembersNA );
1539 return xMembersNA;
1540 }
1541
1542 // ============================================================================
1543
ScDataPilotFieldsObj(ScDataPilotDescriptorBase & rParent)1544 ScDataPilotFieldsObj::ScDataPilotFieldsObj( ScDataPilotDescriptorBase& rParent ) :
1545 ScDataPilotChildObjBase( rParent )
1546 {
1547 }
1548
ScDataPilotFieldsObj(ScDataPilotDescriptorBase & rParent,DataPilotFieldOrientation eOrient)1549 ScDataPilotFieldsObj::ScDataPilotFieldsObj( ScDataPilotDescriptorBase& rParent, DataPilotFieldOrientation eOrient ) :
1550 ScDataPilotChildObjBase( rParent ),
1551 maOrient( eOrient )
1552 {
1553 }
1554
~ScDataPilotFieldsObj()1555 ScDataPilotFieldsObj::~ScDataPilotFieldsObj()
1556 {
1557 }
1558
lcl_GetFieldCount(const Reference<XDimensionsSupplier> & rSource,const Any & rOrient)1559 sal_Int32 lcl_GetFieldCount( const Reference<XDimensionsSupplier>& rSource, const Any& rOrient )
1560 {
1561 sal_Int32 nRet = 0;
1562
1563 Reference<XNameAccess> xDimsName(rSource->getDimensions());
1564 Reference<XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
1565 sal_Int32 nIntCount = xIntDims->getCount();
1566 if (rOrient.hasValue())
1567 {
1568 // all fields of the specified orientation, including duplicated
1569 Reference<XPropertySet> xDim;
1570 for (sal_Int32 i = 0; i < nIntCount; ++i)
1571 {
1572 xDim.set(xIntDims->getByIndex(i), UNO_QUERY);
1573 if (xDim.is() && (xDim->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ORIENTAT))) == rOrient))
1574 ++nRet;
1575 }
1576 }
1577 else
1578 {
1579 // count all non-duplicated fields
1580
1581 Reference<XPropertySet> xDim;
1582 for (sal_Int32 i = 0; i < nIntCount; ++i)
1583 {
1584 xDim.set(xIntDims->getByIndex(i), UNO_QUERY);
1585 if ( xDim.is() && !lcl_IsDuplicated( xDim ) )
1586 ++nRet;
1587 }
1588 }
1589
1590 return nRet;
1591 }
1592
lcl_GetFieldDataByIndex(const Reference<XDimensionsSupplier> & rSource,const Any & rOrient,SCSIZE nIndex,ScFieldIdentifier & rFieldId)1593 sal_Bool lcl_GetFieldDataByIndex( const Reference<XDimensionsSupplier>& rSource,
1594 const Any& rOrient, SCSIZE nIndex, ScFieldIdentifier& rFieldId )
1595 {
1596 sal_Bool bOk = sal_False;
1597 SCSIZE nPos = 0;
1598 sal_Int32 nDimIndex = 0;
1599
1600 Reference<XNameAccess> xDimsName(rSource->getDimensions());
1601 Reference<XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
1602 sal_Int32 nIntCount = xIntDims->getCount();
1603 Reference<XPropertySet> xDim;
1604 if (rOrient.hasValue())
1605 {
1606 sal_Int32 i = 0;
1607 while (i < nIntCount && !bOk)
1608 {
1609 xDim.set(xIntDims->getByIndex(i), UNO_QUERY);
1610 if (xDim.is() && (xDim->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ORIENTAT))) == rOrient))
1611 {
1612 if (nPos == nIndex)
1613 {
1614 bOk = sal_True;
1615 nDimIndex = i;
1616 }
1617 else
1618 ++nPos;
1619 }
1620 ++i;
1621 }
1622 }
1623 else
1624 {
1625 sal_Int32 i = 0;
1626 while (i < nIntCount && !bOk)
1627 {
1628 xDim.set(xIntDims->getByIndex(i), UNO_QUERY);
1629 if ( xDim.is() && !lcl_IsDuplicated( xDim ) )
1630 {
1631 if (nPos == nIndex)
1632 {
1633 bOk = sal_True;
1634 nDimIndex = i;
1635 }
1636 else
1637 ++nPos;
1638 }
1639 ++i;
1640 }
1641 }
1642
1643 if ( bOk )
1644 {
1645 xDim.set( xIntDims->getByIndex(nDimIndex), UNO_QUERY );
1646 Reference<XNamed> xDimName( xDim, UNO_QUERY );
1647 if ( xDimName.is() )
1648 {
1649 OUString sOriginalName( lcl_GetOriginalName( xDimName ) );
1650 rFieldId.maFieldName = sOriginalName;
1651 rFieldId.mbDataLayout = ScUnoHelpFunctions::GetBoolProperty( xDim,
1652 OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ISDATALA)) );
1653
1654 sal_Int32 nRepeat = 0;
1655 if ( rOrient.hasValue() && lcl_IsDuplicated( xDim ) )
1656 {
1657 // find the repeat count
1658 // (this relies on the original dimension always being before the duplicates)
1659
1660 Reference<XNamed> xPrevName;
1661 for (sal_Int32 i = 0; i < nDimIndex; ++i)
1662 {
1663 xPrevName.set( xIntDims->getByIndex(i), UNO_QUERY );
1664 if ( xPrevName.is() && lcl_GetOriginalName( xPrevName ) == sOriginalName )
1665 ++nRepeat;
1666 }
1667 }
1668 rFieldId.mnFieldIdx = nRepeat;
1669 }
1670 else
1671 bOk = sal_False;
1672 }
1673
1674 return bOk;
1675 }
1676
lcl_GetFieldDataByName(ScDPObject * pDPObj,const OUString & rFieldName,ScFieldIdentifier & rFieldId)1677 sal_Bool lcl_GetFieldDataByName( ScDPObject* pDPObj, const OUString& rFieldName, ScFieldIdentifier& rFieldId )
1678 {
1679 // "By name" is always the first match.
1680 // The name "Data" always refers to the data layout field.
1681 rFieldId.maFieldName = rFieldName;
1682 rFieldId.mnFieldIdx = 0;
1683 rFieldId.mbDataLayout = rFieldName.equalsAscii( SC_DATALAYOUT_NAME );
1684
1685 pDPObj->GetSource(); // IsDimNameInUse doesn't update source data
1686
1687 // check if the named field exists (not for data layout)
1688 return rFieldId.mbDataLayout || pDPObj->IsDimNameInUse( rFieldName );
1689 }
1690
1691 // XDataPilotFields
1692
GetObjectByIndex_Impl(sal_Int32 nIndex) const1693 ScDataPilotFieldObj* ScDataPilotFieldsObj::GetObjectByIndex_Impl( sal_Int32 nIndex ) const
1694 {
1695 // TODO
1696 if (ScDPObject* pObj = GetDPObject())
1697 {
1698 ScFieldIdentifier aFieldId;
1699 if (lcl_GetFieldDataByIndex( pObj->GetSource(), maOrient, nIndex, aFieldId ))
1700 return new ScDataPilotFieldObj( mrParent, aFieldId, maOrient );
1701 }
1702 return 0;
1703 }
1704
GetObjectByName_Impl(const OUString & aName) const1705 ScDataPilotFieldObj* ScDataPilotFieldsObj::GetObjectByName_Impl(const OUString& aName) const
1706 {
1707 if (ScDPObject* pDPObj = GetDPObject())
1708 {
1709 ScFieldIdentifier aFieldId;
1710 if (lcl_GetFieldDataByName( pDPObj, aName, aFieldId ))
1711 return new ScDataPilotFieldObj( mrParent, aFieldId, maOrient );
1712 }
1713 return 0;
1714 }
1715
1716 // XEnumerationAccess
1717
createEnumeration()1718 Reference<XEnumeration> SAL_CALL ScDataPilotFieldsObj::createEnumeration()
1719 {
1720 ScUnoGuard aGuard;
1721 return new ScIndexEnumeration(this, OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DataPilotFieldsEnumeration")));
1722 }
1723
1724 // XIndexAccess
1725
getCount()1726 sal_Int32 SAL_CALL ScDataPilotFieldsObj::getCount()
1727 {
1728 ScUnoGuard aGuard;
1729 // TODO
1730 ScDPObject* pDPObj = GetDPObject();
1731 return pDPObj ? lcl_GetFieldCount( pDPObj->GetSource(), maOrient ) : 0;
1732 }
1733
getByIndex(sal_Int32 nIndex)1734 Any SAL_CALL ScDataPilotFieldsObj::getByIndex( sal_Int32 nIndex )
1735 {
1736 ScUnoGuard aGuard;
1737 Reference< XPropertySet > xField( GetObjectByIndex_Impl( nIndex ) );
1738 if (!xField.is())
1739 throw IndexOutOfBoundsException();
1740 return Any( xField );
1741 }
1742
getElementType()1743 uno::Type SAL_CALL ScDataPilotFieldsObj::getElementType()
1744 {
1745 ScUnoGuard aGuard;
1746 return getCppuType((Reference<XPropertySet>*)0);
1747 }
1748
hasElements()1749 sal_Bool SAL_CALL ScDataPilotFieldsObj::hasElements()
1750 {
1751 ScUnoGuard aGuard;
1752 return ( getCount() != 0 );
1753 }
1754
getByName(const OUString & aName)1755 Any SAL_CALL ScDataPilotFieldsObj::getByName( const OUString& aName )
1756 {
1757 ScUnoGuard aGuard;
1758 Reference<XPropertySet> xField(GetObjectByName_Impl(aName));
1759 if (!xField.is())
1760 throw NoSuchElementException();
1761 return Any( xField );
1762 }
1763
getElementNames()1764 Sequence<OUString> SAL_CALL ScDataPilotFieldsObj::getElementNames()
1765 {
1766 ScUnoGuard aGuard;
1767 // TODO
1768 if (ScDPObject* pDPObj = GetDPObject())
1769 {
1770 Sequence< OUString > aSeq( lcl_GetFieldCount( pDPObj->GetSource(), maOrient ) );
1771 OUString* pAry = aSeq.getArray();
1772 const List& rDimensions = pDPObj->GetSaveData()->GetDimensions();
1773 sal_Int32 nDimCount = rDimensions.Count();
1774 for (sal_Int32 nDim = 0; nDim < nDimCount; nDim++)
1775 {
1776 ScDPSaveDimension* pDim = (ScDPSaveDimension*)rDimensions.GetObject(nDim);
1777 if(maOrient.hasValue() && (pDim->GetOrientation() == maOrient.get< DataPilotFieldOrientation >()))
1778 {
1779 *pAry = pDim->GetName();
1780 ++pAry;
1781 }
1782 }
1783 return aSeq;
1784 }
1785 return Sequence<OUString>();
1786 }
1787
hasByName(const OUString & aName)1788 sal_Bool SAL_CALL ScDataPilotFieldsObj::hasByName( const OUString& aName )
1789 {
1790 ScUnoGuard aGuard;
1791
1792 return GetObjectByName_Impl(aName) != NULL;
1793 }
1794
1795 //------------------------------------------------------------------------
1796
ScDataPilotFieldObj(ScDataPilotDescriptorBase & rParent,const ScFieldIdentifier & rFieldId)1797 ScDataPilotFieldObj::ScDataPilotFieldObj(
1798 ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId ) :
1799 ScDataPilotChildObjBase( rParent, rFieldId ),
1800 maPropSet( lcl_GetDataPilotFieldMap() )
1801 {
1802 }
1803
ScDataPilotFieldObj(ScDataPilotDescriptorBase & rParent,const ScFieldIdentifier & rFieldId,const Any & rOrient)1804 ScDataPilotFieldObj::ScDataPilotFieldObj( ScDataPilotDescriptorBase& rParent,
1805 const ScFieldIdentifier& rFieldId, const Any& rOrient ) :
1806 ScDataPilotChildObjBase( rParent, rFieldId ),
1807 maPropSet( lcl_GetDataPilotFieldMap() ),
1808 maOrient( rOrient )
1809 {
1810 }
1811
~ScDataPilotFieldObj()1812 ScDataPilotFieldObj::~ScDataPilotFieldObj()
1813 {
1814 }
1815
1816 // XNamed
1817
getName()1818 OUString SAL_CALL ScDataPilotFieldObj::getName()
1819 {
1820 ScUnoGuard aGuard;
1821 OUString aName;
1822 if( ScDPSaveDimension* pDim = GetDPDimension() )
1823 {
1824 if( pDim->IsDataLayout() )
1825 aName = OUString( RTL_CONSTASCII_USTRINGPARAM( SC_DATALAYOUT_NAME ) );
1826 else
1827 {
1828 const rtl::OUString* pLayoutName = pDim->GetLayoutName();
1829 if (pLayoutName)
1830 aName = *pLayoutName;
1831 else
1832 aName = pDim->GetName();
1833 } }
1834 return aName;
1835 }
1836
setName(const OUString & rName)1837 void SAL_CALL ScDataPilotFieldObj::setName( const OUString& rName )
1838 {
1839 ScUnoGuard aGuard;
1840 ScDPObject* pDPObj = 0;
1841 ScDPSaveDimension* pDim = GetDPDimension( &pDPObj );
1842 if( pDim && !pDim->IsDataLayout() )
1843 {
1844 String aName( rName );
1845 pDim->SetLayoutName(aName);
1846 SetDPObject( pDPObj );
1847 }
1848 }
1849
1850 // XPropertySet
1851
getPropertySetInfo()1852 Reference<XPropertySetInfo> SAL_CALL ScDataPilotFieldObj::getPropertySetInfo()
1853 {
1854 ScUnoGuard aGuard;
1855 static Reference<XPropertySetInfo> aRef(
1856 new SfxItemPropertySetInfo( maPropSet.getPropertyMap() ));
1857 return aRef;
1858 }
1859
setPropertyValue(const OUString & aPropertyName,const Any & aValue)1860 void SAL_CALL ScDataPilotFieldObj::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
1861 {
1862 ScUnoGuard aGuard;
1863 String aNameString(aPropertyName);
1864 if ( aNameString.EqualsAscii( SC_UNONAME_FUNCTION ) )
1865 {
1866 // #i109350# use GetEnumFromAny because it also allows sal_Int32
1867 GeneralFunction eFunction = (GeneralFunction)
1868 ScUnoHelpFunctions::GetEnumFromAny( aValue );
1869 setFunction( eFunction );
1870 }
1871 else if ( aNameString.EqualsAscii( SC_UNONAME_SUBTOTALS ) )
1872 {
1873 Sequence< GeneralFunction > aSubtotals;
1874 if( aValue >>= aSubtotals )
1875 setSubtotals( aSubtotals );
1876 }
1877 else if ( aNameString.EqualsAscii( SC_UNONAME_ORIENT ) )
1878 {
1879 //! test for correct enum type?
1880 DataPilotFieldOrientation eOrient = (DataPilotFieldOrientation)
1881 ScUnoHelpFunctions::GetEnumFromAny( aValue );
1882 setOrientation( eOrient );
1883 }
1884 else if ( aNameString.EqualsAscii( SC_UNONAME_SELPAGE ) )
1885 {
1886 OUString sCurrentPage;
1887 if (aValue >>= sCurrentPage)
1888 setCurrentPage(sCurrentPage);
1889 }
1890 else if ( aNameString.EqualsAscii( SC_UNONAME_USESELPAGE ) )
1891 {
1892 setUseCurrentPage(cppu::any2bool(aValue));
1893 }
1894 else if ( aNameString.EqualsAscii( SC_UNONAME_HASAUTOSHOW ) )
1895 {
1896 if (!cppu::any2bool(aValue))
1897 setAutoShowInfo(NULL);
1898 }
1899 else if ( aNameString.EqualsAscii( SC_UNONAME_AUTOSHOW ) )
1900 {
1901 DataPilotFieldAutoShowInfo aInfo;
1902 if (aValue >>= aInfo)
1903 setAutoShowInfo(&aInfo);
1904 }
1905 else if ( aNameString.EqualsAscii( SC_UNONAME_HASLAYOUTINFO ) )
1906 {
1907 if (!cppu::any2bool(aValue))
1908 setLayoutInfo(NULL);
1909 }
1910 else if ( aNameString.EqualsAscii( SC_UNONAME_LAYOUTINFO ) )
1911 {
1912 DataPilotFieldLayoutInfo aInfo;
1913 if (aValue >>= aInfo)
1914 setLayoutInfo(&aInfo);
1915 }
1916 else if ( aNameString.EqualsAscii( SC_UNONAME_HASREFERENCE ) )
1917 {
1918 if (!cppu::any2bool(aValue))
1919 setReference(NULL);
1920 }
1921 else if ( aNameString.EqualsAscii( SC_UNONAME_REFERENCE ) )
1922 {
1923 DataPilotFieldReference aRef;
1924 if (aValue >>= aRef)
1925 setReference(&aRef);
1926 }
1927 else if ( aNameString.EqualsAscii( SC_UNONAME_HASSORTINFO ) )
1928 {
1929 if (!cppu::any2bool(aValue))
1930 setSortInfo(NULL);
1931 }
1932 else if ( aNameString.EqualsAscii( SC_UNONAME_SORTINFO ) )
1933 {
1934 DataPilotFieldSortInfo aInfo;
1935 if (aValue >>= aInfo)
1936 setSortInfo(&aInfo);
1937 }
1938 else if ( aNameString.EqualsAscii( SC_UNONAME_ISGROUP ) )
1939 {
1940 if (!cppu::any2bool(aValue))
1941 setGroupInfo(NULL);
1942 }
1943 else if ( aNameString.EqualsAscii( SC_UNONAME_GROUPINFO ) )
1944 {
1945 DataPilotFieldGroupInfo aInfo;
1946 if (aValue >>= aInfo)
1947 setGroupInfo(&aInfo);
1948 }
1949 else if ( aNameString.EqualsAscii( SC_UNONAME_SHOWEMPTY ) )
1950 {
1951 setShowEmpty(cppu::any2bool(aValue));
1952 }
1953 }
1954
getPropertyValue(const OUString & aPropertyName)1955 Any SAL_CALL ScDataPilotFieldObj::getPropertyValue( const OUString& aPropertyName )
1956 {
1957 ScUnoGuard aGuard;
1958 String aNameString(aPropertyName);
1959 Any aRet;
1960
1961 if ( aNameString.EqualsAscii( SC_UNONAME_FUNCTION ) )
1962 aRet <<= getFunction();
1963 else if ( aNameString.EqualsAscii( SC_UNONAME_SUBTOTALS ) )
1964 aRet <<= getSubtotals();
1965 else if ( aNameString.EqualsAscii( SC_UNONAME_ORIENT ) )
1966 aRet <<= getOrientation();
1967 else if ( aNameString.EqualsAscii( SC_UNONAME_SELPAGE ) )
1968 aRet <<= getCurrentPage();
1969 else if ( aNameString.EqualsAscii( SC_UNONAME_USESELPAGE ) )
1970 aRet <<= getUseCurrentPage();
1971 else if ( aNameString.EqualsAscii( SC_UNONAME_HASAUTOSHOW ) )
1972 aRet = ::cppu::bool2any(getAutoShowInfo() != NULL);
1973 else if ( aNameString.EqualsAscii( SC_UNONAME_AUTOSHOW ) )
1974 {
1975 const DataPilotFieldAutoShowInfo* pInfo = getAutoShowInfo();
1976 if (pInfo)
1977 aRet <<= DataPilotFieldAutoShowInfo(*pInfo);
1978 }
1979 else if ( aNameString.EqualsAscii( SC_UNONAME_HASLAYOUTINFO ) )
1980 aRet = ::cppu::bool2any(getLayoutInfo() != NULL);
1981 else if ( aNameString.EqualsAscii( SC_UNONAME_LAYOUTINFO ) )
1982 {
1983 const DataPilotFieldLayoutInfo* pInfo = getLayoutInfo();
1984 if (pInfo)
1985 aRet <<= DataPilotFieldLayoutInfo(*pInfo);
1986 }
1987 else if ( aNameString.EqualsAscii( SC_UNONAME_HASREFERENCE ) )
1988 aRet = ::cppu::bool2any(getReference() != NULL);
1989 else if ( aNameString.EqualsAscii( SC_UNONAME_REFERENCE ) )
1990 {
1991 const DataPilotFieldReference* pRef = getReference();
1992 if (pRef)
1993 aRet <<= DataPilotFieldReference(*pRef);
1994 }
1995 else if ( aNameString.EqualsAscii( SC_UNONAME_HASSORTINFO ) )
1996 aRet = ::cppu::bool2any(getSortInfo() != NULL);
1997 else if ( aNameString.EqualsAscii( SC_UNONAME_SORTINFO ) )
1998 {
1999 const DataPilotFieldSortInfo* pInfo = getSortInfo();
2000 if (pInfo)
2001 aRet <<= DataPilotFieldSortInfo(*pInfo);
2002 }
2003 else if ( aNameString.EqualsAscii( SC_UNONAME_ISGROUP ) )
2004 aRet = ::cppu::bool2any(hasGroupInfo());
2005 else if ( aNameString.EqualsAscii( SC_UNONAME_GROUPINFO ) )
2006 {
2007 aRet <<= getGroupInfo();
2008 }
2009 else if ( aNameString.EqualsAscii( SC_UNONAME_SHOWEMPTY ) )
2010 aRet <<= getShowEmpty();
2011
2012 return aRet;
2013 }
2014
2015 // XDatePilotField
2016
getItems()2017 Reference<XIndexAccess> SAL_CALL ScDataPilotFieldObj::getItems()
2018 {
2019 ScUnoGuard aGuard;
2020 if (!mxItems.is())
2021 mxItems.set( new ScDataPilotItemsObj( mrParent, maFieldId ) );
2022 return mxItems;
2023 }
2024
SC_IMPL_DUMMY_PROPERTY_LISTENER(ScDataPilotFieldObj)2025 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDataPilotFieldObj )
2026
2027 DataPilotFieldOrientation ScDataPilotFieldObj::getOrientation() const
2028 {
2029 ScUnoGuard aGuard;
2030 ScDPSaveDimension* pDim = GetDPDimension();
2031 return pDim ? static_cast< DataPilotFieldOrientation >( pDim->GetOrientation() ) : DataPilotFieldOrientation_HIDDEN;
2032 }
2033
setOrientation(DataPilotFieldOrientation eNew)2034 void ScDataPilotFieldObj::setOrientation(DataPilotFieldOrientation eNew)
2035 {
2036 ScUnoGuard aGuard;
2037 if (maOrient.hasValue() && (eNew == maOrient.get< DataPilotFieldOrientation >()))
2038 return;
2039
2040 ScDPObject* pDPObj = 0;
2041 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2042 {
2043 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2044
2045 /* If the field was taken from getDataPilotFields(), don't reset the
2046 orientation for an existing use, but create a duplicated field
2047 instead (for "Data" orientation only). */
2048 if ( !maOrient.hasValue() && !maFieldId.mbDataLayout &&
2049 (pDim->GetOrientation() != DataPilotFieldOrientation_HIDDEN) &&
2050 (eNew == DataPilotFieldOrientation_DATA) )
2051 {
2052
2053 ScDPSaveDimension* pNewDim = 0;
2054
2055 // look for existing duplicate with orientation "hidden"
2056
2057 String aNameStr( maFieldId.maFieldName );
2058 const List& rDimensions = pSaveData->GetDimensions();
2059 sal_Int32 nDimCount = rDimensions.Count();
2060 sal_Int32 nFound = 0;
2061 for ( sal_Int32 nDim = 0; nDim < nDimCount && !pNewDim; nDim++ )
2062 {
2063 ScDPSaveDimension* pOneDim = static_cast<ScDPSaveDimension*>(rDimensions.GetObject(nDim));
2064 if ( !pOneDim->IsDataLayout() && (pOneDim->GetName() == aNameStr) )
2065 {
2066 if ( pOneDim->GetOrientation() == DataPilotFieldOrientation_HIDDEN )
2067 pNewDim = pOneDim; // use this one
2068 else
2069 ++nFound; // count existing non-hidden occurrences
2070 }
2071 }
2072
2073 if ( !pNewDim ) // if none found, create a new duplicated dimension
2074 pNewDim = &pSaveData->DuplicateDimension( *pDim );
2075
2076 maFieldId.mnFieldIdx = nFound; // keep accessing the new one
2077 pDim = pNewDim;
2078 }
2079
2080 pDim->SetOrientation(sal::static_int_cast<sal_uInt16>(eNew));
2081
2082 // move changed field behind all other fields (make it the last field in dimension)
2083 pSaveData->SetPosition( pDim, pSaveData->GetDimensions().Count() );
2084
2085 SetDPObject( pDPObj );
2086
2087 maOrient <<= eNew; // modifying the same object's orientation again doesn't create another duplicate
2088 }
2089 }
2090
getFunction() const2091 GeneralFunction ScDataPilotFieldObj::getFunction() const
2092 {
2093 ScUnoGuard aGuard;
2094 GeneralFunction eRet = GeneralFunction_NONE;
2095 if( ScDPSaveDimension* pDim = GetDPDimension() )
2096 {
2097 if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA )
2098 {
2099 // for non-data fields, property Function is the subtotals
2100 long nSubCount = pDim->GetSubTotalsCount();
2101 if ( nSubCount > 0 )
2102 eRet = (GeneralFunction)pDim->GetSubTotalFunc(0); // always use the first one
2103 // else keep NONE
2104 }
2105 else
2106 eRet = (GeneralFunction)pDim->GetFunction();
2107 }
2108 return eRet;
2109 }
2110
setFunction(GeneralFunction eNewFunc)2111 void ScDataPilotFieldObj::setFunction(GeneralFunction eNewFunc)
2112 {
2113 ScUnoGuard aGuard;
2114 ScDPObject* pDPObj = 0;
2115 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2116 {
2117 if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA )
2118 {
2119 // for non-data fields, property Function is the subtotals
2120 if ( eNewFunc == GeneralFunction_NONE )
2121 pDim->SetSubTotals( 0, NULL );
2122 else
2123 {
2124 sal_uInt16 nFunc = sal::static_int_cast<sal_uInt16>( eNewFunc );
2125 pDim->SetSubTotals( 1, &nFunc );
2126 }
2127 }
2128 else
2129 pDim->SetFunction( sal::static_int_cast<sal_uInt16>( eNewFunc ) );
2130 SetDPObject( pDPObj );
2131 }
2132 }
2133
getSubtotals() const2134 Sequence< GeneralFunction > ScDataPilotFieldObj::getSubtotals() const
2135 {
2136 ScUnoGuard aGuard;
2137 Sequence< GeneralFunction > aRet;
2138 if( ScDPSaveDimension* pDim = GetDPDimension() )
2139 {
2140 if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA )
2141 {
2142 // for non-data fields, property Functions is the sequence of subtotals
2143 sal_Int32 nCount = static_cast< sal_Int32 >( pDim->GetSubTotalsCount() );
2144 if ( nCount > 0 )
2145 {
2146 aRet.realloc( nCount );
2147 for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
2148 aRet[ nIdx ] = (GeneralFunction)pDim->GetSubTotalFunc( nIdx );
2149 }
2150 }
2151 }
2152 return aRet;
2153 }
2154
setSubtotals(const Sequence<GeneralFunction> & rSubtotals)2155 void ScDataPilotFieldObj::setSubtotals( const Sequence< GeneralFunction >& rSubtotals )
2156 {
2157 ScUnoGuard aGuard;
2158 ScDPObject* pDPObj = 0;
2159 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2160 {
2161 if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA )
2162 {
2163 sal_Int32 nCount = rSubtotals.getLength();
2164 if( nCount == 1 )
2165 {
2166 // count 1: all values are allowed (including NONE and AUTO)
2167 if( rSubtotals[ 0 ] == GeneralFunction_NONE )
2168 pDim->SetSubTotals( 0, NULL );
2169 else
2170 {
2171 sal_uInt16 nFunc = sal::static_int_cast<sal_uInt16>( rSubtotals[ 0 ] );
2172 pDim->SetSubTotals( 1, &nFunc );
2173 }
2174 }
2175 else if( nCount > 1 )
2176 {
2177 // set multiple functions, ignore NONE and AUTO in this case
2178 ::std::vector< sal_uInt16 > aSubt;
2179 for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
2180 {
2181 GeneralFunction eFunc = rSubtotals[ nIdx ];
2182 if( (eFunc != GeneralFunction_NONE) && (eFunc != GeneralFunction_AUTO) )
2183 {
2184 // do not insert functions twice
2185 sal_uInt16 nFunc = static_cast< sal_uInt16 >( eFunc );
2186 if( ::std::find( aSubt.begin(), aSubt.end(), nFunc ) == aSubt.end() )
2187 aSubt.push_back( nFunc );
2188 }
2189 }
2190 // set values from vector to ScDPSaveDimension
2191 if ( aSubt.empty() )
2192 pDim->SetSubTotals( 0, NULL );
2193 else
2194 pDim->SetSubTotals( static_cast< long >( aSubt.size() ), &aSubt.front() );
2195 }
2196 }
2197 SetDPObject( pDPObj );
2198 }
2199 }
2200
getCurrentPage() const2201 OUString ScDataPilotFieldObj::getCurrentPage() const
2202 {
2203 ScUnoGuard aGuard;
2204 ScDPSaveDimension* pDim = GetDPDimension();
2205 if( pDim && pDim->HasCurrentPage() )
2206 return pDim->GetCurrentPage();
2207 return OUString();
2208 }
2209
setCurrentPage(const OUString & rPage)2210 void ScDataPilotFieldObj::setCurrentPage( const OUString& rPage )
2211 {
2212 ScUnoGuard aGuard;
2213 ScDPObject* pDPObj = 0;
2214 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2215 {
2216 String aPage( rPage );
2217 pDim->SetCurrentPage( &aPage );
2218 SetDPObject( pDPObj );
2219 }
2220 }
2221
getUseCurrentPage() const2222 sal_Bool ScDataPilotFieldObj::getUseCurrentPage() const
2223 {
2224 ScUnoGuard aGuard;
2225 ScDPSaveDimension* pDim = GetDPDimension();
2226 return pDim && pDim->HasCurrentPage();
2227 }
2228
setUseCurrentPage(sal_Bool bUse)2229 void ScDataPilotFieldObj::setUseCurrentPage( sal_Bool bUse )
2230 {
2231 ScUnoGuard aGuard;
2232 ScDPObject* pDPObj = 0;
2233 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2234 {
2235 if( bUse )
2236 {
2237 /* It is somehow useless to set the property "HasSelectedPage" to
2238 true, because it is still needed to set an explicit page name. */
2239 if( !pDim->HasCurrentPage() )
2240 {
2241 String aPage;
2242 pDim->SetCurrentPage( &aPage );
2243 }
2244 }
2245 else
2246 pDim->SetCurrentPage( 0 );
2247 SetDPObject( pDPObj );
2248 }
2249 }
2250
getAutoShowInfo()2251 const DataPilotFieldAutoShowInfo* ScDataPilotFieldObj::getAutoShowInfo()
2252 {
2253 ScUnoGuard aGuard;
2254 ScDPSaveDimension* pDim = GetDPDimension();
2255 return pDim ? pDim->GetAutoShowInfo() : 0;
2256 }
2257
setAutoShowInfo(const DataPilotFieldAutoShowInfo * pInfo)2258 void ScDataPilotFieldObj::setAutoShowInfo( const DataPilotFieldAutoShowInfo* pInfo )
2259 {
2260 ScUnoGuard aGuard;
2261 ScDPObject* pDPObj = 0;
2262 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2263 {
2264 pDim->SetAutoShowInfo( pInfo );
2265 SetDPObject( pDPObj );
2266 }
2267 }
2268
getLayoutInfo()2269 const DataPilotFieldLayoutInfo* ScDataPilotFieldObj::getLayoutInfo()
2270 {
2271 ScUnoGuard aGuard;
2272 ScDPSaveDimension* pDim = GetDPDimension();
2273 return pDim ? pDim->GetLayoutInfo() : 0;
2274 }
2275
setLayoutInfo(const DataPilotFieldLayoutInfo * pInfo)2276 void ScDataPilotFieldObj::setLayoutInfo( const DataPilotFieldLayoutInfo* pInfo )
2277 {
2278 ScUnoGuard aGuard;
2279 ScDPObject* pDPObj = 0;
2280 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2281 {
2282 pDim->SetLayoutInfo( pInfo );
2283 SetDPObject( pDPObj );
2284 }
2285 }
2286
getReference()2287 const DataPilotFieldReference* ScDataPilotFieldObj::getReference()
2288 {
2289 ScUnoGuard aGuard;
2290 ScDPSaveDimension* pDim = GetDPDimension();
2291 return pDim ? pDim->GetReferenceValue() : 0;
2292 }
2293
setReference(const DataPilotFieldReference * pInfo)2294 void ScDataPilotFieldObj::setReference( const DataPilotFieldReference* pInfo )
2295 {
2296 ScUnoGuard aGuard;
2297 ScDPObject* pDPObj = 0;
2298 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2299 {
2300 pDim->SetReferenceValue( pInfo );
2301 SetDPObject( pDPObj );
2302 }
2303 }
2304
getSortInfo()2305 const DataPilotFieldSortInfo* ScDataPilotFieldObj::getSortInfo()
2306 {
2307 ScUnoGuard aGuard;
2308 ScDPSaveDimension* pDim = GetDPDimension();
2309 return pDim ? pDim->GetSortInfo() : 0;
2310 }
2311
setSortInfo(const DataPilotFieldSortInfo * pInfo)2312 void ScDataPilotFieldObj::setSortInfo( const DataPilotFieldSortInfo* pInfo )
2313 {
2314 ScUnoGuard aGuard;
2315 ScDPObject* pDPObj = 0;
2316 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2317 {
2318 pDim->SetSortInfo( pInfo );
2319 SetDPObject( pDPObj );
2320 }
2321 }
2322
getShowEmpty() const2323 sal_Bool ScDataPilotFieldObj::getShowEmpty() const
2324 {
2325 ScUnoGuard aGuard;
2326 ScDPSaveDimension* pDim = GetDPDimension();
2327 return pDim && pDim->GetShowEmpty();
2328 }
2329
setShowEmpty(sal_Bool bShow)2330 void ScDataPilotFieldObj::setShowEmpty( sal_Bool bShow )
2331 {
2332 ScUnoGuard aGuard;
2333 ScDPObject* pDPObj = 0;
2334 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2335 {
2336 pDim->SetShowEmpty( bShow );
2337 SetDPObject( pDPObj );
2338 }
2339 }
2340
hasGroupInfo()2341 sal_Bool ScDataPilotFieldObj::hasGroupInfo()
2342 {
2343 ScUnoGuard aGuard;
2344 ScDPObject* pDPObj = 0;
2345 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2346 if( const ScDPDimensionSaveData* pDimData = pDPObj->GetSaveData()->GetExistingDimensionData() )
2347 return pDimData->GetNamedGroupDim( pDim->GetName() ) || pDimData->GetNumGroupDim( pDim->GetName() );
2348 return sal_False;
2349 }
2350
getGroupInfo()2351 DataPilotFieldGroupInfo ScDataPilotFieldObj::getGroupInfo()
2352 {
2353 ScUnoGuard aGuard;
2354 DataPilotFieldGroupInfo aInfo;
2355 ScDPObject* pDPObj = 0;
2356 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2357 {
2358 if( const ScDPDimensionSaveData* pDimData = pDPObj->GetSaveData()->GetExistingDimensionData() )
2359 {
2360 if( const ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDim( pDim->GetName() ) )
2361 {
2362 // grouped by ...
2363 aInfo.GroupBy = pGroupDim->GetDatePart();
2364
2365 // find source field
2366 try
2367 {
2368 Reference< XNameAccess > xFields( mrParent.getDataPilotFields(), UNO_QUERY_THROW );
2369 aInfo.SourceField.set( xFields->getByName( pGroupDim->GetSourceDimName() ), UNO_QUERY );
2370 }
2371 catch( Exception& )
2372 {
2373 }
2374
2375 ScDataPilotConversion::FillGroupInfo( aInfo, pGroupDim->GetDateInfo() );
2376 if( pGroupDim->GetDatePart() == 0 )
2377 {
2378 // fill vector of group and group member information
2379 ScFieldGroups aGroups;
2380 for( sal_Int32 nIdx = 0, nCount = pGroupDim->GetGroupCount(); nIdx < nCount; ++nIdx )
2381 {
2382 if( const ScDPSaveGroupItem* pGroup = pGroupDim->GetGroupByIndex( nIdx ) )
2383 {
2384 ScFieldGroup aGroup;
2385 aGroup.maName = pGroup->GetGroupName();
2386 for( sal_Int32 nMemIdx = 0, nMemCount = pGroup->GetElementCount(); nMemIdx < nMemCount; ++nMemIdx )
2387 if( const String* pMem = pGroup->GetElementByIndex( nMemIdx ) )
2388 aGroup.maMembers.push_back( *pMem );
2389 aGroups.push_back( aGroup );
2390 }
2391 }
2392 aInfo.Groups = new ScDataPilotFieldGroupsObj( aGroups );
2393 }
2394 }
2395 else if( const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( pDim->GetName() ) )
2396 {
2397 if (pNumGroupDim->GetDatePart())
2398 {
2399 ScDataPilotConversion::FillGroupInfo( aInfo, pNumGroupDim->GetDateInfo() );
2400 aInfo.GroupBy = pNumGroupDim->GetDatePart();
2401 }
2402 else
2403 {
2404 ScDataPilotConversion::FillGroupInfo( aInfo, pNumGroupDim->GetInfo() );
2405 }
2406 }
2407 }
2408 }
2409 return aInfo;
2410 }
2411
setGroupInfo(const DataPilotFieldGroupInfo * pInfo)2412 void ScDataPilotFieldObj::setGroupInfo( const DataPilotFieldGroupInfo* pInfo )
2413 {
2414 ScUnoGuard aGuard;
2415 ScDPObject* pDPObj = 0;
2416 if( /*ScDPSaveDimension* pDim =*/ GetDPDimension( &pDPObj ) )
2417 {
2418 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2419 if( pInfo && lclCheckMinMaxStep( *pInfo ) )
2420 {
2421 ScDPNumGroupInfo aInfo;
2422 aInfo.Enable = sal_True;
2423 aInfo.DateValues = pInfo->HasDateValues;
2424 aInfo.AutoStart = pInfo->HasAutoStart;
2425 aInfo.AutoEnd = pInfo->HasAutoEnd;
2426 aInfo.Start = pInfo->Start;
2427 aInfo.End = pInfo->End;
2428 aInfo.Step = pInfo->Step;
2429 Reference< XNamed > xNamed( pInfo->SourceField, UNO_QUERY );
2430 if( xNamed.is() )
2431 {
2432 ScDPSaveGroupDimension aGroupDim( xNamed->getName(), getName() );
2433 if( pInfo->GroupBy )
2434 aGroupDim.SetDateInfo(aInfo, pInfo->GroupBy);
2435 else
2436 {
2437 Reference<XIndexAccess> xIndex(pInfo->Groups, UNO_QUERY);
2438 if (xIndex.is())
2439 {
2440 sal_Int32 nCount(xIndex->getCount());
2441 for(sal_Int32 i = 0; i < nCount; i++)
2442 {
2443 Reference<XNamed> xGroupNamed(xIndex->getByIndex(i), UNO_QUERY);
2444 if (xGroupNamed.is())
2445 {
2446 ScDPSaveGroupItem aItem(xGroupNamed->getName());
2447 Reference<XIndexAccess> xGroupIndex(xGroupNamed, UNO_QUERY);
2448 if (xGroupIndex.is())
2449 {
2450 sal_Int32 nItemCount(xGroupIndex->getCount());
2451 for (sal_Int32 j = 0; j < nItemCount; ++j)
2452 {
2453 Reference<XNamed> xItemNamed(xGroupIndex->getByIndex(j), UNO_QUERY);
2454 if (xItemNamed.is())
2455 aItem.AddElement(xItemNamed->getName());
2456 }
2457 }
2458 aGroupDim.AddGroupItem(aItem);
2459 }
2460 }
2461 }
2462 }
2463
2464 // get dimension savedata or create new if none
2465 ScDPDimensionSaveData& rDimSaveData = *pSaveData->GetDimensionData();
2466 rDimSaveData.ReplaceGroupDimension( aGroupDim );
2467 }
2468 else // no source field in group info -> numeric group
2469 {
2470 ScDPDimensionSaveData* pDimData = pSaveData->GetDimensionData(); // created if not there
2471
2472 ScDPSaveNumGroupDimension* pExisting = pDimData->GetNumGroupDimAcc( getName() );
2473 if ( pExisting )
2474 {
2475 if (pInfo->GroupBy)
2476 pExisting->SetDateInfo(aInfo, pInfo->GroupBy);
2477 // modify existing group dimension
2478 pExisting->SetGroupInfo( aInfo );
2479 }
2480 else if (pInfo->GroupBy)
2481 {
2482 // create new group dimension
2483 ScDPSaveNumGroupDimension aNumGroupDim( getName(), aInfo, pInfo->GroupBy );
2484 pDimData->AddNumGroupDimension( aNumGroupDim );
2485 }
2486 else
2487 {
2488 // create new group dimension
2489 ScDPSaveNumGroupDimension aNumGroupDim( getName(), aInfo );
2490 pDimData->AddNumGroupDimension( aNumGroupDim );
2491 }
2492 }
2493 }
2494 else // null passed as argument
2495 {
2496 pSaveData->SetDimensionData( 0 );
2497 }
2498
2499 pDPObj->SetSaveData( *pSaveData );
2500 SetDPObject( pDPObj );
2501 }
2502 }
2503
HasString(const Sequence<OUString> & rItems,const OUString & aString)2504 sal_Bool ScDataPilotFieldObj::HasString(const Sequence< OUString >& rItems, const OUString& aString)
2505 {
2506 sal_Bool bRet = sal_False;
2507
2508 sal_Int32 nCount(rItems.getLength());
2509 sal_Int32 nItem(0);
2510 while (nItem < nCount && !bRet)
2511 {
2512 bRet = rItems[nItem] == aString;
2513 ++nItem;
2514 }
2515
2516 return bRet;
2517 }
2518
2519 // XDataPilotFieldGrouping
createNameGroup(const Sequence<OUString> & rItems)2520 Reference< XDataPilotField > SAL_CALL ScDataPilotFieldObj::createNameGroup( const Sequence< OUString >& rItems )
2521 {
2522 ScUnoGuard aGuard;
2523
2524 Reference< XDataPilotField > xRet;
2525 OUString sNewDim;
2526
2527 if( !rItems.hasElements() )
2528 throw IllegalArgumentException();
2529
2530 ScDPObject* pDPObj = 0;
2531 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2532 {
2533 String aDimName = pDim->GetName();
2534
2535 ScDPSaveData aSaveData = *pDPObj->GetSaveData();
2536 ScDPDimensionSaveData* pDimData = aSaveData.GetDimensionData(); // created if not there
2537
2538 // find original base
2539 String aBaseDimName( aDimName );
2540 const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName );
2541 if ( pBaseGroupDim )
2542 {
2543 // any entry's SourceDimName is the original base
2544 aBaseDimName = pBaseGroupDim->GetSourceDimName();
2545 }
2546
2547 // find existing group dimension
2548 // (using the selected dim, can be intermediate group dim)
2549 ScDPSaveGroupDimension* pGroupDimension = pDimData->GetGroupDimAccForBase( aDimName );
2550
2551 // remove the selected items from their groups
2552 // (empty groups are removed, too)
2553 sal_Int32 nEntryCount = rItems.getLength();
2554 sal_Int32 nEntry;
2555 if ( pGroupDimension )
2556 {
2557 for (nEntry=0; nEntry<nEntryCount; nEntry++)
2558 {
2559 String aEntryName(rItems[nEntry]);
2560 if ( pBaseGroupDim )
2561 {
2562 // for each selected (intermediate) group, remove all its items
2563 // (same logic as for adding, below)
2564 const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName );
2565 if ( pBaseGroup )
2566 pBaseGroup->RemoveElementsFromGroups( *pGroupDimension ); // remove all elements
2567 else
2568 pGroupDimension->RemoveFromGroups( aEntryName );
2569 }
2570 else
2571 pGroupDimension->RemoveFromGroups( aEntryName );
2572 }
2573 }
2574
2575 ScDPSaveGroupDimension* pNewGroupDim = 0;
2576 if ( !pGroupDimension )
2577 {
2578 // create a new group dimension
2579 String aGroupDimName = pDimData->CreateGroupDimName( aBaseDimName, *pDPObj, false, NULL );
2580 pNewGroupDim = new ScDPSaveGroupDimension( aBaseDimName, aGroupDimName );
2581 sNewDim = aGroupDimName;
2582
2583 pGroupDimension = pNewGroupDim; // make changes to the new dim if none existed
2584
2585 if ( pBaseGroupDim )
2586 {
2587 // If it's a higher-order group dimension, pre-allocate groups for all
2588 // non-selected original groups, so the individual base members aren't
2589 // used for automatic groups (this would make the original groups hard
2590 // to find).
2591 //! Also do this when removing groups?
2592 //! Handle this case dynamically with automatic groups?
2593
2594 long nGroupCount = pBaseGroupDim->GetGroupCount();
2595 for ( long nGroup = 0; nGroup < nGroupCount; nGroup++ )
2596 {
2597 const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetGroupByIndex( nGroup );
2598
2599 StrData aStrData( pBaseGroup->GetGroupName() );
2600 if ( !HasString(rItems, aStrData.GetString()) ) //! ignore case?
2601 {
2602 // add an additional group for each item that is not in the selection
2603 ScDPSaveGroupItem aGroup( pBaseGroup->GetGroupName() );
2604 aGroup.AddElementsFromGroup( *pBaseGroup );
2605 pGroupDimension->AddGroupItem( aGroup );
2606 }
2607 }
2608 }
2609 }
2610 String aGroupDimName = pGroupDimension->GetGroupDimName();
2611
2612 //! localized prefix string
2613 String aGroupName = pGroupDimension->CreateGroupName( String( RTL_CONSTASCII_USTRINGPARAM( "Group" ) ) );
2614 ScDPSaveGroupItem aGroup( aGroupName );
2615 Reference< XNameAccess > xMembers = GetMembers();
2616 if (!xMembers.is())
2617 {
2618 delete pNewGroupDim;
2619 throw RuntimeException();
2620 }
2621
2622 for (nEntry=0; nEntry<nEntryCount; nEntry++)
2623 {
2624 String aEntryName(rItems[nEntry]);
2625
2626 if (!xMembers->hasByName(aEntryName))
2627 {
2628 delete pNewGroupDim;
2629 throw IllegalArgumentException();
2630 }
2631
2632 if ( pBaseGroupDim )
2633 {
2634 // for each selected (intermediate) group, add all its items
2635 const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName );
2636 if ( pBaseGroup )
2637 aGroup.AddElementsFromGroup( *pBaseGroup );
2638 else
2639 aGroup.AddElement( aEntryName ); // no group found -> automatic group, add the item itself
2640 }
2641 else
2642 aGroup.AddElement( aEntryName ); // no group dimension, add all items directly
2643 }
2644
2645 pGroupDimension->AddGroupItem( aGroup );
2646
2647 if ( pNewGroupDim )
2648 {
2649 pDimData->AddGroupDimension( *pNewGroupDim );
2650 delete pNewGroupDim; // AddGroupDimension copies the object
2651 // don't access pGroupDimension after here
2652 }
2653 pGroupDimension = pNewGroupDim = NULL;
2654
2655 // set orientation
2656 ScDPSaveDimension* pSaveDimension = aSaveData.GetDimensionByName( aGroupDimName );
2657 if ( pSaveDimension->GetOrientation() == DataPilotFieldOrientation_HIDDEN )
2658 {
2659 ScDPSaveDimension* pOldDimension = aSaveData.GetDimensionByName( aDimName );
2660 pSaveDimension->SetOrientation( pOldDimension->GetOrientation() );
2661 long nPosition = 0; //! before (immediate) base
2662 aSaveData.SetPosition( pSaveDimension, nPosition );
2663 }
2664
2665 // apply changes
2666 pDPObj->SetSaveData( aSaveData );
2667 SetDPObject( pDPObj );
2668 }
2669
2670 // if new grouping field has been created (on first group), return it
2671 if( sNewDim.getLength() > 0 )
2672 {
2673 Reference< XNameAccess > xFields(mrParent.getDataPilotFields(), UNO_QUERY);
2674 if (xFields.is())
2675 {
2676 xRet.set(xFields->getByName(sNewDim), UNO_QUERY);
2677 DBG_ASSERT(xRet.is(), "there is a name, so there should be also a field");
2678 }
2679 }
2680 return xRet;
2681 }
2682
createDateGroup(const DataPilotFieldGroupInfo & rInfo)2683 Reference < XDataPilotField > SAL_CALL ScDataPilotFieldObj::createDateGroup( const DataPilotFieldGroupInfo& rInfo )
2684 {
2685 ScUnoGuard aGuard;
2686 using namespace ::com::sun::star::sheet::DataPilotFieldGroupBy;
2687
2688 // check min/max/step, HasDateValues must be set always
2689 if( !rInfo.HasDateValues || !lclCheckMinMaxStep( rInfo ) )
2690 throw IllegalArgumentException();
2691 // only a single date flag is allowed
2692 if( (rInfo.GroupBy == 0) || (rInfo.GroupBy > YEARS) || ((rInfo.GroupBy & (rInfo.GroupBy - 1)) != 0) )
2693 throw IllegalArgumentException();
2694 // step must be zero, if something else than DAYS is specified
2695 if( rInfo.Step >= ((rInfo.GroupBy == DAYS) ? 32768.0 : 1.0) )
2696 throw IllegalArgumentException();
2697
2698 String aGroupDimName;
2699 ScDPObject* pDPObj = 0;
2700 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
2701 {
2702 ScDPNumGroupInfo aInfo;
2703 aInfo.Enable = sal_True;
2704 aInfo.DateValues = (rInfo.GroupBy == DAYS) && (rInfo.Step >= 1.0);
2705 aInfo.AutoStart = rInfo.HasAutoStart;
2706 aInfo.AutoEnd = rInfo.HasAutoEnd;
2707 aInfo.Start = rInfo.Start;
2708 aInfo.End = rInfo.End;
2709 aInfo.Step = static_cast< sal_Int32 >( rInfo.Step );
2710
2711 // create a local copy of the entire save data (will be written back below)
2712 ScDPSaveData aSaveData = *pDPObj->GetSaveData();
2713 // get or create dimension save data
2714 ScDPDimensionSaveData& rDimData = *aSaveData.GetDimensionData();
2715
2716 // find source dimension name
2717 const String& rDimName = pDim->GetName();
2718 const ScDPSaveGroupDimension* pGroupDim = rDimData.GetNamedGroupDim( rDimName );
2719 String aSrcDimName = pGroupDim ? pGroupDim->GetSourceDimName() : rDimName;
2720
2721 // find a group dimension for the base field, or get numeric grouping
2722 pGroupDim = rDimData.GetFirstNamedGroupDim( aSrcDimName );
2723 const ScDPSaveNumGroupDimension* pNumGroupDim = rDimData.GetNumGroupDim( aSrcDimName );
2724
2725 // do not group by dates, if named groups or numeric grouping is present
2726 bool bHasNamedGrouping = pGroupDim && !pGroupDim->GetDateInfo().Enable;
2727 bool bHasNumGrouping = pNumGroupDim && pNumGroupDim->GetInfo().Enable && !pNumGroupDim->GetInfo().DateValues && !pNumGroupDim->GetDateInfo().Enable;
2728 if( bHasNamedGrouping || bHasNumGrouping )
2729 throw IllegalArgumentException();
2730
2731 if( aInfo.DateValues ) // create day ranges grouping
2732 {
2733 // first remove all named group dimensions
2734 while( pGroupDim )
2735 {
2736 String aGroupDimName2 = pGroupDim->GetGroupDimName();
2737 // find next group dimension before deleting this group
2738 pGroupDim = rDimData.GetNextNamedGroupDim( aGroupDimName2 );
2739 // remove from dimension save data
2740 rDimData.RemoveGroupDimension( aGroupDimName2 );
2741 // also remove save data settings for the dimension that no longer exists
2742 aSaveData.RemoveDimensionByName( aGroupDimName2 );
2743 }
2744 // create or replace the number grouping dimension
2745 ScDPSaveNumGroupDimension aNumGroupDim( aSrcDimName, aInfo );
2746 rDimData.ReplaceNumGroupDimension( aNumGroupDim );
2747 }
2748 else // create date grouping
2749 {
2750 // collect all existing date flags
2751 sal_Int32 nDateParts = rDimData.CollectDateParts( aSrcDimName );
2752 if( nDateParts == 0 )
2753 {
2754 // insert numeric group dimension, if no date groups exist yet (or replace day range grouping)
2755 ScDPSaveNumGroupDimension aNumGroupDim( aSrcDimName, aInfo, rInfo.GroupBy );
2756 rDimData.ReplaceNumGroupDimension( aNumGroupDim );
2757 }
2758 else if( (nDateParts & rInfo.GroupBy) == 0 ) // do nothing if date field exists already
2759 {
2760 // create new named group dimension for additional date groups
2761 aGroupDimName = rDimData.CreateDateGroupDimName( rInfo.GroupBy, *pDPObj, true, 0 );
2762 ScDPSaveGroupDimension aGroupDim( aSrcDimName, aGroupDimName, aInfo, rInfo.GroupBy );
2763 rDimData.AddGroupDimension( aGroupDim );
2764
2765 // set orientation of new named group dimension
2766 ScDPSaveDimension& rSaveDim = *aSaveData.GetDimensionByName( aGroupDimName );
2767 if( rSaveDim.GetOrientation() == DataPilotFieldOrientation_HIDDEN )
2768 {
2769 ScDPSaveDimension& rOldDim = *aSaveData.GetDimensionByName( aSrcDimName );
2770 rSaveDim.SetOrientation( rOldDim.GetOrientation() );
2771 aSaveData.SetPosition( &rSaveDim, 0 ); //! before (immediate) base
2772 }
2773 }
2774 }
2775
2776 // apply changes
2777 pDPObj->SetSaveData( aSaveData );
2778 SetDPObject( pDPObj );
2779 }
2780
2781 // return the UNO object of the new dimension, after writing back saved data
2782 Reference< XDataPilotField > xRet;
2783 if( aGroupDimName.Len() > 0 ) try
2784 {
2785 Reference< XNameAccess > xFields( mrParent.getDataPilotFields(), UNO_QUERY_THROW );
2786 xRet.set( xFields->getByName( aGroupDimName ), UNO_QUERY );
2787 }
2788 catch( Exception& )
2789 {
2790 }
2791 return xRet;
2792 }
2793
2794 // ============================================================================
2795
2796 namespace {
2797
lclExtractGroupMembers(ScFieldGroupMembers & rMembers,const Any & rElement)2798 bool lclExtractGroupMembers( ScFieldGroupMembers& rMembers, const Any& rElement )
2799 {
2800 // allow empty value to create a new group
2801 if( !rElement.hasValue() )
2802 return true;
2803
2804 // try to extract a simple sequence of strings
2805 Sequence< OUString > aSeq;
2806 if( rElement >>= aSeq )
2807 {
2808 if( aSeq.hasElements() )
2809 rMembers.insert( rMembers.end(), aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength() );
2810 return true;
2811 }
2812
2813 // try to use XIndexAccess providing objects that support XNamed
2814 Reference< XIndexAccess > xItemsIA( rElement, UNO_QUERY );
2815 if( xItemsIA.is() )
2816 {
2817 for( sal_Int32 nIdx = 0, nCount = xItemsIA->getCount(); nIdx < nCount; ++nIdx )
2818 {
2819 try // getByIndex() should not throw, but we cannot be sure
2820 {
2821 Reference< XNamed > xItemName( xItemsIA->getByIndex( nIdx ), UNO_QUERY_THROW );
2822 rMembers.push_back( xItemName->getName() );
2823 }
2824 catch( Exception& )
2825 {
2826 // ignore exceptions, go ahead with next element in the array
2827 }
2828 }
2829 return true;
2830 }
2831
2832 // nothing valid inside the Any -> return false
2833 return false;
2834 }
2835
2836 } // namespace
2837
2838 // ----------------------------------------------------------------------------
2839
ScDataPilotFieldGroupsObj(const ScFieldGroups & rGroups)2840 ScDataPilotFieldGroupsObj::ScDataPilotFieldGroupsObj( const ScFieldGroups& rGroups ) :
2841 maGroups( rGroups )
2842 {
2843 }
2844
~ScDataPilotFieldGroupsObj()2845 ScDataPilotFieldGroupsObj::~ScDataPilotFieldGroupsObj()
2846 {
2847 }
2848
2849 // XNameAccess
2850
getByName(const OUString & rName)2851 Any SAL_CALL ScDataPilotFieldGroupsObj::getByName( const OUString& rName )
2852 {
2853 ScUnoGuard aGuard;
2854 if( implFindByName( rName ) == maGroups.end() )
2855 throw NoSuchElementException();
2856 return Any( Reference< XNameAccess >( new ScDataPilotFieldGroupObj( *this, rName ) ) );
2857 }
2858
getElementNames()2859 Sequence< OUString > SAL_CALL ScDataPilotFieldGroupsObj::getElementNames()
2860 {
2861 ScUnoGuard aGuard;
2862 Sequence< OUString > aSeq;
2863 if( !maGroups.empty() )
2864 {
2865 aSeq.realloc( static_cast< sal_Int32 >( maGroups.size() ) );
2866 OUString* pName = aSeq.getArray();
2867 for( ScFieldGroups::iterator aIt = maGroups.begin(), aEnd = maGroups.end(); aIt != aEnd; ++aIt, ++pName )
2868 *pName = aIt->maName;
2869 }
2870 return aSeq;
2871 }
2872
hasByName(const OUString & rName)2873 sal_Bool SAL_CALL ScDataPilotFieldGroupsObj::hasByName( const OUString& rName )
2874 {
2875 ScUnoGuard aGuard;
2876 return implFindByName( rName ) != maGroups.end();
2877 }
2878
2879 // XNameReplace
2880
replaceByName(const OUString & rName,const Any & rElement)2881 void SAL_CALL ScDataPilotFieldGroupsObj::replaceByName( const OUString& rName, const Any& rElement )
2882 {
2883 ScUnoGuard aGuard;
2884
2885 if( rName.getLength() == 0 )
2886 throw IllegalArgumentException();
2887
2888 ScFieldGroups::iterator aIt = implFindByName( rName );
2889 if( aIt == maGroups.end() )
2890 throw NoSuchElementException();
2891
2892 // read all item names provided by the passed object
2893 ScFieldGroupMembers aMembers;
2894 if( !lclExtractGroupMembers( aMembers, rElement ) )
2895 throw IllegalArgumentException();
2896
2897 // copy and forget, faster than vector assignment
2898 aIt->maMembers.swap( aMembers );
2899 }
2900
2901 // XNameContainer
2902
insertByName(const OUString & rName,const Any & rElement)2903 void SAL_CALL ScDataPilotFieldGroupsObj::insertByName( const OUString& rName, const Any& rElement )
2904 {
2905 ScUnoGuard aGuard;
2906
2907 if( rName.getLength() == 0 )
2908 throw IllegalArgumentException();
2909
2910 ScFieldGroups::iterator aIt = implFindByName( rName );
2911 if( aIt != maGroups.end() )
2912 throw ElementExistException();
2913
2914 // read all item names provided by the passed object
2915 ScFieldGroupMembers aMembers;
2916 if( !lclExtractGroupMembers( aMembers, rElement ) )
2917 throw IllegalArgumentException();
2918
2919 // create the new entry if no error has been occurred
2920 maGroups.resize( maGroups.size() + 1 );
2921 ScFieldGroup& rGroup = maGroups.back();
2922 rGroup.maName = rName;
2923 rGroup.maMembers.swap( aMembers );
2924 }
2925
removeByName(const OUString & rName)2926 void SAL_CALL ScDataPilotFieldGroupsObj::removeByName( const OUString& rName )
2927 {
2928 ScUnoGuard aGuard;
2929
2930 if( rName.getLength() == 0 )
2931 throw IllegalArgumentException();
2932
2933 ScFieldGroups::iterator aIt = implFindByName( rName );
2934 if( aIt == maGroups.end() )
2935 throw NoSuchElementException();
2936
2937 maGroups.erase( aIt );
2938 }
2939
2940 // XIndexAccess
2941
getCount()2942 sal_Int32 SAL_CALL ScDataPilotFieldGroupsObj::getCount()
2943 {
2944 ScUnoGuard aGuard;
2945 return static_cast< sal_Int32 >( maGroups.size() );
2946 }
2947
getByIndex(sal_Int32 nIndex)2948 Any SAL_CALL ScDataPilotFieldGroupsObj::getByIndex( sal_Int32 nIndex )
2949 {
2950 ScUnoGuard aGuard;
2951 if ((nIndex < 0) || (nIndex >= static_cast< sal_Int32 >( maGroups.size() )))
2952 throw IndexOutOfBoundsException();
2953 return Any( Reference< XNameAccess >( new ScDataPilotFieldGroupObj( *this, maGroups[ nIndex ].maName ) ) );
2954 }
2955
2956 // XEnumerationAccess
2957
createEnumeration()2958 Reference<XEnumeration> SAL_CALL ScDataPilotFieldGroupsObj::createEnumeration()
2959 {
2960 ScUnoGuard aGuard;
2961 return new ScIndexEnumeration( this, OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.DataPilotFieldGroupsEnumeration" ) ) );
2962 }
2963
2964 // XElementAccess
2965
getElementType()2966 uno::Type SAL_CALL ScDataPilotFieldGroupsObj::getElementType()
2967 {
2968 ScUnoGuard aGuard;
2969 return getCppuType( (Reference< XNameAccess >*)0 );
2970 }
2971
hasElements()2972 sal_Bool SAL_CALL ScDataPilotFieldGroupsObj::hasElements()
2973 {
2974 ScUnoGuard aGuard;
2975 return !maGroups.empty();
2976 }
2977
2978 // implementation
2979
getFieldGroup(const OUString & rName)2980 ScFieldGroup& ScDataPilotFieldGroupsObj::getFieldGroup( const OUString& rName )
2981 {
2982 ScUnoGuard aGuard;
2983 ScFieldGroups::iterator aIt = implFindByName( rName );
2984 if( aIt == maGroups.end() )
2985 throw RuntimeException();
2986 return *aIt;
2987 }
2988
renameFieldGroup(const OUString & rOldName,const OUString & rNewName)2989 void ScDataPilotFieldGroupsObj::renameFieldGroup( const OUString& rOldName, const OUString& rNewName )
2990 {
2991 ScUnoGuard aGuard;
2992 ScFieldGroups::iterator aOldIt = implFindByName( rOldName );
2993 ScFieldGroups::iterator aNewIt = implFindByName( rNewName );
2994 // new name must not exist yet
2995 if( (aOldIt == maGroups.end()) || ((aNewIt != maGroups.end()) && (aNewIt != aOldIt)) )
2996 throw RuntimeException();
2997 aOldIt->maName = rNewName;
2998 }
2999
3000 // private
3001
implFindByName(const OUString & rName)3002 ScFieldGroups::iterator ScDataPilotFieldGroupsObj::implFindByName( const OUString& rName )
3003 {
3004 for( ScFieldGroups::iterator aIt = maGroups.begin(), aEnd = maGroups.end(); aIt != aEnd; ++aIt )
3005 if( aIt->maName == rName )
3006 return aIt;
3007 return maGroups.end();
3008 }
3009
3010 // ============================================================================
3011
3012 namespace {
3013
lclExtractMember(const Any & rElement)3014 OUString lclExtractMember( const Any& rElement )
3015 {
3016 if( rElement.has< OUString >() )
3017 return rElement.get< OUString >();
3018
3019 Reference< XNamed > xNamed( rElement, UNO_QUERY );
3020 if( xNamed.is() )
3021 return xNamed->getName();
3022
3023 return OUString();
3024 }
3025
3026 } // namespace
3027
3028 // ----------------------------------------------------------------------------
3029
ScDataPilotFieldGroupObj(ScDataPilotFieldGroupsObj & rParent,const OUString & rGroupName)3030 ScDataPilotFieldGroupObj::ScDataPilotFieldGroupObj( ScDataPilotFieldGroupsObj& rParent, const OUString& rGroupName ) :
3031 mrParent( rParent ),
3032 maGroupName( rGroupName )
3033 {
3034 mrParent.acquire();
3035 }
3036
~ScDataPilotFieldGroupObj()3037 ScDataPilotFieldGroupObj::~ScDataPilotFieldGroupObj()
3038 {
3039 mrParent.release();
3040 }
3041
3042 // XNameAccess
3043
getByName(const OUString & rName)3044 Any SAL_CALL ScDataPilotFieldGroupObj::getByName( const OUString& rName )
3045 {
3046 ScUnoGuard aGuard;
3047 ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3048 ScFieldGroupMembers::iterator aIt = ::std::find( rMembers.begin(), rMembers.end(), rName );
3049 if( aIt == rMembers.end() )
3050 throw NoSuchElementException();
3051 return Any( Reference< XNamed >( new ScDataPilotFieldGroupItemObj( *this, *aIt ) ) );
3052 }
3053
getElementNames()3054 Sequence< OUString > SAL_CALL ScDataPilotFieldGroupObj::getElementNames()
3055 {
3056 ScUnoGuard aGuard;
3057 return ::comphelper::containerToSequence( mrParent.getFieldGroup( maGroupName ).maMembers );
3058 }
3059
hasByName(const OUString & rName)3060 sal_Bool SAL_CALL ScDataPilotFieldGroupObj::hasByName( const OUString& rName )
3061 {
3062 ScUnoGuard aGuard;
3063 ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3064 return ::std::find( rMembers.begin(), rMembers.end(), rName ) != rMembers.end();
3065 }
3066
3067 // XNameReplace
3068
replaceByName(const OUString & rName,const Any & rElement)3069 void SAL_CALL ScDataPilotFieldGroupObj::replaceByName( const OUString& rName, const Any& rElement )
3070 {
3071 ScUnoGuard aGuard;
3072
3073 // it should be possible to quickly rename an item -> accept string or XNamed
3074 OUString aNewName = lclExtractMember( rElement );
3075 if( (rName.getLength() == 0) || (aNewName.getLength() == 0) )
3076 throw IllegalArgumentException();
3077 if( rName == aNewName )
3078 return;
3079
3080 ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3081 ScFieldGroupMembers::iterator aOldIt = ::std::find( rMembers.begin(), rMembers.end(), rName );
3082 ScFieldGroupMembers::iterator aNewIt = ::std::find( rMembers.begin(), rMembers.end(), aNewName );
3083 // throw if passed member name does not exist
3084 if( aOldIt == rMembers.end() )
3085 throw NoSuchElementException();
3086 // throw if new name already exists
3087 if( aNewIt != rMembers.end() )
3088 throw IllegalArgumentException();
3089 *aOldIt = aNewName;
3090 }
3091
3092 // XNameContainer
3093
insertByName(const OUString & rName,const Any &)3094 void SAL_CALL ScDataPilotFieldGroupObj::insertByName( const OUString& rName, const Any& /*rElement*/ )
3095 {
3096 ScUnoGuard aGuard;
3097
3098 // we will ignore the passed element and just try to insert the name
3099 if( rName.getLength() == 0 )
3100 throw IllegalArgumentException();
3101
3102 ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3103 ScFieldGroupMembers::iterator aIt = ::std::find( rMembers.begin(), rMembers.end(), rName );
3104 // throw if passed name already exists
3105 if( aIt != rMembers.end() )
3106 throw IllegalArgumentException();
3107 rMembers.push_back( rName );
3108 }
3109
removeByName(const OUString & rName)3110 void SAL_CALL ScDataPilotFieldGroupObj::removeByName( const OUString& rName )
3111 {
3112 ScUnoGuard aGuard;
3113
3114 if( rName.getLength() == 0 )
3115 throw IllegalArgumentException();
3116 ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3117 ScFieldGroupMembers::iterator aIt = ::std::find( rMembers.begin(), rMembers.end(), rName );
3118 // throw if passed name does not exist
3119 if( aIt == rMembers.end() )
3120 throw NoSuchElementException();
3121 rMembers.erase( aIt );
3122 }
3123
3124 // XIndexAccess
3125
getCount()3126 sal_Int32 SAL_CALL ScDataPilotFieldGroupObj::getCount()
3127 {
3128 ScUnoGuard aGuard;
3129 return static_cast< sal_Int32 >( mrParent.getFieldGroup( maGroupName ).maMembers.size() );
3130 }
3131
getByIndex(sal_Int32 nIndex)3132 Any SAL_CALL ScDataPilotFieldGroupObj::getByIndex( sal_Int32 nIndex )
3133 {
3134 ScUnoGuard aGuard;
3135 ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers;
3136 if ((nIndex < 0) || (nIndex >= static_cast< sal_Int32 >( rMembers.size() )))
3137 throw IndexOutOfBoundsException();
3138 return Any( Reference< XNamed >( new ScDataPilotFieldGroupItemObj( *this, rMembers[ nIndex ] ) ) );
3139 }
3140
3141 // XEnumerationAccess
3142
createEnumeration()3143 Reference< XEnumeration > SAL_CALL ScDataPilotFieldGroupObj::createEnumeration()
3144 {
3145 ScUnoGuard aGuard;
3146 return new ScIndexEnumeration( this, OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.DataPilotFieldGroupEnumeration" ) ) );
3147 }
3148
3149 // XElementAccess
3150
getElementType()3151 uno::Type SAL_CALL ScDataPilotFieldGroupObj::getElementType()
3152 {
3153 ScUnoGuard aGuard;
3154 return getCppuType( (Reference< XNamed >*)0 );
3155 }
3156
hasElements()3157 sal_Bool SAL_CALL ScDataPilotFieldGroupObj::hasElements()
3158 {
3159 ScUnoGuard aGuard;
3160 return !mrParent.getFieldGroup( maGroupName ).maMembers.empty();
3161 }
3162
3163 // XNamed
3164
getName()3165 OUString SAL_CALL ScDataPilotFieldGroupObj::getName()
3166 {
3167 ScUnoGuard aGuard;
3168 return maGroupName;
3169 }
3170
setName(const OUString & rName)3171 void SAL_CALL ScDataPilotFieldGroupObj::setName( const OUString& rName )
3172 {
3173 ScUnoGuard aGuard;
3174 mrParent.renameFieldGroup( maGroupName, rName );
3175 // if call to renameFieldGroup() did not throw, remember the new name
3176 maGroupName = rName;
3177 }
3178
3179 // ============================================================================
3180
ScDataPilotFieldGroupItemObj(ScDataPilotFieldGroupObj & rParent,const OUString & rName)3181 ScDataPilotFieldGroupItemObj::ScDataPilotFieldGroupItemObj( ScDataPilotFieldGroupObj& rParent, const OUString& rName ) :
3182 mrParent( rParent ),
3183 maName( rName )
3184 {
3185 mrParent.acquire();
3186 }
3187
~ScDataPilotFieldGroupItemObj()3188 ScDataPilotFieldGroupItemObj::~ScDataPilotFieldGroupItemObj()
3189 {
3190 mrParent.release();
3191 }
3192
3193 // XNamed
3194
getName()3195 OUString SAL_CALL ScDataPilotFieldGroupItemObj::getName()
3196 {
3197 ScUnoGuard aGuard;
3198 return maName;
3199 }
3200
setName(const OUString & rName)3201 void SAL_CALL ScDataPilotFieldGroupItemObj::setName( const OUString& rName )
3202 {
3203 ScUnoGuard aGuard;
3204 mrParent.replaceByName( maName, Any( rName ) );
3205 // if call to replaceByName() did not throw, remember the new name
3206 maName = rName;
3207 }
3208
3209 // ============================================================================
3210
ScDataPilotItemsObj(ScDataPilotDescriptorBase & rParent,const ScFieldIdentifier & rFieldId)3211 ScDataPilotItemsObj::ScDataPilotItemsObj( ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId ) :
3212 ScDataPilotChildObjBase( rParent, rFieldId )
3213 {
3214 }
3215
~ScDataPilotItemsObj()3216 ScDataPilotItemsObj::~ScDataPilotItemsObj()
3217 {
3218 }
3219
3220 // XDataPilotItems
3221
GetObjectByIndex_Impl(sal_Int32 nIndex) const3222 ScDataPilotItemObj* ScDataPilotItemsObj::GetObjectByIndex_Impl( sal_Int32 nIndex ) const
3223 {
3224 return ((0 <= nIndex) && (nIndex < GetMemberCount())) ?
3225 new ScDataPilotItemObj( mrParent, maFieldId, nIndex ) : 0;
3226 }
3227
3228 // XNameAccess
3229
getByName(const OUString & aName)3230 Any SAL_CALL ScDataPilotItemsObj::getByName( const OUString& aName )
3231 {
3232 ScUnoGuard aGuard;
3233 Reference<XNameAccess> xMembers = GetMembers();
3234 if (xMembers.is())
3235 {
3236 Reference<XIndexAccess> xMembersIndex(new ScNameToIndexAccess( xMembers ));
3237 sal_Int32 nCount = xMembersIndex->getCount();
3238 sal_Bool bFound(sal_False);
3239 sal_Int32 nItem = 0;
3240 while (nItem < nCount && !bFound )
3241 {
3242 Reference<XNamed> xMember(xMembersIndex->getByIndex(nItem), UNO_QUERY);
3243 if (xMember.is() && (aName == xMember->getName()))
3244 return Any( Reference< XPropertySet >( GetObjectByIndex_Impl( nItem ) ) );
3245 ++nItem;
3246 }
3247 if (!bFound)
3248 throw NoSuchElementException();
3249 }
3250 return Any();
3251 }
3252
getElementNames()3253 Sequence<OUString> SAL_CALL ScDataPilotItemsObj::getElementNames()
3254 {
3255 ScUnoGuard aGuard;
3256 Sequence< OUString > aSeq;
3257 if( ScDPObject* pDPObj = GetDPObject() )
3258 pDPObj->GetMemberNames( lcl_GetObjectIndex( pDPObj, maFieldId ), aSeq );
3259 return aSeq;
3260 }
3261
hasByName(const OUString & aName)3262 sal_Bool SAL_CALL ScDataPilotItemsObj::hasByName( const OUString& aName )
3263 {
3264 ScUnoGuard aGuard;
3265 sal_Bool bFound = sal_False;
3266 Reference<XNameAccess> xMembers = GetMembers();
3267 if (xMembers.is())
3268 {
3269 Reference<XIndexAccess> xMembersIndex(new ScNameToIndexAccess( xMembers ));
3270 sal_Int32 nCount = xMembersIndex->getCount();
3271 sal_Int32 nItem = 0;
3272 while (nItem < nCount && !bFound )
3273 {
3274 Reference<XNamed> xMember(xMembersIndex->getByIndex(nItem), UNO_QUERY);
3275 if (xMember.is() && aName == xMember->getName())
3276 bFound = sal_True;
3277 else
3278 nItem++;
3279 }
3280 }
3281 return bFound;
3282 }
3283
3284 // XEnumerationAccess
3285
createEnumeration()3286 Reference<XEnumeration> SAL_CALL ScDataPilotItemsObj::createEnumeration()
3287 {
3288 ScUnoGuard aGuard;
3289 return new ScIndexEnumeration(this, OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DataPilotItemsEnumeration")));
3290 }
3291
3292 // XIndexAccess
3293
getCount()3294 sal_Int32 SAL_CALL ScDataPilotItemsObj::getCount()
3295 {
3296 ScUnoGuard aGuard;
3297 return GetMemberCount();
3298 }
3299
getByIndex(sal_Int32 nIndex)3300 Any SAL_CALL ScDataPilotItemsObj::getByIndex( sal_Int32 nIndex )
3301 {
3302 ScUnoGuard aGuard;
3303 Reference< XPropertySet > xItem( GetObjectByIndex_Impl( nIndex ) );
3304 if (!xItem.is())
3305 throw IndexOutOfBoundsException();
3306 return Any( xItem );
3307 }
3308
getElementType()3309 uno::Type SAL_CALL ScDataPilotItemsObj::getElementType()
3310 {
3311 ScUnoGuard aGuard;
3312 return getCppuType((Reference<XPropertySet>*)0);
3313 }
3314
hasElements()3315 sal_Bool SAL_CALL ScDataPilotItemsObj::hasElements()
3316 {
3317 ScUnoGuard aGuard;
3318 return ( getCount() != 0 );
3319 }
3320
3321 //------------------------------------------------------------------------
3322
ScDataPilotItemObj(ScDataPilotDescriptorBase & rParent,const ScFieldIdentifier & rFieldId,sal_Int32 nIndex)3323 ScDataPilotItemObj::ScDataPilotItemObj( ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId, sal_Int32 nIndex ) :
3324 ScDataPilotChildObjBase( rParent, rFieldId ),
3325 maPropSet( lcl_GetDataPilotItemMap() ),
3326 mnIndex( nIndex )
3327 {
3328 }
3329
~ScDataPilotItemObj()3330 ScDataPilotItemObj::~ScDataPilotItemObj()
3331 {
3332 }
3333
3334 // XNamed
getName()3335 OUString SAL_CALL ScDataPilotItemObj::getName()
3336 {
3337 ScUnoGuard aGuard;
3338 OUString sRet;
3339 Reference<XNameAccess> xMembers = GetMembers();
3340 if (xMembers.is())
3341 {
3342 Reference<XIndexAccess> xMembersIndex(new ScNameToIndexAccess( xMembers ));
3343 sal_Int32 nCount = xMembersIndex->getCount();
3344 if (mnIndex < nCount)
3345 {
3346 Reference<XNamed> xMember(xMembersIndex->getByIndex(mnIndex), UNO_QUERY);
3347 sRet = xMember->getName();
3348 }
3349 }
3350 return sRet;
3351 }
3352
setName(const OUString &)3353 void SAL_CALL ScDataPilotItemObj::setName( const OUString& /* aName */ )
3354 {
3355 }
3356
3357 // XPropertySet
3358 Reference< XPropertySetInfo >
getPropertySetInfo()3359 SAL_CALL ScDataPilotItemObj::getPropertySetInfo( )
3360 {
3361 ScUnoGuard aGuard;
3362 static Reference<XPropertySetInfo> aRef =
3363 new SfxItemPropertySetInfo( maPropSet.getPropertyMap() );
3364 return aRef;
3365 }
3366
setPropertyValue(const OUString & aPropertyName,const Any & aValue)3367 void SAL_CALL ScDataPilotItemObj::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
3368 {
3369 ScUnoGuard aGuard;
3370 ScDPObject* pDPObj = 0;
3371 if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) )
3372 {
3373 Reference<XNameAccess> xMembers = GetMembers();
3374 if( xMembers.is() )
3375 {
3376 Reference<XIndexAccess> xMembersIndex( new ScNameToIndexAccess( xMembers ) );
3377 sal_Int32 nCount = xMembersIndex->getCount();
3378 if( mnIndex < nCount )
3379 {
3380 Reference<XNamed> xMember(xMembersIndex->getByIndex(mnIndex), UNO_QUERY);
3381 String sName(xMember->getName());
3382 ScDPSaveMember* pMember = pDim->GetMemberByName(sName);
3383 if (pMember)
3384 {
3385 bool bGetNewIndex = false;
3386 if ( aPropertyName.equalsAscii( SC_UNONAME_SHOWDETAIL ) )
3387 pMember->SetShowDetails(cppu::any2bool(aValue));
3388 else if ( aPropertyName.equalsAscii( SC_UNONAME_ISHIDDEN ) )
3389 pMember->SetIsVisible(!cppu::any2bool(aValue));
3390 else if ( aPropertyName.equalsAscii( SC_UNONAME_POS ) )
3391 {
3392 sal_Int32 nNewPos = 0;
3393 if ( ( aValue >>= nNewPos ) && nNewPos >= 0 && nNewPos < nCount )
3394 {
3395 pDim->SetMemberPosition( sName, nNewPos );
3396 // get new effective index (depends on sorting mode, which isn't modified)
3397 bGetNewIndex = true;
3398 }
3399 else
3400 throw IllegalArgumentException();
3401 }
3402 SetDPObject( pDPObj );
3403
3404 if ( bGetNewIndex ) // after SetDPObject, get the new index
3405 {
3406 OUString aOUName( sName );
3407 Sequence< OUString > aItemNames = xMembers->getElementNames();
3408 sal_Int32 nItemCount = aItemNames.getLength();
3409 for (sal_Int32 nItem=0; nItem<nItemCount; ++nItem)
3410 if (aItemNames[nItem] == aOUName)
3411 mnIndex = nItem;
3412 }
3413 }
3414 }
3415 }
3416 }
3417 }
3418
getPropertyValue(const OUString & aPropertyName)3419 Any SAL_CALL ScDataPilotItemObj::getPropertyValue( const OUString& aPropertyName )
3420 {
3421 ScUnoGuard aGuard;
3422 Any aRet;
3423 if( ScDPSaveDimension* pDim = GetDPDimension() )
3424 {
3425 Reference< XNameAccess > xMembers = GetMembers();
3426 if( xMembers.is() )
3427 {
3428 Reference< XIndexAccess > xMembersIndex( new ScNameToIndexAccess( xMembers ) );
3429 sal_Int32 nCount = xMembersIndex->getCount();
3430 if( mnIndex < nCount )
3431 {
3432 Reference< XNamed > xMember( xMembersIndex->getByIndex( mnIndex ), UNO_QUERY );
3433 String sName( xMember->getName() );
3434 ScDPSaveMember* pMember = pDim->GetExistingMemberByName( sName );
3435 if( aPropertyName.equalsAscii( SC_UNONAME_SHOWDETAIL ) )
3436 {
3437 if (pMember && pMember->HasShowDetails())
3438 {
3439 aRet <<= (bool)pMember->GetShowDetails();
3440 }
3441 else
3442 {
3443 Reference< XPropertySet > xMemberProps( xMember, UNO_QUERY );
3444 if( xMemberProps.is() )
3445 aRet = xMemberProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_SHOWDETA ) ) );
3446 else
3447 aRet <<= true;
3448 }
3449 }
3450 else if ( aPropertyName.equalsAscii( SC_UNONAME_ISHIDDEN ) )
3451 {
3452 if (pMember && pMember->HasIsVisible())
3453 {
3454 aRet <<= !pMember->GetIsVisible();
3455 }
3456 else
3457 {
3458 Reference< XPropertySet > xMemberProps( xMember, UNO_QUERY );
3459 if( xMemberProps.is() )
3460 aRet <<= !cppu::any2bool( xMemberProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_ISVISIBL ) ) ) );
3461 else
3462 aRet <<= false;
3463 }
3464 }
3465 else if ( aPropertyName.equalsAscii( SC_UNONAME_POS ) )
3466 {
3467 aRet <<= mnIndex;
3468 }
3469 }
3470 }
3471 }
3472 return aRet;
3473 }
3474
addPropertyChangeListener(const OUString &,const Reference<XPropertyChangeListener> &)3475 void SAL_CALL ScDataPilotItemObj::addPropertyChangeListener(
3476 const OUString& /* aPropertyName */, const Reference< XPropertyChangeListener >& /* xListener */ )
3477 {
3478 }
3479
removePropertyChangeListener(const OUString &,const Reference<XPropertyChangeListener> &)3480 void SAL_CALL ScDataPilotItemObj::removePropertyChangeListener(
3481 const OUString& /* aPropertyName */, const Reference< XPropertyChangeListener >& /* aListener */ )
3482 {
3483 }
3484
addVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)3485 void SAL_CALL ScDataPilotItemObj::addVetoableChangeListener(
3486 const OUString& /* PropertyName */, const Reference< XVetoableChangeListener >& /* aListener */ )
3487 {
3488 }
3489
removeVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)3490 void SAL_CALL ScDataPilotItemObj::removeVetoableChangeListener(
3491 const OUString& /* PropertyName */, const Reference< XVetoableChangeListener >& /* aListener */ )
3492 {
3493 }
3494
3495 //------------------------------------------------------------------------
3496