summaryrefslogtreecommitdiffstats
path: root/basctl/source/basicide/macrodlg.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--basctl/source/basicide/macrodlg.cxx883
1 files changed, 883 insertions, 0 deletions
diff --git a/basctl/source/basicide/macrodlg.cxx b/basctl/source/basicide/macrodlg.cxx
new file mode 100644
index 000000000..63b487349
--- /dev/null
+++ b/basctl/source/basicide/macrodlg.cxx
@@ -0,0 +1,883 @@
+/* -*- 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 <basidesh.hxx>
+#include <strings.hrc>
+#include <iderid.hxx>
+
+#include <iderdll.hxx>
+#include "iderdll2.hxx"
+
+#include "moduldlg.hxx"
+#include <basic/basmgr.hxx>
+#include <basic/sbmeth.hxx>
+#include <basic/sbmod.hxx>
+#include <com/sun/star/script/XLibraryContainer2.hpp>
+#include <sal/log.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/frame.hxx>
+#include <sfx2/minfitem.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <tools/debug.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <osl/diagnose.h>
+
+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, "modules/BasicIDE/ui/basicmacrodialog.ui", "BasicMacroDialog")
+ , 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("macronameedit"))
+ , m_xMacroFromTxT(m_xBuilder->weld_label("macrofromft"))
+ , m_xMacrosSaveInTxt(m_xBuilder->weld_label("macrotoft"))
+ , m_xBasicBox(new SbTreeListBox(m_xBuilder->weld_tree_view("libraries"), m_xDialog.get()))
+ , m_xBasicBoxIter(m_xBasicBox->make_iterator())
+ , m_xMacrosInTxt(m_xBuilder->weld_label("existingmacrosft"))
+ , m_xMacroBox(m_xBuilder->weld_tree_view("macros"))
+ , m_xMacroBoxIter(m_xMacroBox->make_iterator())
+ , m_xRunButton(m_xBuilder->weld_button("ok"))
+ , m_xCloseButton(m_xBuilder->weld_button("close"))
+ , m_xAssignButton(m_xBuilder->weld_button("assign"))
+ , m_xEditButton(m_xBuilder->weld_button("edit"))
+ , m_xDelButton(m_xBuilder->weld_button("delete"))
+ , m_xNewButton(m_xBuilder->weld_button("new"))
+ , m_xOrganizeButton(m_xBuilder->weld_button("organize"))
+ , m_xNewLibButton(m_xBuilder->weld_button("newlibrary"))
+ , m_xNewModButton(m_xBuilder->weld_button("newmodule"))
+{
+ 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()
+{
+ EntryDescriptor aDesc;
+ if (Shell* pShell = GetShell())
+ {
+ if (BaseWindow* pCurWin = pShell->GetCurWindow())
+ aDesc = pCurWin->CreateEntryDescriptor();
+ }
+ else
+ {
+ if (ExtraData* pData = basctl::GetExtraData())
+ aDesc = pData->GetLastEntryDescriptor();
+ }
+
+ // No valid EntryDescriptor found
+ if (aDesc.GetMethodName().isEmpty())
+ {
+ m_xMacroNameEdit->select_region(0, 0);
+ return;
+ }
+
+ 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<weld::TreeIter> xEntry(m_xBasicBox->make_iterator());
+ m_xBasicBox->copy_iterator(*m_xBasicBoxIter, *xEntry);
+ std::unique_ptr<weld::TreeIter> 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<StarBASIC*>(pModule->GetParent()) : nullptr;
+ BasicManager* pBasMgr = pBasic ? FindBasicManager(pBasic) : nullptr;
+ ScriptDocument aDocument(ScriptDocument::getDocumentForBasicManager(pBasMgr));
+ if (aDocument.isDocument() && !aDocument.allowMacros())
+ {
+ std::unique_ptr<weld::MessageDialog> 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<SbMethod*>(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<weld::TreeIter> 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<StarBASIC*>(pModule->GetParent()) : nullptr;
+ BasicManager* pBasMgr = pBasic ? FindBasicManager(pBasic) : nullptr;
+ if ( pBasMgr )
+ {
+ ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) );
+ if ( aDocument.isDocument() && !aDocument.allowMacros() )
+ {
+ std::unique_ptr<weld::MessageDialog> 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<weld::MessageDialog> 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<weld::MessageDialog> 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_CONFIG, 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<OrganizeDialog>(m_xDialog.get(), 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<weld::Builder> xBuilder(Application::CreateBuilder(m_xMacroBox.get(), "modules/BasicIDE/ui/sortmenu.ui"));
+ std::unique_ptr<weld::Menu> xPopup(xBuilder->weld_menu("sortmenu"));
+ std::unique_ptr<weld::Menu> xDropMenu(xBuilder->weld_menu("sortsubmenu"));
+ xDropMenu->set_active("alphabetically", m_xMacroBox->get_sort_order());
+ xDropMenu->set_active("properorder", !m_xMacroBox->get_sort_order());
+
+ OString 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("");
+ 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: */