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