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