The browse node factory had a wrapper using XAggregation that wraps every XBrowseNode. As far as I can tell this was used to replace the implementation of getChildNodes with one that checks for exceptions from the underlying provider and then sorts all of the resulting nodes by name. The trouble with this is that it prevents the script providers from detecting when a node is one from the same script provider and thus makes it difficult to implement the XCopyableBrowseNode interface. The documentation for XAggregation mentions this problem and also states that the interface is deprecated. To avoid this overhead, this patch replaces the aggregation with a helper function in comphelper that should be used to retrieve children from a browse node. That takes care of catching exceptions and sorting the results. Change-Id: I319888fee1b84ddcef397317d2cf7e72bd2867cd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208160 Tested-by: Jenkins Reviewed-by: Neil Roberts <nroberts@libreoffice.org>
580 lines
22 KiB
C++
580 lines
22 KiB
C++
/* -*- 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 <comphelper/diagnose_ex.hxx>
|
|
#include <unotools/textsearch.hxx>
|
|
|
|
#include <dialmgr.hxx>
|
|
#include <strings.hrc>
|
|
#include <comphelper/processfactory.hxx>
|
|
#include <comphelper/sequenceashashmap.hxx>
|
|
#include <comphelper/SetFlagContextHelper.hxx>
|
|
#include <comphelper/scriptbrowse.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()
|
|
{
|
|
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>(
|
|
SfxGroupInfo_Data(SfxCfgKindAsIndex<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(u""_ustr);
|
|
|
|
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>(
|
|
SfxGroupInfo_Data(SfxCfgKindAsIndex<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(u""_ustr);
|
|
|
|
// Add macros category
|
|
m_aGroupInfo.push_back(std::make_unique<SfxGroupInfo_Impl>(
|
|
SfxGroupInfo_Data(SfxCfgKindAsIndex<SfxCfgKind::GROUP_SCRIPTCONTAINER>), 0));
|
|
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>(
|
|
SfxGroupInfo_Data(SfxCfgKindAsIndex<SfxCfgKind::GROUP_STYLES>), 0));
|
|
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>(
|
|
SfxGroupInfo_Data(SfxCfgKindAsIndex<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(u"Name"_ustr, 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->getKind())
|
|
{
|
|
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->getKind() == 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())
|
|
{
|
|
m_aGroupInfo.push_back(std::make_unique<SfxGroupInfo_Impl>(
|
|
SfxGroupInfo_Data(SfxCfgKindAsIndex<SfxCfgKind::GROUP_SCRIPTCONTAINER>,
|
|
rootNode),
|
|
0));
|
|
|
|
// Add main macro groups
|
|
const std::vector<css::uno::Reference<css::script::browse::XBrowseNode>> aChildNodes
|
|
= comphelper::scriptbrowse::getChildNodes(rootNode);
|
|
for (auto const& childGroup : aChildNodes)
|
|
{
|
|
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>(
|
|
SfxGroupInfo_Data(SfxCfgKindAsIndex<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>(
|
|
SfxGroupInfo_Data(SfxCfgKindAsIndex<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;
|
|
}
|
|
|
|
auto pStyle = std::make_unique<SfxStyleInfo_Impl>(pStyleIt);
|
|
|
|
m_aGroupInfo.push_back(std::make_unique<SfxGroupInfo_Impl>(
|
|
SfxGroupInfo_Data(SfxCfgKindAsIndex<SfxCfgKind::GROUP_STYLES>,
|
|
std::move(pStyle)),
|
|
0));
|
|
|
|
m_aGroupInfo.back()->sCommand = pStyleIt.sCommand;
|
|
m_aGroupInfo.back()->sLabel = pStyleIt.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: " << pInfo->aData.index());
|
|
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 std::vector<css::uno::Reference<css::script::browse::XBrowseNode>> aChildNodes
|
|
= comphelper::scriptbrowse::getSortedChildNodes(parentNode);
|
|
for (auto const& child : aChildNodes)
|
|
{
|
|
if (child->hasChildNodes())
|
|
{
|
|
OUString sUIName = child->getName();
|
|
|
|
m_aGroupInfo.push_back(std::make_unique<SfxGroupInfo_Impl>(
|
|
SfxGroupInfo_Data(SfxCfgKindAsIndex<SfxCfgKind::GROUP_SCRIPTCONTAINER>, child), 0));
|
|
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(u"URI"_ustr);
|
|
value >>= uri;
|
|
|
|
try
|
|
{
|
|
value = xPropSet->getPropertyValue(u"Description"_ustr);
|
|
value >>= description;
|
|
}
|
|
catch (css::uno::Exception&)
|
|
{
|
|
// do nothing, the description will be empty
|
|
}
|
|
|
|
if (description.isEmpty())
|
|
{
|
|
description = CuiResId(RID_CUISTR_NOMACRODESC);
|
|
}
|
|
|
|
css::uno::Reference<css::graphic::XGraphic> xImage;
|
|
if (pCurrentSaveInData)
|
|
xImage = pCurrentSaveInData->GetImage(uri);
|
|
|
|
m_aGroupInfo.push_back(std::make_unique<SfxGroupInfo_Impl>(
|
|
SfxGroupInfo_Data(SfxCfgKindAsIndex<SfxCfgKind::FUNCTION_SCRIPT>, uri), 0));
|
|
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: */
|