tdf#108259 Enable autofilter with many different values

When you create an autofilter on a column which contains many different
values, you will have problems.

First of all, if you exceed 65535 values, you will enter in an infinite
loop because a uint16 is incremented for each value, and after 65535,
you restart to 0.

Secondly, the algorithm executes a double loop in O(n2) to determine
checked values, it's too long. Instead of that, all checked values can be
determined before.

This patch is graciously offered by Linagora.

Change-Id: Idc4500f6a496ae789aae11eb0e183aee157daa20
Reviewed-on: https://gerrit.libreoffice.org/38269
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Tested-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx
index d3ed848..ee51abb 100644
--- a/sc/source/ui/cctrl/checklistmenu.cxx
+++ b/sc/source/ui/cctrl/checklistmenu.cxx
@@ -1141,8 +1141,8 @@ void ScCheckListMenuWindow::setAllMemberState(bool bSet)
    {
        if (!(*itr))
        {
            sal_uInt16 nCount = maChecks->GetEntryCount();
            for( sal_uInt16 i = 0; i < nCount; ++i)
            sal_uInt32 nCount = maChecks->GetEntryCount();
            for( sal_uInt32 i = 0; i < nCount; ++i)
            {
                SvTreeListEntry* pEntry = maChecks->GetEntry(i);
                if (!pEntry)
@@ -1620,7 +1620,7 @@ ScCheckListBox::ScCheckListBox( vcl::Window* pParent )

SvTreeListEntry* ScCheckListBox::FindEntry( SvTreeListEntry* pParent, const OUString& sNode )
{
    sal_uInt16 nRootPos = 0;
    sal_uInt32 nRootPos = 0;
    SvTreeListEntry* pEntry = pParent ? FirstChild( pParent ) : GetEntry( nRootPos );
    while ( pEntry )
    {
@@ -1639,6 +1639,23 @@ void ScCheckListBox::Init()
    SetNodeDefaultImages();
}

std::unordered_set<OUString, OUStringHash> ScCheckListBox::GetAllChecked()
{
    std::unordered_set<OUString, OUStringHash> results(0);
    sal_uInt32 nRootPos = 0;
    SvTreeListEntry* pEntry = GetEntry(nRootPos);
    while (pEntry)
    {
        if (GetCheckButtonState(pEntry) == SvButtonState::Checked)
        {
            results.insert(GetEntryText(pEntry));
        }
        pEntry = GetEntry(++nRootPos);
    }

    return results;
}

bool ScCheckListBox::IsChecked( const OUString& sName, SvTreeListEntry* pParent )
{
    SvTreeListEntry* pEntry = FindEntry( pParent, sName );
@@ -1907,6 +1924,7 @@ bool ScCheckListMenuWindow::isAllSelected() const
void ScCheckListMenuWindow::getResult(ResultType& rResult)
{
    ResultType aResult;
    std::unordered_set<OUString, OUStringHash> checkeds = maChecks->GetAllChecked();
    size_t n = maMembers.size();
    for (size_t i = 0; i < n; ++i)
    {
@@ -1915,7 +1933,7 @@ void ScCheckListMenuWindow::getResult(ResultType& rResult)
            OUString aLabel = maMembers[i].maName;
            if (aLabel.isEmpty())
                aLabel = ScGlobal::GetRscString(STR_EMPTYDATA);
            bool bState =  maChecks->IsChecked( aLabel,  maMembers[i].mpParent );
            bool bState = checkeds.find(aLabel) != checkeds.end();
            ResultEntry aResultEntry;
            aResultEntry.bValid = bState;
            if ( maMembers[i].mbDate )
diff --git a/sc/source/ui/inc/checklistmenu.hxx b/sc/source/ui/inc/checklistmenu.hxx
index 9c1a1f3..7bae385 100644
--- a/sc/source/ui/inc/checklistmenu.hxx
+++ b/sc/source/ui/inc/checklistmenu.hxx
@@ -19,6 +19,7 @@
#include <svx/checklbx.hxx>

#include <memory>
#include <unordered_set>
#include <unordered_map>
#include <map>

@@ -239,6 +240,7 @@ class ScCheckListBox : public SvTreeListBox
    void CheckEntry( const OUString& sName, SvTreeListEntry* pParent, bool bCheck );
    void CheckEntry( SvTreeListEntry* pEntry, bool bCheck );
    SvTreeListEntry* ShowCheckEntry( const OUString& sName, ScCheckListMember& rMember, bool bShow = true, bool bCheck = true );
    std::unordered_set<OUString, OUStringHash> GetAllChecked();
    bool IsChecked( const OUString& sName, SvTreeListEntry* pParent );
    SvTreeListEntry* FindEntry( SvTreeListEntry* pParent, const OUString& sNode );
    sal_uInt16 GetCheckedEntryCount() const;