diff options
author | Caolán McNamara <caolanm@redhat.com> | 2020-11-12 16:30:46 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2020-11-16 09:49:48 +0100 |
commit | f57b158701fb082ad9016819a2af7cdb13e6fa30 (patch) | |
tree | 4d7be5c4c5318b0c1243b23b0db44e868b5d592b /sc | |
parent | 577b6be9ba4d55804e088dabfc2f40473ea3e726 (diff) |
tdf#122419 optimize autofilter search when there are no dates
Change-Id: Id679b4a2e7a290780142daae39d28a429fb3b11d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105765
Tested-by: Jenkins
Reviewed-by: Kevin Suo <suokunlong@126.com>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/source/ui/cctrl/checklistmenu.cxx | 95 |
1 files changed, 65 insertions, 30 deletions
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index 07eb9b45b3df..a55547cbc12b 100644 --- a/sc/source/ui/cctrl/checklistmenu.cxx +++ b/sc/source/ui/cctrl/checklistmenu.cxx @@ -662,6 +662,18 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, TriStateHdl, weld::ToggleButton&, void) mePrevToggleAllState = mxChkToggleAll->get_state(); } +namespace +{ + void insertMember(weld::TreeView& rView, const weld::TreeIter& rIter, const ScCheckListMember& rMember, bool bChecked) + { + OUString aLabel = rMember.maName; + if (aLabel.isEmpty()) + aLabel = ScResId(STR_EMPTYDATA); + rView.set_toggle(rIter, bChecked ? TRISTATE_TRUE : TRISTATE_FALSE); + rView.set_text(rIter, aLabel, 0); + } +} + IMPL_LINK_NOARG(ScCheckListMenuControl, EdModifyHdl, weld::Entry&, void) { OUString aSearchText = mxEdSearch->get_text(); @@ -669,18 +681,15 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, EdModifyHdl, weld::Entry&, void) bool bSearchTextEmpty = aSearchText.isEmpty(); size_t n = maMembers.size(); size_t nSelCount = 0; - bool bSomeDateDeletes = false; mpChecks->freeze(); - if (bSearchTextEmpty && !mbHasDates) - { - // when there are a lot of rows, it is cheaper to simply clear the tree and re-initialise - mpChecks->clear(); - nSelCount = initMembers(); - } - else + // This branch is the general case, the other is an optimized variant of + // this one where we can take advantage of knowing we have no hierarchy + if (mbHasDates) { + bool bSomeDateDeletes = false; + for (size_t i = 0; i < n; ++i) { bool bIsDate = maMembers[i].mbDate; @@ -725,20 +734,58 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, EdModifyHdl, weld::Entry&, void) bSomeDateDeletes = true; } } - } - if ( bSomeDateDeletes ) + if ( bSomeDateDeletes ) + { + for (size_t i = 0; i < n; ++i) + { + if (!maMembers[i].mbDate) + continue; + if (maMembers[i].meDatePartType != ScCheckListMember::DAY) + continue; + updateMemberParents(nullptr, i); + } + } + } + else { - for (size_t i = 0; i < n; ++i) + // when there are a lot of rows, it is cheaper to simply clear the tree and either + // re-initialise or just insert the filtered lines + mpChecks->clear(); + + if (bSearchTextEmpty) + nSelCount = initMembers(); + else { - if (!maMembers[i].mbDate) - continue; - if (maMembers[i].meDatePartType != ScCheckListMember::DAY) - continue; - updateMemberParents(nullptr, i); + std::vector<size_t> aShownIndexes; + + for (size_t i = 0; i < n; ++i) + { + assert(!maMembers[i].mbDate); + + OUString aLabelDisp = maMembers[i].maName; + if ( aLabelDisp.isEmpty() ) + aLabelDisp = ScResId( STR_EMPTYDATA ); + + bool bPartialMatch = ScGlobal::getCharClassPtr()->lowercase( aLabelDisp ).indexOf( aSearchText ) != -1; + + if (!bPartialMatch) + continue; + + aShownIndexes.push_back(i); + } + + std::vector<int> aFixedWidths { mnCheckWidthReq }; + // tdf#122419 insert in the fastest order, this might be backwards. + mpChecks->bulk_insert_for_each(aShownIndexes.size(), [this, &aShownIndexes, &nSelCount](weld::TreeIter& rIter, int i) { + size_t nIndex = aShownIndexes[i]; + insertMember(*mpChecks, rIter, maMembers[nIndex], true); + ++nSelCount; + }, &aFixedWidths); } } + mpChecks->thaw(); if ( nSelCount == n ) @@ -1167,18 +1214,6 @@ IMPL_LINK(ScCheckListMenuControl, KeyInputHdl, const KeyEvent&, rKEvt, bool) return false; } -namespace -{ - void insertMember(weld::TreeView& rView, const weld::TreeIter& rIter, const ScCheckListMember& rMember) - { - OUString aLabel = rMember.maName; - if (aLabel.isEmpty()) - aLabel = ScResId(STR_EMPTYDATA); - rView.set_toggle(rIter, rMember.mbVisible ? TRISTATE_TRUE : TRISTATE_FALSE); - rView.set_text(rIter, aLabel, 0); - } -} - size_t ScCheckListMenuControl::initMembers(int nMaxMemberWidth) { size_t n = maMembers.size(); @@ -1195,7 +1230,7 @@ size_t ScCheckListMenuControl::initMembers(int nMaxMemberWidth) // inserted. We cannot retain pre-existing treeview content, only clear and fill it. mpChecks->bulk_insert_for_each(n, [this, &nVisMemCount](weld::TreeIter& rIter, int i) { assert(!maMembers[i].mbDate); - insertMember(*mpChecks, rIter, maMembers[i]); + insertMember(*mpChecks, rIter, maMembers[i], maMembers[i].mbVisible); if (maMembers[i].mbVisible) ++nVisMemCount; }, &aFixedWidths); @@ -1223,7 +1258,7 @@ size_t ScCheckListMenuControl::initMembers(int nMaxMemberWidth) else { mpChecks->append(xEntry.get()); - insertMember(*mpChecks, *xEntry, maMembers[i]); + insertMember(*mpChecks, *xEntry, maMembers[i], maMembers[i].mbVisible); } if (maMembers[i].mbVisible) |