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 41 kB image not shown  

Quelle  scriptdlg.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 <memory>
#include <string_view>
#include <utility>

#include <sfx2/objsh.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>

#include <strings.hrc>
#include <bitmaps.hlst>
#include <scriptdlg.hxx>
#include <dialmgr.hxx>

#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/script/provider/ScriptFrameworkErrorException.hpp>
#include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
#include <com/sun/star/script/provider/XScriptProvider.hpp>
#include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
#include <com/sun/star/script/browse/XBrowseNodeFactory.hpp>
#include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
#include <com/sun/star/script/browse/theBrowseNodeFactory.hpp>
#include <com/sun/star/script/provider/ScriptErrorRaisedException.hpp>
#include <com/sun/star/script/provider/ScriptExceptionRaisedException.hpp>
#include <com/sun/star/script/provider/ScriptFrameworkErrorType.hpp>
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/frame/ModuleManager.hpp>
#include <com/sun/star/script/XInvocation.hpp>
#include <com/sun/star/document/XEmbeddedScripts.hpp>

#include <comphelper/lok.hxx>
#include <comphelper/SetFlagContextHelper.hxx>
#include <comphelper/documentinfo.hxx>
#include <comphelper/processfactory.hxx>
#include <o3tl/string_view.hxx>

#include <svtools/imagemgr.hxx>
#include <tools/urlobj.hxx>
#include <comphelper/diagnose_ex.hxx>

using namespace ::com::sun::star;
using namespace css::uno;
using namespace css::script;
using namespace css::frame;
using namespace css::document;

void SvxScriptOrgDialog::delUserData(const weld::TreeIter& rIter)
{
    SFEntry* pUserData = weld::fromId<SFEntry*>(m_xScriptsBox->get_id(rIter));
    if (pUserData)
    {
        delete pUserData;
        // TBD seem to get a Select event on node that is remove ( below )
        // so need to be able to detect that this node is not to be
        // processed in order to do this, setting userData to NULL ( must
        // be a better way to do this )
        m_xScriptsBox->set_id(rIter, OUString());
    }
}

void SvxScriptOrgDialog::deleteTree(const weld::TreeIter& rIter)
{
    delUserData(rIter);
    std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator(&rIter);
    if (!m_xScriptsBox->iter_children(*xIter))
        return;

    std::unique_ptr<weld::TreeIter> xAltIter = m_xScriptsBox->make_iterator();
    bool bNextEntry;
    do
    {
        m_xScriptsBox->copy_iterator(*xIter, *xAltIter);
        bNextEntry = m_xScriptsBox->iter_next_sibling(*xAltIter);
        deleteTree(*xIter);
        m_xScriptsBox->remove(*xIter);
        m_xScriptsBox->copy_iterator(*xAltIter, *xIter);
    }
    while (bNextEntry);
}

void SvxScriptOrgDialog::deleteAllTree()
{
    std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
    if (!m_xScriptsBox->get_iter_first(*xIter))
        return;

    std::unique_ptr<weld::TreeIter> xAltIter = m_xScriptsBox->make_iterator();
    // TBD - below is a candidate for a destroyAllTrees method
    bool bNextEntry;
    do
    {
        m_xScriptsBox->copy_iterator(*xIter, *xAltIter);
        bNextEntry = m_xScriptsBox->iter_next_sibling(*xAltIter);
        deleteTree(*xIter);
        m_xScriptsBox->remove(*xIter);
        m_xScriptsBox->copy_iterator(*xAltIter, *xIter);
    }
    while (bNextEntry);
}

void SvxScriptOrgDialog::Init( std::u16string_view language  )
{
    m_xScriptsBox->freeze();

    deleteAllTree();

    Reference< browse::XBrowseNode > rootNode;
    const Reference< XComponentContext >& xCtx(
        comphelper::getProcessComponentContext() );

    Sequence< Reference< browse::XBrowseNode > > children;

    try
    {
        Reference< browse::XBrowseNodeFactory > xFac = browse::theBrowseNodeFactory::get(xCtx);

        rootNode.set( xFac->createView(
            browse::BrowseNodeFactoryViewTypes::MACROORGANIZER ) );

        if (  rootNode.is() && rootNode->hasChildNodes() )
        {
            children = rootNode->getChildNodes();
        }
    }
    catchconst Exception& )
    {
        TOOLS_WARN_EXCEPTION("cui.dialogs""Exception getting root browse node from factory");
        // TODO exception handling
    }

    Reference<XModel> xDocumentModel;
    for (const Reference<browse::XBrowseNode>& childNode : children)
    {
        bool app = false;
        OUString uiName = childNode->getName();
        OUString factoryURL;
        if (uiName == "user")
        {
            app = true;
            uiName = m_sMyMacros;
        }
        else if (uiName == "share")
        {
            app = true;
            uiName = m_sProdMacros;
        }
        else
        {
            xDocumentModel.set(getDocumentModel(xCtx, uiName ), UNO_QUERY);

            if ( xDocumentModel.is() )
            {
                Reference< frame::XModuleManager2 > xModuleManager( frame::ModuleManager::create(xCtx) );

                // get the long name of the document:
                Sequence<beans::PropertyValue> moduleDescr;
                try{
                    OUString appModule = xModuleManager->identify( xDocumentModel );
                    xModuleManager->getByName(appModule) >>= moduleDescr;
                } catch(const uno::Exception&)
                    {}

                for (const beans::PropertyValue& prop : moduleDescr)
                {
                    if ( prop.Name == "ooSetupFactoryEmptyDocumentURL" )
                    {
                        prop.Value >>= factoryURL;
                        break;
                    }
                }
            }
        }

        Reference< browse::XBrowseNode > langEntries =
            getLangNodeFromRootNode( childNode, language );

        insertEntry( uiName, app ? RID_CUIBMP_HARDDISK : RID_CUIBMP_DOC,
            nullptr, true, std::make_unique< SFEntry >( langEntries, xDocumentModel ), factoryURL, false );
    }

    m_xScriptsBox->thaw();
}

Reference< XInterface  >
SvxScriptOrgDialog::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;
}

Reference< browse::XBrowseNode >
SvxScriptOrgDialog::getLangNodeFromRootNode( Reference< browse::XBrowseNode > const &&nbsp;rootNode, std::u16string_view language )
{
    Reference< browse::XBrowseNode > langNode;

    try
    {
        auto tryFind = [&] {
            const Sequence<Reference<browse::XBrowseNode>> children = rootNode->getChildNodes();
            const auto it = std::find_if(children.begin(), children.end(),
                                         [&](const Reference<browse::XBrowseNode>& child) {
                                             return child->getName() == language;
                                         });
            return (it != children.end()) ? *it : nullptr;
        };
        {
            // First try without Java interaction, to avoid warnings for non-JRE-dependent providers
            css::uno::ContextLayer layer(comphelper::NoEnableJavaInteractionContext());
            langNode = tryFind();
        }
        if (!langNode)
        {
            // Now try with Java interaction enabled
            langNode = tryFind();
        }
    }
    catch ( Exception& )
    {
        // if getChildNodes() throws an exception we just return
        // the empty Reference
    }
    return langNode;
}

void SvxScriptOrgDialog::RequestSubEntries(const weld::TreeIter& rRootEntry, Reference< css::script::browse::XBrowseNode > const & node,
                                           Reference< XModel >& model)
{
    if (!node.is())
    {
        return;
    }

    Sequence< Reference< browse::XBrowseNode > > children;
    try
    {
        children = node->getChildNodes();
    }
    catch ( Exception& )
    {
        // if we catch an exception in getChildNodes then no entries are added
    }

    for (const Reference<browse::XBrowseNode>& childNode : children)
    {
        OUString name( childNode->getName() );
        if (  childNode->getType() !=  browse::BrowseNodeTypes::SCRIPT)
        {
            insertEntry(name, RID_CUIBMP_LIB, &rRootEntry, true, std::make_unique<SFEntry>(childNode, model), false);
        }
        else
        {
            insertEntry(name, RID_CUIBMP_MACRO, &rRootEntry, false, std::make_unique<SFEntry>(childNode, model), false);
        }
    }
}

void SvxScriptOrgDialog::insertEntry(const OUString& rText, const OUString& rBitmap,
    const weld::TreeIter* pParent, bool bChildrenOnDemand, std::unique_ptr<SFEntry> && aUserData,
    std::u16string_view factoryURL, bool bSelect)
{
    if (rBitmap == RID_CUIBMP_DOC && !factoryURL.empty())
    {
        OUString aImage = SvFileInformationManager::GetFileImageId(INetURLObject(factoryURL));
        insertEntry(rText, aImage, pParent, bChildrenOnDemand, std::move(aUserData), bSelect);
        return;
    }
    insertEntry(rText, rBitmap, pParent, bChildrenOnDemand, std::move(aUserData), bSelect);
}

void SvxScriptOrgDialog::insertEntry(
    const OUString& rText, const OUString& rBitmap, const weld::TreeIter* pParent,
    bool bChildrenOnDemand, std::unique_ptr<SFEntry> && aUserData, bool bSelect)
{
    OUString sId(weld::toId(aUserData.release())); // XXX possible leak
    m_xScriptsBox->insert(pParent, -1, &rText, &sId, nullptr, nullptr,
                          bChildrenOnDemand, m_xScratchIter.get());
    m_xScriptsBox->set_image(*m_xScratchIter, rBitmap);
    if (bSelect)
    {
        m_xScriptsBox->set_cursor(*m_xScratchIter);
        m_xScriptsBox->select(*m_xScratchIter);
    }
}

IMPL_LINK(SvxScriptOrgDialog, ExpandingHdl, const weld::TreeIter&, rIter, bool)
{
    SFEntry* userData = weld::fromId<SFEntry*>(m_xScriptsBox->get_id(rIter));

    Reference< browse::XBrowseNode > node;
    Reference< XModel > model;
    if ( userData && !userData->isLoaded() )
    {
        node = userData->GetNode();
        model = userData->GetModel();
        RequestSubEntries(rIter, node, model);
        userData->setLoaded();
    }

    return true;
}

// CuiInputDialog ------------------------------------------------------------
CuiInputDialog::CuiInputDialog(weld::Window * pParent, InputDialogMode nMode)
    : GenericDialogController(pParent, u"cui/ui/newlibdialog.ui"_ustr, u"NewLibDialog"_ustr)
    , m_xEdit(m_xBuilder->weld_entry(u"entry"_ustr))
{
    m_xEdit->grab_focus();

    std::unique_ptr<weld::Label> xNewLibFT(m_xBuilder->weld_label(u"newlibft"_ustr));

    if ( nMode == InputDialogMode::NEWMACRO )
    {
        xNewLibFT->hide();
        std::unique_ptr<weld::Label> xNewMacroFT(m_xBuilder->weld_label(u"newmacroft"_ustr));
        xNewMacroFT->show();
        std::unique_ptr<weld::Label> xAltTitle(m_xBuilder->weld_label(u"altmacrotitle"_ustr));
        m_xDialog->set_title(xAltTitle->get_label());
    }
    else if ( nMode == InputDialogMode::RENAME )
    {
        xNewLibFT->hide();
        std::unique_ptr<weld::Label> xRenameFT(m_xBuilder->weld_label(u"renameft"_ustr));
        xRenameFT->show();
        std::unique_ptr<weld::Label> xAltTitle(m_xBuilder->weld_label(u"altrenametitle"_ustr));
        m_xDialog->set_title(xAltTitle->get_label());
    }
}

// ScriptOrgDialog ------------------------------------------------------------

SvxScriptOrgDialog::SvxScriptOrgDialog(weld::Window* pParent, OUString language)
    : SfxDialogController(pParent, u"cui/ui/scriptorganizer.ui"_ustr, u"ScriptOrganizerDialog"_ustr)
    , m_pParent(pParent)
    , m_sLanguage(std::move(language))
    , m_delErrStr(CuiResId(RID_CUISTR_DELFAILED))
    , m_delErrTitleStr(CuiResId(RID_CUISTR_DELFAILED_TITLE))
    , m_delQueryStr(CuiResId(RID_CUISTR_DELQUERY))
    , m_delQueryTitleStr(CuiResId(RID_CUISTR_DELQUERY_TITLE))
    , m_createErrStr(CuiResId(RID_CUISTR_CREATEFAILED))
    , m_createDupStr(CuiResId(RID_CUISTR_CREATEFAILEDDUP))
    , m_createErrTitleStr(CuiResId(RID_CUISTR_CREATEFAILED_TITLE))
    , m_renameErrStr(CuiResId(RID_CUISTR_RENAMEFAILED))
    , m_renameErrTitleStr(CuiResId(RID_CUISTR_RENAMEFAILED_TITLE))
    , m_sMyMacros(CuiResId(RID_CUISTR_MYMACROS))
    , m_sProdMacros(CuiResId(RID_CUISTR_PRODMACROS))
    , m_xScriptsBox(m_xBuilder->weld_tree_view(u"scripts"_ustr))
    , m_xScratchIter(m_xScriptsBox->make_iterator())
    , m_xRunButton(m_xBuilder->weld_button(u"ok"_ustr))
    , m_xCloseButton(m_xBuilder->weld_button(u"close"_ustr))
    , m_xCreateButton(m_xBuilder->weld_button(u"create"_ustr))
    , m_xEditButton(m_xBuilder->weld_button(u"edit"_ustr))
    , m_xRenameButton(m_xBuilder->weld_button(u"rename"_ustr))
    , m_xDelButton(m_xBuilder->weld_button(u"delete"_ustr))
{
    // must be a neater way to deal with the strings than as above
    // append the language to the dialog title
    OUString winTitle(m_xDialog->get_title());
    winTitle = winTitle.replaceFirst( "%MACROLANG", m_sLanguage );
    m_xDialog->set_title(winTitle);

    m_xScriptsBox->set_size_request(m_xScriptsBox->get_approximate_digit_width() * 45,
                                    m_xScriptsBox->get_height_rows(12));

    m_xScriptsBox->connect_selection_changed(LINK(this, SvxScriptOrgDialog, ScriptSelectHdl));
    m_xScriptsBox->connect_expanding(LINK( this, SvxScriptOrgDialog, ExpandingHdl ) );
    m_xRunButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
    m_xCloseButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
    m_xRenameButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
    m_xEditButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
    m_xDelButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
    m_xCreateButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );

    m_xRunButton->set_sensitive(false);
    m_xRenameButton->set_sensitive(false);
    m_xEditButton->set_sensitive(false);
    m_xDelButton->set_sensitive(false);
    m_xCreateButton->set_sensitive(false);

    Init(m_sLanguage);
    RestorePreviousSelection();
}

SvxScriptOrgDialog::~SvxScriptOrgDialog()
{
    deleteAllTree();
}

short SvxScriptOrgDialog::run()
{
    SfxObjectShell *pDoc = SfxObjectShell::GetFirst();

    // force load of MSPs for all documents
    while ( pDoc )
    {
        Reference< provider::XScriptProviderSupplier > xSPS( pDoc->GetModel(), UNO_QUERY );
        if ( xSPS.is() )
        {
            xSPS->getScriptProvider();
        }

        pDoc = SfxObjectShell::GetNext(*pDoc);
    }

    return SfxDialogController::run();
}

void SvxScriptOrgDialog::CheckButtons( Reference< browse::XBrowseNode > const & node )
{
    if ( node.is() )
    {
        if ( node->getType() == browse::BrowseNodeTypes::SCRIPT)
        {
            m_xRunButton->set_sensitive(true);
        }
        else
        {
            m_xRunButton->set_sensitive(false);
        }
        Reference< beans::XPropertySet > xProps( node, UNO_QUERY );

        if ( !xProps.is() )
        {
            m_xEditButton->set_sensitive(false);
            m_xDelButton->set_sensitive(false);
            m_xCreateButton->set_sensitive(false);
            m_xRunButton->set_sensitive(false);
            return;
        }

        OUString sName(u"Editable"_ustr);

        if ( getBoolProperty( xProps, sName ) )
        {
            m_xEditButton->set_sensitive(true);
        }
        else
        {
            m_xEditButton->set_sensitive(false);
        }

        sName = "Deletable";

        if ( getBoolProperty( xProps, sName ) )
        {
            m_xDelButton->set_sensitive(true);
        }
        else
        {
            m_xDelButton->set_sensitive(false);
        }

        sName = "Creatable";

        if ( getBoolProperty( xProps, sName ) )
        {
            m_xCreateButton->set_sensitive(true);
        }
        else
        {
            m_xCreateButton->set_sensitive(false);
        }

        sName = "Renamable";

        if ( getBoolProperty( xProps, sName ) )
        {
            m_xRenameButton->set_sensitive(true);
        }
        else
        {
            m_xRenameButton->set_sensitive(false);
        }
    }
    else
    {
        // no node info available, disable all configurable actions
        m_xDelButton->set_sensitive(false);
        m_xCreateButton->set_sensitive(false);
        m_xEditButton->set_sensitive(false);
        m_xRunButton->set_sensitive(false);
        m_xRenameButton->set_sensitive(false);
    }
}

IMPL_LINK_NOARG(SvxScriptOrgDialog, ScriptSelectHdl, weld::TreeView&, void)
{
    std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
    if (!m_xScriptsBox->get_selected(xIter.get()))
        return;

    SFEntry* userData = weld::fromId<SFEntry*>(m_xScriptsBox->get_id(*xIter));

    Reference< browse::XBrowseNode > node;
    if (userData)
    {
        node = userData->GetNode();
        CheckButtons(node);
    }
}

IMPL_LINK(SvxScriptOrgDialog, ButtonHdl, weld::Button&, rButton, void)
{
    if ( &rButton == m_xCloseButton.get() )
    {
        StoreCurrentSelection();
        m_xDialog->response(RET_CANCEL);
    }
    if (!(&rButton == m_xEditButton.get() ||
        &rButton == m_xCreateButton.get() ||
        &rButton == m_xDelButton.get() ||
        &rButton == m_xRunButton.get() ||
        &rButton == m_xRenameButton.get()))

        return;

    std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
    if (!m_xScriptsBox->get_selected(xIter.get()))
        return;
    SFEntry* userData = weld::fromId<SFEntry*>(m_xScriptsBox->get_id(*xIter));
    if (!userData)
        return;

    Reference< browse::XBrowseNode > node;
    Reference< XModel > xModel;

    node = userData->GetNode();
    xModel = userData->GetModel();

    if ( !node.is() )
    {
        return;
    }

    if (&rButton == m_xRunButton.get())
    {
        OUString tmpString;
        Reference< beans::XPropertySet > xProp( node, UNO_QUERY );
        Reference< provider::XScriptProvider > mspNode;
        if( !xProp.is() )
        {
            return;
        }

        if ( xModel.is() )
        {
            Reference< XEmbeddedScripts >  xEmbeddedScripts( xModel, UNO_QUERY);
            if( !xEmbeddedScripts.is() )
            {
                return;
            }

            if (!xEmbeddedScripts->getAllowMacroExecution())
            {
                // Please FIXME: Show a message box if AllowMacroExecution is false
                return;
            }
        }

        std::unique_ptr<weld::TreeIter> xParentIter = m_xScriptsBox->make_iterator(xIter.get());
        bool bParent = m_xScriptsBox->iter_parent(*xParentIter);
        while (bParent && !mspNode.is() )
        {
            SFEntry* mspUserData = weld::fromId<SFEntry*>(m_xScriptsBox->get_id(*xParentIter));
            mspNode.set( mspUserData->GetNode() , UNO_QUERY );
            bParent = m_xScriptsBox->iter_parent(*xParentIter);
        }
        xProp->getPropertyValue(u"URI"_ustr) >>= tmpString;
        const OUString scriptURL( tmpString );

        if ( mspNode.is() )
        {
            try
            {
                Reference< provider::XScript > xScript(
                    mspNode->getScript( scriptURL ), UNO_SET_THROW );

                const Sequence< Any > args(0);
                Sequence< sal_Int16 > outIndex;
                Sequence< Any > outArgs( 0 );
                xScript->invoke( args, outIndex, outArgs );
            }
            catch ( reflection::InvocationTargetException& ite )
            {
                SvxScriptErrorDialog::ShowAsyncErrorDialog(m_pParent, css::uno::Any(ite));
            }
            catch ( provider::ScriptFrameworkErrorException& ite )
            {
                SvxScriptErrorDialog::ShowAsyncErrorDialog(m_pParent, css::uno::Any(ite));
            }
            catch ( RuntimeException& re )
            {
                SvxScriptErrorDialog::ShowAsyncErrorDialog(m_pParent, css::uno::Any(re));
            }
            catch ( Exception& e )
            {
                SvxScriptErrorDialog::ShowAsyncErrorDialog(m_pParent, css::uno::Any(e));
            }
        }
        StoreCurrentSelection();
        m_xDialog->response(RET_CANCEL);
    }
    else if ( &rButton == m_xEditButton.get() )
    {
        Reference< script::XInvocation > xInv( node, UNO_QUERY );
        if ( xInv.is() )
        {
            StoreCurrentSelection();
            m_xDialog->response(RET_CANCEL);
            Sequence< Any > args(0);
            Sequence< Any > outArgs( 0 );
            Sequence< sal_Int16 > outIndex;
            try
            {
                // ISSUE need code to run script here
                xInv->invoke( u"Editable"_ustr, args, outIndex, outArgs );
            }
            catch( Exception const & )
            {
                TOOLS_WARN_EXCEPTION("cui.dialogs""Caught exception trying to invoke" );
            }
        }
    }
    else if ( &rButton == m_xCreateButton.get() )
    {
        createEntry(*xIter);
    }
    else if ( &rButton == m_xDelButton.get() )
    {
        deleteEntry(*xIter);
    }
    else if ( &rButton == m_xRenameButton.get() )
    {
        renameEntry(*xIter);
    }
}

Reference< browse::XBrowseNode > SvxScriptOrgDialog::getBrowseNode(const weld::TreeIter& rEntry)
{
    Reference< browse::XBrowseNode > node;
    SFEntry* userData = weld::fromId<SFEntry*>(m_xScriptsBox->get_id(rEntry));
    if (userData)
    {
        node = userData->GetNode();
    }
    return node;
}

Reference< XModel > SvxScriptOrgDialog::getModel(const weld::TreeIter& rEntry)
{
    Reference< XModel > model;
    SFEntry* userData = weld::fromId<SFEntry*>(m_xScriptsBox->get_id(rEntry));
    if ( userData )
    {
        model = userData->GetModel();
    }
    return model;
}

void SvxScriptOrgDialog::createEntry(const weld::TreeIter& rEntry)
{

    Reference< browse::XBrowseNode >  aChildNode;
    Reference< browse::XBrowseNode > node = getBrowseNode( rEntry );
    Reference< script::XInvocation > xInv( node, UNO_QUERY );

    if ( xInv.is() )
    {
        OUString aNewName;
        OUString aNewStdName;
        InputDialogMode nMode = InputDialogMode::NEWLIB;
        if (m_xScriptsBox->get_iter_depth(rEntry) == 0)
        {
            aNewStdName = "Library" ;
        }
        else
        {
            aNewStdName = "Macro" ;
            nMode = InputDialogMode::NEWMACRO;
        }
        //do we need L10N for this? ie something like:
        //String aNewStdName( ResId( STR_STDMODULENAME ) );
        bool bValid = false;
        sal_Int32 i = 1;

        Sequence< Reference< browse::XBrowseNode > > childNodes;
        // no children => ok to create Parcel1 or Script1 without checking
        try
        {
            if( !node->hasChildNodes() )
            {
                aNewName = aNewStdName + OUString::number(i);
                bValid = true;
            }
            else
            {
                childNodes = node->getChildNodes();
            }
        }
        catch ( Exception& )
        {
            // ignore, will continue on with empty sequence
        }

        OUString extn;
        while ( !bValid )
        {
            aNewName = aNewStdName + OUString::number(i);
            bool bFound = false;
            if(childNodes.hasElements() )
            {
                OUString nodeName = childNodes[0]->getName();
                sal_Int32 extnPos = nodeName.lastIndexOf( '.' );
                if(extnPos>0)
                    extn = nodeName.copy(extnPos);
            }
            for (const Reference<browse::XBrowseNode>& n : childNodes)
            {
                if (Concat2View(aNewName+extn) == n->getName())
                {
                    bFound = true;
                    break;
                }
            }
            if( bFound )
            {
                i++;
            }
            else
            {
                bValid = true;
            }
        }

        CuiInputDialog aNewDlg(m_xDialog.get(), nMode);
        aNewDlg.SetObjectName(aNewName);

        do
        {
            if (aNewDlg.run() && !aNewDlg.GetObjectName().isEmpty())
            {
                OUString aUserSuppliedName = aNewDlg.GetObjectName();
                bValid = true;
                for (const Reference<browse::XBrowseNode>& n : childNodes)
                {
                    if (Concat2View(aUserSuppliedName+extn) == n->getName())
                    {
                        bValid = false;
                        OUString aError = m_createErrStr + m_createDupStr;

                        std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
                                                                       VclMessageType::Warning, VclButtonsType::Ok, aError));
                        xErrorBox->set_title(m_createErrTitleStr);
                        xErrorBox->run();
                        aNewDlg.SetObjectName(aNewName);
                        break;
                    }
                }
                if( bValid )
                    aNewName = aUserSuppliedName;
            }
            else
            {
                // user hit cancel or hit OK with nothing in the editbox

                return;
            }
        }
        while ( !bValid );

        // open up parent node (which ensures it's loaded)
        m_xScriptsBox->expand_row(rEntry);

        Sequence< Any > args{ Any(aNewName) };
        Sequence< Any > outArgs;
        Sequence< sal_Int16 > outIndex;
        try
        {
            Any aResult = xInv->invoke( u"Creatable"_ustr, args, outIndex, outArgs );
            aChildNode.set(aResult, UNO_QUERY);

        }
        catch( Exception const & )
        {
            TOOLS_WARN_EXCEPTION("cui.dialogs""Caught exception trying to Create" );
        }
    }
    if ( aChildNode.is() )
    {
        OUString aChildName = aChildNode->getName();

        Reference<XModel> xDocumentModel = getModel( rEntry );

        // ISSUE do we need to remove all entries for parent
        // to achieve sort? Just need to determine position
        // -- Basic doesn't do this on create.
        // Suppose we could avoid this too. -> created nodes are
        // not in alphabetical order
        if ( aChildNode->getType() == browse::BrowseNodeTypes::SCRIPT )
        {
            insertEntry(aChildName, RID_CUIBMP_MACRO, &rEntry, false,
                        std::make_unique<SFEntry>(aChildNode,xDocumentModel), true);
        }
        else
        {
            insertEntry(aChildName, RID_CUIBMP_LIB, &rEntry, false,
                        std::make_unique<SFEntry>(aChildNode,xDocumentModel), true);

            // If the Parent is not loaded then set to
            // loaded, this will prevent RequestingChildren ( called
            // from vcl via RequestingChildren ) from
            // creating new ( duplicate ) children
            SFEntry* userData = weld::fromId<SFEntry*>(m_xScriptsBox->get_id(rEntry));
            if ( userData &&  !userData->isLoaded() )
            {
                userData->setLoaded();
            }
        }
    }
    else
    {
        //ISSUE L10N & message from exception?
        OUString aError( m_createErrStr );
        std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
                                                       VclMessageType::Warning, VclButtonsType::Ok, aError));
        xErrorBox->set_title(m_createErrTitleStr);
        xErrorBox->run();
    }
}

void SvxScriptOrgDialog::renameEntry(const weld::TreeIter& rEntry)
{

    Reference< browse::XBrowseNode >  aChildNode;
    Reference< browse::XBrowseNode > node = getBrowseNode(rEntry);
    Reference< script::XInvocation > xInv( node, UNO_QUERY );

    if ( xInv.is() )
    {
        OUString aNewName = node->getName();
        sal_Int32 extnPos = aNewName.lastIndexOf( '.' );
        if(extnPos>0)
        {
            aNewName = aNewName.copy(0,extnPos);
        }
        CuiInputDialog aNewDlg(m_xDialog.get(), InputDialogMode::RENAME);
        aNewDlg.SetObjectName(aNewName);

        if (!aNewDlg.run() || aNewDlg.GetObjectName().isEmpty())
            return// user hit cancel or hit OK with nothing in the editbox

        aNewName = aNewDlg.GetObjectName();

        Sequence< Any > args{ Any(aNewName) };
        Sequence< Any > outArgs;
        Sequence< sal_Int16 > outIndex;
        try
        {
            Any aResult = xInv->invoke( u"Renamable"_ustr, args, outIndex, outArgs );
            aChildNode.set(aResult, UNO_QUERY);

        }
        catch( Exception const & )
        {
            TOOLS_WARN_EXCEPTION("cui.dialogs""Caught exception trying to Rename" );
        }
    }
    if ( aChildNode.is() )
    {
        m_xScriptsBox->set_text(rEntry, aChildNode->getName());
        m_xScriptsBox->set_cursor(rEntry);
        m_xScriptsBox->select(rEntry);

    }
    else
    {
        //ISSUE L10N & message from exception?
        OUString aError( m_renameErrStr );
        std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
                                                       VclMessageType::Warning, VclButtonsType::Ok, aError));
        xErrorBox->set_title(m_renameErrTitleStr);
        xErrorBox->run();
    }
}

void SvxScriptOrgDialog::deleteEntry(const weld::TreeIter& rEntry)
{
    bool result = false;
    Reference< browse::XBrowseNode > node = getBrowseNode(rEntry);
    // ISSUE L10N string & can we center list?
    OUString aQuery = m_delQueryStr + getListOfChildren( node, 0 );
    std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_xDialog.get(),
                                                   VclMessageType::Question, VclButtonsType::YesNo, aQuery));
    xQueryBox->set_title(m_delQueryTitleStr);
    if (xQueryBox->run() == RET_NO)
    {
        return;
    }

    Reference< script::XInvocation > xInv( node, UNO_QUERY );
    if ( xInv.is() )
    {
        Sequence< Any > args( 0 );
        Sequence< Any > outArgs( 0 );
        Sequence< sal_Int16 > outIndex;
        try
        {
            Any aResult = xInv->invoke( u"Deletable"_ustr, args, outIndex, outArgs );
            aResult >>= result; // or do we just assume true if no exception ?
        }
        catch( Exception const & )
        {
            TOOLS_WARN_EXCEPTION("cui.dialogs""Caught exception trying to delete" );
        }
    }

    if ( result )
    {
        deleteTree(rEntry);
        m_xScriptsBox->remove(rEntry);
    }
    else
    {
        //ISSUE L10N & message from exception?
        std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
                                                       VclMessageType::Warning, VclButtonsType::Ok, m_delErrStr));
        xErrorBox->set_title(m_delErrTitleStr);
        xErrorBox->run();
    }

}

bool SvxScriptOrgDialog::getBoolProperty( Reference< beans::XPropertySet > const & xProps,
                OUString const & propName )
{
    bool result = false;
    try
    {
        xProps->getPropertyValue( propName ) >>= result;
    }
    catch ( Exception& )
    {
        return result;
    }
    return result;
}

OUString SvxScriptOrgDialog::getListOfChildren( const Reference< browse::XBrowseNode >&&nbsp;node, int depth )
{
    OUStringBuffer result = "\n";
    forint i=0;i<=depth;i++ )
    {
        result.append("\t");
    }
    result.append(node->getName());

    try
    {
        if ( node->hasChildNodes() )
        {
            const Sequence< Reference< browse::XBrowseNode > > children
                = node->getChildNodes();
            forconst Reference< browse::XBrowseNode >& n : children )
            {
                result.append( getListOfChildren( n , depth+1 ) );
            }
        }
    }
    catch ( Exception& )
    {
        // ignore, will return an empty string
    }

    return result.makeStringAndClear();
}

Selection_hash SvxScriptOrgDialog::m_lastSelection;

void SvxScriptOrgDialog::StoreCurrentSelection()
{
    std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
    if (!m_xScriptsBox->get_selected(xIter.get()))
        return;
    OUString aDescription;
    bool bEntry;
    do
    {
        aDescription = m_xScriptsBox->get_text(*xIter) + aDescription;
        bEntry = m_xScriptsBox->iter_parent(*xIter);
        if (bEntry)
            aDescription = ";" + aDescription;
    }
    while (bEntry);
    m_lastSelection[m_sLanguage] = aDescription;
}

void SvxScriptOrgDialog::RestorePreviousSelection()
{
    OUString aStoredEntry = m_lastSelection[ m_sLanguage ];
    if( aStoredEntry.isEmpty() )
        return;
    std::unique_ptr<weld::TreeIter> xEntry;
    std::unique_ptr<weld::TreeIter> xTmpEntry(m_xScriptsBox->make_iterator());
    sal_Int32 nIndex = 0;
    while (nIndex != -1)
    {
        std::u16string_view aTmp( o3tl::getToken(aStoredEntry, 0, ';', nIndex ) );

        bool bTmpEntry;
        if (!xEntry)
        {
            xEntry = m_xScriptsBox->make_iterator();
            bTmpEntry = m_xScriptsBox->get_iter_first(*xEntry);
            m_xScriptsBox->copy_iterator(*xEntry, *xTmpEntry);
        }
        else
        {
            m_xScriptsBox->copy_iterator(*xEntry, *xTmpEntry);
            bTmpEntry = m_xScriptsBox->iter_children(*xTmpEntry);
        }

        while (bTmpEntry)
        {
            if (m_xScriptsBox->get_text(*xTmpEntry) == aTmp)
            {
                m_xScriptsBox->copy_iterator(*xTmpEntry, *xEntry);
                break;
            }
            bTmpEntry = m_xScriptsBox->iter_next_sibling(*xTmpEntry);
        }

        if (!bTmpEntry)
            break;

        m_xScriptsBox->expand_row(*xEntry);
    }

    if (xEntry)
    {
        m_xScriptsBox->set_cursor(*xEntry);
        ScriptSelectHdl(*m_xScriptsBox);
    }
}

namespace {

OUString ReplaceString(
    const OUString& source,
    std::u16string_view token,
    std::u16string_view value )
{
    sal_Int32 pos = source.indexOf( token );

    if ( pos != -1 && !value.empty() )
    {
        return source.replaceAt( pos, token.size(), value );
    }
    else
    {
        return source;
    }
}

OUString FormatErrorString(
    const OUString& unformatted,
    std::u16string_view language,
    std::u16string_view script,
    std::u16string_view line,
    std::u16string_view type,
    std::u16string_view message )
{
    OUString result = unformatted;

    result = ReplaceString(result, u"%LANGUAGENAME", language );
    result = ReplaceString(result, u"%SCRIPTNAME", script );
    result = ReplaceString(result, u"%LINENUMBER", line );

    if ( !type.empty() )
    {
        result += "\n\n" + CuiResId(RID_CUISTR_ERROR_TYPE_LABEL) + " " + type;
    }

    if ( !message.empty() )
    {
        result += "\n\n" + CuiResId(RID_CUISTR_ERROR_MESSAGE_LABEL) + " " + message;
    }

    return result;
}

OUString GetErrorMessage(
    const provider::ScriptErrorRaisedException& eScriptError )
{
    OUString unformatted = CuiResId( RID_CUISTR_ERROR_AT_LINE );

    OUString unknown(u"UNKNOWN"_ustr);
    OUString language = unknown;
    OUString script = unknown;
    OUString line = unknown;
    OUString message = eScriptError.Message;

    if ( !eScriptError.language.isEmpty() )
    {
        language = eScriptError.language;
    }

    if ( !eScriptError.scriptName.isEmpty() )
    {
        script = eScriptError.scriptName;
    }

    if ( !eScriptError.Message.isEmpty() )
    {
        message = eScriptError.Message;
    }
    if ( eScriptError.lineNum != -1 )
    {
        line = OUString::number( eScriptError.lineNum );
        unformatted = CuiResId( RID_CUISTR_ERROR_AT_LINE );
    }
    else
    {
        unformatted = CuiResId( RID_CUISTR_ERROR_RUNNING );
    }

    return FormatErrorString(
        unformatted, language, script, line, u"", message );
}

OUString GetErrorMessage(
    const provider::ScriptExceptionRaisedException& eScriptException )
{
    OUString unformatted = CuiResId( RID_CUISTR_EXCEPTION_AT_LINE );

    OUString unknown(u"UNKNOWN"_ustr);
    OUString language = unknown;
    OUString script = unknown;
    OUString line = unknown;
    OUString type = unknown;
    OUString message = eScriptException.Message;

    if ( !eScriptException.language.isEmpty() )
    {
        language = eScriptException.language;
    }
    if ( !eScriptException.scriptName.isEmpty() )
    {
        script = eScriptException.scriptName;
    }

    if ( !eScriptException.Message.isEmpty() )
    {
        message = eScriptException.Message;
    }

    if ( eScriptException.lineNum != -1 )
    {
        line = OUString::number( eScriptException.lineNum );
        unformatted = CuiResId( RID_CUISTR_EXCEPTION_AT_LINE );
    }
    else
    {
        unformatted = CuiResId( RID_CUISTR_EXCEPTION_RUNNING );
    }

    if ( !eScriptException.exceptionType.isEmpty() )
    {
        type = eScriptException.exceptionType;
    }

    return FormatErrorString(
        unformatted, language, script, line, type, message );

}
OUString GetErrorMessage(
    const provider::ScriptFrameworkErrorException& sError )
{
    OUString unformatted = CuiResId( RID_CUISTR_FRAMEWORK_ERROR_RUNNING );

    OUString language(u"UNKNOWN"_ustr);

    OUString script(u"UNKNOWN"_ustr);

    OUString message;

    if ( !sError.scriptName.isEmpty() )
    {
        script = sError.scriptName;
    }
    if ( !sError.language.isEmpty() )
    {
        language = sError.language;
    }
    if ( sError.errorType == provider::ScriptFrameworkErrorType::NOTSUPPORTED )
    {
        message = CuiResId(RID_CUISTR_ERROR_LANG_NOT_SUPPORTED);
        message = ReplaceString(message, u"%LANGUAGENAME", language );

    }
    else
    {
        message = sError.Message;
    }
    return FormatErrorString(
        unformatted, language, script, u"", std::u16string_view(), message );
}

OUString GetErrorMessage( const css::uno::Any& aException )
{
    if ( aException.getValueType() ==
         cppu::UnoType<reflection::InvocationTargetException>::get())
    {
        reflection::InvocationTargetException ite;
        aException >>= ite;
        if ( ite.TargetException.getValueType() == cppu::UnoType<provider::ScriptErrorRaisedException>::get())
        {
            // Error raised by script
            provider::ScriptErrorRaisedException scriptError;
            ite.TargetException >>= scriptError;
            return GetErrorMessage( scriptError );
        }
        else if ( ite.TargetException.getValueType() == cppu::UnoType<provider::ScriptExceptionRaisedException>::get())
        {
            // Exception raised by script
            provider::ScriptExceptionRaisedException scriptException;
            ite.TargetException >>= scriptException;
            return GetErrorMessage( scriptException );
        }
        else
        {
            // Unknown error, shouldn't happen
            // OSL_ASSERT(...)
        }

    }
    else if ( aException.getValueType() == cppu::UnoType<provider::ScriptFrameworkErrorException>::get())
    {
        // A Script Framework error has occurred
        provider::ScriptFrameworkErrorException sfe;
        aException >>= sfe;
        return GetErrorMessage( sfe );

    }
    // unknown exception
    auto msg = aException.getValueTypeName();
    Exception e;
    if ( (aException >>= e) && !e.Message.isEmpty() )
    {
        msg += ": " + e.Message;
    }
    return msg;
}

}

// Show Error dialog asynchronously
void SvxScriptErrorDialog::ShowAsyncErrorDialog( weld::Window* pParent, css::uno::Anconst & aException )
{
    SolarMutexGuard aGuard;

    // Pass a copy of the message to the ShowDialog method as the
    // SvxScriptErrorDialog may be deleted before ShowDialog is called
    DialogData* pData = new DialogData;
    pData->sMessage = GetErrorMessage(aException);
    pData->pParent = pParent;
    Application::PostUserEvent(
        LINK( nullptr, SvxScriptErrorDialog, ShowDialog ),
        pData );
}

IMPL_STATIC_LINK( SvxScriptErrorDialog, ShowDialog, void*, p, void )
{
    std::unique_ptr<DialogData> xData(static_cast<DialogData*>(p));
    OUString message = xData->sMessage;

    if ( message.isEmpty() )
        message = CuiResId( RID_CUISTR_ERROR_TITLE );

    std::shared_ptr<weld::MessageDialog> xBox;
    xBox.reset(Application::CreateMessageDialog(
            xData->pParent,
            VclMessageType::Warning,
            VclButtonsType::Ok,
            message));

    xBox->set_title(CuiResId(RID_CUISTR_ERROR_TITLE));

    xBox->runAsync(xBox, [](sal_Int32 /*nResult*/) {});
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

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

¤ Dauer der Verarbeitung: 0.14 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.