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
