sc/inc/colorscale.hxx                          |    6 +-
 sc/inc/fillinfo.hxx                            |    1 
 sc/qa/unit/subsequent_filters_test4.cxx        |   14 +++++
 sc/qa/unit/ucalc_condformat.cxx                |    9 +--
 sc/source/core/data/colorscale.cxx             |   66 ++++++++++++++++++-------
 sc/source/ui/condformat/condformatdlgentry.cxx |   30 ++++-------
 sc/uiconfig/scalc/ui/conditionaliconset.ui     |   11 +++-
 7 files changed, 96 insertions(+), 41 deletions(-)

New commits:
commit fcc5770dd1e33dcb4f4f0c28683569af5d1d8368
Author:     AhmedHamed <ahmedhamed3...@gmail.com>
AuthorDate: Tue Apr 2 19:05:00 2024 +0200
Commit:     Andreas Heinisch <andreas.heini...@yahoo.de>
CommitDate: Mon Apr 22 18:37:01 2024 +0200

    tdf#61313 Replace the static ">=" with a dropdown of different operators
    
    The problem is with conditional formatting using icon set, as the icons 
order is fixed.
    It is solved by using comboBoxes for condition mode in 
ScIconSetFrmtDataEntry for every icon, and adjusting the UI file.
    A function that compares according to the currnt mode is added.
    Related CppunitTest files are updated.
    For every cell, last valid condition is applied.
    
    Change-Id: I489206d349a46092b307203c180705f42883183d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165701
    Tested-by: Jenkins
    Reviewed-by: Heiko Tietze <heiko.tie...@documentfoundation.org>
    Reviewed-by: Andreas Heinisch <andreas.heini...@yahoo.de>

diff --git a/sc/inc/colorscale.hxx b/sc/inc/colorscale.hxx
index 2bb2c8ea5f6a..cbef08b6e05d 100644
--- a/sc/inc/colorscale.hxx
+++ b/sc/inc/colorscale.hxx
@@ -48,11 +48,13 @@ private:
     ScConditionalFormat* mpFormat;
     Color maColor;
     ScColorScaleEntryType meType;
+    ScConditionMode meMode;
 
     void setListener();
 
 public:
-    SC_DLLPUBLIC ScColorScaleEntry(double nVal, const Color& rCol, 
ScColorScaleEntryType eType = COLORSCALE_VALUE);
+    SC_DLLPUBLIC ScColorScaleEntry(double nVal, const Color& rCol, 
ScColorScaleEntryType eType = COLORSCALE_VALUE,
+            ScConditionMode eMode = ScConditionMode::Equal);
     SC_DLLPUBLIC ScColorScaleEntry();
     ScColorScaleEntry(const ScColorScaleEntry& rEntry);
     ScColorScaleEntry(ScDocument* pDoc, const ScColorScaleEntry& rEntry);
@@ -74,7 +76,9 @@ public:
     SC_DLLPUBLIC OUString GetFormula( formula::FormulaGrammar::Grammar 
eGrammar ) const;
 
     ScColorScaleEntryType GetType() const { return meType;}
+    ScConditionMode GetMode() const { return meMode; }
     SC_DLLPUBLIC void SetType( ScColorScaleEntryType eType );
+    SC_DLLPUBLIC void SetMode( ScConditionMode eMode ) { meMode = eMode; }
 
     void SetRepaintCallback(ScConditionalFormat* pParent);
     void SetRepaintCallback(const std::function<void()>& func);
diff --git a/sc/inc/fillinfo.hxx b/sc/inc/fillinfo.hxx
index caecd6a7072b..e9c713373724 100644
--- a/sc/inc/fillinfo.hxx
+++ b/sc/inc/fillinfo.hxx
@@ -92,6 +92,7 @@ struct ScIconSetInfo
 {
     sal_Int32 nIconIndex;
     ScIconSetType eIconSetType;
+    ScConditionMode eConditionMode;
     tools::Long mnHeight = 0;
     bool mbShowValue;
 };
diff --git a/sc/qa/unit/subsequent_filters_test4.cxx 
b/sc/qa/unit/subsequent_filters_test4.cxx
index e7bced8a313f..1adab95122e2 100644
--- a/sc/qa/unit/subsequent_filters_test4.cxx
+++ b/sc/qa/unit/subsequent_filters_test4.cxx
@@ -864,6 +864,17 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest4, 
testCondFormatThemeColor3XLSX)
 
 namespace
 {
+// This function is used temporarily so we don't have to update test files.
+void convertToOldCondFormat(const ScIconSetFormat* pIconSet)
+{
+    auto itr = pIconSet->begin();
+    (*itr)->SetMode(ScConditionMode::Less);
+    (*itr)->SetValue((*(itr + 1))->GetValue());
+    (*itr)->SetType((*(++itr))->GetType());
+    for (; itr != pIconSet->end(); ++itr)
+        (*itr)->SetMode(ScConditionMode::EqGreater);
+}
+
 void testComplexIconSetsXLSX_Impl(const ScDocument& rDoc, SCCOL nCol, 
ScIconSetType eType)
 {
     ScConditionalFormat* pFormat = rDoc.GetCondFormat(nCol, 1, 0);
@@ -886,6 +897,7 @@ void testCustomIconSetsXLSX_Impl(const ScDocument& rDoc, 
SCCOL nCol, SCROW nRow,
     CPPUNIT_ASSERT(pEntry);
     CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::Iconset, pEntry->GetType());
     const ScIconSetFormat* pIconSet = static_cast<const 
ScIconSetFormat*>(pEntry);
+    convertToOldCondFormat(pIconSet);
     std::unique_ptr<ScIconSetInfo> 
pInfo(pIconSet->GetIconSetInfo(ScAddress(nCol, nRow, 1)));
     if (nIndex == -1)
         CPPUNIT_ASSERT(!pInfo);
@@ -934,6 +946,7 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testTdf101104)
     CPPUNIT_ASSERT(pEntry);
     CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::Iconset, pEntry->GetType());
     const ScIconSetFormat* pIconSet = static_cast<const 
ScIconSetFormat*>(pEntry);
+    convertToOldCondFormat(pIconSet);
 
     for (size_t i = 1; i < 10; ++i)
     {
@@ -960,6 +973,7 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest4, testTdf64401)
     CPPUNIT_ASSERT(pEntry);
     CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::Iconset, pEntry->GetType());
     const ScIconSetFormat* pIconSet = static_cast<const 
ScIconSetFormat*>(pEntry);
+    convertToOldCondFormat(pIconSet);
 
     for (size_t i = 0; i < 10; ++i)
     {
diff --git a/sc/qa/unit/ucalc_condformat.cxx b/sc/qa/unit/ucalc_condformat.cxx
index c4dd685c41a8..b38632743f65 100644
--- a/sc/qa/unit/ucalc_condformat.cxx
+++ b/sc/qa/unit/ucalc_condformat.cxx
@@ -731,9 +731,9 @@ CPPUNIT_TEST_FIXTURE(TestCondformat, testIconSet)
 
     ScIconSetFormat* pEntry = new ScIconSetFormat(m_pDoc);
     ScIconSetFormatData* pData = new ScIconSetFormatData;
-    pData->m_Entries.emplace_back(new ScColorScaleEntry(0, COL_BLUE));
-    pData->m_Entries.emplace_back(new ScColorScaleEntry(1, COL_GREEN));
-    pData->m_Entries.emplace_back(new ScColorScaleEntry(2, COL_RED));
+    pData->m_Entries.emplace_back(new ScColorScaleEntry(0, COL_BLUE, 
COLORSCALE_VALUE, ScConditionMode::EqGreater));
+    pData->m_Entries.emplace_back(new ScColorScaleEntry(1, COL_GREEN, 
COLORSCALE_VALUE, ScConditionMode::EqGreater));
+    pData->m_Entries.emplace_back(new ScColorScaleEntry(2, COL_RED, 
COLORSCALE_VALUE, ScConditionMode::Equal));
     pEntry->SetIconSetData(pData);
 
     m_pDoc->AddCondFormatData(pFormat->GetRange(), 0, 1);
@@ -742,11 +742,10 @@ CPPUNIT_TEST_FIXTURE(TestCondformat, testIconSet)
     static struct {
         double nVal; sal_Int32 nIndex;
     } const aTests[] = {
-        { -1.0, 0 },
         { 0.0, 0 },
         { 1.0, 1 },
         { 2.0, 2 },
-        { 3.0, 2 }
+        { 3.0, 1 }
     };
     for(size_t i = 0; i < SAL_N_ELEMENTS(aTests); ++i)
     {
diff --git a/sc/source/core/data/colorscale.cxx 
b/sc/source/core/data/colorscale.cxx
index 415dde5872e5..963ee78c05d3 100644
--- a/sc/source/core/data/colorscale.cxx
+++ b/sc/source/core/data/colorscale.cxx
@@ -154,15 +154,17 @@ bool ScFormulaListener::NeedsRepaint() const
 ScColorScaleEntry::ScColorScaleEntry():
     mnVal(0),
     mpFormat(nullptr),
-    meType(COLORSCALE_VALUE)
+    meType(COLORSCALE_VALUE),
+    meMode(ScConditionMode::Equal)
 {
 }
 
-ScColorScaleEntry::ScColorScaleEntry(double nVal, const Color& rCol, 
ScColorScaleEntryType eType):
+ScColorScaleEntry::ScColorScaleEntry(double nVal, const Color& rCol, 
ScColorScaleEntryType eType, ScConditionMode eMode):
     mnVal(nVal),
     mpFormat(nullptr),
     maColor(rCol),
-    meType(eType)
+    meType(eType),
+    meMode(eMode)
 {
 }
 
@@ -170,7 +172,8 @@ ScColorScaleEntry::ScColorScaleEntry(const 
ScColorScaleEntry& rEntry):
     mnVal(rEntry.mnVal),
     mpFormat(rEntry.mpFormat),
     maColor(rEntry.maColor),
-    meType(rEntry.meType)
+    meType(rEntry.meType),
+    meMode(rEntry.meMode)
 {
     setListener();
     if(rEntry.mpCell)
@@ -185,7 +188,8 @@ ScColorScaleEntry::ScColorScaleEntry(ScDocument* pDoc, 
const ScColorScaleEntry&
     mnVal(rEntry.mnVal),
     mpFormat(rEntry.mpFormat),
     maColor(rEntry.maColor),
-    meType(rEntry.meType)
+    meType(rEntry.meType),
+    meMode(rEntry.meMode)
 {
     setListener();
     if(rEntry.mpCell)
@@ -1066,6 +1070,30 @@ void ScDataBarFormat::EnsureSize()
     }
 }
 
+static bool Compare(double nVal1, double nVal2, const 
ScIconSetFormat::const_iterator& itr)
+{
+    switch ((*itr)->GetMode())
+    {
+        case ScConditionMode::Equal:
+            return nVal1 == nVal2;
+        case ScConditionMode::Less:
+            return nVal1 < nVal2;
+        case ScConditionMode::Greater:
+            return nVal1 > nVal2;
+        case ScConditionMode::EqLess:
+            return nVal1 <= nVal2;
+        case ScConditionMode::EqGreater:
+            return nVal1 >= nVal2;
+        case ScConditionMode::NotEqual:
+            return nVal1 != nVal2;
+
+        default:
+            break;
+    }
+
+    return false;
+}
+
 ScIconSetFormatData::ScIconSetFormatData(ScIconSetFormatData const& rOther)
     : eIconSetType(rOther.eIconSetType)
     , mbShowValue(rOther.mbShowValue)
@@ -1131,27 +1159,32 @@ std::unique_ptr<ScIconSetInfo> 
ScIconSetFormat::GetIconSetInfo(const ScAddress&
     // now we have for sure a value
     double nVal = rCell.getValue();
 
-    if (mpFormatData->m_Entries.size() < 2)
+    if (mpFormatData->m_Entries.size() < 1)
         return nullptr;
 
     double nMin = GetMinValue();
     double nMax = GetMaxValue();
 
-    sal_Int32 nIndex = 0;
+    sal_Int32 nIndex = -1;
+    ScConditionMode eMode = ScConditionMode::EqGreater;
     const_iterator itr = begin();
-    ++itr;
-    double nValMax = CalcValue(nMin, nMax, itr);
+    double nValRef = 0;
 
-    ++itr;
-    while(itr != end() && nVal >= nValMax)
+    int i = 0;
+    while(itr != end())
     {
-        ++nIndex;
-        nValMax = CalcValue(nMin, nMax, itr);
-        ++itr;
+        nValRef = CalcValue(nMin, nMax, itr);
+        if (Compare(nVal, nValRef, itr))
+        {
+            nIndex = i;
+            eMode = (*itr)->GetMode();
+        }
+        itr++;
+        i++;
     }
 
-    if(nVal >= nValMax)
-        ++nIndex;
+    if (nIndex == -1)
+        return nullptr;
 
     std::unique_ptr<ScIconSetInfo> pInfo(new ScIconSetInfo);
 
@@ -1184,6 +1217,7 @@ std::unique_ptr<ScIconSetInfo> 
ScIconSetFormat::GetIconSetInfo(const ScAddress&
     }
 
     pInfo->mbShowValue = mpFormatData->mbShowValue;
+    pInfo->eConditionMode = eMode;
     return pInfo;
 }
 
diff --git a/sc/source/ui/condformat/condformatdlgentry.cxx 
b/sc/source/ui/condformat/condformatdlgentry.cxx
index 860e8c225150..9798263d06c7 100644
--- a/sc/source/ui/condformat/condformatdlgentry.cxx
+++ b/sc/source/ui/condformat/condformatdlgentry.cxx
@@ -1318,9 +1318,9 @@ protected:
 private:
     std::unique_ptr<weld::Container> mxGrid;
     std::unique_ptr<weld::Image> mxImgIcon;
-    std::unique_ptr<weld::Label> mxFtEntry;
     std::unique_ptr<weld::Entry> mxEdEntry;
     std::unique_ptr<weld::ComboBox> mxLbEntryType;
+    std::unique_ptr<weld::ComboBox> mxConditionMode;
     weld::Container* mpContainer;
 
 public:
@@ -1336,22 +1336,25 @@ public:
     }
 
     ScColorScaleEntry* CreateEntry(ScDocument& rDoc, const ScAddress& rPos) 
const;
-
-    void SetFirstEntry();
 };
 
 ScIconSetFrmtDataEntry::ScIconSetFrmtDataEntry(weld::Container* pParent, 
ScIconSetType eType, const ScDocument* pDoc, sal_Int32 i, const 
ScColorScaleEntry* pEntry)
     : mxBuilder(Application::CreateBuilder(pParent, 
"modules/scalc/ui/conditionaliconset.ui"))
     , mxGrid(mxBuilder->weld_container("ConditionalIconSet"))
     , mxImgIcon(mxBuilder->weld_image("icon"))
-    , mxFtEntry(mxBuilder->weld_label("label"))
     , mxEdEntry(mxBuilder->weld_entry("entry"))
     , mxLbEntryType(mxBuilder->weld_combo_box("listbox"))
+    , mxConditionMode(mxBuilder->weld_combo_box("conditionMode"))
     , mpContainer(pParent)
 {
     mxImgIcon->set_from_icon_name(ScIconSetFormat::getIconName(eType, i));
     if(pEntry)
     {
+        if (pEntry->GetMode() >= ScConditionMode::Equal && pEntry->GetMode() 
<= ScConditionMode::NotEqual)
+            mxConditionMode->set_active(static_cast<int>(pEntry->GetMode()));
+        else
+            assert(false && "ScIconSetFrmtDataEntry::ScIconSetFrmtDataEntry: 
Invalid condition mode");
+
         switch(pEntry->GetType())
         {
             case COLORSCALE_VALUE:
@@ -1377,6 +1380,7 @@ 
ScIconSetFrmtDataEntry::ScIconSetFrmtDataEntry(weld::Container* pParent, ScIconS
     else
     {
         mxLbEntryType->set_active(1);
+        mxConditionMode->set_active(0);
     }
 }
 
@@ -1387,7 +1391,8 @@ ScIconSetFrmtDataEntry::~ScIconSetFrmtDataEntry()
 
 ScColorScaleEntry* ScIconSetFrmtDataEntry::CreateEntry(ScDocument& rDoc, const 
ScAddress& rPos) const
 {
-    sal_Int32 nPos = mxLbEntryType->get_active();
+    sal_Int32 nTypePos = mxLbEntryType->get_active();
+    sal_Int32 nModePos = mxConditionMode->get_active();
     OUString aText = mxEdEntry->get_text();
     ScColorScaleEntry* pEntry = new ScColorScaleEntry();
 
@@ -1397,7 +1402,7 @@ ScColorScaleEntry* 
ScIconSetFrmtDataEntry::CreateEntry(ScDocument& rDoc, const S
     (void)pNumberFormatter->IsNumberFormat(aText, nIndex, nVal);
     pEntry->SetValue(nVal);
 
-    switch(nPos)
+    switch(nTypePos)
     {
         case 0:
             pEntry->SetType(COLORSCALE_VALUE);
@@ -1416,16 +1421,9 @@ ScColorScaleEntry* 
ScIconSetFrmtDataEntry::CreateEntry(ScDocument& rDoc, const S
             assert(false);
     }
 
-    return pEntry;
-}
+    pEntry->SetMode(static_cast<ScConditionMode>(nModePos));
 
-void ScIconSetFrmtDataEntry::SetFirstEntry()
-{
-    mxEdEntry->hide();
-    mxLbEntryType->hide();
-    mxFtEntry->hide();
-    mxEdEntry->set_text("0");
-    mxLbEntryType->set_active(1);
+    return pEntry;
 }
 
 ScIconSetFrmtEntry::ScIconSetFrmtEntry(ScCondFormatList* pParent, ScDocument* 
pDoc, const ScAddress& rPos, const ScIconSetFormat* pFormat)
@@ -1454,7 +1452,6 @@ ScIconSetFrmtEntry::ScIconSetFrmtEntry(ScCondFormatList* 
pParent, ScDocument* pD
                 mxIconParent.get(), eType, pDoc, i, 
pIconSetFormatData->m_Entries[i].get()));
             maEntries[i]->set_grid_top_attach(i);
         }
-        maEntries[0]->SetFirstEntry();
     }
     else
         IconSetTypeHdl(*mxLbIconSetType);
@@ -1488,7 +1485,6 @@ IMPL_LINK_NOARG( ScIconSetFrmtEntry, IconSetTypeHdl, 
weld::ComboBox&, void )
         maEntries[i]->set_grid_top_attach(i);
         maEntries[i]->Show();
     }
-    maEntries[0]->SetFirstEntry();
 }
 
 OUString ScIconSetFrmtEntry::GetExpressionString()
diff --git a/sc/uiconfig/scalc/ui/conditionaliconset.ui 
b/sc/uiconfig/scalc/ui/conditionaliconset.ui
index bf129a2c914c..342a4747c012 100644
--- a/sc/uiconfig/scalc/ui/conditionaliconset.ui
+++ b/sc/uiconfig/scalc/ui/conditionaliconset.ui
@@ -16,10 +16,17 @@
         <property name="row_spacing">6</property>
         <property name="column_spacing">12</property>
         <child>
-          <object class="GtkLabel" id="label">
+          <object class="GtkComboBoxText" id="conditionMode">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="label" translatable="yes" 
context="conditionaliconset|label"> &gt;= </property>
+            <items>
+              <item translatable="no" 
context="conditionaliconset|conditionMode"> = </item>
+              <item translatable="no" 
context="conditionaliconset|conditionMode"> &lt; </item>
+              <item translatable="no" 
context="conditionaliconset|conditionMode"> &gt; </item>
+              <item translatable="no" 
context="conditionaliconset|conditionMode"> &lt;= </item>
+              <item translatable="no" 
context="conditionaliconset|conditionMode"> &gt;= </item>
+              <item translatable="no" 
context="conditionaliconset|conditionMode"> &lt;&gt; </item>
+            </items>
           </object>
           <packing>
             <property name="left_attach">1</property>

Reply via email to