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 <cfgutil.hxx> 21 #include <cfg.hxx> 22 23 #include <com/sun/star/beans/XPropertySet.hpp> 24 #include <com/sun/star/container/XEnumerationAccess.hpp> 25 #include <com/sun/star/container/XEnumeration.hpp> 26 #include <com/sun/star/document/XScriptInvocationContext.hpp> 27 #include <com/sun/star/frame/ModuleManager.hpp> 28 #include <com/sun/star/frame/Desktop.hpp> 29 #include <com/sun/star/frame/theUICommandDescription.hpp> 30 #include <com/sun/star/frame/XDispatchInformationProvider.hpp> 31 #include <com/sun/star/script/browse/XBrowseNode.hpp> 32 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp> 33 #include <com/sun/star/script/browse/theBrowseNodeFactory.hpp> 34 #include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp> 35 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> 36 #include <com/sun/star/uno/RuntimeException.hpp> 37 #include <com/sun/star/ui/theUICategoryDescription.hpp> 38 39 #include <basic/sbx.hxx> 40 #include <basic/basicmanagerrepository.hxx> 41 #include <basic/sbstar.hxx> 42 #include <basic/sbxmeth.hxx> 43 #include <basic/sbmod.hxx> 44 #include <basic/basmgr.hxx> 45 #include <tools/urlobj.hxx> 46 #include <strings.hrc> 47 #include <bitmaps.hlst> 48 #include <sfx2/app.hxx> 49 #include <sfx2/minfitem.hxx> 50 #include <comphelper/DisableInteractionHelper.hxx> 51 #include <comphelper/documentinfo.hxx> 52 #include <comphelper/processfactory.hxx> 53 #include <comphelper/sequenceashashmap.hxx> 54 #include <comphelper/string.hxx> 55 #include <svtools/imagemgr.hxx> 56 #include <svtools/treelistentry.hxx> 57 #include <rtl/ustrbuf.hxx> 58 #include <sal/log.hxx> 59 #include <unotools/configmgr.hxx> 60 #include <dialmgr.hxx> 61 #include <svl/stritem.hxx> 62 #include <vcl/builderfactory.hxx> 63 #include <vcl/button.hxx> 64 #include <vcl/commandinfoprovider.hxx> 65 #include <vcl/fixed.hxx> 66 #include <vcl/help.hxx> 67 #include <vcl/vclmedit.hxx> 68 #include <o3tl/make_unique.hxx> 69 70 using namespace ::com::sun::star; 71 using namespace ::com::sun::star::uno; 72 using namespace ::com::sun::star::script; 73 using namespace ::com::sun::star::frame; 74 using namespace ::com::sun::star::document; 75 76 SfxStylesInfo_Impl::SfxStylesInfo_Impl() 77 {} 78 79 void SfxStylesInfo_Impl::init(const OUString& rModuleName, const css::uno::Reference< css::frame::XModel >& xModel) 80 { 81 m_aModuleName = rModuleName; 82 m_xDoc = xModel; 83 } 84 85 static const char CMDURL_STYLEPROT_ONLY[] = ".uno:StyleApply?"; 86 static const char CMDURL_SPART_ONLY [] = "Style:string="; 87 static const char CMDURL_FPART_ONLY [] = "FamilyName:string="; 88 89 static const char STYLEPROP_UINAME[] = "DisplayName"; 90 91 OUString SfxStylesInfo_Impl::generateCommand(const OUString& sFamily, const OUString& sStyle) 92 { 93 return ".uno:StyleApply?Style:string=" 94 + sStyle 95 + "&FamilyName:string=" 96 + sFamily; 97 } 98 99 bool SfxStylesInfo_Impl::parseStyleCommand(SfxStyleInfo_Impl& aStyle) 100 { 101 static const sal_Int32 LEN_STYLEPROT = strlen(CMDURL_STYLEPROT_ONLY); 102 static const sal_Int32 LEN_SPART = strlen(CMDURL_SPART_ONLY); 103 static const sal_Int32 LEN_FPART = strlen(CMDURL_FPART_ONLY); 104 105 if (!aStyle.sCommand.startsWith(CMDURL_STYLEPROT_ONLY)) 106 return false; 107 108 aStyle.sFamily.clear(); 109 aStyle.sStyle.clear(); 110 111 sal_Int32 nCmdLen = aStyle.sCommand.getLength(); 112 OUString sCmdArgs = aStyle.sCommand.copy(LEN_STYLEPROT, nCmdLen-LEN_STYLEPROT); 113 sal_Int32 i = sCmdArgs.indexOf('&'); 114 if (i<0) 115 return false; 116 117 OUString sArg = sCmdArgs.copy(0, i); 118 if (sArg.startsWith(CMDURL_SPART_ONLY)) 119 aStyle.sStyle = sArg.copy(LEN_SPART); 120 else if (sArg.startsWith(CMDURL_FPART_ONLY)) 121 aStyle.sFamily = sArg.copy(LEN_FPART); 122 123 sArg = sCmdArgs.copy(i+1, sCmdArgs.getLength()-i-1); 124 if (sArg.startsWith(CMDURL_SPART_ONLY)) 125 aStyle.sStyle = sArg.copy(LEN_SPART); 126 else if (sArg.startsWith(CMDURL_FPART_ONLY)) 127 aStyle.sFamily = sArg.copy(LEN_FPART); 128 129 return !(aStyle.sFamily.isEmpty() || aStyle.sStyle.isEmpty()); 130 } 131 132 void SfxStylesInfo_Impl::getLabel4Style(SfxStyleInfo_Impl& aStyle) 133 { 134 try 135 { 136 css::uno::Reference< css::style::XStyleFamiliesSupplier > xModel(m_xDoc, css::uno::UNO_QUERY); 137 138 css::uno::Reference< css::container::XNameAccess > xFamilies; 139 if (xModel.is()) 140 xFamilies = xModel->getStyleFamilies(); 141 142 css::uno::Reference< css::container::XNameAccess > xStyleSet; 143 if (xFamilies.is()) 144 xFamilies->getByName(aStyle.sFamily) >>= xStyleSet; 145 146 css::uno::Reference< css::beans::XPropertySet > xStyle; 147 if (xStyleSet.is()) 148 xStyleSet->getByName(aStyle.sStyle) >>= xStyle; 149 150 aStyle.sLabel.clear(); 151 if (xStyle.is()) 152 xStyle->getPropertyValue(STYLEPROP_UINAME) >>= aStyle.sLabel; 153 } 154 catch(const css::uno::RuntimeException&) 155 { throw; } 156 catch(const css::uno::Exception&) 157 { aStyle.sLabel.clear(); } 158 159 if (aStyle.sLabel.isEmpty()) 160 { 161 aStyle.sLabel = aStyle.sCommand; 162 } 163 } 164 165 std::vector< SfxStyleInfo_Impl > SfxStylesInfo_Impl::getStyleFamilies() 166 { 167 // It's an optional interface! 168 css::uno::Reference< css::style::XStyleFamiliesSupplier > xModel(m_xDoc, css::uno::UNO_QUERY); 169 if (!xModel.is()) 170 return std::vector< SfxStyleInfo_Impl >(); 171 172 css::uno::Reference< css::container::XNameAccess > xCont = xModel->getStyleFamilies(); 173 css::uno::Sequence< OUString > lFamilyNames = xCont->getElementNames(); 174 std::vector< SfxStyleInfo_Impl > lFamilies; 175 for (const auto& aFamily : lFamilyNames) 176 { 177 if ((aFamily == "CellStyles" && m_aModuleName != "com.sun.star.sheet.SpreadsheetDocument") || 178 aFamily == "cell" || aFamily == "table" || aFamily == "Default") 179 continue; 180 181 SfxStyleInfo_Impl aFamilyInfo; 182 aFamilyInfo.sFamily = aFamily; 183 184 try 185 { 186 css::uno::Reference< css::beans::XPropertySet > xFamilyInfo; 187 xCont->getByName(aFamilyInfo.sFamily) >>= xFamilyInfo; 188 if (!xFamilyInfo.is()) 189 { 190 // TODO_AS currently there is no support for an UIName property .. use internal family name instead 191 aFamilyInfo.sLabel = aFamilyInfo.sFamily; 192 } 193 else 194 xFamilyInfo->getPropertyValue(STYLEPROP_UINAME) >>= aFamilyInfo.sLabel; 195 } 196 catch(const css::uno::RuntimeException&) 197 { throw; } 198 catch(const css::uno::Exception&) 199 { return std::vector< SfxStyleInfo_Impl >(); } 200 201 lFamilies.push_back(aFamilyInfo); 202 } 203 204 return lFamilies; 205 } 206 207 std::vector< SfxStyleInfo_Impl > SfxStylesInfo_Impl::getStyles(const OUString& sFamily) 208 { 209 css::uno::Sequence< OUString > lStyleNames; 210 css::uno::Reference< css::style::XStyleFamiliesSupplier > xModel(m_xDoc, css::uno::UNO_QUERY_THROW); 211 css::uno::Reference< css::container::XNameAccess > xFamilies = xModel->getStyleFamilies(); 212 css::uno::Reference< css::container::XNameAccess > xStyleSet; 213 try 214 { 215 xFamilies->getByName(sFamily) >>= xStyleSet; 216 lStyleNames = xStyleSet->getElementNames(); 217 } 218 catch(const css::uno::RuntimeException&) 219 { throw; } 220 catch(const css::uno::Exception&) 221 { return std::vector< SfxStyleInfo_Impl >(); } 222 223 std::vector< SfxStyleInfo_Impl > lStyles; 224 sal_Int32 c = lStyleNames.getLength(); 225 sal_Int32 i = 0; 226 for (i=0; i<c; ++i) 227 { 228 SfxStyleInfo_Impl aStyleInfo; 229 aStyleInfo.sFamily = sFamily; 230 aStyleInfo.sStyle = lStyleNames[i]; 231 aStyleInfo.sCommand = SfxStylesInfo_Impl::generateCommand(aStyleInfo.sFamily, aStyleInfo.sStyle); 232 233 try 234 { 235 css::uno::Reference< css::beans::XPropertySet > xStyle; 236 xStyleSet->getByName(aStyleInfo.sStyle) >>= xStyle; 237 if (!xStyle.is()) 238 continue; 239 xStyle->getPropertyValue("DisplayName") >>= aStyleInfo.sLabel; 240 } 241 catch(const css::uno::RuntimeException&) 242 { throw; } 243 catch(const css::uno::Exception&) 244 { continue; } 245 246 lStyles.push_back(aStyleInfo); 247 } 248 return lStyles; 249 } 250 251 SfxConfigFunctionListBox::SfxConfigFunctionListBox(vcl::Window* pParent, WinBits nStyle) 252 : SvTreeListBox( pParent, nStyle ) 253 { 254 SetStyle( GetStyle() | WB_CLIPCHILDREN | WB_HSCROLL | WB_SORT ); 255 GetModel()->SetSortMode( SortAscending ); 256 SetQuickSearch( true ); 257 } 258 259 VCL_BUILDER_FACTORY_CONSTRUCTOR(SfxConfigFunctionListBox, WB_TABSTOP) 260 261 SfxConfigFunctionListBox::~SfxConfigFunctionListBox() 262 { 263 disposeOnce(); 264 } 265 266 void SfxConfigFunctionListBox::dispose() 267 { 268 ClearAll(); 269 SvTreeListBox::dispose(); 270 } 271 272 void SfxConfigFunctionListBox::MouseMove( const MouseEvent& ) 273 { 274 } 275 276 void SfxConfigFunctionListBox::ClearAll() 277 /* Description 278 Deletes all entries in the FunctionListBox, all UserData and all 279 possibly existing MacroInfo. 280 */ 281 { 282 sal_uInt16 nCount = aArr.size(); 283 for ( sal_uInt16 i=0; i<nCount; ++i ) 284 { 285 SfxGroupInfo_Impl *pData = aArr[i].get(); 286 287 if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) 288 { 289 OUString* pScriptURI = static_cast<OUString*>(pData->pObject); 290 delete pScriptURI; 291 } 292 293 if ( pData->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER ) 294 { 295 XInterface* xi = static_cast<XInterface *>(pData->pObject); 296 if (xi != nullptr) 297 { 298 xi->release(); 299 } 300 } 301 } 302 303 aArr.clear(); 304 Clear(); 305 } 306 307 OUString SfxConfigFunctionListBox::GetSelectedScriptURI() 308 { 309 SvTreeListEntry *pEntry = FirstSelected(); 310 if ( pEntry ) 311 { 312 SfxGroupInfo_Impl *pData = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData()); 313 if ( pData && ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) ) 314 return *static_cast<OUString*>(pData->pObject); 315 } 316 return OUString(); 317 } 318 319 OUString SfxConfigFunctionListBox::GetHelpText( bool bConsiderParent ) 320 { 321 SvTreeListEntry *pEntry = FirstSelected(); 322 if ( pEntry ) 323 { 324 SfxGroupInfo_Impl *pData = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData()); 325 if ( pData ) 326 { 327 if ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) 328 { 329 if (bConsiderParent) 330 return Application::GetHelp()->GetHelpText( pData->sCommand, this ); 331 else 332 return Application::GetHelp()->GetHelpText( pData->sCommand, nullptr ); 333 } 334 else if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) 335 { 336 return pData->sHelpText; 337 } 338 } 339 } 340 return OUString(); 341 } 342 343 OUString SfxConfigFunctionListBox::GetCurCommand() 344 { 345 SvTreeListEntry *pEntry = FirstSelected(); 346 if (!pEntry) 347 return OUString(); 348 SfxGroupInfo_Impl *pData = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData()); 349 if (!pData) 350 return OUString(); 351 return pData->sCommand; 352 } 353 354 OUString SfxConfigFunctionListBox::GetCurLabel() 355 { 356 SvTreeListEntry *pEntry = FirstSelected(); 357 if (!pEntry) 358 return OUString(); 359 SfxGroupInfo_Impl *pData = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData()); 360 if (!pData) 361 return OUString(); 362 if (!pData->sLabel.isEmpty()) 363 return pData->sLabel; 364 return pData->sCommand; 365 } 366 367 struct SvxConfigGroupBoxResource_Impl 368 { 369 Image m_hdImage; 370 Image m_libImage; 371 Image m_macImage; 372 Image m_docImage; 373 OUString m_sMyMacros; 374 OUString m_sProdMacros; 375 OUString m_sMacros; 376 OUString m_sDlgMacros; 377 OUString m_aStrGroupStyles; 378 Image m_collapsedImage; 379 Image m_expandedImage; 380 381 SvxConfigGroupBoxResource_Impl(); 382 }; 383 384 SvxConfigGroupBoxResource_Impl::SvxConfigGroupBoxResource_Impl() : 385 m_hdImage(BitmapEx(RID_CUIBMP_HARDDISK)), 386 m_libImage(BitmapEx(RID_CUIBMP_LIB)), 387 m_macImage(BitmapEx(RID_CUIBMP_MACRO)), 388 m_docImage(BitmapEx(RID_CUIBMP_DOC)), 389 m_sMyMacros(CuiResId(RID_SVXSTR_MYMACROS)), 390 m_sProdMacros(CuiResId(RID_SVXSTR_PRODMACROS)), 391 m_sMacros(CuiResId(RID_SVXSTR_BASICMACROS)), 392 m_sDlgMacros(CuiResId(RID_SVXSTR_PRODMACROS)), 393 m_aStrGroupStyles(CuiResId(RID_SVXSTR_GROUP_STYLES)), 394 m_collapsedImage(BitmapEx(RID_CUIBMP_COLLAPSED)), 395 m_expandedImage(BitmapEx(RID_CUIBMP_EXPANDED)) 396 { 397 } 398 399 SfxConfigGroupListBox::SfxConfigGroupListBox(vcl::Window* pParent, WinBits nStyle) 400 : SvTreeListBox(pParent, nStyle) 401 , xImp(new SvxConfigGroupBoxResource_Impl()) 402 , pFunctionListBox(nullptr) 403 , pStylesInfo(nullptr) 404 { 405 SetStyle( GetStyle() | WB_CLIPCHILDREN | WB_HSCROLL | WB_HASBUTTONS | WB_HASLINES | WB_HASLINESATROOT | WB_HASBUTTONSATROOT ); 406 SetNodeBitmaps(xImp->m_collapsedImage, xImp->m_expandedImage); 407 } 408 409 VCL_BUILDER_FACTORY_CONSTRUCTOR(SfxConfigGroupListBox, WB_TABSTOP) 410 411 SfxConfigGroupListBox::~SfxConfigGroupListBox() 412 { 413 disposeOnce(); 414 } 415 416 void SfxConfigGroupListBox::dispose() 417 { 418 ClearAll(); 419 pFunctionListBox.clear(); 420 SvTreeListBox::dispose(); 421 } 422 423 void SfxConfigGroupListBox::ClearAll() 424 { 425 sal_uInt16 nCount = aArr.size(); 426 for ( sal_uInt16 i=0; i<nCount; ++i ) 427 { 428 SfxGroupInfo_Impl *pData = aArr[i].get(); 429 if (pData->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER) 430 { 431 XInterface* xi = static_cast<XInterface *>(pData->pObject); 432 if (xi != nullptr) 433 { 434 xi->release(); 435 } 436 } 437 } 438 439 aArr.clear(); 440 Clear(); 441 } 442 443 void SfxConfigGroupListBox::SetStylesInfo(SfxStylesInfo_Impl* pStyles) 444 { 445 pStylesInfo = pStyles; 446 } 447 448 449 void SfxConfigGroupListBox::InitModule() 450 { 451 try 452 { 453 css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider(m_xFrame, css::uno::UNO_QUERY_THROW); 454 css::uno::Sequence< sal_Int16 > lGroups = xProvider->getSupportedCommandGroups(); 455 sal_Int32 c1 = lGroups.getLength(); 456 sal_Int32 i1 = 0; 457 458 if ( c1 ) 459 { 460 // Add All Commands category 461 SvTreeListEntry* pEntry = InsertEntry( CuiResId(RID_SVXSTR_ALLFUNCTIONS) ); 462 aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_ALLFUNCTIONS, 0 ) ); 463 pEntry->SetUserData(aArr.back().get()); 464 } 465 466 for (i1=0; i1<c1; ++i1) 467 { 468 sal_Int16& rGroupID = lGroups[i1]; 469 OUString sGroupID = OUString::number(rGroupID); 470 OUString sGroupName ; 471 472 try 473 { 474 m_xModuleCategoryInfo->getByName(sGroupID) >>= sGroupName; 475 if (sGroupName.isEmpty()) 476 continue; 477 } 478 catch(const css::container::NoSuchElementException&) 479 { continue; } 480 481 SvTreeListEntry* pEntry = InsertEntry(sGroupName); 482 aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_FUNCTION, rGroupID ) ); 483 pEntry->SetUserData(aArr.back().get()); 484 } 485 } 486 catch(const css::uno::RuntimeException&) 487 { throw; } 488 catch(const css::uno::Exception&) 489 {} 490 } 491 492 493 namespace 494 { 495 496 /** examines a component whether it supports XEmbeddedScripts, or provides access to such a 497 component by implementing XScriptInvocationContext. 498 @return 499 the model which supports the embedded scripts, or <NULL/> if it cannot find such a 500 model 501 */ 502 Reference< XModel > lcl_getDocumentWithScripts_throw( const Reference< XInterface >& _rxComponent ) 503 { 504 Reference< XEmbeddedScripts > xScripts( _rxComponent, UNO_QUERY ); 505 if ( !xScripts.is() ) 506 { 507 Reference< XScriptInvocationContext > xContext( _rxComponent, UNO_QUERY ); 508 if ( xContext.is() ) 509 xScripts.set( xContext->getScriptContainer(), UNO_QUERY ); 510 } 511 512 return Reference< XModel >( xScripts, UNO_QUERY ); 513 } 514 515 516 Reference< XModel > lcl_getScriptableDocument_nothrow( const Reference< XFrame >& _rxFrame ) 517 { 518 Reference< XModel > xDocument; 519 520 // examine our associated frame 521 try 522 { 523 OSL_ENSURE( _rxFrame.is(), "lcl_getScriptableDocument_nothrow: you need to pass a frame to this dialog/tab page!" ); 524 if ( _rxFrame.is() ) 525 { 526 // first try the model in the frame 527 Reference< XController > xController( _rxFrame->getController(), UNO_SET_THROW ); 528 xDocument = lcl_getDocumentWithScripts_throw( xController->getModel() ); 529 530 if ( !xDocument.is() ) 531 { 532 // if there is no suitable document in the frame, try the controller 533 xDocument = lcl_getDocumentWithScripts_throw( _rxFrame->getController() ); 534 } 535 } 536 } 537 catch( const Exception& ) 538 { 539 } 540 541 return xDocument; 542 } 543 } 544 545 546 void SfxConfigGroupListBox::FillScriptList(const css::uno::Reference< css::script::browse::XBrowseNode >& xRootNode, 547 SvTreeListEntry* pParentEntry, bool bCheapChildrenOnDemand) 548 { 549 try { 550 if ( xRootNode->hasChildNodes() ) 551 { 552 // tdf#120362: Don't ask to enable disabled Java when filling script list 553 css::uno::ContextLayer layer( 554 new comphelper::NoEnableJavaInteractionContext(css::uno::getCurrentContext())); 555 556 Sequence< Reference< browse::XBrowseNode > > children = 557 xRootNode->getChildNodes(); 558 bool bIsRootNode = false; 559 560 OUString user("user"); 561 OUString share("share"); 562 if ( xRootNode->getName() == "Root" ) 563 { 564 bIsRootNode = true; 565 } 566 567 //To mimic current starbasic behaviour we 568 //need to make sure that only the current document 569 //is displayed in the config tree. Tests below 570 //set the bDisplay flag to FALSE if the current 571 //node is a first level child of the Root and is NOT 572 //either the current document, user or share 573 OUString currentDocTitle; 574 Reference< XModel > xDocument( lcl_getScriptableDocument_nothrow( m_xFrame ) ); 575 if ( xDocument.is() ) 576 { 577 currentDocTitle = ::comphelper::DocumentInfo::getDocumentTitle( xDocument ); 578 } 579 580 for ( sal_Int32 n = 0; n < children.getLength(); ++n ) 581 { 582 Reference< browse::XBrowseNode >& theChild = children[n]; 583 bool bDisplay = true; 584 OUString uiName = theChild->getName(); 585 if ( bIsRootNode ) 586 { 587 if ( ! (theChild->getName() == user || theChild->getName() == share || 588 theChild->getName() == currentDocTitle ) ) 589 { 590 bDisplay=false; 591 } 592 else 593 { 594 if ( uiName == user ) 595 { 596 uiName = xImp->m_sMyMacros; 597 } 598 else if ( uiName == share ) 599 { 600 uiName = xImp->m_sProdMacros; 601 } 602 } 603 } 604 if (children[n]->getType() != browse::BrowseNodeTypes::SCRIPT && bDisplay ) 605 { 606 // We call acquire on the XBrowseNode so that it does not 607 // get autodestructed and become invalid when accessed later. 608 theChild->acquire(); 609 610 Image aImage = GetImage( theChild, m_xContext, bIsRootNode ); 611 SvTreeListEntry* pNewEntry = 612 InsertEntry( uiName, pParentEntry ); 613 SetExpandedEntryBmp( pNewEntry, aImage ); 614 SetCollapsedEntryBmp( pNewEntry, aImage ); 615 616 aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_SCRIPTCONTAINER, 617 0, static_cast<void *>( theChild.get()))); 618 619 pNewEntry->SetUserData( aArr.back().get() ); 620 621 if ( !bCheapChildrenOnDemand && children[n]->hasChildNodes() ) 622 { 623 Sequence< Reference< browse::XBrowseNode > > grandchildren = 624 children[n]->getChildNodes(); 625 626 for ( sal_Int32 m = 0; m < grandchildren.getLength(); ++m ) 627 { 628 if ( grandchildren[m]->getType() == browse::BrowseNodeTypes::CONTAINER ) 629 { 630 pNewEntry->EnableChildrenOnDemand(); 631 m = grandchildren.getLength(); 632 } 633 } 634 } 635 else 636 { 637 /* i30923 - Would be nice if there was a better 638 * way to determine if a basic lib had children 639 * without having to ask for them (which forces 640 * the library to be loaded */ 641 pNewEntry->EnableChildrenOnDemand(); 642 } 643 } 644 } 645 } 646 } 647 catch (RuntimeException&) { 648 // do nothing, the entry will not be displayed in the UI 649 } 650 } 651 652 void SfxConfigGroupListBox::FillFunctionsList(const css::uno::Sequence<DispatchInformation>& xCommands) 653 { 654 for (const auto & rInfo : xCommands) 655 { 656 OUString sUIName = MapCommand2UIName(rInfo.Command); 657 SvTreeListEntry* pFuncEntry = pFunctionListBox->InsertEntry(sUIName ); 658 aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SLOT, 0 ) ); 659 SfxGroupInfo_Impl* pGrpInfo = aArr.back().get(); 660 pGrpInfo->sCommand = rInfo.Command; 661 pGrpInfo->sLabel = sUIName; 662 pFuncEntry->SetUserData(pGrpInfo); 663 } 664 } 665 666 void SfxConfigGroupListBox::Init(const css::uno::Reference< css::uno::XComponentContext >& xContext, 667 const css::uno::Reference< css::frame::XFrame >& xFrame, 668 const OUString& sModuleLongName, 669 bool bEventMode) 670 { 671 SetUpdateMode(false); 672 ClearAll(); // Remove all old entries from treelist box 673 674 m_xContext = xContext; 675 m_xFrame = xFrame; 676 if( bEventMode ) 677 { 678 m_sModuleLongName = sModuleLongName; 679 m_xGlobalCategoryInfo = css::ui::theUICategoryDescription::get( m_xContext ); 680 m_xModuleCategoryInfo.set(m_xGlobalCategoryInfo->getByName(m_sModuleLongName), css::uno::UNO_QUERY_THROW); 681 m_xUICmdDescription = css::frame::theUICommandDescription::get( m_xContext ); 682 683 InitModule(); 684 } 685 686 SAL_INFO("cui.customize", "** ** About to initialise SF Scripts"); 687 // Add Scripting Framework entries 688 Reference< browse::XBrowseNode > rootNode; 689 try 690 { 691 Reference< browse::XBrowseNodeFactory > xFac = browse::theBrowseNodeFactory::get( m_xContext ); 692 rootNode.set( xFac->createView( browse::BrowseNodeFactoryViewTypes::MACROSELECTOR ) ); 693 } 694 catch( Exception& e ) 695 { 696 SAL_INFO("cui.customize", "Caught some exception whilst retrieving browse nodes from factory... Exception: " << e); 697 // TODO exception handling 698 } 699 700 701 if ( rootNode.is() ) 702 { 703 if ( bEventMode ) 704 { 705 //We call acquire on the XBrowseNode so that it does not 706 //get autodestructed and become invalid when accessed later. 707 rootNode->acquire(); 708 709 aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, 710 static_cast<void *>(rootNode.get()))); 711 OUString aTitle(xImp->m_sDlgMacros); 712 SvTreeListEntry *pNewEntry = InsertEntry( aTitle ); 713 pNewEntry->SetUserData( aArr.back().get() ); 714 pNewEntry->EnableChildrenOnDemand(); 715 } 716 else 717 { 718 //We are only showing scripts not slot APIs so skip 719 //Root node and show location nodes 720 FillScriptList(rootNode, nullptr, false); 721 } 722 } 723 724 // add styles 725 if ( bEventMode ) 726 { 727 OUString sStyle(xImp->m_aStrGroupStyles); 728 SvTreeListEntry *pEntry = InsertEntry( sStyle ); 729 aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, nullptr ) ); // TODO last parameter should contain user data 730 pEntry->SetUserData( aArr.back().get() ); 731 pEntry->EnableChildrenOnDemand(); 732 } 733 734 MakeVisible( GetEntry( nullptr,0 ) ); 735 SetUpdateMode( true ); 736 } 737 738 Image SfxConfigGroupListBox::GetImage( 739 const Reference< browse::XBrowseNode >& node, 740 Reference< XComponentContext > const & xCtx, 741 bool bIsRootNode 742 ) 743 { 744 Image aImage; 745 if ( bIsRootNode ) 746 { 747 if (node->getName() == "user" || node->getName() == "share" ) 748 { 749 aImage = xImp->m_hdImage; 750 } 751 else 752 { 753 OUString factoryURL; 754 OUString nodeName = node->getName(); 755 Reference<XInterface> xDocumentModel = getDocumentModel(xCtx, nodeName ); 756 if ( xDocumentModel.is() ) 757 { 758 Reference< frame::XModuleManager2 > xModuleManager( frame::ModuleManager::create(xCtx) ); 759 // get the long name of the document: 760 OUString appModule( xModuleManager->identify( 761 xDocumentModel ) ); 762 Sequence<beans::PropertyValue> moduleDescr; 763 Any aAny = xModuleManager->getByName(appModule); 764 if( !( aAny >>= moduleDescr ) ) 765 { 766 throw RuntimeException("SFTreeListBox::Init: failed to get PropertyValue"); 767 } 768 beans::PropertyValue const * pmoduleDescr = 769 moduleDescr.getConstArray(); 770 for ( sal_Int32 pos = moduleDescr.getLength(); pos--; ) 771 { 772 if ( pmoduleDescr[ pos ].Name == "ooSetupFactoryEmptyDocumentURL" ) 773 { 774 pmoduleDescr[ pos ].Value >>= factoryURL; 775 SAL_INFO("cui.customize", "factory url for doc images is " << factoryURL); 776 break; 777 } 778 } 779 } 780 if( !factoryURL.isEmpty() ) 781 { 782 aImage = SvFileInformationManager::GetFileImage( INetURLObject(factoryURL) ); 783 } 784 else 785 { 786 aImage = xImp->m_docImage; 787 } 788 } 789 } 790 else 791 { 792 if( node->getType() == browse::BrowseNodeTypes::SCRIPT ) 793 aImage = xImp->m_macImage; 794 else 795 aImage = xImp->m_libImage; 796 } 797 return aImage; 798 } 799 800 Reference< XInterface > 801 SfxConfigGroupListBox::getDocumentModel( Reference< XComponentContext > const & xCtx, OUString const & docName ) 802 { 803 Reference< XInterface > xModel; 804 Reference< frame::XDesktop2 > desktop = frame::Desktop::create( xCtx ); 805 806 Reference< container::XEnumerationAccess > componentsAccess = 807 desktop->getComponents(); 808 Reference< container::XEnumeration > components = 809 componentsAccess->createEnumeration(); 810 while (components->hasMoreElements()) 811 { 812 Reference< frame::XModel > model( 813 components->nextElement(), UNO_QUERY ); 814 if ( model.is() ) 815 { 816 OUString sTdocUrl = 817 ::comphelper::DocumentInfo::getDocumentTitle( model ); 818 if( sTdocUrl == docName ) 819 { 820 xModel = model; 821 break; 822 } 823 } 824 } 825 return xModel; 826 } 827 828 829 OUString SfxConfigGroupListBox::MapCommand2UIName(const OUString& sCommand) 830 { 831 OUString sUIName; 832 try 833 { 834 css::uno::Reference< css::container::XNameAccess > xModuleConf; 835 m_xUICmdDescription->getByName(m_sModuleLongName) >>= xModuleConf; 836 if (xModuleConf.is()) 837 { 838 ::comphelper::SequenceAsHashMap lProps(xModuleConf->getByName(sCommand)); 839 sUIName = lProps.getUnpackedValueOrDefault("Name", OUString()); 840 } 841 } 842 catch(const css::uno::RuntimeException&) 843 { throw; } 844 catch(css::uno::Exception&) 845 { sUIName.clear(); } 846 847 // fallback for missing UINames !? 848 if (sUIName.isEmpty()) 849 { 850 sUIName = sCommand; 851 } 852 853 return sUIName; 854 } 855 856 857 void SfxConfigGroupListBox::GroupSelected() 858 /* Description 859 A function group or a basic module has been selected. 860 All functions/macros are displayed in the functionlistbox. 861 */ 862 { 863 SvTreeListEntry *pEntry = FirstSelected(); 864 SfxGroupInfo_Impl *pInfo = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData()); 865 pFunctionListBox->SetUpdateMode(false); 866 pFunctionListBox->ClearAll(); 867 868 switch ( pInfo->nKind ) 869 { 870 case SfxCfgKind::GROUP_ALLFUNCTIONS: 871 { 872 css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider( m_xFrame, UNO_QUERY ); 873 SvTreeListEntry *pCurrEntry = First(); 874 while( pCurrEntry ) 875 { 876 SfxGroupInfo_Impl *pCurrentInfo = static_cast<SfxGroupInfo_Impl*>(pCurrEntry->GetUserData()); 877 if (pCurrentInfo->nKind == SfxCfgKind::GROUP_FUNCTION) 878 { 879 css::uno::Sequence< css::frame::DispatchInformation > lCommands; 880 try 881 { 882 lCommands = xProvider->getConfigurableDispatchInformation( pCurrentInfo->nUniqueID ); 883 FillFunctionsList( lCommands ); 884 } 885 catch ( container::NoSuchElementException& ) 886 { 887 } 888 } 889 pCurrEntry = Next( pCurrEntry ); 890 } 891 break; 892 } 893 894 case SfxCfgKind::GROUP_FUNCTION : 895 { 896 sal_uInt16 nGroup = pInfo->nUniqueID; 897 css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider (m_xFrame, css::uno::UNO_QUERY_THROW); 898 css::uno::Sequence< css::frame::DispatchInformation > lCommands = xProvider->getConfigurableDispatchInformation(nGroup); 899 FillFunctionsList( lCommands ); 900 break; 901 } 902 903 case SfxCfgKind::GROUP_SCRIPTCONTAINER: 904 { 905 if ( !GetChildCount( pEntry ) ) 906 { 907 Reference< browse::XBrowseNode > rootNode( 908 static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ; 909 910 try { 911 if ( rootNode->hasChildNodes() ) 912 { 913 Sequence< Reference< browse::XBrowseNode > > children = 914 rootNode->getChildNodes(); 915 916 for ( sal_Int32 n = 0; n < children.getLength(); ++n ) 917 { 918 if (children[n]->getType() == browse::BrowseNodeTypes::SCRIPT) 919 { 920 OUString uri, description; 921 922 Reference < beans::XPropertySet >xPropSet( children[n], UNO_QUERY ); 923 if (!xPropSet.is()) 924 { 925 continue; 926 } 927 928 Any value = 929 xPropSet->getPropertyValue("URI"); 930 value >>= uri; 931 932 try 933 { 934 value = xPropSet->getPropertyValue("Description"); 935 value >>= description; 936 } 937 catch (Exception &) { 938 // do nothing, the description will be empty 939 } 940 941 OUString* pScriptURI = new OUString( uri ); 942 943 Image aImage = GetImage( children[n], Reference< XComponentContext >(), false ); 944 SvTreeListEntry* pNewEntry = 945 pFunctionListBox->InsertEntry( children[n]->getName() ); 946 pFunctionListBox->SetExpandedEntryBmp( pNewEntry, aImage ); 947 pFunctionListBox->SetCollapsedEntryBmp(pNewEntry, aImage ); 948 949 pFunctionListBox->aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI )); 950 pFunctionListBox->aArr.back()->sCommand = uri; 951 pFunctionListBox->aArr.back()->sLabel = children[n]->getName(); 952 pFunctionListBox->aArr.back()->sHelpText = description; 953 pNewEntry->SetUserData( pFunctionListBox->aArr.back().get() ); 954 } 955 } 956 } 957 } 958 catch (RuntimeException&) { 959 // do nothing, the entry will not be displayed in the UI 960 } 961 } 962 break; 963 } 964 965 case SfxCfgKind::GROUP_STYLES : 966 { 967 SfxStyleInfo_Impl* pFamily = static_cast<SfxStyleInfo_Impl*>(pInfo->pObject); 968 if (pFamily) 969 { 970 const std::vector< SfxStyleInfo_Impl > lStyles = pStylesInfo->getStyles(pFamily->sFamily); 971 for (auto const& lStyle : lStyles) 972 { 973 SfxStyleInfo_Impl* pStyle = new SfxStyleInfo_Impl(lStyle); 974 SvTreeListEntry* pFuncEntry = pFunctionListBox->InsertEntry( pStyle->sLabel ); 975 pFunctionListBox->aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, pStyle ) ); 976 pFunctionListBox->aArr.back()->sCommand = pStyle->sCommand; 977 pFunctionListBox->aArr.back()->sLabel = pStyle->sLabel; 978 pFuncEntry->SetUserData( pFunctionListBox->aArr.back().get() ); 979 } 980 } 981 break; 982 } 983 984 default: 985 // Do nothing, the list box will stay empty 986 SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " << static_cast<int>(pInfo->nKind) ); 987 break; 988 } 989 990 if ( pFunctionListBox->GetEntryCount() ) 991 pFunctionListBox->Select( pFunctionListBox->GetEntry( nullptr, 0 ) ); 992 993 pFunctionListBox->SetUpdateMode(true); 994 } 995 996 bool SfxConfigGroupListBox::Expand( SvTreeListEntry* pParent ) 997 { 998 bool bRet = SvTreeListBox::Expand( pParent ); 999 if ( bRet ) 1000 { 1001 sal_uLong nEntries = GetOutputSizePixel().Height() / GetEntryHeight(); 1002 1003 sal_uLong nChildCount = GetVisibleChildCount( pParent ); 1004 1005 if ( nChildCount+1 > nEntries ) 1006 { 1007 MakeVisible( pParent, true ); 1008 } 1009 else 1010 { 1011 SvTreeListEntry *pEntry = GetFirstEntryInView(); 1012 sal_uLong nParentPos = 0; 1013 while ( pEntry && pEntry != pParent ) 1014 { 1015 ++nParentPos; 1016 pEntry = GetNextEntryInView( pEntry ); 1017 } 1018 1019 if ( nParentPos + nChildCount + 1 > nEntries ) 1020 ScrollOutputArea( static_cast<short>( nEntries - ( nParentPos + nChildCount + 1 ) ) ); 1021 } 1022 } 1023 1024 return bRet; 1025 } 1026 1027 void SfxConfigGroupListBox::RequestingChildren( SvTreeListEntry *pEntry ) 1028 /* Description 1029 A basic or a library is opened. 1030 */ 1031 { 1032 SfxGroupInfo_Impl *pInfo = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData()); 1033 switch ( pInfo->nKind ) 1034 { 1035 case SfxCfgKind::GROUP_SCRIPTCONTAINER: 1036 { 1037 if ( !GetChildCount( pEntry ) ) 1038 { 1039 Reference< browse::XBrowseNode > rootNode( 1040 static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ; 1041 FillScriptList(rootNode, pEntry, true /* i30923 */ ); 1042 } 1043 break; 1044 } 1045 1046 case SfxCfgKind::GROUP_STYLES: 1047 { 1048 if ( !GetChildCount( pEntry ) ) 1049 { 1050 const std::vector< SfxStyleInfo_Impl > lStyleFamilies = pStylesInfo->getStyleFamilies(); 1051 for (auto const& lStyleFamily : lStyleFamilies) 1052 { 1053 SfxStyleInfo_Impl* pFamily = new SfxStyleInfo_Impl(lStyleFamily); 1054 SvTreeListEntry* pStyleEntry = InsertEntry( pFamily->sLabel, pEntry ); 1055 aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, pFamily )); 1056 pStyleEntry->SetUserData( aArr.back().get() ); 1057 pStyleEntry->EnableChildrenOnDemand( false ); 1058 } 1059 } 1060 break; 1061 } 1062 1063 default: 1064 OSL_FAIL( "Wrong group type!" ); 1065 break; 1066 } 1067 } 1068 1069 void SfxConfigGroupListBox::SelectMacro( const SfxMacroInfoItem *pItem ) 1070 { 1071 SelectMacro( pItem->GetBasicManager()->GetName(), 1072 pItem->GetQualifiedName() ); 1073 } 1074 1075 void SfxConfigGroupListBox::SelectMacro( const OUString& rBasic, 1076 const OUString& rMacro ) 1077 { 1078 const OUString aBasicName(rBasic + " " + xImp->m_sMacros); 1079 const sal_Int32 nCount = comphelper::string::getTokenCount(rMacro, '.'); 1080 const OUString aMethod( rMacro.getToken( nCount-1, '.' ) ); 1081 OUString aLib; 1082 OUString aModule; 1083 if ( nCount > 2 ) 1084 { 1085 aLib = rMacro.getToken( 0, '.' ); 1086 aModule = rMacro.getToken( nCount-2, '.' ); 1087 } 1088 1089 SvTreeListEntry *pEntry = FirstChild(nullptr); 1090 while ( pEntry ) 1091 { 1092 OUString aEntryBas = GetEntryText( pEntry ); 1093 if ( aEntryBas == aBasicName ) 1094 { 1095 Expand( pEntry ); 1096 SvTreeListEntry *pLib = FirstChild( pEntry ); 1097 while ( pLib ) 1098 { 1099 OUString aEntryLib = GetEntryText( pLib ); 1100 if ( aEntryLib == aLib ) 1101 { 1102 Expand( pLib ); 1103 SvTreeListEntry *pMod = FirstChild( pLib ); 1104 while ( pMod ) 1105 { 1106 OUString aEntryMod = GetEntryText( pMod ); 1107 if ( aEntryMod == aModule ) 1108 { 1109 Expand( pMod ); 1110 MakeVisible( pMod ); 1111 Select( pMod ); 1112 SvTreeListEntry *pMethod = pFunctionListBox->First(); 1113 while ( pMethod ) 1114 { 1115 OUString aEntryMethod = GetEntryText( pMethod ); 1116 if ( aEntryMethod == aMethod ) 1117 { 1118 pFunctionListBox->Select( pMethod ); 1119 pFunctionListBox->MakeVisible( pMethod ); 1120 return; 1121 } 1122 pMethod = pFunctionListBox->Next( pMethod ); 1123 } 1124 } 1125 pMod = pMod->NextSibling(); 1126 } 1127 } 1128 pLib = pLib->NextSibling(); 1129 } 1130 } 1131 pEntry = pEntry->NextSibling(); 1132 } 1133 } 1134 1135 /* 1136 * Implementation of SvxScriptSelectorDialog 1137 * 1138 * This dialog is used for selecting Slot API commands 1139 * and Scripting Framework Scripts. 1140 */ 1141 1142 SvxScriptSelectorDialog::SvxScriptSelectorDialog( 1143 vcl::Window* pParent, bool bShowSlots, const css::uno::Reference< css::frame::XFrame >& xFrame) 1144 : ModalDialog(pParent, "MacroSelectorDialog", "cui/ui/macroselectordialog.ui") 1145 , m_bShowSlots(bShowSlots) 1146 { 1147 get<FixedText>("libraryft")->Show(!m_bShowSlots); 1148 get<FixedText>("categoryft")->Show(m_bShowSlots); 1149 get<FixedText>("macronameft")->Show(!m_bShowSlots); 1150 get<FixedText>("commandsft")->Show(m_bShowSlots); 1151 get(m_pDescriptionText, "description"); 1152 get(m_pCommands, "commands"); 1153 if (m_bShowSlots) 1154 { 1155 // If we are showing Slot API commands update labels in the UI 1156 SetText(CuiResId(RID_SVXSTR_SELECTOR_ADD_COMMANDS)); 1157 get(m_pCancelButton, "close"); 1158 get(m_pDialogDescription, "helptoolbar"); 1159 get(m_pOKButton, "add"); 1160 } 1161 else 1162 { 1163 get(m_pCancelButton, "cancel"); 1164 get(m_pDialogDescription, "helpmacro"); 1165 get(m_pOKButton, "ok"); 1166 } 1167 m_pCancelButton->Show(); 1168 m_pDialogDescription->Show(); 1169 m_pOKButton->Show(); 1170 1171 get(m_pCategories, "categories"); 1172 const OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(xFrame)); 1173 m_pCategories->SetFunctionListBox(m_pCommands); 1174 m_pCategories->Init(comphelper::getProcessComponentContext(), xFrame, aModuleName, bShowSlots); 1175 1176 m_pCategories->SetSelectHdl( 1177 LINK( this, SvxScriptSelectorDialog, SelectHdl ) ); 1178 m_pCommands->SetSelectHdl( LINK( this, SvxScriptSelectorDialog, SelectHdl ) ); 1179 m_pCommands->SetDoubleClickHdl( LINK( this, SvxScriptSelectorDialog, FunctionDoubleClickHdl ) ); 1180 1181 m_pOKButton->SetClickHdl( LINK( this, SvxScriptSelectorDialog, ClickHdl ) ); 1182 m_pCancelButton->SetClickHdl( LINK( this, SvxScriptSelectorDialog, ClickHdl ) ); 1183 1184 m_sDefaultDesc = m_pDescriptionText->GetText(); 1185 1186 // Support style commands 1187 uno::Reference<frame::XController> xController; 1188 uno::Reference<frame::XModel> xModel; 1189 if (xFrame.is()) 1190 xController = xFrame->getController(); 1191 if (xController.is()) 1192 xModel = xController->getModel(); 1193 1194 m_aStylesInfo.init(aModuleName, xModel); 1195 m_pCategories->SetStylesInfo(&m_aStylesInfo); 1196 1197 UpdateUI(); 1198 } 1199 1200 SvxScriptSelectorDialog::~SvxScriptSelectorDialog() 1201 { 1202 disposeOnce(); 1203 } 1204 1205 void SvxScriptSelectorDialog::dispose() 1206 { 1207 m_pDialogDescription.clear(); 1208 m_pCategories.clear(); 1209 m_pCommands.clear(); 1210 m_pOKButton.clear(); 1211 m_pCancelButton.clear(); 1212 m_pDescriptionText.clear(); 1213 ModalDialog::dispose(); 1214 } 1215 1216 IMPL_LINK( SvxScriptSelectorDialog, SelectHdl, SvTreeListBox*, pCtrl, void ) 1217 { 1218 if (pCtrl == m_pCategories) 1219 { 1220 m_pCategories->GroupSelected(); 1221 } 1222 UpdateUI(); 1223 } 1224 1225 IMPL_LINK_NOARG( SvxScriptSelectorDialog, FunctionDoubleClickHdl, SvTreeListBox*, bool ) 1226 { 1227 if (m_pOKButton->IsEnabled()) 1228 ClickHdl(m_pOKButton); 1229 return false; 1230 } 1231 1232 // Check if command is selected and enable the OK button accordingly 1233 // Grab the help text for this id if available and update the description field 1234 void 1235 SvxScriptSelectorDialog::UpdateUI() 1236 { 1237 OUString url = GetScriptURL(); 1238 if ( !url.isEmpty() ) 1239 { 1240 OUString sMessage = m_pCommands->GetHelpText(); 1241 m_pDescriptionText->SetText(sMessage.isEmpty() ? m_sDefaultDesc : sMessage); 1242 1243 m_pOKButton->Enable(); 1244 } 1245 else 1246 { 1247 m_pDescriptionText->SetText(m_sDefaultDesc); 1248 m_pOKButton->Enable( false ); 1249 } 1250 } 1251 1252 IMPL_LINK( SvxScriptSelectorDialog, ClickHdl, Button *, pButton, void ) 1253 { 1254 if (pButton == m_pCancelButton) 1255 { 1256 EndDialog(); 1257 } 1258 else if (pButton == m_pOKButton) 1259 { 1260 // If we are displaying Slot API commands then this the dialog is being 1261 // run from Tools/Configure and we should not close it 1262 if ( !m_bShowSlots ) 1263 { 1264 EndDialog( RET_OK ); 1265 } 1266 else 1267 { 1268 // Select the next entry in the list if possible 1269 SvTreeListEntry* current = m_pCommands->FirstSelected(); 1270 SvTreeListEntry* next = current->NextSibling(); 1271 1272 if ( next != nullptr ) 1273 { 1274 m_pCommands->Select( next ); 1275 } 1276 } 1277 } 1278 } 1279 1280 void 1281 SvxScriptSelectorDialog::SetRunLabel() 1282 { 1283 m_pOKButton->SetText(CuiResId(RID_SVXSTR_SELECTOR_RUN)); 1284 } 1285 1286 OUString 1287 SvxScriptSelectorDialog::GetScriptURL() const 1288 { 1289 OUString result; 1290 1291 SvTreeListEntry *pEntry = const_cast< SvxScriptSelectorDialog* >( this )->m_pCommands->FirstSelected(); 1292 if ( pEntry ) 1293 { 1294 SfxGroupInfo_Impl *pData = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData()); 1295 if ( ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) 1296 || ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) 1297 || ( pData->nKind == SfxCfgKind::GROUP_STYLES ) 1298 ) 1299 { 1300 result = pData->sCommand; 1301 } 1302 } 1303 1304 return result; 1305 } 1306 1307 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1308
