1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_SC_INC_DPSAVE_HXX
21 #define INCLUDED_SC_INC_DPSAVE_HXX
22 
23 #include <memory>
24 #include <vector>
25 
26 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
27 #include <rtl/ustring.hxx>
28 #include <sal/types.h>
29 
30 #include "scdllapi.h"
31 #include "calcmacros.hxx"
32 
33 #include <unordered_map>
34 #include <unordered_set>
35 #include <boost/optional.hpp>
36 
37 namespace com { namespace sun { namespace star { namespace sheet {
38     class XDimensionsSupplier;
39     struct DataPilotFieldReference;
40     struct DataPilotFieldSortInfo;
41     struct DataPilotFieldAutoShowInfo;
42     struct DataPilotFieldLayoutInfo;
43 } } } }
44 
45 class ScDPDimensionSaveData;
46 class ScDPTableData;
47 enum class ScGeneralFunction;
48 
49 // classes to save Data Pilot settings
50 
51 class ScDPSaveMember
52 {
53 private:
54     OUString aName;
55     boost::optional<OUString> mpLayoutName; // custom name to be displayed in the table.
56     sal_uInt16 nVisibleMode;
57     sal_uInt16 nShowDetailsMode;
58 
59 public:
60     ScDPSaveMember(const OUString& rName);
61     ScDPSaveMember(const ScDPSaveMember& r);
62     ~ScDPSaveMember();
63 
64     bool operator== ( const ScDPSaveMember& r ) const;
65 
GetName() const66     const OUString& GetName() const
67         { return aName; }
68 
69     SC_DLLPUBLIC bool HasIsVisible() const;
70     SC_DLLPUBLIC void SetIsVisible(bool bSet);
GetIsVisible() const71     bool GetIsVisible() const
72         { return bool(nVisibleMode); }
73 
74     SC_DLLPUBLIC bool HasShowDetails() const;
75     SC_DLLPUBLIC void SetShowDetails(bool bSet);
GetShowDetails() const76     bool GetShowDetails() const
77         { return bool(nShowDetailsMode); }
78 
79     void SetName( const OUString& rNew ); // used if the source member was renamed (groups)
80 
81     SC_DLLPUBLIC void SetLayoutName( const OUString& rName );
82     SC_DLLPUBLIC const boost::optional<OUString> & GetLayoutName() const;
83     void RemoveLayoutName();
84 
85     void WriteToSource( const css::uno::Reference<css::uno::XInterface>& xMember,
86                             sal_Int32 nPosition );
87 
88 #if DUMP_PIVOT_TABLE
89     void Dump(int nIndent = 0) const;
90 #endif
91 };
92 
93 class SC_DLLPUBLIC ScDPSaveDimension
94 {
95 private:
96     OUString aName;
97     boost::optional<OUString> mpLayoutName;
98     boost::optional<OUString> mpSubtotalName;
99     bool bIsDataLayout;
100     bool bDupFlag;
101     css::sheet::DataPilotFieldOrientation nOrientation;
102     ScGeneralFunction nFunction; // for data dimensions
103     long nUsedHierarchy;
104     sal_uInt16 nShowEmptyMode; //! at level
105     bool bRepeatItemLabels; //! at level
106     bool bSubTotalDefault; //! at level
107     std::vector<ScGeneralFunction> maSubTotalFuncs;
108     std::unique_ptr<css::sheet::DataPilotFieldReference> pReferenceValue;
109     std::unique_ptr<css::sheet::DataPilotFieldSortInfo> pSortInfo; // (level)
110     std::unique_ptr<css::sheet::DataPilotFieldAutoShowInfo> pAutoShowInfo; // (level)
111     std::unique_ptr<css::sheet::DataPilotFieldLayoutInfo> pLayoutInfo; // (level)
112 
113 public:
114     typedef std::unordered_set<OUString> MemberSetType;
115     typedef std::vector<ScDPSaveMember*> MemberList;
116 
117 private:
118     std::unordered_map<OUString, std::unique_ptr<ScDPSaveMember>> maMemberHash;
119     MemberList maMemberList;
120 
121 public:
122     ScDPSaveDimension(const OUString& rName, bool bDataLayout);
123     ScDPSaveDimension(const ScDPSaveDimension& r);
124     ~ScDPSaveDimension();
125 
126     bool operator== ( const ScDPSaveDimension& r ) const;
127 
GetMembers() const128     const MemberList& GetMembers() const
129         { return maMemberList; }
130 
131     void AddMember(std::unique_ptr<ScDPSaveMember> pMember);
132 
SetDupFlag(bool bSet)133     void SetDupFlag(bool bSet)
134         { bDupFlag = bSet; }
135 
GetDupFlag() const136     bool GetDupFlag() const
137         { return bDupFlag; }
138 
GetName() const139     const OUString& GetName() const
140         { return aName; }
141 
IsDataLayout() const142     bool IsDataLayout() const
143         { return bIsDataLayout; }
144 
145     void SetName( const OUString& rNew ); // used if the source dim was renamed (groups)
146 
147     void SetOrientation(css::sheet::DataPilotFieldOrientation nNew);
148     void SetSubTotals(std::vector<ScGeneralFunction> const & rFuncs);
GetSubTotalsCount() const149     long GetSubTotalsCount() const
150         { return maSubTotalFuncs.size(); }
151 
GetSubTotalFunc(long nIndex) const152     ScGeneralFunction GetSubTotalFunc(long nIndex) const
153         { return maSubTotalFuncs[nIndex]; }
154 
155     bool HasShowEmpty() const;
156     void SetShowEmpty(bool bSet);
GetShowEmpty() const157     bool GetShowEmpty() const
158         { return bool(nShowEmptyMode); }
159 
160     void SetRepeatItemLabels(bool bSet);
GetRepeatItemLabels() const161     bool GetRepeatItemLabels() const
162         { return bRepeatItemLabels; }
163 
164     void SetFunction(ScGeneralFunction nNew);
GetFunction() const165     ScGeneralFunction GetFunction() const
166         { return nFunction; }
167 
168     void SetUsedHierarchy(long nNew);
GetUsedHierarchy() const169     long GetUsedHierarchy() const
170         { return nUsedHierarchy; }
171 
172     void SetLayoutName(const OUString& rName);
173     const boost::optional<OUString> & GetLayoutName() const;
174     void RemoveLayoutName();
175     void SetSubtotalName(const OUString& rName);
176     const boost::optional<OUString> & GetSubtotalName() const;
177     void RemoveSubtotalName();
178 
179     bool IsMemberNameInUse(const OUString& rName) const;
180 
GetReferenceValue() const181     const css::sheet::DataPilotFieldReference* GetReferenceValue() const
182         { return pReferenceValue.get(); }
183 
184     void SetReferenceValue(const css::sheet::DataPilotFieldReference* pNew);
185 
GetSortInfo() const186     const css::sheet::DataPilotFieldSortInfo* GetSortInfo() const
187         { return pSortInfo.get(); }
188 
189     void SetSortInfo(const css::sheet::DataPilotFieldSortInfo* pNew);
GetAutoShowInfo() const190     const css::sheet::DataPilotFieldAutoShowInfo* GetAutoShowInfo() const
191         { return pAutoShowInfo.get(); }
192 
193     void SetAutoShowInfo(const css::sheet::DataPilotFieldAutoShowInfo* pNew);
GetLayoutInfo() const194     const css::sheet::DataPilotFieldLayoutInfo* GetLayoutInfo() const
195         { return pLayoutInfo.get(); }
196 
197     void SetLayoutInfo(const css::sheet::DataPilotFieldLayoutInfo* pNew);
198 
199     void SetCurrentPage( const OUString* pPage ); // NULL = no selection (all)
200     OUString GetCurrentPage() const; // only for ODF compatibility
201 
GetOrientation() const202     css::sheet::DataPilotFieldOrientation GetOrientation() const
203         { return nOrientation; }
204 
205     ScDPSaveMember* GetExistingMemberByName(const OUString& rName);
206 
207     /**
208      * Get a member object by its name.  If one doesn't exist, create a new
209      * object and return it.  This class manages the life cycle of all member
210      * objects belonging to it, so <i>don't delete the returned instance.</i>
211      *
212      * @param rName member name
213      *
214      * @return pointer to the member object.
215      */
216     ScDPSaveMember* GetMemberByName(const OUString& rName);
217 
218     void SetMemberPosition( const OUString& rName, sal_Int32 nNewPos );
219 
220     void WriteToSource( const css::uno::Reference<css::uno::XInterface>& xDim );
221 
222     void UpdateMemberVisibility(const std::unordered_map< OUString, bool>& rData);
223 
224     bool HasInvisibleMember() const;
225 
226     void RemoveObsoleteMembers(const MemberSetType& rMembers);
227 
228 #if DUMP_PIVOT_TABLE
229     void Dump(int nIndent = 0) const;
230 #endif
231 };
232 
233 class ScDPSaveData
234 {
235     typedef std::unordered_map<OUString, size_t> DupNameCountType;
236 public:
237     typedef std::unordered_map<OUString, size_t> DimOrderType;
238     typedef std::vector<std::unique_ptr<ScDPSaveDimension>> DimsType;
239 
240 private:
241     DimsType m_DimList;
242     DupNameCountType maDupNameCounts; /// keep track of number of duplicates in each name.
243     std::unique_ptr<ScDPDimensionSaveData> pDimensionData; // settings that create new dimensions
244     sal_uInt16 nColumnGrandMode;
245     sal_uInt16 nRowGrandMode;
246     sal_uInt16 nIgnoreEmptyMode;
247     sal_uInt16 nRepeatEmptyMode;
248     bool bFilterButton; // not passed to DataPilotSource
249     bool bDrillDown; // not passed to DataPilotSource
250 
251     /** if true, all dimensions already have all of their member instances
252      *  created. */
253     bool mbDimensionMembersBuilt;
254 
255     boost::optional<OUString> mpGrandTotalName;
256     mutable std::unique_ptr<DimOrderType> mpDimOrder; // dimension order for row and column dimensions, to traverse result tree.
257 
258 public:
259     SC_DLLPUBLIC ScDPSaveData();
260     ScDPSaveData(const ScDPSaveData& r);
261     SC_DLLPUBLIC ~ScDPSaveData();
262 
263     ScDPSaveData& operator= ( const ScDPSaveData& r );
264 
265     bool operator== ( const ScDPSaveData& r ) const;
266 
267     SC_DLLPUBLIC void SetGrandTotalName(const OUString& rName);
268     SC_DLLPUBLIC const boost::optional<OUString> & GetGrandTotalName() const;
269 
GetDimensions() const270     const DimsType& GetDimensions() const { return m_DimList; }
271 
272     /**
273      * Get sort order map to sort row and column dimensions in order of
274      * appearance. Row dimensions get sorted before column dimensions.  This
275      * is used to traverse result tree, which is structured following this
276      * order.
277      */
278     const DimOrderType& GetDimensionSortOrder() const;
279 
280     /**
281      * Get all dimensions in a given orientation.  The order represents the
282      * actual order of occurrence.  The returned list also includes data
283      * layout dimension.
284      *
285      * @param eOrientation orientation
286      * @param rDims (out) list of dimensions for specified orientation
287      */
288     SC_DLLPUBLIC void GetAllDimensionsByOrientation(
289         css::sheet::DataPilotFieldOrientation eOrientation,
290         std::vector<const ScDPSaveDimension*>& rDims) const;
291 
292     void AddDimension(ScDPSaveDimension* pDim);
293 
294     /**
295      * Get a dimension object by its name.  <i>If one doesn't exist for the
296      * given name, it creates a new one.</i>
297      *
298      * @param rName dimension name
299      *
300      * @return pointer to the dimension object.  The ScDPSaveData instance
301      *         manages its life cycle; hence the caller must
302      *         <i>not</i> delete this object.
303      */
304     SC_DLLPUBLIC ScDPSaveDimension* GetDimensionByName(const OUString& rName);
305     SC_DLLPUBLIC ScDPSaveDimension* GetDataLayoutDimension();
306     SC_DLLPUBLIC ScDPSaveDimension* GetExistingDataLayoutDimension() const;
307 
308     ScDPSaveDimension* DuplicateDimension(const OUString& rName);
309     SC_DLLPUBLIC ScDPSaveDimension& DuplicateDimension(const ScDPSaveDimension& rDim);
310 
311     SC_DLLPUBLIC ScDPSaveDimension* GetExistingDimensionByName(const OUString& rName) const;
312     SC_DLLPUBLIC ScDPSaveDimension* GetNewDimensionByName(const OUString& rName);
313 
314     void RemoveDimensionByName(const OUString& rName);
315 
316     ScDPSaveDimension* GetInnermostDimension(css::sheet::DataPilotFieldOrientation nOrientation);
317     ScDPSaveDimension* GetFirstDimension(css::sheet::DataPilotFieldOrientation eOrientation);
318     SC_DLLPUBLIC long GetDataDimensionCount() const;
319 
320     void SetPosition( ScDPSaveDimension* pDim, long nNew );
321     SC_DLLPUBLIC void SetColumnGrand( bool bSet );
GetColumnGrand() const322     bool GetColumnGrand() const
323         { return bool(nColumnGrandMode); }
324 
325     SC_DLLPUBLIC void SetRowGrand( bool bSet );
GetRowGrand() const326     bool GetRowGrand() const
327         { return bool(nRowGrandMode); }
328 
329     SC_DLLPUBLIC void SetIgnoreEmptyRows( bool bSet );
GetIgnoreEmptyRows() const330     bool GetIgnoreEmptyRows() const
331         { return bool(nIgnoreEmptyMode); }
332 
333     SC_DLLPUBLIC void SetRepeatIfEmpty( bool bSet );
GetRepeatIfEmpty() const334     bool GetRepeatIfEmpty() const
335         { return bool(nRepeatEmptyMode); }
336 
337     SC_DLLPUBLIC void SetFilterButton( bool bSet );
GetFilterButton() const338     bool GetFilterButton() const
339         { return bFilterButton; }
340 
341     SC_DLLPUBLIC void SetDrillDown( bool bSet );
GetDrillDown() const342     bool GetDrillDown() const
343         { return bDrillDown; }
344 
345     void WriteToSource( const css::uno::Reference<css::sheet::XDimensionsSupplier>& xSource );
346     bool IsEmpty() const;
347 
GetExistingDimensionData() const348     const ScDPDimensionSaveData* GetExistingDimensionData() const
349         { return pDimensionData.get(); }
350 
351     void RemoveAllGroupDimensions( const OUString& rSrcDimName, std::vector<OUString>* pDeletedNames = nullptr );
352 
353     SC_DLLPUBLIC ScDPDimensionSaveData* GetDimensionData(); // create if not there
354     SC_DLLPUBLIC void SetDimensionData( const ScDPDimensionSaveData* pNew ); // copied
355     void BuildAllDimensionMembers(ScDPTableData* pData);
356     void SyncAllDimensionMembers(ScDPTableData* pData);
357 
358     /**
359      * Check whether a dimension has one or more invisible members.
360      *
361      * @param rDimName dimension name
362      */
363     SC_DLLPUBLIC bool HasInvisibleMember(const OUString& rDimName) const;
364 
365 #if DUMP_PIVOT_TABLE
366     void Dump() const;
367 #endif
368 
369 private:
370     void CheckDuplicateName(ScDPSaveDimension& rDim);
371     void RemoveDuplicateNameCount(const OUString& rName);
372 
373     /**
374      * Append a new original dimension. Not to be called to insert a duplicate
375      * dimension.
376      *
377      * @param rName Dimension name. The name must be the original dimension
378      *              name; not a duplicate dimension name.
379      * @param bDataLayout true if this is a data layout dimension, false
380      *                    otherwise.
381      *
382      * @return pointer to the new dimension just inserted.
383      */
384     ScDPSaveDimension* AppendNewDimension(const OUString& rName, bool bDataLayout);
385 
386     void DimensionsChanged();
387 };
388 
389 #endif
390 
391 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
392