sc/inc/sortparam.hxx                  |    9 +++
 sc/inc/strings.hrc                    |    1 
 sc/inc/table.hxx                      |    3 +
 sc/qa/uitest/autofilter/autofilter.py |    1 
 sc/qa/uitest/autofilter2/tdf126306.py |    3 +
 sc/qa/uitest/autofilter2/tdf141559.py |    4 +
 sc/qa/uitest/autofilter2/tdf46184.py  |    1 
 sc/qa/uitest/autofilter2/tdf68113.py  |    2 
 sc/qa/unit/ucalc_sort.cxx             |   21 +++++++
 sc/source/core/data/column3.cxx       |   63 +--------------------
 sc/source/core/data/table3.cxx        |   31 ++++++++++
 sc/source/core/data/table5.cxx        |   63 +++++++++++++++++++++
 sc/source/ui/dbgui/tpsort.cxx         |    2 
 sc/source/ui/view/gridwin.cxx         |  102 +++++++++++++++++++++++++++++++---
 14 files changed, 238 insertions(+), 68 deletions(-)

New commits:
commit bb5e03681c576bc108c1e5c819957f1b34f80ca7
Author:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
AuthorDate: Wed Apr 26 15:46:26 2023 +0200
Commit:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
CommitDate: Mon May 8 08:14:42 2023 +0200

    tdf#95520 Autofilter: Sort by color
    
    Change-Id: I2c1455cc2c741d16f09eccee0bf489f8990684f7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151064
    Tested-by: Jenkins
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>

diff --git a/sc/inc/sortparam.hxx b/sc/inc/sortparam.hxx
index 63d83e2c0595..94817b862b3e 100644
--- a/sc/inc/sortparam.hxx
+++ b/sc/inc/sortparam.hxx
@@ -24,17 +24,26 @@
 #include <vector>
 
 #include "address.hxx"
+#include <editeng/colritem.hxx>
 #include <com/sun/star/lang/Locale.hpp>
 #include "scdllapi.h"
 
 struct ScSubTotalParam;
 struct ScQueryParam;
 
+enum class ScColorSortMode {
+    None,
+    TextColor,
+    BackgroundColor
+};
+
 struct ScSortKeyState
 {
     SCCOLROW nField;
     bool     bDoSort;
     bool     bAscending;
+    ScColorSortMode aColorSortMode;
+    Color    aColorSortColor;
 };
 
 /** Struct to hold non-data extended area, used with
diff --git a/sc/inc/strings.hrc b/sc/inc/strings.hrc
index 6c85b3d617da..cfc1eae6f7c2 100644
--- a/sc/inc/strings.hrc
+++ b/sc/inc/strings.hrc
@@ -43,6 +43,7 @@
 #define SCSTR_FILTER_BACKGROUND_COLOR_COND          
NC_("STANDARDFILTERDIALOG_COND", "Background color")
 #define SCSTR_FILTER_NO_FILL                        
NC_("SCSTR_FILTER_NO_FILL", "No Fill")
 #define SCSTR_FILTER_AUTOMATIC_COLOR                
NC_("SCSTR_FILTER_AUTOMATIC_COLOR", "Automatic")
+#define SCSTR_SORT_COLOR                            NC_("SCSTR_SORT_COLOR", 
"Sort by Color")
 #define SCSTR_NONAME                                NC_("SCSTR_NONAME", 
"unnamed")
 #define SCSTR_INSERT_RTL                            NC_("SCSTR_INSERT_RTL", 
"Shift cells left")
 // "%1 is replaced to column letter, such as 'Column A'"
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index cbce92da3998..a2cc60f9d70e 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -990,6 +990,9 @@ public:
     SCROW       LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const;
     SCROW       CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow) const;
 
+    Color GetCellBackgroundColor(ScAddress aPos) const;
+    Color GetCellTextColor(ScAddress aPos) const;
+
     bool IsManualRowHeight(SCROW nRow) const;
 
     bool HasUniformRowHeight( SCROW nRow1, SCROW nRow2 ) const;
diff --git a/sc/qa/uitest/autofilter/autofilter.py 
b/sc/qa/uitest/autofilter/autofilter.py
index 8ffba26539a5..fbf46cc5d397 100644
--- a/sc/qa/uitest/autofilter/autofilter.py
+++ b/sc/qa/uitest/autofilter/autofilter.py
@@ -476,6 +476,7 @@ class AutofilterTest(UITestCase):
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
+            xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"}))
             xSubFloatWindow = self.xUITest.getFloatWindow()
             xSubMenu = xSubFloatWindow.getChild("menu")
diff --git a/sc/qa/uitest/autofilter2/tdf126306.py 
b/sc/qa/uitest/autofilter2/tdf126306.py
index 51c099a3f3c2..2ebb3789bf8f 100644
--- a/sc/qa/uitest/autofilter2/tdf126306.py
+++ b/sc/qa/uitest/autofilter2/tdf126306.py
@@ -81,6 +81,7 @@ class tdf126306(UITestCase):
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
+            xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"}))
             xSubFloatWindow = self.xUITest.getFloatWindow()
             xSubMenu = xSubFloatWindow.getChild("menu")
@@ -107,6 +108,7 @@ class tdf126306(UITestCase):
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
+            xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"}))
             xSubFloatWindow = self.xUITest.getFloatWindow()
             xSubMenu = xSubFloatWindow.getChild("menu")
@@ -129,6 +131,7 @@ class tdf126306(UITestCase):
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
+            xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"}))
             xSubFloatWindow = self.xUITest.getFloatWindow()
             xSubMenu = xSubFloatWindow.getChild("menu")
diff --git a/sc/qa/uitest/autofilter2/tdf141559.py 
b/sc/qa/uitest/autofilter2/tdf141559.py
index e4eba12056b0..37068ccec0ba 100644
--- a/sc/qa/uitest/autofilter2/tdf141559.py
+++ b/sc/qa/uitest/autofilter2/tdf141559.py
@@ -38,6 +38,7 @@ class tdf141559(UITestCase):
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
+            xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"}))
             xSubFloatWindow = self.xUITest.getFloatWindow()
             xSubMenu = xSubFloatWindow.getChild("menu")
@@ -76,13 +77,14 @@ class tdf141559(UITestCase):
 
             # check last item: 'Clear Filter'
             nLastIdx = int(get_state_as_dict(xMenu)['Children']) - 1
-            self.assertEqual(5, nLastIdx)
+            self.assertEqual(6, nLastIdx)
             self.assertEqual('Clear Filter', 
get_state_as_dict(xMenu.getChild(str(nLastIdx)))['Text'])
 
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
+            xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             # Use new menu item "Clear Filter" to remove the standard filter 
condition
             self.assertEqual("Clear Filter", 
get_state_as_dict(xMenu)['SelectEntryText'])
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"}))
diff --git a/sc/qa/uitest/autofilter2/tdf46184.py 
b/sc/qa/uitest/autofilter2/tdf46184.py
index 87908b833507..508346321e73 100755
--- a/sc/qa/uitest/autofilter2/tdf46184.py
+++ b/sc/qa/uitest/autofilter2/tdf46184.py
@@ -36,6 +36,7 @@ class tdf46184(UITestCase):
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
+            xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"}))
             xSubFloatWindow = self.xUITest.getFloatWindow()
             xSubMenu = xSubFloatWindow.getChild("menu")
diff --git a/sc/qa/uitest/autofilter2/tdf68113.py 
b/sc/qa/uitest/autofilter2/tdf68113.py
index 74c35d65b665..2f10d16ad70b 100644
--- a/sc/qa/uitest/autofilter2/tdf68113.py
+++ b/sc/qa/uitest/autofilter2/tdf68113.py
@@ -36,6 +36,7 @@ class tdf68113(UITestCase):
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
+            xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"}))
             xSubFloatWindow = self.xUITest.getFloatWindow()
             xSubMenu = xSubFloatWindow.getChild("menu")
@@ -60,6 +61,7 @@ class tdf68113(UITestCase):
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
+            xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"DOWN"}))
             xMenu.executeAction("TYPE", mkPropertyValues({"KEYCODE":"RETURN"}))
             xSubFloatWindow = self.xUITest.getFloatWindow()
             xSubMenu = xSubFloatWindow.getChild("menu")
diff --git a/sc/qa/unit/ucalc_sort.cxx b/sc/qa/unit/ucalc_sort.cxx
index 8d7b672926ef..f2cd7d2d149b 100644
--- a/sc/qa/unit/ucalc_sort.cxx
+++ b/sc/qa/unit/ucalc_sort.cxx
@@ -75,6 +75,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSort)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 1;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
 
     m_pDoc->Sort(0, aSortData, false, true, nullptr, nullptr);
 
@@ -176,6 +177,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortHorizontal)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
     CPPUNIT_ASSERT(bSorted);
 
@@ -243,6 +245,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, 
testSortHorizontalWholeColumn)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
     CPPUNIT_ASSERT(bSorted);
 
@@ -304,6 +307,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortSingleRow)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
 
     // Do the sorting.  This should not crash.
     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
@@ -417,6 +421,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortWithFormulaRefs)
     aSortData.nRow2 = 7;
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
 
     m_pDoc->Sort(0, aSortData, false, true, nullptr, nullptr);
 
@@ -452,6 +457,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortWithStrings)
     aParam.maKeyState[0].bDoSort = true;
     aParam.maKeyState[0].bAscending = true;
     aParam.maKeyState[0].nField = 1;
+    aParam.maKeyState[0].aColorSortMode = ScColorSortMode::None;
 
     m_pDoc->Sort(0, aParam, false, true, nullptr, nullptr);
 
@@ -505,6 +511,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortInFormulaGroup)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
 
     m_pDoc->Sort(0, aSortData, false, true, nullptr, nullptr);
 
@@ -672,6 +679,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortWithCellFormats)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
     bool bSorted = aFunc.Sort(0, aSortData, true, false, true);
     CPPUNIT_ASSERT(bSorted);
 
@@ -741,6 +749,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortRefUpdate)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
     CPPUNIT_ASSERT(bSorted);
 
@@ -892,6 +901,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortRefUpdate2)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
     CPPUNIT_ASSERT(bSorted);
 
@@ -977,6 +987,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortRefUpdate3)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
     CPPUNIT_ASSERT(bSorted);
 
@@ -1105,6 +1116,7 @@ void TestSort::testSortRefUpdate4_Impl()
         aSortData.maKeyState[0].bDoSort = true;         // sort on
         aSortData.maKeyState[0].nField = 3;             // Average
         aSortData.maKeyState[0].bAscending = false;     // descending
+        aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
 
         m_pDoc->SetAnonymousDBData( 0, std::unique_ptr<ScDBData>(new ScDBData( 
STR_DB_LOCAL_NONAME, aSortRange.aStart.Tab(),
                     aSortData.nCol1, aSortData.nRow1, aSortData.nCol2, 
aSortData.nRow2)));
@@ -1176,6 +1188,7 @@ void TestSort::testSortRefUpdate4_Impl()
         aSortData.maKeyState[0].bDoSort = true;         // sort on
         aSortData.maKeyState[0].nField = 0;             // Name
         aSortData.maKeyState[0].bAscending = false;     // descending
+        aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
 
         m_pDoc->SetAnonymousDBData( 0, std::unique_ptr<ScDBData>(new ScDBData( 
STR_DB_LOCAL_NONAME, aSortRange.aStart.Tab(),
                     aSortData.nCol1, aSortData.nRow1, aSortData.nCol2, 
aSortData.nRow2)));
@@ -1281,6 +1294,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortRefUpdate5)
     aSortData.maKeyState[0].bDoSort = true;         // sort on
     aSortData.maKeyState[0].nField = 0;             // Date
     aSortData.maKeyState[0].bAscending = true;      // ascending
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
     CPPUNIT_ASSERT(bSorted);
 
@@ -1376,6 +1390,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortRefUpdate6)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
     CPPUNIT_ASSERT(bSorted);
 
@@ -1512,6 +1527,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortBroadcaster)
         aSortData.maKeyState[0].bDoSort = true;
         aSortData.maKeyState[0].nField = 0;
         aSortData.maKeyState[0].bAscending = false;
+        aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
         bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
         CPPUNIT_ASSERT(bSorted);
 
@@ -1609,6 +1625,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortBroadcaster)
         aSortData.maKeyState[0].bDoSort = true;
         aSortData.maKeyState[0].nField = 0;
         aSortData.maKeyState[0].bAscending = false;
+        aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
         bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
         CPPUNIT_ASSERT(bSorted);
 
@@ -1712,6 +1729,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, 
testSortBroadcastBroadcaster)
         aSortData.maKeyState[0].bDoSort = true;
         aSortData.maKeyState[0].nField = 0;
         aSortData.maKeyState[0].bAscending = false;
+        aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
         bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
         CPPUNIT_ASSERT(bSorted);
 
@@ -1782,6 +1800,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortOutOfPlaceResult)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
     CPPUNIT_ASSERT(bSorted);
 
@@ -1858,6 +1877,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, 
testSortPartialFormulaGroup)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
     CPPUNIT_ASSERT(bSorted);
 
@@ -1927,6 +1947,7 @@ CPPUNIT_TEST_FIXTURE(TestSort, testSortImages)
     aSortData.maKeyState[0].bDoSort = true;
     aSortData.maKeyState[0].nField = 0;
     aSortData.maKeyState[0].bAscending = true;
+    aSortData.maKeyState[0].aColorSortMode = ScColorSortMode::None;
 
     m_pDoc->Sort(0, aSortData, false, true, nullptr, nullptr);
 
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index c6051674bec1..0c834b85bb40 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -46,6 +46,7 @@
 #include <filterentries.hxx>
 #include <conditio.hxx>
 #include <colorscale.hxx>
+#include <table.hxx>
 #include <editeng/brushitem.hxx>
 #include <editeng/colritem.hxx>
 
@@ -2574,65 +2575,9 @@ class FilterEntriesHandler
 
         // Colors
         ScAddress aPos(rColumn.GetCol(), nRow, rColumn.GetTab());
-
-        Color backgroundColor;
-        bool bHasConditionalBackgroundColor = false;
-
-        Color textColor;
-        bool bHasConditionalTextColor = false;
-        // Check text & background color from cond. formatting
-        const ScPatternAttr* pPattern
-            = mrColumn.GetDoc().GetPattern(aPos.Col(), aPos.Row(), aPos.Tab());
-        if (pPattern)
-        {
-            if 
(!pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData().empty())
-            {
-                const SfxItemSet* pCondSet
-                    = mrColumn.GetDoc().GetCondResult(aPos.Col(), aPos.Row(), 
aPos.Tab());
-                const SvxColorItem* pColor = 
&pPattern->GetItem(ATTR_FONT_COLOR, pCondSet);
-                textColor = pColor->GetValue();
-                bHasConditionalTextColor = true;
-
-                const SvxBrushItem* pBackgroundColor = 
&pPattern->GetItem(ATTR_BACKGROUND, pCondSet);
-                backgroundColor = pBackgroundColor->GetColor();
-                bHasConditionalBackgroundColor = true;
-            }
-        }
-
-        if (!bHasConditionalTextColor)
-        {
-            const SvxColorItem* pColor = rColumn.GetDoc().GetAttr(aPos, 
ATTR_FONT_COLOR);
-            textColor = pColor->GetValue();
-        }
-        mrFilterEntries.addTextColor(textColor);
-
-        // Color scale needs a different handling
-        ScConditionalFormat* pCondFormat
-            = rColumn.GetDoc().GetCondFormat(aPos.Col(), aPos.Row(), 
aPos.Tab());
-        if (pCondFormat)
-        {
-            for (size_t i = 0; i < pCondFormat->size(); i++)
-            {
-                auto aEntry = pCondFormat->GetEntry(i);
-                if (aEntry->GetType() == ScFormatEntry::Type::Colorscale)
-                {
-                    const ScColorScaleFormat* pColFormat
-                        = static_cast<const ScColorScaleFormat*>(aEntry);
-                    std::optional<Color> oColor = pColFormat->GetColor(aPos);
-                    if (oColor)
-                    {
-                        backgroundColor = *oColor;
-                        bHasConditionalBackgroundColor = true;
-                    }
-                }
-            }
-        }
-        if (!bHasConditionalBackgroundColor)
-        {
-            const SvxBrushItem* pBrush = rColumn.GetDoc().GetAttr(aPos, 
ATTR_BACKGROUND);
-            backgroundColor = pBrush->GetColor();
-        }
-        mrFilterEntries.addBackgroundColor(backgroundColor);
+        ScTable* pTable = rColumn.GetDoc().FetchTable(rColumn.GetTab());
+        mrFilterEntries.addTextColor(pTable->GetCellTextColor(aPos));
+        
mrFilterEntries.addBackgroundColor(pTable->GetCellBackgroundColor(aPos));
 
         if (rCell.hasString())
         {
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index a535726fd8fc..f0a55b478c0c 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1531,6 +1531,37 @@ short ScTable::CompareCell(
 
     CellType eType1 = rCell1.getType(), eType2 = rCell2.getType();
 
+    // tdf#95520 Sort by color - selected color goes on top, everything else 
according to compare function
+    if (aSortParam.maKeyState[nSort].aColorSortMode == 
ScColorSortMode::TextColor
+        || aSortParam.maKeyState[nSort].aColorSortMode == 
ScColorSortMode::BackgroundColor)
+    {
+        ScAddress aPos1(nCell1Col, nCell1Row, GetTab());
+        ScAddress aPos2(nCell2Col, nCell2Row, GetTab());
+        Color aTheChosenColor = aSortParam.maKeyState[nSort].aColorSortColor;
+        Color aColor1;
+        Color aColor2;
+        if (aSortParam.maKeyState[nSort].aColorSortMode == 
ScColorSortMode::TextColor)
+        {
+            aColor1 = GetCellTextColor(aPos1);
+            aColor2 = GetCellTextColor(aPos2);
+        }
+        else
+        {
+            aColor1 = GetCellBackgroundColor(aPos1);
+            aColor2 = GetCellBackgroundColor(aPos2);
+        }
+        if (aTheChosenColor == aColor1)
+            return -1;
+        if (aTheChosenColor == aColor2)
+            return 1;
+        if (aColor1 == aColor2)
+            return 0;
+        if (aColor1 > aColor2)
+            return 1;
+        if (aColor1 < aColor2)
+            return -1;
+    }
+
     if (!rCell1.isEmpty())
     {
         if (!rCell2.isEmpty())
diff --git a/sc/source/core/data/table5.cxx b/sc/source/core/data/table5.cxx
index 69345ad42989..be866aa634ea 100644
--- a/sc/source/core/data/table5.cxx
+++ b/sc/source/core/data/table5.cxx
@@ -37,9 +37,13 @@
 #include <bcaslot.hxx>
 #include <compressedarray.hxx>
 #include <userdat.hxx>
+#include <conditio.hxx>
+#include <colorscale.hxx>
 
 #include <com/sun/star/sheet/TablePageBreakData.hpp>
 
+#include <editeng/brushitem.hxx>
+#include <editeng/colritem.hxx>
 #include <osl/diagnose.h>
 
 #include <algorithm>
@@ -1043,6 +1047,65 @@ SCROW ScTable::CountNonFilteredRows(SCROW nStartRow, 
SCROW nEndRow) const
     return nCount;
 }
 
+Color ScTable::GetCellBackgroundColor(ScAddress aPos) const
+{
+    Color backgroundColor;
+    bool bHasConditionalBackgroundColor = false;
+    // Check background color from cond. formatting
+    const ScPatternAttr* pPattern = GetDoc().GetPattern(aPos.Col(), 
aPos.Row(), aPos.Tab());
+    if (pPattern)
+    {
+        if (!pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData().empty())
+        {
+            const SfxItemSet* pCondSet = GetDoc().GetCondResult(aPos.Col(), 
aPos.Row(), aPos.Tab());
+            const SvxBrushItem* pBackgroundColor = 
&pPattern->GetItem(ATTR_BACKGROUND, pCondSet);
+            backgroundColor = pBackgroundColor->GetColor();
+            bHasConditionalBackgroundColor = true;
+        }
+    }
+
+    // Color scale needs a different handling
+    ScConditionalFormat* pCondFormat = GetDoc().GetCondFormat(aPos.Col(), 
aPos.Row(), aPos.Tab());
+    if (pCondFormat)
+    {
+        for (size_t i = 0; i < pCondFormat->size(); i++)
+        {
+            auto aEntry = pCondFormat->GetEntry(i);
+            if (aEntry->GetType() == ScFormatEntry::Type::Colorscale)
+            {
+                const ScColorScaleFormat* pColFormat
+                    = static_cast<const ScColorScaleFormat*>(aEntry);
+                std::optional<Color> oColor = pColFormat->GetColor(aPos);
+                if (oColor)
+                {
+                    backgroundColor = oColor.value();
+                    bHasConditionalBackgroundColor = true;
+                }
+            }
+        }
+    }
+    return bHasConditionalBackgroundColor ? backgroundColor
+                                          : GetDoc().GetAttr(aPos, 
ATTR_BACKGROUND)->GetColor();
+}
+
+Color ScTable::GetCellTextColor(ScAddress aPos) const
+{
+    // Check text & background color from cond. formatting
+    const ScPatternAttr* pPattern = GetDoc().GetPattern(aPos.Col(), 
aPos.Row(), aPos.Tab());
+    if (pPattern)
+    {
+        if (!pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData().empty())
+        {
+            const SfxItemSet* pCondSet = GetDoc().GetCondResult(aPos.Col(), 
aPos.Row(), aPos.Tab());
+            const SvxColorItem* pColor = &pPattern->GetItem(ATTR_FONT_COLOR, 
pCondSet);
+            return pColor->GetValue();
+        }
+    }
+
+    const SvxColorItem* pColor = GetDoc().GetAttr(aPos, ATTR_FONT_COLOR);
+    return pColor->GetValue();
+}
+
 bool ScTable::IsManualRowHeight(SCROW nRow) const
 {
     return bool(pRowFlags->GetValue(nRow) & CRFlags::ManualSize);
diff --git a/sc/source/ui/dbgui/tpsort.cxx b/sc/source/ui/dbgui/tpsort.cxx
index c137ec4cf898..49390a404f35 100644
--- a/sc/source/ui/dbgui/tpsort.cxx
+++ b/sc/source/ui/dbgui/tpsort.cxx
@@ -392,7 +392,7 @@ sal_uInt16 ScTabPageSortFields::GetFieldSelPos( SCCOLROW 
nField )
 void ScTabPageSortFields::SetLastSortKey( sal_uInt16 nItem )
 {
     // Extend local SortParam copy
-    const ScSortKeyState atempKeyState = { 0, false, true };
+    const ScSortKeyState atempKeyState = { 0, false, true, 
ScColorSortMode::None, Color() };
     aSortData.maKeyState.push_back( atempKeyState );
 
     // Add Sort Key Item
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 1465a7424032..c2ec3311bc9d 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -643,11 +643,75 @@ public:
     }
 };
 
+class AutoFilterSortColorAction : public AutoFilterSubMenuAction
+{
+private:
+    Color m_aColor;
+    ScViewData& m_rViewData;
+
+public:
+    AutoFilterSortColorAction(ScGridWindow* p, ScListSubMenuControl* pSubMenu, 
ScGridWindow::AutoFilterMode eMode, const Color& rColor, ScViewData& rViewData)
+        : AutoFilterSubMenuAction(p, pSubMenu, eMode)
+        , m_aColor(rColor)
+        , m_rViewData(rViewData)
+    {
+    }
+
+    virtual bool execute() override
+    {
+        const AutoFilterData* pData =
+            static_cast<const AutoFilterData*>(m_pSubMenu->getExtendedData());
+
+        if (!pData)
+            return false;
+
+        ScDBData* pDBData = pData->mpData;
+        if (!pDBData)
+            return false;
+
+        const ScAddress& rPos = pData->maPos;
+        SCCOL nCol = rPos.Col();
+        ScSortParam aSortParam;
+        pDBData->GetSortParam(aSortParam);
+        if (nCol < aSortParam.nCol1 || nCol > aSortParam.nCol2)
+            // out of bound
+            return false;
+
+        bool bHasHeader = pDBData->HasHeader();
+
+        aSortParam.bHasHeader = bHasHeader;
+        aSortParam.bByRow = true;
+        aSortParam.bCaseSens = false;
+        aSortParam.bNaturalSort = false;
+        aSortParam.aDataAreaExtras.mbCellNotes = false;
+        aSortParam.aDataAreaExtras.mbCellDrawObjects = true;
+        aSortParam.aDataAreaExtras.mbCellFormats = true;
+        aSortParam.bInplace = true;
+        aSortParam.maKeyState[0].bDoSort = true;
+        aSortParam.maKeyState[0].nField = nCol;
+        aSortParam.maKeyState[0].bAscending = true;
+        aSortParam.maKeyState[0].aColorSortMode = meMode == 
ScGridWindow::AutoFilterMode::TextColor
+                                                      ? 
ScColorSortMode::TextColor
+                                                      : 
ScColorSortMode::BackgroundColor;
+        aSortParam.maKeyState[0].aColorSortColor = m_aColor;
+
+        for (size_t i = 1; i < aSortParam.GetSortKeyCount(); ++i)
+            aSortParam.maKeyState[i].bDoSort = false;
+
+        m_rViewData.GetViewShell()->UISort(aSortParam);
+
+        return true;
+    }
+};
+
 class AutoFilterColorPopupStartAction : public AutoFilterSubMenuAction
 {
+private:
+    bool mbIsFilter;
 public:
-    AutoFilterColorPopupStartAction(ScGridWindow* p, ScListSubMenuControl* 
pSubMenu)
-        : AutoFilterSubMenuAction(p, pSubMenu, 
ScGridWindow::AutoFilterMode::Normal)
+    AutoFilterColorPopupStartAction(ScGridWindow* p, ScListSubMenuControl* 
pSubMenu, bool bIsFilter)
+        : AutoFilterSubMenuAction(p, pSubMenu, 
ScGridWindow::AutoFilterMode::Normal),
+        mbIsFilter(bIsFilter)
     {
     }
 
@@ -748,8 +812,18 @@ public:
                     OUString sText = eMode == 
ScGridWindow::AutoFilterMode::TextColor
                                          ? 
ScResId(SCSTR_FILTER_AUTOMATIC_COLOR)
                                          : ScResId(SCSTR_FILTER_NO_FILL);
-                    m_pSubMenu->addMenuColorItem(sText, bActive, *xDev, nMenu,
-                                                 new 
AutoFilterColorAction(mpWindow, m_pSubMenu, eMode, rColor));
+                    if (mbIsFilter)
+                    {
+                        m_pSubMenu->addMenuColorItem(
+                            sText, bActive, *xDev, nMenu,
+                            new AutoFilterColorAction(mpWindow, m_pSubMenu, 
eMode, rColor));
+                    }
+                    else
+                    {
+                        m_pSubMenu->addMenuColorItem(
+                            sText, bActive, *xDev, nMenu,
+                            new AutoFilterSortColorAction(mpWindow, 
m_pSubMenu, eMode, rColor, rViewData));
+                    }
                 }
                 else
                 {
@@ -769,8 +843,19 @@ public:
                     if (!bFoundColorName)
                         sName = "#" + 
rColor.AsRGBHexString().toAsciiUpperCase();
 
-                    m_pSubMenu->addMenuColorItem(sName, bActive, *xDev, nMenu,
-                                                 new 
AutoFilterColorAction(mpWindow, m_pSubMenu, eMode, rColor));
+                    if (mbIsFilter)
+                    {
+                        m_pSubMenu->addMenuColorItem(
+                            sName, bActive, *xDev, nMenu,
+                            new AutoFilterColorAction(mpWindow, m_pSubMenu, 
eMode, rColor));
+                    }
+                    else
+                    {
+                        m_pSubMenu->addMenuColorItem(
+                            sName, bActive, *xDev, nMenu,
+                            new AutoFilterSortColorAction(mpWindow, 
m_pSubMenu, eMode, rColor,
+                                                          rViewData));
+                    }
                 }
             }
 
@@ -993,8 +1078,10 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW 
nRow)
         ScResId(STR_MENU_SORT_DESC),
         new AutoFilterAction(this, AutoFilterMode::SortDescending));
     mpAutoFilterPopup->addSeparator();
+    if (ScListSubMenuControl* pSubMenu = 
mpAutoFilterPopup->addSubMenuItem(ScResId(SCSTR_SORT_COLOR), true, true))
+        pSubMenu->setPopupStartAction(new 
AutoFilterColorPopupStartAction(this, pSubMenu, false));
     if (ScListSubMenuControl* pSubMenu = 
mpAutoFilterPopup->addSubMenuItem(ScResId(SCSTR_FILTER_COLOR), true, true))
-        pSubMenu->setPopupStartAction(new 
AutoFilterColorPopupStartAction(this, pSubMenu));
+        pSubMenu->setPopupStartAction(new 
AutoFilterColorPopupStartAction(this, pSubMenu, true));
     if (ScListSubMenuControl* pSubMenu = 
mpAutoFilterPopup->addSubMenuItem(ScResId(SCSTR_FILTER_CONDITION), true, false))
     {
         pSubMenu->addMenuItem(
@@ -1086,6 +1173,7 @@ void 
ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode)
             aSortParam.maKeyState[0].bDoSort = true;
             aSortParam.maKeyState[0].nField = nCol;
             aSortParam.maKeyState[0].bAscending = (eMode == 
AutoFilterMode::SortAscending);
+            aSortParam.maKeyState[0].aColorSortMode = ScColorSortMode::None;
 
             for (size_t i = 1; i < aSortParam.GetSortKeyCount(); ++i)
                 aSortParam.maKeyState[i].bDoSort = false;

Reply via email to