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