basctl/Library_basctl.mk | 2 basctl/inc/pch/precompiled_basctl.hxx | 2 basctl/source/basicide/basobj3.cxx | 2 basctl/source/basicide/bastypes.cxx | 5 basctl/source/basicide/doceventnotifier.cxx | 2 basctl/source/basicide/docsignature.cxx | 2 basctl/source/basicide/moduldl2.cxx | 145 basctl/source/basicide/moduldlg.hxx | 15 basctl/source/basicide/sbxitem.cxx | 2 basctl/source/basicide/scriptdocument.cxx | 2 basctl/source/inc/IDEComboBox.hxx | 2 basctl/source/inc/basidesh.hxx | 2 basctl/source/inc/basobj.hxx | 9 basctl/source/inc/bastype2.hxx | 2 basctl/source/inc/bastypes.hxx | 10 basctl/source/inc/localizationmgr.hxx | 2 chart2/uiconfig/menubar/menubar.xml | 2 cui/Library_cui.mk | 2 cui/UIConfig_cui.mk | 1 cui/inc/bitmaps.hlst | 3 cui/inc/strings.hrc | 29 cui/source/customize/cfgutil.cxx | 137 cui/source/dialogs/MacroManagerDialog.cxx | 2512 ++++++++++ cui/source/factory/dlgfact.cxx | 15 cui/source/factory/dlgfact.hxx | 13 cui/source/inc/MacroManagerDialog.hxx | 255 + cui/source/inc/cfgutil.hxx | 10 cui/uiconfig/ui/macromanagerdialog.ui | 564 ++ dbaccess/uiconfig/dbapp/menubar/menubar.xml | 2 dbaccess/uiconfig/dbquery/menubar/menubar.xml | 2 dbaccess/uiconfig/dbrelation/menubar/menubar.xml | 2 dbaccess/uiconfig/dbtable/menubar/menubar.xml | 2 dbaccess/uiconfig/dbtdata/menubar/menubar.xml | 2 extensions/uiconfig/sbibliography/menubar/menubar.xml | 2 framework/uiconfig/startmodule/menubar/menubar.xml | 2 include/basctl/basctldllapi.h | 23 include/basctl/basctldllpublic.hxx | 43 include/basctl/sbxitem.hxx | 3 include/basctl/scriptdocument.hxx | 4 include/sfx2/minfitem.hxx | 5 include/sfx2/sfxdlg.hxx | 15 include/sfx2/sfxsids.hrc | 1 include/svl/hint.hxx | 3 include/svx/passwd.hxx | 2 include/svx/svxdlg.hxx | 3 officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu | 11 reportdesign/uiconfig/dbreport/menubar/menubar.xml | 2 sc/uiconfig/scalc/menubar/menubar.xml | 2 sd/uiconfig/sdraw/menubar/menubar.xml | 2 sd/uiconfig/simpress/menubar/menubar.xml | 2 sfx2/sdi/appslots.sdi | 5 sfx2/sdi/sfx.sdi | 17 sfx2/source/appl/appserv.cxx | 51 sfx2/source/control/minfitem.cxx | 6 solenv/clang-format/excludelist | 4 starmath/uiconfig/smath/menubar/menubar.xml | 2 sw/uiconfig/sglobal/menubar/menubar.xml | 2 sw/uiconfig/sweb/menubar/menubar.xml | 2 sw/uiconfig/swform/menubar/menubar.xml | 2 sw/uiconfig/swreport/menubar/menubar.xml | 2 sw/uiconfig/swriter/menubar/menubar.xml | 2 sw/uiconfig/swxform/menubar/menubar.xml | 2 62 files changed, 3830 insertions(+), 151 deletions(-)
New commits: commit 55e86edcb37a37123a69ce3e1eb9e20758415fb6 Author: Jim Raykowski <[email protected]> AuthorDate: Mon Oct 7 10:56:34 2024 -0800 Commit: Jim Raykowski <[email protected]> CommitDate: Mon Dec 2 07:13:00 2024 +0100 tdf#120658 - Reworking of dialogues Organize macros (make from 5 existing only one) Much of what makes up this patch is adapted from existing code that is used to organize and select macros and to assign macros to shortcut keys. Comments in the patch say where code is borrowed from. Known issues: + Scripting framework library rename for BeanShell, Java, and JavaScript always returns fail when there are no macro entries in the library even though it actually succeeds. The same thing happens using SvxScriptOrgDialog::renameEntry. + Deleting Basic macros from the Macro Manager dialog is not implemented yet. Change-Id: If4da04549f8b39675910cbbd1f94dd9a6b73c31a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176254 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> diff --git a/basctl/Library_basctl.mk b/basctl/Library_basctl.mk index cb41fa9e461c..9006a9aadd17 100644 --- a/basctl/Library_basctl.mk +++ b/basctl/Library_basctl.mk @@ -29,6 +29,8 @@ $(eval $(call gb_Library_set_include,basctl,\ -I$(WORKDIR)/SdiTarget/basctl/sdi \ )) +$(eval $(call gb_Library_add_defs,basctl,-DBASCTL_DLLIMPLEMENTATION)) + $(eval $(call gb_Library_use_external,basctl,boost_headers)) $(eval $(call gb_Library_use_custom_headers,basctl,\ diff --git a/basctl/inc/pch/precompiled_basctl.hxx b/basctl/inc/pch/precompiled_basctl.hxx index 1794f96f90e9..41afc13b5199 100644 --- a/basctl/inc/pch/precompiled_basctl.hxx +++ b/basctl/inc/pch/precompiled_basctl.hxx @@ -576,7 +576,7 @@ #include <iderid.hxx> #include <localizationmgr.hxx> #include <managelang.hxx> -#include <scriptdocument.hxx> +#include <basctl/scriptdocument.hxx> #endif // PCH_LEVEL >= 4 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/basicide/basobj3.cxx b/basctl/source/basicide/basobj3.cxx index 8e1eaf40c79f..44c5adc072b8 100644 --- a/basctl/source/basicide/basobj3.cxx +++ b/basctl/source/basicide/basobj3.cxx @@ -244,6 +244,8 @@ BasicManager* FindBasicManager( StarBASIC const * pLib ) void MarkDocumentModified( const ScriptDocument& rDocument ) { + SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScriptDocumentChanged)); + Shell* pShell = GetShell(); // does not have to come from a document... diff --git a/basctl/source/basicide/bastypes.cxx b/basctl/source/basicide/bastypes.cxx index edc9fe32149a..e01b9d1861dd 100644 --- a/basctl/source/basicide/bastypes.cxx +++ b/basctl/source/basicide/bastypes.cxx @@ -764,21 +764,26 @@ bool QueryReplaceMacro( std::u16string_view rName, weld::Widget* pParent ) bool QueryDelDialog( std::u16string_view rName, weld::Widget* pParent ) { + EnsureIde(); return QueryDel( rName, IDEResId( RID_STR_QUERYDELDIALOG ), pParent ); } bool QueryDelLib( std::u16string_view rName, bool bRef, weld::Widget* pParent ) { + EnsureIde(); return QueryDel( rName, IDEResId( bRef ? RID_STR_QUERYDELLIBREF : RID_STR_QUERYDELLIB ), pParent ); } bool QueryDelModule( std::u16string_view rName, weld::Widget* pParent ) { + EnsureIde(); return QueryDel( rName, IDEResId( RID_STR_QUERYDELMODULE ), pParent ); } bool QueryPassword(weld::Widget* pDialogParent, const Reference< script::XLibraryContainer >& xLibContainer, const OUString& rLibName, OUString& rPassword, bool bRepeat, bool bNewTitle) { + EnsureIde(); + bool bOK = false; sal_uInt16 nRet = 0; diff --git a/basctl/source/basicide/doceventnotifier.cxx b/basctl/source/basicide/doceventnotifier.cxx index abee782c09fe..2365aef2ee16 100644 --- a/basctl/source/basicide/doceventnotifier.cxx +++ b/basctl/source/basicide/doceventnotifier.cxx @@ -18,7 +18,7 @@ */ #include <doceventnotifier.hxx> -#include <scriptdocument.hxx> +#include <basctl/scriptdocument.hxx> #include <com/sun/star/frame/theGlobalEventBroadcaster.hpp> diff --git a/basctl/source/basicide/docsignature.cxx b/basctl/source/basicide/docsignature.cxx index ee04435274db..f516a4d24458 100644 --- a/basctl/source/basicide/docsignature.cxx +++ b/basctl/source/basicide/docsignature.cxx @@ -18,7 +18,7 @@ */ #include <docsignature.hxx> -#include <scriptdocument.hxx> +#include <basctl/scriptdocument.hxx> #include <sfx2/objsh.hxx> #include <sfx2/signaturestate.hxx> diff --git a/basctl/source/basicide/moduldl2.cxx b/basctl/source/basicide/moduldl2.cxx index 5b3d49547dc7..49cf87a2d0d8 100644 --- a/basctl/source/basicide/moduldl2.cxx +++ b/basctl/source/basicide/moduldl2.cxx @@ -464,7 +464,13 @@ IMPL_LINK( LibPage, ButtonHdl, weld::Button&, rButton, void ) else if (&rButton == m_xInsertLibButton.get()) InsertLib(); else if (&rButton == m_xExportButton.get()) - Export(); + { + std::unique_ptr<weld::TreeIter> xCurEntry(m_xLibBox->make_iterator()); + if (!m_xLibBox->get_cursor(xCurEntry.get())) + return; + OUString aLibName(m_xLibBox->get_text(*xCurEntry, 0)); + Export(m_aCurDocument, aLibName, m_pDialog->getDialog()); + } else if (&rButton == m_xDelButton.get()) DeleteCurrent(); else if (&rButton == m_xPasswordButton.get()) @@ -565,9 +571,32 @@ void LibPage::NewLib() void LibPage::InsertLib() { + auto remove_entry = [this](OUString& rLibName) { // remove listbox entry + int nEntry = FindEntry(*m_xLibBox, rLibName); + if (nEntry != -1) + m_xLibBox->remove(nEntry); + }; + + auto insert_entry = [this](OUString& rLibName) { // insert listbox entry + m_xLibBox->make_unsorted(); + ImpInsertLibEntry(rLibName, m_xLibBox->n_children()); + m_xLibBox->make_sorted(); + m_xLibBox->set_cursor(m_xLibBox->find_text(rLibName)); + }; + + ImportLib(m_aCurDocument, m_pDialog->getDialog(), remove_entry, insert_entry, {}); +} + +void ImportLib(const ScriptDocument& rDocument, weld::Dialog* pDialog, + const std::function<void(OUString& rLibName)>& func_remove_entry, + const std::function<void(OUString& rLibName)>& func_insert_entry, + const std::function<void()>& func_insert_entries) +{ + basctl::EnsureIde(); + const Reference< uno::XComponentContext >& xContext( ::comphelper::getProcessComponentContext() ); // file open dialog - sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, m_pDialog->getDialog()); + sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, pDialog); aDlg.SetContext(sfx2::FileDialogHelper::BasicInsertLib); const Reference <XFilePicker3>& xFP = aDlg.GetFilePicker(); @@ -643,7 +672,7 @@ void LibPage::InsertLib() if (aLibNames.hasElements()) { // library import dialog - xLibDlg = std::make_shared<LibDialog>(m_pDialog->getDialog()); + xLibDlg = std::make_shared<LibDialog>(pDialog); xLibDlg->SetStorageName(aURLObj.getName()); weld::TreeView& rView = xLibDlg->GetLibBox(); rView.make_unsorted(); @@ -671,7 +700,7 @@ void LibPage::InsertLib() if (!xLibDlg) { - std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(), + std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pDialog, VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_NOLIBINSTORAGE))); xErrorBox->run(); return; @@ -685,9 +714,12 @@ void LibPage::InsertLib() if ( aExtension != aLibExtension && aExtension != aContExtension ) xLibDlg->EnableReference(false); - weld::DialogController::runAsync(xLibDlg, [aContExtension, xDlgURLObj=std::move(xDlgURLObj), aExtension, - aLibExtension, xModURLObj=std::move(xModURLObj), xLibDlg, - xDlgLibContImport, xModLibContImport, this](sal_Int32 nResult) + weld::DialogController::runAsync( + xLibDlg, + [aContExtension, xDlgURLObj = std::move(xDlgURLObj), aExtension, aLibExtension, + xModURLObj = std::move(xModURLObj), xLibDlg, xDlgLibContImport, xModLibContImport, + rDocument, pDialog, func_remove_entry, func_insert_entry, + func_insert_entries](sal_Int32 nResult) { if (!nResult ) return; @@ -702,8 +734,10 @@ void LibPage::InsertLib() if (rView.get_toggle(nLib) == TRISTATE_TRUE) { OUString aLibName(rView.get_text(nLib)); - Reference< script::XLibraryContainer2 > xModLibContainer( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY ); - Reference< script::XLibraryContainer2 > xDlgLibContainer( m_aCurDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY ); + Reference<script::XLibraryContainer2> xModLibContainer( + rDocument.getLibraryContainer(E_SCRIPTS), UNO_QUERY); + Reference<script::XLibraryContainer2> xDlgLibContainer( + rDocument.getLibraryContainer(E_DIALOGS), UNO_QUERY); // check, if the library is already existing if ( ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) ) || @@ -714,8 +748,10 @@ void LibPage::InsertLib() // check, if the library is the Standard library if ( aLibName == "Standard" ) { - std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(), - VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_REPLACESTDLIB))); + std::unique_ptr<weld::MessageDialog> xErrorBox( + Application::CreateMessageDialog( + pDialog, VclMessageType::Warning, VclButtonsType::Ok, + IDEResId(RID_STR_REPLACESTDLIB))); xErrorBox->run(); continue; } @@ -726,8 +762,10 @@ void LibPage::InsertLib() { OUString aErrStr( IDEResId(RID_STR_REPLACELIB) ); aErrStr = aErrStr.replaceAll("XX", aLibName) + " " + IDEResId(RID_STR_LIBISREADONLY); - std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(), - VclMessageType::Warning, VclButtonsType::Ok, aErrStr)); + std::unique_ptr<weld::MessageDialog> xErrorBox( + Application::CreateMessageDialog(pDialog, + VclMessageType::Warning, + VclButtonsType::Ok, aErrStr)); xErrorBox->run(); continue; } @@ -743,8 +781,9 @@ void LibPage::InsertLib() else aErrStr = IDEResId(RID_STR_IMPORTNOTPOSSIBLE); aErrStr = aErrStr.replaceAll("XX", aLibName) + " " +IDEResId(RID_STR_SBXNAMEALLREADYUSED); - std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(), - VclMessageType::Warning, VclButtonsType::Ok, aErrStr)); + std::unique_ptr<weld::MessageDialog> xErrorBox( + Application::CreateMessageDialog(pDialog, VclMessageType::Warning, + VclButtonsType::Ok, aErrStr)); xErrorBox->run(); continue; } @@ -758,14 +797,17 @@ void LibPage::InsertLib() Reference< script::XLibraryContainerPassword > xPasswd( xModLibContImport, UNO_QUERY ); if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aLibName ) && !xPasswd->isLibraryPasswordVerified( aLibName ) && !bReference ) { - bOK = QueryPassword(m_pDialog->getDialog(), xModLibContImport, aLibName, aPassword, true, true); + bOK = QueryPassword(pDialog, xModLibContImport, aLibName, aPassword, + true, true); if ( !bOK ) { OUString aErrStr( IDEResId(RID_STR_NOIMPORT) ); aErrStr = aErrStr.replaceAll("XX", aLibName); - std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(), - VclMessageType::Warning, VclButtonsType::Ok, aErrStr)); + std::unique_ptr<weld::MessageDialog> xErrorBox( + Application::CreateMessageDialog(pDialog, + VclMessageType::Warning, + VclButtonsType::Ok, aErrStr)); xErrorBox->run(); continue; } @@ -775,10 +817,7 @@ void LibPage::InsertLib() // remove existing libraries if ( bRemove ) { - // remove listbox entry - int nEntry_ = FindEntry(*m_xLibBox, aLibName); - if (nEntry_ != -1) - m_xLibBox->remove(nEntry_); + func_remove_entry(aLibName); // LibPage::InsertLib // remove module library if ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) ) @@ -901,29 +940,24 @@ void LibPage::InsertLib() } } - // insert listbox entry - m_xLibBox->make_unsorted(); - ImpInsertLibEntry( aLibName, m_xLibBox->n_children() ); - m_xLibBox->make_sorted(); - m_xLibBox->set_cursor( m_xLibBox->find_text(aLibName) ); + func_insert_entry(aLibName); // LibPage::InsertLib bChanges = true; } } - if ( bChanges ) - MarkDocumentModified( m_aCurDocument ); + if (bChanges) + { + func_insert_entries(); // MacroManager + MarkDocumentModified(rDocument); + } }); } -void LibPage::Export() +void Export(const ScriptDocument& rDocument, const OUString& aLibName, weld::Dialog* pDialog) { - std::unique_ptr<weld::TreeIter> xCurEntry(m_xLibBox->make_iterator()); - if (!m_xLibBox->get_cursor(xCurEntry.get())) - return; - OUString aLibName(m_xLibBox->get_text(*xCurEntry, 0)); - // Password verification - Reference< script::XLibraryContainer2 > xModLibContainer( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY ); + Reference<script::XLibraryContainer2> xModLibContainer(rDocument.getLibraryContainer(E_SCRIPTS), + UNO_QUERY); if ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && !xModLibContainer->isLibraryLoaded( aLibName ) ) { @@ -934,13 +968,13 @@ void LibPage::Export() if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aLibName ) && !xPasswd->isLibraryPasswordVerified( aLibName ) ) { OUString aPassword; - bOK = QueryPassword(m_pDialog->getDialog(), xModLibContainer, aLibName, aPassword); + bOK = QueryPassword(pDialog, xModLibContainer, aLibName, aPassword); } if ( !bOK ) return; } - std::unique_ptr<ExportDialog> xNewDlg(new ExportDialog(m_pDialog->getDialog())); + std::unique_ptr<ExportDialog> xNewDlg(new ExportDialog(pDialog)); if (xNewDlg->run() != RET_OK) return; @@ -951,24 +985,24 @@ void LibPage::Export() //parent of file dialog from ExportAs... xNewDlg.reset(); if (bExportAsPackage) - ExportAsPackage( aLibName ); + ExportAsPackage(rDocument, aLibName, pDialog); else - ExportAsBasic( aLibName ); + ExportAsBasic(rDocument, aLibName, pDialog); } catch(const util::VetoException& ) // user canceled operation { } } -void LibPage::implExportLib( const OUString& aLibName, const OUString& aTargetURL, - const Reference< task::XInteractionHandler >& Handler ) +void implExportLib(const ScriptDocument& rScriptDocument, const OUString& aLibName, + const OUString& aTargetURL, const Reference<task::XInteractionHandler>& Handler) { - Reference< script::XLibraryContainerExport > xModLibContainerExport - ( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY ); - Reference< script::XLibraryContainerExport > xDlgLibContainerExport - ( m_aCurDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY ); + Reference<script::XLibraryContainerExport> xModLibContainerExport( + rScriptDocument.getLibraryContainer(E_SCRIPTS), UNO_QUERY); + Reference<script::XLibraryContainerExport> xDlgLibContainerExport( + rScriptDocument.getLibraryContainer(E_DIALOGS), UNO_QUERY); if ( xModLibContainerExport.is() ) - xModLibContainerExport->exportLibrary( aLibName, aTargetURL, Handler ); + xModLibContainerExport->exportLibrary(aLibName, aTargetURL, Handler); if (!xDlgLibContainerExport.is()) return; @@ -1011,10 +1045,13 @@ Reference< XProgressHandler > OLibCommandEnvironment::getProgressHandler() return xRet; } -void LibPage::ExportAsPackage( const OUString& aLibName ) +void ExportAsPackage(const ScriptDocument& rScriptDocument, const OUString& aLibName, + weld::Dialog* pDialog) { + EnsureIde(); // file open dialog - sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILESAVE_SIMPLE, FileDialogFlags::NONE, m_pDialog->getDialog()); + sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILESAVE_SIMPLE, + FileDialogFlags::NONE, pDialog); aDlg.SetContext(sfx2::FileDialogHelper::BasicExportPackage); const Reference <XFilePicker3>& xFP = aDlg.GetFilePicker(); @@ -1049,7 +1086,7 @@ void LibPage::ExportAsPackage( const OUString& aLibName ) if( xSFA->exists( aSourcePath ) ) xSFA->kill( aSourcePath ); Reference< task::XInteractionHandler > xDummyHandler( new DummyInteractionHandler( xHandler ) ); - implExportLib( aLibName, aTmpPath, xDummyHandler ); + implExportLib(rScriptDocument, aLibName, aTmpPath, xDummyHandler); Reference< XCommandEnvironment > xCmdEnv = new OLibCommandEnvironment(xHandler); @@ -1113,11 +1150,13 @@ void LibPage::ExportAsPackage( const OUString& aLibName ) xSFA->kill( aMetaInfFolder ); } -void LibPage::ExportAsBasic( const OUString& aLibName ) +void ExportAsBasic(const ScriptDocument& rScriptDocument, const OUString& aLibName, + weld::Dialog* pDialog) { + EnsureIde(); // Folder picker const Reference< uno::XComponentContext >& xContext( ::comphelper::getProcessComponentContext() ); - Reference< XFolderPicker2 > xFolderPicker = sfx2::createFolderPicker(xContext, m_pDialog->getDialog()); + Reference<XFolderPicker2> xFolderPicker = sfx2::createFolderPicker(xContext, pDialog); Reference< task::XInteractionHandler2 > xHandler( task::InteractionHandler::createWithParent(xContext, nullptr) ); xFolderPicker->setTitle(IDEResId(RID_STR_EXPORTBASIC)); @@ -1136,7 +1175,7 @@ void LibPage::ExportAsBasic( const OUString& aLibName ) GetExtraData()->SetAddLibPath(aTargetURL); Reference< task::XInteractionHandler > xDummyHandler( new DummyInteractionHandler( xHandler ) ); - implExportLib( aLibName, aTargetURL, xDummyHandler ); + implExportLib(rScriptDocument, aLibName, aTargetURL, xDummyHandler); } } diff --git a/basctl/source/basicide/moduldlg.hxx b/basctl/source/basicide/moduldlg.hxx index c6ff166c5bb7..4491a4709371 100644 --- a/basctl/source/basicide/moduldlg.hxx +++ b/basctl/source/basicide/moduldlg.hxx @@ -27,6 +27,8 @@ #include <vcl/weld.hxx> #include <com/sun/star/task/XInteractionHandler.hpp> +#include <basctl/basctldllpublic.hxx> + class SvxPasswordDialog; namespace basctl @@ -185,11 +187,6 @@ class LibPage final : public OrganizePage void DeleteCurrent(); void NewLib(); void InsertLib(); - void implExportLib( const OUString& aLibName, const OUString& aTargetURL, - const css::uno::Reference< css::task::XInteractionHandler >& Handler ); - void Export(); - void ExportAsPackage( const OUString& aLibName ); - void ExportAsBasic( const OUString& aLibName ); void EndTabDialog(); void FillListBox(); void InsertListBoxEntry( const ScriptDocument& rDocument, LibraryLocation eLocation ); @@ -202,6 +199,14 @@ public: virtual void ActivatePage() override; }; +void implExportLib(const ScriptDocument& rScriptDocument, const OUString& aLibName, + const OUString& aTargetURL, + const css::uno::Reference<css::task::XInteractionHandler>& Handler); +void ExportAsPackage(const ScriptDocument& rScriptDocument, const OUString& aLibName, + weld::Dialog* pDialog); +void ExportAsBasic(const ScriptDocument& rScriptDocument, const OUString& aLibName, + weld::Dialog* pDialog); + class OrganizeDialog : public weld::GenericDialogController { private: diff --git a/basctl/source/basicide/sbxitem.cxx b/basctl/source/basicide/sbxitem.cxx index b3ceccc4727d..8d098c5ab68e 100644 --- a/basctl/source/basicide/sbxitem.cxx +++ b/basctl/source/basicide/sbxitem.cxx @@ -17,7 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include <sbxitem.hxx> +#include <basctl/sbxitem.hxx> #include <sal/log.hxx> #include <utility> diff --git a/basctl/source/basicide/scriptdocument.cxx b/basctl/source/basicide/scriptdocument.cxx index 00ef24a1b279..722c5c1d8ba8 100644 --- a/basctl/source/basicide/scriptdocument.cxx +++ b/basctl/source/basicide/scriptdocument.cxx @@ -18,7 +18,7 @@ */ #include <memory> -#include <scriptdocument.hxx> +#include <basctl/scriptdocument.hxx> #include <basobj.hxx> #include <strings.hrc> #include <iderid.hxx> diff --git a/basctl/source/inc/IDEComboBox.hxx b/basctl/source/inc/IDEComboBox.hxx index a5e7008a42e9..0baf28b13cac 100644 --- a/basctl/source/inc/IDEComboBox.hxx +++ b/basctl/source/inc/IDEComboBox.hxx @@ -24,7 +24,7 @@ #include <vcl/InterimItemWindow.hxx> #include "doceventnotifier.hxx" -#include "scriptdocument.hxx" +#include <basctl/scriptdocument.hxx> namespace basctl { diff --git a/basctl/source/inc/basidesh.hxx b/basctl/source/inc/basidesh.hxx index 3bf3abaa1a05..c1cedb982046 100644 --- a/basctl/source/inc/basidesh.hxx +++ b/basctl/source/inc/basidesh.hxx @@ -19,7 +19,7 @@ #pragma once #include "doceventnotifier.hxx" -#include "sbxitem.hxx" +#include <basctl/sbxitem.hxx> #include "ObjectCatalog.hxx" #include <com/sun/star/container/XContainerListener.hpp> diff --git a/basctl/source/inc/basobj.hxx b/basctl/source/inc/basobj.hxx index 95e46b097f56..01ac1cbbb13a 100644 --- a/basctl/source/inc/basobj.hxx +++ b/basctl/source/inc/basobj.hxx @@ -18,7 +18,8 @@ */ #pragma once -#include "scriptdocument.hxx" +#include <basctl/basctldllpublic.hxx> +#include <basctl/scriptdocument.hxx> #include <tools/long.hxx> class SbMethod; @@ -44,14 +45,10 @@ namespace basctl void BasicStopped( bool* pbAppWindowDisabled = nullptr, bool* pbDispatcherLocked = nullptr, sal_uInt16* pnWaitCount = nullptr, SfxUInt16Item** ppSWActionCount = nullptr, SfxUInt16Item** ppSWLockViewCount = nullptr ); - bool IsValidSbxName( std::u16string_view rName ); - SAL_RET_MAYBENULL BasicManager* FindBasicManager( StarBASIC const * pLib ); SAL_RET_MAYBENULL SfxBindings* GetBindingsPtr(); - SAL_RET_MAYBENULL SfxDispatcher* GetDispatcher (); - void InvalidateDebuggerSlots(); // libraries @@ -98,8 +95,6 @@ namespace basctl bool RemoveDialog( const ScriptDocument& rDocument, const OUString& rLibName, const OUString& rDlgName ); - void MarkDocumentModified( const ScriptDocument& rDocument ); - } // namespace basctl /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/inc/bastype2.hxx b/basctl/source/inc/bastype2.hxx index 34115a1dff7d..292d59b3ea8a 100644 --- a/basctl/source/inc/bastype2.hxx +++ b/basctl/source/inc/bastype2.hxx @@ -26,7 +26,7 @@ #include "doceventnotifier.hxx" #include <vcl/weld.hxx> -#include "sbxitem.hxx" +#include <basctl/sbxitem.hxx> #include <o3tl/typed_flags_set.hxx> class SbModule; diff --git a/basctl/source/inc/bastypes.hxx b/basctl/source/inc/bastypes.hxx index ecd744528056..e0362ef2163b 100644 --- a/basctl/source/inc/bastypes.hxx +++ b/basctl/source/inc/bastypes.hxx @@ -18,9 +18,9 @@ */ #pragma once -#include "scriptdocument.hxx" - -#include "sbxitem.hxx" +#include <basctl/basctldllpublic.hxx> +#include <basctl/scriptdocument.hxx> +#include <basctl/sbxitem.hxx> #include <svtools/scrolladaptor.hxx> #include <svtools/tabbar.hxx> #include <basic/sbdef.hxx> @@ -297,10 +297,6 @@ sal_uInt32 CalcLineCount( SvStream& rStream ); bool QueryReplaceMacro( std::u16string_view rName, weld::Widget* pParent ); bool QueryDelMacro( std::u16string_view rName, weld::Widget* pParent ); -bool QueryDelDialog( std::u16string_view rName, weld::Widget* pParent ); -bool QueryDelModule( std::u16string_view rName, weld::Widget* pParent ); -bool QueryDelLib( std::u16string_view rName, bool bRef, weld::Widget* pParent ); -bool QueryPassword(weld::Widget* pDialogParent, const css::uno::Reference< css::script::XLibraryContainer >& xLibContainer, const OUString& rLibName, OUString& rPassword, bool bRepeat = false, bool bNewTitle = false); class ModuleInfoHelper { diff --git a/basctl/source/inc/localizationmgr.hxx b/basctl/source/inc/localizationmgr.hxx index 3e2ff0fc58a8..1070e609f18d 100644 --- a/basctl/source/inc/localizationmgr.hxx +++ b/basctl/source/inc/localizationmgr.hxx @@ -23,7 +23,7 @@ #include <string_view> -#include "scriptdocument.hxx" +#include <basctl/scriptdocument.hxx> #include <com/sun/star/resource/XStringResourceManager.hpp> diff --git a/chart2/uiconfig/menubar/menubar.xml b/chart2/uiconfig/menubar/menubar.xml index e295d77a3943..53e300045e44 100644 --- a/chart2/uiconfig/menubar/menubar.xml +++ b/chart2/uiconfig/menubar/menubar.xml @@ -134,6 +134,8 @@ <menu:menupopup> <menu:menu menu:id=".uno:MacrosMenu"> <menu:menupopup> + <menu:menuitem menu:id=".uno:MacroManager"/> + <menu:menuseparator/> <menu:menuitem menu:id=".uno:MacroRecorder"/> <menu:menuitem menu:id=".uno:RunMacro"/> <menu:menuitem menu:id=".uno:BasicIDEAppear"/> diff --git a/cui/Library_cui.mk b/cui/Library_cui.mk index e01e33ecb4ec..4942d1548524 100644 --- a/cui/Library_cui.mk +++ b/cui/Library_cui.mk @@ -32,6 +32,7 @@ $(eval $(call gb_Library_use_sdk_api,cui)) $(eval $(call gb_Library_use_libraries,cui,\ $(call gb_Helper_optional,AVMEDIA,avmedia) \ + basctl \ basegfx \ comphelper \ cppu \ @@ -147,6 +148,7 @@ $(eval $(call gb_Library_add_exception_objects,cui,\ cui/source/dialogs/GraphicTestsDialog \ cui/source/dialogs/ImageViewerDialog \ cui/source/dialogs/scriptdlg \ + cui/source/dialogs/MacroManagerDialog \ cui/source/dialogs/SignatureLineDialogBase \ cui/source/dialogs/SignatureLineDialog \ cui/source/dialogs/SignSignatureLineDialog \ diff --git a/cui/UIConfig_cui.mk b/cui/UIConfig_cui.mk index 10acd83c8c39..601e58d2c9c4 100644 --- a/cui/UIConfig_cui.mk +++ b/cui/UIConfig_cui.mk @@ -116,6 +116,7 @@ $(eval $(call gb_UIConfig_add_uifiles,cui,\ cui/uiconfig/ui/listdialog \ cui/uiconfig/ui/macroassigndialog \ cui/uiconfig/ui/macroassignpage \ + cui/uiconfig/ui/macromanagerdialog \ cui/uiconfig/ui/macroselectordialog \ cui/uiconfig/ui/menuassignpage \ cui/uiconfig/ui/mosaicdialog \ diff --git a/cui/inc/bitmaps.hlst b/cui/inc/bitmaps.hlst index aab916827507..4b2d667f4673 100644 --- a/cui/inc/bitmaps.hlst +++ b/cui/inc/bitmaps.hlst @@ -62,8 +62,11 @@ inline constexpr OUString RID_SVXBMP_THEME_DEFAULT_BIG = u"svx/res/galdefl.png"_ inline constexpr OUString RID_CUIBMP_HARDDISK = u"res/harddisk_16.png"_ustr; inline constexpr OUString RID_CUIBMP_LIB = u"res/im30820.png"_ustr; +inline constexpr OUString RID_CUIBMP_DIALOG = u"res/im30823.png"_ustr; inline constexpr OUString RID_CUIBMP_MACRO = u"res/im30821.png"_ustr; inline constexpr OUString RID_CUIBMP_DOC = u"res/im30826.png"_ustr; +inline constexpr OUString RID_CUIBMP_LOCKED = u"res/lock.png"_ustr; +inline constexpr OUString RID_CUIBMP_LINKED = u"sw/res/nc20007.png"_ustr; inline constexpr OUString RID_SVXBMP_SCRIPT = u"res/script.png"_ustr; diff --git a/cui/inc/strings.hrc b/cui/inc/strings.hrc index 1674f7299f9a..0b5068b6fcae 100644 --- a/cui/inc/strings.hrc +++ b/cui/inc/strings.hrc @@ -436,4 +436,33 @@ #define STR_STYLE_NO_LANGUAGE NC_("STR_STYLE_NO_LANGUAGE", "Check if styles have a language set.") #define STR_DOCUMENT_TITLE NC_("STR_DOCUMENT_TITLE", "Check if the document title is set.") +// Unified script organizer selector +#define STR_LIBRARY NC_("STR_LIBRARY", "Library") +#define STR_MODULE NC_("STR_MODULE", "Module") +#define STR_DIALOG NC_("STR_DIALOG", "Dialog") +#define STR_MACRO NC_("STR_MACRO", "Macro") + +#define STR_INPUTDIALOG_NEWLIBRARYTITLE NC_("STR_INPUTDIALOG_NEWLIBRARYTITLE", "New Library") +#define STR_INPUTDIALOG_NEWLIBRARYLABEL NC_("STR_INPUTDIALOG_NEWLIBRARYLABEL", "Please enter a name for the new library:") +#define STR_INPUTDIALOG_NEWMODULETITLE NC_("STR_INPUTDIALOG_NEWMODULETITLE", "New Module") +#define STR_INPUTDIALOG_NEWMODULELABEL NC_("STR_INPUTDIALOG_NEWMODULELABEL", "Please enter a name for the new module:") +#define STR_INPUTDIALOG_NEWDIALOGTITLE NC_("STR_INPUTDIALOG_NEWDIALOGTITLE", "New Dialog") +#define STR_INPUTDIALOG_NEWDIALOGLABEL NC_("STR_INPUTDIALOG_NEWDIALOGLABEL", "Please enter a name for the new dialog:") +#define STR_INPUTDIALOG_NEWMACROTITLE NC_("STR_INPUTDIALOG_NEWMACROTITLE", "New Macro") +#define STR_INPUTDIALOG_NEWMACROLABEL NC_("STR_INPUTDIALOG_NEWMACROLABEL", "Please enter a name for the new macro:") + +#define STR_INPUTDIALOG_RENAMELIBRARYTITLE NC_("STR_INPUTDIALOG_RENAMELIBRARYTITLE", "Rename Library") +#define STR_INPUTDIALOG_RENAMELIBRARYLABEL NC_("STR_INPUTDIALOG_RENAMELIBRARYLABEL", "Please enter a name to rename the library:") +#define STR_INPUTDIALOG_RENAMEMODULETITLE NC_("STR_INPUTDIALOG_RENAMEMODULETITLE", "Rename Module") +#define STR_INPUTDIALOG_RENAMEMODULELABEL NC_("STR_INPUTDIALOG_RENAMEMODULELABEL", "Please enter a name to rename the module:") +#define STR_INPUTDIALOG_RENAMEDIALOGTITLE NC_("STR_INPUTDIALOG_RENAMEDIALOGTITLE", "Rename Dialog") +#define STR_INPUTDIALOG_RENAMEDIALOGLABEL NC_("STR_INPUTDIALOG_RENAMEDIALOGLABEL", "Please enter a name to rename the dialog:") +#define STR_INPUTDIALOG_RENAMEMACROTITLE NC_("STR_INPUTDIALOG_RENAMEMACROTITLE", "Rename Macro") +#define STR_INPUTDIALOG_RENAMEMACROLABEL NC_("STR_INPUTDIALOG_RENAMEMACROLABEL", "Please enter a name to rename the macro:") + +#define STR_LIBISREADONLY NC_("STR_LIBISREADONLY", "This library is read-only.") +#define STR_SBXNAMEALLREADYUSED NC_("STR_SBXNAMEALLREADYUSED", "Name already exists") + +#define STR_SELECTEDENTRYNOTFOUND NC_("STR_SELECTEDENTRYNOTFOUND", "The selected entry doesn't exist. It will be removed from the list.") + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/customize/cfgutil.cxx b/cui/source/customize/cfgutil.cxx index 8646e5146cc5..5b1a9c9ced70 100644 --- a/cui/source/customize/cfgutil.cxx +++ b/cui/source/customize/cfgutil.cxx @@ -540,6 +540,9 @@ void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::scrip for ( Reference< browse::XBrowseNode > const & theChild : children ) { + if (!theChild.is()) + continue; + bool bDisplay = true; OUString uiName = theChild->getName(); if ( bIsRootNode ) @@ -576,6 +579,9 @@ void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::scrip for ( const auto& rxNode : grandchildren ) { + if (!rxNode.is()) + continue; + if ( rxNode->getType() == browse::BrowseNodeTypes::CONTAINER ) { bChildOnDemand = true; @@ -875,59 +881,59 @@ void CuiConfigGroupListBox::GroupSelected() case SfxCfgKind::GROUP_SCRIPTCONTAINER: { - if (!m_xTreeView->iter_has_child(*xIter)) - { - Reference< browse::XBrowseNode > rootNode( - static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ; + Reference< browse::XBrowseNode > rootNode( + static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ; + + try { + if ( rootNode->hasChildNodes() ) + { + const Sequence< Reference< browse::XBrowseNode > > children = + rootNode->getChildNodes(); - try { - if ( rootNode->hasChildNodes() ) + for ( const Reference< browse::XBrowseNode >& childNode : children ) { - const Sequence< Reference< browse::XBrowseNode > > children = - rootNode->getChildNodes(); + if (!childNode.is()) + continue; - for ( const Reference< browse::XBrowseNode >& childNode : children ) + if (childNode->getType() == browse::BrowseNodeTypes::SCRIPT) { - if (childNode->getType() == browse::BrowseNodeTypes::SCRIPT) - { - OUString uri, description; + OUString uri, description; - Reference < beans::XPropertySet >xPropSet( childNode, UNO_QUERY ); - if (!xPropSet.is()) - { - continue; - } + Reference < beans::XPropertySet >xPropSet( childNode, UNO_QUERY ); + if (!xPropSet.is()) + { + continue; + } - Any value = - xPropSet->getPropertyValue(u"URI"_ustr); - value >>= uri; + Any value = + xPropSet->getPropertyValue(u"URI"_ustr); + value >>= uri; - try - { - value = xPropSet->getPropertyValue(u"Description"_ustr); - value >>= description; - } - catch (Exception &) { - // do nothing, the description will be empty - } + try + { + value = xPropSet->getPropertyValue(u"Description"_ustr); + value >>= description; + } + catch (Exception &) { + // do nothing, the description will be empty + } - OUString* pScriptURI = new OUString( uri ); + OUString* pScriptURI = new OUString( uri ); - OUString aImage = GetImage(childNode, Reference< XComponentContext >(), false); - m_pFunctionListBox->aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI )); - m_pFunctionListBox->aArr.back()->sCommand = uri; - m_pFunctionListBox->aArr.back()->sLabel = childNode->getName(); - m_pFunctionListBox->aArr.back()->sHelpText = description; + OUString aImage = GetImage(childNode, Reference< XComponentContext >(), false); + m_pFunctionListBox->aArr.push_back( std::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI )); + m_pFunctionListBox->aArr.back()->sCommand = uri; + m_pFunctionListBox->aArr.back()->sLabel = childNode->getName(); + m_pFunctionListBox->aArr.back()->sHelpText = description; - OUString sId(weld::toId(m_pFunctionListBox->aArr.back().get())); - m_pFunctionListBox->append(sId, childNode->getName(), aImage); - } + OUString sId(weld::toId(m_pFunctionListBox->aArr.back().get())); + m_pFunctionListBox->append(sId, childNode->getName(), aImage); } } } - catch (RuntimeException&) { - // do nothing, the entry will not be displayed in the UI - } + } + catch (RuntimeException&) { + // do nothing, the entry will not be displayed in the UI } break; } @@ -1032,23 +1038,10 @@ IMPL_LINK(CuiConfigGroupListBox, ExpandingHdl, const weld::TreeIter&, rIter, boo #if HAVE_FEATURE_SCRIPTING void CuiConfigGroupListBox::SelectMacro( const SfxMacroInfoItem *pItem ) { - auto const rMacro = pItem->GetQualifiedName(); - sal_Int32 nIdx {rMacro.lastIndexOf('.')}; - const std::u16string_view aMethod( rMacro.subView(nIdx + 1) ); - std::u16string_view aLib; - std::u16string_view aModule; - if ( nIdx>0 ) - { - // string contains at least 2 tokens - nIdx = rMacro.lastIndexOf('.', nIdx); - if (nIdx != -1) - { - // string contains at least 3 tokens - aLib = o3tl::getToken(rMacro, 0, '.' ); - sal_Int32 nIdx2 = nIdx + 1; - aModule = o3tl::getToken(rMacro, 0, '.', nIdx2 ); - } - } + const std::u16string_view aLocation = pItem->GetLocation(); + const std::u16string_view aLib = pItem->GetLib(); + const std::u16string_view aModule = pItem->GetModule(); + const std::u16string_view aMethod = pItem->GetMethod(); std::unique_ptr<weld::TreeIter> xIter = m_xTreeView->make_iterator(); if (!m_xTreeView->get_iter_first(*xIter)) @@ -1065,6 +1058,8 @@ void CuiConfigGroupListBox::SelectMacro( const SfxMacroInfoItem *pItem ) { do { + if (aLocation != m_xTreeView->get_text(*xLocationIter)) + continue; m_xTreeView->expand_row(*xLocationIter); std::unique_ptr<weld::TreeIter> xLibIter = m_xTreeView->make_iterator(xLocationIter.get()); if (m_xTreeView->iter_children(*xLibIter)) @@ -1074,6 +1069,34 @@ void CuiConfigGroupListBox::SelectMacro( const SfxMacroInfoItem *pItem ) OUString aEntryLib = m_xTreeView->get_text(*xLibIter); if (aEntryLib == aLib) { + if (aModule.empty()) + { + m_xTreeView->scroll_to_row(*xLibIter); + m_xTreeView->select(*xLibIter); + GroupSelected(); + weld::TreeView& rFunctionListBoxTreeView + = m_pFunctionListBox->get_widget(); + std::unique_ptr<weld::TreeIter> xFunctionListBoxIter + = rFunctionListBoxTreeView.make_iterator(); + if (!rFunctionListBoxTreeView.get_iter_first( + *xFunctionListBoxIter)) + return; + do + { + OUString aEntryMethod = rFunctionListBoxTreeView.get_text( + *xFunctionListBoxIter); + if (aEntryMethod == aMethod) + { + rFunctionListBoxTreeView.scroll_to_row( + *xFunctionListBoxIter); + rFunctionListBoxTreeView.select(*xFunctionListBoxIter); + return; + } + } while ( + rFunctionListBoxTreeView.iter_next(*xFunctionListBoxIter)); + return; + } + m_xTreeView->expand_row(*xLibIter); std::unique_ptr<weld::TreeIter> xModIter = m_xTreeView->make_iterator(xLibIter.get()); if (m_xTreeView->iter_children(*xModIter)) diff --git a/cui/source/dialogs/MacroManagerDialog.cxx b/cui/source/dialogs/MacroManagerDialog.cxx new file mode 100644 index 000000000000..021bcaf19751 --- /dev/null +++ b/cui/source/dialogs/MacroManagerDialog.cxx @@ -0,0 +1,2512 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <MacroManagerDialog.hxx> + +#include <bitmaps.hlst> +#include <cfgutil.hxx> +#include <dialmgr.hxx> +#include <scriptdlg.hxx> +#include <strings.hrc> +#include <basctl/basctldllpublic.hxx> +#include <basctl/sbxitem.hxx> +#include <basctl/scriptdocument.hxx> +#include <basic/basmgr.hxx> +#include <comphelper/SetFlagContextHelper.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <comphelper/documentinfo.hxx> +#include <comphelper/lok.hxx> +#include <comphelper/processfactory.hxx> +#include <sfx2/app.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/inputdlg.hxx> +#include <sfx2/minfitem.hxx> +#include <sfx2/request.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/viewfrm.hxx> +#include <svl/itemset.hxx> +#include <svl/stritem.hxx> +#include <svtools/imagemgr.hxx> +#include <svx/passwd.hxx> +#include <tools/urlobj.hxx> +#include <unotools/viewoptions.hxx> +#include <vcl/commandevent.hxx> +#include <vcl/weldutils.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/document/XEmbeddedScripts.hpp> +#include <com/sun/star/document/XScriptInvocationContext.hpp> +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/script/browse/XBrowseNode.hpp> +#include <com/sun/star/script/browse/BrowseNodeTypes.hpp> +#include <com/sun/star/script/browse/theBrowseNodeFactory.hpp> +#include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp> +#include <com/sun/star/script/XLibraryContainer2.hpp> +#include <com/sun/star/script/XLibraryContainerPassword.hpp> +#include <com/sun/star/script/XPersistentLibraryContainer.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> + +ScriptsListBox::ScriptsListBox(std::unique_ptr<weld::TreeView> xTreeView) + : m_xTreeView(std::move(xTreeView)) + , m_xScratchIter(m_xTreeView->make_iterator()) +{ + m_xTreeView->make_sorted(); + m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 35, + m_xTreeView->get_height_rows(9)); + m_xTreeView->connect_query_tooltip(LINK(this, ScriptsListBox, QueryTooltip)); +} + +ScriptsListBox::~ScriptsListBox() { ClearAll(); } + +void ScriptsListBox::ClearAll() +{ + sal_uInt16 nCount = aArr.size(); + for (sal_uInt16 i = 0; i < nCount; ++i) + { + ScriptInfo* pScriptInfo = aArr[i].get(); + if (pScriptInfo && pScriptInfo->pBrowseNode) + pScriptInfo->pBrowseNode->release(); + } + aArr.clear(); + m_xTreeView->clear(); +} + +void ScriptsListBox::Remove(const weld::TreeIter& rEntry) +{ + ScriptInfo* pScriptInfo = weld::fromId<ScriptInfo*>(m_xTreeView->get_id(rEntry)); + if (pScriptInfo) + { + if (pScriptInfo->pBrowseNode) + pScriptInfo->pBrowseNode->release(); + for (auto it = aArr.begin(); it != aArr.end(); ++it) + { + if ((*it).get() == pScriptInfo) + { + aArr.erase(it); + break; + } + } + } + m_xTreeView->remove(rEntry); +} + +OUString ScriptsListBox::GetDescriptionText(const OUString& rId) +{ + ScriptInfo* pScriptInfo = weld::fromId<ScriptInfo*>(rId); + if (pScriptInfo) + { + return pScriptInfo->sDescription; + } + return OUString(); +} + +OUString ScriptsListBox::GetSelectedScriptName() +{ + std::unique_ptr<weld::TreeIter> xScriptsEntryIter = m_xTreeView->make_iterator(); + if (!m_xTreeView->get_selected(xScriptsEntryIter.get())) + return OUString(); + return m_xTreeView->get_text(*xScriptsEntryIter); +} + +IMPL_LINK(ScriptsListBox, QueryTooltip, const weld::TreeIter&, rEntryIter, OUString) +{ + return GetDescriptionText(m_xTreeView->get_id(rEntryIter)); +} + +ScriptContainersListBox::ScriptContainersListBox(std::unique_ptr<weld::TreeView> xTreeView, + MacroManagerDialog* pMacroManagerDialog) + : m_pScriptsListBox(nullptr) + , m_xTreeView(std::move(xTreeView)) + , m_pMacroManagerDialog(pMacroManagerDialog) +{ + m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 35, + m_xTreeView->get_height_rows(9)); + m_xTreeView->connect_expanding(LINK(this, ScriptContainersListBox, ExpandingHdl)); + m_xTreeView->connect_query_tooltip(LINK(this, ScriptContainersListBox, QueryTooltip)); +} + +ScriptContainersListBox::~ScriptContainersListBox() { ClearAll(); } + +void ScriptContainersListBox::ClearAll() +{ + sal_uInt16 nCount = m_xTreeView->n_children(); + for (sal_uInt16 i = 0; i < nCount; ++i) + { + ScriptContainerInfo* pScriptContainerInfo + = weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(i)); + if (pScriptContainerInfo) + { + if (pScriptContainerInfo->pBrowseNode) + pScriptContainerInfo->pBrowseNode->release(); + delete pScriptContainerInfo; + } + } + m_xTreeView->clear(); +} + +void ScriptContainersListBox::Init(const css::uno::Reference<css::uno::XComponentContext>& xContext, + const css::uno::Reference<css::frame::XFrame>& xFrame) +{ + m_xContext = xContext; + m_xFrame = xFrame; + m_xTreeView->freeze(); + Fill(nullptr); + m_xTreeView->thaw(); + m_xTreeView->set_cursor(0); +} + +void ScriptContainersListBox::Remove(const weld::TreeIter* pEntryIter, bool bRemoveEntryIter) +{ + // remove all children of pEntryIter + std::unique_ptr<weld::TreeIter> xIter = m_xTreeView->make_iterator(pEntryIter); + if (m_xTreeView->iter_has_child(*pEntryIter) && m_xTreeView->iter_children(*xIter)) + { + // set xIter to the last child of pEntryIter + do + { + std::unique_ptr<weld::TreeIter> xChildIter = m_xTreeView->make_iterator(xIter.get()); + while (m_xTreeView->iter_next_sibling(*xChildIter)) + m_xTreeView->copy_iterator(*xChildIter, *xIter); + } while (m_xTreeView->iter_has_child(*xIter) && m_xTreeView->iter_children(*xIter)); + + // children must be removed from the tree in reverse order + std::unique_ptr<weld::TreeIter> xRemoveIter = m_xTreeView->make_iterator(); + while (m_xTreeView->iter_compare(*xIter, *pEntryIter) != 0) + { + m_xTreeView->copy_iterator(*xIter, *xRemoveIter); + m_xTreeView->iter_previous(*xIter); + ScriptContainerInfo* pScriptContainerInfo + = weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*xRemoveIter)); + if (pScriptContainerInfo) + { + if (pScriptContainerInfo->pBrowseNode) + pScriptContainerInfo->pBrowseNode->release(); + delete pScriptContainerInfo; + } + m_xTreeView->remove(*xRemoveIter); + } + } + + // maybe remove the entry + if (bRemoveEntryIter) + { + ScriptContainerInfo* pScriptContainerInfo + = weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*pEntryIter)); + if (pScriptContainerInfo) + { + if (pScriptContainerInfo->pBrowseNode) + pScriptContainerInfo->pBrowseNode->release(); + delete pScriptContainerInfo; + } + m_xTreeView->remove(*pEntryIter); + } +} + +// inspired by CuiConfigGroupListBox::FillScriptList +// cui/source/customize/cfgutil.cxx +void ScriptContainersListBox::Fill(const weld::TreeIter* pEntryIter) +{ + weld::WaitObject aWait(m_pMacroManagerDialog->getDialog()); + + css::uno::Reference<css::script::browse::XBrowseNode> xNode; + if (pEntryIter == nullptr) + { + ClearAll(); + try + { + css::uno::Reference<css::script::browse::XBrowseNodeFactory> xFac + = css::script::browse::theBrowseNodeFactory::get( + comphelper::getProcessComponentContext()); + xNode.set( + xFac->createView(css::script::browse::BrowseNodeFactoryViewTypes::MACROORGANIZER)); + } + catch (const css::uno::Exception&) + { + TOOLS_WARN_EXCEPTION( + "cui.dialogs", "Caught some exception whilst retrieving browse nodes from factory"); + // TODO exception handling + return; + } + } + else + { + ScriptContainerInfo* pScriptContainerInfoEntry + = weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*pEntryIter)); + + xNode.set(pScriptContainerInfoEntry->pBrowseNode); + + Remove(pEntryIter, /*bRemoveEntryIter*/ false); + } + + if (xNode->hasChildNodes()) + { + // tdf#120362: Don't ask to enable disabled Java when filling script list + css::uno::ContextLayer layer(comphelper::NoEnableJavaInteractionContext()); + + bool bIsRootNode = false; + + OUString user(u"user"_ustr); + OUString share(u"share"_ustr); + OUString uno_packages(u"uno_packages"_ustr); + if (xNode->getName() == "Root") + { + bIsRootNode = true; + } + + //To mimic current starbasic behaviour we + //need to make sure that only the current document + //is displayed in the config tree. Tests below + //set the bDisplay flag to FALSE if the current + //node is a first level child of the Root and is NOT + //either the current document, user or share + // + // NOTE: This approach doesn't work for open documents with the same name, for example + // Untitled 1.odt and Untitled 1.ods will both be included as root containers. + OUString currentDocTitle; + if (css::uno::Reference<css::frame::XController> xController = m_xFrame->getController(); + xController.is()) + { + css::uno::Reference<css::frame::XModel> xModel = xController->getModel(); + if (xModel.is()) + currentDocTitle = comphelper::DocumentInfo::getDocumentTitle(xModel); + } + + const css::uno::Sequence<css::uno::Reference<css::script::browse::XBrowseNode>> children + = xNode->getChildNodes(); + for (css::uno::Reference<css::script::browse::XBrowseNode> const& theChild : children) + { + if (!theChild.is()) + continue; + + if (theChild->getType() == css::script::browse::BrowseNodeTypes::SCRIPT) + // we only want containers in this list box + continue; + if (theChild->getName() == uno_packages) + continue; + + OUString uiName = theChild->getName(); + if (bIsRootNode) + { + if (uiName == user) + { + uiName = CuiResId(RID_CUISTR_MYMACROS); + } + else if (uiName == share) + { + uiName = CuiResId(RID_CUISTR_PRODMACROS); + } + else if (uiName != currentDocTitle) + { + // as noted above + // NOTE: This approach doesn't work for open documents with the same name, for + // example, Untitled 1.odt and Untitled 1.ods will both be included as root + // containers. + continue; + } + } + + // We call acquire on the XBrowseNode so that it does not + // get autodestructed and become invalid when accessed later. + theChild->acquire(); + + bool bChildOnDemand = false; + + if (theChild->hasChildNodes()) + { + const css::uno::Sequence<css::uno::Reference<css::script::browse::XBrowseNode>> + grandchildren = theChild->getChildNodes(); + for (const auto& rxNode : grandchildren) + { + if (!rxNode.is()) + continue; + if (rxNode->getType() == css::script::browse::BrowseNodeTypes::CONTAINER) + { + bChildOnDemand = true; + break; + } + } + } + + OUString aImage = CuiConfigGroupListBox::GetImage(theChild, m_xContext, bIsRootNode); + Insert(theChild, pEntryIter, uiName, aImage, bChildOnDemand); + } + } + + // add Basic dialogs + if (pEntryIter && m_xTreeView->get_iter_depth(*pEntryIter) == 2) // library + { + // parent node of entry node is a language node + std::unique_ptr<weld::TreeIter> xIter = m_xTreeView->make_iterator(pEntryIter); + m_xTreeView->iter_parent(*xIter); // language + if (m_xTreeView->get_text(*xIter) == "Basic") + { + basctl::ScriptDocument aDocument = GetScriptDocument(pEntryIter); + if (!aDocument.isAlive()) + { + return; + } + + OUString aLibName = m_xTreeView->get_text(*pEntryIter); + + css::uno::Reference<css::script::XLibraryContainer> xDlgLibContainer( + aDocument.getLibraryContainer(basctl::E_DIALOGS)); + + if (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName) + && !xDlgLibContainer->isLibraryLoaded(aLibName)) + { + xDlgLibContainer->loadLibrary(aLibName); + } + + if (!(xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName) + && xDlgLibContainer->isLibraryLoaded(aLibName))) + { + return; + } + + for (const OUString& rDlgName : aDocument.getObjectNames(basctl::E_DIALOGS, aLibName)) + { + Insert(nullptr, pEntryIter, rDlgName, RID_CUIBMP_DIALOG, false); + } + } + } +} + +void ScriptContainersListBox::Insert( + const css::uno::Reference<css::script::browse::XBrowseNode>& xInsertNode, + const weld::TreeIter* pIter, const OUString& rsUiName, const OUString& rsImage, + bool bChildOnDemand, int nPos, weld::TreeIter* pRet) +{ + std::unique_ptr<weld::TreeIter> xNewEntryIter = m_xTreeView->make_iterator(); + + OUString sId(weld::toId(new ScriptContainerInfo(xInsertNode.get()))); + m_xTreeView->insert(pIter, nPos, &rsUiName, &sId, nullptr, nullptr, bChildOnDemand, + xNewEntryIter.get()); + m_xTreeView->set_image(*xNewEntryIter, rsImage); + + // set password and linked image only for Basic libraries + if (m_xTreeView->get_iter_depth(*xNewEntryIter) == 2) // library + { + std::unique_ptr<weld::TreeIter> xLanguageIter + = m_xTreeView->make_iterator(xNewEntryIter.get()); + m_xTreeView->iter_parent(*xLanguageIter); + if (m_xTreeView->get_text(*xLanguageIter) == "Basic") + { + basctl::ScriptDocument aDocument = GetScriptDocument(xNewEntryIter.get()); + if (!aDocument.isAlive()) + return; + + OUString aLibName = m_xTreeView->get_text(*xNewEntryIter); + + css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer( + aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)) + { + css::uno::Reference<css::script::XLibraryContainerPassword> xPasswd( + xModLibContainer, css::uno::UNO_QUERY); + if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName)) + { + // password protected + m_xTreeView->set_image(*xNewEntryIter, RID_CUIBMP_LOCKED); + } + else if (xModLibContainer->isLibraryLink(aLibName)) + { + // linked + m_xTreeView->set_image(*xNewEntryIter, RID_CUIBMP_LINKED); + } + } + } + } + if (pRet) + pRet = xNewEntryIter.get(); +} + +// fills the scripts list box +// inspired by code in void CommandCategoryListBox::addChildren +// cui/source/customize/CommandCategoryListBox.cxx +// and void CuiConfigGroupListBox::GroupSelected() +// cui/source/customize/cfgutil.cxx +void ScriptContainersListBox::ScriptContainerSelected() +{ + std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_selected(xIter.get())) + return; + + m_pScriptsListBox->freeze(); + m_pScriptsListBox->ClearAll(); + + if (!m_xTreeView->iter_has_child(*xIter) && !m_xTreeView->get_children_on_demand(*xIter)) + { + // maybe the browse node has children and those children are most likely script nodes + ScriptContainerInfo* pScriptContainerInfo + = weld::fromId<ScriptContainerInfo*>(m_xTreeView->get_id(*xIter)); + css::uno::Reference<css::script::browse::XBrowseNode> xBrowseNode( + pScriptContainerInfo->pBrowseNode); + try + { + if (xBrowseNode->hasChildNodes()) + { + const css::uno::Sequence<css::uno::Reference<css::script::browse::XBrowseNode>> + children = xBrowseNode->getChildNodes(); + + for (const css::uno::Reference<css::script::browse::XBrowseNode>& childNode : + children) + { + if (!childNode.is()) + continue; + + if (childNode->getType() == css::script::browse::BrowseNodeTypes::SCRIPT) + { + css::uno::Reference<css::beans::XPropertySet> xPropSet(childNode, + css::uno::UNO_QUERY); + if (!xPropSet.is()) + { + continue; + } + + OUString sURI; + try + { + css::uno::Any value = xPropSet->getPropertyValue(u"URI"_ustr); + value >>= sURI; + } + catch (css::uno::Exception&) + { + // do nothing, the URI will be empty + } + + OUString sDescription; + try + { + css::uno::Any value = xPropSet->getPropertyValue(u"Description"_ustr); + value >>= sDescription; + } + catch (css::uno::Exception&) + { + // do nothing, the description will be empty + } + + childNode->acquire(); + + m_pScriptsListBox->aArr.push_back( + std::make_unique<ScriptInfo>(childNode.get(), sURI, sDescription)); + + OUString sId(weld::toId(m_pScriptsListBox->aArr.back().get())); + m_pScriptsListBox->append(sId, childNode->getName(), RID_CUIBMP_MACRO); + } + } + } + } + catch (css::uno::RuntimeException&) + { + // do nothing, the entry will not be displayed in the UI + } + } + + m_pScriptsListBox->thaw(); + + if (m_pScriptsListBox->n_children()) + m_pScriptsListBox->select(0); +} + +OUString ScriptContainersListBox::GetContainerName(const weld::TreeIter& rIter, + const ScriptContainerType eScriptContainerType) +{ + weld::TreeView& rScriptContainersTreeView = *m_xTreeView; + std::unique_ptr<weld::TreeIter> xSelectedEntryIter + = rScriptContainersTreeView.make_iterator(&rIter); + + std::unique_ptr<weld::TreeIter> xIter + = rScriptContainersTreeView.make_iterator(xSelectedEntryIter.get()); + + int nEntryDepth; + while ((nEntryDepth = rScriptContainersTreeView.get_iter_depth(*xIter))) + { + if ((nEntryDepth == 3 && eScriptContainerType == ScriptContainerType::MODULEORDIALOG) + || (nEntryDepth == 2 && eScriptContainerType == ScriptContainerType::LIBRARY) + || (nEntryDepth == 1 && eScriptContainerType == ScriptContainerType::LANGUAGE)) + return rScriptContainersTreeView.get_text(*xIter); + rScriptContainersTreeView.iter_parent(*xIter); + } + if (eScriptContainerType == ScriptContainerType::LOCATION) + return rScriptContainersTreeView.get_text(*xIter); + + return OUString(); +} + +OUString +ScriptContainersListBox::GetSelectedEntryContainerName(ScriptContainerType eScriptContainerType) +{ + std::unique_ptr<weld::TreeIter> xSelectedEntryIter = m_xTreeView->make_iterator(); + if (!m_xTreeView->get_selected(xSelectedEntryIter.get())) + return OUString(); // should never happen + return GetContainerName(*xSelectedEntryIter, eScriptContainerType); +} + +IMPL_LINK(ScriptContainersListBox, QueryTooltip, const weld::TreeIter&, rEntryIter, OUString) +{ + // for Basic library check for linked library + if (m_xTreeView->get_iter_depth(rEntryIter) == 2) // library + { + // language + std::unique_ptr<weld::TreeIter> xLanguageIter = m_xTreeView->make_iterator(&rEntryIter); + m_xTreeView->iter_parent(*xLanguageIter); + if (m_xTreeView->get_text(*xLanguageIter) == "Basic") + { + basctl::ScriptDocument aDocument = GetScriptDocument(&rEntryIter); + if (!aDocument.isAlive()) + return OUString(); + + css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer( + aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + // check for linked library + OUString aLibName = m_xTreeView->get_text(rEntryIter); + if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName) + && xModLibContainer->isLibraryLink(aLibName)) + { + OUString aLinkURL = xModLibContainer->getLibraryLinkURL(aLibName); + return aLinkURL; + } + } + } + return OUString(); +} + +IMPL_LINK(ScriptContainersListBox, ExpandingHdl, const weld::TreeIter&, rEntryIter, bool) +{ + // for Basic library check for password protected + if (m_xTreeView->get_iter_depth(rEntryIter) == 2) // library + { + // language + std::unique_ptr<weld::TreeIter> xLanguageIter = m_xTreeView->make_iterator(&rEntryIter); + m_xTreeView->iter_parent(*xLanguageIter); + if (m_xTreeView->get_text(*xLanguageIter) == "Basic") + { + basctl::ScriptDocument aDocument = GetScriptDocument(&rEntryIter); + if (!aDocument.isAlive()) + return false; // not expanded + + OUString aLibName = m_xTreeView->get_text(rEntryIter); + + // check if the library is password protected + css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer( + aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)) + { + css::uno::Reference<css::script::XLibraryContainerPassword> xPasswd( + xModLibContainer, css::uno::UNO_QUERY); + if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName) + && !xPasswd->isLibraryPasswordVerified(aLibName)) + { + // ensure selection before password dialog is shown + m_xTreeView->select(rEntryIter); + OUString sPassword; + if (!basctl::QueryPassword(m_pMacroManagerDialog->getDialog(), xModLibContainer, + aLibName, sPassword, true, true)) + { + return false; // indicates the expansion of the row is refused + } + } + } + } + } + + if (m_xTreeView->get_children_on_demand(rEntryIter)) + { + Fill(&rEntryIter); + } + + return true; +} + +MacroManagerDialog::MacroManagerDialog(weld::Window* pParent, + const css::uno::Reference<css::frame::XFrame>& xDocFrame) + : GenericDialogController(pParent, u"cui/ui/macromanagerdialog.ui"_ustr, + u"MacroManagerDialog"_ustr) + , m_xDocumentFrame(xDocFrame) + , m_xScriptContainersListBox( + new ScriptContainersListBox(m_xBuilder->weld_tree_view(u"scriptcontainers"_ustr), this)) + , m_xScriptsListBox(new ScriptsListBox(m_xBuilder->weld_tree_view(u"scripts"_ustr))) + , m_xScriptContainersListBoxLabel(m_xBuilder->weld_label(u"scriptcontainerlistboxlabel"_ustr)) + , m_xScriptsListBoxLabel(m_xBuilder->weld_label(u"scriptslistboxlabel"_ustr)) + , m_xRunButton(m_xBuilder->weld_button(u"run"_ustr)) + , m_xCloseButton(m_xBuilder->weld_button(u"close"_ustr)) + , m_xDescriptionText(m_xBuilder->weld_text_view(u"description"_ustr)) + , m_xDescriptionFrame(m_xBuilder->weld_frame(u"descriptionframe"_ustr)) + , m_xNewLibraryButton(m_xBuilder->weld_button(u"newlibrary"_ustr)) + , m_xNewModuleButton(m_xBuilder->weld_button(u"newmodule"_ustr)) + , m_xNewDialogButton(m_xBuilder->weld_button(u"newdialog"_ustr)) + , m_xLibraryModuleDialogEditButton(m_xBuilder->weld_button(u"librarymoduledialogedit"_ustr)) + , m_xLibraryModuleDialogRenameButton(m_xBuilder->weld_button(u"librarymoduledialogrename"_ustr)) + , m_xLibraryModuleDialogDeleteButton(m_xBuilder->weld_button(u"librarymoduledialogdelete"_ustr)) + , m_xLibraryPasswordButton(m_xBuilder->weld_button(u"librarypassword"_ustr)) + , m_xLibraryImportButton(m_xBuilder->weld_button(u"libraryimport"_ustr)) + , m_xLibraryExportButton(m_xBuilder->weld_button(u"libraryexport"_ustr)) + , m_xMacroEditButton(m_xBuilder->weld_button(u"macroedit"_ustr)) + , m_xMacroDeleteButton(m_xBuilder->weld_button(u"macrodelete"_ustr)) + , m_xMacroCreateButton(m_xBuilder->weld_button(u"macrocreate"_ustr)) + , m_xMacroRenameButton(m_xBuilder->weld_button(u"macrorename"_ustr)) + , m_xAssignButton(m_xBuilder->weld_button(u"assign"_ustr)) +{ + m_aScriptsListBoxLabelBaseStr = m_xScriptsListBoxLabel->get_label(); + + m_xScriptContainersListBox->SetScriptsListBox(m_xScriptsListBox.get()); + m_xScriptContainersListBox->Init(comphelper::getProcessComponentContext(), m_xDocumentFrame); + + m_xScriptContainersListBox->connect_changed(LINK(this, MacroManagerDialog, SelectHdl)); + + m_xScriptsListBox->connect_changed(LINK(this, MacroManagerDialog, SelectHdl)); + m_xScriptsListBox->connect_row_activated( + LINK(this, MacroManagerDialog, FunctionDoubleClickHdl)); + m_xScriptsListBox->connect_popup_menu(LINK(this, MacroManagerDialog, ContextMenuHdl)); + + m_xAssignButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xRunButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xCloseButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xNewLibraryButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xNewModuleButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xNewDialogButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xLibraryModuleDialogEditButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xLibraryModuleDialogRenameButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xLibraryModuleDialogDeleteButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xLibraryPasswordButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xLibraryImportButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xLibraryExportButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xMacroCreateButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xMacroEditButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xMacroRenameButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + m_xMacroDeleteButton->connect_clicked(LINK(this, MacroManagerDialog, ClickHdl)); + + StartListening(*SfxGetpApp()); +} + +MacroManagerDialog::~MacroManagerDialog() { EndListening(*SfxGetpApp()); } + +void MacroManagerDialog::Notify(SfxBroadcaster&, const SfxHint& rHint) +{ + if (rHint.GetId() == SfxHintId::ScriptDocumentChanged) + { + weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget(); + + auto get_path = [&rScriptContainersTreeView](const weld::TreeIter* pIter) { + std::unique_ptr<weld::TreeIter> xIter = rScriptContainersTreeView.make_iterator(pIter); + OUString sPath = rScriptContainersTreeView.get_text(*xIter); + while (rScriptContainersTreeView.iter_parent(*xIter)) + sPath = rScriptContainersTreeView.get_text(*xIter) + "|" + sPath; + return sPath; + }; + + std::unique_ptr<weld::TreeIter> xIter = rScriptContainersTreeView.make_iterator(); + + // for use to restore the script container tree scroll position + int nOldScrollPos = rScriptContainersTreeView.vadjustment_get_value(); + + // save the current path of the selection in the script containers list for reselection + // and the selected entry in the scripts list box + OUString sScriptContainersListBoxSelectedEntryPath; + OUString sScriptsListBoxSelectedEntry; + if (rScriptContainersTreeView.get_selected(xIter.get())) + { + sScriptContainersListBoxSelectedEntryPath = get_path(xIter.get()); + sScriptsListBoxSelectedEntry = m_xScriptsListBox->GetSelectedScriptName(); + } + + // create a set containing paths for use to restore the script containers tree expand state + std::unordered_set<OUString> aExpandedSet; + if (!rScriptContainersTreeView.get_iter_first(*xIter)) // no entries? + return; + do + { + if (rScriptContainersTreeView.get_row_expanded(*xIter)) + aExpandedSet.insert(get_path(xIter.get())); + } while (rScriptContainersTreeView.iter_next(*xIter)); + + // fill + rScriptContainersTreeView.freeze(); + m_xScriptContainersListBox->Fill(nullptr); + rScriptContainersTreeView.thaw(); + + // restore script container tree expand state or at least try + if (!rScriptContainersTreeView.get_iter_first(*xIter)) + { + UpdateUI(); + return; + } + do + { + if (aExpandedSet.erase(get_path(xIter.get()))) + rScriptContainersTreeView.expand_row(*xIter); + } while (aExpandedSet.size() && rScriptContainersTreeView.iter_next(*xIter)); + + // restore the script containers tree scroll position + rScriptContainersTreeView.vadjustment_set_value(nOldScrollPos); + + // if possible select the saved scripts container list entry + if (sScriptContainersListBoxSelectedEntryPath.isEmpty()) + { + UpdateUI(); + return; + } + bool bFound = false; + while (true) + { + if (!rScriptContainersTreeView.get_iter_first(*xIter)) + { + UpdateUI(); + return; + } + do + { + if (get_path(xIter.get()) == sScriptContainersListBoxSelectedEntryPath) + { + rScriptContainersTreeView.select(*xIter); + bFound = true; + break; + } + } while (rScriptContainersTreeView.iter_next(*xIter)); + if (bFound) + break; + // when not found remove the last node from path and try again + auto i = sScriptContainersListBoxSelectedEntryPath.lastIndexOf('|'); + if (i == -1) + { + // didn't find + UpdateUI(); + return; + } + sScriptContainersListBoxSelectedEntryPath + = sScriptContainersListBoxSelectedEntryPath.copy(0, i); + } + + // fill the scripts list box and set label + m_xScriptContainersListBox->ScriptContainerSelected(); + m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr + " " + + rScriptContainersTreeView.get_text(*xIter)); + + // reselect the macro in the scripts list box + if (!sScriptsListBoxSelectedEntry.isEmpty()) + { + weld::TreeView& rScriptsTreeView = m_xScriptsListBox->get_widget(); + xIter = rScriptsTreeView.make_iterator(); + if (!rScriptsTreeView.get_iter_first(*xIter)) + { + UpdateUI(); + return; + } + bool bIsIterValid = true; + while (bIsIterValid + && rScriptsTreeView.get_text(*xIter) != sScriptsListBoxSelectedEntry) + bIsIterValid = rScriptsTreeView.iter_next_sibling(*xIter); + if (bIsIterValid) + { + rScriptsTreeView.scroll_to_row(*xIter); + rScriptsTreeView.select(*xIter); + } + } + + UpdateUI(); + } +} + +IMPL_LINK(MacroManagerDialog, SelectHdl, weld::TreeView&, rTreeView, void) +{ + if (&rTreeView == &m_xScriptContainersListBox->get_widget()) + { + m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr); + m_xScriptsListBox->ClearAll(); + + std::unique_ptr<weld::TreeIter> xSelectedEntryIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedEntryIter.get())) + { + UpdateUI(); + return; + } + + auto nSelectedEntryDepth = rTreeView.get_iter_depth(*xSelectedEntryIter); + bool bBasic = m_xScriptContainersListBox->GetContainerName(*xSelectedEntryIter, + ScriptContainerType::LANGUAGE) + == u"Basic"_ustr; + + if (nSelectedEntryDepth > 1) + { + if (nSelectedEntryDepth > (!bBasic ? 1 : 2)) + { + ScriptContainerInfo* pScriptContainerInfo + = weld::fromId<ScriptContainerInfo*>(rTreeView.get_id(*xSelectedEntryIter)); + // pBrowseNode is nullptr for Basic Dialog entries + if (pScriptContainerInfo->pBrowseNode) + { + // fill the scripts list box and set the label + m_xScriptContainersListBox->ScriptContainerSelected(); + m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr + " " + + rTreeView.get_text(*xSelectedEntryIter)); + } + } + } + } + UpdateUI(); +} + +// IMPL_LINK_NOARG(SvxScriptSelectorDialog, FunctionDoubleClickHdl, weld::TreeView&, bool) +// cui/source/customize/cfgutil.cxx +IMPL_LINK_NOARG(MacroManagerDialog, FunctionDoubleClickHdl, weld::TreeView&, bool) +{ + if (m_xRunButton->get_sensitive()) + ClickHdl(*m_xRunButton); + return true; +} + +// IMPL_LINK(SvxScriptSelectorDialog, ContextMenuHdl, const CommandEvent&, rCEvt, bool) +// cui/source/customize/cfgutil.cxx +// and +// IMPL_LINK(MacroChooser, ContextMenuHdl, const CommandEvent&, rCEvt, bool) +// basctl/source/basicide/macrodlg.cxx +IMPL_LINK(MacroManagerDialog, ContextMenuHdl, const CommandEvent&, rCEvt, bool) +{ + weld::TreeView& xTreeView = m_xScriptsListBox->get_widget(); + if (rCEvt.GetCommand() != CommandEventId::ContextMenu || !xTreeView.n_children()) + return false; + + std::unique_ptr<weld::Builder> xBuilder( + Application::CreateBuilder(&xTreeView, u"modules/BasicIDE/ui/sortmenu.ui"_ustr)); + std::unique_ptr<weld::Menu> xPopup(xBuilder->weld_menu(u"sortmenu"_ustr)); + std::unique_ptr<weld::Menu> xDropMenu(xBuilder->weld_menu(u"sortsubmenu"_ustr)); + xDropMenu->set_active(u"alphabetically"_ustr, xTreeView.get_sort_order()); + xDropMenu->set_active(u"properorder"_ustr, !xTreeView.get_sort_order()); + + OUString sCommand( + xPopup->popup_at_rect(&xTreeView, tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1)))); + if (sCommand == "alphabetically") + { + xTreeView.make_sorted(); + } + else if (sCommand == "properorder") + { + xTreeView.make_unsorted(); + m_xScriptContainersListBox->ScriptContainerSelected(); + } + else if (!sCommand.isEmpty()) + { + SAL_WARN("cui.dialogs", "Unknown context menu action: " << sCommand); + } + + return true; +} + +// same as OUString SvxScriptOrgDialog::getBoolProperty((Reference<beans::XPropertySet> const& xProps, OUString const& propName) +// cui/source/dialogs/scriptdlg.cxx +bool MacroManagerDialog::getBoolProperty( + css::uno::Reference<css::beans::XPropertySet> const& xProps, OUString const& propName) +{ + bool result = false; + try + { + xProps->getPropertyValue(propName) >>= result; + } + catch (css::uno::Exception&) + { + return result; + } + return result; +} + +css::uno::Reference<css::script::browse::XBrowseNode> +MacroManagerDialog::getBrowseNode(const weld::TreeView& rTreeView, const weld::TreeIter& rTreeIter) +{ + if (&rTreeView == m_xScriptContainersListBox->m_xTreeView.get()) + { + ScriptContainerInfo* pScriptContainerInfo; + pScriptContainerInfo = weld::fromId<ScriptContainerInfo*>(rTreeView.get_id(rTreeIter)); + if (pScriptContainerInfo) + return pScriptContainerInfo->pBrowseNode; + } + else + { + ScriptInfo* pScriptInfo = weld::fromId<ScriptInfo*>(rTreeView.get_id(rTreeIter)); + if (pScriptInfo) + return pScriptInfo->pBrowseNode; + } + return nullptr; +} + +void MacroManagerDialog::UpdateUI() +{ + OUString sDescriptionText + = ScriptsListBox::GetDescriptionText(m_xScriptsListBox->get_selected_id()); + + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr<weld::TreeIter> xSelectedIter = rTreeView.make_iterator(); + if (rTreeView.get_selected(xSelectedIter.get()) + && rTreeView.get_iter_depth(*xSelectedIter) == 2) // library + { + if (m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LANGUAGE) + == "Basic") + { + basctl::ScriptDocument aDocument + = m_xScriptContainersListBox->GetScriptDocument(xSelectedIter.get()); + if (aDocument.isAlive()) + { + // if this is a Basic linked library use the link url name for the description string + css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer( + aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + OUString aLibName = rTreeView.get_text(*xSelectedIter); + if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName) + && xModLibContainer->isLibraryLink(aLibName)) + { + sDescriptionText = xModLibContainer->getLibraryLinkURL(aLibName); + } + } + } + } + + m_xDescriptionText->set_text(sDescriptionText); + CheckButtons(); +} + +void MacroManagerDialog::CheckButtons() +{ + bool bSensitiveNewLibraryButton = false; + bool bSensitiveNewModuleButton = false; + bool bSensitiveNewDialogButton = false; + bool bSensitiveLibraryModuleDialogEditButton = false; + bool bSensitiveLibraryModuleDialogRenameButton = false; + bool bSensitiveLibraryModuleDialogDeleteButton = false; + bool bSensitiveLibraryPasswordButton = false; + bool bSensitiveLibraryImportButton = false; + bool bSensitiveLibraryExportButton = false; + + bool bSensitiveMacroRunButton = false; + bool bSensitiveMacroCreateButton = false; + bool bSensitiveMacroEditButton = false; + bool bSensitiveMacroRenameButton = false; + bool bSensitiveMacroDeleteButton = false; + + bool bSensitiveAssignButton = false; + + weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr<weld::TreeIter> xScriptContainersSelectedIter + = rScriptContainersTreeView.make_iterator(); + if (rScriptContainersTreeView.get_selected(xScriptContainersSelectedIter.get())) + { + if (auto nSelectedIterDepth + = rScriptContainersTreeView.get_iter_depth(*xScriptContainersSelectedIter)) + { + std::unique_ptr<weld::TreeIter> xLocationContainerIter + = rScriptContainersTreeView.make_iterator(xScriptContainersSelectedIter.get()); + while (rScriptContainersTreeView.get_iter_depth(*xLocationContainerIter)) + rScriptContainersTreeView.iter_parent(*xLocationContainerIter); + bool bSharedLocationContainer + = getBrowseNode(rScriptContainersTreeView, *xLocationContainerIter)->getName() + == u"share"_ustr; + + bool bBasic = m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LANGUAGE) + == u"Basic"_ustr; + + if (nSelectedIterDepth == 1) // language node + { + if (!bSharedLocationContainer) + { + if (bBasic) + { + bSensitiveNewLibraryButton = true; + bSensitiveLibraryImportButton = true; + } + else + { + css::uno::Reference<css::script::browse::XBrowseNode> node = getBrowseNode( + rScriptContainersTreeView, *xScriptContainersSelectedIter); + if (node.is()) + { + css::uno::Reference<css::beans::XPropertySet> xProps( + node, css::uno::UNO_QUERY); + if (xProps.is()) + { + if (getBoolProperty(xProps, "Creatable")) + { + bSensitiveNewLibraryButton = true; + } + } + } + } + } + } + else if (bBasic && nSelectedIterDepth == 2) // library node + { + basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument(); + if (!aDocument.isAlive()) + return; + + OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LIBRARY); + + css::uno::Reference<css::script::XLibraryContainerPassword> xPasswd( + aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + + if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName) + && !xPasswd->isLibraryPasswordVerified(aLibName)) + { + bSensitiveLibraryPasswordButton = true; + } + else if (bSharedLocationContainer) + { + bSensitiveLibraryModuleDialogEditButton = true; + } + else + { + // check, if library is readonly + css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer( + aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + + bool bReadOnly = xModLibContainer.is() && xModLibContainer->hasByName(aLibName) + && xModLibContainer->isLibraryReadOnly(aLibName); + + bSensitiveNewModuleButton = !bReadOnly; + bSensitiveNewDialogButton = !bReadOnly; + bSensitiveLibraryModuleDialogEditButton = true; + if (aLibName != u"Standard"_ustr) // need to use a ResId? + { + bSensitiveLibraryModuleDialogRenameButton = !bReadOnly; + bSensitiveLibraryModuleDialogDeleteButton = true; //!bReadOnly; + bSensitiveLibraryPasswordButton = !bReadOnly; + // why not export for "Standard"? + bSensitiveLibraryExportButton = true; + } + } + } + else if (bBasic && nSelectedIterDepth == 3) // module/dialog node + { + if (bSharedLocationContainer) + { + bSensitiveLibraryModuleDialogEditButton = true; + } + else + { + basctl::ScriptDocument aDocument + = m_xScriptContainersListBox->GetScriptDocument(); + assert(aDocument.isAlive()); + + OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LIBRARY); + + css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer( + aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + css::uno::Reference<css::script::XLibraryContainer2> xDlgLibContainer( + aDocument.getLibraryContainer(basctl::E_DIALOGS), css::uno::UNO_QUERY); + + bool bReadOnly + = (xModLibContainer.is() && xModLibContainer->hasByName(aLibName) + && (xModLibContainer->isLibraryReadOnly(aLibName) + || xModLibContainer->isLibraryLink(aLibName))) + || (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName) + && (xDlgLibContainer->isLibraryReadOnly(aLibName) + || xDlgLibContainer->isLibraryLink(aLibName))); + + bSensitiveLibraryModuleDialogEditButton = true; + bSensitiveLibraryModuleDialogRenameButton = !bReadOnly; + bSensitiveLibraryModuleDialogDeleteButton = !bReadOnly; + } + } + + if (!bSharedLocationContainer && nSelectedIterDepth > 1) + { + css::uno::Reference<css::script::browse::XBrowseNode> node + = getBrowseNode(rScriptContainersTreeView, *xScriptContainersSelectedIter); + if (node.is()) + { + css::uno::Reference<css::beans::XPropertySet> xProps(node, css::uno::UNO_QUERY); + if (xProps.is()) + { + if (getBoolProperty(xProps, "Creatable") + && rScriptContainersTreeView.get_iter_depth( + *xScriptContainersSelectedIter) + == 2) // library entry + { + bSensitiveMacroCreateButton = true; + } + if (getBoolProperty(xProps, "Editable")) + { + bSensitiveLibraryModuleDialogEditButton = true; + } + if (getBoolProperty(xProps, "Deletable")) + { + bSensitiveLibraryModuleDialogDeleteButton = true; + } + if (getBoolProperty(xProps, "Renamable")) + { + bSensitiveLibraryModuleDialogRenameButton = true; + } + } + } + } + + // scripts list box state dependant buttons + weld::TreeView& rScriptsTreeView = m_xScriptsListBox->get_widget(); + std::unique_ptr<weld::TreeIter> xScriptsSelectedIter = rScriptsTreeView.make_iterator(); + if (rScriptsTreeView.n_children() + && rScriptsTreeView.get_selected(xScriptsSelectedIter.get())) + { + bSensitiveAssignButton = true; + + css::uno::Reference<css::script::browse::XBrowseNode> node; + node = getBrowseNode(rScriptsTreeView, *xScriptsSelectedIter); + if (node.is()) + { + bSensitiveMacroRunButton = true; + + css::uno::Reference<css::beans::XPropertySet> xProps(node, css::uno::UNO_QUERY); + if (xProps.is()) + { + if (getBoolProperty(xProps, "Editable")) + { + bSensitiveMacroEditButton = true; + } + if (!bSharedLocationContainer) + { + if (getBoolProperty(xProps, "Deletable")) + { + bSensitiveMacroDeleteButton = true; + } + if (getBoolProperty(xProps, "Renamable")) + { + bSensitiveMacroRenameButton = true; + } + } + } + } + } + } + } + + m_xNewLibraryButton->set_sensitive(bSensitiveNewLibraryButton); + m_xNewModuleButton->set_sensitive(bSensitiveNewModuleButton); + m_xNewDialogButton->set_sensitive(bSensitiveNewDialogButton); + m_xLibraryModuleDialogEditButton->set_sensitive(bSensitiveLibraryModuleDialogEditButton); + m_xLibraryModuleDialogRenameButton->set_sensitive(bSensitiveLibraryModuleDialogRenameButton); + m_xLibraryModuleDialogDeleteButton->set_sensitive(bSensitiveLibraryModuleDialogDeleteButton); + m_xLibraryPasswordButton->set_sensitive(bSensitiveLibraryPasswordButton); + m_xLibraryImportButton->set_sensitive(bSensitiveLibraryImportButton); + m_xLibraryExportButton->set_sensitive(bSensitiveLibraryExportButton); + m_xRunButton->set_sensitive(bSensitiveMacroRunButton); + m_xMacroCreateButton->set_sensitive(bSensitiveMacroCreateButton); + m_xMacroEditButton->set_sensitive(bSensitiveMacroEditButton); + m_xMacroRenameButton->set_sensitive(bSensitiveMacroRenameButton); + m_xMacroDeleteButton->set_sensitive(bSensitiveMacroDeleteButton); + m_xAssignButton->set_sensitive(bSensitiveAssignButton); +} + +// void createLibImpl(weld::Window* pWin, const ScriptDocument& rDocument, +// weld::TreeView* pLibBox, SbTreeListBox* pBasicBox) +// basctl/source/basicide/moduldl2.cxx +void MacroManagerDialog::BasicScriptsCreateLibrary(const basctl::ScriptDocument& rDocument) +{ + // create a unique library name + OUString aLibName = CuiResId(STR_LIBRARY) + OUString::number(1); + for (sal_uInt32 i = 1; rDocument.hasLibrary(basctl::E_SCRIPTS, aLibName) + || rDocument.hasLibrary(basctl::E_DIALOGS, aLibName); + aLibName = CuiResId(STR_LIBRARY) + OUString::number(++i)) + ; + + InputDialog aInputDlg(m_xDialog.get(), CuiResId(STR_INPUTDIALOG_NEWLIBRARYLABEL)); + aInputDlg.set_title(CuiResId(STR_INPUTDIALOG_NEWLIBRARYTITLE)); + aInputDlg.SetEntryText(aLibName); + aInputDlg.HideHelpBtn(); + aInputDlg.setCheckEntry([&](OUString sNewName) { + if (sNewName.isEmpty() || rDocument.hasLibrary(basctl::E_SCRIPTS, sNewName) + || rDocument.hasLibrary(basctl::E_DIALOGS, sNewName) || sNewName.getLength() > 30 + || !basctl::IsValidSbxName(sNewName)) + return false; + return true; + }); + + if (!aInputDlg.run()) + return; + + aLibName = aInputDlg.GetEntryText(); + + try + { + // create library container for modules + rDocument.getOrCreateLibrary(basctl::E_SCRIPTS, aLibName); + + // create a module + OUString aModName = rDocument.createObjectName(basctl::E_SCRIPTS, aLibName); + OUString sModuleCode; + if (!rDocument.createModule(aLibName, aModName, true, sModuleCode)) + throw css::uno::Exception("could not create module " + aModName, nullptr); + + // tdf#151741 - store all libraries to the file system, otherwise they + // cannot be renamed/moved since the SfxLibraryContainer::renameLibrary + // moves the folders/files on the file system + css::uno::Reference<css::script::XLibraryContainer2> xModLibContainer( + rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + css::uno::Reference<css::script::XPersistentLibraryContainer> xModPersLibContainer( + xModLibContainer, css::uno::UNO_QUERY); + if (xModPersLibContainer.is()) + xModPersLibContainer->storeLibraries(); + + // update Basic IDE object catalog + SbxItem aModuleSbxItem(SID_BASICIDE_ARG_SBX, rDocument, aLibName, aModName, + basctl::SBX_TYPE_MODULE); + if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) + pDispatcher->ExecuteList(SID_BASICIDE_SBXINSERTED, SfxCallMode::SYNCHRON, + { &aModuleSbxItem }); + } + catch (const css::uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("basctl.basicide"); + } +} + +void MacroManagerDialog::BasicScriptsCreateModule(const basctl::ScriptDocument& rDocument) +{ + // library name is the selected tree entry + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr<weld::TreeIter> xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + + OUString aLibName = rTreeView.get_text(*xSelectedIter); + + // create an unused module name + OUString aModName = CuiResId(STR_MODULE) + OUString::number(1); + for (sal_uInt32 i = 1; rDocument.hasModule(aLibName, aModName); + aModName = CuiResId(STR_MODULE) + OUString::number(++i)) + ; + + InputDialog aInputDlg(m_xDialog.get(), CuiResId(STR_INPUTDIALOG_NEWMODULELABEL)); + aInputDlg.set_title(CuiResId(STR_INPUTDIALOG_NEWMODULETITLE)); + aInputDlg.SetEntryText(aModName); -e ... etc. - the rest is truncated
