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;