support undo of whole conditional format list, tdf#95617

Change-Id: I3ff0ddb05f794064e33164c60cd1b4e6b89dbcca
Reviewed-on: https://gerrit.libreoffice.org/36295
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Markus Mohrhard <markus.mohrhard@googlemail.com>
diff --git a/sc/inc/conditio.hxx b/sc/inc/conditio.hxx
index bba11bc..631d044 100644
--- a/sc/inc/conditio.hxx
+++ b/sc/inc/conditio.hxx
@@ -511,6 +511,11 @@ public:
    typedef ConditionalFormatContainer::iterator iterator;
    typedef ConditionalFormatContainer::const_iterator const_iterator;

    ScRangeList GetCombinedRange() const;

    void RemoveFromDocument(ScDocument* pDoc) const;
    void AddToDocument(ScDocument* pDoc) const;

    iterator begin();
    const_iterator begin() const;
    iterator end();
diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc
index 793b59c..6696945 100644
--- a/sc/inc/globstr.hrc
+++ b/sc/inc/globstr.hrc
@@ -662,7 +662,9 @@

#define STR_QUERY_PIVOTTABLE_DELTAB     535

#define SC_GLOBSTR_STR_COUNT            536     /**< the count of permanently resident strings */
#define STR_UNDO_CONDFORMAT_LIST        536

#define SC_GLOBSTR_STR_COUNT            537     /**< the count of permanently resident strings */

#endif

diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx
index a692f27..a2b2f18 100644
--- a/sc/source/core/data/conditio.cxx
+++ b/sc/source/core/data/conditio.cxx
@@ -2245,6 +2245,43 @@ ScConditionalFormatList::const_iterator ScConditionalFormatList::end() const
    return m_ConditionalFormats.end();
}

ScRangeList ScConditionalFormatList::GetCombinedRange() const
{
    ScRangeList aRange;
    for (auto& itr: m_ConditionalFormats)
    {
        const ScRangeList& rRange = itr->GetRange();
        for (size_t i = 0, n = rRange.size(); i < n; ++i)
        {
            if (rRange[i])
                aRange.Join(*rRange[i]);
        }
    }
    return aRange;
}

void ScConditionalFormatList::RemoveFromDocument(ScDocument* pDoc) const
{
    ScRangeList aRange = GetCombinedRange();
    ScMarkData aMark;
    aMark.MarkFromRangeList(aRange, true);
    sal_uInt16 pItems[2] = { ATTR_CONDITIONAL,0};
    pDoc->ClearSelectionItems(pItems, aMark);
}

void ScConditionalFormatList::AddToDocument(ScDocument* pDoc) const
{
    for (auto& itr: m_ConditionalFormats)
    {
        const ScRangeList& rRange = itr->GetRange();
        if (rRange.empty())
            continue;

        SCTAB nTab = rRange.front()->aStart.Tab();
        pDoc->AddCondFormatData(rRange, nTab, itr->GetKey());
    }
}

size_t ScConditionalFormatList::size() const
{
    return m_ConditionalFormats.size();
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index dda9430..1619865 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -5470,22 +5470,42 @@ void ScDocFunc::SetConditionalFormatList( ScConditionalFormatList* pList, SCTAB 
    if(rDoc.IsTabProtected(nTab))
        return;

    // first remove all old entries
    ScConditionalFormatList* pOldList = rDoc.GetCondFormList(nTab);
    for(ScConditionalFormatList::const_iterator itr = pOldList->begin(), itrEnd = pOldList->end(); itr != itrEnd; ++itr)
    bool bUndo = rDoc.IsUndoEnabled();
    ScDocument* pUndoDoc = nullptr;
    if (bUndo)
    {
        rDoc.RemoveCondFormatData((*itr)->GetRange(), nTab, (*itr)->GetKey());
        pUndoDoc = new ScDocument(SCDOCMODE_UNDO);
        pUndoDoc->InitUndo( &rDoc, nTab, nTab );

        ScConditionalFormatList* pOld = rDoc.GetCondFormList(nTab);

        if (pOld)
            pUndoDoc->SetCondFormList(new ScConditionalFormatList(pUndoDoc, *pOld), nTab);
        else
            pUndoDoc->SetCondFormList(nullptr, nTab);

    }

    // first remove all old entries
    ScConditionalFormatList* pOldList = rDoc.GetCondFormList(nTab);
    pOldList->RemoveFromDocument(&rDoc);

    // then set new entries
    for(ScConditionalFormatList::iterator itr = pList->begin(); itr != pList->end(); ++itr)
    {
        rDoc.AddCondFormatData((*itr)->GetRange(), nTab, (*itr)->GetKey());
    }
    pList->AddToDocument(&rDoc);

    rDoc.SetCondFormList(pList, nTab);
    rDocShell.PostPaintGridAll();

    if(bUndo)
    {
        ScDocument* pRedoDoc = new ScDocument(SCDOCMODE_UNDO);
        pRedoDoc->InitUndo( &rDoc, nTab, nTab );
        pRedoDoc->SetCondFormList(new ScConditionalFormatList(pRedoDoc, *pList), nTab);

        rDocShell.GetUndoManager()->AddUndoAction(
                new ScUndoConditionalFormatList(&rDocShell, pUndoDoc, pRedoDoc, nTab));
    }

    rDoc.SetStreamValid(nTab, false);
    aModificator.SetDocumentModified();
    SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScAreasChanged));
diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx
index c558b44..b5cc4ad 100644
--- a/sc/source/ui/inc/undoblk.hxx
+++ b/sc/source/ui/inc/undoblk.hxx
@@ -631,6 +631,27 @@ private:
    ScRange maRange;
};

class ScUndoConditionalFormatList : public ScSimpleUndo
{
public:
    ScUndoConditionalFormatList( ScDocShell* pNewDocShell,
            ScDocument* pUndoDoc, ScDocument* pRedoDoc, SCTAB nTab);
    virtual         ~ScUndoConditionalFormatList() override;

    virtual void    Undo() override;
    virtual void    Redo() override;
    virtual void    Repeat(SfxRepeatTarget& rTarget) override;
    virtual bool    CanRepeat(SfxRepeatTarget& rTarget) const override;

    virtual OUString GetComment() const override;

private:
    void DoChange(ScDocument* pDoc);
    std::unique_ptr<ScDocument> mpUndoDoc;
    std::unique_ptr<ScDocument> mpRedoDoc;
    SCTAB mnTab;
};

class ScUndoUseScenario: public ScSimpleUndo
{
public:
diff --git a/sc/source/ui/src/globstr.src b/sc/source/ui/src/globstr.src
index 0a26724..7936525 100644
--- a/sc/source/ui/src/globstr.src
+++ b/sc/source/ui/src/globstr.src
@@ -1873,6 +1873,11 @@ String STR_UNDO_CONDFORMAT+RID_GLOBSTR_OFFSET
    Text [ en-US ] = "Conditional Format";
};

String STR_UNDO_CONDFORMAT_LIST+RID_GLOBSTR_OFFSET
{
    Text [ en-US ] = "Conditional Formats";
};

String STR_UNDO_FORMULA_TO_VALUE+RID_GLOBSTR_OFFSET
{
    Text [ en-US ] = "Convert Formula To Value";
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index 2170228..dccc583 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -1535,6 +1535,66 @@ bool ScUndoConditionalFormat::CanRepeat(SfxRepeatTarget& ) const
    return false;
}

ScUndoConditionalFormatList::ScUndoConditionalFormatList(ScDocShell* pNewDocShell,
        ScDocument* pUndoDoc, ScDocument* pRedoDoc, SCTAB nTab):
    ScSimpleUndo( pNewDocShell ),
    mpUndoDoc(pUndoDoc),
    mpRedoDoc(pRedoDoc),
    mnTab(nTab)
{
}

ScUndoConditionalFormatList::~ScUndoConditionalFormatList()
{
}

OUString ScUndoConditionalFormatList::GetComment() const
{
    return ScGlobal::GetRscString( STR_UNDO_CONDFORMAT_LIST );
}

void ScUndoConditionalFormatList::Undo()
{
    DoChange(mpUndoDoc.get());
}

void ScUndoConditionalFormatList::Redo()
{
    DoChange(mpRedoDoc.get());
}

void ScUndoConditionalFormatList::DoChange(ScDocument* pSrcDoc)
{
    ScDocument& rDoc = pDocShell->GetDocument();

    if (pSrcDoc == mpUndoDoc.get())
    {
        mpRedoDoc->GetCondFormList(mnTab)->RemoveFromDocument(&rDoc);
        mpUndoDoc->GetCondFormList(mnTab)->AddToDocument(&rDoc);
    }
    else
    {
        mpUndoDoc->GetCondFormList(mnTab)->RemoveFromDocument(&rDoc);
        mpRedoDoc->GetCondFormList(mnTab)->AddToDocument(&rDoc);
    }
    rDoc.SetCondFormList(new ScConditionalFormatList(&rDoc, *pSrcDoc->GetCondFormList(mnTab)), mnTab);

    pDocShell->PostPaintGridAll();
    pDocShell->PostDataChanged();
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
    if (pViewShell)
        pViewShell->CellContentChanged();
}

void ScUndoConditionalFormatList::Repeat(SfxRepeatTarget& )
{
}

bool ScUndoConditionalFormatList::CanRepeat(SfxRepeatTarget& ) const
{
    return false;
}

ScUndoUseScenario::ScUndoUseScenario( ScDocShell* pNewDocShell,
                        const ScMarkData& rMark,
/*C*/                   const ScArea& rDestArea,