Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  cfgutil.cxx   Sprache: 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() );
                }
            }
        }
        catchconst 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 ) );
    }
    catchconst 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&,&nbsp;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: */

Messung V0.5
C=95 H=92 G=93

¤ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Ziele

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Ergonomie der
Schnittstellen

Diese beiden folgenden Angebotsgruppen bietet das Unternehmen

Angebot

Hier finden Sie eine Liste der Produkte des Unternehmens






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge