/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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(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 xIter = m_xScriptsBox->make_iterator(&rIter); if (!m_xScriptsBox->iter_children(*xIter)) return; std::unique_ptr 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 xIter = m_xScriptsBox->make_iterator(); if (!m_xScriptsBox->get_iter_first(*xIter)) return; std::unique_ptr 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; 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 xDocumentModel; for ( const Reference< browse::XBrowseNode >& childNode : std::as_const(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 moduleDescr; try{ OUString appModule = xModuleManager->identify( xDocumentModel ); xModuleManager->getByName(appModule) >>= moduleDescr; } catch(const uno::Exception&) {} for ( const beans::PropertyValue& prop : std::as_const(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> children = rootNode->getChildNodes(); const auto it = std::find_if(children.begin(), children.end(), [&](const Reference& 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 : std::as_const(children) ) { OUString name( childNode->getName() ); if ( childNode->getType() != browse::BrowseNodeTypes::SCRIPT) { insertEntry(name, RID_CUIBMP_LIB, &rRootEntry, true, std::make_unique(childNode, model), false); } else { insertEntry(name, RID_CUIBMP_MACRO, &rRootEntry, false, std::make_unique(childNode, model), false); } } } void SvxScriptOrgDialog::insertEntry(const OUString& rText, const OUString& rBitmap, const weld::TreeIter* pParent, bool bChildrenOnDemand, std::unique_ptr && 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 && 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(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, "cui/ui/newlibdialog.ui", "NewLibDialog") , m_xEdit(m_xBuilder->weld_entry("entry")) { m_xEdit->grab_focus(); std::unique_ptr xNewLibFT(m_xBuilder->weld_label("newlibft")); if ( nMode == InputDialogMode::NEWMACRO ) { xNewLibFT->hide(); std::unique_ptr xNewMacroFT(m_xBuilder->weld_label("newmacroft")); xNewMacroFT->show(); std::unique_ptr xAltTitle(m_xBuilder->weld_label("altmacrotitle")); m_xDialog->set_title(xAltTitle->get_label()); } else if ( nMode == InputDialogMode::RENAME ) { xNewLibFT->hide(); std::unique_ptr xRenameFT(m_xBuilder->weld_label("renameft")); xRenameFT->show(); std::unique_ptr xAltTitle(m_xBuilder->weld_label("altrenametitle")); m_xDialog->set_title(xAltTitle->get_label()); } } // ScriptOrgDialog ------------------------------------------------------------ SvxScriptOrgDialog::SvxScriptOrgDialog(weld::Window* pParent, OUString language) : SfxDialogController(pParent, "cui/ui/scriptorganizer.ui", "ScriptOrganizerDialog") , 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("scripts")) , m_xScratchIter(m_xScriptsBox->make_iterator()) , 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 xIter = m_xScriptsBox->make_iterator(); if (!m_xScriptsBox->get_selected(xIter.get())) return; SFEntry* userData = weld::fromId(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 xIter = m_xScriptsBox->make_iterator(); if (!m_xScriptsBox->get_selected(xIter.get())) return; SFEntry* userData = weld::fromId(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 xParentIter = m_xScriptsBox->make_iterator(xIter.get()); bool bParent = m_xScriptsBox->iter_parent(*xParentIter); while (bParent && !mspNode.is() ) { SFEntry* mspUserData = weld::fromId(m_xScriptsBox->get_id(*xParentIter)); 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 ) { 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( "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 = weld::fromId(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(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 : std::as_const(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 : std::as_const(childNodes) ) { if (Concat2View(aUserSuppliedName+extn) == n->getName()) { bValid = false; OUString aError = m_createErrStr + m_createDupStr; std::unique_ptr 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( "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 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(aChildNode,xDocumentModel), true); } else { insertEntry(aChildName, RID_CUIBMP_LIB, &rEntry, false, std::make_unique(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(m_xScriptsBox->get_id(rEntry)); if ( userData && !userData->isLoaded() ) { userData->setLoaded(); } } } else { //ISSUE L10N & message from exception? OUString aError( m_createErrStr ); std::unique_ptr 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( "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 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 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 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 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 xEntry; std::unique_ptr 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("UNKNOWN"); 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("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_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("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_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::get()) { reflection::InvocationTargetException ite; aException >>= ite; if ( ite.TargetException.getValueType() == cppu::UnoType::get()) { // Error raised by script provider::ScriptErrorRaisedException scriptError; ite.TargetException >>= scriptError; return GetErrorMessage( scriptError ); } else if ( ite.TargetException.getValueType() == cppu::UnoType::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::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 xData(static_cast(p)); OUString message = xData->sMessage; if ( message.isEmpty() ) message = CuiResId( RID_CUISTR_ERROR_TITLE ); std::shared_ptr 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: */