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 #include #include -#include +#include #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 -#include +#include #include 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 -#include +#include #include #include 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 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& func_remove_entry, + const std::function& func_insert_entry, + const std::function& 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 & xFP = aDlg.GetFilePicker(); @@ -643,7 +672,7 @@ void LibPage::InsertLib() if (aLibNames.hasElements()) { // library import dialog - xLibDlg = std::make_shared(m_pDialog->getDialog()); + xLibDlg = std::make_shared(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 xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(), + std::unique_ptr 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 xModLibContainer( + rDocument.getLibraryContainer(E_SCRIPTS), UNO_QUERY); + Reference 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 xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(), - VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_REPLACESTDLIB))); + std::unique_ptr 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) + "\n" + IDEResId(RID_STR_LIBISREADONLY); - std::unique_ptr xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(), - VclMessageType::Warning, VclButtonsType::Ok, aErrStr)); + std::unique_ptr 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) + "\n" +IDEResId(RID_STR_SBXNAMEALLREADYUSED); - std::unique_ptr xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(), - VclMessageType::Warning, VclButtonsType::Ok, aErrStr)); + std::unique_ptr 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 xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(), - VclMessageType::Warning, VclButtonsType::Ok, aErrStr)); + std::unique_ptr 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 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 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 xNewDlg(new ExportDialog(m_pDialog->getDialog())); + std::unique_ptr 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& Handler) { - Reference< script::XLibraryContainerExport > xModLibContainerExport - ( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY ); - Reference< script::XLibraryContainerExport > xDlgLibContainerExport - ( m_aCurDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY ); + Reference xModLibContainerExport( + rScriptDocument.getLibraryContainer(E_SCRIPTS), UNO_QUERY); + Reference 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 & 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 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 #include +#include + 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& 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 +#include #include #include 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 -#include +#include #include #include #include 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 #include "doceventnotifier.hxx" -#include "scriptdocument.hxx" +#include 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 #include "ObjectCatalog.hxx" #include 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 +#include #include 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 -#include "sbxitem.hxx" +#include #include 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 +#include +#include #include #include #include @@ -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 -#include "scriptdocument.hxx" +#include #include 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 @@ + + 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() ) + try { + if ( rootNode->hasChildNodes() ) + { + const Sequence< Reference< browse::XBrowseNode > > children = + rootNode->getChildNodes(); + + 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; + + Reference < beans::XPropertySet >xPropSet( childNode, UNO_QUERY ); + if (!xPropSet.is()) { - OUString uri, description; - - Reference < beans::XPropertySet >xPropSet( childNode, UNO_QUERY ); - if (!xPropSet.is()) - { - continue; - } - - 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 - } - - OUString* pScriptURI = new OUString( uri ); - - OUString aImage = GetImage(childNode, Reference< XComponentContext >(), false); - m_pFunctionListBox->aArr.push_back( std::make_unique( 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); + continue; } + + 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 + } + + OUString* pScriptURI = new OUString( uri ); + + OUString aImage = GetImage(childNode, Reference< XComponentContext >(), false); + m_pFunctionListBox->aArr.push_back( std::make_unique( 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); } } } - 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 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 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 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 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +ScriptsListBox::ScriptsListBox(std::unique_ptr 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(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(rId); + if (pScriptInfo) + { + return pScriptInfo->sDescription; + } + return OUString(); +} + +OUString ScriptsListBox::GetSelectedScriptName() +{ + std::unique_ptr 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 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(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& xContext, + const css::uno::Reference& 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 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 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 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(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(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 xNode; + if (pEntryIter == nullptr) + { + ClearAll(); + try + { + css::uno::Reference 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(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 xController = m_xFrame->getController(); + xController.is()) + { + css::uno::Reference xModel = xController->getModel(); + if (xModel.is()) + currentDocTitle = comphelper::DocumentInfo::getDocumentTitle(xModel); + } + + const css::uno::Sequence> children + = xNode->getChildNodes(); + for (css::uno::Reference 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> + 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 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 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& xInsertNode, + const weld::TreeIter* pIter, const OUString& rsUiName, const OUString& rsImage, + bool bChildOnDemand, int nPos, weld::TreeIter* pRet) +{ + std::unique_ptr 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 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 xModLibContainer( + aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)) + { + css::uno::Reference 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 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(m_xTreeView->get_id(*xIter)); + css::uno::Reference xBrowseNode( + pScriptContainerInfo->pBrowseNode); + try + { + if (xBrowseNode->hasChildNodes()) + { + const css::uno::Sequence> + children = xBrowseNode->getChildNodes(); + + for (const css::uno::Reference& childNode : + children) + { + if (!childNode.is()) + continue; + + if (childNode->getType() == css::script::browse::BrowseNodeTypes::SCRIPT) + { + css::uno::Reference 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(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 xSelectedEntryIter + = rScriptContainersTreeView.make_iterator(&rIter); + + std::unique_ptr 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 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 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 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 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 xModLibContainer( + aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)) + { + css::uno::Reference 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& 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 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 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 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 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(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 xBuilder( + Application::CreateBuilder(&xTreeView, u"modules/BasicIDE/ui/sortmenu.ui"_ustr)); + std::unique_ptr xPopup(xBuilder->weld_menu(u"sortmenu"_ustr)); + std::unique_ptr 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 const& xProps, OUString const& propName) +// cui/source/dialogs/scriptdlg.cxx +bool MacroManagerDialog::getBoolProperty( + css::uno::Reference const& xProps, OUString const& propName) +{ + bool result = false; + try + { + xProps->getPropertyValue(propName) >>= result; + } + catch (css::uno::Exception&) + { + return result; + } + return result; +} + +css::uno::Reference +MacroManagerDialog::getBrowseNode(const weld::TreeView& rTreeView, const weld::TreeIter& rTreeIter) +{ + if (&rTreeView == m_xScriptContainersListBox->m_xTreeView.get()) + { + ScriptContainerInfo* pScriptContainerInfo; + pScriptContainerInfo = weld::fromId(rTreeView.get_id(rTreeIter)); + if (pScriptContainerInfo) + return pScriptContainerInfo->pBrowseNode; + } + else + { + ScriptInfo* pScriptInfo = weld::fromId(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 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 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 xScriptContainersSelectedIter + = rScriptContainersTreeView.make_iterator(); + if (rScriptContainersTreeView.get_selected(xScriptContainersSelectedIter.get())) + { + if (auto nSelectedIterDepth + = rScriptContainersTreeView.get_iter_depth(*xScriptContainersSelectedIter)) + { + std::unique_ptr 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 node = getBrowseNode( + rScriptContainersTreeView, *xScriptContainersSelectedIter); + if (node.is()) + { + css::uno::Reference 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 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 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 xModLibContainer( + aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + css::uno::Reference 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 node + = getBrowseNode(rScriptContainersTreeView, *xScriptContainersSelectedIter); + if (node.is()) + { + css::uno::Reference 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 xScriptsSelectedIter = rScriptsTreeView.make_iterator(); + if (rScriptsTreeView.n_children() + && rScriptsTreeView.get_selected(xScriptsSelectedIter.get())) + { + bSensitiveAssignButton = true; + + css::uno::Reference node; + node = getBrowseNode(rScriptsTreeView, *xScriptsSelectedIter); + if (node.is()) + { + bSensitiveMacroRunButton = true; + + css::uno::Reference 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 xModLibContainer( + rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + css::uno::Reference 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 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); + aInputDlg.HideHelpBtn(); + aInputDlg.setCheckEntry([&](OUString sNewName) { + if (sNewName.isEmpty() || rDocument.hasModule(aLibName, sNewName) + || sNewName.getLength() > 30 || !basctl::IsValidSbxName(sNewName)) + return false; + return true; + }); + + if (!aInputDlg.run()) + return; + + aModName = aInputDlg.GetEntryText(); + + OUString sModuleCode; + if (!rDocument.createModule(aLibName, aModName, true /*create main sub*/, sModuleCode)) + return; + + // update Basic IDE object catalog + SbxItem aSbxItem(SID_BASICIDE_ARG_SBX, rDocument, aLibName, aModName, basctl::SBX_TYPE_MODULE); + if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) + { + pDispatcher->ExecuteList(SID_BASICIDE_SBXINSERTED, SfxCallMode::SYNCHRON, { &aSbxItem }); + } +} + +void MacroManagerDialog::BasicScriptsCreateDialog(const basctl::ScriptDocument& rDocument) +{ + // library name is the selected tree entry + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + + OUString aLibName = rTreeView.get_text(*xSelectedIter); + + // create an unused dialog name + OUString sDialogName = CuiResId(STR_DIALOG) + OUString::number(1); + for (sal_uInt32 i = 1; rDocument.hasDialog(aLibName, sDialogName); + sDialogName = CuiResId(STR_DIALOG) + OUString::number(++i)) + ; + + InputDialog aInputDlg(m_xDialog.get(), CuiResId(STR_INPUTDIALOG_NEWDIALOGLABEL)); + aInputDlg.set_title(CuiResId(STR_INPUTDIALOG_NEWDIALOGTITLE)); + aInputDlg.SetEntryText(sDialogName); + aInputDlg.HideHelpBtn(); + aInputDlg.setCheckEntry([&](OUString sNewName) { + if (sNewName.isEmpty() || rDocument.hasDialog(aLibName, sNewName) + || sNewName.getLength() > 30 || !basctl::IsValidSbxName(sNewName)) + return false; + return true; + }); + + if (!aInputDlg.run()) + return; + + sDialogName = aInputDlg.GetEntryText(); + + try + { + rDocument.getOrCreateLibrary(basctl::E_DIALOGS, aLibName); + + css::uno::Reference xISP; + if (!rDocument.createDialog(aLibName, sDialogName, xISP)) + return; + + // update Basic IDE object catalog + SbxItem aSbxItem(SID_BASICIDE_ARG_SBX, rDocument, aLibName, sDialogName, + basctl::SBX_TYPE_DIALOG); + if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) + { + pDispatcher->ExecuteList(SID_BASICIDE_SBXINSERTED, SfxCallMode::SYNCHRON, + { &aSbxItem }); + } + } + catch (const css::container::ElementExistException&) + { + std::unique_ptr xError(Application::CreateMessageDialog( + m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, + CuiResId(STR_SBXNAMEALLREADYUSED))); + xError->run(); + } + catch (const css::container::NoSuchElementException&) + { + DBG_UNHANDLED_EXCEPTION("basctl.basicide"); + } +} + +void MacroManagerDialog::BasicScriptsLibraryModuleDialogEdit( + const basctl::ScriptDocument& rDocument) +{ + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + + m_xDialog->hide(); + + // show the Basic IDE + SfxAllItemSet aArgs(SfxGetpApp()->GetPool()); + SfxRequest aRequest(SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs); + SfxGetpApp()->ExecuteSlot(aRequest); + + if (rTreeView.get_iter_depth(*xSelectedIter) == 2) // library + { + SfxUnoAnyItem aDocItem(SID_BASICIDE_ARG_DOCUMENT_MODEL, + css::uno::Any(rDocument.getDocumentOrNull())); + SfxStringItem aLibNameItem(SID_BASICIDE_ARG_LIBNAME, + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LIBRARY)); + if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) + pDispatcher->ExecuteList(SID_BASICIDE_LIBSELECTED, SfxCallMode::ASYNCHRON, + { &aDocItem, &aLibNameItem }); + } + else // module/dialog + { + ScriptContainerInfo* pScriptContainerInfo + = weld::fromId(rTreeView.get_id(*xSelectedIter)); + // pScriptContainerInfo->pBrowseNode is nullptr for Dialog entries + SbxItem aSbxItem( + SID_BASICIDE_ARG_SBX, rDocument, + m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LIBRARY), + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::MODULEORDIALOG), + pScriptContainerInfo->pBrowseNode ? basctl::SBX_TYPE_MODULE : basctl::SBX_TYPE_DIALOG); + if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) + pDispatcher->ExecuteList(SID_BASICIDE_SHOWSBX, SfxCallMode::ASYNCHRON, { &aSbxItem }); + } + + // close the MacroManagerDialog + m_xDialog->response(0); +} + +IMPL_LINK(MacroManagerDialog, CheckPasswordHdl, SvxPasswordDialog*, pDlg, bool) +{ + basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument(); + if (!aDocument.isAlive()) + return false; + + bool bRet = false; + + css::uno::Reference xPasswd( + aDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + + if (xPasswd.is()) + { + try + { + OUString aOldPassword(pDlg->GetOldPassword()); + OUString aNewPassword(pDlg->GetNewPassword()); + OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LIBRARY); + xPasswd->changeLibraryPassword(aLibName, aOldPassword, aNewPassword); + bRet = true; + } + catch (...) + { + } + } + + return bRet; +} + +basctl::ScriptDocument ScriptContainersListBox::GetScriptDocument(const weld::TreeIter* pIter) +{ + std::unique_ptr xIter = m_xTreeView->make_iterator(pIter); + if (pIter == nullptr) + { + if (!m_xTreeView->get_selected(xIter.get())) + return basctl::ScriptDocument::getApplicationScriptDocument(); + } + + while (m_xTreeView->get_iter_depth(*xIter)) + m_xTreeView->iter_parent(*xIter); + + ScriptContainerInfo* pScriptContainerInfo + = weld::fromId(m_xTreeView->get_id(*xIter)); + if (pScriptContainerInfo && pScriptContainerInfo->pBrowseNode) + { + css::uno::Reference aRootNode; + aRootNode = pScriptContainerInfo->pBrowseNode; + if (aRootNode->getName() == u"user"_ustr || aRootNode->getName() == u"share"_ustr) + return basctl::ScriptDocument::getApplicationScriptDocument(); + return basctl::ScriptDocument::getDocumentWithURLOrCaption(aRootNode->getName()); + } + + return basctl::ScriptDocument::getApplicationScriptDocument(); +} + +IMPL_LINK(MacroManagerDialog, ClickHdl, weld::Button&, rButton, void) +{ + if (&rButton == m_xCloseButton.get()) + { + m_xDialog->response(RET_CANCEL); + return; + } + if (&rButton == m_xRunButton.get()) + { + SaveLastUsedMacro(); + m_xDialog->response(RET_OK); + return; + } + + if (m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LANGUAGE) + == "Basic") + { + basctl::ScriptDocument aDocument = m_xScriptContainersListBox->GetScriptDocument(); + if (!aDocument.isAlive()) + return; + + if (&rButton == m_xNewLibraryButton.get()) + { + BasicScriptsCreateLibrary(aDocument); + } + else if (&rButton == m_xNewModuleButton.get()) + { + BasicScriptsCreateModule(aDocument); + } + else if (&rButton == m_xNewDialogButton.get()) + { + BasicScriptsCreateDialog(aDocument); + } + else if (&rButton == m_xLibraryModuleDialogEditButton.get()) + { + BasicScriptsLibraryModuleDialogEdit(aDocument); + } + else if (&rButton == m_xLibraryModuleDialogRenameButton.get()) + { + BasicScriptsLibraryModuleDialogRename(aDocument); + } + else if (&rButton == m_xLibraryModuleDialogDeleteButton.get()) + { + BasicScriptsLibraryModuleDialogDelete(aDocument); + } + else if (&rButton == m_xLibraryPasswordButton.get()) + { + BasicScriptsLibraryPassword(aDocument); + } + else if (&rButton == m_xLibraryImportButton.get()) + { + auto insert_entries = [this]() { + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + m_xScriptContainersListBox->Fill(xSelectedIter.get()); + rTreeView.expand_row(*xSelectedIter); + rTreeView.select(*xSelectedIter); + }; + basctl::ImportLib(aDocument, m_xDialog.get(), {}, {}, insert_entries); + } + else if (&rButton == m_xLibraryExportButton.get()) + { + basctl::Export(aDocument, + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LIBRARY), + m_xDialog.get()); + } + else if (&rButton == m_xMacroEditButton.get()) + { + BasicScriptsMacroEdit(aDocument); + } + else if (&rButton == m_xMacroDeleteButton.get()) + { + // todo + // see: void MacroChooser::DeleteMacro() + return; + } + else if (&rButton == m_xAssignButton.get()) + { + SfxAllItemSet Args(SfxGetpApp()->GetPool()); + SfxAllItemSet aInternalSet(SfxGetpApp()->GetPool()); + if (m_xDocumentFrame.is()) + aInternalSet.Put(SfxUnoFrameItem(SID_FILLFRAME, m_xDocumentFrame)); + SfxRequest aRequest(SID_CONFIGACCEL, SfxCallMode::SYNCHRON, Args, aInternalSet); + + SfxMacroInfoItem aMacroInfoItem( + SID_MACROINFO, aDocument.getBasicManager(), + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LIBRARY), + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::MODULEORDIALOG), + m_xScriptsListBox->GetSelectedScriptName(), OUString(), + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LOCATION)); + aRequest.AppendItem(aMacroInfoItem); + + SfxGetpApp()->ExecuteSlot(aRequest); + } + return; + } + + // + // button operations on Scripting Framework languages + // + if (&rButton == m_xNewLibraryButton.get()) + { + ScriptingFrameworkScriptsCreateEntry(InputDialogMode::NEWLIB); + } + else if (&rButton == m_xMacroCreateButton.get()) + { + ScriptingFrameworkScriptsCreateEntry(InputDialogMode::NEWMACRO); + } + else if (&rButton == m_xMacroEditButton.get()) + { + weld::TreeView& rTreeView = m_xScriptsListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + css::uno::Reference node + = getBrowseNode(rTreeView, *xSelectedIter); + css::uno::Reference xInv(node, css::uno::UNO_QUERY); + if (xInv.is()) + { + m_xDialog->response(RET_CANCEL); + css::uno::Sequence args(0); + css::uno::Sequence outArgs(0); + css::uno::Sequence outIndex; + try + { + // ISSUE need code to run script here + xInv->invoke(u"Editable"_ustr, args, outIndex, outArgs); + } + catch (css::uno::Exception const&) + { + TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to invoke"); + } + } + } + else if (&rButton == m_xLibraryModuleDialogDeleteButton.get()) + { + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + ScriptingFrameworkScriptsDeleteEntry(rTreeView, *xSelectedIter); + } + else if (&rButton == m_xMacroDeleteButton.get()) + { + weld::TreeView& rTreeView = m_xScriptsListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + ScriptingFrameworkScriptsDeleteEntry(rTreeView, *xSelectedIter); + } + else if (&rButton == m_xLibraryModuleDialogRenameButton.get()) + { + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + ScriptingFrameworkScriptsRenameEntry(rTreeView, *xSelectedIter); + } + else if (&rButton == m_xMacroRenameButton.get()) + { + weld::TreeView& rTreeView = m_xScriptsListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + ScriptingFrameworkScriptsRenameEntry(rTreeView, *xSelectedIter); + } + else if (&rButton == m_xAssignButton.get()) + { + SfxAllItemSet Args(SfxGetpApp()->GetPool()); + SfxAllItemSet aInternalSet(SfxGetpApp()->GetPool()); + if (m_xDocumentFrame.is()) + aInternalSet.Put(SfxUnoFrameItem(SID_FILLFRAME, m_xDocumentFrame)); + SfxRequest aRequest(SID_CONFIGACCEL, SfxCallMode::SYNCHRON, Args, aInternalSet); + + SfxMacroInfoItem aMacroInfoItem( + SID_MACROINFO, nullptr, + m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LIBRARY), + OUString(), m_xScriptsListBox->GetSelectedScriptName(), OUString(), + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LOCATION)); + aRequest.AppendItem(aMacroInfoItem); + SfxGetpApp()->ExecuteSlot(aRequest); + } +} + +bool MacroManagerDialog::IsLibraryReadOnlyOrFailedPasswordQuery( + const basctl::ScriptDocument& rDocument, weld::TreeIter* pIter) +{ + css::uno::Reference xModLibContainer( + rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + css::uno::Reference xDlgLibContainer( + rDocument.getLibraryContainer(basctl::E_DIALOGS), css::uno::UNO_QUERY); + + OUString aLibName + = m_xScriptContainersListBox->GetContainerName(*pIter, ScriptContainerType::LIBRARY); + + // check if library is readonly + if ((xModLibContainer.is() && xModLibContainer->hasByName(aLibName) + && xModLibContainer->isLibraryReadOnly(aLibName) + && !xModLibContainer->isLibraryLink(aLibName)) + || (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName) + && xDlgLibContainer->isLibraryReadOnly(aLibName) + && !xDlgLibContainer->isLibraryLink(aLibName))) + { + std::unique_ptr xErrorBox( + Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, + VclButtonsType::Ok, CuiResId(STR_LIBISREADONLY))); + xErrorBox->run(); + return true; + } + + // password + if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName) + /*&& !xModLibContainer->isLibraryLoaded(aLibName)*/) + { + bool bOK = true; + // check password + css::uno::Reference xPasswd(xModLibContainer, + css::uno::UNO_QUERY); + if (xPasswd.is() && xPasswd->isLibraryPasswordProtected(aLibName) + && !xPasswd->isLibraryPasswordVerified(aLibName)) + { + OUString sPassword; + bOK = basctl::QueryPassword(m_xDialog.get(), xModLibContainer, aLibName, sPassword, + true, true); + } + if (!bOK) + return true; + } + + return false; +} + +// adapted from LibPage inline renaming +// IMPL_LINK(LibPage, EditingEntryHdl, const weld::TreeIter&, rIter, bool) +// IMPL_LINK(LibPage, EditedEntryHdl, const IterString&, rIterString, bool) +// basctl/source/basicide/moduldl2.cxx +void MacroManagerDialog::BasicScriptsLibraryModuleDialogRename( + const basctl::ScriptDocument& rDocument) +{ + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + + if (IsLibraryReadOnlyOrFailedPasswordQuery(rDocument, xSelectedIter.get())) + return; + + OUString sOldName = rTreeView.get_text(*xSelectedIter); + + if (rTreeView.get_iter_depth(*xSelectedIter) == 2) // library + { + InputDialog aInputDlg(m_xDialog.get(), CuiResId(STR_INPUTDIALOG_RENAMELIBRARYLABEL)); + aInputDlg.HideHelpBtn(); + aInputDlg.set_title(CuiResId(STR_INPUTDIALOG_RENAMELIBRARYTITLE)); + aInputDlg.SetEntryText(sOldName); + aInputDlg.setCheckEntry([&](OUString sNewName) { + if (sNewName != sOldName + && (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; + + OUString sNewName = aInputDlg.GetEntryText(); + if (sNewName == sOldName) + return; + + bool bSuccess = true; + try + { + css::uno::Reference xModLibContainer( + rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + if (xModLibContainer.is() && xModLibContainer->hasByName(sOldName)) + xModLibContainer->renameLibrary(sOldName, sNewName); + css::uno::Reference xDlgLibContainer( + rDocument.getLibraryContainer(basctl::E_DIALOGS), css::uno::UNO_QUERY); + if (xDlgLibContainer.is() && xDlgLibContainer->hasByName(sOldName)) + xDlgLibContainer->renameLibrary(sOldName, sNewName); + } + catch (css::uno::Exception const&) + { + bSuccess = false; + TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to Rename"); + } + + if (bSuccess) + { + basctl::MarkDocumentModified(rDocument); + // rTreeView.set_text(*xSelectedIter, sNewName); + } + } + else + { + // module/dialog + ScriptContainerInfo* pScriptContainerInfo + = weld::fromId(rTreeView.get_id(*xSelectedIter)); + if (!pScriptContainerInfo) + return; // should never happen + + OUString aLibName = m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LIBRARY); + + InputDialog aInputDlg(m_xDialog.get(), CuiResId(pScriptContainerInfo->pBrowseNode + ? STR_INPUTDIALOG_RENAMEMODULELABEL + : STR_INPUTDIALOG_RENAMEDIALOGLABEL)); + aInputDlg.HideHelpBtn(); + aInputDlg.set_title(CuiResId(pScriptContainerInfo->pBrowseNode + ? STR_INPUTDIALOG_RENAMEMODULETITLE + : STR_INPUTDIALOG_RENAMEMODULETITLE)); + aInputDlg.SetEntryText(sOldName); + aInputDlg.setCheckEntry([&](OUString sNewName) { + if (sNewName != sOldName + && (sNewName.isEmpty() || sNewName.getLength() > 30 + || !basctl::IsValidSbxName(sNewName) + || pScriptContainerInfo->pBrowseNode + ? rDocument.hasModule(aLibName, sNewName) + : rDocument.hasDialog(aLibName, sNewName))) + return false; + return true; + }); + + if (!aInputDlg.run()) + return; + + OUString sNewName = aInputDlg.GetEntryText(); + if (sNewName == sOldName) + return; + + if (pScriptContainerInfo->pBrowseNode + ? rDocument.renameModule(aLibName, sOldName, sNewName) + : rDocument.renameDialog(aLibName, sOldName, sNewName, nullptr)) + { + basctl::MarkDocumentModified(rDocument); + // rTreeView.set_text(*xSelectedIter, sNewName); + } + } +} + +void MacroManagerDialog::BasicScriptsLibraryModuleDialogDelete( + const basctl::ScriptDocument& rDocument) +{ + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + + if (IsLibraryReadOnlyOrFailedPasswordQuery(rDocument, xSelectedIter.get())) + return; + + if (rTreeView.get_iter_depth(*xSelectedIter) == 2) // library + { + // see: void LibPage::DeleteCurrent() + // basctl/source/basicide/moduldl2.cxx + OUString aLibName = rTreeView.get_text(*xSelectedIter); + + // check, if library is link + bool bIsLibraryLink = false; + css::uno::Reference xModLibContainer( + rDocument.getLibraryContainer(basctl::E_SCRIPTS), css::uno::UNO_QUERY); + css::uno::Reference xDlgLibContainer( + rDocument.getLibraryContainer(basctl::E_DIALOGS), css::uno::UNO_QUERY); + if ((xModLibContainer.is() && xModLibContainer->hasByName(aLibName) + && xModLibContainer->isLibraryLink(aLibName)) + || (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName) + && xDlgLibContainer->isLibraryLink(aLibName))) + { + bIsLibraryLink = true; + } + + if (!basctl::QueryDelLib(aLibName, bIsLibraryLink, m_xDialog.get())) + return; + + // inform BasicIDE + SfxUnoAnyItem aDocItem(SID_BASICIDE_ARG_DOCUMENT_MODEL, + css::uno::Any(rDocument.getDocumentOrNull())); + SfxStringItem aLibNameItem(SID_BASICIDE_ARG_LIBNAME, aLibName); + if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) + pDispatcher->ExecuteList(SID_BASICIDE_LIBREMOVED, SfxCallMode::SYNCHRON, + { &aDocItem, &aLibNameItem }); + + // remove library from module and dialog library containers + if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)) + xModLibContainer->removeLibrary(aLibName); + if (xDlgLibContainer.is() && xDlgLibContainer->hasByName(aLibName)) + xDlgLibContainer->removeLibrary(aLibName); + + basctl::MarkDocumentModified(rDocument); + } + else + { + // delete Basic module or dialog + // adapted from void ObjectPage::DeleteCurrent() basctl/source/basicide/moduldlg.cxx + ScriptContainerInfo* pScriptContainerInfo + = weld::fromId(rTreeView.get_id(*xSelectedIter)); + if (!pScriptContainerInfo) + return; // shouldn't happen + + // pBrowseNode points to nullptr for dialog entries + if (pScriptContainerInfo->pBrowseNode) + { + if (!basctl::QueryDelModule(m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::MODULEORDIALOG), + m_xDialog.get())) + return; + } + else + { + if (!basctl::QueryDelDialog(m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::MODULEORDIALOG), + m_xDialog.get())) + return; + } + + bool bSuccess = false; + if (pScriptContainerInfo->pBrowseNode) + bSuccess + = rDocument.removeModule(m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LIBRARY), + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::MODULEORDIALOG)); + else + bSuccess + = rDocument.removeDialog(m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LIBRARY), + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::MODULEORDIALOG)); + + if (bSuccess) + { + if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) + { + SbxItem aSbxItem(SID_BASICIDE_ARG_SBX, rDocument, + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::LIBRARY), + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::MODULEORDIALOG), + pScriptContainerInfo->pBrowseNode ? basctl::SBX_TYPE_MODULE + : basctl::SBX_TYPE_DIALOG); + pDispatcher->ExecuteList(SID_BASICIDE_SBXDELETED, SfxCallMode::SYNCHRON, + { &aSbxItem }); + } + basctl::MarkDocumentModified(rDocument); + } + } +} + +// inspired by IMPL_LINK( LibPage, ButtonHdl, weld::Button&, rButton, void ) +// else if (&rButton == m_xPasswordButton.get()) +// basctl/source/basicide/moduldl2.cxx +void MacroManagerDialog::BasicScriptsLibraryPassword(const basctl::ScriptDocument& rDocument) +{ + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + + OUString aLibName = rTreeView.get_text(*xSelectedIter); + + // load module library (if not loaded) + css::uno::Reference xModLibContainer + = rDocument.getLibraryContainer(basctl::E_SCRIPTS); + if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName) + && !xModLibContainer->isLibraryLoaded(aLibName)) + { + xModLibContainer->loadLibrary(aLibName); + } + + // check if library is password protected --> this is for setting and removing password + if (xModLibContainer.is() && xModLibContainer->hasByName(aLibName)) + { + css::uno::Reference xPasswd(xModLibContainer, + css::uno::UNO_QUERY); + if (xPasswd.is()) + { + if (xPasswd->isLibraryPasswordProtected(aLibName) + && !xPasswd->isLibraryPasswordVerified(aLibName)) + { + // password not verified + OUString sPassword; + if (basctl::QueryPassword(m_xDialog.get(), xModLibContainer, aLibName, sPassword, + true, true)) + { + CheckButtons(); + } + return; + } + + // set/change password dialog + SvxPasswordDialog aDlg(m_xDialog.get(), !xPasswd->isLibraryPasswordProtected(aLibName)); + aDlg.SetCheckPasswordHdl(LINK(this, MacroManagerDialog, CheckPasswordHdl)); + + if (aDlg.run() == RET_OK) + { + if (xPasswd->isLibraryPasswordProtected(aLibName)) + rTreeView.set_image(*xSelectedIter, RID_CUIBMP_LOCKED); + else + rTreeView.set_image(*xSelectedIter, RID_CUIBMP_LIB); + basctl::MarkDocumentModified(rDocument); + } + + rTreeView.grab_focus(); + } + } +} + +void MacroManagerDialog::BasicScriptsMacroEdit(const basctl::ScriptDocument& rDocument) +{ + // hide the scripts organizer selector dialog before opening the basic ide + m_xDialog->hide(); + + // open the basic ide + SfxAllItemSet aArgs(SfxGetpApp()->GetPool()); + SfxRequest aRequest(SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs); + SfxGetpApp()->ExecuteSlot(aRequest); + + // navigate to the method + SbxItem aSbxItem( + SID_BASICIDE_ARG_SBX, rDocument, + m_xScriptContainersListBox->GetSelectedEntryContainerName(ScriptContainerType::LIBRARY), + m_xScriptContainersListBox->GetSelectedEntryContainerName( + ScriptContainerType::MODULEORDIALOG), + m_xScriptsListBox->GetSelectedScriptName(), basctl::SBX_TYPE_METHOD); + // need to use basctl::GetDispatcher() to have expected results with qt5 and x11, + // gtk3 works with SfxGetpApp()->GetDispatcher() + if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) + pDispatcher->ExecuteList(SID_BASICIDE_SHOWSBX, SfxCallMode::ASYNCHRON, { &aSbxItem }); + // alternate way to do this + // BasicManager* pBasMgr = rDocument.getBasicManager(); + // SfxMacroInfoItem aInfoItem( SID_BASICIDE_ARG_MACROINFO, pBasMgr, aLibName, aModName, aMethodName, OUString() ); + // if (SfxDispatcher* pDispatcher = basctl::GetDispatcher()) + // pDispatcher->ExecuteList(SID_BASICIDE_EDITMACRO, SfxCallMode::ASYNCHRON, { &aInfoItem }); + + // now it is safe to close the scripts organizer selector dialog + m_xDialog->response(0); +} + +// modified version of void SvxScriptOrgDialog::renameEntry(const weld::TreeIter& rEntry) +// cui/source/dialogs/scriptdlg.cxx +void MacroManagerDialog::ScriptingFrameworkScriptsRenameEntry(weld::TreeView& rTreeView, + const weld::TreeIter& rEntry) +{ + css::uno::Reference xBrowseNode + = getBrowseNode(rTreeView, rEntry); + css::uno::Reference xInv(xBrowseNode, css::uno::UNO_QUERY); + + if (xInv.is()) + { + OUString aNewName = xBrowseNode->getName(); + sal_Int32 extnPos = aNewName.lastIndexOf('.'); + if (extnPos > 0) + { + aNewName = aNewName.copy(0, extnPos); + } + + InputDialog aInputDlg(m_xDialog.get(), + xBrowseNode->getType() + == css::script::browse::BrowseNodeTypes::CONTAINER + ? CuiResId(STR_INPUTDIALOG_RENAMELIBRARYLABEL) + : CuiResId(STR_INPUTDIALOG_RENAMEMACROLABEL)); + aInputDlg.set_title(xBrowseNode->getType() + == css::script::browse::BrowseNodeTypes::CONTAINER + ? CuiResId(STR_INPUTDIALOG_RENAMELIBRARYTITLE) + : CuiResId(STR_INPUTDIALOG_RENAMEMACROTITLE)); + aInputDlg.SetEntryText(aNewName); + aInputDlg.HideHelpBtn(); + // doesn't check if the name already exists, that will be caught below by invoke + aInputDlg.setCheckEntry([](OUString sNewName) { + if (sNewName.isEmpty() || sNewName.getLength() > 30 + || !basctl::IsValidSbxName(sNewName)) + return false; + return true; + }); + + if (!aInputDlg.run()) + return; + + aNewName = aInputDlg.GetEntryText(); + + css::uno::Sequence args{ css::uno::Any(aNewName) }; + css::uno::Sequence outArgs; + css::uno::Sequence outIndex; + try + { + css::uno::Any aResult = xInv->invoke(u"Renamable"_ustr, args, outIndex, outArgs); + xBrowseNode.set(aResult, css::uno::UNO_QUERY); + } + catch (css::uno::Exception const&) + { + TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to Rename"); + } + } + if (xBrowseNode.is()) + { + if (xBrowseNode->getType() == css::script::browse::BrowseNodeTypes::CONTAINER) + { + m_xScriptContainersListBox->ScriptContainerSelected(); + } + else + { + ScriptInfo* pScriptInfo = weld::fromId(m_xScriptsListBox->get_id(rEntry)); + if (pScriptInfo) + { + css::uno::Reference xPropSet(xBrowseNode, + css::uno::UNO_QUERY); + if (xPropSet.is()) + { + 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 + } + pScriptInfo->sURL = sURI; + } + } + } + rTreeView.set_text(rEntry, xBrowseNode->getName()); + rTreeView.set_cursor(rEntry); + } + else + { + //ISSUE L10N & message from exception? + OUString aError(CuiResId(RID_CUISTR_RENAMEFAILED)); + std::unique_ptr xErrorBox(Application::CreateMessageDialog( + m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, aError)); + xErrorBox->set_title(CuiResId(RID_CUISTR_RENAMEFAILED_TITLE)); + xErrorBox->run(); + } +} + +// for Scripting Framework entries +// duplicate of OUString SvxScriptOrgDialog::getListOfChildren +// cui/source/dialogs/scriptdlg.cxx +OUString MacroManagerDialog::getListOfChildren( + const css::uno::Reference& node, int depth) +{ + OUStringBuffer result = "\n"; + for (int i = 0; i <= depth; i++) + { + result.append("\t"); + } + result.append(node->getName()); + + try + { + if (node->hasChildNodes()) + { + const css::uno::Sequence> children + = node->getChildNodes(); + for (const css::uno::Reference& n : children) + { + result.append(getListOfChildren(n, depth + 1)); + } + } + } + catch (css::uno::Exception&) + { + // ignore, will return an empty string + } + + return result.makeStringAndClear(); +} + +// modified verson of void SvxScriptOrgDialog::deleteEntry(const weld::TreeIter& rEntry) +// cui/source/dialogs/scriptdlg.cxx +void MacroManagerDialog::ScriptingFrameworkScriptsDeleteEntry(weld::TreeView& rTreeView, + const weld::TreeIter& rEntry) +{ + bool result = false; + css::uno::Reference node = getBrowseNode(rTreeView, rEntry); + // ISSUE L10N string & can we center list? + OUString aQuery = CuiResId(RID_CUISTR_DELQUERY) + getListOfChildren(node, 0); + std::unique_ptr xQueryBox(Application::CreateMessageDialog( + m_xDialog.get(), VclMessageType::Question, VclButtonsType::YesNo, aQuery)); + xQueryBox->set_title(CuiResId(RID_CUISTR_DELQUERY_TITLE)); + if (xQueryBox->run() == RET_NO) + { + return; + } + + css::uno::Reference xInv(node, css::uno::UNO_QUERY); + if (xInv.is()) + { + css::uno::Sequence args(0); + css::uno::Sequence outArgs(0); + css::uno::Sequence outIndex; + try + { + css::uno::Any aResult = xInv->invoke(u"Deletable"_ustr, args, outIndex, outArgs); + aResult >>= result; // or do we just assume true if no exception ? + } + catch (css::uno::Exception const&) + { + TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to delete"); + } + } + if (result) + { + if (&rTreeView == &m_xScriptContainersListBox->get_widget()) + { + m_xScriptContainersListBox->Remove(&rEntry, true); + SelectHdl(rTreeView); + } + else + { + m_xScriptsListBox->Remove(rEntry); + } + UpdateUI(); + } + else + { + //ISSUE L10N & message from exception? + std::unique_ptr xErrorBox( + Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, + VclButtonsType::Ok, CuiResId(RID_CUISTR_DELFAILED))); + xErrorBox->set_title(CuiResId(RID_CUISTR_CREATEFAILED_TITLE)); + xErrorBox->run(); + } +} + +// Modified version of SvxScriptOrgDialog::CreateEntry +// cui/source/dialogs/scriptdlg.cxx +void MacroManagerDialog::ScriptingFrameworkScriptsCreateEntry(InputDialogMode eInputDialogMode) +{ + weld::TreeView& rTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xSelectedIter = rTreeView.make_iterator(); + if (!rTreeView.get_selected(xSelectedIter.get())) + return; // should never happen + + css::uno::Reference aChildNode; + css::uno::Reference xBrowseNode + = getBrowseNode(rTreeView, *xSelectedIter); + css::uno::Reference xInv(xBrowseNode, css::uno::UNO_QUERY); + + // Currently, invocation is not implemented for python, only beanshell, javascript, and java. + if (xInv.is()) + { + OUString aNewName; + OUString aNewStdName; + if (eInputDialogMode == InputDialogMode::NEWLIB) + { + aNewStdName = CuiResId(STR_LIBRARY); + } + else + { + aNewStdName = CuiResId(STR_MACRO); + } + + bool bValid = false; + sal_Int32 i = 1; + + css::uno::Sequence> childNodes; + // no children => ok to create Parcel1 or Script1 without checking ? + try + { + if (!xBrowseNode->hasChildNodes()) + { + aNewName = aNewStdName + OUString::number(i); + bValid = true; + } + else + { + childNodes = xBrowseNode->getChildNodes(); + } + } + catch (css::uno::Exception&) + { + // ignore, will continue on with empty sequence + } + + OUString extn; + while (!bValid) + { + aNewName = aNewStdName + OUString::number(i); + bool bFound = false; + if (childNodes.hasElements()) + { + OUString nodeName = childNodes[0]->getName(); + sal_Int32 extnPos = nodeName.lastIndexOf('.'); + if (extnPos > 0) + extn = nodeName.copy(extnPos); + } + for (const css::uno::Reference& n : childNodes) + { + if (Concat2View(aNewName + extn) == n->getName()) + { + bFound = true; + break; + } + } + if (bFound) + { + i++; + } + else + { + bValid = true; + } + } + + InputDialog aInputDlg(m_xDialog.get(), eInputDialogMode == InputDialogMode::NEWLIB + ? CuiResId(STR_INPUTDIALOG_NEWLIBRARYLABEL) + : CuiResId(STR_INPUTDIALOG_NEWMACROLABEL)); + aInputDlg.set_title(eInputDialogMode == InputDialogMode::NEWLIB + ? CuiResId(STR_INPUTDIALOG_NEWLIBRARYTITLE) + : CuiResId(STR_INPUTDIALOG_NEWMACROTITLE)); + aInputDlg.SetEntryText(aNewName); + aInputDlg.HideHelpBtn(); + + // setCheckEntry doesn't check if the name already exists. It is checked after the dialog + // in the Creatable invocation call - this could be improved by including a check for + // existing name + aInputDlg.setCheckEntry([](OUString sNewName) { + if (sNewName.isEmpty() || sNewName.getLength() > 30 + || !basctl::IsValidSbxName(sNewName)) + return false; + return true; + }); + + do + { + if (aInputDlg.run()) + { + OUString aUserSuppliedName = aInputDlg.GetEntryText(); + bValid = true; + for (const css::uno::Reference& n : childNodes) + { + if (Concat2View(aUserSuppliedName + extn) == n->getName()) + { + bValid = false; + OUString aError = CuiResId(RID_CUISTR_CREATEFAILED) + + CuiResId(RID_CUISTR_CREATEFAILEDDUP); + + std::unique_ptr xErrorBox( + Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, + VclButtonsType::Ok, aError)); + xErrorBox->set_title(CuiResId(RID_CUISTR_CREATEFAILED_TITLE)); + xErrorBox->run(); + aInputDlg.SetEntryText(aNewName); + break; + } + } + if (bValid) + aNewName = aUserSuppliedName; + } + else + { + // user hit cancel + return; + } + } while (!bValid); + + // open up parent node (which ensures it's loaded) + rTreeView.expand_row(*xSelectedIter); + + css::uno::Sequence args{ css::uno::Any(aNewName) }; + css::uno::Sequence outArgs; + css::uno::Sequence outIndex; + try + { + css::uno::Any aResult = xInv->invoke(u"Creatable"_ustr, args, outIndex, outArgs); + aChildNode.set(aResult, css::uno::UNO_QUERY); + } + catch (css::uno::Exception const&) + { + TOOLS_WARN_EXCEPTION("cui.dialogs", "Caught exception trying to Create"); + } + } + if (aChildNode.is()) + { + if (rTreeView.get_iter_depth(*xSelectedIter) == 1) // language node + { + m_xScriptContainersListBox->Fill(xSelectedIter.get()); + rTreeView.expand_row(*xSelectedIter); + rTreeView.select(*xSelectedIter); + } + else + { + m_xScriptContainersListBox->ScriptContainerSelected(); + } + UpdateUI(); + } + else + { + //ISSUE L10N & message from exception? + OUString aError(CuiResId(RID_CUISTR_CREATEFAILED)); + std::unique_ptr xErrorBox(Application::CreateMessageDialog( + m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, aError)); + xErrorBox->set_title(CuiResId(RID_CUISTR_CREATEFAILED_TITLE)); + xErrorBox->run(); + } +} + +// called from OUString AbstractMacroManagerDialog_Impl::GetScriptURL() const +// cui/source/factory/dlgfact.cxx +OUString MacroManagerDialog::GetScriptURL() const +{ + OUString result; + std::unique_ptr xIter = m_xScriptsListBox->make_iterator(); + if (m_xScriptsListBox->get_selected(xIter.get())) + { + ScriptInfo* pScriptInfo = weld::fromId(m_xScriptsListBox->get_id(*xIter)); + if (pScriptInfo) + result = pScriptInfo->sURL; + } + return result; +} + +constexpr OUString MACRO_MANAGER_CONFIGNAME = u"MacroManagerDialog"_ustr; +constexpr OUString LAST_RUN_MACRO_INFO = u"LastRunMacro"_ustr; + +// adapted from SvxScriptSelectorDialog::SaveLastUsedMacro() +// cui/source/customize/cfgutil.cxx +void MacroManagerDialog::SaveLastUsedMacro() +{ + // Gets the current selection in the dialog as a series of selected entries + OUString sMacroInfo = m_xScriptsListBox->GetSelectedScriptName(); + + weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xIter = rScriptContainersTreeView.make_iterator(); + + if (!rScriptContainersTreeView.get_selected(xIter.get())) + return; + + do + { + sMacroInfo = rScriptContainersTreeView.get_text(*xIter) + "|" + sMacroInfo; + } while (rScriptContainersTreeView.iter_parent(*xIter)); + + SvtViewOptions(EViewType::Dialog, MACRO_MANAGER_CONFIGNAME) + .SetUserItem(LAST_RUN_MACRO_INFO, css::uno::Any(sMacroInfo)); +} + +// adapted from SvxScriptSelectorDialog::LoadLastUsedMacro() +// cui/source/customize/cfgutil.cxx +void MacroManagerDialog::LoadLastUsedMacro() +{ + SvtViewOptions aDlgOpt(EViewType::Dialog, MACRO_MANAGER_CONFIGNAME); + if (!aDlgOpt.Exists()) + return; + + OUString sMacroInfo; + aDlgOpt.GetUserItem(LAST_RUN_MACRO_INFO) >>= sMacroInfo; + if (sMacroInfo.isEmpty()) + return; + + // Counts how many entries exist in the macro info string + sal_Int16 nInfoParts = 0; + sal_Int16 nLastIndex = sMacroInfo.indexOf('|'); + if (nLastIndex > -1) + { + nInfoParts = 1; + while (nLastIndex != -1) + { + nInfoParts++; + nLastIndex = sMacroInfo.indexOf('|', nLastIndex + 1); + } + } + + weld::TreeView& rScriptContainersTreeView = m_xScriptContainersListBox->get_widget(); + std::unique_ptr xIter = rScriptContainersTreeView.make_iterator(); + + if (!rScriptContainersTreeView.get_iter_first(*xIter)) + return; + + // Expand the nodes in the script containers tree + OUString sNodeToExpand; + bool bIsIterValid; + sal_Int16 nOpenedNodes = 0; + for (sal_Int16 i = 0; i < nInfoParts - 1; i++) + { + sNodeToExpand = sMacroInfo.getToken(i, '|'); + bIsIterValid = true; + while (bIsIterValid && rScriptContainersTreeView.get_text(*xIter) != sNodeToExpand) + bIsIterValid = rScriptContainersTreeView.iter_next_sibling(*xIter); + + if (bIsIterValid) + { + rScriptContainersTreeView.expand_row(*xIter); + nOpenedNodes++; + } + if (rScriptContainersTreeView.iter_has_child(*xIter)) + (void)rScriptContainersTreeView.iter_children(*xIter); + else if (nOpenedNodes < nInfoParts - 1) + // If the number of levels in the tree is smaller than the + // number of parts in the macro info string, then return + return; + } + rScriptContainersTreeView.select(*xIter); + rScriptContainersTreeView.scroll_to_row(*xIter); + + // fill the scripts list box and set the label + m_xScriptContainersListBox->ScriptContainerSelected(); + m_xScriptsListBoxLabel->set_label(m_aScriptsListBoxLabelBaseStr + " " + + rScriptContainersTreeView.get_text(*xIter)); + + // Select the macro in the scripts tree + weld::TreeView& rScriptsTreeView = m_xScriptsListBox->get_widget(); + xIter = rScriptsTreeView.make_iterator(); + if (rScriptsTreeView.get_iter_first(*xIter)) + { + OUString sMacroName = sMacroInfo.getToken(nInfoParts - 1, '|'); + bIsIterValid = true; + while (bIsIterValid && rScriptsTreeView.get_text(*xIter) != sMacroName) + bIsIterValid = rScriptsTreeView.iter_next_sibling(*xIter); + if (bIsIterValid) + { + rScriptsTreeView.scroll_to_row(*xIter); + rScriptsTreeView.select(*xIter); + } + } + + UpdateUI(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/factory/dlgfact.cxx b/cui/source/factory/dlgfact.cxx index 4e8a2dab3c5a..2018878eaefa 100644 --- a/cui/source/factory/dlgfact.cxx +++ b/cui/source/factory/dlgfact.cxx @@ -94,6 +94,8 @@ #include #include +#include + using namespace ::com::sun::star; using namespace ::com::sun::star::frame; using namespace ::com::sun::star::container; @@ -134,6 +136,7 @@ IMPL_ABSTDLG_CLASS_ASYNC(AbstractPasswordToOpenModifyDialog,weld::DialogControll IMPL_ABSTDLG_CLASS_ASYNC(AbstractQrCodeGenDialog,QrCodeGenDialog) IMPL_ABSTDLG_CLASS_ASYNC(AbstractPasteDialog,SfxDialogController) IMPL_ABSTDLG_CLASS_ASYNC(AbstractScriptSelectorDialog,SfxDialogController) +IMPL_ABSTDLG_CLASS_ASYNC(AbstractMacroManagerDialog,SfxDialogController) IMPL_ABSTDLG_CLASS_ASYNC(AbstractSpellDialog,SfxDialogController) IMPL_ABSTDLG_CLASS_ASYNC(AbstractSvxAreaTabDialog,SfxTabDialogController) IMPL_ABSTDLG_CLASS_ASYNC(AbstractSvxCaptionDialog,SfxTabDialogController) @@ -996,6 +999,18 @@ void AbstractScriptSelectorDialog_Impl::SetRunLabel() m_xDlg->SetRunLabel(); } +VclPtr +AbstractDialogFactory_Impl::CreateMacroManagerDialog(weld::Window* pParent, + const Reference& rxFrame) +{ + return VclPtr::Create( + std::make_shared(pParent, rxFrame)); +} + +OUString AbstractMacroManagerDialog_Impl::GetScriptURL() const { return m_xDlg->GetScriptURL(); } + +void AbstractMacroManagerDialog_Impl::LoadLastUsedMacro() const { m_xDlg->LoadLastUsedMacro(); } + VclPtr AbstractDialogFactory_Impl::CreateSvxScriptOrgDialog(weld::Window* pParent, const OUString& rLanguage) { diff --git a/cui/source/factory/dlgfact.hxx b/cui/source/factory/dlgfact.hxx index b1c82104c7a0..793cf193af09 100644 --- a/cui/source/factory/dlgfact.hxx +++ b/cui/source/factory/dlgfact.hxx @@ -60,6 +60,8 @@ #include #include +#include + #define DECL_ABSTDLG_CLASS_(Class,Base,Dialog,StdPtr) \ class Class##_Impl final : public Base \ { \ @@ -206,6 +208,13 @@ DECL_ABSTDLG_CLASS_ASYNC(AbstractScriptSelectorDialog,SvxScriptSelectorDialog) virtual void SetRunLabel() override; }; + +// AbstractMacroManagerDialog_Impl +DECL_ABSTDLG_CLASS_ASYNC(AbstractMacroManagerDialog,MacroManagerDialog) + virtual OUString GetScriptURL() const override; + virtual void LoadLastUsedMacro() const override; +}; + // AbstractGalleryIdDialog_Impl DECL_ABSTDLG_CLASS(AbstractGalleryIdDialog,GalleryIdDialog) virtual sal_uInt32 GetId() const override; @@ -575,6 +584,10 @@ public: virtual VclPtr CreateScriptSelectorDialog(weld::Window* pParent, const css::uno::Reference< css::frame::XFrame >& rxFrame) override; + virtual VclPtr CreateMacroManagerDialog(weld::Window* pParent, + const css::uno::Reference< css::frame::XFrame >& rxFrame) override; + + virtual void ShowAsyncScriptErrorDialog(weld::Window* pParent, const css::uno::Any& rException) override; virtual VclPtr CreateSvxMacroAssignDlg( diff --git a/cui/source/inc/MacroManagerDialog.hxx b/cui/source/inc/MacroManagerDialog.hxx new file mode 100644 index 000000000000..64854d6980a6 --- /dev/null +++ b/cui/source/inc/MacroManagerDialog.hxx @@ -0,0 +1,255 @@ +/* -*- 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/. + */ + +#pragma once + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +struct ScriptContainerInfo +{ + css::script::browse::XBrowseNode* pBrowseNode; + + ScriptContainerInfo(css::script::browse::XBrowseNode* pObj) + : pBrowseNode(pObj) + { + } +}; + +struct ScriptInfo +{ + css::script::browse::XBrowseNode* pBrowseNode; + OUString sURL; + OUString sDescription; + + ScriptInfo(css::script::browse::XBrowseNode* pObj, const OUString& rsUrl, + const OUString& rsDesc) + : pBrowseNode(pObj) + , sURL(rsUrl) + , sDescription(rsDesc) + { + } +}; + +typedef std::vector> ScriptInfoArr; + +// inspired by class CuiConfigFunctionListBox +// cui/source/inc/cfgutil.hxx +class ScriptsListBox +{ + friend class ScriptContainersListBox; // for access to aArr + + ScriptInfoArr aArr; + + std::unique_ptr m_xTreeView; + std::unique_ptr m_xScratchIter; + + DECL_LINK(QueryTooltip, const weld::TreeIter& rIter, OUString); + +public: + ScriptsListBox(std::unique_ptr xTreeView); + ~ScriptsListBox(); + + void ClearAll(); + static OUString GetDescriptionText(const OUString& rId); + OUString GetSelectedScriptName(); + + void connect_changed(const Link& rLink) + { + m_xTreeView->connect_changed(rLink); + } + void connect_popup_menu(const Link& rLink) + { + m_xTreeView->connect_popup_menu(rLink); + } + void connect_row_activated(const Link& rLink) + { + m_xTreeView->connect_row_activated(rLink); + } + void freeze() { m_xTreeView->freeze(); } + void thaw() { m_xTreeView->thaw(); } + void append(const OUString& rId, const OUString& rStr, const OUString& rImage, + const weld::TreeIter* pParent = nullptr) + { + m_xTreeView->insert(pParent, -1, &rStr, &rId, nullptr, nullptr, false, + m_xScratchIter.get()); + m_xTreeView->set_image(*m_xScratchIter, rImage); + } + int n_children() const { return m_xTreeView->n_children(); } + std::unique_ptr make_iterator(const weld::TreeIter* pOrig = nullptr) const + { + return m_xTreeView->make_iterator(pOrig); + } + OUString get_id(const weld::TreeIter& rIter) const { return m_xTreeView->get_id(rIter); } + bool get_selected(weld::TreeIter* pIter) const { return m_xTreeView->get_selected(pIter); } + OUString get_selected_id() const + { + if (!m_xTreeView->get_selected(m_xScratchIter.get())) + return OUString(); + return m_xTreeView->get_id(*m_xScratchIter); + } + void select(int pos) { m_xTreeView->select(pos); } + weld::TreeView& get_widget() { return *m_xTreeView; } + + void Remove(const weld::TreeIter& rEntry); +}; + +enum class ScriptContainerType +{ + LOCATION, + LANGUAGE, + LIBRARY, + MODULEORDIALOG +}; + +class MacroManagerDialog; + +// locations, libraries, modules, and dialogs +class ScriptContainersListBox +{ + friend class MacroManagerDialog; + + ScriptsListBox* m_pScriptsListBox; + + css::uno::Reference m_xContext; + css::uno::Reference m_xFrame; + + std::unique_ptr m_xTreeView; + + void Remove(const weld::TreeIter* pEntryIter, bool bRemoveEntryIter); + void Fill(const weld::TreeIter* pEntryIter); + basctl::ScriptDocument GetScriptDocument(const weld::TreeIter* pIter = nullptr); + + DECL_LINK(ExpandingHdl, const weld::TreeIter&, bool); + DECL_LINK(QueryTooltip, const weld::TreeIter& rIter, OUString); + + // for weld::WaitObject which seems not to always behave as expected without the + // dialog window as a parent + MacroManagerDialog* m_pMacroManagerDialog; + +public: + ScriptContainersListBox(std::unique_ptr xTreeView, + MacroManagerDialog* pMacroManagerDialog); + ~ScriptContainersListBox(); + + void connect_changed(const Link& rLink) + { + m_xTreeView->connect_changed(rLink); + } + void set_size_request(int nWidth, int nHeight) + { + m_xTreeView->set_size_request(nWidth, nHeight); + } + weld::TreeView& get_widget() { return *m_xTreeView; } + void ClearAll(); + + void Init(const css::uno::Reference& xContext, + const css::uno::Reference& xFrame); + void SetScriptsListBox(ScriptsListBox* pBox) { m_pScriptsListBox = pBox; } + void ScriptContainerSelected(); + + void Insert(const css::uno::Reference& xInsertNode, + const weld::TreeIter* pParentEntry, const OUString& rsUiName, + const OUString& rsImage, bool bChildOnDemand = false, int nPos = -1, + weld::TreeIter* pRet = nullptr); + + OUString GetContainerName(const weld::TreeIter& rIter, + const ScriptContainerType eScriptContainerType); + OUString GetSelectedEntryContainerName(ScriptContainerType eScriptContainerType); +}; + +enum class InputDialogMode; + +class MacroManagerDialog : public weld::GenericDialogController, public SfxListener +{ + OUString m_aScriptsListBoxLabelBaseStr; + + // For forwarding to Assign dialog + css::uno::Reference m_xDocumentFrame; + + std::unique_ptr m_xDialogDescription; + std::unique_ptr m_xScriptContainersListBox; + std::unique_ptr m_xScriptsListBox; + std::unique_ptr m_xScriptContainersListBoxLabel; + std::unique_ptr m_xScriptsListBoxLabel; + std::unique_ptr m_xRunButton; + std::unique_ptr m_xCloseButton; + std::unique_ptr m_xDescriptionText; + std::unique_ptr m_xDescriptionFrame; + std::unique_ptr m_xNewLibraryButton; + std::unique_ptr m_xNewModuleButton; + std::unique_ptr m_xNewDialogButton; + std::unique_ptr m_xLibraryModuleDialogEditButton; + std::unique_ptr m_xLibraryModuleDialogRenameButton; + std::unique_ptr m_xLibraryModuleDialogDeleteButton; + std::unique_ptr m_xLibraryPasswordButton; + std::unique_ptr m_xLibraryImportButton; + std::unique_ptr m_xLibraryExportButton; + std::unique_ptr m_xMacroEditButton; + std::unique_ptr m_xMacroDeleteButton; + std::unique_ptr m_xMacroCreateButton; + std::unique_ptr m_xMacroRenameButton; + std::unique_ptr m_xAssignButton; + + DECL_LINK(ClickHdl, weld::Button&, void); + DECL_LINK(SelectHdl, weld::TreeView&, void); + DECL_LINK(FunctionDoubleClickHdl, weld::TreeView&, bool); + DECL_LINK(ContextMenuHdl, const CommandEvent&, bool); + DECL_LINK(CheckPasswordHdl, SvxPasswordDialog*, bool); + + void BasicScriptsCreateLibrary(const basctl::ScriptDocument& rDocument); + void BasicScriptsCreateModule(const basctl::ScriptDocument& rDocument); + void BasicScriptsCreateDialog(const basctl::ScriptDocument& rDocument); + void BasicScriptsLibraryModuleDialogEdit(const basctl::ScriptDocument& rDocument); + void BasicScriptsLibraryModuleDialogRename(const basctl::ScriptDocument& rDocument); + void BasicScriptsLibraryModuleDialogDelete(const basctl::ScriptDocument& rDocument); + void BasicScriptsLibraryPassword(const basctl::ScriptDocument& rDocument); + void BasicScriptsMacroEdit(const basctl::ScriptDocument& rDocument); + bool IsLibraryReadOnlyOrFailedPasswordQuery(const basctl::ScriptDocument& rDocument, + weld::TreeIter* pIter); + + void ScriptingFrameworkScriptsCreateEntry(InputDialogMode eInputDialogMode); + void ScriptingFrameworkScriptsRenameEntry(weld::TreeView& rTreeView, + const weld::TreeIter& rEntry); + void ScriptingFrameworkScriptsDeleteEntry(weld::TreeView& rTreeView, + const weld::TreeIter& rEntry); + static bool getBoolProperty(css::uno::Reference const& xProps, + OUString const& propName); + OUString getListOfChildren(const css::uno::Reference& node, + int depth); + + css::uno::Reference + getBrowseNode(const weld::TreeView& rTreeView, const weld::TreeIter& rTreeIter); + + void UpdateUI(); + void CheckButtons(); + + virtual void Notify(SfxBroadcaster&, const SfxHint& rHint) override; + +public: + MacroManagerDialog(weld::Window* pParent, + const css::uno::Reference& xFrame); + virtual ~MacroManagerDialog() override; + + OUString GetScriptURL() const; + + void SaveLastUsedMacro(); + void LoadLastUsedMacro(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/inc/cfgutil.hxx b/cui/source/inc/cfgutil.hxx index 96bf9fb65067..ce409c98e72d 100644 --- a/cui/source/inc/cfgutil.hxx +++ b/cui/source/inc/cfgutil.hxx @@ -195,11 +195,6 @@ class CuiConfigGroupListBox std::unique_ptr m_xTreeView; std::unique_ptr m_xScratchIter; - static OUString GetImage( - const css::uno::Reference< css::script::browse::XBrowseNode >& node, - css::uno::Reference< css::uno::XComponentContext > const & xCtx, - bool bIsRootNode); - static css::uno::Reference< css::uno::XInterface > getDocumentModel( css::uno::Reference< css::uno::XComponentContext > const & xCtx, std::u16string_view docName); @@ -232,6 +227,11 @@ public: void SelectMacro(const SfxMacroInfoItem*); #endif void SetStylesInfo(SfxStylesInfo_Impl* pStyles); + + static OUString GetImage( + const css::uno::Reference< css::script::browse::XBrowseNode >& node, + css::uno::Reference< css::uno::XComponentContext > const & xCtx, + bool bIsRootNode); }; class SvxScriptSelectorDialog : public weld::GenericDialogController diff --git a/cui/uiconfig/ui/macromanagerdialog.ui b/cui/uiconfig/ui/macromanagerdialog.ui new file mode 100644 index 000000000000..d215c18eb4a8 --- /dev/null +++ b/cui/uiconfig/ui/macromanagerdialog.ui @@ -0,0 +1,564 @@ + + + + + + + + + + + + + + + + + + + + + + + + False + 6 + Macro Manager + True + 0 + 0 + dialog + + + False + vertical + 12 + + + False + end + + + Close + True + True + True + True + True + + + False + True + 2 + + + + + _Help + True + True + True + True + + + False + True + 4 + True + + + + + False + True + end + 0 + + + + + True + False + vertical + 12 + + + True + False + 6 + 6 + 6 + 6 + 6 + + + True + False + True + True + 0 + none + + + True + False + True + True + 6 + + + True + True + True + True + in + + + True + True + True + True + liststore1 + False + 1 + True + + + + + + 6 + + + + 0 + + + + + + 1 + + + + + + + + + True + True + 0 + + + + + True + False + vertical + start + + + New Library... + True + False + True + True + + + Creates a new library. + + + + + False + True + 0 + + + + + New Module... + True + False + True + True + + + False + True + 1 + + + + + New Dialog... + True + False + True + True + + + False + True + 2 + + + + + Edit + True + False + True + True + + + False + True + 3 + + + + + Rename... + True + False + True + True + + + False + True + 4 + + + + + Delete... + True + False + True + True + + + False + True + 5 + + + + + Password... + True + False + True + True + + + Assigns or edits the password for the selected library. + + + + + False + True + 6 + + + + + Import... + True + False + True + True + + + Locate the Basic library that you want to add to the current list, and then click Open. + + + + + False + True + 7 + + + + + Export... + True + False + True + True + + + False + True + 8 + + + + + False + True + 2 + + + + + + + True + False + 6 + Libraries/Modules/Dialogs + + + + + + + + False + True + 0 + + + + + True + False + True + True + 0 + none + + + True + False + True + True + 6 + + + True + True + True + True + in + + + True + True + True + liststore2 + False + 0 + False + + + + + + + + + 0 + + + + + + + + + True + True + 0 + + + + + True + False + vertical + start + + + Run + True + False + True + True + + + False + True + 0 + + + + + Assign... + True + False + True + True + + + False + True + 1 + + + + + Create... + True + False + True + True + + + True + True + 2 + + + + + Edit + True + False + True + True + + + False + True + 3 + + + + + Rename... + True + False + True + True + + + False + True + 4 + + + + + Delete... + True + False + True + True + + + False + True + 5 + + + + + False + True + 2 + + + + + + + True + False + 6 + Existing macros in: + + + + + + + + False + True + 1 + + + + + True + True + 2 + + + + + True + False + 6 + 6 + 6 + 6 + 0 + none + + + 100 + True + True + + + True + False + False + word + False + + + + + + + True + False + 6 + _Description + True + + + + + + + + False + True + 3 + + + + + True + True + 1 + + + + + + close + help + + + diff --git a/dbaccess/uiconfig/dbapp/menubar/menubar.xml b/dbaccess/uiconfig/dbapp/menubar/menubar.xml index 29e65762524c..924db564a2f6 100644 --- a/dbaccess/uiconfig/dbapp/menubar/menubar.xml +++ b/dbaccess/uiconfig/dbapp/menubar/menubar.xml @@ -120,6 +120,8 @@ + + diff --git a/dbaccess/uiconfig/dbquery/menubar/menubar.xml b/dbaccess/uiconfig/dbquery/menubar/menubar.xml index 762a5533de74..5eb22274306d 100644 --- a/dbaccess/uiconfig/dbquery/menubar/menubar.xml +++ b/dbaccess/uiconfig/dbquery/menubar/menubar.xml @@ -75,6 +75,8 @@ + + diff --git a/dbaccess/uiconfig/dbrelation/menubar/menubar.xml b/dbaccess/uiconfig/dbrelation/menubar/menubar.xml index 0c2a73ec31d5..a88bb7abf0c7 100644 --- a/dbaccess/uiconfig/dbrelation/menubar/menubar.xml +++ b/dbaccess/uiconfig/dbrelation/menubar/menubar.xml @@ -58,6 +58,8 @@ + + diff --git a/dbaccess/uiconfig/dbtable/menubar/menubar.xml b/dbaccess/uiconfig/dbtable/menubar/menubar.xml index 80511e8ea4d6..5ccbf5d5f84a 100644 --- a/dbaccess/uiconfig/dbtable/menubar/menubar.xml +++ b/dbaccess/uiconfig/dbtable/menubar/menubar.xml @@ -59,6 +59,8 @@ + + diff --git a/dbaccess/uiconfig/dbtdata/menubar/menubar.xml b/dbaccess/uiconfig/dbtdata/menubar/menubar.xml index e787d60d7355..6313b55fc5f7 100644 --- a/dbaccess/uiconfig/dbtdata/menubar/menubar.xml +++ b/dbaccess/uiconfig/dbtdata/menubar/menubar.xml @@ -84,6 +84,8 @@ + + diff --git a/extensions/uiconfig/sbibliography/menubar/menubar.xml b/extensions/uiconfig/sbibliography/menubar/menubar.xml index 9b449072ac32..3851ceb21aa4 100644 --- a/extensions/uiconfig/sbibliography/menubar/menubar.xml +++ b/extensions/uiconfig/sbibliography/menubar/menubar.xml @@ -32,6 +32,8 @@ + + diff --git a/framework/uiconfig/startmodule/menubar/menubar.xml b/framework/uiconfig/startmodule/menubar/menubar.xml index 72f0354a79df..097154cc3483 100644 --- a/framework/uiconfig/startmodule/menubar/menubar.xml +++ b/framework/uiconfig/startmodule/menubar/menubar.xml @@ -45,6 +45,8 @@ + + diff --git a/include/basctl/basctldllapi.h b/include/basctl/basctldllapi.h new file mode 100644 index 000000000000..9cc166361d1c --- /dev/null +++ b/include/basctl/basctldllapi.h @@ -0,0 +1,23 @@ +/* -*- 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/. + */ + +#pragma once + +#include +#include + +#if defined BASCTL_DLLIMPLEMENTATION +#define BASCTL_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define BASCTL_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif + +#define BASCTL_DLLPRIVATE SAL_DLLPRIVATE + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/basctl/basctldllpublic.hxx b/include/basctl/basctldllpublic.hxx new file mode 100644 index 000000000000..13adf9d7cc3c --- /dev/null +++ b/include/basctl/basctldllpublic.hxx @@ -0,0 +1,43 @@ +/* -*- 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/. + */ + +#pragma once + +#include + +#include "basctldllapi.h" +#include "scriptdocument.hxx" +#include +#include + +namespace basctl +{ +BASCTL_DLLPUBLIC bool IsValidSbxName(std::u16string_view rName); +BASCTL_DLLPUBLIC SAL_RET_MAYBENULL SfxDispatcher* GetDispatcher(); +BASCTL_DLLPUBLIC void MarkDocumentModified(const ScriptDocument& rDocument); + +BASCTL_DLLPUBLIC bool QueryDelDialog(std::u16string_view rName, weld::Widget* pParent); +BASCTL_DLLPUBLIC bool QueryDelModule(std::u16string_view rName, weld::Widget* pParent); +BASCTL_DLLPUBLIC bool QueryDelLib(std::u16string_view rName, bool bRef, weld::Widget* pParent); +BASCTL_DLLPUBLIC bool +QueryPassword(weld::Widget* pDialogParent, + const css::uno::Reference& xLibContainer, + const OUString& rLibName, OUString& rPassword, bool bRepeat = false, + bool bNewTitle = false); + +BASCTL_DLLPUBLIC void ImportLib(const ScriptDocument& rDocument, weld::Dialog* pDialog, + const std::function& func_remove_entry, + const std::function& func_insert_entry, + const std::function& func_insert_entries); + +BASCTL_DLLPUBLIC void Export(const ScriptDocument& rDocument, const OUString& aLibName, + weld::Dialog* pDialog); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basctl/source/inc/sbxitem.hxx b/include/basctl/sbxitem.hxx similarity index 96% rename from basctl/source/inc/sbxitem.hxx rename to include/basctl/sbxitem.hxx index a21e792742ca..23244fe2e42f 100644 --- a/basctl/source/inc/sbxitem.hxx +++ b/include/basctl/sbxitem.hxx @@ -18,6 +18,7 @@ */ #pragma once +#include "basctldllapi.h" #include "scriptdocument.hxx" #include @@ -34,7 +35,7 @@ enum SbxItemType SBX_TYPE_METHOD }; -class SbxItem : public SfxPoolItem +class BASCTL_DLLPUBLIC SbxItem : public SfxPoolItem { const ScriptDocument m_aDocument; const OUString m_aLibName; diff --git a/basctl/source/inc/scriptdocument.hxx b/include/basctl/scriptdocument.hxx similarity index 99% rename from basctl/source/inc/scriptdocument.hxx rename to include/basctl/scriptdocument.hxx index d52dcb6c8c5f..645ca1ab055f 100644 --- a/basctl/source/inc/scriptdocument.hxx +++ b/include/basctl/scriptdocument.hxx @@ -19,6 +19,8 @@ #pragma once +#include "basctldllapi.h" + #include #include #include @@ -61,7 +63,7 @@ namespace basctl /** encapsulates a document which contains Basic scripts and dialogs */ - class ScriptDocument + class BASCTL_DLLPUBLIC ScriptDocument { private: class Impl; diff --git a/include/sfx2/minfitem.hxx b/include/sfx2/minfitem.hxx index c89705726e20..bbf4744afd62 100644 --- a/include/sfx2/minfitem.hxx +++ b/include/sfx2/minfitem.hxx @@ -36,6 +36,7 @@ class SFX2_DLLPUBLIC SfxMacroInfoItem final : public SfxPoolItem OUString aModuleName; OUString aMethodName; OUString aCommentText; + OUString aLocationName; public: static SfxPoolItem* CreateDefault(); @@ -44,7 +45,8 @@ public: OUString aLibName, OUString aModuleName, OUString aMethodName, - OUString aComment); + OUString aComment, + OUString aLocation = OUString()); virtual SfxMacroInfoItem* Clone( SfxItemPool *pPool = nullptr ) const override; virtual bool operator==( const SfxPoolItem& ) const override; @@ -63,6 +65,7 @@ public: const BasicManager* GetBasicManager() const { return pBasicManager; } OUString GetQualifiedName() const; + const OUString& GetLocation() const { return aLocationName; } }; #endif diff --git a/include/sfx2/sfxdlg.hxx b/include/sfx2/sfxdlg.hxx index 31bd0c3108ad..d5cf73b667bf 100644 --- a/include/sfx2/sfxdlg.hxx +++ b/include/sfx2/sfxdlg.hxx @@ -112,6 +112,16 @@ public: virtual void SetRunLabel() = 0; }; +class AbstractMacroManagerDialog : virtual public VclAbstractDialog +{ +protected: + virtual ~AbstractMacroManagerDialog() override = default; + +public: + virtual OUString GetScriptURL() const = 0; + virtual void LoadLastUsedMacro() const = 0; +}; + namespace com::sun::star::frame { class XFrame; } class SFX2_DLLPUBLIC SfxAbstractDialogFactory : virtual public VclAbstractDialogFactory @@ -140,6 +150,11 @@ public: virtual VclPtr CreateScriptSelectorDialog(weld::Window* pParent, const css::uno::Reference< css::frame::XFrame >& rxFrame) = 0; + virtual VclPtr + CreateMacroManagerDialog(weld::Window* pParent, + const css::uno::Reference& rxFrame) + = 0; + virtual void ShowAsyncScriptErrorDialog( weld::Window* pParent, const css::uno::Any& rException ) = 0; virtual VclPtr CreateOptionsDialog( diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc index 6dbd397f8922..c71ddca61559 100644 --- a/include/sfx2/sfxsids.hrc +++ b/include/sfx2/sfxsids.hrc @@ -300,6 +300,7 @@ class SvxZoomItem; #define SID_OPTIONS_PAGEID TypedWhichId(SID_SFX_START + 1747) #define SID_GPGSIGN TypedWhichId(SID_SFX_START + 1748) #define FN_INVERT_BACKGROUND (SID_SFX_START + 1749) +#define SID_MACROMANAGER (SID_SFX_START + 1750) // SID_SFX_free_END (SID_SFX_START + 3999) #define SID_OPEN_NEW_VIEW TypedWhichId(SID_SFX_START + 520) diff --git a/include/svl/hint.hxx b/include/svl/hint.hxx index 894bdeec6786..a1c4ea43ae2f 100644 --- a/include/svl/hint.hxx +++ b/include/svl/hint.hxx @@ -84,6 +84,8 @@ enum class SfxHintId { // basctl BasCtlDlgEd, + ScriptDocumentChanged, + // reportdesign ReportDesignDlgEd, @@ -266,6 +268,7 @@ inline std::basic_ostream & operator <<( case SfxHintId::BasicInfoWanted: return stream << "BasicInfoWanted"; case SfxHintId::BasicStart: return stream << "BasicStart"; case SfxHintId::BasicStop: return stream << "BasicStop"; + case SfxHintId::ScriptDocumentChanged: return stream << "ScriptDocumentChanged"; case SfxHintId::FmDesignModeChanged: return stream << "FmDesignModeChanged"; case SfxHintId::EditSourceParasMoved: return stream << "EditSourceParasMoved"; case SfxHintId::EditSourceSelectionChanged: return stream << "EditSourceSelectionChanged"; diff --git a/include/svx/passwd.hxx b/include/svx/passwd.hxx index c6342df0d3c8..0b4a4922a109 100644 --- a/include/svx/passwd.hxx +++ b/include/svx/passwd.hxx @@ -23,7 +23,7 @@ #include #include -class UNLESS_MERGELIBS(SVX_DLLPUBLIC) SvxPasswordDialog final : public SfxDialogController +class UNLESS_MERGELIBS_MORE(SVX_DLLPUBLIC) SvxPasswordDialog final : public SfxDialogController { private: OUString m_aOldPasswdErrStr; diff --git a/include/svx/svxdlg.hxx b/include/svx/svxdlg.hxx index a2ef0c03a47e..90951647ee45 100644 --- a/include/svx/svxdlg.hxx +++ b/include/svx/svxdlg.hxx @@ -430,6 +430,9 @@ public: virtual VclPtr CreateScriptSelectorDialog(weld::Window* pParent, const css::uno::Reference< css::frame::XFrame >& rxFrame) override = 0; + virtual VclPtr CreateMacroManagerDialog(weld::Window* pParent, + const css::uno::Reference< css::frame::XFrame >& rxFrame) override = 0; + virtual void ShowAsyncScriptErrorDialog(weld::Window* pParent, const css::uno::Any& rException) override = 0; virtual VclPtr CreateSvxMacroAssignDlg( diff --git a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu index 5c92e5147718..254ed0d77c2c 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu @@ -5531,6 +5531,17 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 1 + + + Macro Manager... + + + 1 + + + true + + Gallery diff --git a/reportdesign/uiconfig/dbreport/menubar/menubar.xml b/reportdesign/uiconfig/dbreport/menubar/menubar.xml index e95054ed7889..fa2fcf02ba40 100644 --- a/reportdesign/uiconfig/dbreport/menubar/menubar.xml +++ b/reportdesign/uiconfig/dbreport/menubar/menubar.xml @@ -249,6 +249,8 @@ + + diff --git a/sc/uiconfig/scalc/menubar/menubar.xml b/sc/uiconfig/scalc/menubar/menubar.xml index 61ea6c74b286..6563defbafd7 100644 --- a/sc/uiconfig/scalc/menubar/menubar.xml +++ b/sc/uiconfig/scalc/menubar/menubar.xml @@ -720,6 +720,8 @@ + + diff --git a/sd/uiconfig/sdraw/menubar/menubar.xml b/sd/uiconfig/sdraw/menubar/menubar.xml index 1865877146e3..183c595917c0 100644 --- a/sd/uiconfig/sdraw/menubar/menubar.xml +++ b/sd/uiconfig/sdraw/menubar/menubar.xml @@ -595,6 +595,8 @@ + + diff --git a/sd/uiconfig/simpress/menubar/menubar.xml b/sd/uiconfig/simpress/menubar/menubar.xml index ec88c1e06e09..07f0456335aa 100644 --- a/sd/uiconfig/simpress/menubar/menubar.xml +++ b/sd/uiconfig/simpress/menubar/menubar.xml @@ -637,6 +637,8 @@ + + diff --git a/sfx2/sdi/appslots.sdi b/sfx2/sdi/appslots.sdi index 9d8063487637..47af19347cf4 100644 --- a/sfx2/sdi/appslots.sdi +++ b/sfx2/sdi/appslots.sdi @@ -289,6 +289,11 @@ shell SfxApplication [ ExecMethod = OfaExec_Impl; ] + SID_MACROMANAGER + [ + ExecMethod = OfaExec_Impl; + StateMethod = OfaState_Impl; + ] SID_INET_DLG // status(final) [ ExecMethod = OfaExec_Impl; diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi index 3e7ebf9046be..aa09ee044235 100644 --- a/sfx2/sdi/sfx.sdi +++ b/sfx2/sdi/sfx.sdi @@ -2427,6 +2427,23 @@ SfxVoidItem RunMacro SID_RUNMACRO GroupId = SfxGroupId::Macro; ] +SfxVoidItem MacroManager SID_MACROMANAGER +() +[ + AutoUpdate = FALSE, + FastCall = TRUE, + ReadOnlyDoc = TRUE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::Macro; +] + SfxVoidItem GotoLine SID_GOTOLINE [ diff --git a/sfx2/source/appl/appserv.cxx b/sfx2/source/appl/appserv.cxx index cc65220c8fb5..fdc4a8e0b3ee 100644 --- a/sfx2/source/appl/appserv.cxx +++ b/sfx2/source/appl/appserv.cxx @@ -1894,6 +1894,56 @@ void SfxApplication::OfaExec_Impl( SfxRequest& rReq ) rReq.Done(); } break; + + case SID_MACROMANAGER: + { + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + + Reference xFrame(GetRequestFrame(rReq)); + if (!xFrame.is()) + { + if (const SfxViewFrame* pViewFrame = SfxViewFrame::Current()) + xFrame = pViewFrame->GetFrame().GetFrameInterface(); + } + + VclPtr pDlg( + pFact->CreateMacroManagerDialog(lcl_getDialogParent(xFrame), xFrame)); + OSL_ENSURE(pDlg, "SfxApplication::OfaExec_Impl(SID_MACROMANAGER): no dialog!"); + if (pDlg) + { + pDlg->StartExecuteAsync( + [pDlg, xFrame](sal_Int32 nDialogResult) + { + if (!nDialogResult) + { + pDlg->disposeOnce(); + return; + } + + Sequence args; + Sequence outIndex; + Sequence outArgs; + Any ret; + + Reference xScriptContext; + + Reference xController; + if (xFrame.is()) + xController = xFrame->getController(); + if (xController.is()) + xScriptContext = xController->getModel(); + if (!xScriptContext.is()) + xScriptContext = xController; + + SfxObjectShell::CallXScript(xScriptContext, pDlg->GetScriptURL(), args, ret, + outIndex, outArgs); + pDlg->disposeOnce(); + }); + pDlg->LoadLastUsedMacro(); + } + rReq.Done(); + } + break; #endif // HAVE_FEATURE_SCRIPTING case SID_OFFICE_CHECK_PLZ: @@ -2015,6 +2065,7 @@ void SfxApplication::OfaState_Impl(SfxItemSet &rSet) rSet.DisableItem(SID_MACROORGANIZER); rSet.DisableItem(SID_SCRIPTORGANIZER); rSet.DisableItem(SID_BASICIDE_APPEAR); + rSet.DisableItem(SID_MACROMANAGER); } } diff --git a/sfx2/source/control/minfitem.cxx b/sfx2/source/control/minfitem.cxx index c4d0136590c9..7b5b2d62bc2a 100644 --- a/sfx2/source/control/minfitem.cxx +++ b/sfx2/source/control/minfitem.cxx @@ -33,13 +33,15 @@ SfxMacroInfoItem::SfxMacroInfoItem( OUString _aLibName, OUString _aModuleName, OUString _aMethodName, - OUString _aComment) : + OUString _aComment, + OUString _aLocationName) : SfxPoolItem(nWhichId, SfxItemType::SfxMacroInfoItemType), pBasicManager(pMgr), aLibName(std::move(_aLibName)), aModuleName(std::move(_aModuleName)), aMethodName(std::move(_aMethodName)), - aCommentText(std::move(_aComment)) + aCommentText(std::move(_aComment)), + aLocationName(std::move(_aLocationName)) { } diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist index e521a5ccb359..cf05e4de8eb8 100644 --- a/solenv/clang-format/excludelist +++ b/solenv/clang-format/excludelist @@ -237,8 +237,6 @@ basctl/source/inc/docsignature.hxx basctl/source/inc/localizationmgr.hxx basctl/source/inc/managelang.hxx basctl/source/inc/propbrw.hxx -basctl/source/inc/sbxitem.hxx -basctl/source/inc/scriptdocument.hxx basegfx/source/color/bcolormodifier.cxx basegfx/source/color/bcolortools.cxx basegfx/source/curve/b2dbeziertools.cxx @@ -4740,6 +4738,8 @@ include/avmedia/mediaitem.hxx include/avmedia/mediaplayer.hxx include/avmedia/mediatoolbox.hxx include/avmedia/mediawindow.hxx +include/basctl/sbxitem.hxx +include/basctl/scriptdocument.hxx include/basegfx/color/bcolor.hxx include/basegfx/color/bcolormodifier.hxx include/basegfx/curve/b2dbeziertools.hxx diff --git a/starmath/uiconfig/smath/menubar/menubar.xml b/starmath/uiconfig/smath/menubar/menubar.xml index 74b478aaf3b0..2c5aca7361bf 100644 --- a/starmath/uiconfig/smath/menubar/menubar.xml +++ b/starmath/uiconfig/smath/menubar/menubar.xml @@ -129,6 +129,8 @@ + + diff --git a/sw/uiconfig/sglobal/menubar/menubar.xml b/sw/uiconfig/sglobal/menubar/menubar.xml index dd3eb8c6bd12..04ea613b39fd 100644 --- a/sw/uiconfig/sglobal/menubar/menubar.xml +++ b/sw/uiconfig/sglobal/menubar/menubar.xml @@ -760,6 +760,8 @@ + + diff --git a/sw/uiconfig/sweb/menubar/menubar.xml b/sw/uiconfig/sweb/menubar/menubar.xml index 00c5cefefe15..d8379e4db851 100644 --- a/sw/uiconfig/sweb/menubar/menubar.xml +++ b/sw/uiconfig/sweb/menubar/menubar.xml @@ -624,6 +624,8 @@ + + diff --git a/sw/uiconfig/swform/menubar/menubar.xml b/sw/uiconfig/swform/menubar/menubar.xml index 6da6a923e662..c64bf29ce9c0 100644 --- a/sw/uiconfig/swform/menubar/menubar.xml +++ b/sw/uiconfig/swform/menubar/menubar.xml @@ -704,6 +704,8 @@ + + diff --git a/sw/uiconfig/swreport/menubar/menubar.xml b/sw/uiconfig/swreport/menubar/menubar.xml index 57b49e6b9d90..7fb861d383ae 100644 --- a/sw/uiconfig/swreport/menubar/menubar.xml +++ b/sw/uiconfig/swreport/menubar/menubar.xml @@ -658,6 +658,8 @@ + + diff --git a/sw/uiconfig/swriter/menubar/menubar.xml b/sw/uiconfig/swriter/menubar/menubar.xml index 04b9fb4e2c91..a277c2c061b2 100644 --- a/sw/uiconfig/swriter/menubar/menubar.xml +++ b/sw/uiconfig/swriter/menubar/menubar.xml @@ -802,6 +802,8 @@ + + diff --git a/sw/uiconfig/swxform/menubar/menubar.xml b/sw/uiconfig/swxform/menubar/menubar.xml index 393fbf4aec4a..0ee99fadebbc 100644 --- a/sw/uiconfig/swxform/menubar/menubar.xml +++ b/sw/uiconfig/swxform/menubar/menubar.xml @@ -750,6 +750,8 @@ + +