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>
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx
index 07eb9b4..a55547c 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)
// 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)
{
// when there are a lot of rows, it is cheaper to simply clear the tree and re-initialise
mpChecks->clear();
nSelCount = initMembers();
}
else
{
bool bSomeDateDeletes = false;
for (size_t i = 0; i < n; ++i)
{
bool bIsDate = maMembers[i].mbDate;
@@ -725,19 +734,57 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, EdModifyHdl, weld::Entry&, void)
bSomeDateDeletes = true;
}
}
}
if ( bSomeDateDeletes )
{
for (size_t i = 0; i < n; ++i)
if ( bSomeDateDeletes )
{
if (!maMembers[i].mbDate)
continue;
if (maMembers[i].meDatePartType != ScCheckListMember::DAY)
continue;
updateMemberParents(nullptr, i);
for (size_t i = 0; i < n; ++i)
{
if (!maMembers[i].mbDate)
continue;
if (maMembers[i].meDatePartType != ScCheckListMember::DAY)
continue;
updateMemberParents(nullptr, i);
}
}
}
else
{
// 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
{
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();
@@ -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)