1328 lines
41 KiB
C++
1328 lines
41 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <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();
|
|
}
|
|
}
|
|
catch( const 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 & 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_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 >& node, int depth )
|
|
{
|
|
OUStringBuffer result = "\n";
|
|
for( int i=0;i<=depth;i++ )
|
|
{
|
|
result.append("\t");
|
|
}
|
|
result.append(node->getName());
|
|
|
|
try
|
|
{
|
|
if ( node->hasChildNodes() )
|
|
{
|
|
const Sequence< Reference< browse::XBrowseNode > > children
|
|
= node->getChildNodes();
|
|
for( const 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::Any const & 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: */
|