1411 lines
52 KiB
C++
1411 lines
52 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* 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 <cfgutil.hxx>
|
|
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
#include <com/sun/star/container/XEnumerationAccess.hpp>
|
|
#include <com/sun/star/container/XEnumeration.hpp>
|
|
#include <com/sun/star/document/XScriptInvocationContext.hpp>
|
|
#include <com/sun/star/frame/ModuleManager.hpp>
|
|
#include <com/sun/star/frame/Desktop.hpp>
|
|
#include <com/sun/star/frame/theUICommandDescription.hpp>
|
|
#include <com/sun/star/frame/XDispatchInformationProvider.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 <com/sun/star/style/XStyleFamiliesSupplier.hpp>
|
|
#include <com/sun/star/uno/RuntimeException.hpp>
|
|
#include <com/sun/star/ui/theUICategoryDescription.hpp>
|
|
|
|
#include <basic/basmgr.hxx>
|
|
#include <tools/urlobj.hxx>
|
|
#include <strings.hrc>
|
|
#include <bitmaps.hlst>
|
|
#include <sfx2/minfitem.hxx>
|
|
#include <comphelper/SetFlagContextHelper.hxx>
|
|
#include <comphelper/documentinfo.hxx>
|
|
#include <comphelper/lok.hxx>
|
|
#include <comphelper/processfactory.hxx>
|
|
#include <comphelper/sequenceashashmap.hxx>
|
|
#include <svtools/imagemgr.hxx>
|
|
#include <sal/log.hxx>
|
|
#include <osl/diagnose.h>
|
|
#include <dialmgr.hxx>
|
|
#include <comphelper/diagnose_ex.hxx>
|
|
#include <vcl/commandevent.hxx>
|
|
#include <vcl/commandinfoprovider.hxx>
|
|
#include <vcl/help.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <o3tl/string_view.hxx>
|
|
|
|
#include <sfx2/sidebar/ResourceManager.hxx>
|
|
#include <sfx2/sidebar/Context.hxx>
|
|
#include <unotools/viewoptions.hxx>
|
|
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::script;
|
|
using namespace ::com::sun::star::frame;
|
|
using namespace ::com::sun::star::document;
|
|
|
|
SfxStylesInfo_Impl::SfxStylesInfo_Impl()
|
|
{}
|
|
|
|
void SfxStylesInfo_Impl::init(const OUString& rModuleName, const css::uno::Reference< css::frame::XModel >& xModel)
|
|
{
|
|
m_aModuleName = rModuleName;
|
|
m_xDoc = xModel;
|
|
}
|
|
|
|
const char CMDURL_STYLEPROT_ONLY[] = ".uno:StyleApply?";
|
|
const char CMDURL_SPART_ONLY [] = "Style:string=";
|
|
const char CMDURL_FPART_ONLY [] = "FamilyName:string=";
|
|
|
|
constexpr OUString STYLEPROP_UINAME = u"DisplayName"_ustr;
|
|
constexpr OUString MACRO_SELECTOR_CONFIGNAME = u"MacroSelectorDialog"_ustr;
|
|
constexpr OUString LAST_RUN_MACRO_INFO = u"LastRunMacro"_ustr;
|
|
|
|
OUString SfxStylesInfo_Impl::generateCommand(
|
|
std::u16string_view sFamily, std::u16string_view sStyle)
|
|
{
|
|
return OUString::Concat(".uno:StyleApply?Style:string=")
|
|
+ sStyle
|
|
+ "&FamilyName:string="
|
|
+ sFamily;
|
|
}
|
|
|
|
bool SfxStylesInfo_Impl::parseStyleCommand(SfxStyleInfo_Impl& aStyle)
|
|
{
|
|
static const sal_Int32 LEN_STYLEPROT = strlen(CMDURL_STYLEPROT_ONLY);
|
|
static const sal_Int32 LEN_SPART = strlen(CMDURL_SPART_ONLY);
|
|
static const sal_Int32 LEN_FPART = strlen(CMDURL_FPART_ONLY);
|
|
|
|
if (!aStyle.sCommand.startsWith(CMDURL_STYLEPROT_ONLY))
|
|
return false;
|
|
|
|
aStyle.sFamily.clear();
|
|
aStyle.sStyle.clear();
|
|
|
|
sal_Int32 nCmdLen = aStyle.sCommand.getLength();
|
|
OUString sCmdArgs = aStyle.sCommand.copy(LEN_STYLEPROT, nCmdLen-LEN_STYLEPROT);
|
|
sal_Int32 i = sCmdArgs.indexOf('&');
|
|
if (i<0)
|
|
return false;
|
|
|
|
OUString sArg = sCmdArgs.copy(0, i);
|
|
if (sArg.startsWith(CMDURL_SPART_ONLY))
|
|
aStyle.sStyle = sArg.copy(LEN_SPART);
|
|
else if (sArg.startsWith(CMDURL_FPART_ONLY))
|
|
aStyle.sFamily = sArg.copy(LEN_FPART);
|
|
|
|
sArg = sCmdArgs.copy(i+1, sCmdArgs.getLength()-i-1);
|
|
if (sArg.startsWith(CMDURL_SPART_ONLY))
|
|
aStyle.sStyle = sArg.copy(LEN_SPART);
|
|
else if (sArg.startsWith(CMDURL_FPART_ONLY))
|
|
aStyle.sFamily = sArg.copy(LEN_FPART);
|
|
|
|
return !(aStyle.sFamily.isEmpty() || aStyle.sStyle.isEmpty());
|
|
}
|
|
|
|
void SfxStylesInfo_Impl::getLabel4Style(SfxStyleInfo_Impl& aStyle)
|
|
{
|
|
try
|
|
{
|
|
css::uno::Reference< css::style::XStyleFamiliesSupplier > xModel(m_xDoc, css::uno::UNO_QUERY);
|
|
|
|
css::uno::Reference< css::container::XNameAccess > xFamilies;
|
|
if (xModel.is())
|
|
xFamilies = xModel->getStyleFamilies();
|
|
|
|
css::uno::Reference< css::container::XNameAccess > xStyleSet;
|
|
if (xFamilies.is())
|
|
xFamilies->getByName(aStyle.sFamily) >>= xStyleSet;
|
|
|
|
css::uno::Reference< css::beans::XPropertySet > xStyle;
|
|
if (xStyleSet.is())
|
|
xStyleSet->getByName(aStyle.sStyle) >>= xStyle;
|
|
|
|
aStyle.sLabel.clear();
|
|
if (xStyle.is())
|
|
xStyle->getPropertyValue(STYLEPROP_UINAME) >>= aStyle.sLabel;
|
|
}
|
|
catch(const css::uno::RuntimeException&)
|
|
{ throw; }
|
|
catch(const css::uno::Exception&)
|
|
{ aStyle.sLabel.clear(); }
|
|
|
|
if (aStyle.sLabel.isEmpty())
|
|
{
|
|
aStyle.sLabel = aStyle.sCommand;
|
|
}
|
|
}
|
|
|
|
std::vector< SfxStyleInfo_Impl > SfxStylesInfo_Impl::getStyleFamilies() const
|
|
{
|
|
// It's an optional interface!
|
|
css::uno::Reference< css::style::XStyleFamiliesSupplier > xModel(m_xDoc, css::uno::UNO_QUERY);
|
|
if (!xModel.is())
|
|
return std::vector< SfxStyleInfo_Impl >();
|
|
|
|
css::uno::Reference< css::container::XNameAccess > xCont = xModel->getStyleFamilies();
|
|
const css::uno::Sequence< OUString > lFamilyNames = xCont->getElementNames();
|
|
std::vector< SfxStyleInfo_Impl > lFamilies;
|
|
for (const auto& aFamily : lFamilyNames)
|
|
{
|
|
if ((aFamily == "CellStyles" && m_aModuleName != "com.sun.star.sheet.SpreadsheetDocument") ||
|
|
aFamily == "cell" || aFamily == "table" || aFamily == "Default")
|
|
continue;
|
|
|
|
SfxStyleInfo_Impl aFamilyInfo;
|
|
aFamilyInfo.sFamily = aFamily;
|
|
|
|
try
|
|
{
|
|
css::uno::Reference< css::beans::XPropertySet > xFamilyInfo;
|
|
xCont->getByName(aFamilyInfo.sFamily) >>= xFamilyInfo;
|
|
if (!xFamilyInfo.is())
|
|
{
|
|
// TODO_AS currently there is no support for an UIName property .. use internal family name instead
|
|
aFamilyInfo.sLabel = aFamilyInfo.sFamily;
|
|
}
|
|
else
|
|
xFamilyInfo->getPropertyValue(STYLEPROP_UINAME) >>= aFamilyInfo.sLabel;
|
|
}
|
|
catch(const css::uno::RuntimeException&)
|
|
{ throw; }
|
|
catch(const css::uno::Exception&)
|
|
{ return std::vector< SfxStyleInfo_Impl >(); }
|
|
|
|
lFamilies.push_back(aFamilyInfo);
|
|
}
|
|
|
|
return lFamilies;
|
|
}
|
|
|
|
std::vector< SfxStyleInfo_Impl > SfxStylesInfo_Impl::getStyles(const OUString& sFamily)
|
|
{
|
|
css::uno::Sequence< OUString > lStyleNames;
|
|
css::uno::Reference< css::style::XStyleFamiliesSupplier > xModel(m_xDoc, css::uno::UNO_QUERY_THROW);
|
|
css::uno::Reference< css::container::XNameAccess > xFamilies = xModel->getStyleFamilies();
|
|
css::uno::Reference< css::container::XNameAccess > xStyleSet;
|
|
try
|
|
{
|
|
xFamilies->getByName(sFamily) >>= xStyleSet;
|
|
lStyleNames = xStyleSet->getElementNames();
|
|
}
|
|
catch(const css::uno::RuntimeException&)
|
|
{ throw; }
|
|
catch(const css::uno::Exception&)
|
|
{ return std::vector< SfxStyleInfo_Impl >(); }
|
|
|
|
std::vector< SfxStyleInfo_Impl > lStyles;
|
|
sal_Int32 c = lStyleNames.getLength();
|
|
sal_Int32 i = 0;
|
|
for (i=0; i<c; ++i)
|
|
{
|
|
SfxStyleInfo_Impl aStyleInfo;
|
|
aStyleInfo.sFamily = sFamily;
|
|
aStyleInfo.sStyle = lStyleNames[i];
|
|
aStyleInfo.sCommand = SfxStylesInfo_Impl::generateCommand(aStyleInfo.sFamily, aStyleInfo.sStyle);
|
|
|
|
try
|
|
{
|
|
css::uno::Reference< css::beans::XPropertySet > xStyle;
|
|
xStyleSet->getByName(aStyleInfo.sStyle) >>= xStyle;
|
|
if (!xStyle.is())
|
|
continue;
|
|
xStyle->getPropertyValue(u"DisplayName"_ustr) >>= aStyleInfo.sLabel;
|
|
}
|
|
catch(const css::uno::RuntimeException&)
|
|
{ throw; }
|
|
catch(const css::uno::Exception&)
|
|
{ continue; }
|
|
|
|
lStyles.push_back(aStyleInfo);
|
|
}
|
|
return lStyles;
|
|
}
|
|
|
|
OUString CuiConfigFunctionListBox::GetCommandHelpText()
|
|
{
|
|
SfxGroupInfo_Impl *pData = weld::fromId<SfxGroupInfo_Impl*>(get_selected_id());
|
|
if (pData)
|
|
{
|
|
if ( pData->nKind == SfxCfgKind::FUNCTION_SLOT )
|
|
{
|
|
return Application::GetHelp()->GetHelpText(pData->sCommand);
|
|
}
|
|
else if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT )
|
|
{
|
|
return pData->sHelpText;
|
|
}
|
|
}
|
|
return OUString();
|
|
}
|
|
|
|
OUString CuiConfigFunctionListBox::GetCurCommand() const
|
|
{
|
|
SfxGroupInfo_Impl *pData = weld::fromId<SfxGroupInfo_Impl*>(get_selected_id());
|
|
if (!pData)
|
|
return OUString();
|
|
return pData->sCommand;
|
|
}
|
|
|
|
OUString CuiConfigFunctionListBox::GetCurLabel() const
|
|
{
|
|
SfxGroupInfo_Impl *pData = weld::fromId<SfxGroupInfo_Impl*>(get_selected_id());
|
|
if (!pData)
|
|
return OUString();
|
|
if (!pData->sLabel.isEmpty())
|
|
return pData->sLabel;
|
|
return pData->sCommand;
|
|
}
|
|
|
|
CuiConfigFunctionListBox::CuiConfigFunctionListBox(std::unique_ptr<weld::TreeView> xTreeView)
|
|
: m_xTreeView(std::move(xTreeView))
|
|
, m_xScratchIter(m_xTreeView->make_iterator())
|
|
{
|
|
m_xTreeView->make_sorted();
|
|
m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 35, m_xTreeView->get_height_rows(9));
|
|
m_xTreeView->connect_query_tooltip(LINK(this, CuiConfigFunctionListBox, QueryTooltip));
|
|
}
|
|
|
|
CuiConfigFunctionListBox::~CuiConfigFunctionListBox()
|
|
{
|
|
ClearAll();
|
|
}
|
|
|
|
IMPL_LINK(CuiConfigFunctionListBox, QueryTooltip, const weld::TreeIter&, rIter, OUString)
|
|
{
|
|
SfxGroupInfo_Impl *pData = weld::fromId<SfxGroupInfo_Impl*>(m_xTreeView->get_id(rIter));
|
|
if (!pData)
|
|
return OUString();
|
|
OUString aLabel = CuiResId(RID_CUISTR_COMMANDLABEL) + ": ";
|
|
OUString aName = CuiResId(RID_CUISTR_COMMANDNAME) + ": ";
|
|
OUString aTip = CuiResId(RID_CUISTR_COMMANDTIP) + ": ";
|
|
return aLabel + pData->sLabel + "\n" + aName + pData->sCommand+ "\n" + aTip + pData->sTooltip;
|
|
}
|
|
|
|
void CuiConfigFunctionListBox::ClearAll()
|
|
/* Description
|
|
Deletes all entries in the FunctionListBox, all UserData and all
|
|
possibly existing MacroInfo.
|
|
*/
|
|
{
|
|
sal_uInt16 nCount = aArr.size();
|
|
for ( sal_uInt16 i=0; i<nCount; ++i )
|
|
{
|
|
SfxGroupInfo_Impl *pData = aArr[i].get();
|
|
|
|
if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT )
|
|
{
|
|
OUString* pScriptURI = static_cast<OUString*>(pData->pObject);
|
|
delete pScriptURI;
|
|
}
|
|
|
|
if ( pData->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER )
|
|
{
|
|
XInterface* xi = static_cast<XInterface *>(pData->pObject);
|
|
if (xi != nullptr)
|
|
{
|
|
xi->release();
|
|
}
|
|
}
|
|
}
|
|
|
|
aArr.clear();
|
|
m_xTreeView->clear();
|
|
}
|
|
|
|
OUString CuiConfigFunctionListBox::GetSelectedScriptURI() const
|
|
{
|
|
SfxGroupInfo_Impl *pData = weld::fromId<SfxGroupInfo_Impl*>(get_selected_id());
|
|
if (pData && pData->nKind == SfxCfgKind::FUNCTION_SCRIPT)
|
|
return *static_cast<OUString*>(pData->pObject);
|
|
return OUString();
|
|
}
|
|
|
|
struct SvxConfigGroupBoxResource_Impl
|
|
{
|
|
OUString m_sMyMacros;
|
|
OUString m_sProdMacros;
|
|
OUString m_sDlgMacros;
|
|
OUString m_aStrGroupStyles;
|
|
OUString m_aStrGroupSidebarDecks;
|
|
|
|
SvxConfigGroupBoxResource_Impl();
|
|
};
|
|
|
|
SvxConfigGroupBoxResource_Impl::SvxConfigGroupBoxResource_Impl() :
|
|
m_sMyMacros(CuiResId(RID_CUISTR_MYMACROS)),
|
|
m_sProdMacros(CuiResId(RID_CUISTR_PRODMACROS)),
|
|
m_sDlgMacros(CuiResId(RID_CUISTR_PRODMACROS)),
|
|
m_aStrGroupStyles(CuiResId(RID_CUISTR_GROUP_STYLES)),
|
|
m_aStrGroupSidebarDecks(CuiResId(RID_CUISTR_GROUP_SIDEBARDECKS))
|
|
{
|
|
}
|
|
|
|
void CuiConfigGroupListBox::SetStylesInfo(SfxStylesInfo_Impl* pStyles)
|
|
{
|
|
m_pStylesInfo = pStyles;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
|
|
/** examines a component whether it supports XEmbeddedScripts, or provides access to such a
|
|
component by implementing XScriptInvocationContext.
|
|
@return
|
|
the model which supports the embedded scripts, or <NULL/> if it cannot find such a
|
|
model
|
|
*/
|
|
Reference< XModel > lcl_getDocumentWithScripts_throw( const Reference< XInterface >& _rxComponent )
|
|
{
|
|
Reference< XEmbeddedScripts > xScripts( _rxComponent, UNO_QUERY );
|
|
if ( !xScripts.is() )
|
|
{
|
|
Reference< XScriptInvocationContext > xContext( _rxComponent, UNO_QUERY );
|
|
if ( xContext.is() )
|
|
xScripts = xContext->getScriptContainer();
|
|
}
|
|
|
|
return Reference< XModel >( xScripts, UNO_QUERY );
|
|
}
|
|
|
|
|
|
Reference< XModel > lcl_getScriptableDocument_nothrow( const Reference< XFrame >& _rxFrame )
|
|
{
|
|
Reference< XModel > xDocument;
|
|
|
|
// examine our associated frame
|
|
try
|
|
{
|
|
OSL_ENSURE( _rxFrame.is(), "lcl_getScriptableDocument_nothrow: you need to pass a frame to this dialog/tab page!" );
|
|
if ( _rxFrame.is() )
|
|
{
|
|
// first try the model in the frame
|
|
Reference< XController > xController( _rxFrame->getController(), UNO_SET_THROW );
|
|
xDocument = lcl_getDocumentWithScripts_throw( xController->getModel() );
|
|
|
|
if ( !xDocument.is() )
|
|
{
|
|
// if there is no suitable document in the frame, try the controller
|
|
xDocument = lcl_getDocumentWithScripts_throw( _rxFrame->getController() );
|
|
}
|
|
}
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
}
|
|
|
|
return xDocument;
|
|
}
|
|
}
|
|
|
|
CuiConfigGroupListBox::CuiConfigGroupListBox(std::unique_ptr<weld::TreeView> xTreeView)
|
|
: xImp(new SvxConfigGroupBoxResource_Impl())
|
|
, m_pFunctionListBox(nullptr)
|
|
, m_pStylesInfo(nullptr)
|
|
, m_xTreeView(std::move(xTreeView))
|
|
, m_xScratchIter(m_xTreeView->make_iterator())
|
|
{
|
|
m_xTreeView->connect_expanding(LINK(this, CuiConfigGroupListBox, ExpandingHdl));
|
|
m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 35, m_xTreeView->get_height_rows(9));
|
|
}
|
|
|
|
CuiConfigGroupListBox::~CuiConfigGroupListBox()
|
|
{
|
|
ClearAll();
|
|
}
|
|
|
|
void CuiConfigGroupListBox::ClearAll()
|
|
{
|
|
sal_uInt16 nCount = aArr.size();
|
|
for ( sal_uInt16 i=0; i<nCount; ++i )
|
|
{
|
|
SfxGroupInfo_Impl *pData = aArr[i].get();
|
|
if (pData->nKind == SfxCfgKind::GROUP_STYLES && pData->pObject)
|
|
{
|
|
SfxStyleInfo_Impl* pStyle = static_cast<SfxStyleInfo_Impl*>(pData->pObject);
|
|
delete pStyle;
|
|
}
|
|
else if (pData->nKind == SfxCfgKind::FUNCTION_SCRIPT && pData->pObject )
|
|
{
|
|
OUString* pScriptURI = static_cast<OUString*>(pData->pObject);
|
|
delete pScriptURI;
|
|
}
|
|
else if (pData->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER)
|
|
{
|
|
XInterface* xi = static_cast<XInterface *>(pData->pObject);
|
|
if (xi != nullptr)
|
|
{
|
|
xi->release();
|
|
}
|
|
}
|
|
}
|
|
|
|
aArr.clear();
|
|
m_xTreeView->clear();
|
|
}
|
|
|
|
sal_Int32 CuiConfigGroupListBox::InitModule()
|
|
{
|
|
try
|
|
{
|
|
// return the number of added groups
|
|
css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider(m_xFrame, css::uno::UNO_QUERY_THROW);
|
|
css::uno::Sequence< sal_Int16 > lGroups = xProvider->getSupportedCommandGroups();
|
|
sal_Int32 c1 = lGroups.getLength();
|
|
sal_Int32 i1 = 0;
|
|
sal_Int32 nAddedGroups = 0;
|
|
|
|
for (i1=0; i1<c1; ++i1)
|
|
{
|
|
sal_Int16 nGroupID = lGroups[i1];
|
|
OUString sGroupID = OUString::number(nGroupID);
|
|
OUString sGroupName ;
|
|
|
|
try
|
|
{
|
|
m_xModuleCategoryInfo->getByName(sGroupID) >>= sGroupName;
|
|
if (sGroupName.isEmpty())
|
|
continue;
|
|
}
|
|
catch(const css::container::NoSuchElementException&)
|
|
{ continue; }
|
|
|
|
aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_FUNCTION, nGroupID ) );
|
|
m_xTreeView->append(weld::toId(aArr.back().get()), sGroupName);
|
|
nAddedGroups++;
|
|
}
|
|
return nAddedGroups;
|
|
}
|
|
catch(const css::uno::RuntimeException&)
|
|
{ throw; }
|
|
catch(const css::uno::Exception&)
|
|
{}
|
|
return 0;
|
|
}
|
|
|
|
void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::script::browse::XBrowseNode >& xRootNode,
|
|
const weld::TreeIter* pParentEntry)
|
|
{
|
|
try {
|
|
if ( xRootNode->hasChildNodes() )
|
|
{
|
|
// tdf#120362: Don't ask to enable disabled Java when filling script list
|
|
css::uno::ContextLayer layer(comphelper::NoEnableJavaInteractionContext());
|
|
|
|
const Sequence< Reference< browse::XBrowseNode > > children =
|
|
xRootNode->getChildNodes();
|
|
bool bIsRootNode = false;
|
|
|
|
OUString user(u"user"_ustr);
|
|
OUString share(u"share"_ustr);
|
|
if ( xRootNode->getName() == "Root" )
|
|
{
|
|
bIsRootNode = true;
|
|
}
|
|
|
|
//To mimic current starbasic behaviour we
|
|
//need to make sure that only the current document
|
|
//is displayed in the config tree. Tests below
|
|
//set the bDisplay flag to FALSE if the current
|
|
//node is a first level child of the Root and is NOT
|
|
//either the current document, user or share
|
|
OUString currentDocTitle;
|
|
Reference< XModel > xDocument( lcl_getScriptableDocument_nothrow( m_xFrame ) );
|
|
if ( xDocument.is() )
|
|
{
|
|
currentDocTitle = ::comphelper::DocumentInfo::getDocumentTitle( xDocument );
|
|
}
|
|
|
|
for ( Reference< browse::XBrowseNode > const & theChild : children )
|
|
{
|
|
if (!theChild.is())
|
|
continue;
|
|
|
|
bool bDisplay = true;
|
|
OUString uiName = theChild->getName();
|
|
if ( bIsRootNode )
|
|
{
|
|
if ( ! (uiName == user || uiName == share ||
|
|
uiName == currentDocTitle ) )
|
|
{
|
|
bDisplay=false;
|
|
}
|
|
else
|
|
{
|
|
if ( uiName == user )
|
|
{
|
|
uiName = xImp->m_sMyMacros;
|
|
}
|
|
else if ( uiName == share )
|
|
{
|
|
uiName = xImp->m_sProdMacros;
|
|
}
|
|
}
|
|
}
|
|
if (theChild->getType() != browse::BrowseNodeTypes::SCRIPT && bDisplay )
|
|
{
|
|
// We call acquire on the XBrowseNode so that it does not
|
|
// get autodestructed and become invalid when accessed later.
|
|
theChild->acquire();
|
|
|
|
bool bChildOnDemand = false;
|
|
|
|
if ( theChild->hasChildNodes() )
|
|
{
|
|
const Sequence< Reference< browse::XBrowseNode > > grandchildren =
|
|
theChild->getChildNodes();
|
|
|
|
for ( const auto& rxNode : grandchildren )
|
|
{
|
|
if (!rxNode.is())
|
|
continue;
|
|
|
|
if ( rxNode->getType() == browse::BrowseNodeTypes::CONTAINER )
|
|
{
|
|
bChildOnDemand = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
OUString aImage = GetImage(theChild, m_xContext, bIsRootNode);
|
|
|
|
aArr.push_back( std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_SCRIPTCONTAINER,
|
|
0, static_cast<void *>( theChild.get())));
|
|
|
|
OUString sId(weld::toId(aArr.back().get()));
|
|
m_xTreeView->insert(pParentEntry, -1, &uiName, &sId, nullptr, nullptr, bChildOnDemand, m_xScratchIter.get());
|
|
m_xTreeView->set_image(*m_xScratchIter, aImage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (RuntimeException&) {
|
|
// do nothing, the entry will not be displayed in the UI
|
|
}
|
|
}
|
|
|
|
void CuiConfigGroupListBox::FillFunctionsList(const css::uno::Sequence<DispatchInformation>& xCommands)
|
|
{
|
|
m_pFunctionListBox->freeze();
|
|
for (const auto & rInfo : xCommands)
|
|
{
|
|
auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(rInfo.Command, m_sModuleLongName);
|
|
|
|
OUString sUIName = MapCommand2UIName(rInfo.Command);
|
|
aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SLOT, 0 ) );
|
|
SfxGroupInfo_Impl* pGrpInfo = aArr.back().get();
|
|
pGrpInfo->sCommand = rInfo.Command;
|
|
pGrpInfo->sLabel = sUIName;
|
|
pGrpInfo->sTooltip = vcl::CommandInfoProvider::GetTooltipForCommand(rInfo.Command, aProperties, m_xFrame);
|
|
m_pFunctionListBox->append(weld::toId(pGrpInfo), sUIName);
|
|
}
|
|
m_pFunctionListBox->thaw();
|
|
}
|
|
|
|
void CuiConfigGroupListBox::Init(const css::uno::Reference< css::uno::XComponentContext >& xContext,
|
|
const css::uno::Reference< css::frame::XFrame >& xFrame,
|
|
const OUString& sModuleLongName,
|
|
bool bEventMode)
|
|
{
|
|
m_xTreeView->freeze();
|
|
ClearAll(); // Remove all old entries from treelist box
|
|
|
|
m_xContext = xContext;
|
|
m_xFrame = xFrame;
|
|
sal_Int32 nAddedGroups = 0;
|
|
if( bEventMode )
|
|
{
|
|
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 );
|
|
|
|
nAddedGroups = InitModule();
|
|
}
|
|
|
|
SAL_INFO("cui.customize", "** ** About to initialise SF Scripts");
|
|
// Add Scripting Framework entries
|
|
Reference< browse::XBrowseNode > rootNode;
|
|
try
|
|
{
|
|
Reference< browse::XBrowseNodeFactory > xFac = browse::theBrowseNodeFactory::get( m_xContext );
|
|
rootNode.set( xFac->createView( browse::BrowseNodeFactoryViewTypes::MACROSELECTOR ) );
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
TOOLS_WARN_EXCEPTION("cui.customize", "Caught some exception whilst retrieving browse nodes from factory");
|
|
// TODO exception handling
|
|
}
|
|
|
|
m_xTreeView->thaw();
|
|
m_xTreeView->make_sorted();
|
|
m_xTreeView->make_unsorted();
|
|
m_xTreeView->freeze();
|
|
|
|
// add All Commands to the top
|
|
if ( bEventMode && nAddedGroups )
|
|
{
|
|
aArr.insert(aArr.begin(), std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_ALLFUNCTIONS, 0));
|
|
OUString sId(weld::toId(aArr.front().get()));
|
|
OUString s(CuiResId(RID_CUISTR_ALLFUNCTIONS));
|
|
m_xTreeView->insert(nullptr, 0, &s, &sId, nullptr, nullptr, false, nullptr);
|
|
}
|
|
|
|
// add application macros to the end
|
|
if ( rootNode.is() )
|
|
{
|
|
if ( bEventMode )
|
|
{
|
|
//We call acquire on the XBrowseNode so that it does not
|
|
//get autodestructed and become invalid when accessed later.
|
|
rootNode->acquire();
|
|
|
|
aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_SCRIPTCONTAINER, 0,
|
|
static_cast<void *>(rootNode.get())));
|
|
OUString aTitle(xImp->m_sDlgMacros);
|
|
OUString sId(weld::toId(aArr.back().get()));
|
|
m_xTreeView->insert(nullptr, -1, &aTitle, &sId, nullptr, nullptr, true, nullptr);
|
|
}
|
|
else
|
|
{
|
|
//We are only showing scripts not slot APIs so skip
|
|
//Root node and show location nodes
|
|
FillScriptList(rootNode, nullptr);
|
|
}
|
|
}
|
|
|
|
// add styles and sidebar decks to the end
|
|
if ( bEventMode )
|
|
{
|
|
aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, nullptr ) ); // TODO last parameter should contain user data
|
|
OUString sStyle(xImp->m_aStrGroupStyles);
|
|
OUString sId(weld::toId(aArr.back().get()));
|
|
m_xTreeView->insert(nullptr, -1, &sStyle, &sId, nullptr, nullptr, true, nullptr);
|
|
|
|
aArr.push_back( std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_SIDEBARDECKS, 0));
|
|
OUString sSidebarDecks(xImp->m_aStrGroupSidebarDecks);
|
|
sId = weld::toId(aArr.back().get());
|
|
m_xTreeView->insert(nullptr, -1, &sSidebarDecks, &sId, nullptr, nullptr, false, nullptr);
|
|
}
|
|
|
|
m_xTreeView->thaw();
|
|
m_xTreeView->scroll_to_row(0);
|
|
m_xTreeView->select(0);
|
|
}
|
|
|
|
OUString CuiConfigGroupListBox::GetImage(
|
|
const Reference< browse::XBrowseNode >& node,
|
|
Reference< XComponentContext > const & xCtx,
|
|
bool bIsRootNode)
|
|
{
|
|
OUString aImage;
|
|
if ( bIsRootNode )
|
|
{
|
|
if (node->getName() == "user" || node->getName() == "share" )
|
|
{
|
|
aImage = RID_CUIBMP_HARDDISK;
|
|
}
|
|
else
|
|
{
|
|
OUString factoryURL;
|
|
OUString nodeName = node->getName();
|
|
Reference<XInterface> xDocumentModel = getDocumentModel(xCtx, nodeName );
|
|
if ( xDocumentModel.is() )
|
|
{
|
|
Reference< frame::XModuleManager2 > xModuleManager( frame::ModuleManager::create(xCtx) );
|
|
// get the long name of the document:
|
|
OUString appModule( xModuleManager->identify(
|
|
xDocumentModel ) );
|
|
Sequence<beans::PropertyValue> moduleDescr;
|
|
Any aAny = xModuleManager->getByName(appModule);
|
|
if( !( aAny >>= moduleDescr ) )
|
|
{
|
|
throw RuntimeException(u"SFTreeListBox::Init: failed to get PropertyValue"_ustr);
|
|
}
|
|
for ( sal_Int32 pos = moduleDescr.getLength(); pos--; )
|
|
{
|
|
if (moduleDescr[pos].Name == "ooSetupFactoryEmptyDocumentURL")
|
|
{
|
|
moduleDescr[pos].Value >>= factoryURL;
|
|
SAL_INFO("cui.customize", "factory url for doc images is " << factoryURL);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if( !factoryURL.isEmpty() )
|
|
{
|
|
aImage = SvFileInformationManager::GetFileImageId(INetURLObject(factoryURL));
|
|
}
|
|
else
|
|
{
|
|
aImage = RID_CUIBMP_DOC;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( node->getType() == browse::BrowseNodeTypes::SCRIPT )
|
|
aImage = RID_CUIBMP_MACRO;
|
|
else
|
|
aImage = RID_CUIBMP_LIB;
|
|
}
|
|
return aImage;
|
|
}
|
|
|
|
Reference< XInterface >
|
|
CuiConfigGroupListBox::getDocumentModel( Reference< XComponentContext > const & xCtx, std::u16string_view docName )
|
|
{
|
|
Reference< XInterface > xModel;
|
|
Reference< frame::XDesktop2 > desktop = frame::Desktop::create( xCtx );
|
|
|
|
Reference< container::XEnumerationAccess > componentsAccess =
|
|
desktop->getComponents();
|
|
Reference< container::XEnumeration > components =
|
|
componentsAccess->createEnumeration();
|
|
while (components->hasMoreElements())
|
|
{
|
|
Reference< frame::XModel > model(
|
|
components->nextElement(), UNO_QUERY );
|
|
if ( model.is() )
|
|
{
|
|
OUString sTdocUrl =
|
|
::comphelper::DocumentInfo::getDocumentTitle( model );
|
|
if( sTdocUrl == docName )
|
|
{
|
|
xModel = model;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return xModel;
|
|
}
|
|
|
|
OUString CuiConfigGroupListBox::MapCommand2UIName(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 CuiConfigGroupListBox::GroupSelected()
|
|
/* Description
|
|
A function group or a basic module has been selected.
|
|
All functions/macros are displayed in the functionlistbox.
|
|
*/
|
|
{
|
|
std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
|
|
if (!m_xTreeView->get_selected(xIter.get()))
|
|
return;
|
|
|
|
SfxGroupInfo_Impl *pInfo = weld::fromId<SfxGroupInfo_Impl*>(m_xTreeView->get_id(*xIter));
|
|
m_pFunctionListBox->freeze();
|
|
m_pFunctionListBox->ClearAll();
|
|
|
|
switch ( pInfo->nKind )
|
|
{
|
|
case SfxCfgKind::GROUP_ALLFUNCTIONS:
|
|
{
|
|
css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider( m_xFrame, UNO_QUERY );
|
|
bool bValidIter = m_xTreeView->get_iter_first(*xIter);
|
|
while (bValidIter)
|
|
{
|
|
SfxGroupInfo_Impl *pCurrentInfo = weld::fromId<SfxGroupInfo_Impl*>(m_xTreeView->get_id(*xIter));
|
|
if (pCurrentInfo->nKind == SfxCfgKind::GROUP_FUNCTION)
|
|
{
|
|
css::uno::Sequence< css::frame::DispatchInformation > lCommands;
|
|
try
|
|
{
|
|
lCommands = xProvider->getConfigurableDispatchInformation( pCurrentInfo->nUniqueID );
|
|
FillFunctionsList( lCommands );
|
|
}
|
|
catch ( container::NoSuchElementException& )
|
|
{
|
|
}
|
|
}
|
|
bValidIter = m_xTreeView->iter_next(*xIter);
|
|
}
|
|
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 );
|
|
break;
|
|
}
|
|
|
|
case SfxCfgKind::GROUP_SCRIPTCONTAINER:
|
|
{
|
|
Reference< browse::XBrowseNode > rootNode(
|
|
static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ;
|
|
|
|
try {
|
|
if ( rootNode->hasChildNodes() )
|
|
{
|
|
const Sequence< Reference< browse::XBrowseNode > > children =
|
|
rootNode->getChildNodes();
|
|
|
|
for ( const Reference< browse::XBrowseNode >& childNode : children )
|
|
{
|
|
if (!childNode.is())
|
|
continue;
|
|
|
|
if (childNode->getType() == browse::BrowseNodeTypes::SCRIPT)
|
|
{
|
|
OUString uri, description;
|
|
|
|
Reference < beans::XPropertySet >xPropSet( childNode, UNO_QUERY );
|
|
if (!xPropSet.is())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Any value =
|
|
xPropSet->getPropertyValue(u"URI"_ustr);
|
|
value >>= uri;
|
|
|
|
try
|
|
{
|
|
value = xPropSet->getPropertyValue(u"Description"_ustr);
|
|
value >>= description;
|
|
}
|
|
catch (Exception &) {
|
|
// do nothing, the description will be empty
|
|
}
|
|
|
|
OUString* pScriptURI = new OUString( uri );
|
|
|
|
OUString aImage = GetImage(childNode, Reference< XComponentContext >(), false);
|
|
m_pFunctionListBox->aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI ));
|
|
m_pFunctionListBox->aArr.back()->sCommand = uri;
|
|
m_pFunctionListBox->aArr.back()->sLabel = childNode->getName();
|
|
m_pFunctionListBox->aArr.back()->sHelpText = description;
|
|
|
|
OUString sId(weld::toId(m_pFunctionListBox->aArr.back().get()));
|
|
m_pFunctionListBox->append(sId, childNode->getName(), aImage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (RuntimeException&) {
|
|
// do nothing, the entry will not be displayed in the UI
|
|
}
|
|
break;
|
|
}
|
|
|
|
case SfxCfgKind::GROUP_STYLES :
|
|
{
|
|
SfxStyleInfo_Impl* pFamily = static_cast<SfxStyleInfo_Impl*>(pInfo->pObject);
|
|
if (pFamily)
|
|
{
|
|
const std::vector< SfxStyleInfo_Impl > lStyles = m_pStylesInfo->getStyles(pFamily->sFamily);
|
|
for (auto const& lStyle : lStyles)
|
|
{
|
|
SfxStyleInfo_Impl* pStyle = new SfxStyleInfo_Impl(lStyle);
|
|
m_pFunctionListBox->aArr.push_back(std::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_STYLES, 0, pStyle));
|
|
m_pFunctionListBox->aArr.back()->sCommand = pStyle->sCommand;
|
|
m_pFunctionListBox->aArr.back()->sLabel = pStyle->sLabel;
|
|
OUString sId(weld::toId(m_pFunctionListBox->aArr.back().get()));
|
|
m_pFunctionListBox->append(sId, pStyle->sLabel);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case SfxCfgKind::GROUP_SIDEBARDECKS:
|
|
{
|
|
sfx2::sidebar::ResourceManager aResourceManager;
|
|
sfx2::sidebar::Context aContext(m_sModuleLongName, OUString());
|
|
sfx2::sidebar::ResourceManager::DeckContextDescriptorContainer aDecks;
|
|
aResourceManager.GetMatchingDecks(aDecks, aContext, false, m_xFrame->getController());
|
|
|
|
for (auto const& rDeck : aDecks)
|
|
{
|
|
const OUString sCommand = ".uno:SidebarDeck." + rDeck.msId;
|
|
m_pFunctionListBox->aArr.push_back(std::make_unique<SfxGroupInfo_Impl>(
|
|
SfxCfgKind::GROUP_SIDEBARDECKS, 0,
|
|
nullptr));
|
|
m_pFunctionListBox->aArr.back()->sCommand = sCommand;
|
|
m_pFunctionListBox->aArr.back()->sLabel = rDeck.msId;
|
|
m_pFunctionListBox->aArr.back()->sTooltip =
|
|
vcl::CommandInfoProvider::GetCommandShortcut(sCommand, m_xFrame);
|
|
m_pFunctionListBox->append(weld::toId(m_pFunctionListBox->aArr.back().get()),
|
|
rDeck.msId);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
// Do nothing, the list box will stay empty
|
|
SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " << static_cast<int>(pInfo->nKind) );
|
|
break;
|
|
}
|
|
|
|
m_pFunctionListBox->thaw();
|
|
|
|
if (m_pFunctionListBox->n_children())
|
|
m_pFunctionListBox->select(0);
|
|
}
|
|
|
|
/* Description
|
|
A basic or a library is opened.
|
|
*/
|
|
IMPL_LINK(CuiConfigGroupListBox, ExpandingHdl, const weld::TreeIter&, rIter, bool)
|
|
{
|
|
SfxGroupInfo_Impl *pInfo = weld::fromId<SfxGroupInfo_Impl*>(m_xTreeView->get_id(rIter));
|
|
switch ( pInfo->nKind )
|
|
{
|
|
case SfxCfgKind::GROUP_SCRIPTCONTAINER:
|
|
{
|
|
if (!m_xTreeView->iter_has_child(rIter))
|
|
{
|
|
Reference< browse::XBrowseNode > rootNode(
|
|
static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ;
|
|
FillScriptList(rootNode, &rIter);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case SfxCfgKind::GROUP_STYLES:
|
|
{
|
|
if (!m_xTreeView->iter_has_child(rIter))
|
|
{
|
|
const std::vector<SfxStyleInfo_Impl> lStyleFamilies = m_pStylesInfo->getStyleFamilies();
|
|
for (auto const& lStyleFamily : lStyleFamilies)
|
|
{
|
|
SfxStyleInfo_Impl* pFamily = new SfxStyleInfo_Impl(lStyleFamily);
|
|
aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, pFamily ));
|
|
OUString sId(weld::toId(aArr.back().get()));
|
|
m_xTreeView->insert(&rIter, -1, &pFamily->sLabel, &sId, nullptr, nullptr, false, nullptr);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
OSL_FAIL( "Wrong group type!" );
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#if HAVE_FEATURE_SCRIPTING
|
|
void CuiConfigGroupListBox::SelectMacro( const SfxMacroInfoItem *pItem )
|
|
{
|
|
const std::u16string_view aLocation = pItem->GetLocation();
|
|
const std::u16string_view aLib = pItem->GetLib();
|
|
const std::u16string_view aModule = pItem->GetModule();
|
|
const std::u16string_view aMethod = pItem->GetMethod();
|
|
|
|
std::unique_ptr<weld::TreeIter> xIter = m_xTreeView->make_iterator();
|
|
if (!m_xTreeView->get_iter_first(*xIter))
|
|
return;
|
|
|
|
do
|
|
{
|
|
OUString aEntryBas = m_xTreeView->get_text(*xIter);
|
|
if (aEntryBas == xImp->m_sDlgMacros)
|
|
{
|
|
m_xTreeView->expand_row(*xIter);
|
|
std::unique_ptr<weld::TreeIter> xLocationIter = m_xTreeView->make_iterator(xIter.get());
|
|
if (m_xTreeView->iter_children(*xLocationIter))
|
|
{
|
|
do
|
|
{
|
|
if (aLocation != m_xTreeView->get_text(*xLocationIter))
|
|
continue;
|
|
m_xTreeView->expand_row(*xLocationIter);
|
|
std::unique_ptr<weld::TreeIter> xLibIter = m_xTreeView->make_iterator(xLocationIter.get());
|
|
if (m_xTreeView->iter_children(*xLibIter))
|
|
{
|
|
do
|
|
{
|
|
OUString aEntryLib = m_xTreeView->get_text(*xLibIter);
|
|
if (aEntryLib == aLib)
|
|
{
|
|
if (aModule.empty())
|
|
{
|
|
m_xTreeView->scroll_to_row(*xLibIter);
|
|
m_xTreeView->select(*xLibIter);
|
|
GroupSelected();
|
|
weld::TreeView& rFunctionListBoxTreeView
|
|
= m_pFunctionListBox->get_widget();
|
|
std::unique_ptr<weld::TreeIter> xFunctionListBoxIter
|
|
= rFunctionListBoxTreeView.make_iterator();
|
|
if (!rFunctionListBoxTreeView.get_iter_first(
|
|
*xFunctionListBoxIter))
|
|
return;
|
|
do
|
|
{
|
|
OUString aEntryMethod = rFunctionListBoxTreeView.get_text(
|
|
*xFunctionListBoxIter);
|
|
if (aEntryMethod == aMethod)
|
|
{
|
|
rFunctionListBoxTreeView.scroll_to_row(
|
|
*xFunctionListBoxIter);
|
|
rFunctionListBoxTreeView.select(*xFunctionListBoxIter);
|
|
return;
|
|
}
|
|
} while (
|
|
rFunctionListBoxTreeView.iter_next(*xFunctionListBoxIter));
|
|
return;
|
|
}
|
|
|
|
m_xTreeView->expand_row(*xLibIter);
|
|
std::unique_ptr<weld::TreeIter> xModIter = m_xTreeView->make_iterator(xLibIter.get());
|
|
if (m_xTreeView->iter_children(*xModIter))
|
|
{
|
|
do
|
|
{
|
|
OUString aEntryMod = m_xTreeView->get_text(*xModIter);
|
|
if ( aEntryMod == aModule )
|
|
{
|
|
m_xTreeView->expand_row(*xModIter);
|
|
m_xTreeView->scroll_to_row(*xModIter);
|
|
m_xTreeView->select(*xModIter);
|
|
GroupSelected();
|
|
for (int i = 0, nCount = m_pFunctionListBox->n_children(); i < nCount; ++i)
|
|
{
|
|
OUString aEntryMethod = m_pFunctionListBox->get_text(i);
|
|
if (aEntryMethod == aMethod)
|
|
{
|
|
m_pFunctionListBox->select(i);
|
|
m_pFunctionListBox->scroll_to_row(i);
|
|
return;
|
|
}
|
|
}
|
|
m_xTreeView->collapse_row(*xModIter);
|
|
}
|
|
} while (m_xTreeView->iter_next_sibling(*xModIter));
|
|
}
|
|
m_xTreeView->collapse_row(*xLibIter);
|
|
}
|
|
} while (m_xTreeView->iter_next_sibling(*xLibIter));
|
|
}
|
|
m_xTreeView->collapse_row(*xLocationIter);
|
|
} while (m_xTreeView->iter_next_sibling(*xLocationIter));
|
|
}
|
|
// If the macro can't be located, preselect the "Application Macros" category:
|
|
m_xTreeView->scroll_to_row(*xIter);
|
|
m_xTreeView->select(*xIter);
|
|
return;
|
|
}
|
|
} while (m_xTreeView->iter_next_sibling(*xIter));
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Implementation of SvxScriptSelectorDialog
|
|
*
|
|
* This dialog is used for selecting Slot API commands
|
|
* and Scripting Framework Scripts.
|
|
*/
|
|
|
|
SvxScriptSelectorDialog::SvxScriptSelectorDialog(
|
|
weld::Window* pParent, const css::uno::Reference< css::frame::XFrame >& xFrame)
|
|
: GenericDialogController(pParent, u"cui/ui/macroselectordialog.ui"_ustr, u"MacroSelectorDialog"_ustr)
|
|
, m_xDialogDescription(m_xBuilder->weld_label(u"helpmacro"_ustr))
|
|
, m_xCategories(new CuiConfigGroupListBox(m_xBuilder->weld_tree_view(u"categories"_ustr)))
|
|
, m_xCommands(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view(u"commands"_ustr)))
|
|
, m_xLibraryFT(m_xBuilder->weld_label(u"libraryft"_ustr))
|
|
, m_xMacronameFT(m_xBuilder->weld_label(u"macronameft"_ustr))
|
|
, m_xOKButton(m_xBuilder->weld_button(u"ok"_ustr))
|
|
, m_xCancelButton(m_xBuilder->weld_button(u"cancel"_ustr))
|
|
, m_xDescriptionText(m_xBuilder->weld_text_view(u"description"_ustr))
|
|
, m_xDescriptionFrame(m_xBuilder->weld_frame(u"descriptionframe"_ustr))
|
|
{
|
|
m_xCancelButton->show();
|
|
m_xDialogDescription->show();
|
|
m_xOKButton->show();
|
|
|
|
m_xLibraryFT->set_visible(true);
|
|
m_xMacronameFT->set_visible(true);
|
|
|
|
const OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(xFrame));
|
|
m_xCategories->SetFunctionListBox(m_xCommands.get());
|
|
m_xCategories->Init(comphelper::getProcessComponentContext(), xFrame, aModuleName, /*bShowSlots*/false);
|
|
|
|
m_xCategories->connect_changed(
|
|
LINK( this, SvxScriptSelectorDialog, SelectHdl ) );
|
|
m_xCommands->connect_changed( LINK( this, SvxScriptSelectorDialog, SelectHdl ) );
|
|
m_xCommands->connect_row_activated( LINK( this, SvxScriptSelectorDialog, FunctionDoubleClickHdl ) );
|
|
m_xCommands->connect_popup_menu( LINK( this, SvxScriptSelectorDialog, ContextMenuHdl ) );
|
|
|
|
m_xOKButton->connect_clicked( LINK( this, SvxScriptSelectorDialog, ClickHdl ) );
|
|
m_xCancelButton->connect_clicked( LINK( this, SvxScriptSelectorDialog, ClickHdl ) );
|
|
|
|
m_sDefaultDesc = m_xDescriptionText->get_text();
|
|
|
|
// Support style commands
|
|
uno::Reference<frame::XController> xController;
|
|
uno::Reference<frame::XModel> xModel;
|
|
if (xFrame.is())
|
|
xController = xFrame->getController();
|
|
if (xController.is())
|
|
xModel = xController->getModel();
|
|
|
|
m_aStylesInfo.init(aModuleName, xModel);
|
|
m_xCategories->SetStylesInfo(&m_aStylesInfo);
|
|
|
|
// The following call is a workaround to make scroll_to_row work as expected in kf5/x11
|
|
m_xDialog->resize_to_request();
|
|
|
|
LoadLastUsedMacro();
|
|
UpdateUI();
|
|
|
|
if (comphelper::LibreOfficeKit::isActive())
|
|
m_xDescriptionFrame->hide();
|
|
}
|
|
|
|
SvxScriptSelectorDialog::~SvxScriptSelectorDialog()
|
|
{
|
|
}
|
|
|
|
IMPL_LINK(SvxScriptSelectorDialog, SelectHdl, weld::TreeView&, rCtrl, void)
|
|
{
|
|
if (&rCtrl == &m_xCategories->get_widget())
|
|
{
|
|
m_xCategories->GroupSelected();
|
|
}
|
|
UpdateUI();
|
|
}
|
|
|
|
IMPL_LINK_NOARG(SvxScriptSelectorDialog, FunctionDoubleClickHdl, weld::TreeView&, bool)
|
|
{
|
|
if (m_xOKButton->get_sensitive())
|
|
ClickHdl(*m_xOKButton);
|
|
return true;
|
|
}
|
|
|
|
IMPL_LINK(SvxScriptSelectorDialog, ContextMenuHdl, const CommandEvent&, rCEvt, bool)
|
|
{
|
|
weld::TreeView& xTreeView = m_xCommands->get_widget();
|
|
if (rCEvt.GetCommand() != CommandEventId::ContextMenu || !xTreeView.n_children())
|
|
return false;
|
|
|
|
std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(&xTreeView, u"modules/BasicIDE/ui/sortmenu.ui"_ustr));
|
|
std::unique_ptr<weld::Menu> xPopup(xBuilder->weld_menu(u"sortmenu"_ustr));
|
|
std::unique_ptr<weld::Menu> xDropMenu(xBuilder->weld_menu(u"sortsubmenu"_ustr));
|
|
xDropMenu->set_active(u"alphabetically"_ustr, xTreeView.get_sort_order());
|
|
xDropMenu->set_active(u"properorder"_ustr, !xTreeView.get_sort_order());
|
|
|
|
OUString sCommand(xPopup->popup_at_rect(&xTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1))));
|
|
if (sCommand == "alphabetically")
|
|
{
|
|
xTreeView.make_sorted();
|
|
}
|
|
else if (sCommand == "properorder")
|
|
{
|
|
xTreeView.make_unsorted();
|
|
m_xCategories->GroupSelected();
|
|
}
|
|
else if (!sCommand.isEmpty())
|
|
{
|
|
SAL_WARN("cui.customize", "Unknown context menu action: " << sCommand );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Check if command is selected and enable the OK button accordingly
|
|
// Grab the help text for this id if available and update the description field
|
|
void
|
|
SvxScriptSelectorDialog::UpdateUI()
|
|
{
|
|
OUString url = GetScriptURL();
|
|
if ( !url.isEmpty() )
|
|
{
|
|
OUString sMessage = m_xCommands->GetCommandHelpText();
|
|
m_xDescriptionText->set_text(sMessage.isEmpty() ? m_sDefaultDesc : sMessage);
|
|
m_xOKButton->set_sensitive(true);
|
|
}
|
|
else
|
|
{
|
|
m_xDescriptionText->set_text(m_sDefaultDesc);
|
|
m_xOKButton->set_sensitive(false);
|
|
}
|
|
}
|
|
|
|
IMPL_LINK(SvxScriptSelectorDialog, ClickHdl, weld::Button&, rButton, void)
|
|
{
|
|
if (&rButton == m_xCancelButton.get())
|
|
{
|
|
m_xDialog->response(RET_CANCEL);
|
|
}
|
|
else if (&rButton == m_xOKButton.get())
|
|
{
|
|
SaveLastUsedMacro();
|
|
m_xDialog->response(RET_OK);
|
|
}
|
|
}
|
|
|
|
void
|
|
SvxScriptSelectorDialog::SetRunLabel()
|
|
{
|
|
m_xOKButton->set_label(CuiResId(RID_CUISTR_SELECTOR_RUN));
|
|
}
|
|
|
|
OUString
|
|
SvxScriptSelectorDialog::GetScriptURL() const
|
|
{
|
|
OUString result;
|
|
|
|
std::unique_ptr<weld::TreeIter> xIter = m_xCommands->make_iterator();
|
|
if (m_xCommands->get_selected(xIter.get()))
|
|
{
|
|
SfxGroupInfo_Impl *pData = weld::fromId<SfxGroupInfo_Impl*>(m_xCommands->get_id(*xIter));
|
|
if ( ( pData->nKind == SfxCfgKind::FUNCTION_SLOT )
|
|
|| ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT )
|
|
|| ( pData->nKind == SfxCfgKind::GROUP_STYLES )
|
|
)
|
|
{
|
|
result = pData->sCommand;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
SvxScriptSelectorDialog::SaveLastUsedMacro()
|
|
{
|
|
// Gets the current selection in the dialog as a series of selected entries
|
|
OUString sMacroInfo;
|
|
sMacroInfo = m_xCommands->get_selected_text();
|
|
weld::TreeView& xCategories = m_xCategories->get_widget();
|
|
std::unique_ptr<weld::TreeIter> xIter = xCategories.make_iterator();
|
|
|
|
if (!xCategories.get_selected(xIter.get()))
|
|
return;
|
|
|
|
do
|
|
{
|
|
sMacroInfo = xCategories.get_text(*xIter) + "|" + sMacroInfo;
|
|
} while (xCategories.iter_parent(*xIter));
|
|
|
|
SvtViewOptions( EViewType::Dialog, MACRO_SELECTOR_CONFIGNAME ).SetUserItem(
|
|
LAST_RUN_MACRO_INFO, Any(sMacroInfo));
|
|
}
|
|
|
|
void
|
|
SvxScriptSelectorDialog::LoadLastUsedMacro()
|
|
{
|
|
SvtViewOptions aDlgOpt( EViewType::Dialog, MACRO_SELECTOR_CONFIGNAME );
|
|
if (!aDlgOpt.Exists())
|
|
return;
|
|
|
|
OUString sMacroInfo;
|
|
aDlgOpt.GetUserItem(LAST_RUN_MACRO_INFO) >>= sMacroInfo;
|
|
if (sMacroInfo.isEmpty())
|
|
return;
|
|
|
|
// Counts how many entries exist in the macro info string
|
|
sal_Int16 nInfoParts = 0;
|
|
sal_Int16 nLastIndex = sMacroInfo.indexOf('|');
|
|
if (nLastIndex > -1)
|
|
{
|
|
nInfoParts = 1;
|
|
while ( nLastIndex != -1 )
|
|
{
|
|
nInfoParts++;
|
|
nLastIndex = sMacroInfo.indexOf('|', nLastIndex + 1);
|
|
}
|
|
}
|
|
|
|
weld::TreeView& xCategories = m_xCategories->get_widget();
|
|
std::unique_ptr<weld::TreeIter> xIter = xCategories.make_iterator();
|
|
if (!xCategories.get_iter_first(*xIter))
|
|
return;
|
|
|
|
// Expand the nodes in the category tree
|
|
OUString sNodeToExpand;
|
|
bool bIsIterValid;
|
|
sal_Int16 nOpenedNodes = 0;
|
|
for (sal_Int16 i=0; i<nInfoParts - 1; i++)
|
|
{
|
|
sNodeToExpand = sMacroInfo.getToken(i, '|');
|
|
bIsIterValid = true;
|
|
while (bIsIterValid && xCategories.get_text(*xIter) != sNodeToExpand)
|
|
bIsIterValid = xCategories.iter_next_sibling(*xIter);
|
|
|
|
if (bIsIterValid)
|
|
{
|
|
xCategories.expand_row(*xIter);
|
|
nOpenedNodes++;
|
|
}
|
|
if (xCategories.iter_has_child(*xIter))
|
|
(void)xCategories.iter_children(*xIter);
|
|
else if (nOpenedNodes < nInfoParts - 1)
|
|
// If the number of levels in the tree is smaller than the
|
|
// number of parts in the macro info string, then return
|
|
return;
|
|
}
|
|
xCategories.select(*xIter);
|
|
xCategories.scroll_to_row(*xIter);
|
|
m_xCategories->GroupSelected();
|
|
|
|
// Select the macro in the command tree
|
|
weld::TreeView& xCommands = m_xCommands->get_widget();
|
|
xIter = xCommands.make_iterator();
|
|
if (!xCommands.get_iter_first(*xIter))
|
|
return;
|
|
|
|
OUString sMacroName = sMacroInfo.getToken(nInfoParts - 1, '|');
|
|
bIsIterValid = true;
|
|
while (bIsIterValid && xCommands.get_text(*xIter) != sMacroName)
|
|
bIsIterValid = xCommands.iter_next_sibling(*xIter);
|
|
|
|
if (bIsIterValid)
|
|
{
|
|
xCommands.scroll_to_row(*xIter);
|
|
xCommands.select(*xIter);
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|