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