1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "macrodlg.hxx"
22 #include <basidesh.hxx>
23 #include <strings.hrc>
26 #include <iderdll.hxx>
27 #include "iderdll2.hxx"
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>
50 using namespace ::com::sun::star
;
51 using namespace ::com::sun::star::uno
;
53 MacroChooser::MacroChooser(weld::Window
* pParnt
, const Reference
< frame::XFrame
>& xDocFrame
)
54 : SfxDialogController(pParnt
, u
"modules/BasicIDE/ui/basicmacrodialog.ui"_ustr
, u
"BasicMacroDialog"_ustr
)
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)
60 , m_xMacroNameEdit(m_xBuilder
->weld_entry(u
"macronameedit"_ustr
))
61 , m_xMacroFromTxT(m_xBuilder
->weld_label(u
"macrofromft"_ustr
))
62 , m_xMacrosSaveInTxt(m_xBuilder
->weld_label(u
"macrotoft"_ustr
))
63 , m_xBasicBox(new SbTreeListBox(m_xBuilder
->weld_tree_view(u
"libraries"_ustr
), m_xDialog
.get()))
64 , m_xBasicBoxIter(m_xBasicBox
->make_iterator())
65 , m_xMacrosInTxt(m_xBuilder
->weld_label(u
"existingmacrosft"_ustr
))
66 , m_xMacroBox(m_xBuilder
->weld_tree_view(u
"macros"_ustr
))
67 , m_xMacroBoxIter(m_xMacroBox
->make_iterator())
68 , m_xRunButton(m_xBuilder
->weld_button(u
"ok"_ustr
))
69 , m_xCloseButton(m_xBuilder
->weld_button(u
"close"_ustr
))
70 , m_xAssignButton(m_xBuilder
->weld_button(u
"assign"_ustr
))
71 , m_xEditButton(m_xBuilder
->weld_button(u
"edit"_ustr
))
72 , m_xDelButton(m_xBuilder
->weld_button(u
"delete"_ustr
))
73 , m_xNewButton(m_xBuilder
->weld_button(u
"new"_ustr
))
74 , m_xOrganizeButton(m_xBuilder
->weld_button(u
"organize"_ustr
))
75 , m_xNewLibButton(m_xBuilder
->weld_button(u
"newlibrary"_ustr
))
76 , m_xNewModButton(m_xBuilder
->weld_button(u
"newmodule"_ustr
))
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));
81 m_aMacrosInTxtBaseStr
= m_xMacrosInTxt
->get_label();
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
) );
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
98 m_xMacroNameEdit
->connect_changed( LINK( this, MacroChooser
, EditModifyHdl
) );
100 m_xBasicBox
->connect_changed( LINK( this, MacroChooser
, BasicSelectHdl
) );
102 m_xMacroBox
->connect_row_activated( LINK( this, MacroChooser
, MacroDoubleClickHdl
) );
103 m_xMacroBox
->connect_selection_changed(LINK(this, MacroChooser
, MacroSelectHdl
));
104 m_xMacroBox
->connect_popup_menu( LINK( this, MacroChooser
, ContextMenuHdl
) );
106 m_xBasicBox
->SetMode( BrowseMode::Modules
);
108 if (SfxDispatcher
* pDispatcher
= GetDispatcher())
109 pDispatcher
->Execute( SID_BASICIDE_STOREALLMODULESOURCES
);
111 m_xBasicBox
->ScanAllEntries();
114 MacroChooser::~MacroChooser()
116 if (bForceStoreBasic
)
118 SfxGetpApp()->SaveBasicAndDialogContainer();
119 bForceStoreBasic
= false;
123 void MacroChooser::StoreMacroDescription()
125 if (!m_xBasicBox
->get_selected(m_xBasicBoxIter
.get()))
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
);
132 aMethodName
= m_xMacroNameEdit
->get_text();
133 if ( !aMethodName
.isEmpty() )
135 aDesc
.SetMethodName( aMethodName
);
136 aDesc
.SetType( OBJ_TYPE_METHOD
);
139 if (ExtraData
* pData
= basctl::GetExtraData())
140 pData
->SetLastEntryDescriptor( aDesc
);
143 void MacroChooser::RestoreMacroDescription()
145 // The following call is a workaround to ensure the last used macro is scrolled to in kf5
146 m_xDialog
->resize_to_request();
148 EntryDescriptor aDesc
;
149 if (Shell
* pShell
= GetShell())
151 if (BaseWindow
* pCurWin
= pShell
->GetCurWindow())
152 aDesc
= pCurWin
->CreateEntryDescriptor();
156 if (ExtraData
* pData
= basctl::GetExtraData())
157 aDesc
= pData
->GetLastEntryDescriptor();
160 m_xBasicBox
->SetCurrentEntry(aDesc
);
161 BasicSelectHdl(m_xBasicBox
->get_widget());
163 OUString
aLastMacro( aDesc
.GetMethodName() );
164 if (!aLastMacro
.isEmpty())
166 // find entry in macro box
167 auto nIndex
= m_xMacroBox
->find_text(aLastMacro
);
169 m_xMacroBox
->select(nIndex
);
172 m_xMacroNameEdit
->set_text(aLastMacro
);
173 m_xMacroNameEdit
->select_region(0, 0);
178 short MacroChooser::run()
180 RestoreMacroDescription();
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());
187 // App Basic is always ok, so only check if shell was found
188 if( rSelectedDoc
.isDocument() && !rSelectedDoc
.isActive() )
190 // Search for the right entry
191 bool bValidIter
= m_xBasicBox
->get_iter_first(*m_xBasicBoxIter
);
194 EntryDescriptor
aCmpDesc(m_xBasicBox
->GetEntryDescriptor(m_xBasicBoxIter
.get()));
195 const ScriptDocument
& rCmpDoc( aCmpDesc
.GetDocument() );
196 if (rCmpDoc
.isDocument() && rCmpDoc
.isActive())
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;
204 m_xBasicBox
->copy_iterator(*xEntry
, *xLastValid
);
205 bValidEntryIter
= m_xBasicBox
->iter_children(*xEntry
);
207 while (bValidEntryIter
);
208 m_xBasicBox
->set_cursor(*xLastValid
);
210 bValidIter
= m_xBasicBox
->iter_next_sibling(*m_xBasicBoxIter
);
217 // tdf#62955 - Allow searching a name with typing the first letter
218 m_xBasicBox
->get_widget().grab_focus();
220 if ( StarBASIC::IsRunning() )
221 m_xCloseButton
->grab_focus();
223 return SfxDialogController::run();
226 void MacroChooser::EnableButton(weld::Button
& rButton
, bool bEnable
)
230 if (nMode
== ChooseOnly
|| nMode
== Recording
)
231 rButton
.set_sensitive(&rButton
== m_xRunButton
.get());
233 rButton
.set_sensitive(true);
236 rButton
.set_sensitive(false);
239 SbMethod
* MacroChooser::GetMacro()
241 if (!m_xBasicBox
->get_cursor(m_xBasicBoxIter
.get()))
243 SbModule
* pModule
= m_xBasicBox
->FindModule(m_xBasicBoxIter
.get());
246 if (!m_xMacroBox
->get_selected(m_xMacroBoxIter
.get()))
248 OUString
aMacroName(m_xMacroBox
->get_text(*m_xMacroBoxIter
));
249 return pModule
->FindMethod(aMacroName
, SbxClassType::Method
);
252 void MacroChooser::DeleteMacro()
254 SbMethod
* pMethod
= GetMacro();
255 DBG_ASSERT( pMethod
, "DeleteMacro: No Macro !" );
256 if (!(pMethod
&& QueryDelMacro(pMethod
->GetName(), m_xDialog
.get())))
259 if (SfxDispatcher
* pDispatcher
= GetDispatcher())
260 pDispatcher
->Execute( SID_BASICIDE_STOREALLMODULESOURCES
);
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?" );
267 ScriptDocument
aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr
) );
268 if ( aDocument
.isDocument() )
270 aDocument
.setDocumentModified();
271 if (SfxBindings
* pBindings
= GetBindingsPtr())
272 pBindings
->Invalidate( SID_SAVEDOC
);
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
);
284 // update module in library
285 OUString aLibName
= pBasic
->GetName();
286 OUString aModName
= pModule
->GetName();
287 OSL_VERIFY( aDocument
.updateModule( aLibName
, aModName
, aSource
) );
289 bool bSelected
= m_xMacroBox
->get_selected(m_xMacroBoxIter
.get());
290 DBG_ASSERT(bSelected
, "DeleteMacro: Entry ?!");
291 m_xMacroBox
->remove(*m_xMacroBoxIter
);
292 bForceStoreBasic
= true;
295 SbMethod
* MacroChooser::CreateMacro()
297 SbMethod
* pMethod
= nullptr;
298 if (!m_xBasicBox
->get_cursor(m_xBasicBoxIter
.get()) && !m_xBasicBox
->get_iter_first(*m_xBasicBoxIter
))
300 SAL_WARN("basctl.basicide", "neither cursor set nor root entry to use as fallback");
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() )
309 OUString
aLibName( aDesc
.GetLibName() );
311 if ( aLibName
.isEmpty() )
312 aLibName
= "Standard" ;
314 aDocument
.getOrCreateLibrary( E_SCRIPTS
, aLibName
);
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
);
324 BasicManager
* pBasMgr
= aDocument
.getBasicManager();
325 StarBASIC
* pBasic
= pBasMgr
? pBasMgr
->GetLib( aLibName
) : nullptr;
328 SbModule
* pModule
= nullptr;
329 OUString
aModName( aDesc
.GetName() );
330 if ( !aModName
.isEmpty() )
332 // extract the module name from the string like "Sheet1 (Example1)"
333 if( aDesc
.GetLibSubName() == IDEResId(RID_STR_DOCUMENT_OBJECTS
) )
335 aModName
= aModName
.getToken( 0, ' ' );
337 pModule
= pBasic
->FindModule( aModName
);
339 else if ( !pBasic
->GetModules().empty() )
340 pModule
= pBasic
->GetModules().front().get();
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();
348 pModule
= createModImpl(m_xDialog
.get(), aDocument
, *m_xBasicBox
, aLibName
, aModName
, false);
351 DBG_ASSERT( !pModule
|| !pModule
->FindMethod( aSubName
, SbxClassType::Method
), "Macro exists already!" );
352 pMethod
= pModule
? basctl::CreateMacro( pModule
, aSubName
) : nullptr;
358 void MacroChooser::SaveSetCurEntry(weld::TreeView
& rBox
, const weld::TreeIter
& rEntry
)
360 // the edit would be killed by the highlight otherwise:
362 OUString
aSaveText(m_xMacroNameEdit
->get_text());
363 int nStartPos
, nEndPos
;
364 m_xMacroNameEdit
->get_selection_bounds(nStartPos
, nEndPos
);
366 rBox
.set_cursor(rEntry
);
368 m_xMacroNameEdit
->set_text(aSaveText
);
369 m_xMacroNameEdit
->select_region(nStartPos
, nEndPos
);
372 void MacroChooser::CheckButtons()
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();
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 )
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
) ) )
395 if (nMode
!= Recording
)
398 bool bEnable
= pMethod
!= nullptr;
399 if (nMode
!= ChooseOnly
&& StarBASIC::IsRunning())
401 EnableButton(*m_xRunButton
, bEnable
);
404 // organising still possible?
407 EnableButton(*m_xAssignButton
, pMethod
!= nullptr);
410 EnableButton(*m_xEditButton
, bMacroEntry
);
413 EnableButton(*m_xOrganizeButton
, !StarBASIC::IsRunning() && nMode
== All
);
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
);
425 m_xDelButton
->show();
426 m_xNewButton
->hide();
430 m_xNewButton
->show();
431 m_xDelButton
->hide();
435 if (nMode
== Recording
)
438 m_xRunButton
->set_sensitive(!bProtected
&& !bReadOnly
&& !bShare
);
439 // new library button
440 m_xNewLibButton
->set_sensitive(!bShare
);
442 m_xNewModButton
->set_sensitive(!bProtected
&& !bReadOnly
&& !bShare
);
446 IMPL_LINK_NOARG(MacroChooser
, MacroDoubleClickHdl
, weld::TreeView
&, bool)
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;
452 ScriptDocument
aDocument(ScriptDocument::getDocumentForBasicManager(pBasMgr
));
453 if (aDocument
.isDocument() && !aDocument
.allowMacros())
455 std::unique_ptr
<weld::MessageDialog
> xError(
456 Application::CreateMessageDialog(m_xDialog
.get(), VclMessageType::Warning
,
457 VclButtonsType::Ok
, IDEResId(RID_STR_CANNOTRUNMACRO
)));
462 StoreMacroDescription();
463 if (nMode
== Recording
)
465 if (pMethod
&& !QueryReplaceMacro(pMethod
->GetName(), m_xDialog
.get()))
469 m_xDialog
->response(Macro_OkRun
);
473 IMPL_LINK_NOARG(MacroChooser
, MacroSelectHdl
, weld::TreeView
&, void)
479 IMPL_LINK_NOARG(MacroChooser
, BasicSelectHdl
, weld::TreeView
&, void)
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();
487 m_xMacrosInTxt
->set_label(m_aMacrosInTxtBaseStr
+ " " + pModule
->GetName());
489 m_xMacroBox
->freeze();
491 sal_uInt32 nMacroCount
= pModule
->GetMethods()->Count();
492 for ( sal_uInt32 iMeth
= 0; iMeth
< nMacroCount
; iMeth
++ )
494 SbMethod
* pMethod
= static_cast<SbMethod
*>(pModule
->GetMethods()->Get(iMeth
));
495 assert(pMethod
&& "Method not found!");
496 if (pMethod
->IsHidden())
498 m_xMacroBox
->append_text(pMethod
->GetName());
503 if (m_xMacroBox
->get_iter_first(*m_xMacroBoxIter
))
504 m_xMacroBox
->set_cursor(*m_xMacroBoxIter
);
511 IMPL_LINK_NOARG(MacroChooser
, EditModifyHdl
, weld::Entry
&, void)
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()))
517 sal_uInt16 nDepth
= m_xBasicBox
->get_iter_depth(*m_xBasicBoxIter
);
518 if (nDepth
== 1 && m_xBasicBox
->IsEntryProtected(m_xBasicBoxIter
.get()))
520 // then put to the respective Std-Lib...
521 m_xBasicBox
->iter_parent(*m_xBasicBoxIter
);
522 m_xBasicBox
->iter_children(*m_xBasicBoxIter
);
526 std::unique_ptr
<weld::TreeIter
> xNewEntry(m_xBasicBox
->make_iterator());
527 m_xBasicBox
->copy_iterator(*m_xBasicBoxIter
, *xNewEntry
);
528 bool bCurEntry
= true;
531 bCurEntry
= m_xBasicBox
->iter_children(*m_xBasicBoxIter
);
534 m_xBasicBox
->copy_iterator(*m_xBasicBoxIter
, *xNewEntry
);
535 nDepth
= m_xBasicBox
->get_iter_depth(*m_xBasicBoxIter
);
538 while (bCurEntry
&& (nDepth
< 2));
539 SaveSetCurEntry(m_xBasicBox
->get_widget(), *xNewEntry
);
541 auto nCount
= m_xMacroBox
->n_children();
544 OUString
aEdtText(m_xMacroNameEdit
->get_text());
546 bool bValidIter
= m_xMacroBox
->get_iter_first(*m_xMacroBoxIter
);
549 if (m_xMacroBox
->get_text(*m_xMacroBoxIter
).equalsIgnoreAsciiCase(aEdtText
))
551 SaveSetCurEntry(*m_xMacroBox
, *m_xMacroBoxIter
);
555 bValidIter
= m_xMacroBox
->iter_next_sibling(*m_xMacroBoxIter
);
559 bValidIter
= m_xMacroBox
->get_selected(m_xMacroBoxIter
.get());
560 // if the entry exists ->Select ->Description...
562 m_xMacroBox
->unselect(*m_xMacroBoxIter
);
570 IMPL_LINK(MacroChooser
, ButtonHdl
, weld::Button
&, rButton
, void)
572 // apart from New/Record the Description is done by LoseFocus
573 if (&rButton
== m_xRunButton
.get())
575 StoreMacroDescription();
577 // #116444# check security settings before macro execution
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;
586 ScriptDocument
aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr
) );
587 if ( aDocument
.isDocument() && !aDocument
.allowMacros() )
589 std::unique_ptr
<weld::MessageDialog
> xError(Application::CreateMessageDialog(m_xDialog
.get(),
590 VclMessageType::Warning
, VclButtonsType::Ok
, IDEResId(RID_STR_CANNOTRUNMACRO
)));
596 else if (nMode
== Recording
)
598 if ( !IsValidSbxName(m_xMacroNameEdit
->get_text()) )
600 std::unique_ptr
<weld::MessageDialog
> xError(Application::CreateMessageDialog(m_xDialog
.get(),
601 VclMessageType::Warning
, VclButtonsType::Ok
, IDEResId(RID_STR_BADSBXNAME
)));
603 m_xMacroNameEdit
->select_region(0, -1);
604 m_xMacroNameEdit
->grab_focus();
608 SbMethod
* pMethod
= GetMacro();
609 if (pMethod
&& !QueryReplaceMacro(pMethod
->GetName(), m_xDialog
.get()))
613 m_xDialog
->response(Macro_OkRun
);
615 else if (&rButton
== m_xCloseButton
.get())
617 StoreMacroDescription();
618 m_xDialog
->response(Macro_Close
);
620 else if (&rButton
== m_xEditButton
.get() || &rButton
== m_xDelButton
.get() || &rButton
== m_xNewButton
.get())
622 if (!m_xBasicBox
->get_cursor(m_xBasicBoxIter
.get()) && !m_xBasicBox
->get_iter_first(*m_xBasicBoxIter
))
624 SAL_WARN("basctl.basicide", "neither cursor set nor root entry to use as fallback");
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() )
632 BasicManager
* pBasMgr
= aDocument
.getBasicManager();
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
) )
638 aMod
= aMod
.getToken( 0, ' ' );
640 const OUString
& aSub( aDesc
.GetMethodName() );
641 SfxMacroInfoItem
aInfoItem( SID_BASICIDE_ARG_MACROINFO
, pBasMgr
, aLib
, aMod
, aSub
, OUString() );
642 if (&rButton
== m_xEditButton
.get())
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
649 SfxAllItemSet
aArgs( SfxGetpApp()->GetPool() );
650 SfxRequest
aRequest( SID_BASICIDE_APPEAR
, SfxCallMode::SYNCHRON
, aArgs
);
651 SfxGetpApp()->ExecuteSlot( aRequest
);
653 if (SfxDispatcher
* pDispatcher
= GetDispatcher())
655 pDispatcher
->ExecuteList(SID_BASICIDE_EDITMACRO
,
656 SfxCallMode::ASYNCHRON
, { &aInfoItem
});
658 m_xDialog
->response(Macro_Edit
);
662 if (&rButton
== m_xDelButton
.get())
665 if (SfxDispatcher
* pDispatcher
= GetDispatcher())
667 pDispatcher
->ExecuteList( SID_BASICIDE_UPDATEMODULESOURCE
,
668 SfxCallMode::SYNCHRON
, { &aInfoItem
});
672 //if ( m_xMacroBox->GetCurEntry() ) // OV-Bug ?
673 // m_xMacroBox->Select( m_xMacroBox->GetCurEntry() );
677 if ( !IsValidSbxName(m_xMacroNameEdit
->get_text()) )
679 std::unique_ptr
<weld::MessageDialog
> xError(Application::CreateMessageDialog(m_xDialog
.get(),
680 VclMessageType::Warning
, VclButtonsType::Ok
, IDEResId(RID_STR_BADSBXNAME
)));
682 m_xMacroNameEdit
->select_region(0, -1);
683 m_xMacroNameEdit
->grab_focus();
686 SbMethod
* pMethod
= CreateMacro();
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
);
696 if (SfxDispatcher
* pDispatcher
= GetDispatcher())
698 pDispatcher
->ExecuteList(SID_BASICIDE_EDITMACRO
,
699 SfxCallMode::ASYNCHRON
, { &aInfoItem
});
701 StoreMacroDescription();
702 m_xDialog
->response(Macro_New
);
707 else if (&rButton
== m_xAssignButton
.get())
709 if (!m_xBasicBox
->get_cursor(m_xBasicBoxIter
.get()) && !m_xBasicBox
->get_iter_first(*m_xBasicBoxIter
))
711 SAL_WARN("basctl.basicide", "neither cursor set nor root entry to use as fallback");
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() )
719 BasicManager
* pBasMgr
= aDocument
.getBasicManager();
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() );
730 SfxAllItemSet
aInternalSet(SfxGetpApp()->GetPool());
731 if (m_xDocumentFrame
.is())
732 aInternalSet
.Put(SfxUnoFrameItem(SID_FILLFRAME
, m_xDocumentFrame
));
734 SfxRequest
aRequest(SID_CONFIGACCEL
, SfxCallMode::SYNCHRON
, Args
, aInternalSet
);
735 aRequest
.AppendItem( aItem
);
736 SfxGetpApp()->ExecuteSlot( aRequest
);
738 else if (&rButton
== m_xNewLibButton
.get())
740 if (!m_xBasicBox
->get_cursor(m_xBasicBoxIter
.get()) && !m_xBasicBox
->get_iter_first(*m_xBasicBoxIter
))
742 SAL_WARN("basctl.basicide", "neither cursor set nor root entry to use as fallback");
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());
749 else if (&rButton
== m_xNewModButton
.get())
751 if (!m_xBasicBox
->get_cursor(m_xBasicBoxIter
.get()) && !m_xBasicBox
->get_iter_first(*m_xBasicBoxIter
))
753 SAL_WARN("basctl.basicide", "neither cursor set nor root entry to use as fallback");
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);
761 else if (&rButton
== m_xOrganizeButton
.get())
763 StoreMacroDescription();
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
770 m_xDialog
->response(Macro_Edit
);
774 Shell
* pShell
= GetShell();
775 if ( pShell
&& pShell
->IsAppBasicModified() )
776 bForceStoreBasic
= true;
778 m_xBasicBox
->UpdateEntries();
783 IMPL_LINK(MacroChooser
, ContextMenuHdl
, const CommandEvent
&, rCEvt
, bool)
785 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
|| !m_xMacroBox
->n_children())
788 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(m_xMacroBox
.get(), u
"modules/BasicIDE/ui/sortmenu.ui"_ustr
));
789 std::unique_ptr
<weld::Menu
> xPopup(xBuilder
->weld_menu(u
"sortmenu"_ustr
));
790 std::unique_ptr
<weld::Menu
> xDropMenu(xBuilder
->weld_menu(u
"sortsubmenu"_ustr
));
791 xDropMenu
->set_active(u
"alphabetically"_ustr
, m_xMacroBox
->get_sort_order());
792 xDropMenu
->set_active(u
"properorder"_ustr
, !m_xMacroBox
->get_sort_order());
794 OUString
sCommand(xPopup
->popup_at_rect(m_xMacroBox
.get(), tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1,1))));
795 if (sCommand
== "alphabetically")
797 m_xMacroBox
->make_sorted();
799 else if (sCommand
== "properorder")
801 m_xMacroBox
->make_unsorted();
802 BasicSelectHdl(m_xBasicBox
->get_widget());
804 else if (!sCommand
.isEmpty())
806 SAL_WARN("basctl.basicide", "Unknown context menu action: " << sCommand
);
812 void MacroChooser::UpdateFields()
814 auto nMacroEntry
= m_xMacroBox
->get_selected_index();
815 m_xMacroNameEdit
->set_text(u
""_ustr
);
816 if (nMacroEntry
!= -1)
817 m_xMacroNameEdit
->set_text(m_xMacroBox
->get_text(nMacroEntry
));
820 void MacroChooser::SetMode (Mode nM
)
827 m_xRunButton
->set_label(IDEResId(RID_STR_RUN
));
828 EnableButton(*m_xDelButton
, true);
829 EnableButton(*m_xNewButton
, true);
830 EnableButton(*m_xOrganizeButton
, true);
836 m_xRunButton
->set_label(IDEResId(RID_STR_CHOOSE
));
837 EnableButton(*m_xDelButton
, false);
838 EnableButton(*m_xNewButton
, false);
839 EnableButton(*m_xOrganizeButton
, false);
845 m_xRunButton
->set_label(IDEResId(RID_STR_RECORD
));
846 EnableButton(*m_xDelButton
, false);
847 EnableButton(*m_xNewButton
, false);
848 EnableButton(*m_xOrganizeButton
, false);
850 m_xAssignButton
->hide();
851 m_xEditButton
->hide();
852 m_xDelButton
->hide();
853 m_xNewButton
->hide();
854 m_xOrganizeButton
->hide();
855 m_xMacroFromTxT
->hide();
857 m_xNewLibButton
->show();
858 m_xNewModButton
->show();
859 m_xMacrosSaveInTxt
->show();
867 OUString
MacroChooser::GetInfo( SbxVariable
* pVar
)
870 SbxInfoRef xInfo
= pVar
->GetInfo();
872 aComment
= xInfo
->GetComment();
877 } // namespace basctl
879 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */