tdf#154906 tdf#129813 tdf#129814 sc: fix conditional format color scale

This is a follow up to commit 3f614f431475e1bf3bb3bbeac59b0681309628b7
(tdf#95295: don't add duplicate conditional formats)
The above commit clearly describes how this fix works.

Change-Id: I064fb3fe0443705553c6bbfcc34f2d717e0f6bd6
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150899
Tested-by: Jenkins
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/sc/inc/colorscale.hxx b/sc/inc/colorscale.hxx
index de74030..513eb11 100644
--- a/sc/inc/colorscale.hxx
+++ b/sc/inc/colorscale.hxx
@@ -270,6 +270,8 @@ public:
    std::optional<Color> GetColor(const ScAddress& rAddr) const;
    void AddEntry(ScColorScaleEntry* pEntry);

    bool IsEqual(const ScFormatEntry& r, bool bIgnoreSrcPos) const override;

    virtual void UpdateReference( sc::RefUpdateContext& rCxt ) override;
    virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt ) override;
    virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ) override;
diff --git a/sc/qa/unit/ucalc_condformat.cxx b/sc/qa/unit/ucalc_condformat.cxx
index 811cd0d..bfece15 100644
--- a/sc/qa/unit/ucalc_condformat.cxx
+++ b/sc/qa/unit/ucalc_condformat.cxx
@@ -268,6 +268,56 @@ CPPUNIT_TEST_FIXTURE(TestCondformat, testCondFormatInsertDeleteSheets)
    m_pDoc->DeleteTab(0);
}

CPPUNIT_TEST_FIXTURE(TestCondformat, testColorScaleCondCopyPaste)
{
    m_pDoc->InsertTab(0, "Test");

    auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
    ScRange aCondFormatRange(0, 0, 0, 2, 0, 0);
    ScRangeList aRangeList(aCondFormatRange);
    pFormat->SetRange(aRangeList);

    ScColorScaleFormat* pColorScaleFormat = new ScColorScaleFormat(m_pDoc);
    ScColorScaleEntry* pEntryBlue = new ScColorScaleEntry(0, COL_BLUE);
    ScColorScaleEntry* pEntryGreen = new ScColorScaleEntry(1, COL_GREEN);
    ScColorScaleEntry* pEntryRed = new ScColorScaleEntry(2, COL_RED);
    pColorScaleFormat->AddEntry(pEntryBlue);
    pColorScaleFormat->AddEntry(pEntryGreen);
    pColorScaleFormat->AddEntry(pEntryRed);

    pFormat->AddEntry(pColorScaleFormat);
    sal_uLong nIndex = m_pDoc->AddCondFormat(std::move(pFormat), 0);

    ScDocument aClipDoc(SCDOCMODE_CLIP);
    copyToClip(m_pDoc, aCondFormatRange, &aClipDoc);

    ScRange aTargetRange(0, 3, 0, 2, 3, 0);
    pasteFromClip(m_pDoc, aTargetRange, &aClipDoc);

    // Pasting the same conditional format must modify existing format, making its range
    // combined of previous range and newly pasted range having the conditional format.
    // No new conditional formats must be created.
    CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc->GetCondFormList(0)->size());
    aRangeList.Join(aTargetRange);
    for (SCCOL nCol = 0; nCol < 3; ++nCol)
    {
        ScConditionalFormat* pPastedFormat = m_pDoc->GetCondFormat(nCol, 3, 0);
        CPPUNIT_ASSERT(pPastedFormat);
        CPPUNIT_ASSERT_EQUAL(aRangeList, pPastedFormat->GetRange());

        sal_uLong nPastedKey = pPastedFormat->GetKey();
        CPPUNIT_ASSERT_EQUAL(nIndex, nPastedKey);

        const SfxPoolItem* pItem = m_pDoc->GetAttr(nCol, 3, 0, ATTR_CONDITIONAL);
        const ScCondFormatItem* pCondFormatItem = static_cast<const ScCondFormatItem*>(pItem);
        CPPUNIT_ASSERT(pCondFormatItem);
        CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem->GetCondFormatData().size());
        CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().front());
    }

    m_pDoc->DeleteTab(0);
}

CPPUNIT_TEST_FIXTURE(TestCondformat, testCondCopyPaste)
{
    m_pDoc->InsertTab(0, "Test");
diff --git a/sc/source/core/data/colorscale.cxx b/sc/source/core/data/colorscale.cxx
index 0a35782..192dd1c 100644
--- a/sc/source/core/data/colorscale.cxx
+++ b/sc/source/core/data/colorscale.cxx
@@ -404,6 +404,24 @@ void ScColorScaleFormat::AddEntry( ScColorScaleEntry* pEntry )
    maColorScales.back()->SetRepaintCallback(mpParent);
}

bool ScColorScaleFormat::IsEqual(const ScFormatEntry& rOther, bool /*bIgnoreSrcPos*/) const
{
    if (GetType() != rOther.GetType())
        return false;

    const ScColorScaleFormat& r = static_cast<const ScColorScaleFormat&>(rOther);

    for (size_t i = 0; i < maColorScales.size(); ++i)
    {
        if (!maColorScales[i]->GetColor().IsRGBEqual(r.maColorScales[i]->GetColor().GetRGBColor())
            || maColorScales[i]->GetType() != r.maColorScales[i]->GetType()
            || maColorScales[i]->GetValue() != r.maColorScales[i]->GetValue())
            return false;
    }

    return true;
}

double ScColorScaleFormat::GetMinValue() const
{
    ScColorScaleEntries::const_iterator itr = maColorScales.begin();