xref: /core/sc/inc/sortparam.hxx (revision 0fb98963)
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 #pragma once
21 
22 #define DEFSORT 3
23 
24 #include <vector>
25 
26 #include "address.hxx"
27 #include <com/sun/star/lang/Locale.hpp>
28 #include "scdllapi.h"
29 #include "celltextattr.hxx"
30 #include "cellvalue.hxx"
31 #include "patattr.hxx"
32 #include <tools/color.hxx>
33 
34 struct ScSubTotalParam;
35 struct ScQueryParam;
36 class SdrObject;
37 class ScPostIt;
38 
39 enum class ScColorSortMode {
40     None,
41     TextColor,
42     BackgroundColor
43 };
44 
45 struct ScSortKeyState
46 {
47     SCCOLROW nField;
48     bool     bDoSort;
49     bool     bAscending;
50     ScColorSortMode aColorSortMode;
51     Color    aColorSortColor;
52 };
53 
54 /** Struct to hold non-data extended area, used with
55     ScDocument::ShrinkToUsedDataArea().
56 */
57 struct ScDataAreaExtras
58 {
59     /// If TRUE, consider the presence of cell notes besides data.
60     bool    mbCellNotes = false;
61     /// If TRUE, consider the presence of draw objects anchored to the cell.
62     bool    mbCellDrawObjects = false;
63     /// If TRUE, consider the presence of cell formats.
64     bool    mbCellFormats = false;
65     SCCOL   mnStartCol = SCCOL_MAX;
66     SCROW   mnStartRow = SCROW_MAX;
67     SCCOL   mnEndCol = -1;
68     SCROW   mnEndRow = -1;
69 
anyExtrasWantedScDataAreaExtras70     bool anyExtrasWanted() const { return mbCellNotes || mbCellDrawObjects || mbCellFormats; }
resetAreaScDataAreaExtras71     void resetArea() { mnStartCol = SCCOL_MAX; mnStartRow = SCROW_MAX; mnEndCol = -1; mnEndRow = -1; }
72 
operator ==ScDataAreaExtras73     bool operator==( const ScDataAreaExtras& rOther ) const
74     {
75         // Ignore area range, this is used in ScSortParam::operator==().
76         return mbCellNotes       == rOther.mbCellNotes
77             && mbCellDrawObjects == rOther.mbCellDrawObjects
78             && mbCellFormats     == rOther.mbCellFormats;
79     }
80 
81     enum class Clip
82     {
83         None,
84         Col,
85         Row
86     };
87 
88     /// Obtain the overall range if area extras are larger.
GetOverallRangeScDataAreaExtras89     void GetOverallRange( SCCOL& nCol1, SCROW& nRow1, SCCOL& nCol2, SCROW& nRow2, Clip eClip = Clip::None ) const
90     {
91         if (eClip != Clip::Col)
92         {
93             if (nCol1 > mnStartCol)
94                 nCol1 = mnStartCol;
95             if (nCol2 < mnEndCol)
96                 nCol2 = mnEndCol;
97         }
98         if (eClip != Clip::Row)
99         {
100             if (nRow1 > mnStartRow)
101                 nRow1 = mnStartRow;
102             if (nRow2 < mnEndRow)
103                 nRow2 = mnEndRow;
104         }
105     }
106 
107     /// Set the overall range.
SetOverallRangeScDataAreaExtras108     void SetOverallRange( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
109     {
110         mnStartCol = nCol1;
111         mnStartRow = nRow1;
112         mnEndCol   = nCol2;
113         mnEndRow   = nRow2;
114     }
115 };
116 
117 struct SC_DLLPUBLIC ScSortParam
118 {
119     SCCOL       nCol1;
120     SCROW       nRow1;
121     SCCOL       nCol2;
122     SCROW       nRow2;
123     SCTAB       nSourceTab;
124     ScDataAreaExtras aDataAreaExtras;
125     sal_uInt16  nUserIndex;
126     bool        bHasHeader;
127     bool        bByRow;
128     bool        bCaseSens;
129     bool        bNaturalSort;
130     bool        bUserDef;
131     bool        bInplace;
132     SCTAB       nDestTab;
133     SCCOL       nDestCol;
134     SCROW       nDestRow;
135     ::std::vector<ScSortKeyState>
136                 maKeyState;
137     css::lang::Locale aCollatorLocale;
138     OUString    aCollatorAlgorithm;
139     sal_uInt16  nCompatHeader;
140 
141     ScSortParam();
142     ScSortParam( const ScSortParam& r );
143     /// SubTotals sort
144     ScSortParam( const ScSubTotalParam& rSub, const ScSortParam& rOld );
145     /// TopTen sort
146     ScSortParam( const ScQueryParam&, SCCOL nCol );
147     ~ScSortParam();
148 
149     ScSortParam&    operator=  ( const ScSortParam& r );
150     bool            operator== ( const ScSortParam& rOther ) const;
151     void            Clear       ();
152     void            MoveToDest();
153 
GetSortKeyCountScSortParam154     sal_uInt16 GetSortKeyCount() const { return maKeyState.size(); }
155 };
156 
157 struct ScSortInfo final
158 {
159     ScRefCellValue maCell;
160     SCCOLROW       nOrg;
161 };
162 
163 class ScSortInfoArray
164 {
165 public:
166 
167     struct Cell
168     {
169         ScRefCellValue maCell;
170         const sc::CellTextAttr* mpAttr;
171         const ScPostIt* mpNote;
172         std::vector<SdrObject*> maDrawObjects;
173         CellAttributeHolder maPattern;
174 
CellScSortInfoArray::Cell175         Cell() : mpAttr(nullptr), mpNote(nullptr),  maPattern() {}
176     };
177 
178     struct Row
179     {
180         std::vector<Cell> maCells;
181 
182         bool mbHidden:1;
183         bool mbFiltered:1;
184 
RowScSortInfoArray::Row185         explicit Row( size_t nColSize ) : maCells(nColSize, Cell()), mbHidden(false), mbFiltered(false) {}
186     };
187 
188     typedef std::vector<Row> RowsType;
189 
190 private:
191     std::unique_ptr<RowsType> mpRows; /// row-wise data table for sort by row operation.
192 
193     std::vector<std::unique_ptr<ScSortInfo[]>> mvppInfo;
194     SCCOLROW        nStart;
195     SCCOLROW        mnLastIndex; /// index of last non-empty cell position.
196 
197     std::vector<SCCOLROW> maOrderIndices;
198     bool mbKeepQuery;
199     bool mbUpdateRefs;
200 
201 public:
202     ScSortInfoArray(const ScSortInfoArray&) = delete;
203     const ScSortInfoArray& operator=(const ScSortInfoArray&) = delete;
204 
ScSortInfoArray(sal_uInt16 nSorts,SCCOLROW nInd1,SCCOLROW nInd2)205     ScSortInfoArray( sal_uInt16 nSorts, SCCOLROW nInd1, SCCOLROW nInd2 ) :
206         mvppInfo(nSorts),
207         nStart( nInd1 ),
208         mnLastIndex(nInd2),
209         mbKeepQuery(false),
210         mbUpdateRefs(false)
211     {
212         SCSIZE nCount( nInd2 - nInd1 + 1 );
213         if (nSorts)
214         {
215             for ( sal_uInt16 nSort = 0; nSort < nSorts; nSort++ )
216             {
217                 mvppInfo[nSort].reset(new ScSortInfo[nCount]);
218             }
219         }
220 
221         for (size_t i = 0; i < nCount; ++i)
222             maOrderIndices.push_back(i+nStart);
223     }
224 
SetKeepQuery(bool b)225     void SetKeepQuery( bool b ) { mbKeepQuery = b; }
226 
IsKeepQuery() const227     bool IsKeepQuery() const { return mbKeepQuery; }
228 
SetUpdateRefs(bool b)229     void SetUpdateRefs( bool b ) { mbUpdateRefs = b; }
230 
IsUpdateRefs() const231     bool IsUpdateRefs() const { return mbUpdateRefs; }
232 
233     /**
234      * Call this only during normal sorting, not from reordering.
235      */
GetFirstArray() const236     std::unique_ptr<ScSortInfo[]> const & GetFirstArray() const
237     {
238         return mvppInfo[0];
239     }
240 
241     /**
242      * Call this only during normal sorting, not from reordering.
243      */
Get(sal_uInt16 nSort,SCCOLROW nInd)244     ScSortInfo & Get( sal_uInt16 nSort, SCCOLROW nInd )
245     {
246         return mvppInfo[nSort][ nInd - nStart ];
247     }
248 
249     /**
250      * Call this only during normal sorting, not from reordering.
251      */
Swap(SCCOLROW nInd1,SCCOLROW nInd2)252     void Swap( SCCOLROW nInd1, SCCOLROW nInd2 )
253     {
254         if (nInd1 == nInd2) // avoid self-move-assign
255             return;
256         SCSIZE n1 = static_cast<SCSIZE>(nInd1 - nStart);
257         SCSIZE n2 = static_cast<SCSIZE>(nInd2 - nStart);
258         for ( sal_uInt16 nSort = 0; nSort < static_cast<sal_uInt16>(mvppInfo.size()); nSort++ )
259         {
260             auto & ppInfo = mvppInfo[nSort];
261             std::swap(ppInfo[n1], ppInfo[n2]);
262         }
263 
264         std::swap(maOrderIndices[n1], maOrderIndices[n2]);
265 
266         if (mpRows)
267         {
268             // Swap rows in data table.
269             RowsType& rRows = *mpRows;
270             std::swap(rRows[n1], rRows[n2]);
271         }
272     }
273 
SetOrderIndices(std::vector<SCCOLROW> && rIndices)274     void SetOrderIndices( std::vector<SCCOLROW>&& rIndices )
275     {
276         maOrderIndices = std::move(rIndices);
277     }
278 
279     /**
280      * @param rIndices indices are actual row positions on the sheet, not an
281      *                 offset from the top row.
282      */
ReorderByRow(const std::vector<SCCOLROW> & rIndices)283     void ReorderByRow( const std::vector<SCCOLROW>& rIndices )
284     {
285         if (!mpRows)
286             return;
287 
288         RowsType& rRows = *mpRows;
289 
290         std::vector<SCCOLROW> aOrderIndices2;
291         aOrderIndices2.reserve(rIndices.size());
292 
293         RowsType aRows2;
294         aRows2.reserve(rRows.size());
295 
296         for (const auto& rIndex : rIndices)
297         {
298             size_t nPos = rIndex - nStart; // switch to an offset to top row.
299             aRows2.push_back(rRows[nPos]);
300             aOrderIndices2.push_back(maOrderIndices[nPos]);
301         }
302 
303         rRows.swap(aRows2);
304         maOrderIndices.swap(aOrderIndices2);
305     }
306 
GetUsedSorts() const307     sal_uInt16      GetUsedSorts() const { return mvppInfo.size(); }
308 
GetStart() const309     SCCOLROW    GetStart() const { return nStart; }
GetLast() const310     SCCOLROW GetLast() const { return mnLastIndex; }
311 
GetOrderIndices() const312     const std::vector<SCCOLROW>& GetOrderIndices() const { return maOrderIndices; }
313 
InitDataRows(size_t nRowSize,size_t nColSize)314     RowsType& InitDataRows( size_t nRowSize, size_t nColSize )
315     {
316         mpRows.reset(new RowsType);
317         mpRows->resize(nRowSize, Row(nColSize));
318         return *mpRows;
319     }
320 
GetDataRows()321     RowsType* GetDataRows()
322     {
323         return mpRows.get();
324     }
325 };
326 
327 namespace sc {
328 
329 struct ReorderParam
330 {
331     /**
332      * This sort range already takes into account the presence or absence of
333      * header row / column i.e. if a header row / column is present, it
334      * excludes that row / column.
335      */
336     ScRange maSortRange;
337     ScDataAreaExtras maDataAreaExtras;
338 
339     /**
340      * List of original column / row positions after reordering.
341      */
342     std::vector<SCCOLROW> maOrderIndices;
343     bool mbByRow;
344     bool mbHiddenFiltered;
345     bool mbUpdateRefs;
346     bool mbHasHeaders;
347 
348     /**
349      * Reorder the position indices such that it can be used to undo the
350      * original reordering.
351      */
352     void reverse();
353 
ReorderParamsc::ReorderParam354     ReorderParam()
355         : mbByRow(false)
356         , mbHiddenFiltered(false)
357         , mbUpdateRefs(false)
358         , mbHasHeaders(false)
359     {
360     }
361 };
362 
363 }
364 
365 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
366