cui/source/inc/numpages.hxx | 9 + cui/source/tabpages/numpages.cxx | 86 +++++++++++-------- cui/uiconfig/ui/pickbulletpage.ui | 46 +++++----- sw/qa/uitest/writer_tests2/formatBulletsNumbering.py | 38 +++++--- 4 files changed, 104 insertions(+), 75 deletions(-)
New commits: commit 541a19edde3da18e4e979597cc5ed5482386b726 Author: Parth Raiyani <[email protected]> AuthorDate: Mon Aug 25 20:50:13 2025 +0530 Commit: Caolán McNamara <[email protected]> CommitDate: Tue Feb 24 20:50:51 2026 +0100 Switch to IconView from ValueSet for pick bullet page - Replaced SvxNumValueSet with weld::IconView in numpages - Updated UI in pickbulletpage.ui to include GtkIconView and GtkTreeStore - added tooltip support - update relevant test cases Change-Id: I3686773e787a1d028dd5c6c116a60c9de63fd151 Signed-off-by: Parth Raiyani <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189846 Reviewed-by: Szymon Kłos <[email protected]> Tested-by: Szymon Kłos <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200210 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Caolán McNamara <[email protected]> diff --git a/cui/source/inc/numpages.hxx b/cui/source/inc/numpages.hxx index 2c82a6eece90..d1b2b80e58d6 100644 --- a/cui/source/inc/numpages.hxx +++ b/cui/source/inc/numpages.hxx @@ -97,13 +97,14 @@ class SvxBulletPickTabPage final : public SfxTabPage OUString sBulletCharFormatName; std::unique_ptr<weld::Button> m_xBtChangeBullet; - std::unique_ptr<SvxNumValueSet> m_xExamplesVS; - std::unique_ptr<weld::CustomWeld> m_xExamplesVSWin; + std::unique_ptr<weld::IconView> m_xExamplesIV; + Size aPreviewSize; css::uno::Sequence<OUString> m_aBulletSymbols; css::uno::Sequence<OUString> m_aBulletSymbolsFonts; - DECL_LINK(NumSelectHdl_Impl, ValueSet*, void); - DECL_LINK(DoubleClickHdl_Impl, ValueSet*, void); + DECL_LINK(NumSelectHdl_Impl, weld::IconView&, void); + DECL_LINK(DoubleClickHdl_Impl, weld::IconView&, bool); + DECL_LINK(QueryTooltipHdl, const weld::TreeIter&, OUString); DECL_LINK(ClickAddChangeHdl_Impl, weld::Button&, void); public: SvxBulletPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); diff --git a/cui/source/tabpages/numpages.cxx b/cui/source/tabpages/numpages.cxx index 3d3e5083294f..90837e8b9254 100644 --- a/cui/source/tabpages/numpages.cxx +++ b/cui/source/tabpages/numpages.cxx @@ -79,6 +79,19 @@ #include <bitmaps.hlst> +#include <vcl/virdev.hxx> +#include <i18nlangtag/mslangid.hxx> +#include <editeng/svxenum.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <svx/svxbmpnumiconview.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::text; +using namespace com::sun::star::container; +using namespace com::sun::star::style; + using namespace css; using namespace css::uno; using namespace css::beans; @@ -132,21 +145,6 @@ static bool lcl_IsNumFmtSet(SvxNumRule const * pNum, sal_uInt16 nLevelMask) return bRet; } -static vcl::Font& lcl_GetDefaultBulletFont() -{ - static vcl::Font aDefBulletFont = []() - { - vcl::Font tmp(u"OpenSymbol"_ustr, u""_ustr, Size(0, 14)); - tmp.SetCharSet( RTL_TEXTENCODING_SYMBOL ); - tmp.SetFamily( FAMILY_DONTKNOW ); - tmp.SetPitch( PITCH_DONTKNOW ); - tmp.SetWeight( WEIGHT_DONTKNOW ); - tmp.SetTransparent( true ); - return tmp; - }(); - return aDefBulletFont; -} - SvxSingleNumPickTabPage::SvxSingleNumPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) : SfxTabPage(pPage, pController, u"cui/ui/picknumberingpage.ui"_ustr, u"PickNumberingPage"_ustr, &rSet) , nActNumLvl(SAL_MAX_UINT16) @@ -334,14 +332,15 @@ SvxBulletPickTabPage::SvxBulletPickTabPage(weld::Container* pPage, weld::DialogC , bPreset(false) , nNumItemId(SID_ATTR_NUMBERING_RULE) , m_xBtChangeBullet(m_xBuilder->weld_button(u"changeBulletBtn"_ustr)) - , m_xExamplesVS(new SvxNumValueSet(m_xBuilder->weld_scrolled_window(u"valuesetwin"_ustr, true))) - , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *m_xExamplesVS)) + , m_xExamplesIV(m_xBuilder->weld_icon_view(u"pick_bullet_iconview"_ustr)) + , aPreviewSize(150, 200) { SetExchangeSupport(); m_xBtChangeBullet->set_sensitive(false); - m_xExamplesVS->init(NumberingPageType::BULLET); - m_xExamplesVS->SetSelectHdl(LINK(this, SvxBulletPickTabPage, NumSelectHdl_Impl)); - m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxBulletPickTabPage, DoubleClickHdl_Impl)); + SvxBmpNumIconView::PopulateIconView(m_xExamplesIV.get(), NumberingPageType::BULLET, aPreviewSize); + m_xExamplesIV->connect_selection_changed(LINK(this, SvxBulletPickTabPage, NumSelectHdl_Impl)); + m_xExamplesIV->connect_item_activated(LINK(this, SvxBulletPickTabPage, DoubleClickHdl_Impl)); + m_xExamplesIV->connect_query_tooltip(LINK(this, SvxBulletPickTabPage, QueryTooltipHdl)); m_xBtChangeBullet->connect_clicked(LINK(this, SvxBulletPickTabPage, ClickAddChangeHdl_Impl)); m_aBulletSymbols = officecfg::Office::Common::BulletsNumbering::DefaultBullets::get(); m_aBulletSymbolsFonts = officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get(); @@ -349,8 +348,7 @@ SvxBulletPickTabPage::SvxBulletPickTabPage(weld::Container* pPage, weld::DialogC SvxBulletPickTabPage::~SvxBulletPickTabPage() { - m_xExamplesVSWin.reset(); - m_xExamplesVS.reset(); + m_xExamplesIV.reset(); } std::unique_ptr<SfxTabPage> SvxBulletPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController, @@ -389,13 +387,13 @@ void SvxBulletPickTabPage::ActivatePage(const SfxItemSet& rSet) if(pActNum && *pSaveNum != *pActNum) { *pActNum = *pSaveNum; - m_xExamplesVS->SetNoSelection(); + m_xExamplesIV->unselect_all(); } if(pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset)) { - m_xExamplesVS->SelectItem(1); - NumSelectHdl_Impl(m_xExamplesVS.get()); + m_xExamplesIV->select(0); + NumSelectHdl_Impl(*m_xExamplesIV); bPreset = true; } else if (pActNum) @@ -407,7 +405,7 @@ void SvxBulletPickTabPage::ActivatePage(const SfxItemSet& rSet) const sal_uInt16 nLevel = svx::sidebar::NBOTypeMgrBase::IsSingleLevel(nActNumLvl); SvxNumberFormat aFmt(pActNum->GetLevel(nLevel)); if (aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL) - m_xExamplesVS->SelectItem(pChoices->GetNBOIndexForNumRule(*pActNum, nActNumLvl)); + m_xExamplesIV->select(pChoices->GetNBOIndexForNumRule(*pActNum, nActNumLvl) - 1); } } @@ -453,7 +451,17 @@ void SvxBulletPickTabPage::Reset( const SfxItemSet* rSet ) *pActNum = *pSaveNum; } -IMPL_LINK_NOARG(SvxBulletPickTabPage, NumSelectHdl_Impl, ValueSet*, void) +IMPL_LINK(SvxBulletPickTabPage, QueryTooltipHdl, const weld::TreeIter&, rIter, OUString) +{ + const OUString sId = m_xExamplesIV->get_id(rIter); + if (sId.isEmpty()) + return OUString(); + + sal_Int32 nIndex = sId.toInt32(); + return SvxBmpNumIconView::GetNumberingDescription(NumberingPageType::BULLET, nIndex); +} + +IMPL_LINK_NOARG(SvxBulletPickTabPage, NumSelectHdl_Impl, weld::IconView&, void) { if(!pActNum) return; @@ -462,9 +470,10 @@ IMPL_LINK_NOARG(SvxBulletPickTabPage, NumSelectHdl_Impl, ValueSet*, void) bPreset = false; bModified = true; - sal_uInt16 nIndex = m_xExamplesVS->GetSelectedItemId() - 1; + OUString sId = m_xExamplesIV->get_selected_id(); + sal_uInt16 nIndex = !sId.isEmpty() ? sId.toInt32() : 0; sal_Unicode cChar = m_aBulletSymbols[nIndex].toChar(); - vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont(); + vcl::Font& rActBulletFont = SvxBmpNumIconView::GetDefaultBulletFont(); rActBulletFont.SetFamilyName(m_aBulletSymbolsFonts[nIndex]); sal_uInt16 nMask = 1; @@ -486,11 +495,16 @@ IMPL_LINK_NOARG(SvxBulletPickTabPage, NumSelectHdl_Impl, ValueSet*, void) } } -IMPL_LINK_NOARG(SvxBulletPickTabPage, DoubleClickHdl_Impl, ValueSet*, void) +IMPL_LINK_NOARG(SvxBulletPickTabPage, DoubleClickHdl_Impl, weld::IconView&, bool) { - NumSelectHdl_Impl(m_xExamplesVS.get()); + if(m_xExamplesIV->get_selected_id().isEmpty()) + return false; + + NumSelectHdl_Impl(*m_xExamplesIV); weld::Button& rOk = GetDialogController()->GetOKButton(); rOk.clicked(); + + return true; } IMPL_LINK_NOARG(SvxBulletPickTabPage, ClickAddChangeHdl_Impl, weld::Button&, void) @@ -551,7 +565,8 @@ IMPL_LINK_NOARG(SvxBulletPickTabPage, ClickAddChangeHdl_Impl, weld::Button&, voi auto aBulletSymbolsListRange = asNonConstRange(aBulletSymbolsList); auto aBulletSymbolsFontsListRange = asNonConstRange(aBulletSymbolsFontsList); - sal_uInt16 nIndex = m_xExamplesVS->GetSelectedItemId() - 1; + OUString sId = m_xExamplesIV->get_selected_id(); + sal_uInt16 nIndex = !sId.isEmpty() ? sId.toInt32() : 0; for (size_t i = 0; i < m_aBulletSymbols.size(); ++i) { if (i == nIndex) @@ -571,8 +586,7 @@ IMPL_LINK_NOARG(SvxBulletPickTabPage, ClickAddChangeHdl_Impl, weld::Button&, voi officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::set(aBulletSymbolsFontsList, batch); batch->commit(); - m_xExamplesVS->SetFormat(); - m_xExamplesVS->Invalidate(); + SvxBmpNumIconView::PopulateIconView(m_xExamplesIV.get(), NumberingPageType::BULLET, aPreviewSize); } void SvxBulletPickTabPage::PageCreated(const SfxAllItemSet& aSet) @@ -740,7 +754,7 @@ IMPL_LINK_NOARG(SvxNumPickTabPage, NumSelectHdl_Impl, ValueSet*, void) SvxNumSettingsArr_Impl& rItemArr = aNumSettingsArrays[m_xExamplesVS->GetSelectedItemId() - 1]; - const vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont(); + const vcl::Font& rActBulletFont = SvxBmpNumIconView::GetDefaultBulletFont(); SvxNumSettings_Impl* pLevelSettings = nullptr; for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) { @@ -1179,7 +1193,7 @@ SvxNumOptionsTabPage::SvxNumOptionsTabPage(weld::Container* pPage, weld::DialogC m_xBulRelSizeMF->set_min(SVX_NUM_REL_SIZE_MIN, FieldUnit::PERCENT); m_xBulRelSizeMF->set_increments(5, 50, FieldUnit::PERCENT); SetExchangeSupport(); - aActBulletFont = lcl_GetDefaultBulletFont(); + aActBulletFont = SvxBmpNumIconView::GetDefaultBulletFont(); // vertical alignment = fill makes the drawingarea expand the associated spinedits so we have to size it here const sal_Int16 aHeight = static_cast<sal_Int16>(std::max(int(m_xRatioCB->get_preferred_size().getHeight() / 2 diff --git a/cui/uiconfig/ui/pickbulletpage.ui b/cui/uiconfig/ui/pickbulletpage.ui index b8fe43ca04c2..345b00c358c6 100644 --- a/cui/uiconfig/ui/pickbulletpage.ui +++ b/cui/uiconfig/ui/pickbulletpage.ui @@ -2,6 +2,14 @@ <!-- Generated with glade 3.40.0 --> <interface domain="cui"> <requires lib="gtk+" version="3.24"/> + <object class="GtkTreeStore" id="liststore1"> + <columns> + <!-- column-name pixbuf --> + <column type="GdkPixbuf"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> <object class="GtkGrid" id="PickBulletPage"> <property name="visible">True</property> <property name="can-focus">False</property> @@ -13,7 +21,7 @@ <property name="vexpand">True</property> <property name="row-spacing">6</property> <child> - <object class="GtkScrolledWindow" id="valusetwin"> + <object class="GtkScrolledWindow"> <property name="visible">True</property> <property name="can-focus">True</property> <property name="hexpand">True</property> @@ -22,28 +30,26 @@ <property name="vscrollbar-policy">never</property> <property name="shadow-type">in</property> <child> - <object class="GtkViewport"> + <object class="GtkIconView" id="pick_bullet_iconview"> <property name="visible">True</property> - <property name="can-focus">False</property> - <child> - <object class="GtkDrawingArea" id="valueset"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> - <child internal-child="accessible"> - <object class="AtkObject" id="valueset-atkobject"> - <property name="AtkObject::accessible-description" translatable="yes" context="pickbulletpage|extended_tip|valueset">Click the bullet style that you want to use.</property> - </object> - </child> + <property name="can-focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore1</property> + <property name="pixbuf-column">0</property> + <property name="columns">4</property> + <property name="item-width">80</property> + <property name="selection-mode">single</property> + <child internal-child="accessible"> + <object class="AtkObject" id="pick_bullet_iconview-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="pickbulletpage|extended_tip|pick_bullet_iconview">Click the bullet style that you want to use.</property> </object> </child> </object> </child> </object> <packing> - <property name="left-attach">1</property> + <property name="left-attach">0</property> <property name="top-attach">0</property> </packing> </child> @@ -55,10 +61,10 @@ <property name="receives-default">False</property> <property name="halign">end</property> </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">2</property> - </packing> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">1</property> + </packing> </child> <child internal-child="accessible"> <object class="AtkObject" id="PickBulletPage-atkobject"> diff --git a/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py b/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py index f240cfee7152..22ed41059543 100644 --- a/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py +++ b/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py @@ -26,11 +26,13 @@ class formatBulletsNumbering(UITestCase): xTabs = xDialog.getChild("tabcontrol") select_pos(xTabs, "0") xBulletPage = xDialog.getChild("PickBulletPage") - xSelector = xBulletPage.getChild("valueset") + xSelector = xBulletPage.getChild("pick_bullet_iconview") # Select element number 3 - xSelector.executeAction("CHOOSE", mkPropertyValues({"POS": "3"})) - self.assertEqual(get_state_as_dict(xSelector)["SelectedItemId"], "3") + element3 = xSelector.getChild("2") + element3.executeAction("SELECT", mkPropertyValues({})) + self.assertEqual(get_state_as_dict(xSelector)["VisibleCount"], "8") + self.assertEqual(get_state_as_dict(xSelector)["SelectedItemId"], "2") xChangeBulletBtn = xBulletPage.getChild("changeBulletBtn") with self.ui_test.execute_blocking_action(xChangeBulletBtn.executeAction, args=('CLICK', ())) as xCharSetDialog: xCharSet = xCharSetDialog.getChild("showcharset") @@ -42,11 +44,13 @@ class formatBulletsNumbering(UITestCase): xTabs = xDialog.getChild("tabcontrol") select_pos(xTabs, "0") xBulletPage = xDialog.getChild("PickBulletPage") - xSelector = xBulletPage.getChild("valueset") + xSelector = xBulletPage.getChild("pick_bullet_iconview") # Select element number 3 - xSelector.executeAction("CHOOSE", mkPropertyValues({"POS": "3"})) - self.assertEqual(get_state_as_dict(xSelector)["SelectedItemId"], "3") + element3 = xSelector.getChild("2") + element3.executeAction("SELECT", mkPropertyValues({})) + self.assertEqual(get_state_as_dict(xSelector)["VisibleCount"], "8") + self.assertEqual(get_state_as_dict(xSelector)["SelectedItemId"], "2") xChangeBulletBtn = xBulletPage.getChild("changeBulletBtn") with self.ui_test.execute_blocking_action(xChangeBulletBtn.executeAction, args=('CLICK', ())) as xCharSetDialog: xHexText = xCharSetDialog.getChild("hexvalue") @@ -240,16 +244,19 @@ class formatBulletsNumbering(UITestCase): xTabs = xDialog.getChild("tabcontrol") select_pos(xTabs, "0") xBulletPage = xDialog.getChild("PickBulletPage") - xselector = xBulletPage.getChild("valueset") - self.assertEqual(get_state_as_dict(xselector)["ItemsCount"], "8") + xselector = xBulletPage.getChild("pick_bullet_iconview") # Select element num 3 - xselector.executeAction("CHOOSE", mkPropertyValues({"POS": "3"})) + element3 = xselector.getChild("2") + element3.executeAction("SELECT", mkPropertyValues({})) + self.assertEqual(get_state_as_dict(xselector)["VisibleCount"], "8") self.assertEqual(get_state_as_dict(xselector)["SelectedItemPos"], "2") - self.assertEqual(get_state_as_dict(xselector)["SelectedItemId"], "3") + self.assertEqual(get_state_as_dict(xselector)["SelectedItemId"], "2") # Select element num 7 - xselector.executeAction("CHOOSE", mkPropertyValues({"POS": "7"})) + element7 = xselector.getChild("6") + element7.executeAction("SELECT", mkPropertyValues({})) + self.assertEqual(get_state_as_dict(xselector)["VisibleCount"], "8") self.assertEqual(get_state_as_dict(xselector)["SelectedItemPos"], "6") - self.assertEqual(get_state_as_dict(xselector)["SelectedItemId"], "7") + self.assertEqual(get_state_as_dict(xselector)["SelectedItemId"], "6") # Test other Pages with self.ui_test.execute_dialog_through_command(".uno:BulletsAndNumberingDialog") as xDialog: @@ -315,11 +322,12 @@ class formatBulletsNumbering(UITestCase): xTabs = xDialog.getChild("tabcontrol") select_pos(xTabs, "0") xBulletPage = xDialog.getChild("PickBulletPage") - xSelector = xBulletPage.getChild("valueset") + xSelector = xBulletPage.getChild("pick_bullet_iconview") # Select element number 1 - xSelector.executeAction("CHOOSE", mkPropertyValues({"POS": "1"})) - self.assertEqual(get_state_as_dict(xSelector)["SelectedItemId"], "1") + element1 = xSelector.getChild("0") + element1.executeAction("SELECT", mkPropertyValues({})) + self.assertEqual(get_state_as_dict(xSelector)["SelectedItemId"], "0") xChangeBulletBtn = xBulletPage.getChild("changeBulletBtn") with self.ui_test.execute_blocking_action(xChangeBulletBtn.executeAction, args=('CLICK', ())) as xCharSetDialog: # Select the DejaVu Sans font because that should contain the character
