bump product version to 6.3.0.0.beta1
[LibreOffice.git] / cui / source / dialogs / scriptdlg.cxx
blob11ef3a8820e2d1cbe1feb787adf59327d3034400
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <utility>
23 #include <sal/log.hxx>
24 #include <sfx2/objsh.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/weld.hxx>
28 #include <strings.hrc>
29 #include <bitmaps.hlst>
30 #include <scriptdlg.hxx>
31 #include <dialmgr.hxx>
32 #include <cfgutil.hxx>
34 #include <com/sun/star/uno/XComponentContext.hpp>
35 #include <com/sun/star/script/provider/ScriptFrameworkErrorException.hpp>
36 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
37 #include <com/sun/star/script/provider/XScriptProvider.hpp>
38 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
39 #include <com/sun/star/script/browse/XBrowseNodeFactory.hpp>
40 #include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
41 #include <com/sun/star/script/browse/theBrowseNodeFactory.hpp>
42 #include <com/sun/star/script/provider/ScriptErrorRaisedException.hpp>
43 #include <com/sun/star/script/provider/ScriptExceptionRaisedException.hpp>
44 #include <com/sun/star/script/provider/ScriptFrameworkErrorType.hpp>
45 #include <com/sun/star/frame/Desktop.hpp>
46 #include <com/sun/star/frame/ModuleManager.hpp>
47 #include <com/sun/star/script/XInvocation.hpp>
48 #include <com/sun/star/document/XEmbeddedScripts.hpp>
50 #include <comphelper/documentinfo.hxx>
51 #include <comphelper/processfactory.hxx>
53 #include <basic/sbx.hxx>
54 #include <svtools/imagemgr.hxx>
55 #include <tools/urlobj.hxx>
56 #include <tools/diagnose_ex.h>
57 #include <vector>
58 #include <algorithm>
60 using namespace ::com::sun::star;
61 using namespace css::uno;
62 using namespace css::script;
63 using namespace css::frame;
64 using namespace css::document;
66 static void ShowErrorDialog( const Any& aException )
68 ScopedVclPtrInstance<SvxScriptErrorDialog> pDlg( aException );
69 pDlg->Execute();
72 void SvxScriptOrgDialog::delUserData(weld::TreeIter& rIter)
74 SFEntry* pUserData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rIter).toInt64());
75 if (pUserData)
77 delete pUserData;
78 // TBD seem to get a Select event on node that is remove ( below )
79 // so need to be able to detect that this node is not to be
80 // processed in order to do this, setting userData to NULL ( must
81 // be a better way to do this )
82 m_xScriptsBox->set_id(rIter, OUString());
86 void SvxScriptOrgDialog::deleteTree(weld::TreeIter& rIter)
88 delUserData(rIter);
89 std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator(&rIter);
90 if (!m_xScriptsBox->iter_children(*xIter))
91 return;
93 std::unique_ptr<weld::TreeIter> xAltIter = m_xScriptsBox->make_iterator();
94 bool bNextEntry;
97 m_xScriptsBox->copy_iterator(*xIter, *xAltIter);
98 bNextEntry = m_xScriptsBox->iter_next_sibling(*xAltIter);
99 deleteTree(*xIter);
100 m_xScriptsBox->remove(*xIter);
101 m_xScriptsBox->copy_iterator(*xAltIter, *xIter);
103 while (bNextEntry);
106 void SvxScriptOrgDialog::deleteAllTree()
108 std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
109 if (!m_xScriptsBox->get_iter_first(*xIter))
110 return;
112 std::unique_ptr<weld::TreeIter> xAltIter = m_xScriptsBox->make_iterator();
113 // TBD - below is a candidate for a destroyAllTrees method
114 bool bNextEntry;
117 m_xScriptsBox->copy_iterator(*xIter, *xAltIter);
118 bNextEntry = m_xScriptsBox->iter_next_sibling(*xAltIter);
119 deleteTree(*xIter);
120 m_xScriptsBox->remove(*xIter);
121 m_xScriptsBox->copy_iterator(*xAltIter, *xIter);
123 while (bNextEntry);
126 void SvxScriptOrgDialog::Init( const OUString& language )
128 m_xScriptsBox->freeze();
130 deleteAllTree();
132 Reference< browse::XBrowseNode > rootNode;
133 Reference< XComponentContext > xCtx(
134 comphelper::getProcessComponentContext() );
136 Sequence< Reference< browse::XBrowseNode > > children;
138 OUString userStr("user");
139 OUString const shareStr("share");
143 Reference< browse::XBrowseNodeFactory > xFac = browse::theBrowseNodeFactory::get(xCtx);
145 rootNode.set( xFac->createView(
146 browse::BrowseNodeFactoryViewTypes::MACROORGANIZER ) );
148 if ( rootNode.is() && rootNode->hasChildNodes() )
150 children = rootNode->getChildNodes();
153 catch( Exception& e )
155 SAL_WARN("cui.dialogs", "Exception getting root browse node from factory: " << e );
156 // TODO exception handling
159 Reference<XModel> xDocumentModel;
160 for ( sal_Int32 n = 0; n < children.getLength(); n++ )
162 bool app = false;
163 OUString uiName = children[ n ]->getName();
164 OUString factoryURL;
165 if ( uiName == userStr || uiName == shareStr )
167 app = true;
168 if ( uiName == userStr )
170 uiName = m_sMyMacros;
172 else
174 uiName = m_sProdMacros;
177 else
179 xDocumentModel.set(getDocumentModel(xCtx, uiName ), UNO_QUERY);
181 if ( xDocumentModel.is() )
183 Reference< frame::XModuleManager2 > xModuleManager( frame::ModuleManager::create(xCtx) );
185 // get the long name of the document:
186 Sequence<beans::PropertyValue> moduleDescr;
187 try{
188 OUString appModule = xModuleManager->identify( xDocumentModel );
189 xModuleManager->getByName(appModule) >>= moduleDescr;
190 } catch(const uno::Exception&)
193 beans::PropertyValue const * pmoduleDescr =
194 moduleDescr.getConstArray();
195 for ( sal_Int32 pos = moduleDescr.getLength(); pos--; )
197 if ( pmoduleDescr[ pos ].Name == "ooSetupFactoryEmptyDocumentURL" )
199 pmoduleDescr[ pos ].Value >>= factoryURL;
200 break;
206 Reference< browse::XBrowseNode > langEntries =
207 getLangNodeFromRootNode( children[ n ], language );
209 insertEntry( uiName, app ? OUStringLiteral(RID_CUIBMP_HARDDISK) : OUStringLiteral(RID_CUIBMP_DOC),
210 nullptr, true, std::make_unique< SFEntry >( langEntries, xDocumentModel ), factoryURL, false );
213 m_xScriptsBox->thaw();
216 Reference< XInterface >
217 SvxScriptOrgDialog::getDocumentModel( Reference< XComponentContext > const & xCtx, OUString const & docName )
219 Reference< XInterface > xModel;
220 Reference< frame::XDesktop2 > desktop = frame::Desktop::create(xCtx);
222 Reference< container::XEnumerationAccess > componentsAccess =
223 desktop->getComponents();
224 Reference< container::XEnumeration > components =
225 componentsAccess->createEnumeration();
226 while (components->hasMoreElements())
228 Reference< frame::XModel > model(
229 components->nextElement(), UNO_QUERY );
230 if ( model.is() )
232 OUString sTdocUrl = ::comphelper::DocumentInfo::getDocumentTitle( model );
233 if( sTdocUrl == docName )
235 xModel = model;
236 break;
240 return xModel;
243 Reference< browse::XBrowseNode >
244 SvxScriptOrgDialog::getLangNodeFromRootNode( Reference< browse::XBrowseNode > const & rootNode, OUString const & language )
246 Reference< browse::XBrowseNode > langNode;
250 Sequence < Reference< browse::XBrowseNode > > children = rootNode->getChildNodes();
251 for ( sal_Int32 n = 0; n < children.getLength(); n++ )
253 if ( children[ n ]->getName() == language )
255 langNode = children[ n ];
256 break;
260 catch ( Exception& )
262 // if getChildNodes() throws an exception we just return
263 // the empty Reference
265 return langNode;
268 void SvxScriptOrgDialog::RequestSubEntries(const weld::TreeIter& rRootEntry, Reference< css::script::browse::XBrowseNode > const & node,
269 Reference< XModel >& model)
271 if (!node.is())
273 return;
276 Sequence< Reference< browse::XBrowseNode > > children;
279 children = node->getChildNodes();
281 catch ( Exception& )
283 // if we catch an exception in getChildNodes then no entries are added
286 for ( sal_Int32 n = 0; n < children.getLength(); n++ )
288 OUString name( children[ n ]->getName() );
289 if ( children[ n ]->getType() != browse::BrowseNodeTypes::SCRIPT)
291 insertEntry(name, RID_CUIBMP_LIB, &rRootEntry, true, std::make_unique<SFEntry>(children[n], model), false);
293 else
295 insertEntry(name, RID_CUIBMP_MACRO, &rRootEntry, false, std::make_unique<SFEntry>(children[n], model), false);
300 void SvxScriptOrgDialog::insertEntry(const OUString& rText, const OUString& rBitmap,
301 const weld::TreeIter* pParent, bool bChildrenOnDemand, std::unique_ptr<SFEntry> && aUserData,
302 const OUString& factoryURL, bool bSelect)
304 if (rBitmap == RID_CUIBMP_DOC && !factoryURL.isEmpty())
306 OUString aImage = SvFileInformationManager::GetFileImageId(INetURLObject(factoryURL));
307 insertEntry(rText, aImage, pParent, bChildrenOnDemand, std::move(aUserData), bSelect);
308 return;
310 insertEntry(rText, rBitmap, pParent, bChildrenOnDemand, std::move(aUserData), bSelect);
313 void SvxScriptOrgDialog::insertEntry(
314 const OUString& rText, const OUString& rBitmap, const weld::TreeIter* pParent,
315 bool bChildrenOnDemand, std::unique_ptr<SFEntry> && aUserData, bool bSelect)
317 std::unique_ptr<weld::TreeIter> xRetIter;
318 if (bSelect)
319 xRetIter = m_xScriptsBox->make_iterator();
320 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aUserData.release()))); // XXX possible leak
321 m_xScriptsBox->insert(pParent, -1, &rText, &sId, nullptr, nullptr, &rBitmap,
322 bChildrenOnDemand, xRetIter.get());
323 if (bSelect)
325 m_xScriptsBox->set_cursor(*xRetIter);
326 m_xScriptsBox->select(*xRetIter);
330 IMPL_LINK(SvxScriptOrgDialog, ExpandingHdl, const weld::TreeIter&, rIter, bool)
332 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rIter).toInt64());
334 Reference< browse::XBrowseNode > node;
335 Reference< XModel > model;
336 if ( userData && !userData->isLoaded() )
338 node = userData->GetNode();
339 model = userData->GetModel();
340 RequestSubEntries(rIter, node, model);
341 userData->setLoaded();
344 return true;
347 // CuiInputDialog ------------------------------------------------------------
348 CuiInputDialog::CuiInputDialog(weld::Window * pParent, InputDialogMode nMode)
349 : GenericDialogController(pParent, "cui/ui/newlibdialog.ui", "NewLibDialog")
350 , m_xEdit(m_xBuilder->weld_entry("entry"))
352 m_xEdit->grab_focus();
354 std::unique_ptr<weld::Label> xNewLibFT(m_xBuilder->weld_label("newlibft"));
356 if ( nMode == InputDialogMode::NEWMACRO )
358 xNewLibFT->hide();
359 std::unique_ptr<weld::Label> xNewMacroFT(m_xBuilder->weld_label("newmacroft"));
360 xNewMacroFT->show();
361 std::unique_ptr<weld::Label> xAltTitle(m_xBuilder->weld_label("altmacrotitle"));
362 m_xDialog->set_title(xAltTitle->get_label());
364 else if ( nMode == InputDialogMode::RENAME )
366 xNewLibFT->hide();
367 std::unique_ptr<weld::Label> xRenameFT(m_xBuilder->weld_label("renameft"));
368 xRenameFT->show();
369 std::unique_ptr<weld::Label> xAltTitle(m_xBuilder->weld_label("altrenametitle"));
370 m_xDialog->set_title(xAltTitle->get_label());
374 // ScriptOrgDialog ------------------------------------------------------------
376 SvxScriptOrgDialog::SvxScriptOrgDialog(weld::Window* pParent, const OUString& language)
377 : SfxDialogController(pParent, "cui/ui/scriptorganizer.ui", "ScriptOrganizerDialog")
378 , m_sLanguage(language)
379 , m_delErrStr(CuiResId(RID_SVXSTR_DELFAILED))
380 , m_delErrTitleStr(CuiResId(RID_SVXSTR_DELFAILED_TITLE))
381 , m_delQueryStr(CuiResId(RID_SVXSTR_DELQUERY))
382 , m_delQueryTitleStr(CuiResId(RID_SVXSTR_DELQUERY_TITLE))
383 , m_createErrStr(CuiResId(RID_SVXSTR_CREATEFAILED))
384 , m_createDupStr(CuiResId(RID_SVXSTR_CREATEFAILEDDUP))
385 , m_createErrTitleStr(CuiResId(RID_SVXSTR_CREATEFAILED_TITLE))
386 , m_renameErrStr(CuiResId(RID_SVXSTR_RENAMEFAILED))
387 , m_renameErrTitleStr(CuiResId(RID_SVXSTR_RENAMEFAILED_TITLE))
388 , m_sMyMacros(CuiResId(RID_SVXSTR_MYMACROS))
389 , m_sProdMacros(CuiResId(RID_SVXSTR_PRODMACROS))
390 , m_xScriptsBox(m_xBuilder->weld_tree_view("scripts"))
391 , m_xRunButton(m_xBuilder->weld_button("ok"))
392 , m_xCloseButton(m_xBuilder->weld_button("close"))
393 , m_xCreateButton(m_xBuilder->weld_button("create"))
394 , m_xEditButton(m_xBuilder->weld_button("edit"))
395 , m_xRenameButton(m_xBuilder->weld_button("rename"))
396 , m_xDelButton(m_xBuilder->weld_button("delete"))
398 // must be a neater way to deal with the strings than as above
399 // append the language to the dialog title
400 OUString winTitle(m_xDialog->get_title());
401 winTitle = winTitle.replaceFirst( "%MACROLANG", m_sLanguage );
402 m_xDialog->set_title(winTitle);
404 m_xScriptsBox->set_size_request(m_xScriptsBox->get_approximate_digit_width() * 45,
405 m_xScriptsBox->get_height_rows(12));
407 m_xScriptsBox->connect_changed( LINK( this, SvxScriptOrgDialog, ScriptSelectHdl ) );
408 m_xScriptsBox->connect_expanding(LINK( this, SvxScriptOrgDialog, ExpandingHdl ) );
409 m_xRunButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
410 m_xCloseButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
411 m_xRenameButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
412 m_xEditButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
413 m_xDelButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
414 m_xCreateButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
416 m_xRunButton->set_sensitive(false);
417 m_xRenameButton->set_sensitive(false);
418 m_xEditButton->set_sensitive(false);
419 m_xDelButton->set_sensitive(false);
420 m_xCreateButton->set_sensitive(false);
422 Init(m_sLanguage);
423 RestorePreviousSelection();
426 SvxScriptOrgDialog::~SvxScriptOrgDialog()
428 deleteAllTree();
431 short SvxScriptOrgDialog::run()
433 SfxObjectShell *pDoc = SfxObjectShell::GetFirst();
435 // force load of MSPs for all documents
436 while ( pDoc )
438 Reference< provider::XScriptProviderSupplier > xSPS =
439 Reference< provider::XScriptProviderSupplier >
440 ( pDoc->GetModel(), UNO_QUERY );
441 if ( xSPS.is() )
443 xSPS->getScriptProvider();
446 pDoc = SfxObjectShell::GetNext(*pDoc);
449 return SfxDialogController::run();
452 void SvxScriptOrgDialog::CheckButtons( Reference< browse::XBrowseNode > const & node )
454 if ( node.is() )
456 if ( node->getType() == browse::BrowseNodeTypes::SCRIPT)
458 m_xRunButton->set_sensitive(true);
460 else
462 m_xRunButton->set_sensitive(false);
464 Reference< beans::XPropertySet > xProps( node, UNO_QUERY );
466 if ( !xProps.is() )
468 m_xEditButton->set_sensitive(false);
469 m_xDelButton->set_sensitive(false);
470 m_xCreateButton->set_sensitive(false);
471 m_xRunButton->set_sensitive(false);
472 return;
475 OUString sName("Editable");
477 if ( getBoolProperty( xProps, sName ) )
479 m_xEditButton->set_sensitive(true);
481 else
483 m_xEditButton->set_sensitive(false);
486 sName = "Deletable";
488 if ( getBoolProperty( xProps, sName ) )
490 m_xDelButton->set_sensitive(true);
492 else
494 m_xDelButton->set_sensitive(false);
497 sName = "Creatable";
499 if ( getBoolProperty( xProps, sName ) )
501 m_xCreateButton->set_sensitive(true);
503 else
505 m_xCreateButton->set_sensitive(false);
508 sName = "Renamable";
510 if ( getBoolProperty( xProps, sName ) )
512 m_xRenameButton->set_sensitive(true);
514 else
516 m_xRenameButton->set_sensitive(false);
519 else
521 // no node info available, disable all configurable actions
522 m_xDelButton->set_sensitive(false);
523 m_xCreateButton->set_sensitive(false);
524 m_xEditButton->set_sensitive(false);
525 m_xRunButton->set_sensitive(false);
526 m_xRenameButton->set_sensitive(false);
530 IMPL_LINK_NOARG(SvxScriptOrgDialog, ScriptSelectHdl, weld::TreeView&, void)
532 std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
533 if (!m_xScriptsBox->get_selected(xIter.get()))
534 return;
536 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(*xIter).toInt64());
538 Reference< browse::XBrowseNode > node;
539 if (userData)
541 node = userData->GetNode();
542 CheckButtons(node);
546 IMPL_LINK(SvxScriptOrgDialog, ButtonHdl, weld::Button&, rButton, void)
548 if ( &rButton == m_xCloseButton.get() )
550 StoreCurrentSelection();
551 m_xDialog->response(RET_CANCEL);
553 if (&rButton == m_xEditButton.get() ||
554 &rButton == m_xCreateButton.get() ||
555 &rButton == m_xDelButton.get() ||
556 &rButton == m_xRunButton.get() ||
557 &rButton == m_xRenameButton.get())
560 std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
561 if (!m_xScriptsBox->get_selected(xIter.get()))
562 return;
563 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(*xIter).toInt64());
564 if (!userData)
565 return;
567 Reference< browse::XBrowseNode > node;
568 Reference< XModel > xModel;
570 node = userData->GetNode();
571 xModel = userData->GetModel();
573 if ( !node.is() )
575 return;
578 if (&rButton == m_xRunButton.get())
580 OUString tmpString;
581 Reference< beans::XPropertySet > xProp( node, UNO_QUERY );
582 Reference< provider::XScriptProvider > mspNode;
583 if( !xProp.is() )
585 return;
588 if ( xModel.is() )
590 Reference< XEmbeddedScripts > xEmbeddedScripts( xModel, UNO_QUERY);
591 if( !xEmbeddedScripts.is() )
593 return;
596 if (!xEmbeddedScripts->getAllowMacroExecution())
598 // Please FIXME: Show a message box if AllowMacroExecution is false
599 return;
603 std::unique_ptr<weld::TreeIter> xParentIter = m_xScriptsBox->make_iterator(xIter.get());
604 bool bParent = m_xScriptsBox->iter_parent(*xParentIter);
605 while (bParent && !mspNode.is() )
607 SFEntry* mspUserData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(*xParentIter).toInt64());
608 mspNode.set( mspUserData->GetNode() , UNO_QUERY );
609 bParent = m_xScriptsBox->iter_parent(*xParentIter);
611 xProp->getPropertyValue("URI") >>= tmpString;
612 const OUString scriptURL( tmpString );
614 if ( mspNode.is() )
618 Reference< provider::XScript > xScript(
619 mspNode->getScript( scriptURL ), UNO_SET_THROW );
621 const Sequence< Any > args(0);
622 Sequence< sal_Int16 > outIndex;
623 Sequence< Any > outArgs( 0 );
624 xScript->invoke( args, outIndex, outArgs );
626 catch ( reflection::InvocationTargetException& ite )
628 ShowErrorDialog(css::uno::Any(ite));
630 catch ( provider::ScriptFrameworkErrorException& ite )
632 ShowErrorDialog(css::uno::Any(ite));
634 catch ( RuntimeException& re )
636 ShowErrorDialog(css::uno::Any(re));
638 catch ( Exception& e )
640 ShowErrorDialog(css::uno::Any(e));
643 StoreCurrentSelection();
644 m_xDialog->response(RET_CANCEL);
646 else if ( &rButton == m_xEditButton.get() )
648 Reference< script::XInvocation > xInv( node, UNO_QUERY );
649 if ( xInv.is() )
651 StoreCurrentSelection();
652 m_xDialog->response(RET_CANCEL);
653 Sequence< Any > args(0);
654 Sequence< Any > outArgs( 0 );
655 Sequence< sal_Int16 > outIndex;
658 // ISSUE need code to run script here
659 xInv->invoke( "Editable", args, outIndex, outArgs );
661 catch( Exception const & )
663 css::uno::Any ex( cppu::getCaughtException() );
664 SAL_WARN("cui.dialogs", "Caught exception trying to invoke " << exceptionToString(ex) );
668 else if ( &rButton == m_xCreateButton.get() )
670 createEntry(*xIter);
672 else if ( &rButton == m_xDelButton.get() )
674 deleteEntry(*xIter);
676 else if ( &rButton == m_xRenameButton.get() )
678 renameEntry(*xIter);
683 Reference< browse::XBrowseNode > SvxScriptOrgDialog::getBrowseNode(const weld::TreeIter& rEntry)
685 Reference< browse::XBrowseNode > node;
686 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rEntry).toInt64());
687 if (userData)
689 node = userData->GetNode();
691 return node;
694 Reference< XModel > SvxScriptOrgDialog::getModel(const weld::TreeIter& rEntry)
696 Reference< XModel > model;
697 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rEntry).toInt64());
698 if ( userData )
700 model = userData->GetModel();
702 return model;
705 void SvxScriptOrgDialog::createEntry(weld::TreeIter& rEntry)
708 Reference< browse::XBrowseNode > aChildNode;
709 Reference< browse::XBrowseNode > node = getBrowseNode( rEntry );
710 Reference< script::XInvocation > xInv( node, UNO_QUERY );
712 if ( xInv.is() )
714 OUString aNewName;
715 OUString aNewStdName;
716 InputDialogMode nMode = InputDialogMode::NEWLIB;
717 if (m_xScriptsBox->get_iter_depth(rEntry) == 0)
719 aNewStdName = "Library" ;
721 else
723 aNewStdName = "Macro" ;
724 nMode = InputDialogMode::NEWMACRO;
726 //do we need L10N for this? ie something like:
727 //String aNewStdName( ResId( STR_STDMODULENAME ) );
728 bool bValid = false;
729 sal_Int32 i = 1;
731 Sequence< Reference< browse::XBrowseNode > > childNodes;
732 // no children => ok to create Parcel1 or Script1 without checking
735 if( !node->hasChildNodes() )
737 aNewName = aNewStdName + OUString::number(i);
738 bValid = true;
740 else
742 childNodes = node->getChildNodes();
745 catch ( Exception& )
747 // ignore, will continue on with empty sequence
750 OUString extn;
751 while ( !bValid )
753 aNewName = aNewStdName + OUString::number(i);
754 bool bFound = false;
755 if(childNodes.getLength() > 0 )
757 OUString nodeName = childNodes[0]->getName();
758 sal_Int32 extnPos = nodeName.lastIndexOf( '.' );
759 if(extnPos>0)
760 extn = nodeName.copy(extnPos);
762 for( sal_Int32 index = 0; index < childNodes.getLength(); index++ )
764 if (aNewName+extn == childNodes[index]->getName())
766 bFound = true;
767 break;
770 if( bFound )
772 i++;
774 else
776 bValid = true;
780 CuiInputDialog aNewDlg(m_xDialog.get(), nMode);
781 aNewDlg.SetObjectName(aNewName);
785 if (aNewDlg.run() && !aNewDlg.GetObjectName().isEmpty())
787 OUString aUserSuppliedName = aNewDlg.GetObjectName();
788 bValid = true;
789 for( sal_Int32 index = 0; index < childNodes.getLength(); index++ )
791 if (aUserSuppliedName+extn == childNodes[index]->getName())
793 bValid = false;
794 OUString aError = m_createErrStr + m_createDupStr;
796 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
797 VclMessageType::Warning, VclButtonsType::Ok, aError));
798 xErrorBox->set_title(m_createErrTitleStr);
799 xErrorBox->run();
800 aNewDlg.SetObjectName(aNewName);
801 break;
804 if( bValid )
805 aNewName = aUserSuppliedName;
807 else
809 // user hit cancel or hit OK with nothing in the editbox
811 return;
814 while ( !bValid );
816 // open up parent node (which ensures it's loaded)
817 m_xScriptsBox->expand_row(rEntry);
819 Sequence< Any > args( 1 );
820 args[ 0 ] <<= aNewName;
821 Sequence< Any > outArgs( 0 );
822 Sequence< sal_Int16 > outIndex;
825 Any aResult = xInv->invoke( "Creatable", args, outIndex, outArgs );
826 Reference< browse::XBrowseNode > newNode( aResult, UNO_QUERY );
827 aChildNode = newNode;
830 catch( Exception const & )
832 css::uno::Any ex( cppu::getCaughtException() );
833 SAL_WARN("cui.dialogs", "Caught exception trying to Create " << exceptionToString(ex) );
836 if ( aChildNode.is() )
838 OUString aChildName = aChildNode->getName();
840 Reference<XModel> xDocumentModel = getModel( rEntry );
842 // ISSUE do we need to remove all entries for parent
843 // to achieve sort? Just need to determine position
844 // SvTreeListBox::InsertEntry can take position arg
845 // -- Basic doesn't do this on create.
846 // Suppose we could avoid this too. -> created nodes are
847 // not in alphabetical order
848 if ( aChildNode->getType() == browse::BrowseNodeTypes::SCRIPT )
850 insertEntry(aChildName, RID_CUIBMP_MACRO, &rEntry, false,
851 std::make_unique<SFEntry>(aChildNode,xDocumentModel), true);
853 else
855 insertEntry(aChildName, RID_CUIBMP_LIB, &rEntry, false,
856 std::make_unique<SFEntry>(aChildNode,xDocumentModel), true);
858 // If the Parent is not loaded then set to
859 // loaded, this will prevent RequestingChildren ( called
860 // from vcl via RequestingChildren ) from
861 // creating new ( duplicate ) children
862 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rEntry).toInt64());
863 if ( userData && !userData->isLoaded() )
865 userData->setLoaded();
869 else
871 //ISSUE L10N & message from exception?
872 OUString aError( m_createErrStr );
873 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
874 VclMessageType::Warning, VclButtonsType::Ok, aError));
875 xErrorBox->set_title(m_createErrTitleStr);
876 xErrorBox->run();
880 void SvxScriptOrgDialog::renameEntry(weld::TreeIter& rEntry)
883 Reference< browse::XBrowseNode > aChildNode;
884 Reference< browse::XBrowseNode > node = getBrowseNode(rEntry);
885 Reference< script::XInvocation > xInv( node, UNO_QUERY );
887 if ( xInv.is() )
889 OUString aNewName = node->getName();
890 sal_Int32 extnPos = aNewName.lastIndexOf( '.' );
891 if(extnPos>0)
893 aNewName = aNewName.copy(0,extnPos);
895 CuiInputDialog aNewDlg(m_xDialog.get(), InputDialogMode::RENAME);
896 aNewDlg.SetObjectName(aNewName);
898 if (!aNewDlg.run() || aNewDlg.GetObjectName().isEmpty())
899 return; // user hit cancel or hit OK with nothing in the editbox
901 aNewName = aNewDlg.GetObjectName();
903 Sequence< Any > args( 1 );
904 args[ 0 ] <<= aNewName;
905 Sequence< Any > outArgs( 0 );
906 Sequence< sal_Int16 > outIndex;
909 Any aResult = xInv->invoke( "Renamable", args, outIndex, outArgs );
910 Reference< browse::XBrowseNode > newNode( aResult, UNO_QUERY );
911 aChildNode = newNode;
914 catch( Exception const & )
916 css::uno::Any ex( cppu::getCaughtException() );
917 SAL_WARN("cui.dialogs", "Caught exception trying to Rename " << exceptionToString(ex) );
920 if ( aChildNode.is() )
922 m_xScriptsBox->set_text(rEntry, aChildNode->getName());
923 m_xScriptsBox->set_cursor(rEntry);
924 m_xScriptsBox->select(rEntry);
927 else
929 //ISSUE L10N & message from exception?
930 OUString aError( m_renameErrStr );
931 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
932 VclMessageType::Warning, VclButtonsType::Ok, aError));
933 xErrorBox->set_title(m_renameErrTitleStr);
934 xErrorBox->run();
938 void SvxScriptOrgDialog::deleteEntry(weld::TreeIter& rEntry)
940 bool result = false;
941 Reference< browse::XBrowseNode > node = getBrowseNode(rEntry);
942 // ISSUE L10N string & can we centre list?
943 OUString aQuery = m_delQueryStr + getListOfChildren( node, 0 );
944 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_xDialog.get(),
945 VclMessageType::Question, VclButtonsType::YesNo, aQuery));
946 xQueryBox->set_title(m_delQueryTitleStr);
947 if (xQueryBox->run() == RET_NO)
949 return;
952 Reference< script::XInvocation > xInv( node, UNO_QUERY );
953 if ( xInv.is() )
955 Sequence< Any > args( 0 );
956 Sequence< Any > outArgs( 0 );
957 Sequence< sal_Int16 > outIndex;
960 Any aResult = xInv->invoke( "Deletable", args, outIndex, outArgs );
961 aResult >>= result; // or do we just assume true if no exception ?
963 catch( Exception const & )
965 css::uno::Any ex( cppu::getCaughtException() );
966 SAL_WARN("cui.dialogs", "Caught exception trying to delete " << exceptionToString(ex) );
970 if ( result )
972 deleteTree(rEntry);
973 m_xScriptsBox->remove(rEntry);
975 else
977 //ISSUE L10N & message from exception?
978 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
979 VclMessageType::Warning, VclButtonsType::Ok, m_delErrStr));
980 xErrorBox->set_title(m_delErrTitleStr);
981 xErrorBox->run();
986 bool SvxScriptOrgDialog::getBoolProperty( Reference< beans::XPropertySet > const & xProps,
987 OUString const & propName )
989 bool result = false;
992 xProps->getPropertyValue( propName ) >>= result;
994 catch ( Exception& )
996 return result;
998 return result;
1001 OUString SvxScriptOrgDialog::getListOfChildren( const Reference< browse::XBrowseNode >& node, int depth )
1003 OUStringBuffer result = "\n";
1004 for( int i=0;i<=depth;i++ )
1006 result.append("\t");
1008 result.append(node->getName());
1012 if ( node->hasChildNodes() )
1014 Sequence< Reference< browse::XBrowseNode > > children
1015 = node->getChildNodes();
1016 for ( sal_Int32 n = 0; n < children.getLength(); n++ )
1018 result.append( getListOfChildren( children[ n ] , depth+1 ) );
1022 catch ( Exception& )
1024 // ignore, will return an empty string
1027 return result.makeStringAndClear();
1030 Selection_hash SvxScriptOrgDialog::m_lastSelection;
1032 void SvxScriptOrgDialog::StoreCurrentSelection()
1034 std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
1035 if (!m_xScriptsBox->get_selected(xIter.get()))
1036 return;
1037 OUString aDescription;
1038 bool bEntry;
1041 aDescription = m_xScriptsBox->get_text(*xIter) + aDescription;
1042 bEntry = m_xScriptsBox->iter_parent(*xIter);
1043 if (bEntry)
1044 aDescription = ";" + aDescription;
1046 while (bEntry);
1047 OUString sDesc( aDescription );
1048 m_lastSelection[ m_sLanguage ] = sDesc;
1051 void SvxScriptOrgDialog::RestorePreviousSelection()
1053 OUString aStoredEntry = m_lastSelection[ m_sLanguage ];
1054 if( aStoredEntry.isEmpty() )
1055 return;
1056 std::unique_ptr<weld::TreeIter> xEntry;
1057 std::unique_ptr<weld::TreeIter> xTmpEntry(m_xScriptsBox->make_iterator());
1058 sal_Int32 nIndex = 0;
1059 while (nIndex != -1)
1061 OUString aTmp( aStoredEntry.getToken( 0, ';', nIndex ) );
1063 bool bTmpEntry;
1064 if (!xEntry)
1066 xEntry = m_xScriptsBox->make_iterator();
1067 bTmpEntry = m_xScriptsBox->get_iter_first(*xEntry);
1068 m_xScriptsBox->copy_iterator(*xEntry, *xTmpEntry);
1070 else
1072 m_xScriptsBox->copy_iterator(*xEntry, *xTmpEntry);
1073 bTmpEntry = m_xScriptsBox->iter_children(*xTmpEntry);
1076 while (bTmpEntry)
1078 if (m_xScriptsBox->get_text(*xTmpEntry) == aTmp)
1080 m_xScriptsBox->copy_iterator(*xTmpEntry, *xEntry);
1081 break;
1083 bTmpEntry = m_xScriptsBox->iter_next_sibling(*xTmpEntry);
1086 if (!bTmpEntry)
1087 break;
1089 m_xScriptsBox->expand_row(*xEntry);
1092 if (xEntry)
1093 m_xScriptsBox->set_cursor(*xEntry);
1096 namespace {
1098 OUString ReplaceString(
1099 const OUString& source,
1100 const OUString& token,
1101 const OUString& value )
1103 sal_Int32 pos = source.indexOf( token );
1105 if ( pos != -1 && !value.isEmpty() )
1107 return source.replaceAt( pos, token.getLength(), value );
1109 else
1111 return source;
1115 OUString FormatErrorString(
1116 const OUString& unformatted,
1117 const OUString& language,
1118 const OUString& script,
1119 const OUString& line,
1120 const OUString& type,
1121 const OUString& message )
1123 OUString result = unformatted.copy( 0 );
1125 result = ReplaceString(result, "%LANGUAGENAME", language );
1126 result = ReplaceString(result, "%SCRIPTNAME", script );
1127 result = ReplaceString(result, "%LINENUMBER", line );
1129 if ( !type.isEmpty() )
1131 result += "\n\n" + CuiResId(RID_SVXSTR_ERROR_TYPE_LABEL) + " " + type;
1134 if ( !message.isEmpty() )
1136 result += "\n\n" + CuiResId(RID_SVXSTR_ERROR_MESSAGE_LABEL) + " " + message;
1139 return result;
1142 OUString GetErrorMessage(
1143 const provider::ScriptErrorRaisedException& eScriptError )
1145 OUString unformatted = CuiResId( RID_SVXSTR_ERROR_AT_LINE );
1147 OUString unknown("UNKNOWN");
1148 OUString language = unknown;
1149 OUString script = unknown;
1150 OUString line = unknown;
1151 OUString type = "";
1152 OUString message = eScriptError.Message;
1154 if ( !eScriptError.language.isEmpty() )
1156 language = eScriptError.language;
1159 if ( !eScriptError.scriptName.isEmpty() )
1161 script = eScriptError.scriptName;
1164 if ( !eScriptError.Message.isEmpty() )
1166 message = eScriptError.Message;
1168 if ( eScriptError.lineNum != -1 )
1170 line = OUString::number( eScriptError.lineNum );
1171 unformatted = CuiResId( RID_SVXSTR_ERROR_AT_LINE );
1173 else
1175 unformatted = CuiResId( RID_SVXSTR_ERROR_RUNNING );
1178 return FormatErrorString(
1179 unformatted, language, script, line, type, message );
1182 OUString GetErrorMessage(
1183 const provider::ScriptExceptionRaisedException& eScriptException )
1185 OUString unformatted = CuiResId( RID_SVXSTR_EXCEPTION_AT_LINE );
1187 OUString unknown("UNKNOWN");
1188 OUString language = unknown;
1189 OUString script = unknown;
1190 OUString line = unknown;
1191 OUString type = unknown;
1192 OUString message = eScriptException.Message;
1194 if ( !eScriptException.language.isEmpty() )
1196 language = eScriptException.language;
1198 if ( !eScriptException.scriptName.isEmpty() )
1200 script = eScriptException.scriptName;
1203 if ( !eScriptException.Message.isEmpty() )
1205 message = eScriptException.Message;
1208 if ( eScriptException.lineNum != -1 )
1210 line = OUString::number( eScriptException.lineNum );
1211 unformatted = CuiResId( RID_SVXSTR_EXCEPTION_AT_LINE );
1213 else
1215 unformatted = CuiResId( RID_SVXSTR_EXCEPTION_RUNNING );
1218 if ( !eScriptException.exceptionType.isEmpty() )
1220 type = eScriptException.exceptionType;
1223 return FormatErrorString(
1224 unformatted, language, script, line, type, message );
1227 OUString GetErrorMessage(
1228 const provider::ScriptFrameworkErrorException& sError )
1230 OUString unformatted = CuiResId( RID_SVXSTR_FRAMEWORK_ERROR_RUNNING );
1232 OUString language("UNKNOWN");
1234 OUString script("UNKNOWN");
1236 OUString message;
1238 if ( !sError.scriptName.isEmpty() )
1240 script = sError.scriptName;
1242 if ( !sError.language.isEmpty() )
1244 language = sError.language;
1246 if ( sError.errorType == provider::ScriptFrameworkErrorType::NOTSUPPORTED )
1248 message =
1249 CuiResId( RID_SVXSTR_ERROR_LANG_NOT_SUPPORTED );
1250 message = ReplaceString(message, "%LANGUAGENAME", language );
1253 else
1255 message = sError.Message;
1257 return FormatErrorString(
1258 unformatted, language, script, OUString(), OUString(), message );
1261 OUString GetErrorMessage( const css::uno::Any& aException )
1263 if ( aException.getValueType() ==
1264 cppu::UnoType<reflection::InvocationTargetException>::get())
1266 reflection::InvocationTargetException ite;
1267 aException >>= ite;
1268 if ( ite.TargetException.getValueType() == cppu::UnoType<provider::ScriptErrorRaisedException>::get())
1270 // Error raised by script
1271 provider::ScriptErrorRaisedException scriptError;
1272 ite.TargetException >>= scriptError;
1273 return GetErrorMessage( scriptError );
1275 else if ( ite.TargetException.getValueType() == cppu::UnoType<provider::ScriptExceptionRaisedException>::get())
1277 // Exception raised by script
1278 provider::ScriptExceptionRaisedException scriptException;
1279 ite.TargetException >>= scriptException;
1280 return GetErrorMessage( scriptException );
1282 else
1284 // Unknown error, shouldn't happen
1285 // OSL_ASSERT(...)
1289 else if ( aException.getValueType() == cppu::UnoType<provider::ScriptFrameworkErrorException>::get())
1291 // A Script Framework error has occurred
1292 provider::ScriptFrameworkErrorException sfe;
1293 aException >>= sfe;
1294 return GetErrorMessage( sfe );
1297 // unknown exception
1298 auto msg = aException.getValueTypeName();
1299 Exception e;
1300 if ( (aException >>= e) && !e.Message.isEmpty() )
1302 msg += ": " + e.Message;
1304 return msg;
1309 SvxScriptErrorDialog::SvxScriptErrorDialog( css::uno::Any const & aException )
1310 : m_sMessage()
1312 SolarMutexGuard aGuard;
1313 m_sMessage = GetErrorMessage( aException );
1316 SvxScriptErrorDialog::~SvxScriptErrorDialog()
1320 short SvxScriptErrorDialog::Execute()
1322 // Show Error dialog asynchronously
1324 // Pass a copy of the message to the ShowDialog method as the
1325 // SvxScriptErrorDialog may be deleted before ShowDialog is called
1326 Application::PostUserEvent(
1327 LINK( this, SvxScriptErrorDialog, ShowDialog ),
1328 new OUString( m_sMessage ) );
1330 return 0;
1333 IMPL_STATIC_LINK( SvxScriptErrorDialog, ShowDialog, void*, p, void )
1335 OUString* pMessage = static_cast<OUString*>(p);
1336 OUString message;
1338 if ( pMessage && !pMessage->isEmpty() )
1340 message = *pMessage;
1342 else
1344 message = CuiResId( RID_SVXSTR_ERROR_TITLE );
1347 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
1348 VclMessageType::Warning, VclButtonsType::Ok, message));
1349 xBox->set_title(CuiResId(RID_SVXSTR_ERROR_TITLE));
1350 xBox->run();
1352 delete pMessage;
1355 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */