/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * 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/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include "macrodlg.hxx" #include #include #include #include #include "iderdll2.hxx" #include "moduldlg.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace basctl { using namespace ::com::sun::star; using namespace ::com::sun::star::uno; MacroChooser::MacroChooser(weld::Window* pParnt, const Reference< frame::XFrame >& xDocFrame) : SfxDialogController(pParnt, u"modules/BasicIDE/ui/basicmacrodialog.ui"_ustr, u"BasicMacroDialog"_ustr) , m_xDocumentFrame(xDocFrame) // the Sfx doesn't ask the BasicManager whether modified or not // => start saving in case of a change without a into the BasicIDE. , bForceStoreBasic(false) , nMode(All) , m_xMacroNameEdit(m_xBuilder->weld_entry(u"macronameedit"_ustr)) , m_xMacroFromTxT(m_xBuilder->weld_label(u"macrofromft"_ustr)) , m_xMacrosSaveInTxt(m_xBuilder->weld_label(u"macrotoft"_ustr)) , m_xBasicBox(new SbTreeListBox(m_xBuilder->weld_tree_view(u"libraries"_ustr), m_xDialog.get())) , m_xBasicBoxIter(m_xBasicBox->make_iterator()) , m_xMacrosInTxt(m_xBuilder->weld_label(u"existingmacrosft"_ustr)) , m_xMacroBox(m_xBuilder->weld_tree_view(u"macros"_ustr)) , m_xMacroBoxIter(m_xMacroBox->make_iterator()) , m_xRunButton(m_xBuilder->weld_button(u"ok"_ustr)) , m_xCloseButton(m_xBuilder->weld_button(u"close"_ustr)) , m_xAssignButton(m_xBuilder->weld_button(u"assign"_ustr)) , m_xEditButton(m_xBuilder->weld_button(u"edit"_ustr)) , m_xDelButton(m_xBuilder->weld_button(u"delete"_ustr)) , m_xNewButton(m_xBuilder->weld_button(u"new"_ustr)) , m_xOrganizeButton(m_xBuilder->weld_button(u"organize"_ustr)) , m_xNewLibButton(m_xBuilder->weld_button(u"newlibrary"_ustr)) , m_xNewModButton(m_xBuilder->weld_button(u"newmodule"_ustr)) { m_xBasicBox->set_size_request(m_xBasicBox->get_approximate_digit_width() * 30, m_xBasicBox->get_height_rows(18)); m_xMacroBox->set_size_request(m_xMacroBox->get_approximate_digit_width() * 30, m_xMacroBox->get_height_rows(18)); m_aMacrosInTxtBaseStr = m_xMacrosInTxt->get_label(); m_xRunButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); m_xCloseButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); m_xAssignButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); m_xEditButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); m_xDelButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); m_xNewButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); m_xOrganizeButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); // Buttons only for MacroChooser::Recording m_xNewLibButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); m_xNewModButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) ); m_xNewLibButton->hide(); // default m_xNewModButton->hide(); // default m_xMacrosSaveInTxt->hide(); // default m_xMacroNameEdit->connect_changed( LINK( this, MacroChooser, EditModifyHdl ) ); m_xBasicBox->connect_changed( LINK( this, MacroChooser, BasicSelectHdl ) ); m_xMacroBox->connect_row_activated( LINK( this, MacroChooser, MacroDoubleClickHdl ) ); m_xMacroBox->connect_changed( LINK( this, MacroChooser, MacroSelectHdl ) ); m_xMacroBox->connect_popup_menu( LINK( this, MacroChooser, ContextMenuHdl ) ); m_xBasicBox->SetMode( BrowseMode::Modules ); if (SfxDispatcher* pDispatcher = GetDispatcher()) pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES ); m_xBasicBox->ScanAllEntries(); } MacroChooser::~MacroChooser() { if (bForceStoreBasic) { SfxGetpApp()->SaveBasicAndDialogContainer(); bForceStoreBasic = false; } } void MacroChooser::StoreMacroDescription() { if (!m_xBasicBox->get_selected(m_xBasicBoxIter.get())) return; EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); OUString aMethodName; if (m_xMacroBox->get_selected(m_xMacroBoxIter.get())) aMethodName = m_xMacroBox->get_text(*m_xMacroBoxIter); else aMethodName = m_xMacroNameEdit->get_text(); if ( !aMethodName.isEmpty() ) { aDesc.SetMethodName( aMethodName ); aDesc.SetType( OBJ_TYPE_METHOD ); } if (ExtraData* pData = basctl::GetExtraData()) pData->SetLastEntryDescriptor( aDesc ); } void MacroChooser::RestoreMacroDescription() { // The following call is a workaround to ensure the last used macro is scrolled to in kf5 m_xDialog->resize_to_request(); EntryDescriptor aDesc; if (Shell* pShell = GetShell()) { if (BaseWindow* pCurWin = pShell->GetCurWindow()) aDesc = pCurWin->CreateEntryDescriptor(); } else { if (ExtraData* pData = basctl::GetExtraData()) aDesc = pData->GetLastEntryDescriptor(); } m_xBasicBox->SetCurrentEntry(aDesc); BasicSelectHdl(m_xBasicBox->get_widget()); OUString aLastMacro( aDesc.GetMethodName() ); if (!aLastMacro.isEmpty()) { // find entry in macro box auto nIndex = m_xMacroBox->find_text(aLastMacro); if (nIndex != -1) m_xMacroBox->select(nIndex); else { m_xMacroNameEdit->set_text(aLastMacro); m_xMacroNameEdit->select_region(0, 0); } } } short MacroChooser::run() { RestoreMacroDescription(); // #104198 Check if "wrong" document is active bool bSelectedEntry = m_xBasicBox->get_cursor(m_xBasicBoxIter.get()); EntryDescriptor aDesc(m_xBasicBox->GetEntryDescriptor(bSelectedEntry ? m_xBasicBoxIter.get() : nullptr)); const ScriptDocument& rSelectedDoc(aDesc.GetDocument()); // App Basic is always ok, so only check if shell was found if( rSelectedDoc.isDocument() && !rSelectedDoc.isActive() ) { // Search for the right entry bool bValidIter = m_xBasicBox->get_iter_first(*m_xBasicBoxIter); while (bValidIter) { EntryDescriptor aCmpDesc(m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get())); const ScriptDocument& rCmpDoc( aCmpDesc.GetDocument() ); if (rCmpDoc.isDocument() && rCmpDoc.isActive()) { std::unique_ptr xEntry(m_xBasicBox->make_iterator()); m_xBasicBox->copy_iterator(*m_xBasicBoxIter, *xEntry); std::unique_ptr xLastValid(m_xBasicBox->make_iterator()); bool bValidEntryIter = true; do { m_xBasicBox->copy_iterator(*xEntry, *xLastValid); bValidEntryIter = m_xBasicBox->iter_children(*xEntry); } while (bValidEntryIter); m_xBasicBox->set_cursor(*xLastValid); } bValidIter = m_xBasicBox->iter_next_sibling(*m_xBasicBoxIter); } } CheckButtons(); UpdateFields(); // tdf#62955 - Allow searching a name with typing the first letter m_xBasicBox->get_widget().grab_focus(); if ( StarBASIC::IsRunning() ) m_xCloseButton->grab_focus(); return SfxDialogController::run(); } void MacroChooser::EnableButton(weld::Button& rButton, bool bEnable) { if ( bEnable ) { if (nMode == ChooseOnly || nMode == Recording) rButton.set_sensitive(&rButton == m_xRunButton.get()); else rButton.set_sensitive(true); } else rButton.set_sensitive(false); } SbMethod* MacroChooser::GetMacro() { if (!m_xBasicBox->get_cursor(m_xBasicBoxIter.get())) return nullptr; SbModule* pModule = m_xBasicBox->FindModule(m_xBasicBoxIter.get()); if (!pModule) return nullptr; if (!m_xMacroBox->get_selected(m_xMacroBoxIter.get())) return nullptr; OUString aMacroName(m_xMacroBox->get_text(*m_xMacroBoxIter)); return pModule->FindMethod(aMacroName, SbxClassType::Method); } void MacroChooser::DeleteMacro() { SbMethod* pMethod = GetMacro(); DBG_ASSERT( pMethod, "DeleteMacro: No Macro !" ); if (!(pMethod && QueryDelMacro(pMethod->GetName(), m_xDialog.get()))) return; if (SfxDispatcher* pDispatcher = GetDispatcher()) pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES ); // mark current doc as modified: StarBASIC* pBasic = FindBasic(pMethod); assert(pBasic && "Basic?!"); BasicManager* pBasMgr = FindBasicManager( pBasic ); DBG_ASSERT( pBasMgr, "BasMgr?" ); ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) ); if ( aDocument.isDocument() ) { aDocument.setDocumentModified(); if (SfxBindings* pBindings = GetBindingsPtr()) pBindings->Invalidate( SID_SAVEDOC ); } SbModule* pModule = pMethod->GetModule(); assert(pModule && "DeleteMacro: No Module?!"); OUString aSource( pModule->GetSource32() ); sal_uInt16 nStart, nEnd; pMethod->GetLineRange( nStart, nEnd ); pModule->GetMethods()->Remove( pMethod ); CutLines( aSource, nStart-1, nEnd-nStart+1 ); pModule->SetSource32( aSource ); // update module in library OUString aLibName = pBasic->GetName(); OUString aModName = pModule->GetName(); OSL_VERIFY( aDocument.updateModule( aLibName, aModName, aSource ) ); bool bSelected = m_xMacroBox->get_selected(m_xMacroBoxIter.get()); DBG_ASSERT(bSelected, "DeleteMacro: Entry ?!"); m_xMacroBox->remove(*m_xMacroBoxIter); bForceStoreBasic = true; } SbMethod* MacroChooser::CreateMacro() { SbMethod* pMethod = nullptr; if (!m_xBasicBox->get_cursor(m_xBasicBoxIter.get()) && !m_xBasicBox->get_iter_first(*m_xBasicBoxIter)) { SAL_WARN("basctl.basicide", "neither cursor set nor root entry to use as fallback"); return nullptr; } EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); const ScriptDocument& aDocument( aDesc.GetDocument() ); OSL_ENSURE( aDocument.isAlive(), "MacroChooser::CreateMacro: no document!" ); if ( !aDocument.isAlive() ) return nullptr; OUString aLibName( aDesc.GetLibName() ); if ( aLibName.isEmpty() ) aLibName = "Standard" ; aDocument.getOrCreateLibrary( E_SCRIPTS, aLibName ); OUString aOULibName( aLibName ); Reference< script::XLibraryContainer > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ) ); if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) && !xModLibContainer->isLibraryLoaded( aOULibName ) ) xModLibContainer->loadLibrary( aOULibName ); Reference< script::XLibraryContainer > xDlgLibContainer( aDocument.getLibraryContainer( E_DIALOGS ) ); if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aOULibName ) && !xDlgLibContainer->isLibraryLoaded( aOULibName ) ) xDlgLibContainer->loadLibrary( aOULibName ); BasicManager* pBasMgr = aDocument.getBasicManager(); StarBASIC* pBasic = pBasMgr ? pBasMgr->GetLib( aLibName ) : nullptr; if ( pBasic ) { SbModule* pModule = nullptr; OUString aModName( aDesc.GetName() ); if ( !aModName.isEmpty() ) { // extract the module name from the string like "Sheet1 (Example1)" if( aDesc.GetLibSubName() == IDEResId(RID_STR_DOCUMENT_OBJECTS) ) { aModName = aModName.getToken( 0, ' ' ); } pModule = pBasic->FindModule( aModName ); } else if ( !pBasic->GetModules().empty() ) pModule = pBasic->GetModules().front().get(); // Retain the desired macro name before the macro dialog box is forced to close // by opening the module name dialog window when no module exists in the current library. OUString aSubName = m_xMacroNameEdit->get_text(); if ( !pModule ) { pModule = createModImpl(m_xDialog.get(), aDocument, *m_xBasicBox, aLibName, aModName, false); } DBG_ASSERT( !pModule || !pModule->FindMethod( aSubName, SbxClassType::Method ), "Macro exists already!" ); pMethod = pModule ? basctl::CreateMacro( pModule, aSubName ) : nullptr; } return pMethod; } void MacroChooser::SaveSetCurEntry(weld::TreeView& rBox, const weld::TreeIter& rEntry) { // the edit would be killed by the highlight otherwise: OUString aSaveText(m_xMacroNameEdit->get_text()); int nStartPos, nEndPos; m_xMacroNameEdit->get_selection_bounds(nStartPos, nEndPos); rBox.set_cursor(rEntry); m_xMacroNameEdit->set_text(aSaveText); m_xMacroNameEdit->select_region(nStartPos, nEndPos); } void MacroChooser::CheckButtons() { const bool bCurEntry = m_xBasicBox->get_cursor(m_xBasicBoxIter.get()); EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(bCurEntry ? m_xBasicBoxIter.get() : nullptr); const bool bMacroEntry = m_xMacroBox->get_selected(nullptr); SbMethod* pMethod = GetMacro(); // check, if corresponding libraries are readonly bool bReadOnly = false; sal_uInt16 nDepth = bCurEntry ? m_xBasicBox->get_iter_depth(*m_xBasicBoxIter) : 0; if ( nDepth == 1 || nDepth == 2 ) { const ScriptDocument& aDocument( aDesc.GetDocument() ); const OUString& aOULibName( aDesc.GetLibName() ); Reference< script::XLibraryContainer2 > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY ); Reference< script::XLibraryContainer2 > xDlgLibContainer( aDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY ); if ( ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) && xModLibContainer->isLibraryReadOnly( aOULibName ) ) || ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aOULibName ) && xDlgLibContainer->isLibraryReadOnly( aOULibName ) ) ) { bReadOnly = true; } } if (nMode != Recording) { // Run... bool bEnable = pMethod != nullptr; if (nMode != ChooseOnly && StarBASIC::IsRunning()) bEnable = false; EnableButton(*m_xRunButton, bEnable); } // organising still possible? // Assign... EnableButton(*m_xAssignButton, pMethod != nullptr); // Edit... EnableButton(*m_xEditButton, bMacroEntry); // Organizer... EnableButton(*m_xOrganizeButton, !StarBASIC::IsRunning() && nMode == All); // m_xDelButton/m_xNewButton ->... bool bProtected = bCurEntry && m_xBasicBox->IsEntryProtected(m_xBasicBoxIter.get()); bool bShare = ( aDesc.GetLocation() == LIBRARY_LOCATION_SHARE ); bool bEnable = !StarBASIC::IsRunning() && nMode == All && !bProtected && !bReadOnly && !bShare; EnableButton(*m_xDelButton, bEnable); EnableButton(*m_xNewButton, bEnable); if (nMode == All) { if (pMethod) { m_xDelButton->show(); m_xNewButton->hide(); } else { m_xNewButton->show(); m_xDelButton->hide(); } } if (nMode == Recording) { // save button m_xRunButton->set_sensitive(!bProtected && !bReadOnly && !bShare); // new library button m_xNewLibButton->set_sensitive(!bShare); // new module button m_xNewModButton->set_sensitive(!bProtected && !bReadOnly && !bShare); } } IMPL_LINK_NOARG(MacroChooser, MacroDoubleClickHdl, weld::TreeView&, bool) { SbMethod* pMethod = GetMacro(); SbModule* pModule = pMethod ? pMethod->GetModule() : nullptr; StarBASIC* pBasic = pModule ? static_cast(pModule->GetParent()) : nullptr; BasicManager* pBasMgr = pBasic ? FindBasicManager(pBasic) : nullptr; ScriptDocument aDocument(ScriptDocument::getDocumentForBasicManager(pBasMgr)); if (aDocument.isDocument() && !aDocument.allowMacros()) { std::unique_ptr xError( Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO))); xError->run(); return true; } StoreMacroDescription(); if (nMode == Recording) { if (pMethod && !QueryReplaceMacro(pMethod->GetName(), m_xDialog.get())) return true; } m_xDialog->response(Macro_OkRun); return true; } IMPL_LINK_NOARG(MacroChooser, MacroSelectHdl, weld::TreeView&, void) { UpdateFields(); CheckButtons(); } IMPL_LINK_NOARG(MacroChooser, BasicSelectHdl, weld::TreeView&, void) { SbModule* pModule = nullptr; if (m_xBasicBox->get_cursor(m_xBasicBoxIter.get())) pModule = m_xBasicBox->FindModule(m_xBasicBoxIter.get()); m_xMacroBox->clear(); if (pModule) { m_xMacrosInTxt->set_label(m_aMacrosInTxtBaseStr + " " + pModule->GetName()); m_xMacroBox->freeze(); sal_uInt32 nMacroCount = pModule->GetMethods()->Count(); for ( sal_uInt32 iMeth = 0; iMeth < nMacroCount; iMeth++ ) { SbMethod* pMethod = static_cast(pModule->GetMethods()->Get(iMeth)); assert(pMethod && "Method not found!"); if (pMethod->IsHidden()) continue; m_xMacroBox->append_text(pMethod->GetName()); } m_xMacroBox->thaw(); if (m_xMacroBox->get_iter_first(*m_xMacroBoxIter)) m_xMacroBox->set_cursor(*m_xMacroBoxIter); } UpdateFields(); CheckButtons(); } IMPL_LINK_NOARG(MacroChooser, EditModifyHdl, weld::Entry&, void) { // select the module in which the macro is put at "new", // if BasicManager or Lib is selecting if (m_xBasicBox->get_cursor(m_xBasicBoxIter.get())) { sal_uInt16 nDepth = m_xBasicBox->get_iter_depth(*m_xBasicBoxIter); if (nDepth == 1 && m_xBasicBox->IsEntryProtected(m_xBasicBoxIter.get())) { // then put to the respective Std-Lib... m_xBasicBox->iter_parent(*m_xBasicBoxIter); m_xBasicBox->iter_children(*m_xBasicBoxIter); } if (nDepth < 2) { std::unique_ptr xNewEntry(m_xBasicBox->make_iterator()); m_xBasicBox->copy_iterator(*m_xBasicBoxIter, *xNewEntry); bool bCurEntry = true; do { bCurEntry = m_xBasicBox->iter_children(*m_xBasicBoxIter); if (bCurEntry) { m_xBasicBox->copy_iterator(*m_xBasicBoxIter, *xNewEntry); nDepth = m_xBasicBox->get_iter_depth(*m_xBasicBoxIter); } } while (bCurEntry && (nDepth < 2)); SaveSetCurEntry(m_xBasicBox->get_widget(), *xNewEntry); } auto nCount = m_xMacroBox->n_children(); if (nCount) { OUString aEdtText(m_xMacroNameEdit->get_text()); bool bFound = false; bool bValidIter = m_xMacroBox->get_iter_first(*m_xMacroBoxIter); while (bValidIter) { if (m_xMacroBox->get_text(*m_xMacroBoxIter).equalsIgnoreAsciiCase(aEdtText)) { SaveSetCurEntry(*m_xMacroBox, *m_xMacroBoxIter); bFound = true; break; } bValidIter = m_xMacroBox->iter_next_sibling(*m_xMacroBoxIter); } if (!bFound) { bValidIter = m_xMacroBox->get_selected(m_xMacroBoxIter.get()); // if the entry exists ->Select ->Description... if (bValidIter) m_xMacroBox->unselect(*m_xMacroBoxIter); } } } CheckButtons(); } IMPL_LINK(MacroChooser, ButtonHdl, weld::Button&, rButton, void) { // apart from New/Record the Description is done by LoseFocus if (&rButton == m_xRunButton.get()) { StoreMacroDescription(); // #116444# check security settings before macro execution if (nMode == All) { SbMethod* pMethod = GetMacro(); SbModule* pModule = pMethod ? pMethod->GetModule() : nullptr; StarBASIC* pBasic = pModule ? static_cast(pModule->GetParent()) : nullptr; BasicManager* pBasMgr = pBasic ? FindBasicManager(pBasic) : nullptr; if ( pBasMgr ) { ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) ); if ( aDocument.isDocument() && !aDocument.allowMacros() ) { std::unique_ptr xError(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO))); xError->run(); return; } } } else if (nMode == Recording ) { if ( !IsValidSbxName(m_xMacroNameEdit->get_text()) ) { std::unique_ptr xError(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME))); xError->run(); m_xMacroNameEdit->select_region(0, -1); m_xMacroNameEdit->grab_focus(); return; } SbMethod* pMethod = GetMacro(); if (pMethod && !QueryReplaceMacro(pMethod->GetName(), m_xDialog.get())) return; } m_xDialog->response(Macro_OkRun); } else if (&rButton == m_xCloseButton.get()) { StoreMacroDescription(); m_xDialog->response(Macro_Close); } else if (&rButton == m_xEditButton.get() || &rButton == m_xDelButton.get() || &rButton == m_xNewButton.get()) { if (!m_xBasicBox->get_cursor(m_xBasicBoxIter.get()) && !m_xBasicBox->get_iter_first(*m_xBasicBoxIter)) { SAL_WARN("basctl.basicide", "neither cursor set nor root entry to use as fallback"); return; } EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); const ScriptDocument& aDocument( aDesc.GetDocument() ); DBG_ASSERT( aDocument.isAlive(), "MacroChooser::ButtonHdl: no document, or document is dead!" ); if ( !aDocument.isAlive() ) return; BasicManager* pBasMgr = aDocument.getBasicManager(); const OUString& aLib( aDesc.GetLibName() ); OUString aMod( aDesc.GetName() ); // extract the module name from the string like "Sheet1 (Example1)" if( aDesc.GetLibSubName() == IDEResId(RID_STR_DOCUMENT_OBJECTS) ) { aMod = aMod.getToken( 0, ' ' ); } const OUString& aSub( aDesc.GetMethodName() ); SfxMacroInfoItem aInfoItem( SID_BASICIDE_ARG_MACROINFO, pBasMgr, aLib, aMod, aSub, OUString() ); if (&rButton == m_xEditButton.get()) { if (m_xMacroBox->get_selected(m_xMacroBoxIter.get())) aInfoItem.SetMethod(m_xMacroBox->get_text(*m_xMacroBoxIter)); StoreMacroDescription(); m_xDialog->hide(); // tdf#126828 dismiss dialog before opening new window SfxAllItemSet aArgs( SfxGetpApp()->GetPool() ); SfxRequest aRequest( SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs ); SfxGetpApp()->ExecuteSlot( aRequest ); if (SfxDispatcher* pDispatcher = GetDispatcher()) { pDispatcher->ExecuteList(SID_BASICIDE_EDITMACRO, SfxCallMode::ASYNCHRON, { &aInfoItem }); } m_xDialog->response(Macro_Edit); } else { if (&rButton == m_xDelButton.get()) { DeleteMacro(); if (SfxDispatcher* pDispatcher = GetDispatcher()) { pDispatcher->ExecuteList( SID_BASICIDE_UPDATEMODULESOURCE, SfxCallMode::SYNCHRON, { &aInfoItem }); } CheckButtons(); UpdateFields(); //if ( m_xMacroBox->GetCurEntry() ) // OV-Bug ? // m_xMacroBox->Select( m_xMacroBox->GetCurEntry() ); } else { if ( !IsValidSbxName(m_xMacroNameEdit->get_text()) ) { std::unique_ptr xError(Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME))); xError->run(); m_xMacroNameEdit->select_region(0, -1); m_xMacroNameEdit->grab_focus(); return; } SbMethod* pMethod = CreateMacro(); if ( pMethod ) { aInfoItem.SetMethod( pMethod->GetName() ); aInfoItem.SetModule( pMethod->GetModule()->GetName() ); aInfoItem.SetLib( pMethod->GetModule()->GetParent()->GetName() ); SfxAllItemSet aArgs( SfxGetpApp()->GetPool() ); SfxRequest aRequest( SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs ); SfxGetpApp()->ExecuteSlot( aRequest ); if (SfxDispatcher* pDispatcher = GetDispatcher()) { pDispatcher->ExecuteList(SID_BASICIDE_EDITMACRO, SfxCallMode::ASYNCHRON, { &aInfoItem }); } StoreMacroDescription(); m_xDialog->response(Macro_New); } } } } else if (&rButton == m_xAssignButton.get()) { if (!m_xBasicBox->get_cursor(m_xBasicBoxIter.get()) && !m_xBasicBox->get_iter_first(*m_xBasicBoxIter)) { SAL_WARN("basctl.basicide", "neither cursor set nor root entry to use as fallback"); return; } EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); const ScriptDocument& aDocument( aDesc.GetDocument() ); DBG_ASSERT( aDocument.isAlive(), "MacroChooser::ButtonHdl: no document, or document is dead!" ); if ( !aDocument.isAlive() ) return; BasicManager* pBasMgr = aDocument.getBasicManager(); const OUString& aLib( aDesc.GetLibName() ); const OUString& aMod( aDesc.GetName() ); OUString aSub( m_xMacroNameEdit->get_text() ); SbMethod* pMethod = GetMacro(); DBG_ASSERT( pBasMgr, "BasMgr?" ); DBG_ASSERT( pMethod, "Method?" ); OUString aComment( GetInfo( pMethod ) ); SfxMacroInfoItem aItem( SID_MACROINFO, pBasMgr, aLib, aMod, aSub, aComment ); 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); aRequest.AppendItem( aItem ); SfxGetpApp()->ExecuteSlot( aRequest ); } else if (&rButton == m_xNewLibButton.get()) { if (!m_xBasicBox->get_cursor(m_xBasicBoxIter.get()) && !m_xBasicBox->get_iter_first(*m_xBasicBoxIter)) { SAL_WARN("basctl.basicide", "neither cursor set nor root entry to use as fallback"); return; } EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); const ScriptDocument& aDocument( aDesc.GetDocument() ); createLibImpl(m_xDialog.get(), aDocument, nullptr, m_xBasicBox.get()); } else if (&rButton == m_xNewModButton.get()) { if (!m_xBasicBox->get_cursor(m_xBasicBoxIter.get()) && !m_xBasicBox->get_iter_first(*m_xBasicBoxIter)) { SAL_WARN("basctl.basicide", "neither cursor set nor root entry to use as fallback"); return; } EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()); const ScriptDocument& aDocument( aDesc.GetDocument() ); const OUString& aLibName( aDesc.GetLibName() ); createModImpl(m_xDialog.get(), aDocument, *m_xBasicBox, aLibName, OUString(), true); } else if (&rButton == m_xOrganizeButton.get()) { StoreMacroDescription(); m_xBasicBox->get_selected(m_xBasicBoxIter.get()); auto xDlg(std::make_shared(m_xDialog.get(), nullptr, 0)); weld::DialogController::runAsync(xDlg, [this](sal_Int32 nRet) { if (nRet == RET_OK) // not only closed { m_xDialog->response(Macro_Edit); return; } Shell* pShell = GetShell(); if ( pShell && pShell->IsAppBasicModified() ) bForceStoreBasic = true; m_xBasicBox->UpdateEntries(); }); } } IMPL_LINK(MacroChooser, ContextMenuHdl, const CommandEvent&, rCEvt, bool) { if (rCEvt.GetCommand() != CommandEventId::ContextMenu || !m_xMacroBox->n_children()) return false; std::unique_ptr xBuilder(Application::CreateBuilder(m_xMacroBox.get(), 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, m_xMacroBox->get_sort_order()); xDropMenu->set_active(u"properorder"_ustr, !m_xMacroBox->get_sort_order()); OUString sCommand(xPopup->popup_at_rect(m_xMacroBox.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)))); if (sCommand == "alphabetically") { m_xMacroBox->make_sorted(); } else if (sCommand == "properorder") { m_xMacroBox->make_unsorted(); BasicSelectHdl(m_xBasicBox->get_widget()); } else if (!sCommand.isEmpty()) { SAL_WARN("basctl.basicide", "Unknown context menu action: " << sCommand ); } return true; } void MacroChooser::UpdateFields() { auto nMacroEntry = m_xMacroBox->get_selected_index(); m_xMacroNameEdit->set_text(u""_ustr); if (nMacroEntry != -1) m_xMacroNameEdit->set_text(m_xMacroBox->get_text(nMacroEntry)); } void MacroChooser::SetMode (Mode nM) { nMode = nM; switch (nMode) { case All: { m_xRunButton->set_label(IDEResId(RID_STR_RUN)); EnableButton(*m_xDelButton, true); EnableButton(*m_xNewButton, true); EnableButton(*m_xOrganizeButton, true); break; } case ChooseOnly: { m_xRunButton->set_label(IDEResId(RID_STR_CHOOSE)); EnableButton(*m_xDelButton, false); EnableButton(*m_xNewButton, false); EnableButton(*m_xOrganizeButton, false); break; } case Recording: { m_xRunButton->set_label(IDEResId(RID_STR_RECORD)); EnableButton(*m_xDelButton, false); EnableButton(*m_xNewButton, false); EnableButton(*m_xOrganizeButton, false); m_xAssignButton->hide(); m_xEditButton->hide(); m_xDelButton->hide(); m_xNewButton->hide(); m_xOrganizeButton->hide(); m_xMacroFromTxT->hide(); m_xNewLibButton->show(); m_xNewModButton->show(); m_xMacrosSaveInTxt->show(); break; } } CheckButtons(); } OUString MacroChooser::GetInfo( SbxVariable* pVar ) { OUString aComment; SbxInfoRef xInfo = pVar->GetInfo(); if ( xInfo.is() ) aComment = xInfo->GetComment(); return aComment; } } // namespace basctl /* vim:set shiftwidth=4 softtabstop=4 expandtab: */