formula/inc/bitmaps.hlst | 2 formula/inc/strings.hrc | 2 formula/source/ui/dlg/formula.cxx | 64 ++++++++++++--- formula/source/ui/dlg/funcpage.cxx | 62 ++++++++++++-- formula/source/ui/dlg/funcpage.hxx | 10 +- formula/uiconfig/ui/formuladialog.ui | 53 ++++++++++-- formula/uiconfig/ui/functionpage.ui | 1 include/formula/IFunctionDescription.hxx | 12 ++ officecfg/registry/schema/org/openoffice/Office/Calc.xcs | 7 + reportdesign/source/ui/dlg/Formula.cxx | 3 reportdesign/source/ui/inc/Formula.hxx | 1 reportdesign/source/ui/inc/FunctionHelper.hxx | 3 reportdesign/source/ui/misc/FunctionHelper.cxx | 14 +++ sc/inc/appoptio.hxx | 3 sc/inc/funcdesc.hxx | 21 ++++ sc/inc/scmod.hxx | 1 sc/source/core/data/funcdesc.cxx | 15 +++ sc/source/core/tool/appoptio.cxx | 29 ++++++ sc/source/ui/app/scmod.cxx | 15 +++ sc/source/ui/formdlg/dwfunctr.cxx | 42 +++++++-- sc/source/ui/formdlg/formula.cxx | 10 ++ sc/source/ui/inc/dwfunctr.hxx | 2 sc/source/ui/inc/formula.hxx | 1 sc/uiconfig/scalc/ui/functionpanel.ui | 1 24 files changed, 331 insertions(+), 43 deletions(-)
New commits: commit dc77629b31423b4df553b7e63579f15445ddeab1 Author: AhmedHamed <[email protected]> AuthorDate: Tue Aug 13 17:12:45 2024 +0300 Commit: Heiko Tietze <[email protected]> CommitDate: Thu Jan 9 15:51:09 2025 +0100 tdf#162286 Add a category to store favorite functions in FW Change-Id: Iec0d169570ba3d29501a4917d8858a9e9438f608 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171828 Tested-by: Jenkins Reviewed-by: Heiko Tietze <[email protected]> diff --git a/formula/inc/bitmaps.hlst b/formula/inc/bitmaps.hlst index 259499f46f33..a99ff98f5acc 100644 --- a/formula/inc/bitmaps.hlst +++ b/formula/inc/bitmaps.hlst @@ -15,5 +15,7 @@ inline constexpr OUString BMP_STR_ERROR = u"formula/res/faperror.png"_ustr; inline constexpr OUString RID_BMP_REFBTN1 = u"formula/res/refinp1.png"_ustr; inline constexpr OUString RID_BMP_REFBTN2 = u"formula/res/refinp2.png"_ustr; inline constexpr OUString BMP_FX = u"formula/res/fx.png"_ustr; +inline constexpr OUString BMP_STAR_EMPTY = u"sc/res/icon-set-stars-empty.png"_ustr; +inline constexpr OUString BMP_STAR_FULL = u"sc/res/icon-set-stars-full.png"_ustr; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/formula/inc/strings.hrc b/formula/inc/strings.hrc index 63551e6deb25..cbb59c6a8efc 100644 --- a/formula/inc/strings.hrc +++ b/formula/inc/strings.hrc @@ -29,5 +29,7 @@ #define STR_END NC_("STR_END", "~End") #define RID_STR_SHRINK NC_("RID_STR_SHRINK", "Shrink") #define RID_STR_EXPAND NC_("RID_STR_EXPAND", "Expand") +#define FAV_ENABLED NC_("FAV_ENABLED", "Add or remove function from favourites") +#define FAV_DISABLED NC_("FAV_DISABLED", "Extention functions can not be added to favourites") /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/formula/source/ui/dlg/formula.cxx b/formula/source/ui/dlg/formula.cxx index 1d1b3c6c624e..2fd606b89029 100644 --- a/formula/source/ui/dlg/formula.cxx +++ b/formula/source/ui/dlg/formula.cxx @@ -45,11 +45,13 @@ #include <com/sun/star/sheet/FormulaMapGroupSpecialOffset.hpp> #include <com/sun/star/sheet/XFormulaOpCodeMapper.hpp> #include <com/sun/star/sheet/XFormulaParser.hpp> +#include <bitmaps.hlst> #include <map> // For tab page #define TOKEN_OPEN 0 #define TOKEN_CLOSE 1 + namespace formula { @@ -117,6 +119,7 @@ public: DECL_LINK( FormulaHdl, weld::TextView&, void); DECL_LINK( FormulaCursorHdl, weld::TextView&, void ); DECL_LINK( BtnHdl, weld::Button&, void ); + DECL_LINK( FavToggleHdl, weld::Button&, void ); DECL_LINK( DblClkHdl, FuncPage&, void ); DECL_LINK( FuncSelHdl, FuncPage&, void ); DECL_LINK( StructSelHdl, StructPage&, void ); @@ -167,6 +170,8 @@ public: std::unique_ptr<weld::Label> m_xFtFuncName; std::unique_ptr<weld::Label> m_xFtFuncDesc; + std::unique_ptr<weld::Button> m_xBtnFavorites; + std::unique_ptr<weld::Label> m_xFtEditName; std::unique_ptr<weld::Label> m_xFtResult; @@ -230,6 +235,7 @@ FormulaDlg_Impl::FormulaDlg_Impl(weld::Dialog& rDialog, , m_xFtHeadLine(rBuilder.weld_label(u"headline"_ustr)) , m_xFtFuncName(rBuilder.weld_label(u"funcname"_ustr)) , m_xFtFuncDesc(rBuilder.weld_label(u"funcdesc"_ustr)) + , m_xBtnFavorites(rBuilder.weld_button(u"favorites"_ustr)) , m_xFtEditName(rBuilder.weld_label(u"editname"_ustr)) , m_xFtResult(rBuilder.weld_label(u"label2"_ustr)) , m_xWndResult(rBuilder.weld_entry(u"result"_ustr)) @@ -287,6 +293,9 @@ FormulaDlg_Impl::FormulaDlg_Impl(weld::Dialog& rDialog, m_aOldHelp = m_rDialog.get_help_id(); // HelpId from resource always for "Page 1" + m_xBtnFavorites->connect_clicked(LINK(this, FormulaDlg_Impl, FavToggleHdl)); + m_xBtnFavorites->hide(); + m_xFtResult->set_visible( _bSupportResult ); m_xWndResult->set_visible( _bSupportResult ); @@ -863,6 +872,7 @@ void FormulaDlg_Impl::FillControls( bool &rbNext, bool &rbPrev) const bool bTestFlag = (pOldFuncDesc != m_pFuncDesc); if (bTestFlag) { + m_xBtnFavorites->hide(); m_xFtHeadLine->hide(); m_xFtFuncName->hide(); m_xFtFuncDesc->hide(); @@ -965,6 +975,7 @@ void FormulaDlg_Impl::ClearAllParas() m_xParaWinBox->hide(); m_xBtnForward->set_sensitive(true); //@new + m_xBtnFavorites->show(); m_xFtHeadLine->show(); m_xFtFuncName->show(); m_xFtFuncDesc->show(); @@ -1058,6 +1069,27 @@ IMPL_LINK(FormulaDlg_Impl, BtnHdl, weld::Button&, rBtn, void) } } +IMPL_LINK_NOARG(FormulaDlg_Impl, FavToggleHdl, weld::Button&, void) +{ + const IFunctionDescription* pDesc = m_xFuncPage->GetFuncDesc(); + if (!pDesc) + return; + + if (m_xFuncPage->IsFavourite(m_xFuncPage->GetFuncIndex())) + { + m_pHelper->insertOrEraseFavouritesListEntry(pDesc, false); + m_xBtnFavorites->set_from_icon_name(BMP_STAR_EMPTY); + } + else + { + m_pHelper->insertOrEraseFavouritesListEntry(pDesc, true); + m_xBtnFavorites->set_from_icon_name(BMP_STAR_FULL); + } + m_xFuncPage->UpdateFavouritesList(); + if (m_xFuncPage->GetCategory() == FAVOURITES_CATEGORY) + m_xFuncPage->UpdateFunctionList(u""_ustr); +} + // Functions for 1. Page // Handler for Listboxes @@ -1667,23 +1699,25 @@ IMPL_LINK_NOARG( FormulaDlg_Impl, MatrixHdl, weld::Toggleable&, void) IMPL_LINK_NOARG( FormulaDlg_Impl, FuncSelHdl, FuncPage&, void) { - if ( (m_xFuncPage->GetFunctionEntryCount() > 0) - && (m_xFuncPage->GetFunction() != -1) ) - { - const IFunctionDescription* pDesc = m_xFuncPage->GetFuncDesc(); + const IFunctionDescription* pDesc = m_xFuncPage->GetFuncDesc(); + const sal_uInt16 nFIndex = m_xFuncPage->GetFuncIndex(); + m_xBtnFavorites->set_sensitive(true); + if (pDesc) + { if (pDesc != m_pFuncDesc) m_xBtnForward->set_sensitive(true); //new - if (pDesc) - { - pDesc->initArgumentInfo(); // full argument info is needed + pDesc->initArgumentInfo(); // full argument info is needed + OUString aSig = pDesc->getSignature(); + m_xFtHeadLine->set_label( pDesc->getFunctionName() ); + m_xFtFuncName->set_label( aSig ); + m_xFtFuncDesc->set_label( pDesc->getDescription() ); - OUString aSig = pDesc->getSignature(); - m_xFtHeadLine->set_label( pDesc->getFunctionName() ); - m_xFtFuncName->set_label( aSig ); - m_xFtFuncDesc->set_label( pDesc->getDescription() ); - } + if (m_xFuncPage->IsFavourite(nFIndex)) + m_xBtnFavorites->set_from_icon_name(BMP_STAR_FULL); + else + m_xBtnFavorites->set_from_icon_name(BMP_STAR_EMPTY); } else { @@ -1691,6 +1725,12 @@ IMPL_LINK_NOARG( FormulaDlg_Impl, FuncSelHdl, FuncPage&, void) m_xFtFuncName->set_label( OUString() ); m_xFtFuncDesc->set_label( OUString() ); } + + m_xBtnFavorites->set_visible(m_xFtHeadLine->is_visible() + && m_xFtHeadLine->get_label() != u""_ustr); + m_xBtnFavorites->set_sensitive(nFIndex != 0); + m_xBtnFavorites->set_tooltip_text(nFIndex == 0 ? ForResId(FAV_DISABLED) + : ForResId(FAV_ENABLED)); } void FormulaDlg_Impl::UpdateParaWin( const Selection& _rSelection, const OUString& _sRefStr) diff --git a/formula/source/ui/dlg/funcpage.cxx b/formula/source/ui/dlg/funcpage.cxx index 60d1e5adf2a0..315899926680 100644 --- a/formula/source/ui/dlg/funcpage.cxx +++ b/formula/source/ui/dlg/funcpage.cxx @@ -40,7 +40,7 @@ IMPL_LINK(FuncPage, KeyInputHdl, const KeyEvent&, rKEvt, bool) } // tdf#104487 - remember last used function category - set default to All category -sal_Int32 FuncPage::m_nRememberedFunctionCategory = 1; +sal_Int32 FuncPage::m_nRememberedFunctionCategory = ALL_CATEGORY; FuncPage::FuncPage(weld::Container* pParent, const IFunctionManager* _pFunctionManager) : m_xBuilder(Application::CreateBuilder(pParent, u"formula/ui/functionpage.ui"_ustr)) @@ -56,6 +56,7 @@ FuncPage::FuncPage(weld::Container* pParent, const IFunctionManager* _pFunctionM m_aHelpId = m_xLbFunction->get_help_id(); m_pFunctionManager->fillLastRecentlyUsedFunctions(aLRUList); + m_pFunctionManager->fillFavouriteFunctions(aFavouritesList); const sal_uInt32 nCategoryCount = m_pFunctionManager->getCount(); for (sal_uInt32 j = 0; j < nCategoryCount; ++j) @@ -100,6 +101,24 @@ weld::TreeIter* FuncPage::FillCategoriesMap(const OUString& aCategory, bool bFil return mCategories[aCategory].get(); } +bool FuncPage::IsFavourite(sal_uInt16 nFIndex) const +{ + return aFavouritesList.find(nFIndex) != aFavouritesList.end(); +} + +bool FuncPage::UpdateFavouritesList() +{ + sal_uInt16 nFIndex = GetFuncIndex(); + if (nFIndex == 0) + return false; + + if (IsFavourite(nFIndex)) + aFavouritesList.erase(nFIndex); + else + aFavouritesList.insert(nFIndex); + return true; +} + void FuncPage::impl_addFunctions(const IFunctionCategory* _pCategory, bool bFillCategories) { weld::TreeIter* pCategoryIter = FillCategoriesMap(_pCategory->getName(), bFillCategories); @@ -141,17 +160,17 @@ void FuncPage::UpdateFunctionList(const OUString& aStr) sFuncScores.clear(); const sal_Int32 nSelPos = m_xLbCategory->get_active(); - bool bCollapse = nSelPos == 1; + bool bCollapse = nSelPos == ALL_CATEGORY; bool bFilter = !aStr.isEmpty(); // tdf#104487 - remember last used function category m_nRememberedFunctionCategory = nSelPos; - if (!bFilter || nSelPos == 0) + if (!bFilter || nSelPos == LRU_CATEGORY || nSelPos == FAVOURITES_CATEGORY) { const IFunctionCategory* pCategory = weld::fromId<const IFunctionCategory*>(m_xLbCategory->get_id(nSelPos)); - if (nSelPos > 0) + if (nSelPos >= ALL_CATEGORY) { if (pCategory == nullptr) { @@ -166,7 +185,7 @@ void FuncPage::UpdateFunctionList(const OUString& aStr) impl_addFunctions(pCategory, false); } } - else // LRU-List + else if (nSelPos == LRU_CATEGORY) // LRU-List { for (auto const& elem : aLRUList) { @@ -180,6 +199,24 @@ void FuncPage::UpdateFunctionList(const OUString& aStr) } } } + else // Favourites-List + { + for (const auto& elem : aFavouritesList) + { + if (m_pFunctionManager->Get(elem)) + { + TFunctionDesc pDesc(m_pFunctionManager->Get(elem)); + if (pDesc && !pDesc->isHidden()) + { + OUString aFunction(pDesc->getFunctionName()); + OUString sId(weld::toId(pDesc)); + + m_xLbFunction->insert(nullptr, -1, &aFunction, &sId, nullptr, nullptr, + false, m_xScratchIter.get()); + } + } + } + } } else { @@ -249,11 +286,12 @@ void FuncPage::UpdateFunctionList(const OUString& aStr) IMPL_LINK_NOARG(FuncPage, SelComboBoxHdl, weld::ComboBox&, void) { - if (m_xLbCategory->get_active() == 0) + if (m_xLbCategory->get_active() == LRU_CATEGORY + || m_xLbCategory->get_active() == FAVOURITES_CATEGORY) m_xLbFunctionSearchString->set_text(u""_ustr); m_xHelpButton->set_sensitive(false); - OUString searchStr = m_xLbFunctionSearchString->get_text(); m_xLbFunction->set_help_id(m_aHelpId); + OUString searchStr = m_xLbFunctionSearchString->get_text(); UpdateFunctionList(searchStr); } @@ -290,9 +328,10 @@ IMPL_LINK_NOARG(FuncPage, DblClkHdl, weld::TreeView&, bool) IMPL_LINK_NOARG(FuncPage, ModifyHdl, weld::Entry&, void) { - if (m_xLbCategory->get_active() == 0) + if (m_xLbCategory->get_active() == LRU_CATEGORY + || m_xLbCategory->get_active() == FAVOURITES_CATEGORY) { - m_xLbCategory->set_active(1); + m_xLbCategory->set_active(ALL_CATEGORY); m_xHelpButton->set_sensitive(false); } OUString searchStr = m_xLbFunctionSearchString->get_text(); @@ -354,6 +393,11 @@ sal_Int32 FuncPage::GetFunctionEntryCount() const { return m_xLbFunction->n_chil OUString FuncPage::GetSelFunctionName() const { return m_xLbFunction->get_selected_text(); } +sal_uInt16 FuncPage::GetFuncIndex() const +{ + return m_pFunctionManager->getFunctionIndex(GetFuncDesc()); +} + const IFunctionDescription* FuncPage::GetFuncDesc() const { if (GetFunction() == -1) diff --git a/formula/source/ui/dlg/funcpage.hxx b/formula/source/ui/dlg/funcpage.hxx index 010bca872832..9fcd1c0b02c6 100644 --- a/formula/source/ui/dlg/funcpage.hxx +++ b/formula/source/ui/dlg/funcpage.hxx @@ -23,6 +23,7 @@ #include <vector> #include <set> #include <unordered_map> +#include <unordered_set> namespace formula { @@ -51,6 +52,7 @@ private: const IFunctionManager* m_pFunctionManager; ::std::vector< TFunctionDesc > aLRUList; + ::std::unordered_set<sal_uInt16> aFavouritesList; ::std::unordered_map<OUString, std::unique_ptr<weld::TreeIter>> mCategories; ::std::set<std::pair<std::pair<sal_Int32, sal_Int32>, std::pair<OUString, TFunctionDesc>>> sFuncScores; @@ -70,8 +72,6 @@ private: DECL_LINK(SelHelpClickHdl, weld::Button&, void); DECL_LINK(SimilarityToggleHdl, weld::Toggleable&, void); - void UpdateFunctionList(const OUString&); - public: FuncPage(weld::Container* pContainer, const IFunctionManager* _pFunctionManager); @@ -91,6 +91,7 @@ public: sal_Int32 GetFuncPos(const IFunctionDescription* _pDesc); const IFunctionDescription* GetFuncDesc() const; OUString GetSelFunctionName() const; + sal_uInt16 GetFuncIndex() const; void SetDoubleClickHdl( const Link<FuncPage&,void>& rLink ) { aDoubleClickLink = rLink; } @@ -98,6 +99,11 @@ public: bool IsVisible() const { return m_xContainer->get_visible(); } + bool IsFavourite(sal_uInt16) const; + + bool UpdateFavouritesList(); + void UpdateFunctionList(const OUString&); + void SearchFunction(const OUString&, const OUString&, TFunctionDesc, const bool); }; diff --git a/formula/uiconfig/ui/formuladialog.ui b/formula/uiconfig/ui/formuladialog.ui index 1bb11eefe9ba..d43ec78daa6c 100644 --- a/formula/uiconfig/ui/formuladialog.ui +++ b/formula/uiconfig/ui/formuladialog.ui @@ -183,7 +183,7 @@ </object> <packing> <property name="resize">False</property> - <property name="shrink">True</property> + <property name="shrink">False</property> </packing> </child> <child> @@ -285,18 +285,55 @@ <property name="vexpand">True</property> <property name="row-spacing">12</property> <child> - <object class="GtkLabel" id="headline"> + <object class="GtkBox"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="hexpand">True</property> - <property name="wrap">True</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> + <property name="vexpand">False</property> + <property name="orientation">horizontal</property> + <property name="spacing">2</property> + <child> + <object class="GtkButton" id="favorites"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="tooltip-text" translatable="yes" context="formuladialog|favorites|tooltip_text">Add or remove function from favourites</property> + <property name="hexpand">False</property> + <property name="vexpand">False</property> + <property name="halign">start</property> + <property name="valign">center</property> + <property name="relief">none</property> + <property name="border-width">6</property> + <property name="focus-on-click">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="headline"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <property name="wrap">True</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> </object> <packing> + <property name="expand">False</property> + <property name="fill">True</property> <property name="left-attach">0</property> <property name="top-attach">0</property> </packing> diff --git a/formula/uiconfig/ui/functionpage.ui b/formula/uiconfig/ui/functionpage.ui index c48beb6918ac..c867539ce6e9 100644 --- a/formula/uiconfig/ui/functionpage.ui +++ b/formula/uiconfig/ui/functionpage.ui @@ -93,6 +93,7 @@ <property name="can-focus">False</property> <items> <item translatable="yes" context="functionpage|category">Last Used</item> + <item translatable="yes" context="functionpage|category">Favourites</item> <item translatable="yes" context="functionpage|category">All</item> </items> <child internal-child="accessible"> diff --git a/include/formula/IFunctionDescription.hxx b/include/formula/IFunctionDescription.hxx index d511089a274b..70a4ca052f35 100644 --- a/include/formula/IFunctionDescription.hxx +++ b/include/formula/IFunctionDescription.hxx @@ -22,12 +22,18 @@ #include <memory> #include <vector> +#include <unordered_set> +#include <unordered_map> #include <com/sun/star/table/CellAddress.hpp> #include <com/sun/star/uno/Reference.hxx> #include <rtl/ustring.hxx> #include <sal/types.h> +#define LRU_CATEGORY 0 +#define FAVOURITES_CATEGORY 1 +#define ALL_CATEGORY 2 + namespace com::sun::star { namespace sheet { struct FormulaToken; } namespace sheet { class XFormulaOpCodeMapper; } @@ -57,13 +63,18 @@ namespace formula eTableRefOpen, eTableRefClose }; + + virtual const IFunctionDescription* Get(sal_uInt16 nFIndex) const = 0; virtual sal_uInt32 getCount() const = 0; virtual const IFunctionCategory* getCategory(sal_uInt32 nPos) const = 0; + virtual sal_uInt16 getFunctionIndex(const IFunctionDescription* _pDesc) const = 0; virtual void fillLastRecentlyUsedFunctions(::std::vector< const IFunctionDescription*>& _rLastRUFunctions) const = 0; + virtual void fillFavouriteFunctions(::std::unordered_set<sal_uInt16>& rFavouriteFunctions) const = 0; virtual sal_Unicode getSingleToken(const EToken _eToken) const = 0; protected: + bool changeFavouriteList; ~IFunctionManager() {} }; @@ -150,6 +161,7 @@ namespace formula virtual void dispatch(bool _bOK, bool _bMatrixChecked) = 0; virtual void doClose(bool _bOk) = 0; virtual void insertEntryToLRUList(const IFunctionDescription* pDesc) = 0; + virtual void insertOrEraseFavouritesListEntry(const IFunctionDescription* pDesc, bool bInsert) = 0; virtual void showReference(const OUString& _sFormula) = 0; protected: diff --git a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs index 22e14c4421fe..854b480bc424 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs @@ -762,6 +762,13 @@ </constraints> <value>224 226 222 223 6</value> </prop> + <prop oor:name="FavouriteFunctions" oor:type="oor:int-list" oor:nillable="false"> + <info> + <desc>Specifies the favourite functions.</desc> + <label>Favourite Functions</label> + </info> + <value></value> + </prop> <prop oor:name="AutoInput" oor:type="xs:boolean" oor:nillable="false"> <!-- UIHints: Tools Cell Contents AutoInput --> <info> diff --git a/reportdesign/source/ui/dlg/Formula.cxx b/reportdesign/source/ui/dlg/Formula.cxx index ec1fc754549b..83a358d5495d 100644 --- a/reportdesign/source/ui/dlg/Formula.cxx +++ b/reportdesign/source/ui/dlg/Formula.cxx @@ -126,6 +126,9 @@ void FormulaDialog::doClose(bool _bOk) void FormulaDialog::insertEntryToLRUList(const IFunctionDescription* /*_pDesc*/) { } +void FormulaDialog::insertOrEraseFavouritesListEntry(const IFunctionDescription* /*_pDesc*/, bool) +{ +} void FormulaDialog::showReference(const OUString& /*_sFormula*/) { } diff --git a/reportdesign/source/ui/inc/Formula.hxx b/reportdesign/source/ui/inc/Formula.hxx index 9271d68e5a15..48d163e1a054 100644 --- a/reportdesign/source/ui/inc/Formula.hxx +++ b/reportdesign/source/ui/inc/Formula.hxx @@ -77,6 +77,7 @@ public: virtual std::unique_ptr<formula::FormulaCompiler> createCompiler( formula::FormulaTokenArray& rArray ) const override; virtual void doClose(bool _bOk) override; virtual void insertEntryToLRUList(const formula::IFunctionDescription* pDesc) override; + virtual void insertOrEraseFavouritesListEntry(const formula::IFunctionDescription* pDesc, bool bInsert) override; virtual void showReference(const OUString& _sFormula) override; virtual void dispatch(bool _bOK, bool _bMatrixChecked) override; virtual void setDispatcherLock( bool bLock ) override; diff --git a/reportdesign/source/ui/inc/FunctionHelper.hxx b/reportdesign/source/ui/inc/FunctionHelper.hxx index 2d9fbed18cbd..7288d99df6e0 100644 --- a/reportdesign/source/ui/inc/FunctionHelper.hxx +++ b/reportdesign/source/ui/inc/FunctionHelper.hxx @@ -45,9 +45,12 @@ class FunctionManager : public formula::IFunctionManager public: FunctionManager(css::uno::Reference< css::report::meta::XFunctionManager> _xMgr); virtual ~FunctionManager(); + virtual const formula::IFunctionDescription* Get(sal_uInt16 nFIndex) const override; virtual sal_uInt32 getCount() const override; virtual const formula::IFunctionCategory* getCategory(sal_uInt32 nPos) const override; + virtual sal_uInt16 getFunctionIndex(const formula::IFunctionDescription* _pDesc) const override; virtual void fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& _rLastRUFunctions) const override; + virtual void fillFavouriteFunctions(::std::unordered_set<sal_uInt16>& rFavouriteFunctions) const override; virtual sal_Unicode getSingleToken(const EToken _eToken) const override; std::shared_ptr< FunctionDescription > get(const css::uno::Reference< css::report::meta::XFunctionDescription>& _xFunctionDescription) const; diff --git a/reportdesign/source/ui/misc/FunctionHelper.cxx b/reportdesign/source/ui/misc/FunctionHelper.cxx index ec3a2650cb33..e4ec31aad8e2 100644 --- a/reportdesign/source/ui/misc/FunctionHelper.cxx +++ b/reportdesign/source/ui/misc/FunctionHelper.cxx @@ -59,6 +59,11 @@ sal_Unicode FunctionManager::getSingleToken(const formula::IFunctionManager::ETo return 0; } +const formula::IFunctionDescription* FunctionManager::Get(sal_uInt16 /*nFIndex*/) const +{ + return nullptr; +} + sal_uInt32 FunctionManager::getCount() const { return m_xMgr->getCount(); @@ -75,10 +80,19 @@ const formula::IFunctionCategory* FunctionManager::getCategory(sal_uInt32 _nPos) return m_aCategoryIndex[_nPos]->second.get(); } +sal_uInt16 FunctionManager::getFunctionIndex(const formula::IFunctionDescription* /*_pDesc*/) const +{ + return 0; +} + void FunctionManager::fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& /*_rLastRUFunctions*/) const { } +void FunctionManager::fillFavouriteFunctions(::std::unordered_set<sal_uInt16>& /*rFavouriteFunctions*/) const +{ +} + std::shared_ptr< FunctionDescription > FunctionManager::get(const uno::Reference< report::meta::XFunctionDescription>& _xFunctionDescription) const { std::shared_ptr< FunctionDescription > pDesc; diff --git a/sc/inc/appoptio.hxx b/sc/inc/appoptio.hxx index d9e22c9cba78..af637c5dbdef 100644 --- a/sc/inc/appoptio.hxx +++ b/sc/inc/appoptio.hxx @@ -48,6 +48,8 @@ public: sal_uInt16* GetLRUFuncList() const { return pLRUList.get(); } void SetLRUFuncList( const sal_uInt16* pList, const sal_uInt16 nCount ); + std::unordered_set<sal_uInt16> GetFavouritesList() const { return sFavouritesList; } + void SetFavouritesList(const std::unordered_set<sal_uInt16>& rList) { sFavouritesList = rList; } void SetStatusFunc( sal_uInt32 nNew ) { nStatusFunc = nNew; } sal_uInt32 GetStatusFunc() const { return nStatusFunc; } void SetAutoComplete( bool bNew ) { bAutoComplete = bNew; } @@ -87,6 +89,7 @@ private: sal_uInt16 nLRUFuncCount; std::unique_ptr<sal_uInt16[]> pLRUList; + std::unordered_set<sal_uInt16> sFavouritesList; SvxZoomType eZoomType; sal_uInt16 nZoom; bool bSynchronizeZoom; diff --git a/sc/inc/funcdesc.hxx b/sc/inc/funcdesc.hxx index 49b718dbd1ae..21026a401828 100644 --- a/sc/inc/funcdesc.hxx +++ b/sc/inc/funcdesc.hxx @@ -28,6 +28,7 @@ #include <rtl/ustring.hxx> #include <optional> #include <map> +#include <unordered_set> #include <memory> #define MAX_FUNCCAT 12 /* maximum number of categories for functions */ @@ -336,7 +337,7 @@ public: @return pointer to function with the index nFIndex, null if no such function was found. */ - const ScFuncDesc* Get( sal_uInt16 nFIndex ) const; + const formula::IFunctionDescription* Get( sal_uInt16 nFIndex ) const override; /** Returns the first function in category nCategory. @@ -374,6 +375,16 @@ public: */ virtual const formula::IFunctionCategory* getCategory(sal_uInt32 nPos) const override; + /** + Returns the index of the function. + + @param _pDesc + Pointer to function description + + @return The index of the function if not null, 0 otherwise. + */ + virtual sal_uInt16 getFunctionIndex(const formula::IFunctionDescription* _pDesc) const override; + /** Appends the last recently used functions. @@ -384,6 +395,14 @@ public: */ virtual void fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& _rLastRUFunctions) const override; + /** + Appends favourite functions to the given vector. + + @param rFavouriteFunctions + a vector of pointer to IFunctionDescription, by reference. + */ + virtual void fillFavouriteFunctions(std::unordered_set<sal_uInt16>& rFavouriteFunctions) const override; + /** Maps Etoken to character diff --git a/sc/inc/scmod.hxx b/sc/inc/scmod.hxx index 3811a9334fa6..fd19d67df5d9 100644 --- a/sc/inc/scmod.hxx +++ b/sc/inc/scmod.hxx @@ -173,6 +173,7 @@ public: SC_DLLPUBLIC void SetInputOptions ( const ScInputOptions& rOpt ); void SetPrintOptions ( const ScPrintOptions& rOpt ); void InsertEntryToLRUList(sal_uInt16 nFIndex); + void InsertOrEraseFavouritesListEntry(sal_uInt16 nFIndex, bool bInsert); static void GetSpellSettings( LanguageType& rDefLang, LanguageType& rCjkLang, LanguageType& rCtlLang ); static void SetAutoSpellProperty( bool bSet ); diff --git a/sc/source/core/data/funcdesc.cxx b/sc/source/core/data/funcdesc.cxx index 6ca1b262792c..f3eae4ea07ab 100644 --- a/sc/source/core/data/funcdesc.cxx +++ b/sc/source/core/data/funcdesc.cxx @@ -1081,7 +1081,7 @@ ScFunctionMgr::~ScFunctionMgr() } -const ScFuncDesc* ScFunctionMgr::Get( sal_uInt16 nFIndex ) const +const formula::IFunctionDescription* ScFunctionMgr::Get( sal_uInt16 nFIndex ) const { const ScFuncDesc* pDesc; for (pDesc = First(); pDesc; pDesc = Next()) @@ -1137,6 +1137,12 @@ const formula::IFunctionCategory* ScFunctionMgr::getCategory(sal_uInt32 nCategor return nullptr; } +sal_uInt16 ScFunctionMgr::getFunctionIndex(const formula::IFunctionDescription* _pDesc) const +{ + const ScFuncDesc* pDesc = dynamic_cast<const ScFuncDesc*>(_pDesc); + return pDesc ? pDesc->nFIndex : 0; +} + void ScFunctionMgr::fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& _rLastRUFunctions) const { const ScAppOptions& rAppOpt = ScModule::get()->GetAppOptions(); @@ -1153,6 +1159,13 @@ void ScFunctionMgr::fillLastRecentlyUsedFunctions(::std::vector< const formula:: } } +void ScFunctionMgr::fillFavouriteFunctions(std::unordered_set<sal_uInt16>& rFavouriteFunctions) const +{ + const ScAppOptions& rAppOpt = ScModule::get()->GetAppOptions(); + rFavouriteFunctions.clear(); + rFavouriteFunctions = rAppOpt.GetFavouritesList(); +} + OUString ScFunctionMgr::GetCategoryName(sal_uInt32 _nCategoryNumber ) { if (_nCategoryNumber >= SC_FUNCGROUP_COUNT) diff --git a/sc/source/core/tool/appoptio.cxx b/sc/source/core/tool/appoptio.cxx index 0115be53db76..e6137341094d 100644 --- a/sc/source/core/tool/appoptio.cxx +++ b/sc/source/core/tool/appoptio.cxx @@ -26,6 +26,7 @@ #include <miscuno.hxx> #include <vector> #include <osl/diagnose.h> +#include <comphelper/sequence.hxx> using namespace utl; using namespace com::sun::star::uno; @@ -90,6 +91,7 @@ ScAppOptions& ScAppOptions::operator=( const ScAppOptions& rCpy ) bSynchronizeZoom = rCpy.bSynchronizeZoom; nZoom = rCpy.nZoom; SetLRUFuncList( rCpy.pLRUList.get(), rCpy.nLRUFuncCount ); + SetFavouritesList(rCpy.sFavouritesList); nStatusFunc = rCpy.nStatusFunc; bAutoComplete = rCpy.bAutoComplete; bDetectiveAuto = rCpy.bDetectiveAuto; @@ -139,6 +141,11 @@ static void lcl_GetLastFunctions( Any& rDest, const ScAppOptions& rOpt ) rDest <<= Sequence<sal_Int32>(0); // empty } +static void lcl_GetFavouriteFunctions(Any& rDest, const ScAppOptions& rOpt) +{ + rDest <<= comphelper::containerToSequence<sal_Int32>(rOpt.GetFavouritesList()); +} + static void lcl_GetSortList( Any& rDest ) { const ScUserList& rUserList = ScGlobal::GetUserList(); @@ -162,8 +169,9 @@ constexpr OUStringLiteral CFGPATH_LAYOUT = u"Office.Calc/Layout"; constexpr OUStringLiteral CFGPATH_INPUT = u"Office.Calc/Input"; #define SCINPUTOPT_LASTFUNCS 0 -#define SCINPUTOPT_AUTOINPUT 1 -#define SCINPUTOPT_DET_AUTO 2 +#define SCINPUTOPT_FAVOURITEFUNCS 1 +#define SCINPUTOPT_AUTOINPUT 2 +#define SCINPUTOPT_DET_AUTO 3 constexpr OUStringLiteral CFGPATH_REVISION = u"Office.Calc/Revision/Color"; @@ -225,6 +233,7 @@ Sequence<OUString> ScAppCfg::GetLayoutPropertyNames() Sequence<OUString> ScAppCfg::GetInputPropertyNames() { return {u"LastFunctions"_ustr, // SCINPUTOPT_LASTFUNCS + u"FavouriteFunctions"_ustr, // SCINPUTOPT_FAVOURITEFUNCS u"AutoInput"_ustr, // SCINPUTOPT_AUTOINPUT u"DetectiveAuto"_ustr}; // SCINPUTOPT_DET_AUTO } @@ -363,6 +372,19 @@ void ScAppCfg::ReadInputCfg() SetLRUFuncList(pUShorts.data(), nLRUCount); } } + + if (Sequence<sal_Int32> aSeq; aValues[SCINPUTOPT_FAVOURITEFUNCS] >>= aSeq) + { + sal_Int32 nCount = aSeq.getLength(); + if (nCount < SAL_MAX_UINT16) + { + sal_uInt16 nFavouritesCount = nCount; + std::unordered_set<sal_uInt16> sFavouriteFunctions; + for (sal_uInt16 i = 0; i < nFavouritesCount; ++i) + sFavouriteFunctions.insert(aSeq[i]); + SetFavouritesList(sFavouriteFunctions); + } + } SetAutoComplete(ScUnoHelpFunctions::GetBoolFromAny(aValues[SCINPUTOPT_AUTOINPUT])); SetDetectiveAuto(ScUnoHelpFunctions::GetBoolFromAny(aValues[SCINPUTOPT_DET_AUTO])); } @@ -515,6 +537,9 @@ IMPL_LINK_NOARG(ScAppCfg, InputCommitHdl, ScLinkConfigItem&, void) case SCINPUTOPT_DET_AUTO: pValues[nProp] <<= GetDetectiveAuto(); break; + case SCINPUTOPT_FAVOURITEFUNCS: + lcl_GetFavouriteFunctions(pValues[nProp], *this); + break; } } aInputItem.PutProperties(aNames, aValues); diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx index e5f940bbbe34..84238486fa6b 100644 --- a/sc/source/ui/app/scmod.cxx +++ b/sc/source/ui/app/scmod.cxx @@ -785,6 +785,21 @@ void ScModule::InsertEntryToLRUList(sal_uInt16 nFIndex) SetAppOptions(aNewOpts); } +void ScModule::InsertOrEraseFavouritesListEntry(sal_uInt16 nFIndex, bool bInsert) +{ + const ScAppOptions& rAppOpt = GetAppOptions(); + std::unordered_set<sal_uInt16> sFavouriteFunctions = rAppOpt.GetFavouritesList(); + + if (bInsert) + sFavouriteFunctions.insert(nFIndex); + else + sFavouriteFunctions.erase(nFIndex); + + ScAppOptions aNewOpts(rAppOpt); + aNewOpts.SetFavouritesList(sFavouriteFunctions); + SetAppOptions(aNewOpts); +} + void ScModule::SetAppOptions( const ScAppOptions& rOpt ) { if ( !m_pAppCfg ) diff --git a/sc/source/ui/formdlg/dwfunctr.cxx b/sc/source/ui/formdlg/dwfunctr.cxx index 3345e1f83f95..e46a4edd582c 100644 --- a/sc/source/ui/formdlg/dwfunctr.cxx +++ b/sc/source/ui/formdlg/dwfunctr.cxx @@ -64,6 +64,7 @@ ScFunctionWin::ScFunctionWin(weld::Widget* pParent) , pFuncDesc(nullptr) { InitLRUList(); + UpdateFavouritesList(); nArgs=0; m_aListHelpId = xFuncList->get_help_id(); @@ -141,6 +142,14 @@ void ScFunctionWin::InitLRUList() UpdateFunctionList(u""_ustr); } +void ScFunctionWin::UpdateFavouritesList() +{ + ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr(); + pFuncMgr->fillFavouriteFunctions(aFavouritesList); + + if (xCatBox->get_active() == 0) + UpdateFunctionList(u""_ustr); +} /************************************************************************* #* Member: FillCategoriesMap @@ -263,16 +272,16 @@ void ScFunctionWin::UpdateFunctionList(const OUString& rSearchString) { sal_Int32 nSelPos = xCatBox->get_active(); sal_Int32 nCategory = ( -1 != nSelPos ) - ? (nSelPos-1) : 0; + ? (nSelPos-ALL_CATEGORY) : 0; xFuncList->clear(); xFuncList->freeze(); mCategories.clear(); sFuncScores.clear(); - bool bCollapse = nCategory == 0; + bool bCollapse = nSelPos == ALL_CATEGORY; bool bFilter = !rSearchString.isEmpty(); - if ( nSelPos > 0 ) + if (nSelPos >= ALL_CATEGORY) { ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr(); @@ -314,7 +323,7 @@ void ScFunctionWin::UpdateFunctionList(const OUString& rSearchString) xScratchIter.get()); } } - else // LRU list + else if (nSelPos == LRU_CATEGORY) // LRU list { for (const formula::IFunctionDescription* pDesc : aLRUList) { @@ -328,6 +337,22 @@ void ScFunctionWin::UpdateFunctionList(const OUString& rSearchString) } } } + else // Favourites List + { + ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr(); + for (const auto& elem : aFavouritesList) + { + const formula::IFunctionDescription* pDesc(pFuncMgr->Get(elem)); + if (pDesc) + { + OUString aFunction(pDesc->getFunctionName()); + OUString aFuncDescId(weld::toId(pDesc)); + + xFuncList->insert(nullptr, -1, &aFunction, &aFuncDescId, nullptr, nullptr, false, + xScratchIter.get()); + } + } + } xFuncList->thaw(); @@ -487,9 +512,9 @@ void ScFunctionWin::DoEnter(bool bDoubleOrEnter) IMPL_LINK_NOARG(ScFunctionWin, ModifyHdl, weld::Entry&, void) { - if (xCatBox->get_active() == 0) + if (xCatBox->get_active() == LRU_CATEGORY || xCatBox->get_active() == FAVOURITES_CATEGORY) { - xCatBox->set_active(1); + xCatBox->set_active(ALL_CATEGORY); xHelpButton->set_sensitive(false); } OUString searchStr = m_xSearchString->get_text(); @@ -591,10 +616,11 @@ IMPL_LINK(ScFunctionWin, KeyInputHdl, const KeyEvent&, rEvent, bool) IMPL_LINK_NOARG(ScFunctionWin, SelComboHdl, weld::ComboBox&, void) { - if (xCatBox->get_active() == 0) + if (xCatBox->get_active() == LRU_CATEGORY || xCatBox->get_active() == FAVOURITES_CATEGORY) m_xSearchString->set_text(u""_ustr); - xHelpButton->set_sensitive(xCatBox->get_active() != 1); + xHelpButton->set_sensitive(xCatBox->get_active() != ALL_CATEGORY); OUString searchStr = m_xSearchString->get_text(); + UpdateFavouritesList(); UpdateFunctionList(searchStr); SetDescription(); } diff --git a/sc/source/ui/formdlg/formula.cxx b/sc/source/ui/formdlg/formula.cxx index 9af2adbe7472..a2cd6b4e568a 100644 --- a/sc/source/ui/formdlg/formula.cxx +++ b/sc/source/ui/formdlg/formula.cxx @@ -512,6 +512,16 @@ void ScFormulaDlg::insertEntryToLRUList(const formula::IFunctionDescription* const ScFuncDesc* pDesc = dynamic_cast<const ScFuncDesc*>(_pDesc); SaveLRUEntry(pDesc); } + +void ScFormulaDlg::insertOrEraseFavouritesListEntry(const formula::IFunctionDescription* _pDesc, bool bInsert) +{ + const ScFuncDesc* pDesc = dynamic_cast<const ScFuncDesc*>(_pDesc); + if (pDesc && pDesc->nFIndex != 0) + { + ScModule::get()->InsertOrEraseFavouritesListEntry(pDesc->nFIndex, bInsert); + } +} + void ScFormulaDlg::showReference(const OUString& _sFormula) { ShowReference(_sFormula); diff --git a/sc/source/ui/inc/dwfunctr.hxx b/sc/source/ui/inc/dwfunctr.hxx index 9c05491dac2d..e66b02270cbe 100644 --- a/sc/source/ui/inc/dwfunctr.hxx +++ b/sc/source/ui/inc/dwfunctr.hxx @@ -63,9 +63,11 @@ private: ::std::set<std::pair<std::pair<sal_Int32, sal_Int32>, std::pair<OUString, const ScFuncDesc*>>> sFuncScores; ::std::vector< const formula::IFunctionDescription*> aLRUList; + ::std::unordered_set<sal_uInt16> aFavouritesList; ::std::unordered_map<OUString, std::unique_ptr<weld::TreeIter>> mCategories; void UpdateLRUList(); + void UpdateFavouritesList(); void DoEnter(bool bDouble_or_Enter = false); void SetDescription(); weld::TreeIter* FillCategoriesMap(const OUString&, bool); diff --git a/sc/source/ui/inc/formula.hxx b/sc/source/ui/inc/formula.hxx index 02ee866c1bc9..db6ef49f6b45 100644 --- a/sc/source/ui/inc/formula.hxx +++ b/sc/source/ui/inc/formula.hxx @@ -57,6 +57,7 @@ public: virtual std::unique_ptr<formula::FormulaCompiler> createCompiler( formula::FormulaTokenArray& rArray ) const override; virtual void doClose(bool _bOk) override; virtual void insertEntryToLRUList(const formula::IFunctionDescription* pDesc) override; + virtual void insertOrEraseFavouritesListEntry(const formula::IFunctionDescription* pDesc, bool bInsert) override; virtual void showReference(const OUString& _sFormula) override; virtual void dispatch(bool _bOK, bool _bMatrixChecked) override; virtual void setDispatcherLock( bool bLock ) override; diff --git a/sc/uiconfig/scalc/ui/functionpanel.ui b/sc/uiconfig/scalc/ui/functionpanel.ui index f2bade14020e..d9c68d35f4cf 100644 --- a/sc/uiconfig/scalc/ui/functionpanel.ui +++ b/sc/uiconfig/scalc/ui/functionpanel.ui @@ -67,6 +67,7 @@ <property name="hexpand">True</property> <items> <item translatable="yes" context="functionpanel|category">Last Used</item> + <item translatable="yes" context="functionpanel|category">Favourites</item> <item translatable="yes" context="functionpanel|category">All</item> <item translatable="yes" context="functionpanel|category">Database</item> <item translatable="yes" context="functionpanel|category">Date&Time</item>
