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 21 #include "macrodlg.hxx" 22 #include <basidesh.hxx> 23 #include <strings.hrc> 24 #include <iderid.hxx> 25 26 #include <iderdll.hxx> 27 #include "iderdll2.hxx" 28 29 #include "moduldlg.hxx" 30 #include <basic/basmgr.hxx> 31 #include <basic/sbmeth.hxx> 32 #include <basic/sbmod.hxx> 33 #include <com/sun/star/script/XLibraryContainer2.hpp> 34 35 #include <sfx2/app.hxx> 36 #include <sfx2/dispatch.hxx> 37 #include <sfx2/frame.hxx> 38 #include <sfx2/minfitem.hxx> 39 #include <sfx2/request.hxx> 40 #include <sfx2/sfxsids.hrc> 41 #include <tools/debug.hxx> 42 #include <vcl/svapp.hxx> 43 #include <vcl/weld.hxx> 44 #include <osl/diagnose.h> 45 46 namespace basctl 47 { 48 49 using namespace ::com::sun::star; 50 using namespace ::com::sun::star::uno; 51 52 MacroChooser::MacroChooser(weld::Window* pParnt, const Reference< frame::XFrame >& xDocFrame) 53 : SfxDialogController(pParnt, "modules/BasicIDE/ui/basicmacrodialog.ui", "BasicMacroDialog") 54 , m_xDocumentFrame(xDocFrame) 55 // the Sfx doesn't ask the BasicManager whether modified or not 56 // => start saving in case of a change without a into the BasicIDE. 57 , bForceStoreBasic(false) 58 , nMode(All) 59 , m_xMacroNameEdit(m_xBuilder->weld_entry("macronameedit")) 60 , m_xMacroFromTxT(m_xBuilder->weld_label("macrofromft")) 61 , m_xMacrosSaveInTxt(m_xBuilder->weld_label("macrotoft")) 62 , m_xBasicBox(new SbTreeListBox(m_xBuilder->weld_tree_view("libraries"), m_xDialog.get())) 63 , m_xBasicBoxIter(m_xBasicBox->make_iterator()) 64 , m_xMacrosInTxt(m_xBuilder->weld_label("existingmacrosft")) 65 , m_xMacroBox(m_xBuilder->weld_tree_view("macros")) 66 , m_xMacroBoxIter(m_xMacroBox->make_iterator()) 67 , m_xRunButton(m_xBuilder->weld_button("ok")) 68 , m_xCloseButton(m_xBuilder->weld_button("close")) 69 , m_xAssignButton(m_xBuilder->weld_button("assign")) 70 , m_xEditButton(m_xBuilder->weld_button("edit")) 71 , m_xDelButton(m_xBuilder->weld_button("delete")) 72 , m_xNewButton(m_xBuilder->weld_button("new")) 73 , m_xOrganizeButton(m_xBuilder->weld_button("organize")) 74 , m_xNewLibButton(m_xBuilder->weld_button("newlibrary")) 75 , m_xNewModButton(m_xBuilder->weld_button("newmodule")) 76 { 77 m_xBasicBox->set_size_request(m_xBasicBox->get_approximate_digit_width() * 30, m_xBasicBox->get_height_rows(18)); 78 m_xMacroBox->set_size_request(m_xMacroBox->get_approximate_digit_width() * 30, m_xMacroBox->get_height_rows(18)); 79 // tdf#70813 The macros should be listed alphabetically 80 m_xMacroBox->make_sorted(); 81 82 m_aMacrosInTxtBaseStr = m_xMacrosInTxt->get_label(); 83 84 m_xRunButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); 85 m_xCloseButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); 86 m_xAssignButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); 87 m_xEditButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); 88 m_xDelButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); 89 m_xNewButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); 90 m_xOrganizeButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); 91 92 // Buttons only for MacroChooser::Recording 93 m_xNewLibButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); 94 m_xNewModButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); 95 m_xNewLibButton->hide(); // default 96 m_xNewModButton->hide(); // default 97 m_xMacrosSaveInTxt->hide(); // default 98 99 m_xMacroNameEdit->connect_changed( LINK( this, MacroChooser, EditModifyHdl ) ); 100 101 m_xBasicBox->connect_changed( LINK( this, MacroChooser, BasicSelectHdl ) ); 102 103 m_xMacroBox->connect_row_activated( LINK( this, MacroChooser, MacroDoubleClickHdl ) ); 104 m_xMacroBox->connect_changed( LINK( this, MacroChooser, MacroSelectHdl ) ); 105 106 m_xBasicBox->SetMode( BrowseMode::Modules ); 107 108 if (SfxDispatcher* pDispatcher = GetDispatcher()) 109 pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES ); 110 111 m_xBasicBox->ScanAllEntries(); 112 } 113 114 MacroChooser::~MacroChooser() 115 { 116 if (bForceStoreBasic) 117 { 118 SfxGetpApp()->SaveBasicAndDialogContainer(); 119 bForceStoreBasic = false; 120 } 121 } 122 123 void MacroChooser::StoreMacroDescription() 124 { 125 m_xBasicBox->get_selected(m_xBasicBoxIter.get()); 126 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); 127 OUString aMethodName; 128 if (m_xMacroBox->get_selected(m_xMacroBoxIter.get())) 129 aMethodName = m_xMacroBox->get_text(*m_xMacroBoxIter); 130 else 131 aMethodName = m_xMacroNameEdit->get_text(); 132 if ( !aMethodName.isEmpty() ) 133 { 134 aDesc.SetMethodName( aMethodName ); 135 aDesc.SetType( OBJ_TYPE_METHOD ); 136 } 137 138 if (ExtraData* pData = basctl::GetExtraData()) 139 pData->SetLastEntryDescriptor( aDesc ); 140 } 141 142 void MacroChooser::RestoreMacroDescription() 143 { 144 EntryDescriptor aDesc; 145 if (Shell* pShell = GetShell()) 146 { 147 if (BaseWindow* pCurWin = pShell->GetCurWindow()) 148 aDesc = pCurWin->CreateEntryDescriptor(); 149 } 150 else 151 { 152 if (ExtraData* pData = basctl::GetExtraData()) 153 aDesc = pData->GetLastEntryDescriptor(); 154 } 155 156 m_xBasicBox->SetCurrentEntry(aDesc); 157 BasicSelectHdl(m_xBasicBox->get_widget()); 158 159 OUString aLastMacro( aDesc.GetMethodName() ); 160 if (!aLastMacro.isEmpty()) 161 { 162 // find entry in macro box 163 auto nIndex = m_xMacroBox->find_text(aLastMacro); 164 if (nIndex != -1) 165 m_xMacroBox->select(nIndex); 166 else 167 { 168 m_xMacroNameEdit->set_text(aLastMacro); 169 m_xMacroNameEdit->select_region(0, 0); 170 } 171 } 172 } 173 174 short MacroChooser::run() 175 { 176 RestoreMacroDescription(); 177 178 // #104198 Check if "wrong" document is active 179 bool bSelectedEntry = m_xBasicBox->get_cursor(m_xBasicBoxIter.get()); 180 EntryDescriptor aDesc(m_xBasicBox->GetEntryDescriptor(bSelectedEntry ? m_xBasicBoxIter.get() : nullptr)); 181 const ScriptDocument& rSelectedDoc(aDesc.GetDocument()); 182 183 // App Basic is always ok, so only check if shell was found 184 if( rSelectedDoc.isDocument() && !rSelectedDoc.isActive() ) 185 { 186 // Search for the right entry 187 bool bValidIter = m_xBasicBox->get_iter_first(*m_xBasicBoxIter); 188 while (bValidIter) 189 { 190 EntryDescriptor aCmpDesc(m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get())); 191 const ScriptDocument& rCmpDoc( aCmpDesc.GetDocument() ); 192 if (rCmpDoc.isDocument() && rCmpDoc.isActive()) 193 { 194 std::unique_ptr<weld::TreeIter> xEntry(m_xBasicBox->make_iterator()); 195 m_xBasicBox->copy_iterator(*m_xBasicBoxIter, *xEntry); 196 std::unique_ptr<weld::TreeIter> xLastValid(m_xBasicBox->make_iterator()); 197 bool bValidEntryIter = true; 198 do 199 { 200 m_xBasicBox->copy_iterator(*xEntry, *xLastValid); 201 bValidEntryIter = m_xBasicBox->iter_children(*xEntry); 202 } 203 while (bValidEntryIter); 204 m_xBasicBox->set_cursor(*xLastValid); 205 } 206 bValidIter = m_xBasicBox->iter_next_sibling(*m_xBasicBoxIter); 207 } 208 } 209 210 CheckButtons(); 211 UpdateFields(); 212 213 // tdf#62955 - Allow searching a name with typing the first letter 214 m_xBasicBox->get_widget().grab_focus(); 215 216 if ( StarBASIC::IsRunning() ) 217 m_xCloseButton->grab_focus(); 218 219 return SfxDialogController::run(); 220 } 221 222 void MacroChooser::EnableButton(weld::Button& rButton, bool bEnable) 223 { 224 if ( bEnable ) 225 { 226 if (nMode == ChooseOnly || nMode == Recording) 227 rButton.set_sensitive(&rButton == m_xRunButton.get()); 228 else 229 rButton.set_sensitive(true); 230 } 231 else 232 rButton.set_sensitive(false); 233 } 234 235 SbMethod* MacroChooser::GetMacro() 236 { 237 if (!m_xBasicBox->get_cursor(m_xBasicBoxIter.get())) 238 return nullptr; 239 SbModule* pModule = m_xBasicBox->FindModule(m_xBasicBoxIter.get()); 240 if (!pModule) 241 return nullptr; 242 if (!m_xMacroBox->get_selected(m_xMacroBoxIter.get())) 243 return nullptr; 244 OUString aMacroName(m_xMacroBox->get_text(*m_xMacroBoxIter)); 245 return pModule->FindMethod(aMacroName, SbxClassType::Method); 246 } 247 248 void MacroChooser::DeleteMacro() 249 { 250 SbMethod* pMethod = GetMacro(); 251 DBG_ASSERT( pMethod, "DeleteMacro: No Macro !" ); 252 if (!(pMethod && QueryDelMacro(pMethod->GetName(), m_xDialog.get()))) 253 return; 254 255 if (SfxDispatcher* pDispatcher = GetDispatcher()) 256 pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES ); 257 258 // mark current doc as modified: 259 StarBASIC* pBasic = FindBasic(pMethod); 260 assert(pBasic && "Basic?!"); 261 BasicManager* pBasMgr = FindBasicManager( pBasic ); 262 DBG_ASSERT( pBasMgr, "BasMgr?" ); 263 ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) ); 264 if ( aDocument.isDocument() ) 265 { 266 aDocument.setDocumentModified(); 267 if (SfxBindings* pBindings = GetBindingsPtr()) 268 pBindings->Invalidate( SID_SAVEDOC ); 269 } 270 271 SbModule* pModule = pMethod->GetModule(); 272 assert(pModule && "DeleteMacro: No Module?!"); 273 OUString aSource( pModule->GetSource32() ); 274 sal_uInt16 nStart, nEnd; 275 pMethod->GetLineRange( nStart, nEnd ); 276 pModule->GetMethods()->Remove( pMethod ); 277 CutLines( aSource, nStart-1, nEnd-nStart+1 ); 278 pModule->SetSource32( aSource ); 279 280 // update module in library 281 OUString aLibName = pBasic->GetName(); 282 OUString aModName = pModule->GetName(); 283 OSL_VERIFY( aDocument.updateModule( aLibName, aModName, aSource ) ); 284 285 bool bSelected = m_xMacroBox->get_selected(m_xMacroBoxIter.get()); 286 DBG_ASSERT(bSelected, "DeleteMacro: Entry ?!"); 287 m_xMacroBox->remove(*m_xMacroBoxIter); 288 bForceStoreBasic = true; 289 } 290 291 SbMethod* MacroChooser::CreateMacro() 292 { 293 SbMethod* pMethod = nullptr; 294 m_xBasicBox->get_cursor(m_xBasicBoxIter.get()); 295 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); 296 const ScriptDocument& aDocument( aDesc.GetDocument() ); 297 OSL_ENSURE( aDocument.isAlive(), "MacroChooser::CreateMacro: no document!" ); 298 if ( !aDocument.isAlive() ) 299 return nullptr; 300 301 OUString aLibName( aDesc.GetLibName() ); 302 303 if ( aLibName.isEmpty() ) 304 aLibName = "Standard" ; 305 306 aDocument.getOrCreateLibrary( E_SCRIPTS, aLibName ); 307 308 OUString aOULibName( aLibName ); 309 Reference< script::XLibraryContainer > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ) ); 310 if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) && !xModLibContainer->isLibraryLoaded( aOULibName ) ) 311 xModLibContainer->loadLibrary( aOULibName ); 312 Reference< script::XLibraryContainer > xDlgLibContainer( aDocument.getLibraryContainer( E_DIALOGS ) ); 313 if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aOULibName ) && !xDlgLibContainer->isLibraryLoaded( aOULibName ) ) 314 xDlgLibContainer->loadLibrary( aOULibName ); 315 316 BasicManager* pBasMgr = aDocument.getBasicManager(); 317 StarBASIC* pBasic = pBasMgr ? pBasMgr->GetLib( aLibName ) : nullptr; 318 if ( pBasic ) 319 { 320 SbModule* pModule = nullptr; 321 OUString aModName( aDesc.GetName() ); 322 if ( !aModName.isEmpty() ) 323 { 324 // extract the module name from the string like "Sheet1 (Example1)" 325 if( aDesc.GetLibSubName() == IDEResId(RID_STR_DOCUMENT_OBJECTS) ) 326 { 327 aModName = aModName.getToken( 0, ' ' ); 328 } 329 pModule = pBasic->FindModule( aModName ); 330 } 331 else if ( !pBasic->GetModules().empty() ) 332 pModule = pBasic->GetModules().front().get(); 333 334 // Retain the desired macro name before the macro dialog box is forced to close 335 // by opening the module name dialog window when no module exists in the current library. 336 OUString aSubName = m_xMacroNameEdit->get_text(); 337 338 if ( !pModule ) 339 { 340 pModule = createModImpl(m_xDialog.get(), aDocument, *m_xBasicBox, aLibName, aModName, false); 341 } 342 343 DBG_ASSERT( !pModule || !pModule->FindMethod( aSubName, SbxClassType::Method ), "Macro exists already!" ); 344 pMethod = pModule ? basctl::CreateMacro( pModule, aSubName ) : nullptr; 345 } 346 347 return pMethod; 348 } 349 350 void MacroChooser::SaveSetCurEntry(weld::TreeView& rBox, const weld::TreeIter& rEntry) 351 { 352 // the edit would be killed by the highlight otherwise: 353 354 OUString aSaveText(m_xMacroNameEdit->get_text()); 355 int nStartPos, nEndPos; 356 m_xMacroNameEdit->get_selection_bounds(nStartPos, nEndPos); 357 358 rBox.set_cursor(rEntry); 359 360 m_xMacroNameEdit->set_text(aSaveText); 361 m_xMacroNameEdit->select_region(nStartPos, nEndPos); 362 } 363 364 void MacroChooser::CheckButtons() 365 { 366 const bool bCurEntry = m_xBasicBox->get_cursor(m_xBasicBoxIter.get()); 367 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(bCurEntry ? m_xBasicBoxIter.get() : nullptr); 368 const bool bMacroEntry = m_xMacroBox->get_selected(nullptr); 369 SbMethod* pMethod = GetMacro(); 370 371 // check, if corresponding libraries are readonly 372 bool bReadOnly = false; 373 sal_uInt16 nDepth = bCurEntry ? m_xBasicBox->get_iter_depth(*m_xBasicBoxIter) : 0; 374 if ( nDepth == 1 || nDepth == 2 ) 375 { 376 const ScriptDocument& aDocument( aDesc.GetDocument() ); 377 const OUString& aOULibName( aDesc.GetLibName() ); 378 Reference< script::XLibraryContainer2 > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY ); 379 Reference< script::XLibraryContainer2 > xDlgLibContainer( aDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY ); 380 if ( ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) && xModLibContainer->isLibraryReadOnly( aOULibName ) ) || 381 ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aOULibName ) && xDlgLibContainer->isLibraryReadOnly( aOULibName ) ) ) 382 { 383 bReadOnly = true; 384 } 385 } 386 387 if (nMode != Recording) 388 { 389 // Run... 390 bool bEnable = pMethod != nullptr; 391 if (nMode != ChooseOnly && StarBASIC::IsRunning()) 392 bEnable = false; 393 EnableButton(*m_xRunButton, bEnable); 394 } 395 396 // organising still possible? 397 398 // Assign... 399 EnableButton(*m_xAssignButton, pMethod != nullptr); 400 401 // Edit... 402 EnableButton(*m_xEditButton, bMacroEntry); 403 404 // Organizer... 405 EnableButton(*m_xOrganizeButton, !StarBASIC::IsRunning() && nMode == All); 406 407 // m_xDelButton/m_xNewButton ->... 408 bool bProtected = bCurEntry && m_xBasicBox->IsEntryProtected(m_xBasicBoxIter.get()); 409 bool bShare = ( aDesc.GetLocation() == LIBRARY_LOCATION_SHARE ); 410 bool bEnable = !StarBASIC::IsRunning() && nMode == All && !bProtected && !bReadOnly && !bShare; 411 EnableButton(*m_xDelButton, bEnable); 412 EnableButton(*m_xNewButton, bEnable); 413 if (nMode == All) 414 { 415 if (pMethod) 416 { 417 m_xDelButton->show(); 418 m_xNewButton->hide(); 419 } 420 else 421 { 422 m_xNewButton->show(); 423 m_xDelButton->hide(); 424 } 425 } 426 427 if (nMode == Recording) 428 { 429 // save button 430 m_xRunButton->set_sensitive(!bProtected && !bReadOnly && !bShare); 431 // new library button 432 m_xNewLibButton->set_sensitive(!bShare); 433 // new module button 434 m_xNewModButton->set_sensitive(!bProtected && !bReadOnly && !bShare); 435 } 436 } 437 438 IMPL_LINK_NOARG(MacroChooser, MacroDoubleClickHdl, weld::TreeView&, bool) 439 { 440 SbMethod* pMethod = GetMacro(); 441 SbModule* pModule = pMethod ? pMethod->GetModule() : nullptr; 442 StarBASIC* pBasic = pModule ? static_cast<StarBASIC*>(pModule->GetParent()) : nullptr; 443 BasicManager* pBasMgr = pBasic ? FindBasicManager(pBasic) : nullptr; 444 ScriptDocument aDocument(ScriptDocument::getDocumentForBasicManager(pBasMgr)); 445 if (aDocument.isDocument() && !aDocument.allowMacros()) 446 { 447 std::unique_ptr<weld::MessageDialog> xError( 448 Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, 449 VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO))); 450 xError->run(); 451 return true; 452 } 453 454 StoreMacroDescription(); 455 if (nMode == Recording) 456 { 457 if (pMethod && !QueryReplaceMacro(pMethod->GetName(), m_xDialog.get())) 458 return true; 459 } 460 461 m_xDialog->response(Macro_OkRun); 462 return true; 463 } 464 465 IMPL_LINK_NOARG(MacroChooser, MacroSelectHdl, weld::TreeView&, void) 466 { 467 UpdateFields(); 468 CheckButtons(); 469 } 470 471 IMPL_LINK_NOARG(MacroChooser, BasicSelectHdl, weld::TreeView&, void) 472 { 473 m_xBasicBox->get_cursor(m_xBasicBoxIter.get()); 474 SbModule* pModule = m_xBasicBox->FindModule(m_xBasicBoxIter.get()); 475 m_xMacroBox->clear(); 476 if (pModule) 477 { 478 m_xMacrosInTxt->set_label(m_aMacrosInTxtBaseStr + " " + pModule->GetName()); 479 480 m_xMacroBox->freeze(); 481 482 sal_uInt32 nMacroCount = pModule->GetMethods()->Count32(); 483 for ( sal_uInt32 iMeth = 0; iMeth < nMacroCount; iMeth++ ) 484 { 485 SbMethod* pMethod = static_cast<SbMethod*>(pModule->GetMethods()->Get32( iMeth )); 486 assert(pMethod && "Method not found!"); 487 if (pMethod->IsHidden()) 488 continue; 489 m_xMacroBox->append_text(pMethod->GetName()); 490 } 491 492 m_xMacroBox->thaw(); 493 494 if (m_xMacroBox->get_iter_first(*m_xMacroBoxIter)) 495 m_xMacroBox->set_cursor(*m_xMacroBoxIter); 496 } 497 498 UpdateFields(); 499 CheckButtons(); 500 } 501 502 IMPL_LINK_NOARG(MacroChooser, EditModifyHdl, weld::Entry&, void) 503 { 504 // select the module in which the macro is put at "new", 505 // if BasicManager or Lib is selecting 506 if (m_xBasicBox->get_cursor(m_xBasicBoxIter.get())) 507 { 508 sal_uInt16 nDepth = m_xBasicBox->get_iter_depth(*m_xBasicBoxIter); 509 if (nDepth == 1 && m_xBasicBox->IsEntryProtected(m_xBasicBoxIter.get())) 510 { 511 // then put to the respective Std-Lib... 512 m_xBasicBox->iter_parent(*m_xBasicBoxIter); 513 m_xBasicBox->iter_children(*m_xBasicBoxIter); 514 } 515 if (nDepth < 2) 516 { 517 std::unique_ptr<weld::TreeIter> xNewEntry(m_xBasicBox->make_iterator()); 518 m_xBasicBox->copy_iterator(*m_xBasicBoxIter, *xNewEntry); 519 bool bCurEntry = true; 520 do 521 { 522 bCurEntry = m_xBasicBox->iter_children(*m_xBasicBoxIter); 523 if (bCurEntry) 524 { 525 m_xBasicBox->copy_iterator(*m_xBasicBoxIter, *xNewEntry); 526 nDepth = m_xBasicBox->get_iter_depth(*m_xBasicBoxIter); 527 } 528 } 529 while (bCurEntry && (nDepth < 2)); 530 SaveSetCurEntry(m_xBasicBox->get_widget(), *xNewEntry); 531 } 532 auto nCount = m_xMacroBox->n_children(); 533 if (nCount) 534 { 535 OUString aEdtText(m_xMacroNameEdit->get_text()); 536 bool bFound = false; 537 bool bValidIter = m_xMacroBox->get_iter_first(*m_xMacroBoxIter); 538 while (bValidIter) 539 { 540 if (m_xMacroBox->get_text(*m_xMacroBoxIter).equalsIgnoreAsciiCase(aEdtText)) 541 { 542 SaveSetCurEntry(*m_xMacroBox, *m_xMacroBoxIter); 543 bFound = true; 544 break; 545 } 546 bValidIter = m_xMacroBox->iter_next_sibling(*m_xMacroBoxIter); 547 } 548 if (!bFound) 549 { 550 bValidIter = m_xMacroBox->get_selected(m_xMacroBoxIter.get()); 551 // if the entry exists ->Select ->Description... 552 if (bValidIter) 553 m_xMacroBox->unselect(*m_xMacroBoxIter); 554 } 555 } 556 } 557 558 CheckButtons(); 559 } 560 561 IMPL_LINK(MacroChooser, ButtonHdl, weld::Button&, rButton, void) 562 { 563 // apart from New/Record the Description is done by LoseFocus 564 if (&rButton == m_xRunButton.get()) 565 { 566 StoreMacroDescription(); 567 568 // #116444# check security settings before macro execution 569 if (nMode == All) 570 { 571 SbMethod* pMethod = GetMacro(); 572 SbModule* pModule = pMethod ? pMethod->GetModule() : nullptr; 573 StarBASIC* pBasic = pModule ? static_cast<StarBASIC*>(pModule->GetParent()) : nullptr; 574 BasicManager* pBasMgr = pBasic ? FindBasicManager(pBasic) : nullptr; 575 if ( pBasMgr ) 576 { 577 ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) ); 578 if ( aDocument.isDocument() && !aDocument.allowMacros() ) 579 { 580 std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(), 581 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO))); 582 xError->run(); 583 return; 584 } 585 } 586 } 587 else if (nMode == Recording ) 588 { 589 if ( !IsValidSbxName(m_xMacroNameEdit->get_text()) ) 590 { 591 std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(), 592 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME))); 593 xError->run(); 594 m_xMacroNameEdit->select_region(0, -1); 595 m_xMacroNameEdit->grab_focus(); 596 return; 597 } 598 599 SbMethod* pMethod = GetMacro(); 600 if (pMethod && !QueryReplaceMacro(pMethod->GetName(), m_xDialog.get())) 601 return; 602 } 603 604 m_xDialog->response(Macro_OkRun); 605 } 606 else if (&rButton == m_xCloseButton.get()) 607 { 608 StoreMacroDescription(); 609 m_xDialog->response(Macro_Close); 610 } 611 else if (&rButton == m_xEditButton.get() || &rButton == m_xDelButton.get() || &rButton == m_xNewButton.get()) 612 { 613 m_xBasicBox->get_cursor(m_xBasicBoxIter.get()); 614 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); 615 const ScriptDocument& aDocument( aDesc.GetDocument() ); 616 DBG_ASSERT( aDocument.isAlive(), "MacroChooser::ButtonHdl: no document, or document is dead!" ); 617 if ( !aDocument.isAlive() ) 618 return; 619 BasicManager* pBasMgr = aDocument.getBasicManager(); 620 const OUString& aLib( aDesc.GetLibName() ); 621 OUString aMod( aDesc.GetName() ); 622 // extract the module name from the string like "Sheet1 (Example1)" 623 if( aDesc.GetLibSubName() == IDEResId(RID_STR_DOCUMENT_OBJECTS) ) 624 { 625 aMod = aMod.getToken( 0, ' ' ); 626 } 627 const OUString& aSub( aDesc.GetMethodName() ); 628 SfxMacroInfoItem aInfoItem( SID_BASICIDE_ARG_MACROINFO, pBasMgr, aLib, aMod, aSub, OUString() ); 629 if (&rButton == m_xEditButton.get()) 630 { 631 if (m_xMacroBox->get_selected(m_xMacroBoxIter.get())) 632 aInfoItem.SetMethod(m_xMacroBox->get_text(*m_xMacroBoxIter)); 633 StoreMacroDescription(); 634 m_xDialog->hide(); // tdf#126828 dismiss dialog before opening new window 635 636 SfxAllItemSet aArgs( SfxGetpApp()->GetPool() ); 637 SfxRequest aRequest( SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs ); 638 SfxGetpApp()->ExecuteSlot( aRequest ); 639 640 if (SfxDispatcher* pDispatcher = GetDispatcher()) 641 { 642 pDispatcher->ExecuteList(SID_BASICIDE_EDITMACRO, 643 SfxCallMode::ASYNCHRON, { &aInfoItem }); 644 } 645 m_xDialog->response(Macro_Edit); 646 } 647 else 648 { 649 if (&rButton == m_xDelButton.get()) 650 { 651 DeleteMacro(); 652 if (SfxDispatcher* pDispatcher = GetDispatcher()) 653 { 654 pDispatcher->ExecuteList( SID_BASICIDE_UPDATEMODULESOURCE, 655 SfxCallMode::SYNCHRON, { &aInfoItem }); 656 } 657 CheckButtons(); 658 UpdateFields(); 659 //if ( m_xMacroBox->GetCurEntry() ) // OV-Bug ? 660 // m_xMacroBox->Select( m_xMacroBox->GetCurEntry() ); 661 } 662 else 663 { 664 if ( !IsValidSbxName(m_xMacroNameEdit->get_text()) ) 665 { 666 std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(), 667 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME))); 668 xError->run(); 669 m_xMacroNameEdit->select_region(0, -1); 670 m_xMacroNameEdit->grab_focus(); 671 return; 672 } 673 SbMethod* pMethod = CreateMacro(); 674 if ( pMethod ) 675 { 676 aInfoItem.SetMethod( pMethod->GetName() ); 677 aInfoItem.SetModule( pMethod->GetModule()->GetName() ); 678 aInfoItem.SetLib( pMethod->GetModule()->GetParent()->GetName() ); 679 SfxAllItemSet aArgs( SfxGetpApp()->GetPool() ); 680 SfxRequest aRequest( SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs ); 681 SfxGetpApp()->ExecuteSlot( aRequest ); 682 683 if (SfxDispatcher* pDispatcher = GetDispatcher()) 684 { 685 pDispatcher->ExecuteList(SID_BASICIDE_EDITMACRO, 686 SfxCallMode::ASYNCHRON, { &aInfoItem }); 687 } 688 StoreMacroDescription(); 689 m_xDialog->response(Macro_New); 690 } 691 } 692 } 693 } 694 else if (&rButton == m_xAssignButton.get()) 695 { 696 m_xBasicBox->get_cursor(m_xBasicBoxIter.get()); 697 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); 698 const ScriptDocument& aDocument( aDesc.GetDocument() ); 699 DBG_ASSERT( aDocument.isAlive(), "MacroChooser::ButtonHdl: no document, or document is dead!" ); 700 if ( !aDocument.isAlive() ) 701 return; 702 BasicManager* pBasMgr = aDocument.getBasicManager(); 703 const OUString& aLib( aDesc.GetLibName() ); 704 const OUString& aMod( aDesc.GetName() ); 705 OUString aSub( m_xMacroNameEdit->get_text() ); 706 SbMethod* pMethod = GetMacro(); 707 DBG_ASSERT( pBasMgr, "BasMgr?" ); 708 DBG_ASSERT( pMethod, "Method?" ); 709 OUString aComment( GetInfo( pMethod ) ); 710 SfxMacroInfoItem aItem( SID_MACROINFO, pBasMgr, aLib, aMod, aSub, aComment ); 711 SfxAllItemSet Args( SfxGetpApp()->GetPool() ); 712 713 SfxAllItemSet aInternalSet(SfxGetpApp()->GetPool()); 714 if (m_xDocumentFrame.is()) 715 aInternalSet.Put(SfxUnoFrameItem(SID_FILLFRAME, m_xDocumentFrame)); 716 717 SfxRequest aRequest(SID_CONFIG, SfxCallMode::SYNCHRON, Args, aInternalSet); 718 aRequest.AppendItem( aItem ); 719 SfxGetpApp()->ExecuteSlot( aRequest ); 720 } 721 else if (&rButton == m_xNewLibButton.get()) 722 { 723 m_xBasicBox->get_cursor(m_xBasicBoxIter.get()); 724 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); 725 const ScriptDocument& aDocument( aDesc.GetDocument() ); 726 createLibImpl(m_xDialog.get(), aDocument, nullptr, m_xBasicBox.get()); 727 } 728 else if (&rButton == m_xNewModButton.get()) 729 { 730 m_xBasicBox->get_cursor(m_xBasicBoxIter.get()); 731 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); 732 const ScriptDocument& aDocument( aDesc.GetDocument() ); 733 const OUString& aLibName( aDesc.GetLibName() ); 734 createModImpl(m_xDialog.get(), aDocument, *m_xBasicBox, aLibName, OUString(), true); 735 } 736 else if (&rButton == m_xOrganizeButton.get()) 737 { 738 StoreMacroDescription(); 739 740 m_xBasicBox->get_selected(m_xBasicBoxIter.get()); 741 auto xDlg(std::make_shared<OrganizeDialog>(m_xDialog.get(), 0)); 742 weld::DialogController::runAsync(xDlg, [this](sal_Int32 nRet) { 743 if (nRet == RET_OK) // not only closed 744 { 745 m_xDialog->response(Macro_Edit); 746 return; 747 } 748 749 Shell* pShell = GetShell(); 750 if ( pShell && pShell->IsAppBasicModified() ) 751 bForceStoreBasic = true; 752 753 m_xBasicBox->UpdateEntries(); 754 }); 755 } 756 } 757 758 void MacroChooser::UpdateFields() 759 { 760 auto nMacroEntry = m_xMacroBox->get_selected_index(); 761 m_xMacroNameEdit->set_text(""); 762 if (nMacroEntry != -1) 763 m_xMacroNameEdit->set_text(m_xMacroBox->get_text(nMacroEntry)); 764 } 765 766 void MacroChooser::SetMode (Mode nM) 767 { 768 nMode = nM; 769 switch (nMode) 770 { 771 case All: 772 { 773 m_xRunButton->set_label(IDEResId(RID_STR_RUN)); 774 EnableButton(*m_xDelButton, true); 775 EnableButton(*m_xNewButton, true); 776 EnableButton(*m_xOrganizeButton, true); 777 break; 778 } 779 780 case ChooseOnly: 781 { 782 m_xRunButton->set_label(IDEResId(RID_STR_CHOOSE)); 783 EnableButton(*m_xDelButton, false); 784 EnableButton(*m_xNewButton, false); 785 EnableButton(*m_xOrganizeButton, false); 786 break; 787 } 788 789 case Recording: 790 { 791 m_xRunButton->set_label(IDEResId(RID_STR_RECORD)); 792 EnableButton(*m_xDelButton, false); 793 EnableButton(*m_xNewButton, false); 794 EnableButton(*m_xOrganizeButton, false); 795 796 m_xAssignButton->hide(); 797 m_xEditButton->hide(); 798 m_xDelButton->hide(); 799 m_xNewButton->hide(); 800 m_xOrganizeButton->hide(); 801 m_xMacroFromTxT->hide(); 802 803 m_xNewLibButton->show(); 804 m_xNewModButton->show(); 805 m_xMacrosSaveInTxt->show(); 806 807 break; 808 } 809 } 810 CheckButtons(); 811 } 812 813 OUString MacroChooser::GetInfo( SbxVariable* pVar ) 814 { 815 OUString aComment; 816 SbxInfoRef xInfo = pVar->GetInfo(); 817 if ( xInfo.is() ) 818 aComment = xInfo->GetComment(); 819 return aComment; 820 } 821 822 823 } // namespace basctl 824 825 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 826
