1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <memory>
21 #include <string_view>
22 #include <utility>
23
24 #include <sfx2/objsh.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/weld.hxx>
27
28 #include <strings.hrc>
29 #include <bitmaps.hlst>
30 #include <scriptdlg.hxx>
31 #include <dialmgr.hxx>
32
33 #include <com/sun/star/uno/XComponentContext.hpp>
34 #include <com/sun/star/script/provider/ScriptFrameworkErrorException.hpp>
35 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
36 #include <com/sun/star/script/provider/XScriptProvider.hpp>
37 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
38 #include <com/sun/star/script/browse/XBrowseNodeFactory.hpp>
39 #include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
40 #include <com/sun/star/script/browse/theBrowseNodeFactory.hpp>
41 #include <com/sun/star/script/provider/ScriptErrorRaisedException.hpp>
42 #include <com/sun/star/script/provider/ScriptExceptionRaisedException.hpp>
43 #include <com/sun/star/script/provider/ScriptFrameworkErrorType.hpp>
44 #include <com/sun/star/frame/Desktop.hpp>
45 #include <com/sun/star/frame/ModuleManager.hpp>
46 #include <com/sun/star/script/XInvocation.hpp>
47 #include <com/sun/star/document/XEmbeddedScripts.hpp>
48
49 #include <comphelper/lok.hxx>
50 #include <comphelper/SetFlagContextHelper.hxx>
51 #include <comphelper/documentinfo.hxx>
52 #include <comphelper/processfactory.hxx>
53
54 #include <svtools/imagemgr.hxx>
55 #include <tools/urlobj.hxx>
56 #include <tools/diagnose_ex.h>
57
58 using namespace ::com::sun::star;
59 using namespace css::uno;
60 using namespace css::script;
61 using namespace css::frame;
62 using namespace css::document;
63
delUserData(const weld::TreeIter & rIter)64 void SvxScriptOrgDialog::delUserData(const weld::TreeIter& rIter)
65 {
66 SFEntry* pUserData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rIter).toInt64());
67 if (pUserData)
68 {
69 delete pUserData;
70 // TBD seem to get a Select event on node that is remove ( below )
71 // so need to be able to detect that this node is not to be
72 // processed in order to do this, setting userData to NULL ( must
73 // be a better way to do this )
74 m_xScriptsBox->set_id(rIter, OUString());
75 }
76 }
77
deleteTree(weld::TreeIter & rIter)78 void SvxScriptOrgDialog::deleteTree(weld::TreeIter& rIter)
79 {
80 delUserData(rIter);
81 std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator(&rIter);
82 if (!m_xScriptsBox->iter_children(*xIter))
83 return;
84
85 std::unique_ptr<weld::TreeIter> xAltIter = m_xScriptsBox->make_iterator();
86 bool bNextEntry;
87 do
88 {
89 m_xScriptsBox->copy_iterator(*xIter, *xAltIter);
90 bNextEntry = m_xScriptsBox->iter_next_sibling(*xAltIter);
91 deleteTree(*xIter);
92 m_xScriptsBox->remove(*xIter);
93 m_xScriptsBox->copy_iterator(*xAltIter, *xIter);
94 }
95 while (bNextEntry);
96 }
97
deleteAllTree()98 void SvxScriptOrgDialog::deleteAllTree()
99 {
100 std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
101 if (!m_xScriptsBox->get_iter_first(*xIter))
102 return;
103
104 std::unique_ptr<weld::TreeIter> xAltIter = m_xScriptsBox->make_iterator();
105 // TBD - below is a candidate for a destroyAllTrees method
106 bool bNextEntry;
107 do
108 {
109 m_xScriptsBox->copy_iterator(*xIter, *xAltIter);
110 bNextEntry = m_xScriptsBox->iter_next_sibling(*xAltIter);
111 deleteTree(*xIter);
112 m_xScriptsBox->remove(*xIter);
113 m_xScriptsBox->copy_iterator(*xAltIter, *xIter);
114 }
115 while (bNextEntry);
116 }
117
Init(std::u16string_view language)118 void SvxScriptOrgDialog::Init( std::u16string_view language )
119 {
120 m_xScriptsBox->freeze();
121
122 deleteAllTree();
123
124 Reference< browse::XBrowseNode > rootNode;
125 Reference< XComponentContext > xCtx(
126 comphelper::getProcessComponentContext() );
127
128 Sequence< Reference< browse::XBrowseNode > > children;
129
130 OUString userStr("user");
131 OUString const shareStr("share");
132
133 try
134 {
135 Reference< browse::XBrowseNodeFactory > xFac = browse::theBrowseNodeFactory::get(xCtx);
136
137 rootNode.set( xFac->createView(
138 browse::BrowseNodeFactoryViewTypes::MACROORGANIZER ) );
139
140 if ( rootNode.is() && rootNode->hasChildNodes() )
141 {
142 children = rootNode->getChildNodes();
143 }
144 }
145 catch( const Exception& )
146 {
147 TOOLS_WARN_EXCEPTION("cui.dialogs", "Exception getting root browse node from factory");
148 // TODO exception handling
149 }
150
151 Reference<XModel> xDocumentModel;
152 for ( const Reference< browse::XBrowseNode >& childNode : std::as_const(children) )
153 {
154 bool app = false;
155 OUString uiName = childNode->getName();
156 OUString factoryURL;
157 if ( uiName == userStr || uiName == shareStr )
158 {
159 app = true;
160 if ( uiName == userStr )
161 {
162 uiName = m_sMyMacros;
163 }
164 else
165 {
166 uiName = m_sProdMacros;
167 }
168 }
169 else
170 {
171 xDocumentModel.set(getDocumentModel(xCtx, uiName ), UNO_QUERY);
172
173 if ( xDocumentModel.is() )
174 {
175 Reference< frame::XModuleManager2 > xModuleManager( frame::ModuleManager::create(xCtx) );
176
177 // get the long name of the document:
178 Sequence<beans::PropertyValue> moduleDescr;
179 try{
180 OUString appModule = xModuleManager->identify( xDocumentModel );
181 xModuleManager->getByName(appModule) >>= moduleDescr;
182 } catch(const uno::Exception&)
183 {}
184
185 for ( const beans::PropertyValue& prop : std::as_const(moduleDescr))
186 {
187 if ( prop.Name == "ooSetupFactoryEmptyDocumentURL" )
188 {
189 prop.Value >>= factoryURL;
190 break;
191 }
192 }
193 }
194 }
195
196 Reference< browse::XBrowseNode > langEntries =
197 getLangNodeFromRootNode( childNode, language );
198
199 insertEntry( uiName, app ? OUString(RID_CUIBMP_HARDDISK) : OUString(RID_CUIBMP_DOC),
200 nullptr, true, std::make_unique< SFEntry >( langEntries, xDocumentModel ), factoryURL, false );
201 }
202
203 m_xScriptsBox->thaw();
204 }
205
206 Reference< XInterface >
getDocumentModel(Reference<XComponentContext> const & xCtx,std::u16string_view docName)207 SvxScriptOrgDialog::getDocumentModel( Reference< XComponentContext > const & xCtx, std::u16string_view docName )
208 {
209 Reference< XInterface > xModel;
210 Reference< frame::XDesktop2 > desktop = frame::Desktop::create(xCtx);
211
212 Reference< container::XEnumerationAccess > componentsAccess =
213 desktop->getComponents();
214 Reference< container::XEnumeration > components =
215 componentsAccess->createEnumeration();
216 while (components->hasMoreElements())
217 {
218 Reference< frame::XModel > model(
219 components->nextElement(), UNO_QUERY );
220 if ( model.is() )
221 {
222 OUString sTdocUrl = ::comphelper::DocumentInfo::getDocumentTitle( model );
223 if( sTdocUrl == docName )
224 {
225 xModel = model;
226 break;
227 }
228 }
229 }
230 return xModel;
231 }
232
233 Reference< browse::XBrowseNode >
getLangNodeFromRootNode(Reference<browse::XBrowseNode> const & rootNode,std::u16string_view language)234 SvxScriptOrgDialog::getLangNodeFromRootNode( Reference< browse::XBrowseNode > const & rootNode, std::u16string_view language )
235 {
236 Reference< browse::XBrowseNode > langNode;
237
238 try
239 {
240 auto tryFind = [&] {
241 const Sequence<Reference<browse::XBrowseNode>> children = rootNode->getChildNodes();
242 const auto it = std::find_if(children.begin(), children.end(),
243 [&](const Reference<browse::XBrowseNode>& child) {
244 return child->getName() == language;
245 });
246 return (it != children.end()) ? *it : nullptr;
247 };
248 {
249 // First try without Java interaction, to avoid warnings for non-JRE-dependent providers
250 css::uno::ContextLayer layer(comphelper::NoEnableJavaInteractionContext());
251 langNode = tryFind();
252 }
253 if (!langNode)
254 {
255 // Now try with Java interaction enabled
256 langNode = tryFind();
257 }
258 }
259 catch ( Exception& )
260 {
261 // if getChildNodes() throws an exception we just return
262 // the empty Reference
263 }
264 return langNode;
265 }
266
RequestSubEntries(const weld::TreeIter & rRootEntry,Reference<css::script::browse::XBrowseNode> const & node,Reference<XModel> & model)267 void SvxScriptOrgDialog::RequestSubEntries(const weld::TreeIter& rRootEntry, Reference< css::script::browse::XBrowseNode > const & node,
268 Reference< XModel >& model)
269 {
270 if (!node.is())
271 {
272 return;
273 }
274
275 Sequence< Reference< browse::XBrowseNode > > children;
276 try
277 {
278 children = node->getChildNodes();
279 }
280 catch ( Exception& )
281 {
282 // if we catch an exception in getChildNodes then no entries are added
283 }
284
285 for ( const Reference< browse::XBrowseNode >& childNode : std::as_const(children) )
286 {
287 OUString name( childNode->getName() );
288 if ( childNode->getType() != browse::BrowseNodeTypes::SCRIPT)
289 {
290 insertEntry(name, RID_CUIBMP_LIB, &rRootEntry, true, std::make_unique<SFEntry>(childNode, model), false);
291 }
292 else
293 {
294 insertEntry(name, RID_CUIBMP_MACRO, &rRootEntry, false, std::make_unique<SFEntry>(childNode, model), false);
295 }
296 }
297 }
298
insertEntry(const OUString & rText,const OUString & rBitmap,const weld::TreeIter * pParent,bool bChildrenOnDemand,std::unique_ptr<SFEntry> && aUserData,const OUString & factoryURL,bool bSelect)299 void SvxScriptOrgDialog::insertEntry(const OUString& rText, const OUString& rBitmap,
300 const weld::TreeIter* pParent, bool bChildrenOnDemand, std::unique_ptr<SFEntry> && aUserData,
301 const OUString& factoryURL, bool bSelect)
302 {
303 if (rBitmap == RID_CUIBMP_DOC && !factoryURL.isEmpty())
304 {
305 OUString aImage = SvFileInformationManager::GetFileImageId(INetURLObject(factoryURL));
306 insertEntry(rText, aImage, pParent, bChildrenOnDemand, std::move(aUserData), bSelect);
307 return;
308 }
309 insertEntry(rText, rBitmap, pParent, bChildrenOnDemand, std::move(aUserData), bSelect);
310 }
311
insertEntry(const OUString & rText,const OUString & rBitmap,const weld::TreeIter * pParent,bool bChildrenOnDemand,std::unique_ptr<SFEntry> && aUserData,bool bSelect)312 void SvxScriptOrgDialog::insertEntry(
313 const OUString& rText, const OUString& rBitmap, const weld::TreeIter* pParent,
314 bool bChildrenOnDemand, std::unique_ptr<SFEntry> && aUserData, bool bSelect)
315 {
316 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aUserData.release()))); // XXX possible leak
317 m_xScriptsBox->insert(pParent, -1, &rText, &sId, nullptr, nullptr,
318 bChildrenOnDemand, m_xScratchIter.get());
319 m_xScriptsBox->set_image(*m_xScratchIter, rBitmap);
320 if (bSelect)
321 {
322 m_xScriptsBox->set_cursor(*m_xScratchIter);
323 m_xScriptsBox->select(*m_xScratchIter);
324 }
325 }
326
IMPL_LINK(SvxScriptOrgDialog,ExpandingHdl,const weld::TreeIter &,rIter,bool)327 IMPL_LINK(SvxScriptOrgDialog, ExpandingHdl, const weld::TreeIter&, rIter, bool)
328 {
329 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rIter).toInt64());
330
331 Reference< browse::XBrowseNode > node;
332 Reference< XModel > model;
333 if ( userData && !userData->isLoaded() )
334 {
335 node = userData->GetNode();
336 model = userData->GetModel();
337 RequestSubEntries(rIter, node, model);
338 userData->setLoaded();
339 }
340
341 return true;
342 }
343
344 // CuiInputDialog ------------------------------------------------------------
CuiInputDialog(weld::Window * pParent,InputDialogMode nMode)345 CuiInputDialog::CuiInputDialog(weld::Window * pParent, InputDialogMode nMode)
346 : GenericDialogController(pParent, "cui/ui/newlibdialog.ui", "NewLibDialog")
347 , m_xEdit(m_xBuilder->weld_entry("entry"))
348 {
349 m_xEdit->grab_focus();
350
351 std::unique_ptr<weld::Label> xNewLibFT(m_xBuilder->weld_label("newlibft"));
352
353 if ( nMode == InputDialogMode::NEWMACRO )
354 {
355 xNewLibFT->hide();
356 std::unique_ptr<weld::Label> xNewMacroFT(m_xBuilder->weld_label("newmacroft"));
357 xNewMacroFT->show();
358 std::unique_ptr<weld::Label> xAltTitle(m_xBuilder->weld_label("altmacrotitle"));
359 m_xDialog->set_title(xAltTitle->get_label());
360 }
361 else if ( nMode == InputDialogMode::RENAME )
362 {
363 xNewLibFT->hide();
364 std::unique_ptr<weld::Label> xRenameFT(m_xBuilder->weld_label("renameft"));
365 xRenameFT->show();
366 std::unique_ptr<weld::Label> xAltTitle(m_xBuilder->weld_label("altrenametitle"));
367 m_xDialog->set_title(xAltTitle->get_label());
368 }
369 }
370
371 // ScriptOrgDialog ------------------------------------------------------------
372
SvxScriptOrgDialog(weld::Window * pParent,const OUString & language)373 SvxScriptOrgDialog::SvxScriptOrgDialog(weld::Window* pParent, const OUString& language)
374 : SfxDialogController(pParent, "cui/ui/scriptorganizer.ui", "ScriptOrganizerDialog")
375 , m_pParent(pParent)
376 , m_sLanguage(language)
377 , m_delErrStr(CuiResId(RID_SVXSTR_DELFAILED))
378 , m_delErrTitleStr(CuiResId(RID_SVXSTR_DELFAILED_TITLE))
379 , m_delQueryStr(CuiResId(RID_SVXSTR_DELQUERY))
380 , m_delQueryTitleStr(CuiResId(RID_SVXSTR_DELQUERY_TITLE))
381 , m_createErrStr(CuiResId(RID_SVXSTR_CREATEFAILED))
382 , m_createDupStr(CuiResId(RID_SVXSTR_CREATEFAILEDDUP))
383 , m_createErrTitleStr(CuiResId(RID_SVXSTR_CREATEFAILED_TITLE))
384 , m_renameErrStr(CuiResId(RID_SVXSTR_RENAMEFAILED))
385 , m_renameErrTitleStr(CuiResId(RID_SVXSTR_RENAMEFAILED_TITLE))
386 , m_sMyMacros(CuiResId(RID_SVXSTR_MYMACROS))
387 , m_sProdMacros(CuiResId(RID_SVXSTR_PRODMACROS))
388 , m_xScriptsBox(m_xBuilder->weld_tree_view("scripts"))
389 , m_xScratchIter(m_xScriptsBox->make_iterator())
390 , m_xRunButton(m_xBuilder->weld_button("ok"))
391 , m_xCloseButton(m_xBuilder->weld_button("close"))
392 , m_xCreateButton(m_xBuilder->weld_button("create"))
393 , m_xEditButton(m_xBuilder->weld_button("edit"))
394 , m_xRenameButton(m_xBuilder->weld_button("rename"))
395 , m_xDelButton(m_xBuilder->weld_button("delete"))
396 {
397 // must be a neater way to deal with the strings than as above
398 // append the language to the dialog title
399 OUString winTitle(m_xDialog->get_title());
400 winTitle = winTitle.replaceFirst( "%MACROLANG", m_sLanguage );
401 m_xDialog->set_title(winTitle);
402
403 m_xScriptsBox->set_size_request(m_xScriptsBox->get_approximate_digit_width() * 45,
404 m_xScriptsBox->get_height_rows(12));
405
406 m_xScriptsBox->connect_changed( LINK( this, SvxScriptOrgDialog, ScriptSelectHdl ) );
407 m_xScriptsBox->connect_expanding(LINK( this, SvxScriptOrgDialog, ExpandingHdl ) );
408 m_xRunButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
409 m_xCloseButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
410 m_xRenameButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
411 m_xEditButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
412 m_xDelButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
413 m_xCreateButton->connect_clicked( LINK( this, SvxScriptOrgDialog, ButtonHdl ) );
414
415 m_xRunButton->set_sensitive(false);
416 m_xRenameButton->set_sensitive(false);
417 m_xEditButton->set_sensitive(false);
418 m_xDelButton->set_sensitive(false);
419 m_xCreateButton->set_sensitive(false);
420
421 Init(m_sLanguage);
422 RestorePreviousSelection();
423 }
424
~SvxScriptOrgDialog()425 SvxScriptOrgDialog::~SvxScriptOrgDialog()
426 {
427 deleteAllTree();
428 }
429
run()430 short SvxScriptOrgDialog::run()
431 {
432 SfxObjectShell *pDoc = SfxObjectShell::GetFirst();
433
434 // force load of MSPs for all documents
435 while ( pDoc )
436 {
437 Reference< provider::XScriptProviderSupplier > xSPS( pDoc->GetModel(), UNO_QUERY );
438 if ( xSPS.is() )
439 {
440 xSPS->getScriptProvider();
441 }
442
443 pDoc = SfxObjectShell::GetNext(*pDoc);
444 }
445
446 return SfxDialogController::run();
447 }
448
CheckButtons(Reference<browse::XBrowseNode> const & node)449 void SvxScriptOrgDialog::CheckButtons( Reference< browse::XBrowseNode > const & node )
450 {
451 if ( node.is() )
452 {
453 if ( node->getType() == browse::BrowseNodeTypes::SCRIPT)
454 {
455 m_xRunButton->set_sensitive(true);
456 }
457 else
458 {
459 m_xRunButton->set_sensitive(false);
460 }
461 Reference< beans::XPropertySet > xProps( node, UNO_QUERY );
462
463 if ( !xProps.is() )
464 {
465 m_xEditButton->set_sensitive(false);
466 m_xDelButton->set_sensitive(false);
467 m_xCreateButton->set_sensitive(false);
468 m_xRunButton->set_sensitive(false);
469 return;
470 }
471
472 OUString sName("Editable");
473
474 if ( getBoolProperty( xProps, sName ) )
475 {
476 m_xEditButton->set_sensitive(true);
477 }
478 else
479 {
480 m_xEditButton->set_sensitive(false);
481 }
482
483 sName = "Deletable";
484
485 if ( getBoolProperty( xProps, sName ) )
486 {
487 m_xDelButton->set_sensitive(true);
488 }
489 else
490 {
491 m_xDelButton->set_sensitive(false);
492 }
493
494 sName = "Creatable";
495
496 if ( getBoolProperty( xProps, sName ) )
497 {
498 m_xCreateButton->set_sensitive(true);
499 }
500 else
501 {
502 m_xCreateButton->set_sensitive(false);
503 }
504
505 sName = "Renamable";
506
507 if ( getBoolProperty( xProps, sName ) )
508 {
509 m_xRenameButton->set_sensitive(true);
510 }
511 else
512 {
513 m_xRenameButton->set_sensitive(false);
514 }
515 }
516 else
517 {
518 // no node info available, disable all configurable actions
519 m_xDelButton->set_sensitive(false);
520 m_xCreateButton->set_sensitive(false);
521 m_xEditButton->set_sensitive(false);
522 m_xRunButton->set_sensitive(false);
523 m_xRenameButton->set_sensitive(false);
524 }
525 }
526
IMPL_LINK_NOARG(SvxScriptOrgDialog,ScriptSelectHdl,weld::TreeView &,void)527 IMPL_LINK_NOARG(SvxScriptOrgDialog, ScriptSelectHdl, weld::TreeView&, void)
528 {
529 std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
530 if (!m_xScriptsBox->get_selected(xIter.get()))
531 return;
532
533 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(*xIter).toInt64());
534
535 Reference< browse::XBrowseNode > node;
536 if (userData)
537 {
538 node = userData->GetNode();
539 CheckButtons(node);
540 }
541 }
542
IMPL_LINK(SvxScriptOrgDialog,ButtonHdl,weld::Button &,rButton,void)543 IMPL_LINK(SvxScriptOrgDialog, ButtonHdl, weld::Button&, rButton, void)
544 {
545 if ( &rButton == m_xCloseButton.get() )
546 {
547 StoreCurrentSelection();
548 m_xDialog->response(RET_CANCEL);
549 }
550 if (!(&rButton == m_xEditButton.get() ||
551 &rButton == m_xCreateButton.get() ||
552 &rButton == m_xDelButton.get() ||
553 &rButton == m_xRunButton.get() ||
554 &rButton == m_xRenameButton.get()))
555
556 return;
557
558 std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
559 if (!m_xScriptsBox->get_selected(xIter.get()))
560 return;
561 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(*xIter).toInt64());
562 if (!userData)
563 return;
564
565 Reference< browse::XBrowseNode > node;
566 Reference< XModel > xModel;
567
568 node = userData->GetNode();
569 xModel = userData->GetModel();
570
571 if ( !node.is() )
572 {
573 return;
574 }
575
576 if (&rButton == m_xRunButton.get())
577 {
578 OUString tmpString;
579 Reference< beans::XPropertySet > xProp( node, UNO_QUERY );
580 Reference< provider::XScriptProvider > mspNode;
581 if( !xProp.is() )
582 {
583 return;
584 }
585
586 if ( xModel.is() )
587 {
588 Reference< XEmbeddedScripts > xEmbeddedScripts( xModel, UNO_QUERY);
589 if( !xEmbeddedScripts.is() )
590 {
591 return;
592 }
593
594 if (!xEmbeddedScripts->getAllowMacroExecution())
595 {
596 // Please FIXME: Show a message box if AllowMacroExecution is false
597 return;
598 }
599 }
600
601 std::unique_ptr<weld::TreeIter> xParentIter = m_xScriptsBox->make_iterator(xIter.get());
602 bool bParent = m_xScriptsBox->iter_parent(*xParentIter);
603 while (bParent && !mspNode.is() )
604 {
605 SFEntry* mspUserData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(*xParentIter).toInt64());
606 mspNode.set( mspUserData->GetNode() , UNO_QUERY );
607 bParent = m_xScriptsBox->iter_parent(*xParentIter);
608 }
609 xProp->getPropertyValue("URI") >>= tmpString;
610 const OUString scriptURL( tmpString );
611
612 if ( mspNode.is() )
613 {
614 try
615 {
616 Reference< provider::XScript > xScript(
617 mspNode->getScript( scriptURL ), UNO_SET_THROW );
618
619 const Sequence< Any > args(0);
620 Sequence< sal_Int16 > outIndex;
621 Sequence< Any > outArgs( 0 );
622 xScript->invoke( args, outIndex, outArgs );
623 }
624 catch ( reflection::InvocationTargetException& ite )
625 {
626 SvxScriptErrorDialog::ShowAsyncErrorDialog(m_pParent, css::uno::Any(ite));
627 }
628 catch ( provider::ScriptFrameworkErrorException& ite )
629 {
630 SvxScriptErrorDialog::ShowAsyncErrorDialog(m_pParent, css::uno::Any(ite));
631 }
632 catch ( RuntimeException& re )
633 {
634 SvxScriptErrorDialog::ShowAsyncErrorDialog(m_pParent, css::uno::Any(re));
635 }
636 catch ( Exception& e )
637 {
638 SvxScriptErrorDialog::ShowAsyncErrorDialog(m_pParent, css::uno::Any(e));
639 }
640 }
641 StoreCurrentSelection();
642 m_xDialog->response(RET_CANCEL);
643 }
644 else if ( &rButton == m_xEditButton.get() )
645 {
646 Reference< script::XInvocation > xInv( node, UNO_QUERY );
647 if ( xInv.is() )
648 {
649 StoreCurrentSelection();
650 m_xDialog->response(RET_CANCEL);
651 Sequence< Any > args(0);
652 Sequence< Any > outArgs( 0 );
653 Sequence< sal_Int16 > outIndex;
654 try
655 {
656 // ISSUE need code to run script here
657 xInv->invoke( "Editable", args, outIndex, outArgs );
658 }
659 catch( Exception const & )
660 {
661 TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to invoke" );
662 }
663 }
664 }
665 else if ( &rButton == m_xCreateButton.get() )
666 {
667 createEntry(*xIter);
668 }
669 else if ( &rButton == m_xDelButton.get() )
670 {
671 deleteEntry(*xIter);
672 }
673 else if ( &rButton == m_xRenameButton.get() )
674 {
675 renameEntry(*xIter);
676 }
677 }
678
getBrowseNode(const weld::TreeIter & rEntry)679 Reference< browse::XBrowseNode > SvxScriptOrgDialog::getBrowseNode(const weld::TreeIter& rEntry)
680 {
681 Reference< browse::XBrowseNode > node;
682 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rEntry).toInt64());
683 if (userData)
684 {
685 node = userData->GetNode();
686 }
687 return node;
688 }
689
getModel(const weld::TreeIter & rEntry)690 Reference< XModel > SvxScriptOrgDialog::getModel(const weld::TreeIter& rEntry)
691 {
692 Reference< XModel > model;
693 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rEntry).toInt64());
694 if ( userData )
695 {
696 model = userData->GetModel();
697 }
698 return model;
699 }
700
createEntry(weld::TreeIter & rEntry)701 void SvxScriptOrgDialog::createEntry(weld::TreeIter& rEntry)
702 {
703
704 Reference< browse::XBrowseNode > aChildNode;
705 Reference< browse::XBrowseNode > node = getBrowseNode( rEntry );
706 Reference< script::XInvocation > xInv( node, UNO_QUERY );
707
708 if ( xInv.is() )
709 {
710 OUString aNewName;
711 OUString aNewStdName;
712 InputDialogMode nMode = InputDialogMode::NEWLIB;
713 if (m_xScriptsBox->get_iter_depth(rEntry) == 0)
714 {
715 aNewStdName = "Library" ;
716 }
717 else
718 {
719 aNewStdName = "Macro" ;
720 nMode = InputDialogMode::NEWMACRO;
721 }
722 //do we need L10N for this? ie something like:
723 //String aNewStdName( ResId( STR_STDMODULENAME ) );
724 bool bValid = false;
725 sal_Int32 i = 1;
726
727 Sequence< Reference< browse::XBrowseNode > > childNodes;
728 // no children => ok to create Parcel1 or Script1 without checking
729 try
730 {
731 if( !node->hasChildNodes() )
732 {
733 aNewName = aNewStdName + OUString::number(i);
734 bValid = true;
735 }
736 else
737 {
738 childNodes = node->getChildNodes();
739 }
740 }
741 catch ( Exception& )
742 {
743 // ignore, will continue on with empty sequence
744 }
745
746 OUString extn;
747 while ( !bValid )
748 {
749 aNewName = aNewStdName + OUString::number(i);
750 bool bFound = false;
751 if(childNodes.hasElements() )
752 {
753 OUString nodeName = childNodes[0]->getName();
754 sal_Int32 extnPos = nodeName.lastIndexOf( '.' );
755 if(extnPos>0)
756 extn = nodeName.copy(extnPos);
757 }
758 for( const Reference< browse::XBrowseNode >& n : std::as_const(childNodes) )
759 {
760 if (aNewName+extn == n->getName())
761 {
762 bFound = true;
763 break;
764 }
765 }
766 if( bFound )
767 {
768 i++;
769 }
770 else
771 {
772 bValid = true;
773 }
774 }
775
776 CuiInputDialog aNewDlg(m_xDialog.get(), nMode);
777 aNewDlg.SetObjectName(aNewName);
778
779 do
780 {
781 if (aNewDlg.run() && !aNewDlg.GetObjectName().isEmpty())
782 {
783 OUString aUserSuppliedName = aNewDlg.GetObjectName();
784 bValid = true;
785 for( const Reference< browse::XBrowseNode >& n : std::as_const(childNodes) )
786 {
787 if (aUserSuppliedName+extn == n->getName())
788 {
789 bValid = false;
790 OUString aError = m_createErrStr + m_createDupStr;
791
792 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
793 VclMessageType::Warning, VclButtonsType::Ok, aError));
794 xErrorBox->set_title(m_createErrTitleStr);
795 xErrorBox->run();
796 aNewDlg.SetObjectName(aNewName);
797 break;
798 }
799 }
800 if( bValid )
801 aNewName = aUserSuppliedName;
802 }
803 else
804 {
805 // user hit cancel or hit OK with nothing in the editbox
806
807 return;
808 }
809 }
810 while ( !bValid );
811
812 // open up parent node (which ensures it's loaded)
813 m_xScriptsBox->expand_row(rEntry);
814
815 Sequence< Any > args( 1 );
816 args[ 0 ] <<= aNewName;
817 Sequence< Any > outArgs( 0 );
818 Sequence< sal_Int16 > outIndex;
819 try
820 {
821 Any aResult = xInv->invoke( "Creatable", args, outIndex, outArgs );
822 Reference< browse::XBrowseNode > newNode( aResult, UNO_QUERY );
823 aChildNode = newNode;
824
825 }
826 catch( Exception const & )
827 {
828 TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to Create" );
829 }
830 }
831 if ( aChildNode.is() )
832 {
833 OUString aChildName = aChildNode->getName();
834
835 Reference<XModel> xDocumentModel = getModel( rEntry );
836
837 // ISSUE do we need to remove all entries for parent
838 // to achieve sort? Just need to determine position
839 // -- Basic doesn't do this on create.
840 // Suppose we could avoid this too. -> created nodes are
841 // not in alphabetical order
842 if ( aChildNode->getType() == browse::BrowseNodeTypes::SCRIPT )
843 {
844 insertEntry(aChildName, RID_CUIBMP_MACRO, &rEntry, false,
845 std::make_unique<SFEntry>(aChildNode,xDocumentModel), true);
846 }
847 else
848 {
849 insertEntry(aChildName, RID_CUIBMP_LIB, &rEntry, false,
850 std::make_unique<SFEntry>(aChildNode,xDocumentModel), true);
851
852 // If the Parent is not loaded then set to
853 // loaded, this will prevent RequestingChildren ( called
854 // from vcl via RequestingChildren ) from
855 // creating new ( duplicate ) children
856 SFEntry* userData = reinterpret_cast<SFEntry*>(m_xScriptsBox->get_id(rEntry).toInt64());
857 if ( userData && !userData->isLoaded() )
858 {
859 userData->setLoaded();
860 }
861 }
862 }
863 else
864 {
865 //ISSUE L10N & message from exception?
866 OUString aError( m_createErrStr );
867 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
868 VclMessageType::Warning, VclButtonsType::Ok, aError));
869 xErrorBox->set_title(m_createErrTitleStr);
870 xErrorBox->run();
871 }
872 }
873
renameEntry(const weld::TreeIter & rEntry)874 void SvxScriptOrgDialog::renameEntry(const weld::TreeIter& rEntry)
875 {
876
877 Reference< browse::XBrowseNode > aChildNode;
878 Reference< browse::XBrowseNode > node = getBrowseNode(rEntry);
879 Reference< script::XInvocation > xInv( node, UNO_QUERY );
880
881 if ( xInv.is() )
882 {
883 OUString aNewName = node->getName();
884 sal_Int32 extnPos = aNewName.lastIndexOf( '.' );
885 if(extnPos>0)
886 {
887 aNewName = aNewName.copy(0,extnPos);
888 }
889 CuiInputDialog aNewDlg(m_xDialog.get(), InputDialogMode::RENAME);
890 aNewDlg.SetObjectName(aNewName);
891
892 if (!aNewDlg.run() || aNewDlg.GetObjectName().isEmpty())
893 return; // user hit cancel or hit OK with nothing in the editbox
894
895 aNewName = aNewDlg.GetObjectName();
896
897 Sequence< Any > args( 1 );
898 args[ 0 ] <<= aNewName;
899 Sequence< Any > outArgs( 0 );
900 Sequence< sal_Int16 > outIndex;
901 try
902 {
903 Any aResult = xInv->invoke( "Renamable", args, outIndex, outArgs );
904 Reference< browse::XBrowseNode > newNode( aResult, UNO_QUERY );
905 aChildNode = newNode;
906
907 }
908 catch( Exception const & )
909 {
910 TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to Rename" );
911 }
912 }
913 if ( aChildNode.is() )
914 {
915 m_xScriptsBox->set_text(rEntry, aChildNode->getName());
916 m_xScriptsBox->set_cursor(rEntry);
917 m_xScriptsBox->select(rEntry);
918
919 }
920 else
921 {
922 //ISSUE L10N & message from exception?
923 OUString aError( m_renameErrStr );
924 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
925 VclMessageType::Warning, VclButtonsType::Ok, aError));
926 xErrorBox->set_title(m_renameErrTitleStr);
927 xErrorBox->run();
928 }
929 }
930
deleteEntry(weld::TreeIter & rEntry)931 void SvxScriptOrgDialog::deleteEntry(weld::TreeIter& rEntry)
932 {
933 bool result = false;
934 Reference< browse::XBrowseNode > node = getBrowseNode(rEntry);
935 // ISSUE L10N string & can we center list?
936 OUString aQuery = m_delQueryStr + getListOfChildren( node, 0 );
937 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_xDialog.get(),
938 VclMessageType::Question, VclButtonsType::YesNo, aQuery));
939 xQueryBox->set_title(m_delQueryTitleStr);
940 if (xQueryBox->run() == RET_NO)
941 {
942 return;
943 }
944
945 Reference< script::XInvocation > xInv( node, UNO_QUERY );
946 if ( xInv.is() )
947 {
948 Sequence< Any > args( 0 );
949 Sequence< Any > outArgs( 0 );
950 Sequence< sal_Int16 > outIndex;
951 try
952 {
953 Any aResult = xInv->invoke( "Deletable", args, outIndex, outArgs );
954 aResult >>= result; // or do we just assume true if no exception ?
955 }
956 catch( Exception const & )
957 {
958 TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to delete" );
959 }
960 }
961
962 if ( result )
963 {
964 deleteTree(rEntry);
965 m_xScriptsBox->remove(rEntry);
966 }
967 else
968 {
969 //ISSUE L10N & message from exception?
970 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
971 VclMessageType::Warning, VclButtonsType::Ok, m_delErrStr));
972 xErrorBox->set_title(m_delErrTitleStr);
973 xErrorBox->run();
974 }
975
976 }
977
getBoolProperty(Reference<beans::XPropertySet> const & xProps,OUString const & propName)978 bool SvxScriptOrgDialog::getBoolProperty( Reference< beans::XPropertySet > const & xProps,
979 OUString const & propName )
980 {
981 bool result = false;
982 try
983 {
984 xProps->getPropertyValue( propName ) >>= result;
985 }
986 catch ( Exception& )
987 {
988 return result;
989 }
990 return result;
991 }
992
getListOfChildren(const Reference<browse::XBrowseNode> & node,int depth)993 OUString SvxScriptOrgDialog::getListOfChildren( const Reference< browse::XBrowseNode >& node, int depth )
994 {
995 OUStringBuffer result = "\n";
996 for( int i=0;i<=depth;i++ )
997 {
998 result.append("\t");
999 }
1000 result.append(node->getName());
1001
1002 try
1003 {
1004 if ( node->hasChildNodes() )
1005 {
1006 const Sequence< Reference< browse::XBrowseNode > > children
1007 = node->getChildNodes();
1008 for( const Reference< browse::XBrowseNode >& n : children )
1009 {
1010 result.append( getListOfChildren( n , depth+1 ) );
1011 }
1012 }
1013 }
1014 catch ( Exception& )
1015 {
1016 // ignore, will return an empty string
1017 }
1018
1019 return result.makeStringAndClear();
1020 }
1021
1022 Selection_hash SvxScriptOrgDialog::m_lastSelection;
1023
StoreCurrentSelection()1024 void SvxScriptOrgDialog::StoreCurrentSelection()
1025 {
1026 std::unique_ptr<weld::TreeIter> xIter = m_xScriptsBox->make_iterator();
1027 if (!m_xScriptsBox->get_selected(xIter.get()))
1028 return;
1029 OUString aDescription;
1030 bool bEntry;
1031 do
1032 {
1033 aDescription = m_xScriptsBox->get_text(*xIter) + aDescription;
1034 bEntry = m_xScriptsBox->iter_parent(*xIter);
1035 if (bEntry)
1036 aDescription = ";" + aDescription;
1037 }
1038 while (bEntry);
1039 OUString sDesc( aDescription );
1040 m_lastSelection[ m_sLanguage ] = sDesc;
1041 }
1042
RestorePreviousSelection()1043 void SvxScriptOrgDialog::RestorePreviousSelection()
1044 {
1045 OUString aStoredEntry = m_lastSelection[ m_sLanguage ];
1046 if( aStoredEntry.isEmpty() )
1047 return;
1048 std::unique_ptr<weld::TreeIter> xEntry;
1049 std::unique_ptr<weld::TreeIter> xTmpEntry(m_xScriptsBox->make_iterator());
1050 sal_Int32 nIndex = 0;
1051 while (nIndex != -1)
1052 {
1053 OUString aTmp( aStoredEntry.getToken( 0, ';', nIndex ) );
1054
1055 bool bTmpEntry;
1056 if (!xEntry)
1057 {
1058 xEntry = m_xScriptsBox->make_iterator();
1059 bTmpEntry = m_xScriptsBox->get_iter_first(*xEntry);
1060 m_xScriptsBox->copy_iterator(*xEntry, *xTmpEntry);
1061 }
1062 else
1063 {
1064 m_xScriptsBox->copy_iterator(*xEntry, *xTmpEntry);
1065 bTmpEntry = m_xScriptsBox->iter_children(*xTmpEntry);
1066 }
1067
1068 while (bTmpEntry)
1069 {
1070 if (m_xScriptsBox->get_text(*xTmpEntry) == aTmp)
1071 {
1072 m_xScriptsBox->copy_iterator(*xTmpEntry, *xEntry);
1073 break;
1074 }
1075 bTmpEntry = m_xScriptsBox->iter_next_sibling(*xTmpEntry);
1076 }
1077
1078 if (!bTmpEntry)
1079 break;
1080
1081 m_xScriptsBox->expand_row(*xEntry);
1082 }
1083
1084 if (xEntry)
1085 {
1086 m_xScriptsBox->set_cursor(*xEntry);
1087 ScriptSelectHdl(*m_xScriptsBox);
1088 }
1089 }
1090
1091 namespace {
1092
ReplaceString(const OUString & source,const OUString & token,const OUString & value)1093 OUString ReplaceString(
1094 const OUString& source,
1095 const OUString& token,
1096 const OUString& value )
1097 {
1098 sal_Int32 pos = source.indexOf( token );
1099
1100 if ( pos != -1 && !value.isEmpty() )
1101 {
1102 return source.replaceAt( pos, token.getLength(), value );
1103 }
1104 else
1105 {
1106 return source;
1107 }
1108 }
1109
FormatErrorString(const OUString & unformatted,const OUString & language,const OUString & script,const OUString & line,std::u16string_view type,std::u16string_view message)1110 OUString FormatErrorString(
1111 const OUString& unformatted,
1112 const OUString& language,
1113 const OUString& script,
1114 const OUString& line,
1115 std::u16string_view type,
1116 std::u16string_view message )
1117 {
1118 OUString result = unformatted.copy( 0 );
1119
1120 result = ReplaceString(result, "%LANGUAGENAME", language );
1121 result = ReplaceString(result, "%SCRIPTNAME", script );
1122 result = ReplaceString(result, "%LINENUMBER", line );
1123
1124 if ( !type.empty() )
1125 {
1126 result += "\n\n" + CuiResId(RID_SVXSTR_ERROR_TYPE_LABEL) + " " + type;
1127 }
1128
1129 if ( !message.empty() )
1130 {
1131 result += "\n\n" + CuiResId(RID_SVXSTR_ERROR_MESSAGE_LABEL) + " " + message;
1132 }
1133
1134 return result;
1135 }
1136
GetErrorMessage(const provider::ScriptErrorRaisedException & eScriptError)1137 OUString GetErrorMessage(
1138 const provider::ScriptErrorRaisedException& eScriptError )
1139 {
1140 OUString unformatted = CuiResId( RID_SVXSTR_ERROR_AT_LINE );
1141
1142 OUString unknown("UNKNOWN");
1143 OUString language = unknown;
1144 OUString script = unknown;
1145 OUString line = unknown;
1146 OUString message = eScriptError.Message;
1147
1148 if ( !eScriptError.language.isEmpty() )
1149 {
1150 language = eScriptError.language;
1151 }
1152
1153 if ( !eScriptError.scriptName.isEmpty() )
1154 {
1155 script = eScriptError.scriptName;
1156 }
1157
1158 if ( !eScriptError.Message.isEmpty() )
1159 {
1160 message = eScriptError.Message;
1161 }
1162 if ( eScriptError.lineNum != -1 )
1163 {
1164 line = OUString::number( eScriptError.lineNum );
1165 unformatted = CuiResId( RID_SVXSTR_ERROR_AT_LINE );
1166 }
1167 else
1168 {
1169 unformatted = CuiResId( RID_SVXSTR_ERROR_RUNNING );
1170 }
1171
1172 return FormatErrorString(
1173 unformatted, language, script, line, u"", message );
1174 }
1175
GetErrorMessage(const provider::ScriptExceptionRaisedException & eScriptException)1176 OUString GetErrorMessage(
1177 const provider::ScriptExceptionRaisedException& eScriptException )
1178 {
1179 OUString unformatted = CuiResId( RID_SVXSTR_EXCEPTION_AT_LINE );
1180
1181 OUString unknown("UNKNOWN");
1182 OUString language = unknown;
1183 OUString script = unknown;
1184 OUString line = unknown;
1185 OUString type = unknown;
1186 OUString message = eScriptException.Message;
1187
1188 if ( !eScriptException.language.isEmpty() )
1189 {
1190 language = eScriptException.language;
1191 }
1192 if ( !eScriptException.scriptName.isEmpty() )
1193 {
1194 script = eScriptException.scriptName;
1195 }
1196
1197 if ( !eScriptException.Message.isEmpty() )
1198 {
1199 message = eScriptException.Message;
1200 }
1201
1202 if ( eScriptException.lineNum != -1 )
1203 {
1204 line = OUString::number( eScriptException.lineNum );
1205 unformatted = CuiResId( RID_SVXSTR_EXCEPTION_AT_LINE );
1206 }
1207 else
1208 {
1209 unformatted = CuiResId( RID_SVXSTR_EXCEPTION_RUNNING );
1210 }
1211
1212 if ( !eScriptException.exceptionType.isEmpty() )
1213 {
1214 type = eScriptException.exceptionType;
1215 }
1216
1217 return FormatErrorString(
1218 unformatted, language, script, line, type, message );
1219
1220 }
GetErrorMessage(const provider::ScriptFrameworkErrorException & sError)1221 OUString GetErrorMessage(
1222 const provider::ScriptFrameworkErrorException& sError )
1223 {
1224 OUString unformatted = CuiResId( RID_SVXSTR_FRAMEWORK_ERROR_RUNNING );
1225
1226 OUString language("UNKNOWN");
1227
1228 OUString script("UNKNOWN");
1229
1230 OUString message;
1231
1232 if ( !sError.scriptName.isEmpty() )
1233 {
1234 script = sError.scriptName;
1235 }
1236 if ( !sError.language.isEmpty() )
1237 {
1238 language = sError.language;
1239 }
1240 if ( sError.errorType == provider::ScriptFrameworkErrorType::NOTSUPPORTED )
1241 {
1242 message =
1243 CuiResId( RID_SVXSTR_ERROR_LANG_NOT_SUPPORTED );
1244 message = ReplaceString(message, "%LANGUAGENAME", language );
1245
1246 }
1247 else
1248 {
1249 message = sError.Message;
1250 }
1251 return FormatErrorString(
1252 unformatted, language, script, OUString(), std::u16string_view(), message );
1253 }
1254
GetErrorMessage(const css::uno::Any & aException)1255 OUString GetErrorMessage( const css::uno::Any& aException )
1256 {
1257 if ( aException.getValueType() ==
1258 cppu::UnoType<reflection::InvocationTargetException>::get())
1259 {
1260 reflection::InvocationTargetException ite;
1261 aException >>= ite;
1262 if ( ite.TargetException.getValueType() == cppu::UnoType<provider::ScriptErrorRaisedException>::get())
1263 {
1264 // Error raised by script
1265 provider::ScriptErrorRaisedException scriptError;
1266 ite.TargetException >>= scriptError;
1267 return GetErrorMessage( scriptError );
1268 }
1269 else if ( ite.TargetException.getValueType() == cppu::UnoType<provider::ScriptExceptionRaisedException>::get())
1270 {
1271 // Exception raised by script
1272 provider::ScriptExceptionRaisedException scriptException;
1273 ite.TargetException >>= scriptException;
1274 return GetErrorMessage( scriptException );
1275 }
1276 else
1277 {
1278 // Unknown error, shouldn't happen
1279 // OSL_ASSERT(...)
1280 }
1281
1282 }
1283 else if ( aException.getValueType() == cppu::UnoType<provider::ScriptFrameworkErrorException>::get())
1284 {
1285 // A Script Framework error has occurred
1286 provider::ScriptFrameworkErrorException sfe;
1287 aException >>= sfe;
1288 return GetErrorMessage( sfe );
1289
1290 }
1291 // unknown exception
1292 auto msg = aException.getValueTypeName();
1293 Exception e;
1294 if ( (aException >>= e) && !e.Message.isEmpty() )
1295 {
1296 msg += ": " + e.Message;
1297 }
1298 return msg;
1299 }
1300
1301 }
1302
1303 // Show Error dialog asynchronously
ShowAsyncErrorDialog(weld::Window * pParent,css::uno::Any const & aException)1304 void SvxScriptErrorDialog::ShowAsyncErrorDialog( weld::Window* pParent, css::uno::Any const & aException )
1305 {
1306 SolarMutexGuard aGuard;
1307 OUString sMessage = GetErrorMessage( aException );
1308
1309 // Pass a copy of the message to the ShowDialog method as the
1310 // SvxScriptErrorDialog may be deleted before ShowDialog is called
1311 DialogData* pData = new DialogData;
1312 pData->sMessage = sMessage;
1313 pData->pParent = pParent;
1314 Application::PostUserEvent(
1315 LINK( nullptr, SvxScriptErrorDialog, ShowDialog ),
1316 pData );
1317 }
1318
IMPL_STATIC_LINK(SvxScriptErrorDialog,ShowDialog,void *,p,void)1319 IMPL_STATIC_LINK( SvxScriptErrorDialog, ShowDialog, void*, p, void )
1320 {
1321 std::unique_ptr<DialogData> xData(static_cast<DialogData*>(p));
1322 OUString message = xData->sMessage;
1323
1324 if ( message.isEmpty() )
1325 message = CuiResId( RID_SVXSTR_ERROR_TITLE );
1326
1327 std::shared_ptr<weld::MessageDialog> xBox;
1328 xBox.reset(Application::CreateMessageDialog(
1329 xData->pParent,
1330 VclMessageType::Warning,
1331 VclButtonsType::Ok,
1332 message,
1333 comphelper::LibreOfficeKit::isActive()));
1334
1335 xBox->set_title(CuiResId(RID_SVXSTR_ERROR_TITLE));
1336
1337 xBox->runAsync(xBox, [](sal_Int32 /*nResult*/) {});
1338 }
1339
1340 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1341