diff options
author | Caolán McNamara <caolanm@redhat.com> | 2020-09-18 20:52:16 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2020-09-20 18:51:56 +0200 |
commit | fcf2f4ac837982e1fae49ddd75383ceab4e2bda7 (patch) | |
tree | 62a17ea5758214334a154c2789e647d072b3ec9e /sc | |
parent | c8900890ad39e77285d284f5070abfe3661e493f (diff) |
tdf#136559 We can get a performance boost from using a ListStore
instead of a TreeStore if we only need a list
see: https://gitlab.gnome.org/GNOME/gtk/-/issues/2693
Change-Id: I03d03f2364ccc75b87d3f7c31d21ac9993fb384b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103036
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/qa/uitest/autofilter/autofilter.py | 2 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter/autofilterBugs.py | 2 | ||||
-rw-r--r-- | sc/qa/uitest/autofilter/tdf97340.py | 4 | ||||
-rw-r--r-- | sc/source/ui/cctrl/checklistmenu.cxx | 239 | ||||
-rw-r--r-- | sc/source/ui/inc/checklistmenu.hxx | 4 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin.cxx | 7 | ||||
-rw-r--r-- | sc/uiconfig/scalc/ui/filterdropdown.ui | 134 |
7 files changed, 243 insertions, 149 deletions
diff --git a/sc/qa/uitest/autofilter/autofilter.py b/sc/qa/uitest/autofilter/autofilter.py index 61e43b2fb5a6..000ddaab77e3 100644 --- a/sc/qa/uitest/autofilter/autofilter.py +++ b/sc/qa/uitest/autofilter/autofilter.py @@ -32,7 +32,7 @@ class AutofilterTest(UITestCase): xFloatWindow = self.xUITest.getFloatWindow() xCheckListMenu = xFloatWindow.getChild("check_list_menu") - xTreeList = xCheckListMenu.getChild("check_list_box") + xTreeList = xCheckListMenu.getChild("check_tree_box") xFirstEntry = xTreeList.getChild("0") xFirstEntry.executeAction("CLICK", tuple()) diff --git a/sc/qa/uitest/autofilter/autofilterBugs.py b/sc/qa/uitest/autofilter/autofilterBugs.py index 193ba49f40a6..e1d0cd19d524 100644 --- a/sc/qa/uitest/autofilter/autofilterBugs.py +++ b/sc/qa/uitest/autofilter/autofilterBugs.py @@ -134,7 +134,7 @@ class autofilter(UITestCase): xGridWindow.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xTreeList = xFloatWindow.getChild("check_list_box") + xTreeList = xFloatWindow.getChild("check_tree_box") xFirstEntry = xTreeList.getChild("0") self.assertEqual(get_state_as_dict(xFirstEntry)["Text"], "2014") diff --git a/sc/qa/uitest/autofilter/tdf97340.py b/sc/qa/uitest/autofilter/tdf97340.py index 442be0bb91dc..602586836622 100644 --- a/sc/qa/uitest/autofilter/tdf97340.py +++ b/sc/qa/uitest/autofilter/tdf97340.py @@ -26,7 +26,7 @@ class tdf97340(UITestCase): xFloatWindow = self.xUITest.getFloatWindow() xCheckListMenu = xFloatWindow.getChild("check_list_menu") - xTreeList = xCheckListMenu.getChild("check_list_box") + xTreeList = xCheckListMenu.getChild("check_tree_box") self.assertEqual(2, len(xTreeList.getChildren())) self.assertEqual("2016", get_state_as_dict(xTreeList.getChild('0'))['Text']) self.assertEqual("2017", get_state_as_dict(xTreeList.getChild('1'))['Text']) @@ -43,4 +43,4 @@ class tdf97340(UITestCase): self.assertEqual("2017", get_state_as_dict(xTreeList.getChild('1'))['Text']) self.ui_test.close_doc() -# vim: set shiftwidth=4 softtabstop=4 expandtab:
\ No newline at end of file +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index 57167b5bbe95..8707aff3f477 100644 --- a/sc/source/ui/cctrl/checklistmenu.cxx +++ b/sc/source/ui/cctrl/checklistmenu.cxx @@ -420,7 +420,9 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v , mxScratchIter(mxMenu->make_iterator()) , mxEdSearch(mxBuilder->weld_entry("search_edit")) , mxBox(mxBuilder->weld_widget("box")) - , mxChecks(mxBuilder->weld_tree_view("check_list_box")) + , mxListChecks(mxBuilder->weld_tree_view("check_list_box")) + , mxTreeChecks(mxBuilder->weld_tree_view("check_tree_box")) + , mpChecks(mxTreeChecks.get()) , mxChkToggleAll(mxBuilder->weld_check_button("toggle_all")) , mxBtnSelectSingle(mxBuilder->weld_button("select_current")) , mxBtnUnselectSingle(mxBuilder->weld_button("unselect_current")) @@ -441,11 +443,12 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v { bool bIsSubMenu = pParent->GetParentMenu(); - int nChecksHeight = mxChecks->get_height_rows(9); + int nChecksHeight = mxTreeChecks->get_height_rows(9); if (!bIsSubMenu && nWidth != -1) { mnCheckWidthReq = nWidth - mxFrame->get_border_width() * 2 - 4; - mxChecks->set_size_request(mnCheckWidthReq, nChecksHeight); + mxTreeChecks->set_size_request(mnCheckWidthReq, nChecksHeight); + mxListChecks->set_size_request(mnCheckWidthReq, nChecksHeight); } // sort ok/cancel into native order, if this was a dialog they would be auto-sorted, but this @@ -454,7 +457,8 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v if (!bIsSubMenu) { - mxChecks->enable_toggle_buttons(weld::ColumnToggleType::Check); + mxTreeChecks->enable_toggle_buttons(weld::ColumnToggleType::Check); + mxListChecks->enable_toggle_buttons(weld::ColumnToggleType::Check); mxBox->show(); mxEdSearch->show(); @@ -472,8 +476,10 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v mxBtnCancel->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); mxEdSearch->connect_changed(LINK(this, ScCheckListMenuControl, EdModifyHdl)); mxEdSearch->connect_activate(LINK(this, ScCheckListMenuControl, EdActivateHdl)); - mxChecks->connect_toggled(LINK(this, ScCheckListMenuControl, CheckHdl)); - mxChecks->connect_key_press(LINK(this, ScCheckListMenuControl, KeyInputHdl)); + mxTreeChecks->connect_toggled(LINK(this, ScCheckListMenuControl, CheckHdl)); + mxTreeChecks->connect_key_press(LINK(this, ScCheckListMenuControl, KeyInputHdl)); + mxListChecks->connect_toggled(LINK(this, ScCheckListMenuControl, CheckHdl)); + mxListChecks->connect_key_press(LINK(this, ScCheckListMenuControl, KeyInputHdl)); mxChkToggleAll->connect_toggled(LINK(this, ScCheckListMenuControl, TriStateHdl)); mxBtnSelectSingle->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); mxBtnUnselectSingle->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); @@ -491,7 +497,8 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v mnCheckWidthReq = mxContainer->get_preferred_size().Width(); // make that size fixed now, we can now use mnCheckWidthReq to speed up // bulk_insert_for_each - mxChecks->set_size_request(mnCheckWidthReq, nChecksHeight); + mxTreeChecks->set_size_request(mnCheckWidthReq, nChecksHeight); + mxListChecks->set_size_request(mnCheckWidthReq, nChecksHeight); } } @@ -579,12 +586,10 @@ void ScCheckListMenuControl::prepWindow() void ScCheckListMenuControl::setAllMemberState(bool bSet) { - mxChecks->freeze(); - mxChecks->all_foreach([this, bSet](weld::TreeIter& rEntry){ - mxChecks->set_toggle(rEntry, bSet ? TRISTATE_TRUE : TRISTATE_FALSE); + mpChecks->all_foreach([this, bSet](weld::TreeIter& rEntry){ + mpChecks->set_toggle(rEntry, bSet ? TRISTATE_TRUE : TRISTATE_FALSE); return false; }); - mxChecks->thaw(); if (!maConfig.mbAllowEmptySet) { @@ -596,10 +601,10 @@ void ScCheckListMenuControl::setAllMemberState(bool bSet) void ScCheckListMenuControl::selectCurrentMemberOnly(bool bSet) { setAllMemberState(!bSet); - std::unique_ptr<weld::TreeIter> xEntry = mxChecks->make_iterator(); - if (!mxChecks->get_cursor(xEntry.get())) + std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator(); + if (!mpChecks->get_cursor(xEntry.get())) return; - mxChecks->set_toggle(*xEntry, bSet ? TRISTATE_TRUE : TRISTATE_FALSE); + mpChecks->set_toggle(*xEntry, bSet ? TRISTATE_TRUE : TRISTATE_FALSE); } IMPL_LINK(ScCheckListMenuControl, ButtonHdl, weld::Button&, rBtn, void) @@ -611,8 +616,8 @@ IMPL_LINK(ScCheckListMenuControl, ButtonHdl, weld::Button&, rBtn, void) else if (&rBtn == mxBtnSelectSingle.get() || &rBtn == mxBtnUnselectSingle.get()) { selectCurrentMemberOnly(&rBtn == mxBtnSelectSingle.get()); - std::unique_ptr<weld::TreeIter> xEntry = mxChecks->make_iterator(); - if (!mxChecks->get_cursor(xEntry.get())) + std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator(); + if (!mpChecks->get_cursor(xEntry.get())) xEntry.reset(); Check(xEntry.get()); } @@ -649,12 +654,12 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, EdModifyHdl, weld::Entry&, void) size_t nSelCount = 0; bool bSomeDateDeletes = false; - mxChecks->freeze(); + mpChecks->freeze(); if (bSearchTextEmpty && !mbHasDates) { // when there are a lot of rows, it is cheaper to simply clear the tree and re-initialise - mxChecks->clear(); + mpChecks->clear(); nSelCount = initMembers(); } else @@ -717,7 +722,7 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, EdModifyHdl, weld::Entry&, void) } } - mxChecks->thaw(); + mpChecks->thaw(); if ( nSelCount == n ) mxChkToggleAll->set_state( TRISTATE_TRUE ); @@ -729,7 +734,7 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, EdModifyHdl, weld::Entry&, void) if ( !maConfig.mbAllowEmptySet ) { const bool bEmptySet( nSelCount == 0 ); - mxChecks->set_sensitive(!bEmptySet); + mpChecks->set_sensitive(!bEmptySet); mxChkToggleAll->set_sensitive(!bEmptySet); mxBtnSelectSingle->set_sensitive(!bEmptySet); mxBtnUnselectSingle->set_sensitive(!bEmptySet); @@ -752,7 +757,7 @@ IMPL_LINK( ScCheckListMenuControl, CheckHdl, const weld::TreeView::iter_col&, rR void ScCheckListMenuControl::Check(const weld::TreeIter* pEntry) { if (pEntry) - CheckEntry(*pEntry, mxChecks->get_toggle(*pEntry) == TRISTATE_TRUE); + CheckEntry(*pEntry, mpChecks->get_toggle(*pEntry) == TRISTATE_TRUE); size_t nNumChecked = GetCheckedEntryCount(); if (nNumChecked == maMembers.size()) // all members visible @@ -782,13 +787,13 @@ void ScCheckListMenuControl::updateMemberParents(const weld::TreeIter* pLeaf, si if ( pLeaf ) { std::unique_ptr<weld::TreeIter> xYearEntry; - std::unique_ptr<weld::TreeIter> xMonthEntry = mxChecks->make_iterator(pLeaf); - if (!mxChecks->iter_parent(*xMonthEntry)) + std::unique_ptr<weld::TreeIter> xMonthEntry = mpChecks->make_iterator(pLeaf); + if (!mpChecks->iter_parent(*xMonthEntry)) xMonthEntry.reset(); else { - xYearEntry = mxChecks->make_iterator(xMonthEntry.get()); - if (!mxChecks->iter_parent(*xYearEntry)) + xYearEntry = mpChecks->make_iterator(xMonthEntry.get()); + if (!mpChecks->iter_parent(*xYearEntry)) xYearEntry.reset(); } @@ -843,15 +848,15 @@ void ScCheckListMenuControl::addDateMember(const OUString& rsName, double nVal, if ( aDayName.getLength() == 1 ) aDayName = "0" + aDayName; - mxChecks->freeze(); + mpChecks->freeze(); std::unique_ptr<weld::TreeIter> xYearEntry = FindEntry(nullptr, aYearName); if (!xYearEntry) { - xYearEntry = mxChecks->make_iterator(); - mxChecks->insert(nullptr, -1, nullptr, nullptr, nullptr, nullptr, false, xYearEntry.get()); - mxChecks->set_toggle(*xYearEntry, TRISTATE_FALSE); - mxChecks->set_text(*xYearEntry, aYearName, 0); + xYearEntry = mpChecks->make_iterator(); + mpChecks->insert(nullptr, -1, nullptr, nullptr, nullptr, nullptr, false, xYearEntry.get()); + mpChecks->set_toggle(*xYearEntry, TRISTATE_FALSE); + mpChecks->set_text(*xYearEntry, aYearName, 0); ScCheckListMember aMemYear; aMemYear.maName = aYearName; aMemYear.maRealName = rsName; @@ -866,10 +871,10 @@ void ScCheckListMenuControl::addDateMember(const OUString& rsName, double nVal, std::unique_ptr<weld::TreeIter> xMonthEntry = FindEntry(xYearEntry.get(), aMonthName); if (!xMonthEntry) { - xMonthEntry = mxChecks->make_iterator(); - mxChecks->insert(xYearEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xMonthEntry.get()); - mxChecks->set_toggle(*xMonthEntry, TRISTATE_FALSE); - mxChecks->set_text(*xMonthEntry, aMonthName, 0); + xMonthEntry = mpChecks->make_iterator(); + mpChecks->insert(xYearEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xMonthEntry.get()); + mpChecks->set_toggle(*xMonthEntry, TRISTATE_FALSE); + mpChecks->set_text(*xMonthEntry, aMonthName, 0); ScCheckListMember aMemMonth; aMemMonth.maName = aMonthName; aMemMonth.maRealName = rsName; @@ -885,10 +890,10 @@ void ScCheckListMenuControl::addDateMember(const OUString& rsName, double nVal, std::unique_ptr<weld::TreeIter> xDayEntry = FindEntry(xMonthEntry.get(), aDayName); if (!xDayEntry) { - xDayEntry = mxChecks->make_iterator(); - mxChecks->insert(xMonthEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xDayEntry.get()); - mxChecks->set_toggle(*xDayEntry, TRISTATE_FALSE); - mxChecks->set_text(*xDayEntry, aDayName, 0); + xDayEntry = mpChecks->make_iterator(); + mpChecks->insert(xMonthEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xDayEntry.get()); + mpChecks->set_toggle(*xDayEntry, TRISTATE_FALSE); + mpChecks->set_text(*xDayEntry, aDayName, 0); ScCheckListMember aMemDay; aMemDay.maName = aDayName; aMemDay.maRealName = rsName; @@ -903,7 +908,7 @@ void ScCheckListMenuControl::addDateMember(const OUString& rsName, double nVal, maMembers.emplace_back(std::move(aMemDay)); } - mxChecks->thaw(); + mpChecks->thaw(); } void ScCheckListMenuControl::addMember(const OUString& rName, bool bVisible) @@ -919,13 +924,13 @@ void ScCheckListMenuControl::addMember(const OUString& rName, bool bVisible) std::unique_ptr<weld::TreeIter> ScCheckListMenuControl::FindEntry(const weld::TreeIter* pParent, const OUString& sNode) { - std::unique_ptr<weld::TreeIter> xEntry = mxChecks->make_iterator(pParent); - bool bEntry = pParent ? mxChecks->iter_children(*xEntry) : mxChecks->get_iter_first(*xEntry); + std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator(pParent); + bool bEntry = pParent ? mpChecks->iter_children(*xEntry) : mpChecks->get_iter_first(*xEntry); while (bEntry) { - if (sNode == mxChecks->get_text(*xEntry, 0)) + if (sNode == mpChecks->get_text(*xEntry, 0)) return xEntry; - bEntry = mxChecks->iter_next_sibling(*xEntry); + bEntry = mpChecks->iter_next_sibling(*xEntry); } return nullptr; } @@ -933,32 +938,32 @@ std::unique_ptr<weld::TreeIter> ScCheckListMenuControl::FindEntry(const weld::Tr void ScCheckListMenuControl::GetRecursiveChecked(const weld::TreeIter* pEntry, std::unordered_set<OUString>& vOut, OUString& rLabel) { - if (mxChecks->get_toggle(*pEntry) != TRISTATE_TRUE) + if (mpChecks->get_toggle(*pEntry) != TRISTATE_TRUE) return; // We have to hash parents and children together. // Per convention for easy access in getResult() // "child;parent;grandparent" while descending. if (rLabel.isEmpty()) - rLabel = mxChecks->get_text(*pEntry, 0); + rLabel = mpChecks->get_text(*pEntry, 0); else - rLabel = mxChecks->get_text(*pEntry, 0) + ";" + rLabel; + rLabel = mpChecks->get_text(*pEntry, 0) + ";" + rLabel; // Prerequisite: the selection mechanism guarantees that if a child is // selected then also the parent is selected, so we only have to // inspect the children in case the parent is selected. - if (!mxChecks->iter_has_child(*pEntry)) + if (!mpChecks->iter_has_child(*pEntry)) return; - std::unique_ptr<weld::TreeIter> xChild(mxChecks->make_iterator(pEntry)); - bool bChild = mxChecks->iter_children(*xChild); + std::unique_ptr<weld::TreeIter> xChild(mpChecks->make_iterator(pEntry)); + bool bChild = mpChecks->iter_children(*xChild); while (bChild) { OUString aLabel = rLabel; GetRecursiveChecked(xChild.get(), vOut, aLabel); if (!aLabel.isEmpty() && aLabel != rLabel) vOut.insert(aLabel); - bChild = mxChecks->iter_next_sibling(*xChild); + bChild = mpChecks->iter_next_sibling(*xChild); } // Let the caller not add the parent alone. rLabel.clear(); @@ -968,15 +973,15 @@ std::unordered_set<OUString> ScCheckListMenuControl::GetAllChecked() { std::unordered_set<OUString> vResults(0); - std::unique_ptr<weld::TreeIter> xEntry = mxChecks->make_iterator(); - bool bEntry = mxChecks->get_iter_first(*xEntry); + std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator(); + bool bEntry = mpChecks->get_iter_first(*xEntry); while (bEntry) { OUString aLabel; GetRecursiveChecked(xEntry.get(), vResults, aLabel); if (!aLabel.isEmpty()) vResults.insert(aLabel); - bEntry = mxChecks->iter_next_sibling(*xEntry); + bEntry = mpChecks->iter_next_sibling(*xEntry); } return vResults; @@ -985,7 +990,7 @@ std::unordered_set<OUString> ScCheckListMenuControl::GetAllChecked() bool ScCheckListMenuControl::IsChecked(const OUString& sName, const weld::TreeIter* pParent) { std::unique_ptr<weld::TreeIter> xEntry = FindEntry(pParent, sName); - return xEntry && mxChecks->get_toggle(*xEntry) == TRISTATE_TRUE; + return xEntry && mpChecks->get_toggle(*xEntry) == TRISTATE_TRUE; } void ScCheckListMenuControl::CheckEntry(const OUString& sName, const weld::TreeIter* pParent, bool bCheck) @@ -998,13 +1003,13 @@ void ScCheckListMenuControl::CheckEntry(const OUString& sName, const weld::TreeI // Recursively check all children of rParent void ScCheckListMenuControl::CheckAllChildren(const weld::TreeIter& rParent, bool bCheck) { - mxChecks->set_toggle(rParent, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE); - std::unique_ptr<weld::TreeIter> xEntry = mxChecks->make_iterator(&rParent); - bool bEntry = mxChecks->iter_children(*xEntry); + mpChecks->set_toggle(rParent, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE); + std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator(&rParent); + bool bEntry = mpChecks->iter_children(*xEntry); while (bEntry) { CheckAllChildren(*xEntry, bCheck); - bEntry = mxChecks->iter_next_sibling(*xEntry); + bEntry = mpChecks->iter_next_sibling(*xEntry); } } @@ -1014,31 +1019,31 @@ void ScCheckListMenuControl::CheckEntry(const weld::TreeIter& rParent, bool bChe CheckAllChildren(rParent, bCheck); // checking rParent can affect ancestors, e.g. if ancestor is unchecked and rParent is // now checked then the ancestor needs to be checked also - if (!mxChecks->get_iter_depth(rParent)) + if (!mpChecks->get_iter_depth(rParent)) return; - std::unique_ptr<weld::TreeIter> xAncestor(mxChecks->make_iterator(&rParent)); - bool bAncestor = mxChecks->iter_parent(*xAncestor); + std::unique_ptr<weld::TreeIter> xAncestor(mpChecks->make_iterator(&rParent)); + bool bAncestor = mpChecks->iter_parent(*xAncestor); while (bAncestor) { // if any first level children checked then ancestor // needs to be checked, similarly if no first level children // checked then ancestor needs to be unchecked - std::unique_ptr<weld::TreeIter> xChild(mxChecks->make_iterator(xAncestor.get())); - bool bChild = mxChecks->iter_children(*xChild); + std::unique_ptr<weld::TreeIter> xChild(mpChecks->make_iterator(xAncestor.get())); + bool bChild = mpChecks->iter_children(*xChild); bool bChildChecked = false; while (bChild) { - if (mxChecks->get_toggle(*xChild) == TRISTATE_TRUE) + if (mpChecks->get_toggle(*xChild) == TRISTATE_TRUE) { bChildChecked = true; break; } - bChild = mxChecks->iter_next_sibling(*xChild); + bChild = mpChecks->iter_next_sibling(*xChild); } - mxChecks->set_toggle(*xAncestor, bChildChecked ? TRISTATE_TRUE : TRISTATE_FALSE); - bAncestor = mxChecks->iter_parent(*xAncestor); + mpChecks->set_toggle(*xAncestor, bChildChecked ? TRISTATE_TRUE : TRISTATE_FALSE); + bAncestor = mpChecks->iter_parent(*xAncestor); } } @@ -1060,50 +1065,50 @@ std::unique_ptr<weld::TreeIter> ScCheckListMenuControl::ShowCheckEntry(const OUS std::unique_ptr<weld::TreeIter> xYearEntry = FindEntry(nullptr, rMember.maDateParts[0]); if (!xYearEntry) { - xYearEntry = mxChecks->make_iterator(); - mxChecks->insert(nullptr, -1, nullptr, nullptr, nullptr, nullptr, false, xYearEntry.get()); - mxChecks->set_toggle(*xYearEntry, TRISTATE_FALSE); - mxChecks->set_text(*xYearEntry, rMember.maDateParts[0], 0); + xYearEntry = mpChecks->make_iterator(); + mpChecks->insert(nullptr, -1, nullptr, nullptr, nullptr, nullptr, false, xYearEntry.get()); + mpChecks->set_toggle(*xYearEntry, TRISTATE_FALSE); + mpChecks->set_text(*xYearEntry, rMember.maDateParts[0], 0); } std::unique_ptr<weld::TreeIter> xMonthEntry = FindEntry(xYearEntry.get(), rMember.maDateParts[1]); if (!xMonthEntry) { - xMonthEntry = mxChecks->make_iterator(); - mxChecks->insert(xYearEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xMonthEntry.get()); - mxChecks->set_toggle(*xMonthEntry, TRISTATE_FALSE); - mxChecks->set_text(*xMonthEntry, rMember.maDateParts[1], 0); + xMonthEntry = mpChecks->make_iterator(); + mpChecks->insert(xYearEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xMonthEntry.get()); + mpChecks->set_toggle(*xMonthEntry, TRISTATE_FALSE); + mpChecks->set_text(*xMonthEntry, rMember.maDateParts[1], 0); } std::unique_ptr<weld::TreeIter> xDayEntry = FindEntry(xMonthEntry.get(), rMember.maName); if (!xDayEntry) { - xDayEntry = mxChecks->make_iterator(); - mxChecks->insert(xMonthEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xDayEntry.get()); - mxChecks->set_toggle(*xDayEntry, TRISTATE_FALSE); - mxChecks->set_text(*xDayEntry, rMember.maName, 0); + xDayEntry = mpChecks->make_iterator(); + mpChecks->insert(xMonthEntry.get(), -1, nullptr, nullptr, nullptr, nullptr, false, xDayEntry.get()); + mpChecks->set_toggle(*xDayEntry, TRISTATE_FALSE); + mpChecks->set_text(*xDayEntry, rMember.maName, 0); } return xDayEntry; // Return leaf node } - xEntry = mxChecks->make_iterator(); - mxChecks->append(xEntry.get()); - mxChecks->set_toggle(*xEntry, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE); - mxChecks->set_text(*xEntry, sName, 0); + xEntry = mpChecks->make_iterator(); + mpChecks->append(xEntry.get()); + mpChecks->set_toggle(*xEntry, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE); + mpChecks->set_text(*xEntry, sName, 0); } else CheckEntry(*xEntry, bCheck); } else if (xEntry) { - mxChecks->remove(*xEntry); + mpChecks->remove(*xEntry); if (rMember.mxParent) { - std::unique_ptr<weld::TreeIter> xParent(mxChecks->make_iterator(rMember.mxParent.get())); - while (xParent && !mxChecks->iter_has_child(*xParent)) + std::unique_ptr<weld::TreeIter> xParent(mpChecks->make_iterator(rMember.mxParent.get())); + while (xParent && !mpChecks->iter_has_child(*xParent)) { - std::unique_ptr<weld::TreeIter> xTmp(mxChecks->make_iterator(xParent.get())); - if (!mxChecks->iter_parent(*xParent)) + std::unique_ptr<weld::TreeIter> xTmp(mpChecks->make_iterator(xParent.get())); + if (!mpChecks->iter_parent(*xParent)) xParent.reset(); - mxChecks->remove(*xTmp); + mpChecks->remove(*xTmp); } } } @@ -1114,8 +1119,8 @@ int ScCheckListMenuControl::GetCheckedEntryCount() const { int nRet = 0; - mxChecks->all_foreach([this, &nRet](weld::TreeIter& rEntry){ - if (mxChecks->get_toggle(rEntry) == TRISTATE_TRUE) + mpChecks->all_foreach([this, &nRet](weld::TreeIter& rEntry){ + if (mpChecks->get_toggle(rEntry) == TRISTATE_TRUE) ++nRet; return false; }); @@ -1129,13 +1134,13 @@ IMPL_LINK(ScCheckListMenuControl, KeyInputHdl, const KeyEvent&, rKEvt, bool) if ( rKey.GetCode() == KEY_RETURN || rKey.GetCode() == KEY_SPACE ) { - std::unique_ptr<weld::TreeIter> xEntry = mxChecks->make_iterator(); - bool bEntry = mxChecks->get_cursor(xEntry.get()); + std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator(); + bool bEntry = mpChecks->get_cursor(xEntry.get()); if (bEntry) { - bool bOldCheck = mxChecks->get_toggle(*xEntry) == TRISTATE_TRUE; + bool bOldCheck = mpChecks->get_toggle(*xEntry) == TRISTATE_TRUE; CheckEntry(*xEntry, !bOldCheck); - bool bNewCheck = mxChecks->get_toggle(*xEntry) == TRISTATE_TRUE; + bool bNewCheck = mpChecks->get_toggle(*xEntry) == TRISTATE_TRUE; if (bOldCheck != bNewCheck) Check(xEntry.get()); } @@ -1148,7 +1153,19 @@ IMPL_LINK(ScCheckListMenuControl, KeyInputHdl, const KeyEvent&, rKEvt, bool) void ScCheckListMenuControl::setHasDates(bool bHasDates) { mbHasDates = bHasDates; - mxChecks->set_show_expanders(mbHasDates); + + /* + tdf#136559 If we have no dates we don't need a tree + structure, just a list. GtkListStore can be then + used which is much faster than a GtkTreeStore, so + with no dates switch to the treeview which uses the + faster GtkListStore + */ + assert(!mpChecks->n_children()); + mpChecks->hide(); + mpChecks = bHasDates ? mxTreeChecks.get() : mxListChecks.get(); + mpChecks->show(); + assert(!mpChecks->n_children()); } namespace @@ -1171,24 +1188,24 @@ size_t ScCheckListMenuControl::initMembers(int nMaxMemberWidth) if (nMaxMemberWidth == -1) nMaxMemberWidth = mnCheckWidthReq; - if (!mxChecks->n_children() && !mbHasDates) + if (!mpChecks->n_children() && !mbHasDates) { std::vector<int> aFixedWidths { nMaxMemberWidth }; // tdf#134038 insert in the fastest order, this might be backwards so only do it for // the !mbHasDates case where no entry depends on another to exist before getting // inserted. We cannot retain pre-existing treeview content, only clear and fill it. - mxChecks->bulk_insert_for_each(n, [this, &nVisMemCount](weld::TreeIter& rIter, int i) { + mpChecks->bulk_insert_for_each(n, [this, &nVisMemCount](weld::TreeIter& rIter, int i) { assert(!maMembers[i].mbDate); - insertMember(*mxChecks, rIter, maMembers[i]); + insertMember(*mpChecks, rIter, maMembers[i]); if (maMembers[i].mbVisible) ++nVisMemCount; }, &aFixedWidths); } else { - mxChecks->freeze(); + mpChecks->freeze(); - std::unique_ptr<weld::TreeIter> xEntry = mxChecks->make_iterator(); + std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator(); std::vector<std::unique_ptr<weld::TreeIter>> aExpandRows; for (size_t i = 0; i < n; ++i) @@ -1206,18 +1223,18 @@ size_t ScCheckListMenuControl::initMembers(int nMaxMemberWidth) } else { - mxChecks->append(xEntry.get()); - insertMember(*mxChecks, *xEntry, maMembers[i]); + mpChecks->append(xEntry.get()); + insertMember(*mpChecks, *xEntry, maMembers[i]); } if (maMembers[i].mbVisible) ++nVisMemCount; } - mxChecks->thaw(); + mpChecks->thaw(); for (auto& rRow : aExpandRows) - mxChecks->expand_row(*rRow); + mpChecks->expand_row(*rRow); } if (nVisMemCount == n) @@ -1239,7 +1256,7 @@ size_t ScCheckListMenuControl::initMembers(int nMaxMemberWidth) } if (nVisMemCount) - mxChecks->select(0); + mpChecks->select(0); return nVisMemCount; } @@ -1272,12 +1289,12 @@ void ScCheckListMenuControl::getResult(ResultType& rResult) // Checked labels are in the form "child;parent;grandparent". if (maMembers[i].mxParent) { - std::unique_ptr<weld::TreeIter> xIter(mxChecks->make_iterator(maMembers[i].mxParent.get())); + std::unique_ptr<weld::TreeIter> xIter(mpChecks->make_iterator(maMembers[i].mxParent.get())); do { - aLabel.append(";").append(mxChecks->get_text(*xIter)); + aLabel.append(";").append(mpChecks->get_text(*xIter)); } - while (mxChecks->iter_parent(*xIter)); + while (mpChecks->iter_parent(*xIter)); } bool bState = vCheckeds.find(aLabel.makeStringAndClear()) != vCheckeds.end(); @@ -1367,8 +1384,8 @@ int ScCheckListMenuControl::IncreaseWindowWidthToFitText(int nMaxTextWidth) if (nNewWidth > mnCheckWidthReq) { mnCheckWidthReq = nNewWidth; - int nChecksHeight = mxChecks->get_height_rows(9); - mxChecks->set_size_request(mnCheckWidthReq, nChecksHeight); + int nChecksHeight = mpChecks->get_height_rows(9); + mpChecks->set_size_request(mnCheckWidthReq, nChecksHeight); } return mnCheckWidthReq + nBorder; } diff --git a/sc/source/ui/inc/checklistmenu.hxx b/sc/source/ui/inc/checklistmenu.hxx index a74775453933..69cb7b92f0fc 100644 --- a/sc/source/ui/inc/checklistmenu.hxx +++ b/sc/source/ui/inc/checklistmenu.hxx @@ -239,7 +239,9 @@ private: std::unique_ptr<weld::TreeIter> mxScratchIter; std::unique_ptr<weld::Entry> mxEdSearch; std::unique_ptr<weld::Widget> mxBox; - std::unique_ptr<weld::TreeView> mxChecks; + std::unique_ptr<weld::TreeView> mxListChecks; + std::unique_ptr<weld::TreeView> mxTreeChecks; + weld::TreeView* mpChecks; std::unique_ptr<weld::CheckButton> mxChkToggleAll; std::unique_ptr<weld::Button> mxBtnSelectSingle; diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index dad20101c4fc..0da30ebc1035 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -660,6 +660,11 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow) // Estimate the width (in pixels) of the longest text in the list ScFilterEntries aFilterEntries; rDoc.GetFilterEntries(nCol, nRow, nTab, aFilterEntries); + + // Set this early so the list or tree widget is selected for use before we might + // use IncreaseWindowWidthToFitText to change its width + rControl.setHasDates(aFilterEntries.mbHasDates); + int nMaxTextWidth = 0; if (aFilterEntries.size() <= 10) { @@ -740,8 +745,6 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow) } // Populate the check box list. - - rControl.setHasDates(aFilterEntries.mbHasDates); rControl.setMemberSize(aFilterEntries.size()); for (const auto& rEntry : aFilterEntries) { diff --git a/sc/uiconfig/scalc/ui/filterdropdown.ui b/sc/uiconfig/scalc/ui/filterdropdown.ui index c84131fd9721..07c484c67ae8 100644 --- a/sc/uiconfig/scalc/ui/filterdropdown.ui +++ b/sc/uiconfig/scalc/ui/filterdropdown.ui @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.22.2 --> +<!-- Generated with glade 3.36.0 --> <interface domain="sw"> <requires lib="gtk+" version="3.18"/> <object class="GtkImage" id="image1"> @@ -22,7 +22,21 @@ <column type="gchararray"/> </columns> </object> - <object class="GtkTreeStore" id="liststore2"> + <object class="GtkListStore" id="liststore2"> + <columns> + <!-- column-name check1 --> + <column type="gboolean"/> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + <!-- column-name checkvis1 --> + <column type="gboolean"/> + <!-- column-name checktri1 --> + <column type="gboolean"/> + </columns> + </object> + <object class="GtkTreeStore" id="treestore2"> <columns> <!-- column-name check1 --> <column type="gboolean"/> @@ -193,50 +207,108 @@ </packing> </child> <child> - <object class="GtkScrolledWindow"> + <object class="GtkBox"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="can_focus">False</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="hscrollbar_policy">automatic</property> - <property name="vscrollbar_policy">automatic</property> - <property name="shadow_type">in</property> <child> - <object class="GtkTreeView" id="check_list_box"> - <property name="visible">True</property> + <object class="GtkScrolledWindow"> <property name="can_focus">True</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="model">liststore2</property> - <property name="headers_visible">False</property> - <property name="headers_clickable">False</property> - <property name="search_column">1</property> - <property name="show_expanders">False</property> - <property name="enable_tree_lines">True</property> - <child internal-child="selection"> - <object class="GtkTreeSelection"/> - </child> + <property name="shadow_type">in</property> <child> - <object class="GtkTreeViewColumn" id="treeviewcolumn4"> - <property name="resizable">True</property> - <property name="spacing">6</property> - <property name="alignment">0.5</property> + <object class="GtkTreeView" id="check_list_box"> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore2</property> + <property name="headers_visible">False</property> + <property name="headers_clickable">False</property> + <property name="search_column">1</property> + <property name="show_expanders">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> + </child> <child> - <object class="GtkCellRendererToggle" id="cellrenderer5"/> - <attributes> - <attribute name="visible">3</attribute> - <attribute name="active">0</attribute> - </attributes> + <object class="GtkTreeViewColumn" id="treeviewcolumn4"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="alignment">0.5</property> + <child> + <object class="GtkCellRendererToggle" id="cellrenderer5"/> + <attributes> + <attribute name="visible">3</attribute> + <attribute name="active">0</attribute> + </attributes> + </child> + <child> + <object class="GtkCellRendererText" id="cellrenderer4"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTreeView" id="check_tree_box"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">treestore2</property> + <property name="headers_visible">False</property> + <property name="headers_clickable">False</property> + <property name="search_column">1</property> + <property name="enable_tree_lines">True</property> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> </child> <child> - <object class="GtkCellRendererText" id="cellrenderer4"/> - <attributes> - <attribute name="text">1</attribute> - </attributes> + <object class="GtkTreeViewColumn" id="treeviewcolumn2"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="alignment">0.5</property> + <child> + <object class="GtkCellRendererToggle" id="cellrenderer1"/> + <attributes> + <attribute name="visible">3</attribute> + <attribute name="active">0</attribute> + </attributes> + </child> + <child> + <object class="GtkCellRendererText" id="cellrenderer2"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> + </object> </child> </object> </child> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> </child> </object> <packing> |