summaryrefslogtreecommitdiffstats
path: root/cui/source/customize/CommandCategoryListBox.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /cui/source/customize/CommandCategoryListBox.cxx
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'cui/source/customize/CommandCategoryListBox.cxx')
-rw-r--r--cui/source/customize/CommandCategoryListBox.cxx607
1 files changed, 607 insertions, 0 deletions
diff --git a/cui/source/customize/CommandCategoryListBox.cxx b/cui/source/customize/CommandCategoryListBox.cxx
new file mode 100644
index 000000000..f6b34076f
--- /dev/null
+++ b/cui/source/customize/CommandCategoryListBox.cxx
@@ -0,0 +1,607 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <CommandCategoryListBox.hxx>
+
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XDispatchInformationProvider.hpp>
+#include <com/sun/star/frame/theUICommandDescription.hpp>
+#include <com/sun/star/ui/theUICategoryDescription.hpp>
+#include <com/sun/star/script/browse/XBrowseNode.hpp>
+#include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
+#include <com/sun/star/script/browse/theBrowseNodeFactory.hpp>
+#include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
+#include <vcl/commandinfoprovider.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+
+// include search util
+#include <com/sun/star/util/SearchFlags.hpp>
+#include <com/sun/star/util/SearchAlgorithms2.hpp>
+#include <tools/diagnose_ex.h>
+#include <unotools/textsearch.hxx>
+
+#include <dialmgr.hxx>
+#include <strings.hrc>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <comphelper/SetFlagContextHelper.hxx>
+#include <comphelper/string.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <i18nutil/searchopt.hxx>
+#include <sal/log.hxx>
+
+#include <cfg.hxx> //for SaveInData
+
+CommandCategoryListBox::CommandCategoryListBox(std::unique_ptr<weld::ComboBox> xControl)
+ : pStylesInfo(nullptr)
+ , m_xControl(std::move(xControl))
+{
+ //Initialize search util
+ m_searchOptions.AlgorithmType2 = css::util::SearchAlgorithms2::ABSOLUTE;
+ m_searchOptions.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
+ m_searchOptions.searchFlag |= (css::util::SearchFlags::REG_NOT_BEGINOFLINE
+ | css::util::SearchFlags::REG_NOT_ENDOFLINE);
+}
+
+CommandCategoryListBox::~CommandCategoryListBox() { ClearAll(); }
+
+void CommandCategoryListBox::ClearAll()
+{
+ // Clear objects from m_aGroupInfo vector to avoid memory leak
+ for (const auto& It : m_aGroupInfo)
+ {
+ if (It->nKind == SfxCfgKind::GROUP_STYLES && It->pObject)
+ {
+ SfxStyleInfo_Impl* pStyle = static_cast<SfxStyleInfo_Impl*>(It->pObject);
+ delete pStyle;
+ }
+ else if (It->nKind == SfxCfgKind::FUNCTION_SCRIPT && It->pObject)
+ {
+ OUString* pScriptURI = static_cast<OUString*>(It->pObject);
+ delete pScriptURI;
+ }
+ else if (It->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER && It->pObject)
+ {
+ css::uno::XInterface* xi = static_cast<css::uno::XInterface*>(It->pObject);
+ if (xi != nullptr)
+ {
+ xi->release();
+ }
+ }
+ }
+
+ m_aGroupInfo.clear();
+ m_xControl->clear();
+}
+
+void CommandCategoryListBox::Init(const css::uno::Reference<css::uno::XComponentContext>& xContext,
+ const css::uno::Reference<css::frame::XFrame>& xFrame,
+ const OUString& sModuleLongName)
+{
+ // User will not see incomplete UI
+ m_xControl->freeze();
+ ClearAll();
+
+ m_xContext = xContext;
+ m_xFrame = xFrame;
+
+ m_sModuleLongName = sModuleLongName;
+ m_xGlobalCategoryInfo = css::ui::theUICategoryDescription::get(m_xContext);
+ m_xModuleCategoryInfo.set(m_xGlobalCategoryInfo->getByName(m_sModuleLongName),
+ css::uno::UNO_QUERY_THROW);
+ m_xUICmdDescription = css::frame::theUICommandDescription::get(m_xContext);
+
+ // Support style commands
+ css::uno::Reference<css::frame::XController> xController;
+ css::uno::Reference<css::frame::XModel> xModel;
+ if (xFrame.is())
+ xController = xFrame->getController();
+ if (xController.is())
+ xModel = xController->getModel();
+
+ m_aStylesInfo.init(sModuleLongName, xModel);
+ SetStylesInfo(&m_aStylesInfo);
+
+ try
+ {
+ css::uno::Reference<css::frame::XDispatchInformationProvider> xProvider(
+ m_xFrame, css::uno::UNO_QUERY_THROW);
+ css::uno::Sequence<sal_Int16> lGroups = xProvider->getSupportedCommandGroups();
+
+ sal_Int32 nGroupsLength = lGroups.getLength();
+
+ if (nGroupsLength > 0)
+ {
+ // Add the category of "All commands"
+ m_aGroupInfo.push_back(
+ std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_ALLFUNCTIONS, 0));
+ m_xControl->append(weld::toId(m_aGroupInfo.back().get()),
+ CuiResId(RID_CUISTR_ALLFUNCTIONS));
+ }
+
+ // Separate the "All commands"category from the actual categories
+ m_xControl->append_separator("");
+
+ typedef std::pair<OUString, sal_Int16> str_id;
+ std::vector<str_id> aCategories;
+
+ // Add the actual categories
+ for (sal_Int32 i = 0; i < nGroupsLength; ++i)
+ {
+ sal_Int16 nGroupID = lGroups[i];
+ OUString sGroupID = OUString::number(nGroupID);
+ OUString sGroupName;
+
+ try
+ {
+ m_xModuleCategoryInfo->getByName(sGroupID) >>= sGroupName;
+ if (sGroupName.isEmpty())
+ continue;
+ }
+ catch (const css::container::NoSuchElementException&)
+ {
+ continue;
+ }
+ aCategories.emplace_back(std::make_pair(sGroupName, nGroupID));
+ }
+
+ auto const sort = comphelper::string::NaturalStringSorter(
+ comphelper::getProcessComponentContext(),
+ Application::GetSettings().GetUILanguageTag().getLocale());
+
+ std::sort(aCategories.begin(), aCategories.end(),
+ [&sort](const str_id& a, const str_id& b) {
+ return sort.compare(a.first, b.first) < 0;
+ });
+
+ // Add the actual categories
+ for (const auto& a : aCategories)
+ {
+ const OUString& rGroupName = a.first;
+ sal_Int16 nGroupID = a.second;
+ m_aGroupInfo.push_back(
+ std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_FUNCTION, nGroupID));
+ m_xControl->append(weld::toId(m_aGroupInfo.back().get()), rGroupName);
+ }
+
+ // Separate regular commands from styles and macros
+ m_xControl->append_separator("");
+
+ // Add macros category
+ m_aGroupInfo.push_back(
+ std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, nullptr));
+ m_xControl->append(weld::toId(m_aGroupInfo.back().get()), CuiResId(RID_CUISTR_MACROS));
+
+ // Add styles category
+ //TODO: last param should contain user data?
+ m_aGroupInfo.push_back(
+ std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_STYLES, 0, nullptr));
+ m_xControl->append(weld::toId(m_aGroupInfo.back().get()),
+ CuiResId(RID_CUISTR_GROUP_STYLES));
+ }
+ catch (const css::uno::RuntimeException&)
+ {
+ throw;
+ }
+ catch (const css::uno::Exception&)
+ {
+ }
+
+ // Reveal the updated UI to user
+ m_xControl->thaw();
+ m_xControl->set_active(0);
+}
+
+void CommandCategoryListBox::FillFunctionsList(
+ const css::uno::Sequence<css::frame::DispatchInformation>& xCommands,
+ CuiConfigFunctionListBox* pFunctionListBox, const OUString& filterTerm,
+ SaveInData* pCurrentSaveInData)
+{
+ // Setup search filter parameters
+ m_searchOptions.searchString = filterTerm;
+ utl::TextSearch textSearch(m_searchOptions);
+ const bool bInExperimentalMode = officecfg::Office::Common::Misc::ExperimentalMode::get();
+
+ for (const auto& rInfo : xCommands)
+ {
+ auto aProperties
+ = vcl::CommandInfoProvider::GetCommandProperties(rInfo.Command, m_sModuleLongName);
+
+ OUString sUIName = getCommandName(rInfo.Command);
+ OUString sLabel = vcl::CommandInfoProvider::GetLabelForCommand(aProperties);
+ OUString sTooltipLabel
+ = vcl::CommandInfoProvider::GetTooltipForCommand(rInfo.Command, aProperties, m_xFrame);
+ OUString sPopupLabel = (vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties))
+ .replaceFirst("~", "");
+ bool bIsExperimental
+ = vcl::CommandInfoProvider::IsExperimental(rInfo.Command, m_sModuleLongName);
+
+ // Hide experimental commands when not in experimental mode
+ bool bHideExperimental = bIsExperimental && !bInExperimentalMode;
+
+ // Apply the search filter
+ if (bHideExperimental
+ || (!filterTerm.isEmpty() && !textSearch.searchForward(sUIName)
+ && !textSearch.searchForward(sLabel) && !textSearch.searchForward(sTooltipLabel)
+ && !textSearch.searchForward(sPopupLabel)))
+ {
+ continue;
+ }
+
+ css::uno::Reference<css::graphic::XGraphic> xImage;
+ if (pCurrentSaveInData)
+ xImage = pCurrentSaveInData->GetImage(rInfo.Command);
+
+ m_aGroupInfo.push_back(std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::FUNCTION_SLOT, 0));
+ SfxGroupInfo_Impl* pGrpInfo = m_aGroupInfo.back().get();
+ pGrpInfo->sCommand = rInfo.Command;
+ pGrpInfo->sLabel = sUIName;
+ pGrpInfo->sTooltip = sTooltipLabel;
+ pFunctionListBox->append(weld::toId(m_aGroupInfo.back().get()), sUIName, xImage);
+ }
+}
+
+OUString CommandCategoryListBox::getCommandName(const OUString& sCommand)
+{
+ OUString sUIName;
+ try
+ {
+ css::uno::Reference<css::container::XNameAccess> xModuleConf;
+ m_xUICmdDescription->getByName(m_sModuleLongName) >>= xModuleConf;
+ if (xModuleConf.is())
+ {
+ ::comphelper::SequenceAsHashMap lProps(xModuleConf->getByName(sCommand));
+ sUIName = lProps.getUnpackedValueOrDefault("Name", OUString());
+ }
+ }
+ catch (const css::uno::RuntimeException&)
+ {
+ throw;
+ }
+ catch (css::uno::Exception&)
+ {
+ sUIName.clear();
+ }
+
+ // fallback for missing UINames !?
+ if (sUIName.isEmpty())
+ {
+ sUIName = sCommand;
+ }
+
+ return sUIName;
+}
+
+void CommandCategoryListBox::categorySelected(CuiConfigFunctionListBox* pFunctionListBox,
+ const OUString& filterTerm,
+ SaveInData* pCurrentSaveInData)
+{
+ SfxGroupInfo_Impl* pInfo = weld::fromId<SfxGroupInfo_Impl*>(m_xControl->get_active_id());
+ std::vector<std::unique_ptr<weld::TreeIter>> aNodesToExpand;
+ pFunctionListBox->freeze();
+ pFunctionListBox->ClearAll();
+
+ switch (pInfo->nKind)
+ {
+ case SfxCfgKind::GROUP_ALLFUNCTIONS:
+ {
+ css::uno::Reference<css::frame::XDispatchInformationProvider> xProvider(
+ m_xFrame, css::uno::UNO_QUERY);
+ sal_Int32 nEntryCount = m_xControl->get_count();
+
+ for (sal_Int32 nCurPos = 0; nCurPos < nEntryCount; ++nCurPos)
+ {
+ SfxGroupInfo_Impl* pCurrentInfo
+ = weld::fromId<SfxGroupInfo_Impl*>(m_xControl->get_id(nCurPos));
+
+ if (!pCurrentInfo) //separator
+ continue;
+
+ if (pCurrentInfo->nKind == SfxCfgKind::GROUP_FUNCTION)
+ {
+ css::uno::Sequence<css::frame::DispatchInformation> lCommands;
+ try
+ {
+ lCommands = xProvider->getConfigurableDispatchInformation(
+ pCurrentInfo->nUniqueID);
+ FillFunctionsList(lCommands, pFunctionListBox, filterTerm,
+ pCurrentSaveInData);
+ }
+ catch (css::container::NoSuchElementException&)
+ {
+ }
+ }
+ }
+
+ break;
+ }
+ case SfxCfgKind::GROUP_FUNCTION:
+ {
+ sal_uInt16 nGroup = pInfo->nUniqueID;
+ css::uno::Reference<css::frame::XDispatchInformationProvider> xProvider(
+ m_xFrame, css::uno::UNO_QUERY_THROW);
+ css::uno::Sequence<css::frame::DispatchInformation> lCommands
+ = xProvider->getConfigurableDispatchInformation(nGroup);
+ FillFunctionsList(lCommands, pFunctionListBox, filterTerm, pCurrentSaveInData);
+ break;
+ }
+ case SfxCfgKind::GROUP_SCRIPTCONTAINER: //Macros
+ {
+ SAL_INFO("cui.customize", "** ** About to initialise SF Scripts");
+ // Add Scripting Framework entries
+ css::uno::Reference<css::script::browse::XBrowseNode> rootNode;
+ try
+ {
+ css::uno::Reference<css::script::browse::XBrowseNodeFactory> xFac
+ = css::script::browse::theBrowseNodeFactory::get(m_xContext);
+ rootNode.set(xFac->createView(
+ css::script::browse::BrowseNodeFactoryViewTypes::MACROSELECTOR));
+ }
+ catch (css::uno::Exception const&)
+ {
+ TOOLS_WARN_EXCEPTION(
+ "cui.customize",
+ "Caught some exception whilst retrieving browse nodes from factory");
+ // TODO exception handling
+ }
+
+ if (rootNode.is() && rootNode->hasChildNodes())
+ {
+ //We call acquire on the XBrowseNode so that it does not
+ //get autodestructed and become invalid when accessed later.
+ rootNode->acquire();
+
+ m_aGroupInfo.push_back(std::make_unique<SfxGroupInfo_Impl>(
+ SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, static_cast<void*>(rootNode.get())));
+
+ // Add main macro groups
+ const css::uno::Sequence<css::uno::Reference<css::script::browse::XBrowseNode>>
+ aChildNodes = rootNode->getChildNodes();
+ for (auto const& childGroup : aChildNodes)
+ {
+ childGroup->acquire();
+
+ if (childGroup->hasChildNodes())
+ {
+ OUString sUIName;
+ if (childGroup->getName() == "user")
+ {
+ sUIName = CuiResId(RID_CUISTR_MYMACROS);
+ }
+ else if (childGroup->getName() == "share")
+ {
+ sUIName = CuiResId(RID_CUISTR_PRODMACROS);
+ }
+ else
+ {
+ sUIName = childGroup->getName();
+ }
+
+ if (sUIName.isEmpty())
+ {
+ continue;
+ }
+
+ m_aGroupInfo.push_back(std::make_unique<SfxGroupInfo_Impl>(
+ SfxCfgKind::GROUP_SCRIPTCONTAINER, 0));
+ std::unique_ptr<weld::TreeIter> xMacroGroup(pFunctionListBox->tree_append(
+ weld::toId(m_aGroupInfo.back().get()), sUIName));
+
+ {
+ // tdf#128010: Do not nag user asking to enable JRE: if it's disabled,
+ // simply don't show relevant entries (user chose to not use JRE)
+ css::uno::ContextLayer layer(
+ comphelper::NoEnableJavaInteractionContext());
+ //Add the children and the grand children
+ addChildren(xMacroGroup.get(), childGroup, pFunctionListBox, filterTerm,
+ pCurrentSaveInData, aNodesToExpand);
+ }
+
+ // Remove the main group if empty
+ if (!pFunctionListBox->iter_has_child(*xMacroGroup))
+ {
+ pFunctionListBox->remove(*xMacroGroup);
+ }
+ else if (!filterTerm.isEmpty())
+ {
+ aNodesToExpand.emplace_back(std::move(xMacroGroup));
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case SfxCfgKind::GROUP_STYLES:
+ {
+ const std::vector<SfxStyleInfo_Impl> lStyleFamilies = pStylesInfo->getStyleFamilies();
+
+ for (const auto& pIt : lStyleFamilies)
+ {
+ if (pIt.sLabel.isEmpty())
+ {
+ continue;
+ }
+
+ m_aGroupInfo.push_back(
+ std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_STYLES, 0));
+ // pIt.sLabel is Name of the style family
+ std::unique_ptr<weld::TreeIter> xFuncEntry(pFunctionListBox->tree_append(
+ weld::toId(m_aGroupInfo.back().get()), pIt.sLabel));
+
+ const std::vector<SfxStyleInfo_Impl> lStyles = pStylesInfo->getStyles(pIt.sFamily);
+
+ // Setup search filter parameters
+ m_searchOptions.searchString = filterTerm;
+ utl::TextSearch textSearch(m_searchOptions);
+
+ // Insert children (styles)
+ for (const auto& pStyleIt : lStyles)
+ {
+ OUString sUIName = pStyleIt.sLabel;
+ sal_Int32 aStartPos = 0;
+ sal_Int32 aEndPos = sUIName.getLength();
+
+ // Apply the search filter
+ if (!filterTerm.isEmpty()
+ && !textSearch.SearchForward(sUIName, &aStartPos, &aEndPos))
+ {
+ continue;
+ }
+
+ SfxStyleInfo_Impl* pStyle = new SfxStyleInfo_Impl(pStyleIt);
+
+ m_aGroupInfo.push_back(
+ std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_STYLES, 0, pStyle));
+
+ m_aGroupInfo.back()->sCommand = pStyle->sCommand;
+ m_aGroupInfo.back()->sLabel = pStyle->sLabel;
+
+ pFunctionListBox->append(weld::toId(m_aGroupInfo.back().get()), sUIName,
+ xFuncEntry.get());
+ }
+
+ // Remove the style group from the list if no children
+ if (!pFunctionListBox->iter_has_child(*xFuncEntry))
+ {
+ pFunctionListBox->remove(*xFuncEntry);
+ }
+ else if (!filterTerm.isEmpty())
+ {
+ aNodesToExpand.emplace_back(std::move(xFuncEntry));
+ }
+ }
+
+ break;
+ }
+ default:
+ // Do nothing, the list box will stay empty
+ SAL_INFO("cui.customize",
+ "Ignoring unexpected SfxCfgKind: " << static_cast<int>(pInfo->nKind));
+ break;
+ }
+
+ pFunctionListBox->thaw();
+
+ if (pFunctionListBox->n_children())
+ pFunctionListBox->select(0);
+
+ //post freeze
+ for (const auto& it : aNodesToExpand)
+ pFunctionListBox->expand_row(*it);
+}
+
+void CommandCategoryListBox::SetStylesInfo(SfxStylesInfo_Impl* pStyles) { pStylesInfo = pStyles; }
+
+void CommandCategoryListBox::addChildren(
+ const weld::TreeIter* parentEntry,
+ const css::uno::Reference<css::script::browse::XBrowseNode>& parentNode,
+ CuiConfigFunctionListBox* pFunctionListBox, const OUString& filterTerm,
+ SaveInData* pCurrentSaveInData, std::vector<std::unique_ptr<weld::TreeIter>>& rNodesToExpand)
+{
+ // Setup search filter parameters
+ m_searchOptions.searchString = filterTerm;
+ utl::TextSearch textSearch(m_searchOptions);
+
+ const css::uno::Sequence<css::uno::Reference<css::script::browse::XBrowseNode>> aChildNodes
+ = parentNode->getChildNodes();
+ for (auto const& child : aChildNodes)
+ {
+ // Acquire to prevent auto-destruction
+ child->acquire();
+
+ if (child->hasChildNodes())
+ {
+ OUString sUIName = child->getName();
+
+ m_aGroupInfo.push_back(std::make_unique<SfxGroupInfo_Impl>(
+ SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, static_cast<void*>(child.get())));
+ std::unique_ptr<weld::TreeIter> xNewEntry(pFunctionListBox->tree_append(
+ weld::toId(m_aGroupInfo.back().get()), sUIName, parentEntry));
+
+ addChildren(xNewEntry.get(), child, pFunctionListBox, filterTerm, pCurrentSaveInData,
+ rNodesToExpand);
+
+ // Remove the group if empty
+ if (!pFunctionListBox->iter_has_child(*xNewEntry))
+ pFunctionListBox->remove(*xNewEntry);
+ else
+ rNodesToExpand.emplace_back(std::move(xNewEntry));
+ }
+ else if (child->getType() == css::script::browse::BrowseNodeTypes::SCRIPT)
+ {
+ // Prepare for filtering
+ OUString sUIName = child->getName();
+ sal_Int32 aStartPos = 0;
+ sal_Int32 aEndPos = sUIName.getLength();
+
+ // Apply the search filter
+ if (!filterTerm.isEmpty() && !textSearch.SearchForward(sUIName, &aStartPos, &aEndPos))
+ {
+ continue;
+ }
+
+ OUString uri, description;
+
+ css::uno::Reference<css::beans::XPropertySet> xPropSet(child, css::uno::UNO_QUERY);
+
+ if (!xPropSet.is())
+ {
+ continue;
+ }
+
+ css::uno::Any value = xPropSet->getPropertyValue("URI");
+ value >>= uri;
+
+ try
+ {
+ value = xPropSet->getPropertyValue("Description");
+ value >>= description;
+ }
+ catch (css::uno::Exception&)
+ {
+ // do nothing, the description will be empty
+ }
+
+ if (description.isEmpty())
+ {
+ description = CuiResId(RID_CUISTR_NOMACRODESC);
+ }
+
+ OUString* pScriptURI = new OUString(uri);
+
+ css::uno::Reference<css::graphic::XGraphic> xImage;
+ if (pCurrentSaveInData)
+ xImage = pCurrentSaveInData->GetImage(uri);
+
+ m_aGroupInfo.push_back(
+ std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI));
+ m_aGroupInfo.back()->sCommand = uri;
+ m_aGroupInfo.back()->sLabel = sUIName;
+ m_aGroupInfo.back()->sHelpText = description;
+ pFunctionListBox->append(weld::toId(m_aGroupInfo.back().get()), sUIName, xImage,
+ parentEntry);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */