sc/inc/SheetView.hxx | 18 +++++--- sc/inc/SheetViewManager.hxx | 2 sc/inc/sortparam.hxx | 9 ++++ sc/qa/unit/types/SortOrderReverserTest.cxx | 18 ++++---- sc/source/core/data/SheetView.cxx | 63 +++++++++++++++++------------ sc/source/core/data/SheetViewManager.cxx | 5 -- sc/source/core/data/table3.cxx | 22 +++++++--- 7 files changed, 88 insertions(+), 49 deletions(-)
New commits: commit 7257b091a19f626e0640fab39f430c00d75ad165 Author: Tomaž Vajngerl <[email protected]> AuthorDate: Fri Jan 23 17:47:06 2026 +0900 Commit: Miklos Vajna <[email protected]> CommitDate: Wed Jan 28 08:58:15 2026 +0100 sc: introduce SortOrderInfo instead of multiple input params SortOrderInfo contains all the needed sort information that was performed by a sort action. This simplifies the code so instead of having multiple input parameters, we have this struct instead. Additionally adds maKeyStates, which remembers the sort information for each specific column. If there are multiple columns you sort specify the sorting condition for each of the columns and the priority of the sorting. For example if you have columns A, B, C, you can define that first sort column B ascending, and then for each equal value in column B, sort those by column A descending. We remember the sort key states, and take them into account when we determine if the sorting has changed. This will however need more work to synchronise correctly. Change-Id: I1844e0705bfea736404085e880b78c99f9656e60 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197922 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> diff --git a/sc/inc/SheetView.hxx b/sc/inc/SheetView.hxx index 32972acecfcb..41f247c162eb 100644 --- a/sc/inc/SheetView.hxx +++ b/sc/inc/SheetView.hxx @@ -13,19 +13,27 @@ #include "types.hxx" #include <rtl/ustring.hxx> #include "SheetViewTypes.hxx" +#include "sortparam.hxx" #include <optional> class ScTable; namespace sc { +/** Contains the information of an performed sort action */ +struct SC_DLLPUBLIC SortOrderInfo +{ + SCROW mnFirstRow = -1; + SCROW mnLastRow = -1; + std::vector<SCCOLROW> maOrder; // Remember the sort order + std::vector<ScSortKeyState> maKeyStates; // Each column sort information +}; + /** Stores the sort order and can reverse the sorting of rows (unsorting). */ struct SC_DLLPUBLIC SortOrderReverser { public: - SCROW mnFirstRow; - SCROW mnLastRow; - std::vector<SCCOLROW> maOrder; + SortOrderInfo maSortInfo; /** Reverse the sort for the input row and output the unsorted row. * @@ -40,7 +48,7 @@ public: * Adds the indices if none are present, or combines the indices if the order indices * were already added previously. **/ - void addOrderIndices(std::vector<SCCOLROW> const& rOrder, SCROW firstRow, SCROW lastRow); + void addOrderIndices(SortOrderInfo const& rSortInfo); }; /** Stores information of a sheet view. @@ -83,7 +91,7 @@ public: * Adds the indices if none are present, or combines the indices if the order indices * were already added previously. **/ - void addOrderIndices(std::vector<SCCOLROW> const& rOrder, SCROW firstRow, SCROW lastRow); + void addOrderIndices(SortOrderInfo const& rSortInfo); }; } diff --git a/sc/inc/SheetViewManager.hxx b/sc/inc/SheetViewManager.hxx index 205f08feb682..9180f4a891db 100644 --- a/sc/inc/SheetViewManager.hxx +++ b/sc/inc/SheetViewManager.hxx @@ -69,7 +69,7 @@ public: static OUString defaultViewName(); std::optional<SortOrderReverser> const& getSortOrder() const { return moSortOrder; } - void addOrderIndices(std::vector<SCCOLROW> const& rOrder, SCROW firstRow, SCROW lastRow); + void addOrderIndices(SortOrderInfo const& rSortInfo); }; } diff --git a/sc/inc/sortparam.hxx b/sc/inc/sortparam.hxx index 1dd105b6d9be..40c8d69dd9c1 100644 --- a/sc/inc/sortparam.hxx +++ b/sc/inc/sortparam.hxx @@ -49,6 +49,15 @@ struct ScSortKeyState bool bAscending; ScColorSortMode aColorSortMode; Color aColorSortColor; + + bool operator==(const ScSortKeyState& rOther) const + { + return nField == rOther.nField + && bDoSort == rOther.bDoSort + && bAscending == rOther.bAscending + && aColorSortMode == rOther.aColorSortMode + && aColorSortColor == rOther.aColorSortColor; + } }; /** Struct to hold non-data extended area, used with diff --git a/sc/qa/unit/types/SortOrderReverserTest.cxx b/sc/qa/unit/types/SortOrderReverserTest.cxx index 996d4f4b865f..2cac807f1ea6 100644 --- a/sc/qa/unit/types/SortOrderReverserTest.cxx +++ b/sc/qa/unit/types/SortOrderReverserTest.cxx @@ -23,7 +23,7 @@ CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testUnsort) // Unchanged order - output rows should be the same as input { sc::SortOrderReverser aReverser; - aReverser.addOrderIndices({ 1, 2, 3, 4 }, 5, 8); + aReverser.addOrderIndices({ 5, 8, { 1, 2, 3, 4 }, {} }); CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(5)); CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.unsort(6)); @@ -34,7 +34,7 @@ CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testUnsort) // Reversed order - output rows should be in reverse order than input { sc::SortOrderReverser aReverser; - aReverser.addOrderIndices({ 4, 3, 2, 1 }, 5, 8); + aReverser.addOrderIndices({ 5, 8, { 4, 3, 2, 1 }, {} }); CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.unsort(5)); CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.unsort(6)); @@ -45,7 +45,7 @@ CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testUnsort) // Some random order - output rows should follow the order { sc::SortOrderReverser aReverser; - aReverser.addOrderIndices({ 3, 1, 4, 2 }, 5, 8); + aReverser.addOrderIndices({ 5, 8, { 3, 1, 4, 2 }, {} }); CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.unsort(5)); CPPUNIT_ASSERT_EQUAL(SCROW(5), aReverser.unsort(6)); @@ -59,10 +59,10 @@ CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testCombiningSortOrder) sc::SortOrderReverser aReverser; // first sorting order - aReverser.addOrderIndices({ 3, 1, 4, 2 }, 5, 8); + aReverser.addOrderIndices({ 5, 8, { 3, 1, 4, 2 }, {} }); // second sorting order - only reverses the order - aReverser.addOrderIndices({ 4, 3, 2, 1 }, 5, 8); + aReverser.addOrderIndices({ 5, 8, { 4, 3, 2, 1 }, {} }); // check CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.unsort(5)); @@ -72,15 +72,15 @@ CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testCombiningSortOrder) // directly compare the order std::vector<SCCOLROW> aExpectedOrder{ 2, 4, 1, 3 }; - CPPUNIT_ASSERT( - std::equal(aExpectedOrder.begin(), aExpectedOrder.end(), aReverser.maOrder.begin())); + CPPUNIT_ASSERT(std::equal(aExpectedOrder.begin(), aExpectedOrder.end(), + aReverser.maSortInfo.maOrder.begin())); } CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testResort) { { sc::SortOrderReverser aReverser; - aReverser.addOrderIndices({ 4, 3, 2, 1 }, 5, 8); + aReverser.addOrderIndices({ 5, 8, { 4, 3, 2, 1 }, {} }); CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.resort(5)); CPPUNIT_ASSERT_EQUAL(SCROW(7), aReverser.resort(6)); @@ -90,7 +90,7 @@ CPPUNIT_TEST_FIXTURE(SortOrderReverserTest, testResort) { sc::SortOrderReverser aReverser; - aReverser.addOrderIndices({ 3, 1, 4, 2 }, 5, 8); + aReverser.addOrderIndices({ 5, 8, { 3, 1, 4, 2 }, {} }); CPPUNIT_ASSERT_EQUAL(SCROW(6), aReverser.resort(5)); CPPUNIT_ASSERT_EQUAL(SCROW(8), aReverser.resort(6)); diff --git a/sc/source/core/data/SheetView.cxx b/sc/source/core/data/SheetView.cxx index b944b325e9d3..a5778259252b 100644 --- a/sc/source/core/data/SheetView.cxx +++ b/sc/source/core/data/SheetView.cxx @@ -12,38 +12,49 @@ namespace sc { -void SortOrderReverser::addOrderIndices(std::vector<SCCOLROW> const& rOrder, SCROW firstRow, - SCROW lastRow) +void SortOrderReverser::addOrderIndices(SortOrderInfo const& rSortInfo) { - mnFirstRow = firstRow; - mnLastRow = lastRow; + bool bKeyStatesEqual = std::equal(rSortInfo.maKeyStates.begin(), rSortInfo.maKeyStates.begin(), + maSortInfo.maKeyStates.begin()); - if (maOrder.empty()) + if (bKeyStatesEqual && maSortInfo.mnFirstRow == rSortInfo.mnFirstRow + && maSortInfo.mnLastRow == rSortInfo.mnLastRow) { - maOrder = rOrder; + if (maSortInfo.maOrder.empty()) + { + // just set the order - no need to merge + maSortInfo.maOrder = rSortInfo.maOrder; + } + else + { + // merge the order + size_t nOrderSize = maSortInfo.maOrder.size(); + assert(nOrderSize == rSortInfo.maOrder.size()); + + std::vector<SCCOLROW> aNewOrder(nOrderSize); + for (size_t nIndex = 0; nIndex < nOrderSize; ++nIndex) + { + size_t nSortedIndex = rSortInfo.maOrder[nIndex]; + aNewOrder[nIndex] = maSortInfo.maOrder[nSortedIndex - 1]; + } + maSortInfo.maOrder = aNewOrder; + } } else { - assert(maOrder.size() == rOrder.size()); - std::vector<SCCOLROW> newOrder(maOrder.size()); - for (size_t nIndex = 0; nIndex < maOrder.size(); ++nIndex) - { - size_t nSortedIndex = rOrder[nIndex]; - newOrder[nIndex] = maOrder[nSortedIndex - 1]; - } - maOrder = newOrder; + maSortInfo = rSortInfo; } } SCROW SortOrderReverser::unsort(SCROW nRow) const { - if (maOrder.empty()) + if (maSortInfo.maOrder.empty()) return nRow; - if (nRow >= mnFirstRow && nRow <= mnLastRow) + if (nRow >= maSortInfo.mnFirstRow && nRow <= maSortInfo.mnLastRow) { - size_t index = nRow - mnFirstRow; - auto nUnsortedRow = mnFirstRow + maOrder[index] - 1; + size_t index = nRow - maSortInfo.mnFirstRow; + auto nUnsortedRow = maSortInfo.mnFirstRow + maSortInfo.maOrder[index] - 1; return nUnsortedRow; } return nRow; @@ -51,16 +62,16 @@ SCROW SortOrderReverser::unsort(SCROW nRow) const SCROW SortOrderReverser::resort(SCROW nRow) const { - if (maOrder.empty()) + if (maSortInfo.maOrder.empty()) return nRow; - if (nRow >= mnFirstRow && nRow <= mnLastRow) + if (nRow >= maSortInfo.mnFirstRow && nRow <= maSortInfo.mnLastRow) { - SCCOLROW nOrderValue = nRow - mnFirstRow + 1; - for (size_t nIndex = 0; nIndex < maOrder.size(); ++nIndex) + SCCOLROW nOrderValue = nRow - maSortInfo.mnFirstRow + 1; + for (size_t nIndex = 0; nIndex < maSortInfo.maOrder.size(); ++nIndex) { - if (maOrder[nIndex] == nOrderValue) - return mnFirstRow + nIndex; + if (maSortInfo.maOrder[nIndex] == nOrderValue) + return maSortInfo.mnFirstRow + nIndex; } } return nRow; @@ -81,11 +92,11 @@ SCTAB SheetView::getTableNumber() const return mpTable->GetTab(); } -void SheetView::addOrderIndices(std::vector<SCCOLROW> const& rOrder, SCROW firstRow, SCROW lastRow) +void SheetView::addOrderIndices(SortOrderInfo const& rSortInfo) { if (!moSortOrder) moSortOrder.emplace(); - moSortOrder->addOrderIndices(rOrder, firstRow, lastRow); + moSortOrder->addOrderIndices(rSortInfo); } } diff --git a/sc/source/core/data/SheetViewManager.cxx b/sc/source/core/data/SheetViewManager.cxx index f021a26ba306..ae0bb6892258 100644 --- a/sc/source/core/data/SheetViewManager.cxx +++ b/sc/source/core/data/SheetViewManager.cxx @@ -130,12 +130,11 @@ OUString SheetViewManager::generateName() OUString SheetViewManager::defaultViewName() { return ScResId(STR_SHEET_VIEW_DEFAULT_VIEW_NAME); } -void SheetViewManager::addOrderIndices(std::vector<SCCOLROW> const& rOrder, SCROW nFirstRow, - SCROW nLastRow) +void SheetViewManager::addOrderIndices(SortOrderInfo const& rSortInfo) { if (!moSortOrder) moSortOrder.emplace(); - moSortOrder->addOrderIndices(rOrder, nFirstRow, nLastRow); + moSortOrder->addOrderIndices(rSortInfo); } } diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index 2341b6ea891e..cb804219971d 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -1757,14 +1757,26 @@ void ScTable::Sort( bool bAutoFilter = GetDoc().HasAutoFilter(rSortParam.nCol1, nRow1, GetTab()); if (bAutoFilter) { - if (IsSheetViewHolder()) + sc::SortOrderInfo aSortOrderInfo; + + for (auto& rState : aSortParam.maKeyState) { - auto pSheetView = mpSheetViewFor->GetSheetViewManager()->get(mnSheetViewID); - pSheetView->addOrderIndices(pArray->GetOrderIndices(), nRow1, nLastRow); + if (rState.bDoSort) + aSortOrderInfo.maKeyStates.push_back(rState); } - else + + aSortOrderInfo.mnFirstRow = nRow1; + aSortOrderInfo.mnLastRow = nLastRow; + aSortOrderInfo.maOrder = pArray->GetOrderIndices(); + + if (IsSheetViewHolder() && GetDefaultViewTable()) + { + auto pSheetView = GetDefaultViewTable()->GetSheetViewManager()->get(mnSheetViewID); + pSheetView->addOrderIndices(aSortOrderInfo); + } + else if (GetSheetViewManager()) { - GetSheetViewManager()->addOrderIndices(pArray->GetOrderIndices(), nRow1, nLastRow); + GetSheetViewManager()->addOrderIndices(aSortOrderInfo); } } }
