Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/cui/source/dialogs/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 101 kB image not shown  

SSL MacroManagerDialog.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */


#include <sal/config.h>

#include <MacroManagerDialog.hxx>

#include <bitmaps.hlst>
#include <cfgutil.hxx>
#include <dialmgr.hxx>
#include <scriptdlg.hxx>
#include <strings.hrc>
#include <basctl/basctldllpublic.hxx>
#include <basctl/sbxitem.hxx>
#include <basctl/scriptdocument.hxx>
#include <basic/basmgr.hxx>
#include <comphelper/SetFlagContextHelper.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <comphelper/documentinfo.hxx>
#include <comphelper/lok.hxx>
#include <comphelper/processfactory.hxx>
#include <osl/file.hxx>
#include <sfx2/app.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/minfitem.hxx>
#include <sfx2/request.hxx>
#include <sfx2/sfxsids.hrc>
#include <sfx2/viewfrm.hxx>
#include <svl/itemset.hxx>
#include <svl/stritem.hxx>
#include <svtools/imagemgr.hxx>
#include <svx/passwd.hxx>
#include <tools/urlobj.hxx>
#include <unotools/viewoptions.hxx>
#include <vcl/commandevent.hxx>
#include <vcl/weldutils.hxx>
#include <dlgname.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/frame/Desktop.hpp>
#include <com/sun/star/document/XEmbeddedScripts.hpp>
#include <com/sun/star/document/XScriptInvocationContext.hpp>
#include <com/sun/star/frame/ModuleManager.hpp>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/frame/XModel.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/script/XLibraryContainer2.hpp>
#include <com/sun/star/script/XLibraryContainerPassword.hpp>
#include <com/sun/star/script/XPersistentLibraryContainer.hpp>
#include <com/sun/star/script/XInvocation.hpp>
#include <com/sun/star/uno/RuntimeException.hpp>

ScriptsListBox::ScriptsListBox(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, ScriptsListBox, QueryTooltip));
}

ScriptsListBox::~ScriptsListBox() { ClearAll(); }

void ScriptsListBox::ClearAll()
{
    sal_uInt16 nCount = aArr.size();
    for (sal_uInt16 i = 0; i < nCount; ++i)
    {
        ScriptInfo* pScriptInfo = aArr[i].get();
        if (pScriptInfo && pScriptInfo->pBrowseNode)
            pScriptInfo->pBrowseNode->release();
    }
    aArr.clear();
    m_xTreeView->clear();
}

void ScriptsListBox::Remove(const weld::TreeIter& rEntry)
{
    ScriptInfo* pScriptInfo = weld::fromId<ScriptInfo*>(m_xTreeView->get_id(rEntry));
    if (pScriptInfo)
    {
        if (pScriptInfo->pBrowseNode)
            pScriptInfo->pBrowseNode->release();
        for (auto it = aArr.begin(); it != aArr.end(); ++it)
        {
            if ((*it).get() == pScriptInfo)
            {
                aArr.erase(it);
                break;
            }
        }
    }
    m_xTreeView->remove(rEntry);
}

OUString ScriptsListBox::GetDescriptionText(const OUString& rId)
{
    ScriptInfo* pScriptInfo = weld::fromId<ScriptInfo*>(rId);
    if (pScriptInfo)
    {
        return pScriptInfo->sDescription;
    }
    return OUString();
}

OUString ScriptsListBox::GetSelectedScriptName()
{
    std::unique_ptr<weld::TreeIter> xScriptsEntryIter = m_xTreeView->make_iterator();
    if (!m_xTreeView->get_selected(xScriptsEntryIter.get()))
        return OUString();
    return m_xTreeView->get_text(*xScriptsEntryIter);
}

IMPL_LINK(ScriptsListBox, QueryTooltip, const weld::TreeIter&, rEntryIter, OUString)
{
    return GetDescriptionText(m_xTreeView->get_id(rEntryIter));
}

ScriptContainersListBox::ScriptContainersListBox(std::unique_ptr<weld::TreeView> xTreeView,
                                                 MacroManagerDialog* pMacroManagerDialog)
    : m_pScriptsListBox(nullptr)
    , m_xTreeView(std::move(xTreeView))
    , m_pMacroManagerDialog(pMacroManagerDialog)
{
    m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 35,
                                  m_xTreeView->get_height_rows(9));
    m_xTreeView->connect_expanding(LINK(this, ScriptContainersListBox, ExpandingHdl));
    m_xTreeView->connect_query_tooltip(LINK(this, ScriptContainersListBox, QueryTooltip));
}

ScriptContainersListBox::~ScriptContainersListBox() { ClearAll(); }

void ScriptContainersListBox::ClearAll()
{
    sal_uInt16 nCount = m_xTreeView->n_children();
    for (sal_uInt16 i = 0; i < nCount; ++i)
    {
        ScriptContainerInfo* pScriptContainerInfo
            = weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(i));
        if (pScriptContainerInfo)
        {
            if (pScriptContainerInfo->pBrowseNode)
                pScriptContainerInfo->pBrowseNode->release();
            delete pScriptContainerInfo;
        }
    }
    m_xTreeView->clear();
}

void ScriptContainersListBox::Init(const css::uno::Reference<css::uno::XComponentContext>& xContext,
                                   const css::uno::Reference<css::frame::XFrame>& xFrame)
{
    m_xContext = xContext;
    m_xFrame = xFrame;
    m_xTreeView->freeze();
    Fill(nullptr);
    m_xTreeView->thaw();
    m_xTreeView->set_cursor(0);
}

void ScriptContainersListBox::Remove(const weld::TreeIter* pEntryIter, bool bRemoveEntryIter)
{
    // remove all children of pEntryIter
    std::unique_ptr<weld::TreeIter> xIter = m_xTreeView->make_iterator(pEntryIter);
    if (m_xTreeView->iter_has_child(*pEntryIter) && m_xTreeView->iter_children(*xIter))
    {
        // set xIter to the last child of pEntryIter
        do
        {
            std::unique_ptr<weld::TreeIter> xChildIter = m_xTreeView->make_iterator(xIter.get());
            while (m_xTreeView->iter_next_sibling(*xChildIter))
                m_xTreeView->copy_iterator(*xChildIter, *xIter);
        } while (m_xTreeView->iter_has_child(*xIter) && m_xTreeView->iter_children(*xIter));

        // children must be removed from the tree in reverse order
        std::unique_ptr<weld::TreeIter> xRemoveIter = m_xTreeView->make_iterator();
        while (m_xTreeView->iter_compare(*xIter, *pEntryIter) != 0)
        {
            m_xTreeView->copy_iterator(*xIter, *xRemoveIter);
            (void)m_xTreeView->iter_previous(*xIter);
            ScriptContainerInfo* pScriptContainerInfo
                = weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*xRemoveIter));
            if (pScriptContainerInfo)
            {
                if (pScriptContainerInfo->pBrowseNode)
                    pScriptContainerInfo->pBrowseNode->release();
                delete pScriptContainerInfo;
            }
            m_xTreeView->remove(*xRemoveIter);
        }
    }

    // maybe remove the entry
    if (bRemoveEntryIter)
    {
        ScriptContainerInfo* pScriptContainerInfo
            = weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*pEntryIter));
        if (pScriptContainerInfo)
        {
            if (pScriptContainerInfo->pBrowseNode)
                pScriptContainerInfo->pBrowseNode->release();
            delete pScriptContainerInfo;
        }
        m_xTreeView->remove(*pEntryIter);
    }
}

// inspired by CuiConfigGroupListBox::FillScriptList
// cui/source/customize/cfgutil.cxx
void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter)
{
    weld::WaitObject aWait(m_pMacroManagerDialog->getDialog());

    css::uno::Reference<css::script::browse::XBrowseNode> xNode;
    if (pEntryIter == nullptr)
    {
        ClearAll();
        try
        {
            css::uno::Reference<css::script::browse::XBrowseNodeFactory> xFac
                = css::script::browse::theBrowseNodeFactory::get(
                    comphelper::getProcessComponentContext());
            xNode.set(
                xFac->createView(css::script::browse::BrowseNodeFactoryViewTypes::MACROORGANIZER));
        }
        catch (const css::uno::Exception&)
        {
            TOOLS_WARN_EXCEPTION(
                "cui.dialogs""Caught some exception whilst retrieving browse nodes from factory");
            // TODO exception handling
            return;
        }
    }
    else
    {
        ScriptContainerInfo* pScriptContainerInfoEntry
            = weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*pEntryIter));

        xNode.set(pScriptContainerInfoEntry->pBrowseNode);

        Remove(pEntryIter, /*bRemoveEntryIter*/ false);
    }

    if (xNode->hasChildNodes())
    {
        // tdf#120362: Don't ask to enable disabled Java when filling script list
        css::uno::ContextLayer layer(comphelper::NoEnableJavaInteractionContext());

        bool bIsRootNode = false;

        OUString user(u"user"_ustr);
        OUString share(u"share"_ustr);
        OUString uno_packages(u"uno_packages"_ustr);
        if (xNode->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
        //
        // NOTE: This approach doesn't work for open documents with the same name, for example
        // Untitled 1.odt and Untitled 1.ods will both be included as root containers.
        OUString currentDocTitle;
        if (css::uno::Reference<css::frame::XController> xController = m_xFrame->getController();
            xController.is())
        {
            css::uno::Reference<css::frame::XModel> xModel = xController->getModel();
            if (xModel.is())
                currentDocTitle = comphelper::DocumentInfo::getDocumentTitle(xModel);
        }

        const css::uno::Sequence<css::uno::Reference<css::script::browse::XBrowseNode>> children
            = xNode->getChildNodes();
        for (css::uno::Reference<css::script::browse::XBrowseNode> const& theChild : children)
        {
            if (!theChild.is())
                continue;

            if (theChild->getType() == css::script::browse::BrowseNodeTypes::SCRIPT)
                // we only want containers in this list box
                continue;
            if (theChild->getName() == uno_packages)
                continue;

            OUString uiName = theChild->getName();
            if (bIsRootNode)
            {
                if (uiName == user)
                {
                    uiName = CuiResId(RID_CUISTR_MYMACROS);
                }
                else if (uiName == share)
                {
                    uiName = CuiResId(RID_CUISTR_PRODMACROS);
                }
                else if (uiName != currentDocTitle)
                {
                    // as noted above
                    // NOTE: This approach doesn't work for open documents with the same name, for
                    // example, Untitled 1.odt and Untitled 1.ods will both be included as root
                    // containers.
                    continue;
                }
            }

            // 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 css::uno::Sequence<css::uno::Reference<css::script::browse::XBrowseNode>>
                    grandchildren = theChild->getChildNodes();
                for (const auto& rxNode : grandchildren)
                {
                    if (!rxNode.is())
                        continue;
                    if (rxNode->getType() == css::script::browse::BrowseNodeTypes::CONTAINER)
                    {
                        bChildOnDemand = true;
                        break;
                    }
                }
            }

            OUString aImage = CuiConfigGroupListBox::GetImage(theChild, m_xContext, bIsRootNode);
            Insert(theChild, pEntryIter, uiName, aImage, bChildOnDemand);
        }
    }

    // add Basic dialogs
    if (pEntryIter && m_xTreeView->get_iter_depth(*pEntryIter) == 2) // library
    {
        // parent node of entry node is a language node
        std::unique_ptr<weld::TreeIter> xIter = m_xTreeView->make_iterator(pEntryIter);
        m_xTreeView->iter_parent(*xIter); // language
        if (m_xTreeView->get_text(*xIter) == "Basic")
        {
            basctl::ScriptDocument aDocument = GetScriptDocument(pEntryIter);
            if (!aDocument.isAlive())
            {
                return;
            }

            OUString aLibName = m_xTreeView->get_text(*pEntryIter);

            css::uno::Reference<css::script::XLibraryContainer> xDlgLibContainer(
                aDocument.getLibraryContainer(basctl::E_DIALOGS));

            if (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName)
                && !xDlgLibContainer->isLibraryLoaded(aLibName))
            {
                xDlgLibContainer->loadLibrary(aLibName);
            }

            if (!(xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName)
                  && xDlgLibContainer->isLibraryLoaded(aLibName)))
            {
                return;
            }

            for (const OUString& rDlgName : aDocument.getObjectNames(basctl::E_DIALOGS, aLibName))
            {
                Insert(nullptr, pEntryIter, rDlgName, RID_CUIBMP_DIALOG, false);
            }
        }
    }
}

void ScriptContainersListBox::Insert(
    const css::uno::Reference<css::script::browse::XBrowseNode>& xInsertNode,
    const weld::TreeIter* pIter, const OUString& rsUiName, const OUString& rsImage,
    bool bChildOnDemand, int nPos, weld::TreeIter* pRet)
{
    std::unique_ptr<weld::TreeIter> xNewEntryIter = m_xTreeView->make_iterator();

    OUString sId(weld::toId(new ScriptContainerInfo(xInsertNode.get())));
    m_xTreeView->insert(pIter, nPos, &rsUiName, &sId, nullptr, nullptr, bChildOnDemand,
                        xNewEntryIter.get());
    m_xTreeView->set_image(*xNewEntryIter, rsImage);

    //  set password and linked image only for Basic libraries
    if (m_xTreeView->get_iter_depth(*xNewEntryIter) == 2) // library
    {
        std::unique_ptr<weld::TreeIter> xLanguageIter
            = m_xTreeView->make_iterator(xNewEntryIter.get());
        m_xTreeView->iter_parent(*xLanguageIter);
        if (m_xTreeView->get_text(*xLanguageIter) == "Basic")
        {
            basctl::ScriptDocument aDocument = GetScriptDocument(xNewEntryIter.get());
            if (!aDocument.isAlive())
                return;

            OUString aLibName = m_xTreeView->get_text(*xNewEntryIter);

            css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
                aDocument.getLibraryContainer(basctl::E_SCRIPTS));
            if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName))
            {
                css::uno::Reference<css::script::XLibraryContainerPassword> xPasswd(
                    xModLibContainer, css::uno::UNO_QUERY);
                if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName))
                {
                    // password protected
                    m_xTreeView->set_image(*xNewEntryIter, RID_CUIBMP_LOCKED);
                }
                else if (xModLibContainer->isLibraryLink(aLibName))
                {
                    // linked
                    m_xTreeView->set_image(*xNewEntryIter, RID_CUIBMP_LINKED);
                }
            }
        }
    }
    if (pRet)
        pRet = xNewEntryIter.get();
}

// fills the scripts list box
// inspired by code in void CommandCategoryListBox::addChildren
// cui/source/customize/CommandCategoryListBox.cxx
// and void CuiConfigGroupListBox::GroupSelected()
// cui/source/customize/cfgutil.cxx
void ScriptContainersListBox::ScriptContainerSelected()
{
    std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
    if (!m_xTreeView->get_selected(xIter.get()))
        return;

    m_pScriptsListBox->freeze();
    m_pScriptsListBox->ClearAll();

    if (!m_xTreeView->iter_has_child(*xIter) && !m_xTreeView->get_children_on_demand(*xIter))
    {
        // maybe the browse node has children and those children are most likely script nodes
        ScriptContainerInfo* pScriptContainerInfo
            = weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*xIter));
        css::uno::Reference<css::script::browse::XBrowseNode> xBrowseNode(
            pScriptContainerInfo->pBrowseNode);
        try
        {
            if (xBrowseNode->hasChildNodes())
            {
                const css::uno::Sequence<css::uno::Reference<css::script::browse::XBrowseNode>>
                    children = xBrowseNode->getChildNodes();

                for (const css::uno::Reference<css::script::browse::XBrowseNode>& childNode :
                     children)
                {
                    if (!childNode.is())
                        continue;

                    if (childNode->getType() == css::script::browse::BrowseNodeTypes::SCRIPT)
                    {
                        css::uno::Reference<css::beans::XPropertySet> xPropSet(childNode,
                                                                               css::uno::UNO_QUERY);
                        if (!xPropSet.is())
                        {
                            continue;
                        }

                        OUString sURI;
                        try
                        {
                            css::uno::Any value = xPropSet->getPropertyValue(u"URI"_ustr);
                            value >>= sURI;
                        }
                        catch (css::uno::Exception&)
                        {
                            // do nothing, the URI will be empty
                        }

                        OUString sDescription;
                        try
                        {
                            css::uno::Any value = xPropSet->getPropertyValue(u"Description"_ustr);
                            value >>= sDescription;
                        }
                        catch (css::uno::Exception&)
                        {
                            // do nothing, the description will be empty
                        }

                        childNode->acquire();

                        m_pScriptsListBox->aArr.push_back(
                            std::make_unique<ScriptInfo>(childNode.get(), sURI, sDescription));

                        OUString sId(weld::toId(m_pScriptsListBox->aArr.back().get()));
                        m_pScriptsListBox->append(sId, childNode->getName(), RID_CUIBMP_MACRO);
                    }
                }
            }
        }
        catch (css::uno::RuntimeException&)
        {
            // do nothing, the entry will not be displayed in the UI
        }
    }

    m_pScriptsListBox->thaw();

    if (m_pScriptsListBox->n_children())
        m_pScriptsListBox->select(0);
}

OUString ScriptContainersListBox::GetContainerName(const weld::TreeIter& rIter,
                                                   const ScriptContainerType eScriptContainerType)
{
    weld::TreeView& rScriptContainersTreeView = *m_xTreeView;
    std::unique_ptr<weld::TreeIter> xSelectedEntryIter
        = rScriptContainersTreeView.make_iterator(&rIter);

    std::unique_ptr<weld::TreeIter> xIter
        = rScriptContainersTreeView.make_iterator(xSelectedEntryIter.get());

    int nEntryDepth;
    while ((nEntryDepth = rScriptContainersTreeView.get_iter_depth(*xIter)))
    {
        if ((nEntryDepth == 3 && eScriptContainerType == ScriptContainerType::MODULEORDIALOG)
            || (nEntryDepth == 2 && eScriptContainerType == ScriptContainerType::LIBRARY)
            || (nEntryDepth == 1 && eScriptContainerType == ScriptContainerType::LANGUAGE))
            return rScriptContainersTreeView.get_text(*xIter);
        rScriptContainersTreeView.iter_parent(*xIter);
    }
    if (eScriptContainerType == ScriptContainerType::LOCATION)
        return rScriptContainersTreeView.get_text(*xIter);

    return OUString();
}

OUString
ScriptContainersListBox::GetSelectedEntryContainerName(ScriptContainerType eScriptContainerType)
{
    std::unique_ptr<weld::TreeIter> xSelectedEntryIter = m_xTreeView->make_iterator();
    if (!m_xTreeView->get_selected(xSelectedEntryIter.get()))
        return OUString(); // should never happen
    return GetContainerName(*xSelectedEntryIter, eScriptContainerType);
}

IMPL_LINK(ScriptContainersListBox, QueryTooltip, const weld::TreeIter&, rEntryIter, OUString)
{
    // for Basic library check for linked library
    if (m_xTreeView->get_iter_depth(rEntryIter) == 2) // library
    {
        // language
        std::unique_ptr<weld::TreeIter> xLanguageIter = m_xTreeView->make_iterator(&rEntryIter);
        m_xTreeView->iter_parent(*xLanguageIter);
        if (m_xTreeView->get_text(*xLanguageIter) == "Basic")
        {
            basctl::ScriptDocument aDocument = GetScriptDocument(&rEntryIter);
            if (!aDocument.isAlive())
                return OUString();

            css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
                aDocument.getLibraryContainer(basctl::E_SCRIPTS));
            // check for linked library
            OUString aLibName = m_xTreeView->get_text(rEntryIter);
            if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)
                && xModLibContainer->isLibraryLink(aLibName))
            {
                OUString aLinkURL = xModLibContainer->getLibraryLinkURL(aLibName);
                osl::File::getSystemPathFromFileURL(aLinkURL, aLinkURL);
                return aLinkURL;
            }
        }
    }
    return OUString();
}

IMPL_LINK(ScriptContainersListBox, ExpandingHdl, const weld::TreeIter&, rEntryIter, bool)
{
    // for Basic library check for password protected
    if (m_xTreeView->get_iter_depth(rEntryIter) == 2) // library
    {
        // language
        std::unique_ptr<weld::TreeIter> xLanguageIter = m_xTreeView->make_iterator(&rEntryIter);
        m_xTreeView->iter_parent(*xLanguageIter);
        if (m_xTreeView->get_text(*xLanguageIter) == "Basic")
        {
            basctl::ScriptDocument aDocument = GetScriptDocument(&rEntryIter);
            if (!aDocument.isAlive())
                return false// not expanded

            OUString aLibName = m_xTreeView->get_text(rEntryIter);

            // check if the library is password protected
            css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
                aDocument.getLibraryContainer(basctl::E_SCRIPTS));
            if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName))
            {
                css::uno::Reference<css::script::XLibraryContainerPassword> xPasswd(
                    xModLibContainer, css::uno::UNO_QUERY);
                if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName)
                    && !xPasswd->isLibraryPasswordVerified(aLibName))
                {
                    // ensure selection before password dialog is shown
                    m_xTreeView->select(rEntryIter);
                    OUString sPassword;
                    if (!basctl::QueryPassword(m_pMacroManagerDialog->getDialog(), xModLibContainer,
                                               aLibName, sPassword, truetrue))
                    {
                        return false// indicates the expansion of the row is refused
                    }
                }
            }
        }
    }

    if (m_xTreeView->get_children_on_demand(rEntryIter))
    {
        Fill(&rEntryIter);
    }

    return true;
}

MacroManagerDialog::MacroManagerDialog(weld::Window* pParent,
                                       const css::uno::Reference<css::frame::XFrame>& xDocFrame)
    : GenericDialogController(pParent, u"cui/ui/macromanagerdialog.ui"_ustr,
                              u"MacroManagerDialog"_ustr)
    , m_xDocumentFrame(xDocFrame)
    , m_xScriptContainersListBox(
          new ScriptContainersListBox(m_xBuilder->weld_tree_view(u"scriptcontainers"_ustr), this))
    , m_xScriptsListBox(new ScriptsListBox(m_xBuilder->weld_tree_view(u"scripts"_ustr)))
    , m_xScriptsListBoxLabel(m_xBuilder->weld_label(u"scriptslistboxlabel"_ustr))
    , m_xRunButton(m_xBuilder->weld_button(u"run"_ustr))
    , m_xCloseButton(m_xBuilder->weld_button(u"close"_ustr))
    , m_xDescriptionText(m_xBuilder->weld_text_view(u"description"_ustr))
    , m_xDescriptionFrame(m_xBuilder->weld_frame(u"descriptionframe"_ustr))
    , m_xNewLibraryButton(m_xBuilder->weld_button(u"newlibrary"_ustr))
    , m_xNewModuleButton(m_xBuilder->weld_button(u"newmodule"_ustr))
    , m_xNewDialogButton(m_xBuilder->weld_button(u"newdialog"_ustr))
    , m_xLibraryModuleDialogEditButton(m_xBuilder->weld_button(u"librarymoduledialogedit"_ustr))
    , m_xLibraryModuleDialogRenameButton(m_xBuilder->weld_button(u"librarymoduledialogrename"_ustr))
    , m_xLibraryModuleDialogDeleteButton(m_xBuilder->weld_button(u"librarymoduledialogdelete"_ustr))
    , m_xLibraryPasswordButton(m_xBuilder->weld_button(u"librarypassword"_ustr))
    , m_xLibraryImportButton(m_xBuilder->weld_button(u"libraryimport"_ustr))
    , m_xLibraryExportButton(m_xBuilder->weld_button(u"libraryexport"_ustr))
    , m_xMacroEditButton(m_xBuilder->weld_button(u"macroedit"_ustr))
    , m_xMacroDeleteButton(m_xBuilder->weld_button(u"macrodelete"_ustr))
    , m_xMacroCreateButton(m_xBuilder->weld_button(u"macrocreate"_ustr))
    , m_xMacroRenameButton(m_xBuilder->weld_button(u"macrorename"_ustr))
    , m_xAssignButton(m_xBuilder->weld_button(u"assign"_ustr))
{
    m_aScriptsListBoxLabelBaseStr = m_xScriptsListBoxLabel->get_label();

    m_xScriptContainersListBox->SetScriptsListBox(m_xScriptsListBox.get());
    m_xScriptContainersListBox->Init(comphelper::getProcessComponentContext(), m_xDocumentFrame);

    m_xScriptContainersListBox->connect_changed(LINK(this, MacroManagerDialog, SelectHdl));

    m_xScriptsListBox->connect_changed(LINK(this, MacroManagerDialog, SelectHdl));
    m_xScriptsListBox->connect_row_activated(
        LINK(this, MacroManagerDialog, FunctionDoubleClickHdl));
    m_xScriptsListBox->connect_popup_menu(LINK(this, MacroManagerDialog, ContextMenuHdl));

    m_xAssignButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xRunButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xCloseButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xNewLibraryButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xNewModuleButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xNewDialogButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xLibraryModuleDialogEditButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xLibraryModuleDialogRenameButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xLibraryModuleDialogDeleteButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xLibraryPasswordButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xLibraryImportButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xLibraryExportButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xMacroCreateButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xMacroEditButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xMacroRenameButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));
    m_xMacroDeleteButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl));

    StartListening(*SfxGetpApp());
}

MacroManagerDialog::~MacroManagerDialog() { EndListening(*SfxGetpApp()); }

void MacroManagerDialog::Notify(SfxBroadcaster&, const SfxHint& rHint)
{
    if (rHint.GetId() == SfxHintId::ScriptDocumentChanged)
    {
        weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget();

        auto get_path = [&rScriptContainersTreeView](const weld::TreeIter* pIter) {
            std::unique_ptr<weld::TreeIter> xIter = rScriptContainersTreeView.make_iterator(pIter);
            OUString sPath = rScriptContainersTreeView.get_text(*xIter);
            while (rScriptContainersTreeView.iter_parent(*xIter))
                sPath = rScriptContainersTreeView.get_text(*xIter) + "|" + sPath;
            return sPath;
        };

        std::unique_ptr<weld::TreeIter> xIter = rScriptContainersTreeView.make_iterator();

        // for use to restore the script container tree scroll position
        int nOldScrollPos = rScriptContainersTreeView.vadjustment_get_value();

        // save the current path of the selection in the script containers list for reselection
        // and the selected entry in the scripts list box
        OUString sScriptContainersListBoxSelectedEntryPath;
        OUString sScriptsListBoxSelectedEntry;
        if (rScriptContainersTreeView.get_selected(xIter.get()))
        {
            sScriptContainersListBoxSelectedEntryPath = get_path(xIter.get());
            sScriptsListBoxSelectedEntry = m_xScriptsListBox->GetSelectedScriptName();
        }

        // create a set containing paths for use to restore the script containers tree expand state
        std::unordered_set<OUString> aExpandedSet;
        if (!rScriptContainersTreeView.get_iter_first(*xIter)) // no entries?
            return;
        do
        {
            if (rScriptContainersTreeView.get_row_expanded(*xIter))
                aExpandedSet.insert(get_path(xIter.get()));
        } while (rScriptContainersTreeView.iter_next(*xIter));

        // fill
        rScriptContainersTreeView.freeze();
        m_xScriptContainersListBox->Fill(nullptr);
        rScriptContainersTreeView.thaw();

        // restore script container tree expand state or at least try
        if (!rScriptContainersTreeView.get_iter_first(*xIter))
        {
            UpdateUI();
            return;
        }
        do
        {
            if (aExpandedSet.erase(get_path(xIter.get())))
                rScriptContainersTreeView.expand_row(*xIter);
        } while (aExpandedSet.size() && rScriptContainersTreeView.iter_next(*xIter));

        // restore the script containers tree scroll position
        rScriptContainersTreeView.vadjustment_set_value(nOldScrollPos);

        // if possible select the saved scripts container list entry
        if (sScriptContainersListBoxSelectedEntryPath.isEmpty())
        {
            UpdateUI();
            return;
        }
        bool bFound = false;
        while (true)
        {
            if (!rScriptContainersTreeView.get_iter_first(*xIter))
            {
                UpdateUI();
                return;
            }
            do
            {
                if (get_path(xIter.get()) == sScriptContainersListBoxSelectedEntryPath)
                {
                    rScriptContainersTreeView.select(*xIter);
                    bFound = true;
                    break;
                }
            } while (rScriptContainersTreeView.iter_next(*xIter));
            if (bFound)
                break;
            // when not found remove the last node from path and try again
            auto i = sScriptContainersListBoxSelectedEntryPath.lastIndexOf('|');
            if (i == -1)
            {
                // didn't find
                UpdateUI();
                return;
            }
            sScriptContainersListBoxSelectedEntryPath
                = sScriptContainersListBoxSelectedEntryPath.copy(0, i);
        }

        // fill the scripts list box and set label
        m_xScriptContainersListBox->ScriptContainerSelected();
        m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr + " "
                                          + rScriptContainersTreeView.get_text(*xIter));

        // reselect the macro in the scripts list box
        if (!sScriptsListBoxSelectedEntry.isEmpty())
        {
            weld::TreeView& rScriptsTreeView = m_xScriptsListBox->get_widget();
            xIter = rScriptsTreeView.make_iterator();
            if (!rScriptsTreeView.get_iter_first(*xIter))
            {
                UpdateUI();
                return;
            }
            bool bIsIterValid = true;
            while (bIsIterValid
                   && rScriptsTreeView.get_text(*xIter) != sScriptsListBoxSelectedEntry)
                bIsIterValid = rScriptsTreeView.iter_next_sibling(*xIter);
            if (bIsIterValid)
            {
                rScriptsTreeView.scroll_to_row(*xIter);
                rScriptsTreeView.select(*xIter);
            }
        }

        UpdateUI();
    }
}

IMPL_LINK(MacroManagerDialog, SelectHdl, weld::TreeView&, rTreeView, void)
{
    if (&rTreeView == &m_xScriptContainersListBox->get_widget())
    {
        m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr);
        m_xScriptsListBox->ClearAll();

        std::unique_ptr<weld::TreeIter> xSelectedEntryIter = rTreeView.make_iterator();
        if (!rTreeView.get_selected(xSelectedEntryIter.get()))
        {
            UpdateUI();
            return;
        }

        auto nSelectedEntryDepth = rTreeView.get_iter_depth(*xSelectedEntryIter);
        bool bBasic = m_xScriptContainersListBox->GetContainerName(*xSelectedEntryIter,
                                                                   ScriptContainerType::LANGUAGE)
                      == u"Basic"_ustr;

        if (nSelectedEntryDepth > 1)
        {
            if (nSelectedEntryDepth > (!bBasic ? 1 : 2))
            {
                ScriptContainerInfo* pScriptContainerInfo
                    = weld::fromId<ScriptContainerInfo*>(rTreeView.get_id(*xSelectedEntryIter));
                // pBrowseNode is nullptr for Basic Dialog entries
                if (pScriptContainerInfo->pBrowseNode)
                {
                    // fill the scripts list box and set the label
                    m_xScriptContainersListBox->ScriptContainerSelected();
                    m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr + " "
                                                      + rTreeView.get_text(*xSelectedEntryIter));
                }
            }
        }
    }
    UpdateUI();
}

// IMPL_LINK_NOARG(SvxScriptSelectorDialog, FunctionDoubleClickHdl, weld::TreeView&,&nbsp;bool)
// cui/source/customize/cfgutil.cxx
IMPL_LINK_NOARG(MacroManagerDialog, FunctionDoubleClickHdl, weld::TreeView&, bool)
{
    if (m_xRunButton->get_sensitive())
        ClickHdl(*m_xRunButton);
    return true;
}

// IMPL_LINK(SvxScriptSelectorDialog, ContextMenuHdl, const CommandEvent&, rCEvt, bool)
// cui/source/customize/cfgutil.cxx
// and
// IMPL_LINK(MacroChooser, ContextMenuHdl, const CommandEvent&, rCEvt, bool)
// basctl/source/basicide/macrodlg.cxx
IMPL_LINK(MacroManagerDialog, ContextMenuHdl, const CommandEvent&, rCEvt, bool)
{
    weld::TreeView& xTreeView = m_xScriptsListBox->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_xScriptContainersListBox->ScriptContainerSelected();
    }
    else if (!sCommand.isEmpty())
    {
        SAL_WARN("cui.dialogs""Unknown context menu action: " << sCommand);
    }

    return true;
}

// same as OUString SvxScriptOrgDialog::getBoolProperty((Reference<beans::XPropertySet> const& xProps, OUString const& propName)
// cui/source/dialogs/scriptdlg.cxx
bool MacroManagerDialog::getBoolProperty(
    css::uno::Reference<css::beans::XPropertySet> const& xProps, OUString const& propName)
{
    bool result = false;
    try
    {
        xProps->getPropertyValue(propName) >>= result;
    }
    catch (css::uno::Exception&)
    {
        return result;
    }
    return result;
}

css::uno::Reference<css::script::browse::XBrowseNode>
MacroManagerDialog::getBrowseNode(const weld::TreeView& rTreeView, const weld::TreeIter& rTreeIter)
{
    if (&rTreeView == m_xScriptContainersListBox->m_xTreeView.get())
    {
        ScriptContainerInfo* pScriptContainerInfo;
        pScriptContainerInfo = weld::fromId<ScriptContainerInfo*>(rTreeView.get_id(rTreeIter));
        if (pScriptContainerInfo)
            return pScriptContainerInfo->pBrowseNode;
    }
    else
    {
        ScriptInfo* pScriptInfo = weld::fromId<ScriptInfo*>(rTreeView.get_id(rTreeIter));
        if (pScriptInfo)
            return pScriptInfo->pBrowseNode;
    }
    return nullptr;
}

void MacroManagerDialog::UpdateUI()
{
    OUString sDescriptionText
        = ScriptsListBox::GetDescriptionText(m_xScriptsListBox->get_selected_id());

    weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget();
    std::unique_ptr<weld::TreeIter> xSelectedIter = rTreeView.make_iterator();
    if (rTreeView.get_selected(xSelectedIter.get())
        && rTreeView.get_iter_depth(*xSelectedIter) == 2) // library
    {
        if (m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LANGUAGE)
            == "Basic")
        {
            basctl::ScriptDocument aDocument
                = m_xScriptContainersListBox->GetScriptDocument(xSelectedIter.get());
            if (aDocument.isAlive())
            {
                // if this is a Basic linked library use the link url name for the description string
                css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
                    aDocument.getLibraryContainer(basctl::E_SCRIPTS));
                OUString aLibName = rTreeView.get_text(*xSelectedIter);
                if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)
                    && xModLibContainer->isLibraryLink(aLibName))
                {
                    OUString aLinkURL = xModLibContainer->getLibraryLinkURL(aLibName);
                    OUString aSysPath;
                    if (osl::File::getSystemPathFromFileURL(aLinkURL, aSysPath)
                        == osl::FileBase::E_None)
                        sDescriptionText = aSysPath;
                    else
                        sDescriptionText = aLinkURL;
                }
            }
        }
    }

    m_xDescriptionText->set_text(sDescriptionText);
    CheckButtons();
}

void MacroManagerDialog::CheckButtons()
{
    bool bSensitiveNewLibraryButton = false;
    bool bSensitiveNewModuleButton = false;
    bool bSensitiveNewDialogButton = false;
    bool bSensitiveLibraryModuleDialogEditButton = false;
    bool bSensitiveLibraryModuleDialogRenameButton = false;
    bool bSensitiveLibraryModuleDialogDeleteButton = false;
    bool bSensitiveLibraryPasswordButton = false;
    bool bSensitiveLibraryImportButton = false;
    bool bSensitiveLibraryExportButton = false;

    bool bSensitiveMacroRunButton = false;
    bool bSensitiveMacroCreateButton = false;
    bool bSensitiveMacroEditButton = false;
    bool bSensitiveMacroRenameButton = false;
    bool bSensitiveMacroDeleteButton = false;

    bool bSensitiveAssignButton = false;

    weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget();
    std::unique_ptr<weld::TreeIter> xScriptContainersSelectedIter
        = rScriptContainersTreeView.make_iterator();
    if (rScriptContainersTreeView.get_selected(xScriptContainersSelectedIter.get()))
    {
        if (auto nSelectedIterDepth
            = rScriptContainersTreeView.get_iter_depth(*xScriptContainersSelectedIter))
        {
            std::unique_ptr<weld::TreeIter> xLocationContainerIter
                = rScriptContainersTreeView.make_iterator(xScriptContainersSelectedIter.get());
            while (rScriptContainersTreeView.get_iter_depth(*xLocationContainerIter))
                rScriptContainersTreeView.iter_parent(*xLocationContainerIter);
            bool bSharedLocationContainer
                = getBrowseNode(rScriptContainersTreeView, *xLocationContainerIter)->getName()
                  == u"share"_ustr;

            bool bBasic = m_xScriptContainersListBox->GetSelectedEntryContainerName(
                              ScriptContainerType::LANGUAGE)
                          == u"Basic"_ustr;

            if (nSelectedIterDepth == 1) // language node
            {
                if (!bSharedLocationContainer)
                {
                    if (bBasic)
                    {
                        bSensitiveNewLibraryButton = true;
                        bSensitiveLibraryImportButton = true;
                    }
                    else
                    {
                        css::uno::Reference<css::script::browse::XBrowseNode> node = getBrowseNode(
                            rScriptContainersTreeView, *xScriptContainersSelectedIter);
                        if (node.is())
                        {
                            css::uno::Reference<css::beans::XPropertySet> xProps(
                                node, css::uno::UNO_QUERY);
                            if (xProps.is())
                            {
                                if (getBoolProperty(xProps, "Creatable"))
                                {
                                    bSensitiveNewLibraryButton = true;
                                }
                            }
                        }
                    }
                }
            }
            else if (bBasic && nSelectedIterDepth == 2) // library node
            {
                basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument();
                if (!aDocument.isAlive())
                    return;

                OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName(
                    ScriptContainerType::LIBRARY);

                css::uno::Reference<css::script::XLibraryContainerPassword> xPasswd(
                    aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);

                if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName)
                    && !xPasswd->isLibraryPasswordVerified(aLibName))
                {
                    bSensitiveLibraryPasswordButton = true;
                }
                else if (bSharedLocationContainer)
                {
                    bSensitiveLibraryModuleDialogEditButton = true;
                }
                else
                {
                    // check, if library is readonly
                    css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
                        aDocument.getLibraryContainer(basctl::E_SCRIPTS));

                    bool bReadOnly = xModLibContainer.is() && xModLibContainer->hasByName(aLibName)
                                     && xModLibContainer->isLibraryReadOnly(aLibName);

                    bSensitiveNewModuleButton = !bReadOnly;
                    bSensitiveNewDialogButton = !bReadOnly;
                    bSensitiveLibraryModuleDialogEditButton = true;
                    if (aLibName != u"Standard"_ustr) // need to use a ResId?
                    {
                        bSensitiveLibraryModuleDialogRenameButton = !bReadOnly;
                        bSensitiveLibraryModuleDialogDeleteButton = true//!bReadOnly;
                        bSensitiveLibraryPasswordButton = !bReadOnly;
                        // why not export for "Standard"?
                        bSensitiveLibraryExportButton = true;
                    }
                }
            }
            else if (bBasic && nSelectedIterDepth == 3) // module/dialog node
            {
                if (bSharedLocationContainer)
                {
                    bSensitiveLibraryModuleDialogEditButton = true;
                }
                else
                {
                    basctl::ScriptDocument aDocument
                        = m_xScriptContainersListBox->GetScriptDocument();
                    assert(aDocument.isAlive());

                    OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName(
                        ScriptContainerType::LIBRARY);

                    css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
                        aDocument.getLibraryContainer(basctl::E_SCRIPTS));
                    css::uno::Reference<css::script::XLibraryContainer2> xDlgLibContainer(
                        aDocument.getLibraryContainer(basctl::E_DIALOGS));

                    bool bReadOnly
                        = (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)
                           && (xModLibContainer->isLibraryReadOnly(aLibName)
                               || xModLibContainer->isLibraryLink(aLibName)))
                          || (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName)
                              && (xDlgLibContainer->isLibraryReadOnly(aLibName)
                                  || xDlgLibContainer->isLibraryLink(aLibName)));

                    bSensitiveLibraryModuleDialogEditButton = true;
                    bSensitiveLibraryModuleDialogRenameButton = !bReadOnly;
                    bSensitiveLibraryModuleDialogDeleteButton = !bReadOnly;
                }
            }

            if (!bSharedLocationContainer && nSelectedIterDepth > 1)
            {
                css::uno::Reference<css::script::browse::XBrowseNode> node
                    = getBrowseNode(rScriptContainersTreeView, *xScriptContainersSelectedIter);
                if (node.is())
                {
                    css::uno::Reference<css::beans::XPropertySet> xProps(node, css::uno::UNO_QUERY);
                    if (xProps.is())
                    {
                        if (getBoolProperty(xProps, "Creatable")
                            && rScriptContainersTreeView.get_iter_depth(
                                   *xScriptContainersSelectedIter)
                                   == 2) // library entry
                        {
                            bSensitiveMacroCreateButton = true;
                        }
                        if (getBoolProperty(xProps, "Editable"))
                        {
                            bSensitiveLibraryModuleDialogEditButton = true;
                        }
                        if (getBoolProperty(xProps, "Deletable"))
                        {
                            bSensitiveLibraryModuleDialogDeleteButton = true;
                        }
                        if (getBoolProperty(xProps, "Renamable"))
                        {
                            bSensitiveLibraryModuleDialogRenameButton = true;
                        }
                    }
                }
            }

            // scripts list box state dependent buttons
            weld::TreeView& rScriptsTreeView = m_xScriptsListBox->get_widget();
            std::unique_ptr<weld::TreeIter> xScriptsSelectedIter = rScriptsTreeView.make_iterator();
            if (rScriptsTreeView.n_children()
                && rScriptsTreeView.get_selected(xScriptsSelectedIter.get()))
            {
                bSensitiveAssignButton = true;

                css::uno::Reference<css::script::browse::XBrowseNode> node;
                node = getBrowseNode(rScriptsTreeView, *xScriptsSelectedIter);
                if (node.is())
                {
                    bSensitiveMacroRunButton = true;

                    css::uno::Reference<css::beans::XPropertySet> xProps(node, css::uno::UNO_QUERY);
                    if (xProps.is())
                    {
                        if (getBoolProperty(xProps, "Editable"))
                        {
                            bSensitiveMacroEditButton = true;
                        }
                        if (!bSharedLocationContainer)
                        {
                            if (getBoolProperty(xProps, "Deletable"))
                            {
                                bSensitiveMacroDeleteButton = true;
                            }
                            if (getBoolProperty(xProps, "Renamable"))
                            {
                                bSensitiveMacroRenameButton = true;
                            }
                        }
                    }
                }
            }
        }
    }

    m_xNewLibraryButton->set_sensitive(bSensitiveNewLibraryButton);
    m_xNewModuleButton->set_sensitive(bSensitiveNewModuleButton);
    m_xNewDialogButton->set_sensitive(bSensitiveNewDialogButton);
    m_xLibraryModuleDialogEditButton->set_sensitive(bSensitiveLibraryModuleDialogEditButton);
    m_xLibraryModuleDialogRenameButton->set_sensitive(bSensitiveLibraryModuleDialogRenameButton);
    m_xLibraryModuleDialogDeleteButton->set_sensitive(bSensitiveLibraryModuleDialogDeleteButton);
    m_xLibraryPasswordButton->set_sensitive(bSensitiveLibraryPasswordButton);
    m_xLibraryImportButton->set_sensitive(bSensitiveLibraryImportButton);
    m_xLibraryExportButton->set_sensitive(bSensitiveLibraryExportButton);
    m_xRunButton->set_sensitive(bSensitiveMacroRunButton);
    m_xMacroCreateButton->set_sensitive(bSensitiveMacroCreateButton);
    m_xMacroEditButton->set_sensitive(bSensitiveMacroEditButton);
    m_xMacroRenameButton->set_sensitive(bSensitiveMacroRenameButton);
    m_xMacroDeleteButton->set_sensitive(bSensitiveMacroDeleteButton);
    m_xAssignButton->set_sensitive(bSensitiveAssignButton);
}

// void createLibImpl(weld::Window* pWin, const ScriptDocument& rDocument,
//                    weld::TreeView* pLibBox, SbTreeListBox* pBasicBox)
// basctl/source/basicide/moduldl2.cxx
void MacroManagerDialog::BasicScriptsCreateLibrary(const basctl::ScriptDocument&&nbsp;rDocument)
{
    // create a unique library name
    OUString aLibName = CuiResId(STR_LIBRARY) + OUString::number(1);
    for (sal_uInt32 i = 1; rDocument.hasLibrary(basctl::E_SCRIPTS, aLibName)
                           || rDocument.hasLibrary(basctl::E_DIALOGS, aLibName);
         aLibName = CuiResId(STR_LIBRARY) + OUString::number(++i))
        ;

    OUString aDesc = CuiResId(STR_INPUTDIALOG_NEWLIBRARYLABEL);

    SvxNameDialog aNameDialog(m_xDialog.get(), aLibName, aDesc,
                              CuiResId(STR_INPUTDIALOG_NEWLIBRARYTITLE));

    aNameDialog.SetCheckName([&](OUString sNewName) -> bool {
        if (sNewName.isEmpty() || rDocument.hasLibrary(basctl::E_SCRIPTS, sNewName)
            || rDocument.hasLibrary(basctl::E_DIALOGS, sNewName) || sNewName.getLength() > 30
            || !basctl::IsValidSbxName(sNewName))
            return false;
        return true;
    });

    if (aNameDialog.run() != RET_OK)
        return;

    aLibName = aNameDialog.GetName();

    try
    {
        // create library container for modules
        rDocument.getOrCreateLibrary(basctl::E_SCRIPTS, aLibName);

        // create a module
        OUString aModName = rDocument.createObjectName(basctl::E_SCRIPTS, aLibName);
        OUString sModuleCode;
        if (!rDocument.createModule(aLibName, aModName, true, sModuleCode))
            throw css::uno::Exception("could not create module " + aModName, nullptr);

        // tdf#151741 - store all libraries to the file system, otherwise they
        // cannot be renamed/moved since the SfxLibraryContainer::renameLibrary
        // moves the folders/files on the file system
        css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer(
            rDocument.getLibraryContainer(basctl::E_SCRIPTS));
        css::uno::Reference<css::script::XPersistentLibraryContainer> xModPersLibContainer(
            xModLibContainer, css::uno::UNO_QUERY);
        if (xModPersLibContainer.is())
            xModPersLibContainer->storeLibraries();

        // update Basic IDE object catalog
        SbxItem aModuleSbxItem(SID_BASICIDE_ARG_SBX, rDocument, aLibName, aModName,
                               basctl::SBX_TYPE_MODULE);
        if (SfxDispatcher* pDispatcher = basctl::GetDispatcher())
            pDispatcher->ExecuteList(SID_BASICIDE_SBXINSERTED, SfxCallMode::SYNCHRON,
                                     { &aModuleSbxItem });
    }
    catch (const css::uno::Exception&)
    {
        DBG_UNHANDLED_EXCEPTION("basctl.basicide");
    }
}

void MacroManagerDialog::BasicScriptsCreateModule(const basctl::ScriptDocument& ;rDocument)
{
    // library name is the selected tree entry
    weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget();
    std::unique_ptr<weld::TreeIter> xSelectedIter = rTreeView.make_iterator();
    if (!rTreeView.get_selected(xSelectedIter.get()))
        return// should never happen

    OUString aLibName = rTreeView.get_text(*xSelectedIter);

    // create an unused module name
    OUString aModName = CuiResId(STR_MODULE) + OUString::number(1);
    for (sal_uInt32 i = 1; rDocument.hasModule(aLibName, aModName);
         aModName = CuiResId(STR_MODULE) + OUString::number(++i))
        ;

    OUString aDesc = CuiResId(STR_INPUTDIALOG_NEWMODULELABEL);

    SvxNameDialog aNameDialog(m_xDialog.get(), aModName, aDesc,
                              CuiResId(STR_INPUTDIALOG_NEWMODULETITLE));

    aNameDialog.SetCheckName([&](OUString sNewName) -> bool {
        if (sNewName.isEmpty() || rDocument.hasModule(aLibName, sNewName)
            || sNewName.getLength() > 30 || !basctl::IsValidSbxName(sNewName))
            return false;
        return true;
    });

    if (!aNameDialog.run())
        return;

    aModName = aNameDialog.GetName();

    OUString sModuleCode;
    if (!rDocument.createModule(aLibName, aModName, true /*create main sub*/, sModuleCode))
        return;

    // update Basic IDE object catalog
    SbxItem aSbxItem(SID_BASICIDE_ARG_SBX, rDocument, aLibName, aModName, basctl::SBX_TYPE_MODULE);
    if (SfxDispatcher* pDispatcher = basctl::GetDispatcher())
    {
        pDispatcher->ExecuteList(SID_BASICIDE_SBXINSERTED, SfxCallMode::SYNCHRON, { &aSbxItem });
    }
}

void MacroManagerDialog::BasicScriptsCreateDialog(const basctl::ScriptDocument& ;rDocument)
{
    // library name is the selected tree entry
    weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget();
    std::unique_ptr<weld::TreeIter> xSelectedIter = rTreeView.make_iterator();
    if (!rTreeView.get_selected(xSelectedIter.get()))
        return// should never happen

    OUString aLibName = rTreeView.get_text(*xSelectedIter);

    // create an unused dialog name
    OUString sDialogName = CuiResId(STR_DIALOG) + OUString::number(1);
    for (sal_uInt32 i = 1; rDocument.hasDialog(aLibName, sDialogName);
         sDialogName = CuiResId(STR_DIALOG) + OUString::number(++i))
        ;

    OUString aDesc = CuiResId(STR_INPUTDIALOG_NEWDIALOGLABEL);

    SvxNameDialog aNameDialog(m_xDialog.get(), sDialogName, aDesc,
                              CuiResId(STR_INPUTDIALOG_NEWDIALOGTITLE));

    aNameDialog.SetCheckName([&](OUString sNewName) -> bool {
        if (sNewName.isEmpty() || rDocument.hasDialog(aLibName, sNewName)
            || sNewName.getLength() > 30 || !basctl::IsValidSbxName(sNewName))
            return false;
        return true;
    });

    if (!aNameDialog.run())
        return;

    sDialogName = aNameDialog.GetName();

    try
    {
        rDocument.getOrCreateLibrary(basctl::E_DIALOGS, aLibName);

        css::uno::Reference<css::io::XInputStreamProvider> xISP;
        if (!rDocument.createDialog(aLibName, sDialogName, xISP))
            return;

        // update Basic IDE object catalog
        SbxItem aSbxItem(SID_BASICIDE_ARG_SBX, rDocument, aLibName, sDialogName,
                         basctl::SBX_TYPE_DIALOG);
        if (SfxDispatcher* pDispatcher = basctl::GetDispatcher())
        {
            pDispatcher->ExecuteList(SID_BASICIDE_SBXINSERTED, SfxCallMode::SYNCHRON,
                                     { &aSbxItem });
        }
    }
    catch (const css::container::ElementExistException&)
    {
        std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(
            m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok,
            CuiResId(STR_SBXNAMEALLREADYUSED)));
        xError->run();
    }
    catch (const css::container::NoSuchElementException&)
    {
        DBG_UNHANDLED_EXCEPTION("basctl.basicide");
    }
}

void MacroManagerDialog::BasicScriptsLibraryModuleDialogEdit(
    const basctl::ScriptDocument& rDocument)
{
    weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget();
    std::unique_ptr<weld::TreeIter> xSelectedIter = rTreeView.make_iterator();
    if (!rTreeView.get_selected(xSelectedIter.get()))
        return// should never happen

    m_xDialog->hide();

    // show the Basic IDE
    SfxAllItemSet aArgs(SfxGetpApp()->GetPool());
    SfxRequest aRequest(SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs);
    SfxGetpApp()->ExecuteSlot(aRequest);

    if (rTreeView.get_iter_depth(*xSelectedIter) == 2) // library
    {
        SfxUnoAnyItem aDocItem(SID_BASICIDE_ARG_DOCUMENT_MODEL,
                               css::uno::Any(rDocument.getDocumentOrNull()));
        SfxStringItem aLibNameItem(SID_BASICIDE_ARG_LIBNAME,
                                   m_xScriptContainersListBox->GetSelectedEntryContainerName(
                                       ScriptContainerType::LIBRARY));
        if (SfxDispatcher* pDispatcher = basctl::GetDispatcher())
            pDispatcher->ExecuteList(SID_BASICIDE_LIBSELECTED, SfxCallMode::ASYNCHRON,
                                     { &aDocItem, &aLibNameItem });
    }
    else // module/dialog
    {
        ScriptContainerInfo* pScriptContainerInfo
            = weld::fromId<ScriptContainerInfo*>(rTreeView.get_id(*xSelectedIter));
        // pScriptContainerInfo->pBrowseNode is nullptr for Dialog entries
        SbxItem aSbxItem(
            SID_BASICIDE_ARG_SBX, rDocument,
            m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LIBRARY),
            m_xScriptContainersListBox->GetSelectedEntryContainerName(
                ScriptContainerType::MODULEORDIALOG),
            pScriptContainerInfo->pBrowseNode ? basctl::SBX_TYPE_MODULE : basctl::SBX_TYPE_DIALOG);
        if (SfxDispatcher* pDispatcher = basctl::GetDispatcher())
            pDispatcher->ExecuteList(SID_BASICIDE_SHOWSBX, SfxCallMode::ASYNCHRON, { &aSbxItem });
    }

    // close the MacroManagerDialog
    m_xDialog->response(0);
}

IMPL_LINK(MacroManagerDialog, CheckPasswordHdl, SvxPasswordDialog*, pDlg, bool)
{
    basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument();
    if (!aDocument.isAlive())
        return false;

    bool bRet = false;

    css::uno::Reference<css::script::XLibraryContainerPassword> xPasswd(
        aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY);

    if (xPasswd.is())
    {
        try
        {
            OUString aOldPassword(pDlg->GetOldPassword());
            OUString aNewPassword(pDlg->GetNewPassword());
            OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName(
                ScriptContainerType::LIBRARY);
            xPasswd->changeLibraryPassword(aLibName, aOldPassword, aNewPassword);
            bRet = true;
        }
        catch (...)
        {
        }
    }

    return bRet;
}

basctl::ScriptDocument ScriptContainersListBox::GetScriptDocument(const weld::TreeIter* pIter)
{
    std::unique_ptr<weld::TreeIter> xIter = m_xTreeView->make_iterator(pIter);
    if (pIter == nullptr)
    {
        if (!m_xTreeView->get_selected(xIter.get()))
            return basctl::ScriptDocument::getApplicationScriptDocument();
    }

    while (m_xTreeView->get_iter_depth(*xIter))
        m_xTreeView->iter_parent(*xIter);

    ScriptContainerInfo* pScriptContainerInfo
        = weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*xIter));
    if (pScriptContainerInfo && pScriptContainerInfo->pBrowseNode)
    {
        css::uno::Reference<css::script::browse::XBrowseNode> aRootNode;
        aRootNode = pScriptContainerInfo->pBrowseNode;
        if (aRootNode->getName() == u"user"_ustr || aRootNode->getName() == u"share"_ustr)
            return basctl::ScriptDocument::getApplicationScriptDocument();
        return basctl::ScriptDocument::getDocumentWithURLOrCaption(aRootNode->getName());
    }

    return basctl::ScriptDocument::getApplicationScriptDocument();
}

IMPL_LINK(MacroManagerDialog, ClickHdl, weld::Button&, rButton, void)
{
    if (&rButton == m_xCloseButton.get())
    {
        m_xDialog->response(RET_CANCEL);
        return;
    }
    if (&rButton == m_xRunButton.get())
    {
        SaveLastUsedMacro();
        m_xDialog->response(RET_OK);
        return;
    }

    if (m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LANGUAGE)
        == "Basic")
    {
        basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument();
        if (!aDocument.isAlive())
            return;

        if (&rButton == m_xNewLibraryButton.get())
        {
            BasicScriptsCreateLibrary(aDocument);
        }
        else if (&rButton == m_xNewModuleButton.get())
        {
            BasicScriptsCreateModule(aDocument);
        }
        else if (&rButton == m_xNewDialogButton.get())
        {
            BasicScriptsCreateDialog(aDocument);
        }
        else if (&rButton == m_xLibraryModuleDialogEditButton.get())
        {
            BasicScriptsLibraryModuleDialogEdit(aDocument);
        }
        else if (&rButton == m_xLibraryModuleDialogRenameButton.get())
        {
            BasicScriptsLibraryModuleDialogRename(aDocument);
        }
        else if (&rButton == m_xLibraryModuleDialogDeleteButton.get())
        {
            BasicScriptsLibraryModuleDialogDelete(aDocument);
        }
        else if (&rButton == m_xLibraryPasswordButton.get())
        {
            BasicScriptsLibraryPassword(aDocument);
        }
        else if (&rButton == m_xLibraryImportButton.get())
        {
            auto insert_entries = [this]() {
                weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget();
                std::unique_ptr<weld::TreeIter> xSelectedIter = rTreeView.make_iterator();
                if (!rTreeView.get_selected(xSelectedIter.get()))
                    return// should never happen
                m_xScriptContainersListBox->Fill(xSelectedIter.get());
                rTreeView.expand_row(*xSelectedIter);
                rTreeView.select(*xSelectedIter);
            };
            basctl::ImportLib(aDocument, m_xDialog.get(), {}, {}, insert_entries);
        }
        else if (&rButton == m_xLibraryExportButton.get())
        {
            basctl::Export(aDocument,
                           m_xScriptContainersListBox->GetSelectedEntryContainerName(
                               ScriptContainerType::LIBRARY),
                           m_xDialog.get());
        }
        else if (&rButton == m_xMacroEditButton.get())
        {
            BasicScriptsMacroEdit(aDocument);
        }
        else if (&rButton == m_xMacroDeleteButton.get())
        {
            // todo
            // see: void MacroChooser::DeleteMacro()
            return;
        }
        else if (&rButton == m_xAssignButton.get())
        {
            SfxAllItemSet Args(SfxGetpApp()->GetPool());
            SfxAllItemSet aInternalSet(SfxGetpApp()->GetPool());
            if (m_xDocumentFrame.is())
                aInternalSet.Put(SfxUnoFrameItem(SID_FILLFRAME, m_xDocumentFrame));
            SfxRequest aRequest(SID_CONFIGACCEL, SfxCallMode::SYNCHRON, Args, aInternalSet);

            SfxMacroInfoItem aMacroInfoItem(
                SID_MACROINFO, aDocument.getBasicManager(),
                m_xScriptContainersListBox->GetSelectedEntryContainerName(
                    ScriptContainerType::LIBRARY),
                m_xScriptContainersListBox->GetSelectedEntryContainerName(
                    ScriptContainerType::MODULEORDIALOG),
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=93 H=89 G=90

¤ Dauer der Verarbeitung: 0.29 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.