Files
libreoffice/cui/source/dialogs/scriptdlg.cxx
Noel Grandin 51fa45c8b8 loplugin:constmethod in cui
Change-Id: I06ffacbb02f3e9088e9c1a51e0e3e0d65d356f62
Reviewed-on: https://gerrit.libreoffice.org/78602
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2019-09-05 08:27:12 +02:00

1358 lines
42 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 <utility>
#include <sal/log.hxx>
#include <sfx2/objsh.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>
#include <uno/current_context.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/DisableInteractionHelper.hxx>
#include <comphelper/documentinfo.hxx>
#include <comphelper/processfactory.hxx>
#include <svtools/imagemgr.hxx>
#include <tools/urlobj.hxx>
#include <tools/diagnose_ex.h>
using namespace ::com::sun::star;
using namespace css::uno;
using namespace css::script;
using namespace css::frame;
using namespace css::document;
static void ShowErrorDialog( const Any& aException )
{
ScopedVclPtrInstance<SvxScriptErrorDialog> pDlg( aException );
pDlg->Execute();
}
void SvxScriptOrgDialog::delUserData(const weld::TreeIter& rIter)
{
SFEntry* pUserData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rIter).toInt64());
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(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( const OUString& language )
{
m_xScriptsBox->freeze();
deleteAllTree();
Reference< browse::XBrowseNode > rootNode;
Reference< XComponentContext > xCtx(
comphelper::getProcessComponentContext() );
Sequence< Reference< browse::XBrowseNode > > children;
OUString userStr("user");
OUString const shareStr("share");
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 ( sal_Int32 n = 0; n < children.getLength(); n++ )
{
bool app = false;
OUString uiName = children[ n ]->getName();
OUString factoryURL;
if ( uiName == userStr || uiName == shareStr )
{
app = true;
if ( uiName == userStr )
{
uiName = m_sMyMacros;
}
else
{
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&)
{}
beans::PropertyValue const * pmoduleDescr =
moduleDescr.getConstArray();
for ( sal_Int32 pos = moduleDescr.getLength(); pos--; )
{
if ( pmoduleDescr[ pos ].Name == "ooSetupFactoryEmptyDocumentURL" )
{
pmoduleDescr[ pos ].Value >>= factoryURL;
break;
}
}
}
}
Reference< browse::XBrowseNode > langEntries =
getLangNodeFromRootNode( children[ n ], language );
insertEntry( uiName, app ? OUStringLiteral(RID_CUIBMP_HARDDISK) : OUStringLiteral(RID_CUIBMP_DOC),
nullptr, true, std::make_unique< SFEntry >( langEntries, xDocumentModel ), factoryURL, false );
}
m_xScriptsBox->thaw();
}
Reference< XInterface >
SvxScriptOrgDialog::getDocumentModel( Reference< XComponentContext > const & xCtx, OUString const & 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, OUString const & 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(
new comphelper::NoEnableJavaInteractionContext(css::uno::getCurrentContext()));
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 ( sal_Int32 n = 0; n < children.getLength(); n++ )
{
OUString name( children[ n ]->getName() );
if ( children[ n ]->getType() != browse::BrowseNodeTypes::SCRIPT)
{
insertEntry(name, RID_CUIBMP_LIB, &rRootEntry, true, std::make_unique<SFEntry>(children[n], model), false);
}
else
{
insertEntry(name, RID_CUIBMP_MACRO, &rRootEntry, false, std::make_unique<SFEntry>(children[n], model), false);
}
}
}
void SvxScriptOrgDialog::insertEntry(const OUString& rText, const OUString& rBitmap,
const weld::TreeIter* pParent, bool bChildrenOnDemand, std::unique_ptr<SFEntry> && aUserData,
const OUString& factoryURL, bool bSelect)
{
if (rBitmap == RID_CUIBMP_DOC && !factoryURL.isEmpty())
{
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)
{
std::unique_ptr<weld::TreeIter> xRetIter;
if (bSelect)
xRetIter = m_xScriptsBox->make_iterator();
OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aUserData.release()))); // XXX possible leak
m_xScriptsBox->insert(pParent, -1, &rText, &sId, nullptr, nullptr, &rBitmap,
bChildrenOnDemand, xRetIter.get());
if (bSelect)
{
m_xScriptsBox->set_cursor(*xRetIter);
m_xScriptsBox->select(*xRetIter);
}
}
IMPL_LINK(SvxScriptOrgDialog, ExpandingHdl, const weld::TreeIter&, rIter, bool)
{
SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rIter).toInt64());
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, "cui/ui/newlibdialog.ui", "NewLibDialog")
, m_xEdit(m_xBuilder->weld_entry("entry"))
{
m_xEdit->grab_focus();
std::unique_ptr<weld::Label> xNewLibFT(m_xBuilder->weld_label("newlibft"));
if ( nMode == InputDialogMode::NEWMACRO )
{
xNewLibFT->hide();
std::unique_ptr<weld::Label> xNewMacroFT(m_xBuilder->weld_label("newmacroft"));
xNewMacroFT->show();
std::unique_ptr<weld::Label> xAltTitle(m_xBuilder->weld_label("altmacrotitle"));
m_xDialog->set_title(xAltTitle->get_label());
}
else if ( nMode == InputDialogMode::RENAME )
{
xNewLibFT->hide();
std::unique_ptr<weld::Label> xRenameFT(m_xBuilder->weld_label("renameft"));
xRenameFT->show();
std::unique_ptr<weld::Label> xAltTitle(m_xBuilder->weld_label("altrenametitle"));
m_xDialog->set_title(xAltTitle->get_label());
}
}
// ScriptOrgDialog ------------------------------------------------------------
SvxScriptOrgDialog::SvxScriptOrgDialog(weld::Window* pParent, const OUString& language)
: SfxDialogController(pParent, "cui/ui/scriptorganizer.ui", "ScriptOrganizerDialog")
, m_sLanguage(language)
, m_delErrStr(CuiResId(RID_SVXSTR_DELFAILED))
, m_delErrTitleStr(CuiResId(RID_SVXSTR_DELFAILED_TITLE))
, m_delQueryStr(CuiResId(RID_SVXSTR_DELQUERY))
, m_delQueryTitleStr(CuiResId(RID_SVXSTR_DELQUERY_TITLE))
, m_createErrStr(CuiResId(RID_SVXSTR_CREATEFAILED))
, m_createDupStr(CuiResId(RID_SVXSTR_CREATEFAILEDDUP))
, m_createErrTitleStr(CuiResId(RID_SVXSTR_CREATEFAILED_TITLE))
, m_renameErrStr(CuiResId(RID_SVXSTR_RENAMEFAILED))
, m_renameErrTitleStr(CuiResId(RID_SVXSTR_RENAMEFAILED_TITLE))
, m_sMyMacros(CuiResId(RID_SVXSTR_MYMACROS))
, m_sProdMacros(CuiResId(RID_SVXSTR_PRODMACROS))
, m_xScriptsBox(m_xBuilder->weld_tree_view("scripts"))
, m_xRunButton(m_xBuilder->weld_button("ok"))
, m_xCloseButton(m_xBuilder->weld_button("close"))
, m_xCreateButton(m_xBuilder->weld_button("create"))
, m_xEditButton(m_xBuilder->weld_button("edit"))
, m_xRenameButton(m_xBuilder->weld_button("rename"))
, m_xDelButton(m_xBuilder->weld_button("delete"))
{
// 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("Editable");
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 = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(*xIter).toInt64());
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())
{
std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
if (!m_xScriptsBox->get_selected(xIter.get()))
return;
SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(*xIter).toInt64());
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 = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(*xParentIter).toInt64());
mspNode.set( mspUserData->GetNode() , UNO_QUERY );
bParent = m_xScriptsBox->iter_parent(*xParentIter);
}
xProp->getPropertyValue("URI") >>= 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 )
{
ShowErrorDialog(css::uno::Any(ite));
}
catch ( provider::ScriptFrameworkErrorException& ite )
{
ShowErrorDialog(css::uno::Any(ite));
}
catch ( RuntimeException& re )
{
ShowErrorDialog(css::uno::Any(re));
}
catch ( Exception& e )
{
ShowErrorDialog(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( "Editable", 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 = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rEntry).toInt64());
if (userData)
{
node = userData->GetNode();
}
return node;
}
Reference< XModel > SvxScriptOrgDialog::getModel(const weld::TreeIter& rEntry)
{
Reference< XModel > model;
SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rEntry).toInt64());
if ( userData )
{
model = userData->GetModel();
}
return model;
}
void SvxScriptOrgDialog::createEntry(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( sal_Int32 index = 0; index < childNodes.getLength(); index++ )
{
if (aNewName+extn == childNodes[index]->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( sal_Int32 index = 0; index < childNodes.getLength(); index++ )
{
if (aUserSuppliedName+extn == childNodes[index]->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( 1 );
args[ 0 ] <<= aNewName;
Sequence< Any > outArgs( 0 );
Sequence< sal_Int16 > outIndex;
try
{
Any aResult = xInv->invoke( "Creatable", args, outIndex, outArgs );
Reference< browse::XBrowseNode > newNode( aResult, UNO_QUERY );
aChildNode = newNode;
}
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
// SvTreeListBox::InsertEntry can take position arg
// -- 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 = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rEntry).toInt64());
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( 1 );
args[ 0 ] <<= aNewName;
Sequence< Any > outArgs( 0 );
Sequence< sal_Int16 > outIndex;
try
{
Any aResult = xInv->invoke( "Renamable", args, outIndex, outArgs );
Reference< browse::XBrowseNode > newNode( aResult, UNO_QUERY );
aChildNode = newNode;
}
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(weld::TreeIter& rEntry)
{
bool result = false;
Reference< browse::XBrowseNode > node = getBrowseNode(rEntry);
// ISSUE L10N string & can we centre 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( "Deletable", 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() )
{
Sequence< Reference< browse::XBrowseNode > > children
= node->getChildNodes();
for ( sal_Int32 n = 0; n < children.getLength(); n++ )
{
result.append( getListOfChildren( children[ 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);
OUString sDesc( aDescription );
m_lastSelection[ m_sLanguage ] = sDesc;
}
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)
{
OUString aTmp( aStoredEntry.getToken( 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);
}
namespace {
OUString ReplaceString(
const OUString& source,
const OUString& token,
const OUString& value )
{
sal_Int32 pos = source.indexOf( token );
if ( pos != -1 && !value.isEmpty() )
{
return source.replaceAt( pos, token.getLength(), value );
}
else
{
return source;
}
}
OUString FormatErrorString(
const OUString& unformatted,
const OUString& language,
const OUString& script,
const OUString& line,
const OUString& type,
const OUString& message )
{
OUString result = unformatted.copy( 0 );
result = ReplaceString(result, "%LANGUAGENAME", language );
result = ReplaceString(result, "%SCRIPTNAME", script );
result = ReplaceString(result, "%LINENUMBER", line );
if ( !type.isEmpty() )
{
result += "\n\n" + CuiResId(RID_SVXSTR_ERROR_TYPE_LABEL) + " " + type;
}
if ( !message.isEmpty() )
{
result += "\n\n" + CuiResId(RID_SVXSTR_ERROR_MESSAGE_LABEL) + " " + message;
}
return result;
}
OUString GetErrorMessage(
const provider::ScriptErrorRaisedException& eScriptError )
{
OUString unformatted = CuiResId( RID_SVXSTR_ERROR_AT_LINE );
OUString unknown("UNKNOWN");
OUString language = unknown;
OUString script = unknown;
OUString line = unknown;
OUString type = "";
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_SVXSTR_ERROR_AT_LINE );
}
else
{
unformatted = CuiResId( RID_SVXSTR_ERROR_RUNNING );
}
return FormatErrorString(
unformatted, language, script, line, type, message );
}
OUString GetErrorMessage(
const provider::ScriptExceptionRaisedException& eScriptException )
{
OUString unformatted = CuiResId( RID_SVXSTR_EXCEPTION_AT_LINE );
OUString unknown("UNKNOWN");
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_SVXSTR_EXCEPTION_AT_LINE );
}
else
{
unformatted = CuiResId( RID_SVXSTR_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_SVXSTR_FRAMEWORK_ERROR_RUNNING );
OUString language("UNKNOWN");
OUString script("UNKNOWN");
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_SVXSTR_ERROR_LANG_NOT_SUPPORTED );
message = ReplaceString(message, "%LANGUAGENAME", language );
}
else
{
message = sError.Message;
}
return FormatErrorString(
unformatted, language, script, OUString(), OUString(), 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;
}
}
SvxScriptErrorDialog::SvxScriptErrorDialog( css::uno::Any const & aException )
: m_sMessage()
{
SolarMutexGuard aGuard;
m_sMessage = GetErrorMessage( aException );
}
SvxScriptErrorDialog::~SvxScriptErrorDialog()
{
}
short SvxScriptErrorDialog::Execute()
{
// Show Error dialog asynchronously
// Pass a copy of the message to the ShowDialog method as the
// SvxScriptErrorDialog may be deleted before ShowDialog is called
Application::PostUserEvent(
LINK( this, SvxScriptErrorDialog, ShowDialog ),
new OUString( m_sMessage ) );
return 0;
}
IMPL_STATIC_LINK( SvxScriptErrorDialog, ShowDialog, void*, p, void )
{
OUString* pMessage = static_cast<OUString*>(p);
OUString message;
if ( pMessage && !pMessage->isEmpty() )
{
message = *pMessage;
}
else
{
message = CuiResId( RID_SVXSTR_ERROR_TITLE );
}
std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
VclMessageType::Warning, VclButtonsType::Ok, message));
xBox->set_title(CuiResId(RID_SVXSTR_ERROR_TITLE));
xBox->run();
delete pMessage;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */