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);
                 }
             }
         }

Reply via email to