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