diff options
author | Jean-Sebastien Bevilacqua <realitix@gmail.com> | 2017-05-31 10:59:42 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2017-05-31 13:18:00 +0200 |
commit | 511fb8e80d298d42f5c45e7410bf64f2a25b441e (patch) | |
tree | 1f3f2c73305127c7fd3404f46a0ec3200c33f4f9 | |
parent | add89eb95021cc6ebda2acffc4c7889109defa5b (diff) |
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>
-rw-r--r-- | sc/source/ui/cctrl/checklistmenu.cxx | 26 | ||||
-rw-r--r-- | sc/source/ui/inc/checklistmenu.hxx | 2 |
2 files changed, 24 insertions, 4 deletions
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index d3ed848145da..ee51abb9f8a8 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 9c1a1f3fd07f..7bae3853e82e 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; |